[RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to support Rev B boards

Subsystems: linux for powerpc (32-bit and 64-bit), linux for powerpc embedded ppc4xx, the rest

28 messages, 8 authors, 2008-05-06 · open the first message on its own page

[RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to support Rev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-17 19:22:52

PIKA Warp: Update platform code to support Rev B boards.
* Switched from 64M NOR/64M NAND to 4M NOR/256M NAND.
* Full DTM support including critical temperature.
* Added POST information.
* Removed LED function, moved to new LED driver.
* Moved ad7414 to new style I2C initialization.

Signed-off-by: Sean MacLennan <redacted>
diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
index eb108a8..2178021 100644
--- a/arch/powerpc/boot/cuboot-warp.c
+++ b/arch/powerpc/boot/cuboot-warp.c
@@ -10,6 +10,7 @@
 #include "ops.h"
 #include "4xx.h"
 #include "cuboot.h"
+#include "stdio.h"
 
 #define TARGET_4xx
 #define TARGET_44x
@@ -17,14 +18,54 @@
 
 static bd_t bd;
 
-static void warp_fixups(void)
+static void warp_fixup_one_nor(u32 from, u32 to)
 {
-	unsigned long sysclk = 66000000;
+	void *devp;
+	char name[50];
+	u32 v[2];
+
+	sprintf(name, "/plb/opb/ebc/nor_flash@0,0/partition@%x", from);
+
+	devp = finddevice(name);
+	if (!devp)
+		return;
+
+	if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+		v[0] = to;
+		setprop(devp, "reg", v, sizeof(v));
+
+		printf("NOR 64M fixup %x -> %x\r\n", from, to);
+	}
+}
+
 
-	ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+static void warp_fixups(void)
+{
+	ibm440ep_fixup_clocks(66000000, 11059200, 50000000);
 	ibm4xx_sdram_fixup_memsize();
 	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
 	dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+
+	/* Fixup for 64M flash on Rev A boards. */
+	if (bd.bi_flashsize == 0x4000000) {
+		void *devp;
+		u32 v[3];
+
+		devp = finddevice("/plb/opb/ebc/nor_flash@0,0");
+		if (!devp)
+			return;
+
+		/* Fixup the size */
+		if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+			v[2] = bd.bi_flashsize;
+			setprop(devp, "reg", v, sizeof(v));
+		}
+
+		/* Fixup parition offsets */
+		warp_fixup_one_nor(0x300000, 0x3f00000);
+		warp_fixup_one_nor(0x340000, 0x3f40000);
+		warp_fixup_one_nor(0x380000, 0x3f80000);
+	}
 }
 
 
diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
index b04a52e..fa070b0 100644
--- a/arch/powerpc/boot/dts/warp.dts
+++ b/arch/powerpc/boot/dts/warp.dts
@@ -132,40 +132,33 @@
 
 				fpga@2,0 {
 					compatible = "pika,fpga";
-			   		reg = <2 0 2200>;
+			   		reg = <2 0 1000>;
 					interrupts = <18 8>;
 					interrupt-parent = <&UIC0>;
 				};
 
+				fpga@2,4000 {
+					compatible = "pika,fpga-sd";
+					reg = <2 4000 A00>;
+				};
+
 				nor_flash@0,0 {
-					compatible = "amd,s29gl512n", "cfi-flash";
+					compatible = "amd,s29gl032a", "cfi-flash";
 					bank-width = <2>;
-					reg = <0 0 4000000>;
+					reg = <0 0 400000>;
 					#address-cells = <1>;
 					#size-cells = <1>;
-					partition@0 {
-						label = "kernel";
-						reg = <0 180000>;
-					};
-					partition@180000 {
-						label = "root";
-						reg = <180000 3480000>;
-					};
-					partition@3600000 {
-						label = "user";
-						reg = <3600000 900000>;
-					};
-					partition@3f00000 {
+					partition@300000 {
 						label = "fpga";
-						reg = <3f00000 40000>;
+						reg = <300000 40000>;
 					};
-					partition@3f40000 {
+					partition@340000 {
 						label = "env";
-						reg = <3f40000 40000>;
+						reg = <340000 40000>;
 					};
-					partition@3f80000 {
+					partition@380000 {
 						label = "u-boot";
-						reg = <3f80000 80000>;
+						reg = <380000 80000>;
 					};
 				};
 			};
@@ -186,6 +179,16 @@
 				reg = <ef600700 14>;
 				interrupt-parent = <&UIC0>;
 				interrupts = <2 4>;
+				index = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				ad7414@4a {
+					compatible = "adi,ad7414";
+					reg = <4a>;
+					interrupts = <19 8>;
+					interrupt-parent = <&UIC0>;
+				};
 			};
 
 			GPIO0: gpio@ef600b00 {
diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
index 9150318..4c6a2a5 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_platform.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,19 +79,15 @@ 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,
 };
 
@@ -96,6 +104,23 @@ 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 = 2;
+		}
+		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 39cf615..d770b8f 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/pika.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,183 @@ 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;
+
+struct dtm_shutdown {
+	struct list_head list;
+	void (*func)(void *arg);
+	void *arg;
+};
+
+
+int dtm_register_shutdown(void (*func)(void *arg), void *arg)
+{
+	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;
+}
+EXPORT_SYMBOL(dtm_register_shutdown);
 
-/* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */
-void warp_set_power_leds(int green, int red)
+int dtm_unregister_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;
 
-		gpio_base = of_iomap(np, 0);
-		of_node_put(np);
-		if (gpio_base == NULL) {
-			printk(KERN_ERR __FILE__ ": Unable to map gpio");
-			return;
+	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;
+}
+EXPORT_SYMBOL(dtm_unregister_shutdown);
+
+static long wdt_keepalive(long time)
+{
+	if (dtm_fpga) {
+		unsigned reset = in_be32(dtm_fpga + 0x14);
+		out_be32(dtm_fpga + 0x14, reset);
 	}
 
-	leds = in_be32(gpio_base);
+	return 0;
+}
+
+static irqreturn_t temp_isr(int irq, void *context)
+{
+	struct dtm_shutdown *shutdown;
+
+	/* Run through the shutdown list. */
+	list_for_each_entry(shutdown, &dtm_shutdown_list, list)
+		shutdown->func(shutdown->arg);
+
+	panic_timeout = 1800;
+	panic_blink = wdt_keepalive;
+	panic("Critical Temperature Shutdown");
+	return IRQ_HANDLED;
+}
+
+static void pika_setup_critical_temp(struct i2c_client *client)
+{
+	struct device_node *np;
+	int irq, rc;
+
+	/* 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 */
 
-	switch (green) {
-	case 0: leds &= ~LED_GREEN; break;
-	case 1: leds |=  LED_GREEN; break;
+	np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
+	if (np == NULL) {
+		printk(KERN_ERR __FILE__ ": Unable to find ad7414\n");
+		return;
 	}
-	switch (red) {
-	case 0: leds &= ~LED_RED; break;
-	case 1: leds |=  LED_RED; break;
+
+	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;
 	}
 
-	out_be32(gpio_base, leds);
+	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;
+	}
 }
-EXPORT_SYMBOL(warp_set_power_leds);
 
+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 +252,28 @@ 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);
 #endif

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-27 19:25:49

Update. HW decided that the panic was bad. Added a flashing led to the
critical temperature.

