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>
@@ -67,19 +79,15 @@ static struct platform_device warp_ndfc_device = {.resource=&warp_ndfc,};-staticstructnand_ecclayoutnand_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+*64Mand256Mflashchips.+*/staticstructplatform_nand_chipwarp_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 = {staticintwarp_setup_nand_flash(void){+structdevice_node*np;++/* Try to detect a rev A based on NOR size. */+np=of_find_compatible_node(NULL,NULL,"cfi-flash");+if(np){+structproperty*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);
@@ -27,6 +30,18 @@ static __initdata struct of_device_id warp_of_bus[] = {{},};+static__initdatastructi2c_board_infowarp_i2c_info[]={+{I2C_BOARD_INFO("ad7414",0x4a)}+};++staticint__initwarp_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));+return0;+}+machine_arch_initcall(warp,warp_arch_init);+staticint__initwarp_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... */+staticint__initwarp_post_info(void)+{+structdevice_node*np;+void__iomem*fpga;+u32post1,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");++return0;+}+machine_late_initcall(warp,warp_post_info);+++#ifdef CONFIG_SENSORS_AD7414++staticLIST_HEAD(dtm_shutdown_list);+staticvoid__iomem*dtm_fpga;++structdtm_shutdown{+structlist_headlist;+void(*func)(void*arg);+void*arg;+};+++intdtm_register_shutdown(void(*func)(void*arg),void*arg)+{+structdtm_shutdown*shutdown;++shutdown=kmalloc(sizeof(structdtm_shutdown),GFP_KERNEL);+if(shutdown==NULL)+return-ENOMEM;++shutdown->func=func;+shutdown->arg=arg;+list_add(&shutdown->list,&dtm_shutdown_list);++return0;+}+EXPORT_SYMBOL(dtm_register_shutdown);-/* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */-voidwarp_set_power_leds(intgreen,intred)+intdtm_unregister_shutdown(void(*func)(void*arg),void*arg){-staticvoid__iomem*gpio_base=NULL;-unsignedleds;--if(gpio_base==NULL){-structdevice_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;-}+structdtm_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);+return0;}++return-EINVAL;+}+EXPORT_SYMBOL(dtm_unregister_shutdown);++staticlongwdt_keepalive(longtime)+{+if(dtm_fpga){+unsignedreset=in_be32(dtm_fpga+0x14);+out_be32(dtm_fpga+0x14,reset);}-leds=in_be32(gpio_base);+return0;+}++staticirqreturn_ttemp_isr(intirq,void*context)+{+structdtm_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");+returnIRQ_HANDLED;+}++staticvoidpika_setup_critical_temp(structi2c_client*client)+{+structdevice_node*np;+intirq,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){-case0:leds&=~LED_GREEN;break;-case1: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){-case0:leds&=~LED_RED;break;-case1: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);+staticinlinevoidpika_dtm_check_fan(void__iomem*fpga)+{+staticintfan_state;+u32fan=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_AD7414staticintpika_dtm_thread(void__iomem*fpga){-externintad7414_get_temp(intindex);+structi2c_adapter*adap;+structi2c_client*client;++/* We loop in case either driver was compiled as a module and+*hasnotbeeninsmodedyet.+*/+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)+gotofound_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()){-inttemp=ad7414_get_temp(0);+u16temp=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)return0;}+staticint__initpika_dtm_start(void){structtask_struct*dtm_thread;structdevice_node*np;-structresourceres;-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-*fpgaspace,whichisover8k.-*/-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);returnPTR_ERR(dtm_thread);}return0;}-device_initcall(pika_dtm_start);+machine_late_initcall(warp,pika_dtm_start);#endif
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>
@@ -67,19 +79,15 @@ static struct platform_device warp_ndfc_device = {.resource=&warp_ndfc,};-staticstructnand_ecclayoutnand_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+*64Mand256Mflashchips.+*/staticstructplatform_nand_chipwarp_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 = {staticintwarp_setup_nand_flash(void){+structdevice_node*np;++/* Try to detect a rev A based on NOR size. */+np=of_find_compatible_node(NULL,NULL,"cfi-flash");+if(np){+structproperty*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);
@@ -27,6 +31,18 @@ static __initdata struct of_device_id warp_of_bus[] = {{},};+static__initdatastructi2c_board_infowarp_i2c_info[]={+{I2C_BOARD_INFO("ad7414",0x4a)}+};++staticint__initwarp_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));+return0;+}+machine_arch_initcall(warp,warp_arch_init);+staticint__initwarp_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... */+staticint__initwarp_post_info(void)+{+structdevice_node*np;+void__iomem*fpga;+u32post1,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");++return0;+}+machine_late_initcall(warp,warp_post_info);+++#ifdef CONFIG_SENSORS_AD7414+staticLIST_HEAD(dtm_shutdown_list);+staticvoid__iomem*dtm_fpga;+staticvoid__iomem*gpio_base;-/* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */-voidwarp_set_power_leds(intgreen,intred)++structdtm_shutdown{+structlist_headlist;+void(*func)(void*arg);+void*arg;+};+++intdtm_register_shutdown(void(*func)(void*arg),void*arg)+{+structdtm_shutdown*shutdown;++shutdown=kmalloc(sizeof(structdtm_shutdown),GFP_KERNEL);+if(shutdown==NULL)+return-ENOMEM;++shutdown->func=func;+shutdown->arg=arg;++list_add(&shutdown->list,&dtm_shutdown_list);++return0;+}++intdtm_unregister_shutdown(void(*func)(void*arg),void*arg){-staticvoid__iomem*gpio_base=NULL;-unsignedleds;--if(gpio_base==NULL){-structdevice_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;+structdtm_shutdown*shutdown;++list_for_each_entry(shutdown,&dtm_shutdown_list,list)+if(shutdown->func==func&&shutdown->arg==arg){+list_del(&shutdown->list);+kfree(shutdown);+return0;+}++return-EINVAL;+}++staticirqreturn_ttemp_isr(intirq,void*context)+{+structdtm_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){+unsignedreset=in_be32(dtm_fpga+0x14);+out_be32(dtm_fpga+0x14,reset);+}++if(gpio_base){+unsignedleds=in_be32(gpio_base);++/* green off, red toggle */+leds&=~0x80000000;+leds^=0x40000000;++out_be32(gpio_base,leds);}+mdelay(500);+}+}++staticvoidpika_setup_critical_temp(structi2c_client*client)+{+structdevice_node*np;+intirq,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){-case0:leds&=~LED_GREEN;break;-case1: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){-case0:leds&=~LED_RED;break;-case1: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);+staticinlinevoidpika_dtm_check_fan(void__iomem*fpga)+{+staticintfan_state;+u32fan=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_AD7414staticintpika_dtm_thread(void__iomem*fpga){-externintad7414_get_temp(intindex);+structi2c_adapter*adap;+structi2c_client*client;++/* We loop in case either driver was compiled as a module and+*hasnotbeeninsmodedyet.+*/+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)+gotofound_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()){-inttemp=ad7414_get_temp(0);+u16temp=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)return0;}+staticint__initpika_dtm_start(void){structtask_struct*dtm_thread;structdevice_node*np;-structresourceres;-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-*fpgaspace,whichisover8k.-*/-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);returnPTR_ERR(dtm_thread);}return0;}-device_initcall(pika_dtm_start);+machine_late_initcall(warp,pika_dtm_start);++#else /* !CONFIG_SENSORS_AD7414 */++intdtm_register_shutdown(void(*func)(void*arg),void*arg)+{+return0;+}++intdtm_unregister_shutdown(void(*func)(void*arg),void*arg)+{+return0;+}+#endif++EXPORT_SYMBOL(dtm_register_shutdown);+EXPORT_SYMBOL(dtm_unregister_shutdown);
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.
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
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.
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
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.
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
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>
@@ -67,19 +79,15 @@ static struct platform_device warp_ndfc_device = {.resource=&warp_ndfc,};-staticstructnand_ecclayoutnand_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+*64Mand256Mflashchips.+*/staticstructplatform_nand_chipwarp_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 = {staticintwarp_setup_nand_flash(void){+structdevice_node*np;++/* Try to detect a rev A based on NOR size. */+np=of_find_compatible_node(NULL,NULL,"cfi-flash");+if(np){+structproperty*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);
@@ -27,6 +31,18 @@ static __initdata struct of_device_id warp_of_bus[] = {{},};+static__initdatastructi2c_board_infowarp_i2c_info[]={+{I2C_BOARD_INFO("ad7414",0x4a)}+};++staticint__initwarp_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));+return0;+}+machine_arch_initcall(warp,warp_arch_init);+staticint__initwarp_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... */+staticint__initwarp_post_info(void)+{+structdevice_node*np;+void__iomem*fpga;+u32post1,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");++return0;+}+machine_late_initcall(warp,warp_post_info);+++#ifdef CONFIG_SENSORS_AD7414++staticLIST_HEAD(dtm_shutdown_list);+staticvoid__iomem*dtm_fpga;+staticvoid__iomem*gpio_base;+++structdtm_shutdown{+structlist_headlist;+void(*func)(void*arg);+void*arg;+};-/* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */-voidwarp_set_power_leds(intgreen,intred)+intdtm_register_shutdown(void(*func)(void*arg),void*arg){-staticvoid__iomem*gpio_base=NULL;-unsignedleds;--if(gpio_base==NULL){-structdevice_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;+structdtm_shutdown*shutdown;++shutdown=kmalloc(sizeof(structdtm_shutdown),GFP_KERNEL);+if(shutdown==NULL)+return-ENOMEM;++shutdown->func=func;+shutdown->arg=arg;++list_add(&shutdown->list,&dtm_shutdown_list);++return0;+}++intdtm_unregister_shutdown(void(*func)(void*arg),void*arg)+{+structdtm_shutdown*shutdown;++list_for_each_entry(shutdown,&dtm_shutdown_list,list)+if(shutdown->func==func&&shutdown->arg==arg){+list_del(&shutdown->list);+kfree(shutdown);+return0;+}++return-EINVAL;+}++staticirqreturn_ttemp_isr(intirq,void*context)+{+structdtm_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){+unsignedreset=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){+unsignedleds=in_be32(gpio_base);++/* green off, red toggle */+leds&=~0x80000000;+leds^=0x40000000;++out_be32(gpio_base,leds);}++mdelay(500);+}+}++staticintpika_setup_leds(void)+{+structdevice_node*np;+constu32*gpios;+intlenp;++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){-case0:leds&=~LED_GREEN;break;-case1: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){-case0:leds&=~LED_RED;break;-case1: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);+return0;}-EXPORT_SYMBOL(warp_set_power_leds);+staticvoidpika_setup_critical_temp(structi2c_client*client)+{+structdevice_node*np;+intirq,rc;++/* Do this before enabling critical temp interrupt since we+*mayimmediatelyinterrupt.+*/+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;+}+}++staticinlinevoidpika_dtm_check_fan(void__iomem*fpga)+{+staticintfan_state;+u32fan=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_AD7414staticintpika_dtm_thread(void__iomem*fpga){-externintad7414_get_temp(intindex);+structi2c_adapter*adap;+structi2c_client*client;++/* We loop in case either driver was compiled as a module and+*hasnotbeeninsmodedyet.+*/+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)+gotofound_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()){-inttemp=ad7414_get_temp(0);+u16temp=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)return0;}+staticint__initpika_dtm_start(void){structtask_struct*dtm_thread;structdevice_node*np;-structresourceres;-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-*fpgaspace,whichisover8k.-*/-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);returnPTR_ERR(dtm_thread);}return0;}-device_initcall(pika_dtm_start);+machine_late_initcall(warp,pika_dtm_start);++#else /* !CONFIG_SENSORS_AD7414 */++intdtm_register_shutdown(void(*func)(void*arg),void*arg)+{+return0;+}++intdtm_unregister_shutdown(void(*func)(void*arg),void*arg)+{+return0;+}+#endif++EXPORT_SYMBOL(dtm_register_shutdown);+EXPORT_SYMBOL(dtm_unregister_shutdown);
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
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.
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.
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
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.
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".
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
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
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
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
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.
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>
@@ -67,19 +79,15 @@ static struct platform_device warp_ndfc_device = {.resource=&warp_ndfc,};-staticstructnand_ecclayoutnand_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+*64Mand256Mflashchips.+*/staticstructplatform_nand_chipwarp_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 = {staticintwarp_setup_nand_flash(void){+structdevice_node*np;++/* Try to detect a rev A based on NOR size. */+np=of_find_compatible_node(NULL,NULL,"cfi-flash");+if(np){+structproperty*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);
@@ -27,6 +31,18 @@ static __initdata struct of_device_id warp_of_bus[] = {{},};+static__initdatastructi2c_board_infowarp_i2c_info[]={+{I2C_BOARD_INFO("ad7414",0x4a)}+};++staticint__initwarp_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));+return0;+}+machine_arch_initcall(warp,warp_arch_init);+staticint__initwarp_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... */+staticint__initwarp_post_info(void)+{+structdevice_node*np;+void__iomem*fpga;+u32post1,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");++return0;+}+machine_late_initcall(warp,warp_post_info);+++#ifdef CONFIG_SENSORS_AD7414++staticLIST_HEAD(dtm_shutdown_list);+staticvoid__iomem*dtm_fpga;+staticvoid__iomem*gpio_base;+++structdtm_shutdown{+structlist_headlist;+void(*func)(void*arg);+void*arg;+};-/* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */-voidwarp_set_power_leds(intgreen,intred)+intpika_dtm_register_shutdown(void(*func)(void*arg),void*arg){-staticvoid__iomem*gpio_base=NULL;-unsignedleds;--if(gpio_base==NULL){-structdevice_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;+structdtm_shutdown*shutdown;++shutdown=kmalloc(sizeof(structdtm_shutdown),GFP_KERNEL);+if(shutdown==NULL)+return-ENOMEM;++shutdown->func=func;+shutdown->arg=arg;++list_add(&shutdown->list,&dtm_shutdown_list);++return0;+}++intpika_dtm_unregister_shutdown(void(*func)(void*arg),void*arg)+{+structdtm_shutdown*shutdown;++list_for_each_entry(shutdown,&dtm_shutdown_list,list)+if(shutdown->func==func&&shutdown->arg==arg){+list_del(&shutdown->list);+kfree(shutdown);+return0;+}++return-EINVAL;+}++staticirqreturn_ttemp_isr(intirq,void*context)+{+structdtm_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){+unsignedreset=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){+unsignedleds=in_be32(gpio_base);++/* green off, red toggle */+leds&=~0x80000000;+leds^=0x40000000;++out_be32(gpio_base,leds);}++mdelay(500);+}+}++staticintpika_setup_leds(void)+{+structdevice_node*np;+constu32*gpios;+intlenp;++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){-case0:leds&=~LED_GREEN;break;-case1: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){-case0:leds&=~LED_RED;break;-case1: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);+return0;}-EXPORT_SYMBOL(warp_set_power_leds);+staticvoidpika_setup_critical_temp(structi2c_client*client)+{+structdevice_node*np;+intirq,rc;++/* Do this before enabling critical temp interrupt since we+*mayimmediatelyinterrupt.+*/+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;+}+}++staticinlinevoidpika_dtm_check_fan(void__iomem*fpga)+{+staticintfan_state;+u32fan=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_AD7414staticintpika_dtm_thread(void__iomem*fpga){-externintad7414_get_temp(intindex);+structi2c_adapter*adap;+structi2c_client*client;++/* We loop in case either driver was compiled as a module and+*hasnotbeeninsmodedyet.+*/+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)+gotofound_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()){-inttemp=ad7414_get_temp(0);+u16temp=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)return0;}+staticint__initpika_dtm_start(void){structtask_struct*dtm_thread;structdevice_node*np;-structresourceres;-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-*fpgaspace,whichisover8k.-*/-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);returnPTR_ERR(dtm_thread);}return0;}-device_initcall(pika_dtm_start);+machine_late_initcall(warp,pika_dtm_start);++#else /* !CONFIG_SENSORS_AD7414 */++intpika_dtm_register_shutdown(void(*func)(void*arg),void*arg)+{+return0;+}++intpika_dtm_unregister_shutdown(void(*func)(void*arg),void*arg)+{+return0;+}+#endif++EXPORT_SYMBOL(pika_dtm_register_shutdown);+EXPORT_SYMBOL(pika_dtm_unregister_shutdown);
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.
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).
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>
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>
@@ -67,19 +79,15 @@ static struct platform_device warp_ndfc_device = {.resource=&warp_ndfc,};-staticstructnand_ecclayoutnand_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+*64Mand256Mflashchips.+*/staticstructplatform_nand_chipwarp_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 = {staticintwarp_setup_nand_flash(void){+structdevice_node*np;++/* Try to detect a rev A based on NOR size. */+np=of_find_compatible_node(NULL,NULL,"cfi-flash");+if(np){+structproperty*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);
@@ -27,6 +31,18 @@ static __initdata struct of_device_id warp_of_bus[] = {{},};+static__initdatastructi2c_board_infowarp_i2c_info[]={+{I2C_BOARD_INFO("ad7414",0x4a)}+};++staticint__initwarp_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));+return0;+}+machine_arch_initcall(warp,warp_arch_init);+staticint__initwarp_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... */+staticint__initwarp_post_info(void)+{+structdevice_node*np;+void__iomem*fpga;+u32post1,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");++return0;+}+machine_late_initcall(warp,warp_post_info);+++#ifdef CONFIG_SENSORS_AD7414++staticLIST_HEAD(dtm_shutdown_list);+staticvoid__iomem*dtm_fpga;+staticvoid__iomem*gpio_base;+++structdtm_shutdown{+structlist_headlist;+void(*func)(void*arg);+void*arg;+};-/* This is for the power LEDs 1 = on, 0 = off, -1 = leave alone */-voidwarp_set_power_leds(intgreen,intred)+intpika_dtm_register_shutdown(void(*func)(void*arg),void*arg){-staticvoid__iomem*gpio_base=NULL;-unsignedleds;--if(gpio_base==NULL){-structdevice_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;+structdtm_shutdown*shutdown;++shutdown=kmalloc(sizeof(structdtm_shutdown),GFP_KERNEL);+if(shutdown==NULL)+return-ENOMEM;++shutdown->func=func;+shutdown->arg=arg;++list_add(&shutdown->list,&dtm_shutdown_list);++return0;+}++intpika_dtm_unregister_shutdown(void(*func)(void*arg),void*arg)+{+structdtm_shutdown*shutdown;++list_for_each_entry(shutdown,&dtm_shutdown_list,list)+if(shutdown->func==func&&shutdown->arg==arg){+list_del(&shutdown->list);+kfree(shutdown);+return0;+}++return-EINVAL;+}++staticirqreturn_ttemp_isr(intirq,void*context)+{+structdtm_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){+unsignedreset=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){+unsignedleds=in_be32(gpio_base);++/* green off, red toggle */+leds&=~0x80000000;+leds^=0x40000000;++out_be32(gpio_base,leds);}++mdelay(500);+}+}++staticintpika_setup_leds(void)+{+structdevice_node*np;+constu32*gpios;+intlen;++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){-case0:leds&=~LED_GREEN;break;-case1: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){-case0:leds&=~LED_RED;break;-case1: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);+return0;}-EXPORT_SYMBOL(warp_set_power_leds);+staticvoidpika_setup_critical_temp(structi2c_client*client)+{+structdevice_node*np;+intirq,rc;++/* Do this before enabling critical temp interrupt since we+*mayimmediatelyinterrupt.+*/+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;+}+}++staticinlinevoidpika_dtm_check_fan(void__iomem*fpga)+{+staticintfan_state;+u32fan=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_AD7414staticintpika_dtm_thread(void__iomem*fpga){-externintad7414_get_temp(intindex);+structi2c_adapter*adap;+structi2c_client*client;++/* We loop in case either driver was compiled as a module and+*hasnotbeeninsmodedyet.+*/+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)+gotofound_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()){-inttemp=ad7414_get_temp(0);+u16temp=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)return0;}+staticint__initpika_dtm_start(void){structtask_struct*dtm_thread;structdevice_node*np;-structresourceres;-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-*fpgaspace,whichisover8k.-*/-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);returnPTR_ERR(dtm_thread);}return0;}-device_initcall(pika_dtm_start);+machine_late_initcall(warp,pika_dtm_start);++#else /* !CONFIG_SENSORS_AD7414 */++intpika_dtm_register_shutdown(void(*func)(void*arg),void*arg)+{+return0;+}++intpika_dtm_unregister_shutdown(void(*func)(void*arg),void*arg)+{+return0;+}+#endif++EXPORT_SYMBOL(pika_dtm_register_shutdown);+EXPORT_SYMBOL(pika_dtm_unregister_shutdown);
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.
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
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
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>