aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/44x
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/platforms/44x')
-rw-r--r--arch/powerpc/platforms/44x/Kconfig35
-rw-r--r--arch/powerpc/platforms/44x/Makefile2
-rw-r--r--arch/powerpc/platforms/44x/sam440ep.c79
-rw-r--r--arch/powerpc/platforms/44x/virtex.c60
-rw-r--r--arch/powerpc/platforms/44x/warp-nand.c57
-rw-r--r--arch/powerpc/platforms/44x/warp.c293
6 files changed, 462 insertions, 64 deletions
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 6abe91357ee..249ba01c667 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -17,6 +17,15 @@ config EBONY
help
This option enables support for the IBM PPC440GP evaluation board.
+config SAM440EP
+ bool "Sam440ep"
+ depends on 44x
+ default n
+ select 440EP
+ select PCI
+ help
+ This option enables support for the ACube Sam440ep board.
+
config SEQUOIA
bool "Sequoia"
depends on 44x
@@ -102,6 +111,22 @@ config YOSEMITE
# help
# This option enables support for the IBM PPC440GX evaluation board.
+config XILINX_VIRTEX440_GENERIC_BOARD
+ bool "Generic Xilinx Virtex 440 board"
+ depends on 44x
+ default n
+ select XILINX_VIRTEX_5_FXT
+ help
+ This option enables generic support for Xilinx Virtex based boards
+ that use a 440 based processor in the Virtex 5 FXT FPGA architecture.
+
+ The generic virtex board support matches any device tree which
+ specifies 'xlnx,virtex440' in its compatible field. This includes
+ the Xilinx ML5xx reference designs using the powerpc core.
+
+ Most Virtex 5 designs should use this unless it needs to do some
+ special configuration at board probe time.
+
# 44x specific CPU modules, selected based on the board above.
config 440EP
bool
@@ -152,3 +177,13 @@ config 460EX
# 44x errata/workaround config symbols, selected by the CPU models above
config IBM440EP_ERR42
bool
+
+# Xilinx specific config options.
+config XILINX_VIRTEX
+ bool
+
+# Xilinx Virtex 5 FXT FPGA architecture, selected by a Xilinx board above
+config XILINX_VIRTEX_5_FXT
+ bool
+ select XILINX_VIRTEX
+
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
index 774165f9acd..8d0b1a192d6 100644
--- a/arch/powerpc/platforms/44x/Makefile
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -3,9 +3,11 @@ obj-$(CONFIG_EBONY) += ebony.o
obj-$(CONFIG_TAISHAN) += taishan.o
obj-$(CONFIG_BAMBOO) += bamboo.o
obj-$(CONFIG_YOSEMITE) += bamboo.o
+obj-$(CONFIG_SAM440EP) += sam440ep.o
obj-$(CONFIG_SEQUOIA) += sequoia.o
obj-$(CONFIG_KATMAI) += katmai.o
obj-$(CONFIG_RAINIER) += rainier.o
obj-$(CONFIG_WARP) += warp.o
obj-$(CONFIG_WARP) += warp-nand.o
obj-$(CONFIG_CANYONLANDS) += canyonlands.o
+obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
diff --git a/arch/powerpc/platforms/44x/sam440ep.c b/arch/powerpc/platforms/44x/sam440ep.c
new file mode 100644
index 00000000000..47f10e64773
--- /dev/null
+++ b/arch/powerpc/platforms/44x/sam440ep.c
@@ -0,0 +1,79 @@
+/*
+ * Sam440ep board specific routines based off bamboo.c code
+ * original copyrights below
+ *
+ * Wade Farnsworth <wfarnsworth@mvista.com>
+ * Copyright 2004 MontaVista Software Inc.
+ *
+ * Rewritten and ported to the merged powerpc tree:
+ * Josh Boyer <jwboyer@linux.vnet.ibm.com>
+ * Copyright 2007 IBM Corporation
+ *
+ * Modified from bamboo.c for sam440ep:
+ * Copyright 2008 Giuseppe Coviello <gicoviello@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+#include <linux/init.h>
+#include <linux/of_platform.h>
+
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/time.h>
+#include <asm/uic.h>
+#include <asm/pci-bridge.h>
+#include <asm/ppc4xx.h>
+#include <linux/i2c.h>
+
+static __initdata struct of_device_id sam440ep_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+ { .compatible = "ibm,opb", },
+ { .compatible = "ibm,ebc", },
+ {},
+};
+
+static int __init sam440ep_device_probe(void)
+{
+ of_platform_bus_probe(NULL, sam440ep_of_bus, NULL);
+
+ return 0;
+}
+machine_device_initcall(sam440ep, sam440ep_device_probe);
+
+static int __init sam440ep_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (!of_flat_dt_is_compatible(root, "acube,sam440ep"))
+ return 0;
+
+ ppc_pci_flags = PPC_PCI_REASSIGN_ALL_RSRC;
+
+ return 1;
+}
+
+define_machine(sam440ep) {
+ .name = "Sam440ep",
+ .probe = sam440ep_probe,
+ .progress = udbg_progress,
+ .init_IRQ = uic_init_tree,
+ .get_irq = uic_get_irq,
+ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+};
+
+static struct i2c_board_info sam440ep_rtc_info = {
+ .type = "m41st85",
+ .addr = 0x68,
+ .irq = -1,
+};
+
+static int sam440ep_setup_rtc(void)
+{
+ return i2c_register_board_info(0, &sam440ep_rtc_info, 1);
+}
+machine_device_initcall(sam440ep, sam440ep_setup_rtc);
diff --git a/arch/powerpc/platforms/44x/virtex.c b/arch/powerpc/platforms/44x/virtex.c
new file mode 100644
index 00000000000..68637faf70a
--- /dev/null
+++ b/arch/powerpc/platforms/44x/virtex.c
@@ -0,0 +1,60 @@
+/*
+ * Xilinx Virtex 5FXT based board support, derived from
+ * the Xilinx Virtex (IIpro & 4FX) based board support
+ *
+ * Copyright 2007 Secret Lab Technologies Ltd.
+ * Copyright 2008 Xilinx, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/of_platform.h>
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+#include <asm/xilinx_intc.h>
+#include <asm/reg.h>
+#include <asm/ppc4xx.h>
+#include "44x.h"
+
+static struct of_device_id xilinx_of_bus_ids[] __initdata = {
+ { .compatible = "simple-bus", },
+ { .compatible = "xlnx,plb-v46-1.00.a", },
+ { .compatible = "xlnx,plb-v46-1.02.a", },
+ { .compatible = "xlnx,plb-v34-1.01.a", },
+ { .compatible = "xlnx,plb-v34-1.02.a", },
+ { .compatible = "xlnx,opb-v20-1.10.c", },
+ { .compatible = "xlnx,dcr-v29-1.00.a", },
+ { .compatible = "xlnx,compound", },
+ {}
+};
+
+static int __init virtex_device_probe(void)
+{
+ of_platform_bus_probe(NULL, xilinx_of_bus_ids, NULL);
+
+ return 0;
+}
+machine_device_initcall(virtex, virtex_device_probe);
+
+static int __init virtex_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (!of_flat_dt_is_compatible(root, "xlnx,virtex440"))
+ return 0;
+
+ return 1;
+}
+
+define_machine(virtex) {
+ .name = "Xilinx Virtex440",
+ .probe = virtex_probe,
+ .init_IRQ = xilinx_intc_init_tree,
+ .get_irq = xilinx_intc_get_irq,
+ .calibrate_decr = generic_calibrate_decr,
+ .restart = ppc4xx_reset_system,
+};
diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
index 9150318cfc5..e55746b824b 100644
--- a/arch/powerpc/platforms/44x/warp-nand.c
+++ b/arch/powerpc/platforms/44x/warp-nand.c
@@ -11,8 +11,10 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/ndfc.h>
+#include <linux/of.h>
#include <asm/machdep.h>
+
#ifdef CONFIG_MTD_NAND_NDFC
#define CS_NAND_0 1 /* use chip select 1 for NAND device 0 */
@@ -35,13 +37,23 @@ static struct mtd_partition nand_parts[] = {
{
.name = "root",
.offset = 0x0200000,
- .size = 0x3400000
+ .size = 0x3E00000
+ },
+ {
+ .name = "persistent",
+ .offset = 0x4000000,
+ .size = 0x4000000
},
{
- .name = "user",
- .offset = 0x3600000,
- .size = 0x0A00000
+ .name = "persistent1",
+ .offset = 0x8000000,
+ .size = 0x4000000
},
+ {
+ .name = "persistent2",
+ .offset = 0xC000000,
+ .size = 0x4000000
+ }
};
struct ndfc_controller_settings warp_ndfc_settings = {
@@ -67,27 +79,22 @@ static struct platform_device warp_ndfc_device = {
.resource = &warp_ndfc,
};
-static struct nand_ecclayout nand_oob_16 = {
- .eccbytes = 3,
- .eccpos = { 0, 1, 2, 3, 6, 7 },
- .oobfree = { {.offset = 8, .length = 16} }
-};
-
+/* Do NOT set the ecclayout: let it default so it is correct for both
+ * 64M and 256M flash chips.
+ */
static struct platform_nand_chip warp_nand_chip0 = {
.nr_chips = 1,
.chip_offset = CS_NAND_0,
.nr_partitions = ARRAY_SIZE(nand_parts),
.partitions = nand_parts,
- .chip_delay = 50,
- .ecclayout = &nand_oob_16,
+ .chip_delay = 20,
.priv = &warp_chip0_settings,
};
static struct platform_device warp_nand_device = {
.name = "ndfc-chip",
.id = 0,
- .num_resources = 1,
- .resource = &warp_ndfc,
+ .num_resources = 0,
.dev = {
.platform_data = &warp_nand_chip0,
.parent = &warp_ndfc_device.dev,
@@ -96,6 +103,28 @@ static struct platform_device warp_nand_device = {
static int warp_setup_nand_flash(void)
{
+ struct device_node *np;
+
+ /* Try to detect a rev A based on NOR size. */
+ np = of_find_compatible_node(NULL, NULL, "cfi-flash");
+ if (np) {
+ struct property *pp;
+
+ pp = of_find_property(np, "reg", NULL);
+ if (pp && (pp->length == 12)) {
+ u32 *v = pp->value;
+ if (v[2] == 0x4000000) {
+ /* Rev A = 64M NAND */
+ warp_nand_chip0.nr_partitions = 3;
+
+ nand_parts[1].size = 0x3000000;
+ nand_parts[2].offset = 0x3200000;
+ nand_parts[2].size = 0x0e00000;
+ }
+ }
+ of_node_put(np);
+ }
+
platform_device_register(&warp_ndfc_device);
platform_device_register(&warp_nand_device);
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c
index 39cf6150a72..9565995cba7 100644
--- a/arch/powerpc/platforms/44x/warp.c
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -12,6 +12,9 @@
#include <linux/init.h>
#include <linux/of_platform.h>
#include <linux/kthread.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <asm/machdep.h>
#include <asm/prom.h>
@@ -27,6 +30,18 @@ static __initdata struct of_device_id warp_of_bus[] = {
{},
};
+static __initdata struct i2c_board_info warp_i2c_info[] = {
+ { I2C_BOARD_INFO("ad7414", 0x4a) }
+};
+
+static int __init warp_arch_init(void)
+{
+ /* This should go away once support is moved to the dts. */
+ i2c_register_board_info(0, warp_i2c_info, ARRAY_SIZE(warp_i2c_info));
+ return 0;
+}
+machine_arch_initcall(warp, warp_arch_init);
+
static int __init warp_device_probe(void)
{
of_platform_bus_probe(NULL, warp_of_bus, NULL);
@@ -52,61 +67,232 @@ define_machine(warp) {
};
-#define LED_GREEN (0x80000000 >> 0)
-#define LED_RED (0x80000000 >> 1)
+/* I am not sure this is the best place for this... */
+static int __init warp_post_info(void)
+{
+ struct device_node *np;
+ void __iomem *fpga;
+ u32 post1, post2;
+
+ /* Sighhhh... POST information is in the sd area. */
+ np = of_find_compatible_node(NULL, NULL, "pika,fpga-sd");
+ if (np == NULL)
+ return -ENOENT;
+
+ fpga = of_iomap(np, 0);
+ of_node_put(np);
+ if (fpga == NULL)
+ return -ENOENT;
+
+ post1 = in_be32(fpga + 0x40);
+ post2 = in_be32(fpga + 0x44);
+
+ iounmap(fpga);
+
+ if (post1 || post2)
+ printk(KERN_INFO "Warp POST %08x %08x\n", post1, post2);
+ else
+ printk(KERN_INFO "Warp POST OK\n");
+
+ return 0;
+}
+machine_late_initcall(warp, warp_post_info);
+
+
+#ifdef CONFIG_SENSORS_AD7414
+
+static LIST_HEAD(dtm_shutdown_list);
+static void __iomem *dtm_fpga;
+static void __iomem *gpio_base;
+
+
+struct dtm_shutdown {
+ struct list_head list;
+ void (*func)(void *arg);
+ void *arg;
+};
-/* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */
-void warp_set_power_leds(int green, int red)
+int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
{
- static void __iomem *gpio_base = NULL;
- unsigned leds;
-
- if (gpio_base == NULL) {
- struct device_node *np;
-
- /* Power LEDS are on the second GPIO controller */
- np = of_find_compatible_node(NULL, NULL, "ibm,gpio-440EP");
- if (np)
- np = of_find_compatible_node(np, NULL, "ibm,gpio-440EP");
- if (np == NULL) {
- printk(KERN_ERR __FILE__ ": Unable to find gpio\n");
- return;
+ struct dtm_shutdown *shutdown;
+
+ shutdown = kmalloc(sizeof(struct dtm_shutdown), GFP_KERNEL);
+ if (shutdown == NULL)
+ return -ENOMEM;
+
+ shutdown->func = func;
+ shutdown->arg = arg;
+
+ list_add(&shutdown->list, &dtm_shutdown_list);
+
+ return 0;
+}
+
+int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
+{
+ struct dtm_shutdown *shutdown;
+
+ list_for_each_entry(shutdown, &dtm_shutdown_list, list)
+ if (shutdown->func == func && shutdown->arg == arg) {
+ list_del(&shutdown->list);
+ kfree(shutdown);
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static irqreturn_t temp_isr(int irq, void *context)
+{
+ struct dtm_shutdown *shutdown;
+
+ local_irq_disable();
+
+ /* Run through the shutdown list. */
+ list_for_each_entry(shutdown, &dtm_shutdown_list, list)
+ shutdown->func(shutdown->arg);
+
+ printk(KERN_EMERG "\n\nCritical Temperature Shutdown\n");
+
+ while (1) {
+ if (dtm_fpga) {
+ unsigned reset = in_be32(dtm_fpga + 0x14);
+ out_be32(dtm_fpga + 0x14, reset);
}
- gpio_base = of_iomap(np, 0);
- of_node_put(np);
- if (gpio_base == NULL) {
- printk(KERN_ERR __FILE__ ": Unable to map gpio");
- return;
+ if (gpio_base) {
+ unsigned leds = in_be32(gpio_base);
+
+ /* green off, red toggle */
+ leds &= ~0x80000000;
+ leds ^= 0x40000000;
+
+ out_be32(gpio_base, leds);
}
+
+ mdelay(500);
+ }
+}
+
+static int pika_setup_leds(void)
+{
+ struct device_node *np;
+ const u32 *gpios;
+ int len;
+
+ np = of_find_compatible_node(NULL, NULL, "linux,gpio-led");
+ if (!np) {
+ printk(KERN_ERR __FILE__ ": Unable to find gpio-led\n");
+ return -ENOENT;
}
- leds = in_be32(gpio_base);
+ gpios = of_get_property(np, "gpios", &len);
+ of_node_put(np);
+ if (!gpios || len < 4) {
+ printk(KERN_ERR __FILE__
+ ": Unable to get gpios property (%d)\n", len);
+ return -ENOENT;
+ }
- switch (green) {
- case 0: leds &= ~LED_GREEN; break;
- case 1: leds |= LED_GREEN; break;
+ np = of_find_node_by_phandle(gpios[0]);
+ if (!np) {
+ printk(KERN_ERR __FILE__ ": Unable to find gpio\n");
+ return -ENOENT;
}
- switch (red) {
- case 0: leds &= ~LED_RED; break;
- case 1: leds |= LED_RED; break;
+
+ gpio_base = of_iomap(np, 0);
+ of_node_put(np);
+ if (!gpio_base) {
+ printk(KERN_ERR __FILE__ ": Unable to map gpio");
+ return -ENOMEM;
}
- out_be32(gpio_base, leds);
+ return 0;
}
-EXPORT_SYMBOL(warp_set_power_leds);
+static void pika_setup_critical_temp(struct i2c_client *client)
+{
+ struct device_node *np;
+ int irq, rc;
+
+ /* Do this before enabling critical temp interrupt since we
+ * may immediately interrupt.
+ */
+ pika_setup_leds();
+
+ /* These registers are in 1 degree increments. */
+ i2c_smbus_write_byte_data(client, 2, 65); /* Thigh */
+ i2c_smbus_write_byte_data(client, 3, 55); /* Tlow */
+
+ np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
+ if (np == NULL) {
+ printk(KERN_ERR __FILE__ ": Unable to find ad7414\n");
+ return;
+ }
+
+ irq = irq_of_parse_and_map(np, 0);
+ of_node_put(np);
+ if (irq == NO_IRQ) {
+ printk(KERN_ERR __FILE__ ": Unable to get ad7414 irq\n");
+ return;
+ }
+
+ rc = request_irq(irq, temp_isr, 0, "ad7414", NULL);
+ if (rc) {
+ printk(KERN_ERR __FILE__
+ ": Unable to request ad7414 irq %d = %d\n", irq, rc);
+ return;
+ }
+}
+
+static inline void pika_dtm_check_fan(void __iomem *fpga)
+{
+ static int fan_state;
+ u32 fan = in_be32(fpga + 0x34) & (1 << 14);
+
+ if (fan_state != fan) {
+ fan_state = fan;
+ if (fan)
+ printk(KERN_WARNING "Fan rotation error detected."
+ " Please check hardware.\n");
+ }
+}
-#ifdef CONFIG_SENSORS_AD7414
static int pika_dtm_thread(void __iomem *fpga)
{
- extern int ad7414_get_temp(int index);
+ struct i2c_adapter *adap;
+ struct i2c_client *client;
+
+ /* We loop in case either driver was compiled as a module and
+ * has not been insmoded yet.
+ */
+ while (!(adap = i2c_get_adapter(0))) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ }
+
+ while (1) {
+ list_for_each_entry(client, &adap->clients, list)
+ if (client->addr == 0x4a)
+ goto found_it;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ }
+
+found_it:
+ i2c_put_adapter(adap);
+
+ pika_setup_critical_temp(client);
+
+ printk(KERN_INFO "PIKA DTM thread running.\n");
while (!kthread_should_stop()) {
- int temp = ad7414_get_temp(0);
+ u16 temp = swab16(i2c_smbus_read_word_data(client, 0));
+ out_be32(fpga + 0x20, temp);
- out_be32(fpga, temp);
+ pika_dtm_check_fan(fpga);
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(HZ);
@@ -115,37 +301,44 @@ static int pika_dtm_thread(void __iomem *fpga)
return 0;
}
+
static int __init pika_dtm_start(void)
{
struct task_struct *dtm_thread;
struct device_node *np;
- struct resource res;
- void __iomem *fpga;
np = of_find_compatible_node(NULL, NULL, "pika,fpga");
if (np == NULL)
return -ENOENT;
- /* We do not call of_iomap here since it would map in the entire
- * fpga space, which is over 8k.
- */
- if (of_address_to_resource(np, 0, &res)) {
- of_node_put(np);
- return -ENOENT;
- }
+ dtm_fpga = of_iomap(np, 0);
of_node_put(np);
-
- fpga = ioremap(res.start, 0x24);
- if (fpga == NULL)
+ if (dtm_fpga == NULL)
return -ENOENT;
- dtm_thread = kthread_run(pika_dtm_thread, fpga + 0x20, "pika-dtm");
+ dtm_thread = kthread_run(pika_dtm_thread, dtm_fpga, "pika-dtm");
if (IS_ERR(dtm_thread)) {
- iounmap(fpga);
+ iounmap(dtm_fpga);
return PTR_ERR(dtm_thread);
}
return 0;
}
-device_initcall(pika_dtm_start);
+machine_late_initcall(warp, pika_dtm_start);
+
+#else /* !CONFIG_SENSORS_AD7414 */
+
+int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg)
+{
+ return 0;
+}
+
+int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
+{
+ return 0;
+}
+
#endif
+
+EXPORT_SYMBOL(pika_dtm_register_shutdown);
+EXPORT_SYMBOL(pika_dtm_unregister_shutdown);