Cheers,
   Sean

PIKA Warp: Update platform code to support Rev B boards.
* Switched from 64M NOR/64M NAND to 4M NOR/256M NAND.
* Full DTM support including critical temperature.
* Added POST information.
* Removed LED function, moved to new LED driver.
* Moved ad7414 to new style I2C initialization.

Signed-off-by: Sean MacLennan <redacted>
diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
index eb108a8..2178021 100644
--- a/arch/powerpc/boot/cuboot-warp.c
+++ b/arch/powerpc/boot/cuboot-warp.c
@@ -10,6 +10,7 @@
 #include "ops.h"
 #include "4xx.h"
 #include "cuboot.h"
+#include "stdio.h"

 #define TARGET_4xx
 #define TARGET_44x
@@ -17,0 +18,0 @@

 static bd_t bd;

-static void warp_fixups(void)
+static void warp_fixup_one_nor(u32 from, u32 to)
 {
-	unsigned long sysclk = 66000000;
+	void *devp;
+	char name[50];
+	u32 v[2];
+
+	sprintf(name, "/plb/opb/ebc/nor_flash@0,0/partition@%x", from);
+
+	devp = finddevice(name);
+	if (!devp)
+		return;
+
+	if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+		v[0] = to;
+		setprop(devp, "reg", v, sizeof(v));
+
+		printf("NOR 64M fixup %x -> %x\r\n", from, to);
+	}
+}
+
 
-	ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+static void warp_fixups(void)
+{
+	ibm440ep_fixup_clocks(66000000, 11059200, 50000000);
 	ibm4xx_sdram_fixup_memsize();
 	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
 	dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+
+	/* Fixup for 64M flash on Rev A boards. */
+	if (bd.bi_flashsize == 0x4000000) {
+		void *devp;
+		u32 v[3];
+
+		devp = finddevice("/plb/opb/ebc/nor_flash@0,0");
+		if (!devp)
+			return;
+
+		/* Fixup the size */
+		if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+			v[2] = bd.bi_flashsize;
+			setprop(devp, "reg", v, sizeof(v));
+		}
+
+		/* Fixup parition offsets */
+		warp_fixup_one_nor(0x300000, 0x3f00000);
+		warp_fixup_one_nor(0x340000, 0x3f40000);
+		warp_fixup_one_nor(0x380000, 0x3f80000);
+	}
 }
 
 
diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
index b04a52e..fa070b0 100644
--- a/arch/powerpc/boot/dts/warp.dts
+++ b/arch/powerpc/boot/dts/warp.dts
@@ -132,40 +132,33 @@
 
 				fpga@2,0 {
 					compatible = "pika,fpga";
-			   		reg = <2 0 2200>;
+			   		reg = <2 0 1000>;
 					interrupts = <18 8>;
 					interrupt-parent = <&UIC0>;
 				};
 
+				fpga@2,4000 {
+					compatible = "pika,fpga-sd";
+					reg = <2 4000 A00>;
+				};
+
 				nor_flash@0,0 {
-					compatible = "amd,s29gl512n", "cfi-flash";
+					compatible = "amd,s29gl032a", "cfi-flash";
 					bank-width = <2>;
-					reg = <0 0 4000000>;
+					reg = <0 0 400000>;
 					#address-cells = <1>;
 					#size-cells = <1>;
-					partition@0 {
-						label = "kernel";
-						reg = <0 180000>;
-					};
-					partition@180000 {
-						label = "root";
-						reg = <180000 3480000>;
-					};
-					partition@3600000 {
-						label = "user";
-						reg = <3600000 900000>;
-					};
-					partition@3f00000 {
+					partition@300000 {
 						label = "fpga";
-						reg = <3f00000 40000>;
+						reg = <300000 40000>;
 					};
-					partition@3f40000 {
+					partition@340000 {
 						label = "env";
-						reg = <3f40000 40000>;
+						reg = <340000 40000>;
 					};
-					partition@3f80000 {
+					partition@380000 {
 						label = "u-boot";
-						reg = <3f80000 80000>;
+						reg = <380000 80000>;
 					};
 				};
 			};
@@ -186,6 +179,16 @@
 				reg = <ef600700 14>;
 				interrupt-parent = <&UIC0>;
 				interrupts = <2 4>;
+				index = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				ad7414@4a {
+					compatible = "adi,ad7414";
+					reg = <4a>;
+					interrupts = <19 8>;
+					interrupt-parent = <&UIC0>;
+				};
 			};
 
 			GPIO0: gpio@ef600b00 {
diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
index 9150318..4c6a2a5 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_platform.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,19 +79,15 @@ 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,
 };
 
@@ -96,6 +104,23 @@ 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 = 2;
+		}
+		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 39cf615..1b2d09e 100644
--- a/arch/powerpc/platforms/44x/warp.c
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -12,6 +12,10 @@
 #include <linux/init.h>
 #include <linux/of_platform.h>
 #include <linux/kthread.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/pika.h>
+#include <linux/delay.h>
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
@@ -27,6 +31,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 +68,200 @@ 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;
 
-/* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */
-void warp_set_power_leds(int green, int red)
+
+struct dtm_shutdown {
+	struct list_head list;
+	void (*func)(void *arg);
+	void *arg;
+};
+
+
+int dtm_register_shutdown(void (*func)(void *arg), void *arg)
+{
+	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 dtm_unregister_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;
+
+	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);
+		}
+
+		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 void pika_setup_critical_temp(struct i2c_client *client)
+{
+	struct device_node *np;
+	int irq, rc;
+
+	/* Setup power LEDS for possible critical temp */
+	np = of_find_compatible_node(NULL, NULL, "ibm,gpio-440EP");
+	if (np)
+		np = of_find_compatible_node(np, NULL, "ibm,gpio-440EP");
+	if (np) {
 		gpio_base = of_iomap(np, 0);
 		of_node_put(np);
-		if (gpio_base == NULL) {
-			printk(KERN_ERR __FILE__ ": Unable to map gpio");
-			return;
-		}
 	}
 
-	leds = in_be32(gpio_base);
+	/* 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 */
 
-	switch (green) {
-	case 0: leds &= ~LED_GREEN; break;
-	case 1: leds |=  LED_GREEN; break;
+	np = of_find_compatible_node(NULL, NULL, "adi,ad7414");
+	if (np == NULL) {
+		printk(KERN_ERR __FILE__ ": Unable to find ad7414\n");
+		return;
 	}
-	switch (red) {
-	case 0: leds &= ~LED_RED; break;
-	case 1: leds |=  LED_RED; break;
+
+	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;
 	}
 
-	out_be32(gpio_base, leds);
+	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;
+	}
 }
-EXPORT_SYMBOL(warp_set_power_leds);
 
+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 +270,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 dtm_register_shutdown(void (*func)(void *arg), void *arg)
+{
+	return 0;
+}
+
+int dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
+{
+	return 0;
+}
+
 #endif
+
+EXPORT_SYMBOL(dtm_register_shutdown);
+EXPORT_SYMBOL(dtm_unregister_shutdown);

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Stephen Rothwell <hidden>
Date: 2008-04-28 00:59:05

Hi Sean,

On Sun, 27 Apr 2008 15:25:46 -0400 Sean MacLennan [off-list ref] wrote:
quoted hunk
+++ 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_platform.h>
You really want linux.of.h (unless there was some preexisting reason to
require of_platform.h).
+static void pika_setup_critical_temp(struct i2c_client *client)
+{
+	struct device_node *np;
+	int irq, rc;
+
+	/* Setup power LEDS for possible critical temp */
+	np = of_find_compatible_node(NULL, NULL, "ibm,gpio-440EP");
+	if (np)
+		np = of_find_compatible_node(np, NULL, "ibm,gpio-440EP");
Did you really mean to test if (!np) above instead?

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Grant Likely <hidden>
Date: 2008-04-28 01:51:58

On Sun, Apr 27, 2008 at 6:58 PM, Stephen Rothwell [off-list ref] wrote:
Hi Sean,


 On Sun, 27 Apr 2008 15:25:46 -0400 Sean MacLennan [off-list ref] wrote:
 >
 > +++ 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_platform.h>

 You really want linux.of.h (unless there was some preexisting reason to
 require of_platform.h).


 > +static void pika_setup_critical_temp(struct i2c_client *client)
 > +{
 > +     struct device_node *np;
 > +     int irq, rc;
 > +
 > +     /* Setup power LEDS for possible critical temp */
 > +     np = of_find_compatible_node(NULL, NULL, "ibm,gpio-440EP");
 > +     if (np)
 > +             np = of_find_compatible_node(np, NULL, "ibm,gpio-440EP");

 Did you really mean to test if (!np) above instead?
Actually, it looks like he's trying to find the second gpio node in the tree.

Sean, if that is true, then this is a very fragile way to do it.
Really, you should have a phandle somewhere that points to the GPIO
node that your LEDs are attached to.  Others have been addressing the
same problem and the consensus seems to be to add a 'leds' node for
each of your leds with a phandle and gpio descriptor to the gpio node.

See the documentation added by this patch (section 't'):
http://patchwork.ozlabs.org/linuxppc/patch?id=18156

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-28 02:25:16

On Sun, 27 Apr 2008 19:51:57 -0600
"Grant Likely" [off-list ref] wrote:
Actually, it looks like he's trying to find the second gpio node in
the tree.
Correct.
Sean, if that is true, then this is a very fragile way to do it.
Really, you should have a phandle somewhere that points to the GPIO
node that your LEDs are attached to.  Others have been addressing the
same problem and the consensus seems to be to add a 'leds' node for
each of your leds with a phandle and gpio descriptor to the gpio node.

See the documentation added by this patch (section 't'):
http://patchwork.ozlabs.org/linuxppc/patch?id=18156
I saw that earlier. I thought that that method relied on the gpio_led
driver? I want to use the gpio_led driver, but I believe the underlying
gpio code for the 440EP is not done yet.

If *either* assumption is wrong, let me know! It would be one less
driver (the warp_led driver) that I would have to support outside the
mainline kernel.

I believe, if the platform update gets accepted, that in 2.6.26 the
Warp will be usable with the the mainline kernel. You will just lose
some functionally, such as the SD driver which has already been
rejected.

Cheers,
   Sean

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-28 02:31:43

On Mon, 28 Apr 2008 10:58:59 +1000
"Stephen Rothwell" [off-list ref] wrote:
You really want linux.of.h (unless there was some preexisting reason
to require of_platform.h).
You are correct. That was a cut and paste from warp.c which
specifically needs of_platform.h.

Cheers,
   Sean

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Grant Likely <hidden>
Date: 2008-04-28 04:47:44

On Sun, Apr 27, 2008 at 8:25 PM, Sean MacLennan [off-list ref] wrote:
On Sun, 27 Apr 2008 19:51:57 -0600
 "Grant Likely" [off-list ref] wrote:

 > Actually, it looks like he's trying to find the second gpio node in
 > the tree.

 Correct.


 > Sean, if that is true, then this is a very fragile way to do it.
 > Really, you should have a phandle somewhere that points to the GPIO
 > node that your LEDs are attached to.  Others have been addressing the
 > same problem and the consensus seems to be to add a 'leds' node for
 > each of your leds with a phandle and gpio descriptor to the gpio node.
 >
 > See the documentation added by this patch (section 't'):
 > http://patchwork.ozlabs.org/linuxppc/patch?id=18156

 I saw that earlier. I thought that that method relied on the gpio_led
 driver? I want to use the gpio_led driver, but I believe the underlying
 gpio code for the 440EP is not done yet.
Something very important to remember:  The device tree is simply a
description of the hardware.  Its layout *must* *not* be driven by
device driver design.  Driver design can and will change over time;
hardware description conventions should be relatively stable.

If your LEDs are attached to gpio pins, then you should use the
current draft led->gpio bindings as shown in the above patch.  Then,
let your platform code extract whatever data it needs from the device
tree to set up the LEDs.

It is irrelevant that the 44EP GPIO driver doesn't support that
binding.  Just make sure that the warp platform code doesn't register
warp's linux,gpio-led device tree nodes onto the of_platform bus.
That way your platform code can do whatever it wants to handle the
LEDs itself.

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-28 17:10:03

On Sun, 27 Apr 2008 22:47:43 -0600
"Grant Likely" [off-list ref] wrote:
If your LEDs are attached to gpio pins, then you should use the
current draft led->gpio bindings as shown in the above patch.  Then,
let your platform code extract whatever data it needs from the device
tree to set up the LEDs.
I added the following to the dts:

	led@31 {
		compatible = "linux,gpio-led";
		linux,name = "green";
		gpios = <&GPIO1 31>;
	};

	led@30 {
		compatible = "linux,gpio-led";
		linux,name = "red";
		gpios = <&GPIO1 30>;
	};

I then map the gpio base as follows (I removed the if checks just to
make things short and sweet):

	np = of_find_compatible_node(NULL, NULL, "linux,gpio-led");

	gpios = of_get_property(np, "gpios", &lenp);
	of_node_put(np);

	np = of_find_node_by_phandle(gpios[0]);

	gpio_base = of_iomap(np, 0);
	of_node_put(np);

Comments?

Cheers,
  Sean

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Grant Likely <hidden>
Date: 2008-04-28 17:44:21

On Mon, Apr 28, 2008 at 11:10 AM, Sean MacLennan
[off-list ref] wrote:
On Sun, 27 Apr 2008 22:47:43 -0600

"Grant Likely" [off-list ref] wrote:

quoted
If your LEDs are attached to gpio pins, then you should use the
 > current draft led->gpio bindings as shown in the above patch.  Then,
 > let your platform code extract whatever data it needs from the device
 > tree to set up the LEDs.

 I added the following to the dts:

        led@31 {
                compatible = "linux,gpio-led";
                linux,name = "green";
                gpios = <&GPIO1 31>;
        };

        led@30 {
                compatible = "linux,gpio-led";
                linux,name = "red";
                gpios = <&GPIO1 30>;
        };
This looks appropriate.  You'll need to make sure that the values in
the linux,name property meet the Linux LED naming guidelines.  I think
this is covered in Documentation/leds-class.c.  You can also as
Richard Purdie; the LED subsystem maintainer.
 I then map the gpio base as follows (I removed the if checks just to
 make things short and sweet):

        np = of_find_compatible_node(NULL, NULL, "linux,gpio-led");

        gpios = of_get_property(np, "gpios", &lenp);
        of_node_put(np);

        np = of_find_node_by_phandle(gpios[0]);


        gpio_base = of_iomap(np, 0);
        of_node_put(np);
This isn't ideal, but it will do to start.  However, if other devices
want to use the same GPIO block, then you'll probably have problems
with race conditions.  Eventually, you'll want to use the common GPIO
infrastructure and remove the custom code.

Cheers,
g.


-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-28 17:59:07

On Mon, 28 Apr 2008 11:44:19 -0600
"Grant Likely" [off-list ref] wrote:
This looks appropriate.  You'll need to make sure that the values in
the linux,name property meet the Linux LED naming guidelines.  I think
this is covered in Documentation/leds-class.c.  You can also as
Richard Purdie; the LED subsystem maintainer.
The leds name is "devicename:colour:function" where you are allowed to
leave sections blank. So I only filled in the colour ;)

I also notice that it is colour, not color.

I am hoping that this code is only for 2.6.26 and that we will switch
to the gpio-leds driver for 2.6.27. I don't want to keep supporting yet
another driver outside of the mainline kernel. Let's face it, I'm
lazy :D

Cheers,
   Sean

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-28 18:53:12

Ok, here is another version of the patch with Stephen Rothwell's and
Grant Likely's suggestions.

Cheers,
  Sean

PIKA Warp: Update platform code to support Rev B boards.
* Switched from 64M NOR/64M NAND to 4M NOR/256M NAND.
* Full DTM support including critical temperature.
* Added POST information.
* Removed LED function, moved to new LED driver.
* Moved ad7414 to new style I2C initialization.

Signed-off-by: Sean MacLennan <redacted>
diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
index eb108a8..2178021 100644
--- a/arch/powerpc/boot/cuboot-warp.c
+++ b/arch/powerpc/boot/cuboot-warp.c
@@ -10,6 +10,7 @@
 #include "ops.h"
 #include "4xx.h"
 #include "cuboot.h"
+#include "stdio.h"
 
 #define TARGET_4xx
 #define TARGET_44x
@@ -17,14 +18,54 @@
 
 static bd_t bd;
 
-static void warp_fixups(void)
+static void warp_fixup_one_nor(u32 from, u32 to)
 {
-	unsigned long sysclk = 66000000;
+	void *devp;
+	char name[50];
+	u32 v[2];
+
+	sprintf(name, "/plb/opb/ebc/nor_flash@0,0/partition@%x", from);
+
+	devp = finddevice(name);
+	if (!devp)
+		return;
+
+	if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+		v[0] = to;
+		setprop(devp, "reg", v, sizeof(v));
+
+		printf("NOR 64M fixup %x -> %x\r\n", from, to);
+	}
+}
+
 
-	ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+static void warp_fixups(void)
+{
+	ibm440ep_fixup_clocks(66000000, 11059200, 50000000);
 	ibm4xx_sdram_fixup_memsize();
 	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
 	dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+
+	/* Fixup for 64M flash on Rev A boards. */
+	if (bd.bi_flashsize == 0x4000000) {
+		void *devp;
+		u32 v[3];
+
+		devp = finddevice("/plb/opb/ebc/nor_flash@0,0");
+		if (!devp)
+			return;
+
+		/* Fixup the size */
+		if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+			v[2] = bd.bi_flashsize;
+			setprop(devp, "reg", v, sizeof(v));
+		}
+
+		/* Fixup parition offsets */
+		warp_fixup_one_nor(0x300000, 0x3f00000);
+		warp_fixup_one_nor(0x340000, 0x3f40000);
+		warp_fixup_one_nor(0x380000, 0x3f80000);
+	}
 }
 
 
diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
index b04a52e..d124497 100644
--- a/arch/powerpc/boot/dts/warp.dts
+++ b/arch/powerpc/boot/dts/warp.dts
@@ -132,40 +132,33 @@
 
 				fpga@2,0 {
 					compatible = "pika,fpga";
-			   		reg = <2 0 2200>;
+			   		reg = <2 0 1000>;
 					interrupts = <18 8>;
 					interrupt-parent = <&UIC0>;
 				};
 
+				fpga@2,4000 {
+					compatible = "pika,fpga-sd";
+					reg = <2 4000 A00>;
+				};
+
 				nor_flash@0,0 {
-					compatible = "amd,s29gl512n", "cfi-flash";
+					compatible = "amd,s29gl032a", "cfi-flash";
 					bank-width = <2>;
-					reg = <0 0 4000000>;
+					reg = <0 0 400000>;
 					#address-cells = <1>;
 					#size-cells = <1>;
-					partition@0 {
-						label = "kernel";
-						reg = <0 180000>;
-					};
-					partition@180000 {
-						label = "root";
-						reg = <180000 3480000>;
-					};
-					partition@3600000 {
-						label = "user";
-						reg = <3600000 900000>;
-					};
-					partition@3f00000 {
+					partition@300000 {
 						label = "fpga";
-						reg = <3f00000 40000>;
+						reg = <300000 40000>;
 					};
-					partition@3f40000 {
+					partition@340000 {
 						label = "env";
-						reg = <3f40000 40000>;
+						reg = <340000 40000>;
 					};
-					partition@3f80000 {
+					partition@380000 {
 						label = "u-boot";
-						reg = <3f80000 80000>;
+						reg = <380000 80000>;
 					};
 				};
 			};
@@ -186,6 +179,16 @@
 				reg = <ef600700 14>;
 				interrupt-parent = <&UIC0>;
 				interrupts = <2 4>;
+				index = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				ad7414@4a {
+					compatible = "adi,ad7414";
+					reg = <4a>;
+					interrupts = <19 8>;
+					interrupt-parent = <&UIC0>;
+				};
 			};
 
 			GPIO0: gpio@ef600b00 {
@@ -196,8 +199,22 @@
 			GPIO1: gpio@ef600c00 {
 				compatible = "ibm,gpio-440ep";
 				reg = <ef600c00 48>;
+
+			};
+
+			led@31 {
+				compatible = "linux,gpio-led";
+				linux,name = "green";
+				gpios = <&GPIO1 31>;
+			};
+	
+			led@30 {
+				compatible = "linux,gpio-led";
+				linux,name = "red";
+				gpios = <&GPIO1 30>;
 			};
 
+
 			ZMII0: emac-zmii@ef600d00 {
 				compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii";
 				reg = <ef600d00 c>;
diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
index 9150318..d293c70 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,19 +79,15 @@ 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,
 };
 
@@ -96,6 +104,23 @@ 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 = 2;
+		}
+		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 39cf615..8f7d016 100644
--- a/arch/powerpc/platforms/44x/warp.c
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -12,6 +12,10 @@
 #include <linux/init.h>
 #include <linux/of_platform.h>
 #include <linux/kthread.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/pika.h>
+#include <linux/delay.h>
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
@@ -27,6 +31,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 +68,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 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 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 lenp;
+
+	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", &lenp);
+	of_node_put(np);
+	if (!gpios || lenp != 8) {
+		printk(KERN_ERR __FILE__
+		       ": Unable to get gpios property (%d)\n", lenp);
+		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 +302,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 dtm_register_shutdown(void (*func)(void *arg), void *arg)
+{
+	return 0;
+}
+
+int dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
+{
+	return 0;
+}
+
 #endif
+
+EXPORT_SYMBOL(dtm_register_shutdown);
+EXPORT_SYMBOL(dtm_unregister_shutdown);

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Grant Likely <hidden>
Date: 2008-04-28 19:56:17

On Mon, Apr 28, 2008 at 12:53 PM, Sean MacLennan
[off-list ref] wrote:
Ok, here is another version of the patch with Stephen Rothwell's and
 Grant Likely's suggestions.

 Cheers,
  Sean
A few more comments below.

Also, it might help to split up the .dts and code changes into 2
separate patches.  That way the .dts can be picked up even if the
actual platform code still needs some revisions.

Finally, since this is a 4xx board port, you need to cc: Josh Boyer on
these patches.
quoted hunk
 diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
 index b04a52e..d124497 100644
--- a/arch/powerpc/boot/dts/warp.dts
 +++ b/arch/powerpc/boot/dts/warp.dts
 @@ -186,6 +179,16 @@
                                reg = <ef600700 14>;
                                interrupt-parent = <&UIC0>;
                                interrupts = <2 4>;
 +                               index = <0>;
 +                               #address-cells = <1>;
 +                               #size-cells = <0>;
 +
 +                               ad7414@4a {
 +                                       compatible = "adi,ad7414";
 +                                       reg = <4a>;
 +                                       interrupts = <19 8>;
 +                                       interrupt-parent = <&UIC0>;
 +                               };
                        };

                        GPIO0: gpio@ef600b00 {
 @@ -196,8 +199,22 @@
                        GPIO1: gpio@ef600c00 {
                                compatible = "ibm,gpio-440ep";
                                reg = <ef600c00 48>;
 +
 +                       };
You need to add the gpio-controller and #gpio-cells properties to the
GPIO nodes for the LED's gpios property to work correctly.  Search for
"2) gpio-controller nodes" in
Documentation/powerpc/booting-without-of.txt for details.  #gpio-cells
should probably be '2' for this gpio controller; 1 cell for the gpio
pin and 1 cell for flags.
 +
 +                       led@31 {

+                               compatible = "linux,gpio-led";
 +                               linux,name = "green";
 +                               gpios = <&GPIO1 31>;
 +                       };
 +
 +                       led@30 {
 +                               compatible = "linux,gpio-led";
 +                               linux,name = "red";
 +                               gpios = <&GPIO1 30>;
                        };
These should not be children of the soc node (they are not part of the
SoC internal bus).  However, I think it would be perfectly valid to
make them children of the gpio node since they don't have any
connections to other device on the platform.
quoted hunk
 +
                        ZMII0: emac-zmii@ef600d00 {
                                compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii";
                                reg = <ef600d00 c>;
diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
 index 9150318..d293c70 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
 +       }
  };
Why is this information in the dts *and* the platform file?  I haven't
been following the flash partition map binding conventions, but having
it in both places looks wrong....

oh, wait... the one in the dts is for NOR and this one is for NAND,
right?  And we don't have a binding yet for NAND partitions yet,
correct?
quoted hunk
  struct ndfc_controller_settings warp_ndfc_settings = {
 @@ -67,19 +79,15 @@ 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,
  };

 @@ -96,6 +104,23 @@ 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 = 2;
 +               }
 +               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 39cf615..8f7d016 100644
--- a/arch/powerpc/platforms/44x/warp.c
 +++ b/arch/powerpc/platforms/44x/warp.c
 @@ -12,6 +12,10 @@

 #include <linux/init.h>
  #include <linux/of_platform.h>
  #include <linux/kthread.h>
 +#include <linux/i2c.h>
 +#include <linux/interrupt.h>
 +#include <linux/pika.h>
 +#include <linux/delay.h>


  #include <asm/machdep.h>
  #include <asm/prom.h>
 @@ -27,6 +31,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 +68,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
<snip>
 +#else /* !CONFIG_SENSORS_AD7414 */

+
 +int dtm_register_shutdown(void (*func)(void *arg), void *arg)
 +{
 +       return 0;
 +}

+
 +int dtm_unregister_shutdown(void (*func)(void *arg), void *arg)
 +{
 +       return 0;
 +}
 +
  #endif
 +

+EXPORT_SYMBOL(dtm_register_shutdown);

+EXPORT_SYMBOL(dtm_unregister_shutdown);
When exporting symbols for platform code you should avoid polluting
the global Linux namespace and prefix the functions with your platform
name.

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Richard Purdie <hidden>
Date: 2008-04-28 21:00:45

On Mon, 2008-04-28 at 13:59 -0400, Sean MacLennan wrote:
On Mon, 28 Apr 2008 11:44:19 -0600
"Grant Likely" [off-list ref] wrote:
quoted
This looks appropriate.  You'll need to make sure that the values in
the linux,name property meet the Linux LED naming guidelines.  I think
this is covered in Documentation/leds-class.c.  You can also as
Richard Purdie; the LED subsystem maintainer.
The leds name is "devicename:colour:function" where you are allowed to
leave sections blank. So I only filled in the colour ;)
You can leave sections blank but it pays to leave the separator in so
use ":red:" or ":red", not "red".
I also notice that it is colour, not color.
;-)

Cheers,

Richard

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code tosupportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-28 21:24:57

On Mon, 28 Apr 2008 21:44:05 +0100
"Richard Purdie" [off-list ref] wrote:
You can leave sections blank but it pays to leave the separator in so
use ":red:" or ":red", not "red".
Ok, :red: and :green: it is.

What would be the advantage of pika:red: or warp:red:?

Cheers,
  Sean

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-28 21:37:40

On Mon, 28 Apr 2008 13:56:11 -0600
"Grant Likely" [off-list ref] wrote:
You need to add the gpio-controller and #gpio-cells properties to the
GPIO nodes for the LED's gpios property to work correctly.  Search for
"2) gpio-controller nodes" in
Documentation/powerpc/booting-without-of.txt for details.  #gpio-cells
should probably be '2' for this gpio controller; 1 cell for the gpio
pin and 1 cell for flags.
I believe these gpio nodes predate that text, but I added the fields
anyway.
These should not be children of the soc node (they are not part of the
SoC internal bus).  However, I think it would be perfectly valid to
make them children of the gpio node since they don't have any
connections to other device on the platform.
I put them in gpio. That was where I put them initialy.
Why is this information in the dts *and* the platform file?  I haven't
been following the flash partition map binding conventions, but having
it in both places looks wrong....

oh, wait... the one in the dts is for NOR and this one is for NAND,
right?  And we don't have a binding yet for NAND partitions yet,
correct?
Correct. Josh originally asked me to split out the warp-nand.c file so
that once the NAND is in the dts, we can just delete the file. NAND is
much more complicated that NOR to configure.
When exporting symbols for platform code you should avoid polluting
the global Linux namespace and prefix the functions with your platform
name.
I was hoping dtm was good enough. I prefixed them with the company name.
We are expecting to have a "family" of Asterisk appliances and I am
trying to make educated guesses as to what will be family wide
(prefixed with pika) and what will be warp specific.

Cheers,
   Sean

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code tosupportRev B boards

From: Richard Purdie <hidden>
Date: 2008-04-28 21:38:09

On Mon, 2008-04-28 at 17:24 -0400, Sean MacLennan wrote:
On Mon, 28 Apr 2008 21:44:05 +0100
"Richard Purdie" [off-list ref] wrote:
quoted
You can leave sections blank but it pays to leave the separator in so
use ":red:" or ":red", not "red".
Ok, :red: and :green: it is.

What would be the advantage of pika:red: or warp:red:?
It makes it more obvious which driver is involved which can be useful
when reading bug reports and helps identify things in cases where LEDs
may be plugged in, e.g. USB.

Cheers,

Richard

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Scott Wood <hidden>
Date: 2008-04-28 21:54:31

On Mon, Apr 28, 2008 at 05:37:38PM -0400, Sean MacLennan wrote:
quoted
Why is this information in the dts *and* the platform file?  I haven't
been following the flash partition map binding conventions, but having
it in both places looks wrong....

oh, wait... the one in the dts is for NOR and this one is for NAND,
right?  And we don't have a binding yet for NAND partitions yet,
correct?
Correct.
Why can't the existing partition binding be used with NAND?  It's what we
do with Freescale FCM NAND.

-Scott

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-28 22:07:19

On Mon, 28 Apr 2008 16:54:24 -0500
Scott Wood [off-list ref] wrote:
Why can't the existing partition binding be used with NAND?  It's
what we do with Freescale FCM NAND.
I guess I could put the partitions in the dts. But I would have to
read them and dynamically create an array to pass to the ndfc driver.

It seems simpler to just statically initialize the array. Once the ndfc
is modified to use the dts, I will switch to that method.

Cheers,
   Sean

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Grant Likely <hidden>
Date: 2008-04-28 22:07:57

On Mon, Apr 28, 2008 at 3:37 PM, Sean MacLennan [off-list ref] wrote:
On Mon, 28 Apr 2008 13:56:11 -0600

"Grant Likely" [off-list ref] wrote:

 >
quoted
You need to add the gpio-controller and #gpio-cells properties to the
 > GPIO nodes for the LED's gpios property to work correctly.  Search for
 > "2) gpio-controller nodes" in
 > Documentation/powerpc/booting-without-of.txt for details.  #gpio-cells
 > should probably be '2' for this gpio controller; 1 cell for the gpio
 > pin and 1 cell for flags.

 I believe these gpio nodes predate that text, but I added the fields
 anyway.


 >
 > These should not be children of the soc node (they are not part of the
 > SoC internal bus).  However, I think it would be perfectly valid to
 > make them children of the gpio node since they don't have any
 > connections to other device on the platform.

 I put them in gpio. That was where I put them initialy.


 > Why is this information in the dts *and* the platform file?  I haven't
 > been following the flash partition map binding conventions, but having
 > it in both places looks wrong....
 >
 > oh, wait... the one in the dts is for NOR and this one is for NAND,
 > right?  And we don't have a binding yet for NAND partitions yet,
 > correct?

 Correct. Josh originally asked me to split out the warp-nand.c file so
 that once the NAND is in the dts, we can just delete the file. NAND is
 much more complicated that NOR to configure.


 > When exporting symbols for platform code you should avoid polluting
 > the global Linux namespace and prefix the functions with your platform
 > name.

 I was hoping dtm was good enough. I prefixed them with the company name.
 We are expecting to have a "family" of Asterisk appliances and I am
 trying to make educated guesses as to what will be family wide
 (prefixed with pika) and what will be warp specific.
Its just kernel code; it can be changed easily at later date.  When
the company has *2* boards supported mainline in the kernel, then make
it generic.  :-P

My experience is that educated guesses in this context are almost
always wrong (ie. the API won't be what you think it should be now).

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

Re: [RESEND][PATCH 1/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-29 01:47:13

Ok, I think I have everybodys changes in. I will split out the DTS into
a separate patch. The changelog is in this one.

Cheers,
  Sean

PIKA Warp: Update platform code to support Rev B boards.
* Switched from 64M NOR/64M NAND to 4M NOR/256M NAND.
* Full DTM support including critical temperature.
* Added POST information.
* Removed LED function, moved to new LED driver.
* Moved ad7414 to new style I2C initialization.

Signed-off-by: Sean MacLennan <redacted>
diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
index eb108a8..2178021 100644
--- a/arch/powerpc/boot/cuboot-warp.c
+++ b/arch/powerpc/boot/cuboot-warp.c
@@ -10,6 +10,7 @@
 #include "ops.h"
 #include "4xx.h"
 #include "cuboot.h"
+#include "stdio.h"
 
 #define TARGET_4xx
 #define TARGET_44x
@@ -17,14 +18,54 @@
 
 static bd_t bd;
 
-static void warp_fixups(void)
+static void warp_fixup_one_nor(u32 from, u32 to)
 {
-	unsigned long sysclk = 66000000;
+	void *devp;
+	char name[50];
+	u32 v[2];
+
+	sprintf(name, "/plb/opb/ebc/nor_flash@0,0/partition@%x", from);
+
+	devp = finddevice(name);
+	if (!devp)
+		return;
+
+	if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+		v[0] = to;
+		setprop(devp, "reg", v, sizeof(v));
+
+		printf("NOR 64M fixup %x -> %x\r\n", from, to);
+	}
+}
+
 
-	ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+static void warp_fixups(void)
+{
+	ibm440ep_fixup_clocks(66000000, 11059200, 50000000);
 	ibm4xx_sdram_fixup_memsize();
 	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
 	dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+
+	/* Fixup for 64M flash on Rev A boards. */
+	if (bd.bi_flashsize == 0x4000000) {
+		void *devp;
+		u32 v[3];
+
+		devp = finddevice("/plb/opb/ebc/nor_flash@0,0");
+		if (!devp)
+			return;
+
+		/* Fixup the size */
+		if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+			v[2] = bd.bi_flashsize;
+			setprop(devp, "reg", v, sizeof(v));
+		}
+
+		/* Fixup parition offsets */
+		warp_fixup_one_nor(0x300000, 0x3f00000);
+		warp_fixup_one_nor(0x340000, 0x3f40000);
+		warp_fixup_one_nor(0x380000, 0x3f80000);
+	}
 }
 
 
diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
index 9150318..d293c70 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,19 +79,15 @@ 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,
 };
 
@@ -96,6 +104,23 @@ 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 = 2;
+		}
+		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 39cf615..aa0f737 100644
--- a/arch/powerpc/platforms/44x/warp.c
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -12,6 +12,10 @@
 #include <linux/init.h>
 #include <linux/of_platform.h>
 #include <linux/kthread.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/pika.h>
+#include <linux/delay.h>
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
@@ -27,6 +31,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 +68,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 lenp;
+
+	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", &lenp);
+	of_node_put(np);
+	if (!gpios || lenp != 8) {
+		printk(KERN_ERR __FILE__
+		       ": Unable to get gpios property (%d)\n", lenp);
+		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 +302,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);

Re: [RESEND][PATCH 2/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-29 01:50:31

diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
index b04a52e..3e95e99 100644
--- a/arch/powerpc/boot/dts/warp.dts
+++ b/arch/powerpc/boot/dts/warp.dts
@@ -132,40 +132,33 @@
 
 				fpga@2,0 {
 					compatible = "pika,fpga";
-			   		reg = <2 0 2200>;
+			   		reg = <2 0 1000>;
 					interrupts = <18 8>;
 					interrupt-parent = <&UIC0>;
 				};
 
+				fpga@2,4000 {
+					compatible = "pika,fpga-sd";
+					reg = <2 4000 A00>;
+				};
+
 				nor_flash@0,0 {
-					compatible = "amd,s29gl512n", "cfi-flash";
+					compatible = "amd,s29gl032a", "cfi-flash";
 					bank-width = <2>;
-					reg = <0 0 4000000>;
+					reg = <0 0 400000>;
 					#address-cells = <1>;
 					#size-cells = <1>;
-					partition@0 {
-						label = "kernel";
-						reg = <0 180000>;
-					};
-					partition@180000 {
-						label = "root";
-						reg = <180000 3480000>;
-					};
-					partition@3600000 {
-						label = "user";
-						reg = <3600000 900000>;
-					};
-					partition@3f00000 {
+					partition@300000 {
 						label = "fpga";
-						reg = <3f00000 40000>;
+						reg = <300000 40000>;
 					};
-					partition@3f40000 {
+					partition@340000 {
 						label = "env";
-						reg = <3f40000 40000>;
+						reg = <340000 40000>;
 					};
-					partition@3f80000 {
+					partition@380000 {
 						label = "u-boot";
-						reg = <3f80000 80000>;
+						reg = <380000 80000>;
 					};
 				};
 			};
@@ -186,18 +179,45 @@
 				reg = <ef600700 14>;
 				interrupt-parent = <&UIC0>;
 				interrupts = <2 4>;
+				index = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				ad7414@4a {
+					compatible = "adi,ad7414";
+					reg = <4a>;
+					interrupts = <19 8>;
+					interrupt-parent = <&UIC0>;
+				};
 			};
 
 			GPIO0: gpio@ef600b00 {
 				compatible = "ibm,gpio-440ep";
 				reg = <ef600b00 48>;
+				#gpio-cells = <2>;
+				gpio-controller;
 			};
 
 			GPIO1: gpio@ef600c00 {
 				compatible = "ibm,gpio-440ep";
 				reg = <ef600c00 48>;
+				#gpio-cells = <2>;
+				gpio-controller;
+
+				led@31 {
+					compatible = "linux,gpio-led";
+					linux,name = ":green:";
+					gpios = <&GPIO1 31>;
+				};		
+	
+				led@30 {	
+					compatible = "linux,gpio-led";
+					linux,name = ":red:";
+					gpios = <&GPIO1 30>;
+				};
 			};
 
+
 			ZMII0: emac-zmii@ef600d00 {
 				compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii";
 				reg = <ef600d00 c>;

Re: [RESEND][PATCH 2/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Grant Likely <hidden>
Date: 2008-04-29 01:58:27

On Mon, Apr 28, 2008 at 7:50 PM, Sean MacLennan [off-list ref] wrote:
quoted hunk
diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
 index b04a52e..3e95e99 100644
You still need to have *some* kind of change log and a signed-off-by
line in this patch.  :-)

There is one minor change that needs to be added below; otherwise:

Acked-by: Grant Likely <redacted>

(You can add my acked-by line to the next version of this patch if
you're only changing the thing I comment on).

Josh, when he respins it I think the dts changes are ready to be picked up.
 @@ -186,18 +179,45 @@
                        GPIO1: gpio@ef600c00 {
                                compatible = "ibm,gpio-440ep";
                                reg = <ef600c00 48>;
 +                               #gpio-cells = <2>;
 +                               gpio-controller;
 +
 +                               led@31 {

+                                       compatible = "linux,gpio-led";
 +                                       linux,name = ":green:";
 +                                       gpios = <&GPIO1 31>;
Since #gpio-cells is '2'; the gpios property needs to reflect that.
It should be:

gpios = <&GPIO1 31 0>;

The second cell the GPIO controller would use for flags (inverted,
open-drain, etc).
 +                               };
 +
 +                               led@30 {
 +                                       compatible = "linux,gpio-led";
 +                                       linux,name = ":red:";
 +                                       gpios = <&GPIO1 30>;
ditto
 +                               };


                        };
Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

Re: [RESEND][PATCH 2/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-29 03:27:48

PIKA Warp: Update DTS to support Rev B boards.
* Switched from 64M NOR/64M NAND to 4M NOR/256M NAND.
* Added led entries.
* Added fpga-sd entry.
* Added ad7414 entry.

Signed-off-by: Sean MacLennan <redacted>
Acked-by: Grant Likely <redacted>
diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts
index b04a52e..c086501 100644
--- a/arch/powerpc/boot/dts/warp.dts
+++ b/arch/powerpc/boot/dts/warp.dts
@@ -132,40 +132,33 @@
 
 				fpga@2,0 {
 					compatible = "pika,fpga";
-			   		reg = <2 0 2200>;
+			   		reg = <2 0 1000>;
 					interrupts = <18 8>;
 					interrupt-parent = <&UIC0>;
 				};
 
+				fpga@2,4000 {
+					compatible = "pika,fpga-sd";
+					reg = <2 4000 A00>;
+				};
+
 				nor_flash@0,0 {
-					compatible = "amd,s29gl512n", "cfi-flash";
+					compatible = "amd,s29gl032a", "cfi-flash";
 					bank-width = <2>;
-					reg = <0 0 4000000>;
+					reg = <0 0 400000>;
 					#address-cells = <1>;
 					#size-cells = <1>;
-					partition@0 {
-						label = "kernel";
-						reg = <0 180000>;
-					};
-					partition@180000 {
-						label = "root";
-						reg = <180000 3480000>;
-					};
-					partition@3600000 {
-						label = "user";
-						reg = <3600000 900000>;
-					};
-					partition@3f00000 {
+					partition@300000 {
 						label = "fpga";
-						reg = <3f00000 40000>;
+						reg = <300000 40000>;
 					};
-					partition@3f40000 {
+					partition@340000 {
 						label = "env";
-						reg = <3f40000 40000>;
+						reg = <340000 40000>;
 					};
-					partition@3f80000 {
+					partition@380000 {
 						label = "u-boot";
-						reg = <3f80000 80000>;
+						reg = <380000 80000>;
 					};
 				};
 			};
@@ -186,18 +179,45 @@
 				reg = <ef600700 14>;
 				interrupt-parent = <&UIC0>;
 				interrupts = <2 4>;
+				index = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				ad7414@4a {
+					compatible = "adi,ad7414";
+					reg = <4a>;
+					interrupts = <19 8>;
+					interrupt-parent = <&UIC0>;
+				};
 			};
 
 			GPIO0: gpio@ef600b00 {
 				compatible = "ibm,gpio-440ep";
 				reg = <ef600b00 48>;
+				#gpio-cells = <2>;
+				gpio-controller;
 			};
 
 			GPIO1: gpio@ef600c00 {
 				compatible = "ibm,gpio-440ep";
 				reg = <ef600c00 48>;
+				#gpio-cells = <2>;
+				gpio-controller;
+
+				led@31 {
+					compatible = "linux,gpio-led";
+					linux,name = ":green:";
+					gpios = <&GPIO1 31 0>;
+				};		
+	
+				led@30 {	
+					compatible = "linux,gpio-led";
+					linux,name = ":red:";
+					gpios = <&GPIO1 30 0>;
+				};
 			};
 
+
 			ZMII0: emac-zmii@ef600d00 {
 				compatible = "ibm,zmii-440ep", "ibm,zmii-440gp", "ibm,zmii";
 				reg = <ef600d00 c>;

Re: [RESEND][PATCH 1/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-29 03:28:57

A change to the dts to get gpios correct broke the led code.

PIKA Warp: Update platform code to support Rev B boards.
* Switched from 64M NOR/64M NAND to 4M NOR/256M NAND.
* Full DTM support including critical temperature.
* Added POST information.
* Removed LED function, moved to new LED driver.
* Moved ad7414 to new style I2C initialization.

Signed-off-by: Sean MacLennan <redacted>
diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c
index eb108a8..2178021 100644
--- a/arch/powerpc/boot/cuboot-warp.c
+++ b/arch/powerpc/boot/cuboot-warp.c
@@ -10,6 +10,7 @@
 #include "ops.h"
 #include "4xx.h"
 #include "cuboot.h"
+#include "stdio.h"
 
 #define TARGET_4xx
 #define TARGET_44x
@@ -17,14 +18,54 @@
 
 static bd_t bd;
 
-static void warp_fixups(void)
+static void warp_fixup_one_nor(u32 from, u32 to)
 {
-	unsigned long sysclk = 66000000;
+	void *devp;
+	char name[50];
+	u32 v[2];
+
+	sprintf(name, "/plb/opb/ebc/nor_flash@0,0/partition@%x", from);
+
+	devp = finddevice(name);
+	if (!devp)
+		return;
+
+	if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+		v[0] = to;
+		setprop(devp, "reg", v, sizeof(v));
+
+		printf("NOR 64M fixup %x -> %x\r\n", from, to);
+	}
+}
+
 
-	ibm440ep_fixup_clocks(sysclk, 11059200, 50000000);
+static void warp_fixups(void)
+{
+	ibm440ep_fixup_clocks(66000000, 11059200, 50000000);
 	ibm4xx_sdram_fixup_memsize();
 	ibm4xx_fixup_ebc_ranges("/plb/opb/ebc");
 	dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr);
+
+	/* Fixup for 64M flash on Rev A boards. */
+	if (bd.bi_flashsize == 0x4000000) {
+		void *devp;
+		u32 v[3];
+
+		devp = finddevice("/plb/opb/ebc/nor_flash@0,0");
+		if (!devp)
+			return;
+
+		/* Fixup the size */
+		if (getprop(devp, "reg", v, sizeof(v)) == sizeof(v)) {
+			v[2] = bd.bi_flashsize;
+			setprop(devp, "reg", v, sizeof(v));
+		}
+
+		/* Fixup parition offsets */
+		warp_fixup_one_nor(0x300000, 0x3f00000);
+		warp_fixup_one_nor(0x340000, 0x3f40000);
+		warp_fixup_one_nor(0x380000, 0x3f80000);
+	}
 }
 
 
diff --git a/arch/powerpc/platforms/44x/warp-nand.c b/arch/powerpc/platforms/44x/warp-nand.c
index 9150318..d293c70 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,19 +79,15 @@ 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,
 };
 
@@ -96,6 +104,23 @@ 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 = 2;
+		}
+		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 39cf615..318f859 100644
--- a/arch/powerpc/platforms/44x/warp.c
+++ b/arch/powerpc/platforms/44x/warp.c
@@ -12,6 +12,10 @@
 #include <linux/init.h>
 #include <linux/of_platform.h>
 #include <linux/kthread.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/pika.h>
+#include <linux/delay.h>
 
 #include <asm/machdep.h>
 #include <asm/prom.h>
@@ -27,6 +31,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 +68,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 +302,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);

Re: [RESEND][PATCH 1/2][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Paul Mackerras <hidden>
Date: 2008-04-29 05:08:29

It doesn't help that both of these patches have the same subject line,
nor that it starts with "Re:". :(

Also, I find the statement "A change to the dts to get gpios correct
broke the led code" a bit opaque.  It doesn't tell me in what way it
was broken or what this patch does to correct, or even what the change
was in enough detail that I could find the change in the git
repository.

Paul.

Re: [RESEND][PATCH 1/2][POWERPC] PIKA Warp: Update platform code tosupportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-04-29 05:42:10

On Tue, 29 Apr 2008 15:08:29 +1000
"Paul Mackerras" [off-list ref] wrote:
It doesn't help that both of these patches have the same subject line,
nor that it starts with "Re:". :(
Sorry about that. I just split up the two patches, but the same subject
does apply to both. The code currently in the mainline kernel is for a
Rev A. Since there are no Rev As outside of PIKA, that is not very
useful. These patches bring the platform code up to Rev B standards
(while still maintaining Rev A support).

So the subject is correct for both.
Also, I find the statement "A change to the dts to get gpios correct
broke the led code" a bit opaque.  It doesn't tell me in what way it
was broken or what this patch does to correct, or even what the change
was in enough detail that I could find the change in the git
repository.
You won't find it. One of the problems is that I am basically adding
patches to patches to patches, but since none of them are in a
mainline git, they all just keep showing up as one big patch. 

That comment was meant as a quick note to explain why the platform patch
changed from the previous platform patch. Short of diffing the
patches, you can't easily see how they changed.

After the Warp is released (sometime in May), the hardware churn should
end and I can submit patches one at a time rather than one massive
patch.

Cheers,
   Sean

Re: [RESEND][PATCH][POWERPC] PIKA Warp: Update platform code to supportRev B boards

From: Josh Boyer <hidden>
Date: 2008-04-30 00:54:44

On Mon, 28 Apr 2008 18:07:17 -0400
Sean MacLennan [off-list ref] wrote:
On Mon, 28 Apr 2008 16:54:24 -0500
Scott Wood [off-list ref] wrote:
quoted
Why can't the existing partition binding be used with NAND?  It's
what we do with Freescale FCM NAND.
I guess I could put the partitions in the dts. But I would have to
read them and dynamically create an array to pass to the ndfc driver.

It seems simpler to just statically initialize the array. Once the ndfc
is modified to use the dts, I will switch to that method.
Right.  It's a limitation of NDFC, which isn't WARP specific and needs
fixing in general.

josh

Re: [RESEND][PATCH 1/2][POWERPC] PIKA Warp: Update platform code tosupportRev B boards

From: Sean MacLennan <hidden>
Date: 2008-05-06 15:27:37

Opps, there is a bug in this patch. The file pika.h is not included. I
have attached it below, but a simpler solution might be to just delete
it from this file. It is not required to build the kernel.

The file currently contains the exported dtm functions. These functions
are only used by the telephony driver, which is not in the mainline
kernel.

Cheers,
   Sean

Signed-off-by: Sean MacLennan <redacted>
diff --git a/include/linux/pika.h b/include/linux/pika.h
new file mode 100644
index 0000000..83d51df
--- /dev/null
+++ b/include/linux/pika.h
@@ -0,0 +1,18 @@
+/*
+ * PIKA exported functions
+ *
+ * Copyright (c) 2008 PIKA Technologies
+ *   Sean MacLennan <smaclennan@pikatech.com>
+ */
+
+#ifndef _LINUX_PIKA_H
+#define _LINUX_PIKA_H
+
+#ifdef __KERNEL__
+
+int pika_dtm_register_shutdown(void (*func)(void *arg), void *arg);
+int pika_dtm_unregister_shutdown(void (*func)(void *arg), void *arg);
+
+#endif
+
+#endif
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help