• Home
  • Help
  • Search
  • Login
  • Register
Pages: [1]
Author Topic: generic GPIO support: success! dallas 1-wire working with parasite power  (Read 9285 times)
tmk
Newbie
*

Karma: 1
Posts: 40


View Profile
« on: April 25, 2009, 10:59:42 PM »

After quite a few days of hacking at the kernel and trying to debug my 1-wire bus, i am pleased to report success!

I have a working 1-wire bus using the GPIO pins on the plug (disabling SDIO gives you GPIO)

see this thread for lots of pictures and details on how i wired it all up. http://openplug.org/plugforum/index.php?topic=104.msg647#msg647

Now that it's all working, i can read my 2 temp sensors on the shared bus:
Code:
root@charger:~# cat /sys/bus/w1/devices/28-000001c76810/w1_slave
a7 01 4b 46 7f ff 09 10 e0 : crc=e0 YES
a7 01 4b 46 7f ff 09 10 e0 t=26437
root@charger:~# cat /sys/bus/w1/devices/28-000001c77bdc/w1_slave
a3 01 4b 46 7f ff 0d 10 ce : crc=ce YES
a3 01 4b 46 7f ff 0d 10 ce t=26187

as you can see, it's ~26 C in here Smiley


Here's all the details:
I decided to use the 2.6.30-rc2 kernel, as it has support for the GPIO kirkwood stuff built-in, and i needed to do less hacking.

I also got a kernel driver from the openwrt package (who got it from somewhere else i think) which allows you to specify which GPIO pin to use for 1-wire at module load-time (or kernel config option, if compiled in)

get it here: https://dev.openwrt.org/browser/branches/8.09/package/w1-gpio-custom/src/w1-gpio-custom.c

I had to apply the following patch to it to get it to load.
Code:
--- w1-gpio-custom.c 2008-04-29 11:31:43.000000000 -0700
+++ tmk-w1-gpio-custom.c 2009-04-25 22:09:46.112712798 -07
@@ -119,7 +119,7 @@
  if (err)
  goto err;
 
- err = platform_device_register(pdev);
+ err = platform_device_add(pdev);
  if (err)
  goto err;

Note: it segfaults if you unload/reload and use the same bus#. I haven't tracked that down yet, but i think it's calling the wrong function as part of the _cleanup process.

4 bus #s are supported by default, so you basically get 4 loads/unloads before you need to reboot. eg

Code:
This works:
## try 1, pin 13
modprobe w1-gpio-custom bus0=0,13,0
rmmod w1-gpio-custom
## try 2, still pin 13
modprobe w1-gpio-custom bus1=1,13,0

Also, in order for this module to work, you have to add the GPIO pins to the available pool. Not sure if this breaks SDIO or not.
arch/arm/mach-kirkwood/sheevaplug-setup.c:
Code:
--- sheevaplug-setup.c 2009-04-14 13:51:48.000000000 -0700
+++ tmk-sheevaplug-setup.c 2009-04-25 22:43:55.187247857 -0700
@@ -97,6 +97,12 @@
 };
 
 static unsigned int sheevaplug_mpp_config[] __initdata = {
+ MPP12_GPO, /* shared with sdio - output only*/
+ MPP13_GPIO, /* shared with sdio */
+ MPP14_GPIO, /* shared with sdio */
+ MPP15_GPIO, /* shared with sdio */
+ MPP16_GPIO, /* shared with sdio */
+ MPP17_GPIO, /* shared with sdio */
  MPP29_GPIO, /* USB Power Enable */
  MPP49_GPIO, /* LED */
  0

That's it for the base stuff. Not too bad. However, i had to make some tweaks to the w1 drivers in the kernel to support the ds18B20 temperature probe (and anything else that needs 'strong pullup' support). The probe needs 'parasite power', which wasn't supported in the default kernel. Again, the following aren't needed unless you have things that need a 'strong pullup' on the 1-wire bus.

a bunch of files need patching for this:

drivers/w1/w1_int.c
Code:
--- w1_int.c 2009-04-14 13:51:48.000000000 -0700
+++ tmk-w1_int.c 2009-04-25 21:44:58.503236242 -0700
@@ -118,12 +118,14 @@
  * pullup.  w1_io.c would need to support calling set_pullup before
  * the last write_bit operation of a w1_write_8 which it currently
  * doesn't.
- */
+ *
+ * added it, commenting this bit out -tmk
  if (!master->write_byte && !master->touch_bit && master->set_pullup) {
  printk(KERN_ERR "w1_add_master_device: set_pullup requires "
  "write_byte or touch_bit, disabling\n");
  master->set_pullup = NULL;
  }
+ */
 
  /* Lock until the device is added (or not) to w1_masters. */
  mutex_lock(&w1_mlock);

drivers/w1/w1_io.c: this one's a hack to fix the timing, and will break the one other driver that uses the set_pullup stuff. It should really go somewhere else, but i didn't want to deal with the kernel infrastructure of adding a new function type. This is what the long comment on the above patch is trying to point out.
Code:
--- w1_io.c 2009-04-14 13:51:48.000000000 -0700
+++ tmk-w1_io.c 2009-04-25 22:33:59.919237033 -0700
@@ -142,9 +142,9 @@
  }
  else
  for (i = 0; i < 8; ++i) {
+ w1_touch_bit(dev, (byte >> i) & 0x1);
  if (i == 7)
  w1_pre_write(dev);
- w1_touch_bit(dev, (byte >> i) & 0x1);
  }
  w1_post_write(dev);
 }

drivers/w1/masters/w1-gpio.c: Had to add support for the strong pullup function
Code:
--- w1-gpio.c 2009-04-14 13:51:48.000000000 -0700
+++ tmk-w1-gpio.c 2009-04-25 22:38:00.571236272 -0700
@@ -12,12 +12,34 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/w1-gpio.h>
+#include <linux/delay.h>
 
 #include "../w1.h"
 #include "../w1_int.h"
 
 #include <asm/gpio.h>
 
+
+static int w1_gpio_set_pullup(struct platform_device *data, int delay)
+{
+ struct w1_gpio_platform_data *pdata = data;
+        if (delay == 0)
+ {
+ /* sleep */
+ msleep(last_duration);
+
+ /* bring pin back low */
+ gpio_direction_input(pdata->pin);
+ } else {
+ /* bring pin high */
+ gpio_direction_output(pdata->pin, 1);
+ }
+
+ last_duration = delay;
+
+ return 0;
+}
+
 static void w1_gpio_write_bit_dir(void *data, u8 bit)
 {
  struct w1_gpio_platform_data *pdata = data;
@@ -67,7 +89,10 @@
  master->write_bit = w1_gpio_write_bit_val;
  } else {
  gpio_direction_input(pdata->pin);
- master->write_bit = w1_gpio_write_bit_dir;
+ master->write_bit  = w1_gpio_write_bit_dir;
+
+ /* Can't vouch for strong pullup for open-drain setups */
+ master->set_pullup = w1_gpio_set_pullup;
  }
 
  err = w1_add_master_device(master);

include/linux/w1-gpio.h:  added the last_duration bit. Could probably be handled cleaner by moving the set_pullup call to the post_write part, and not needing to store the timeout at all.
Code:
--- w1-gpio.h 2009-04-14 13:51:48.000000000 -0700
+++ tmk-w1-gpio.h 2009-04-25 21:45:48.955954736 -0700
@@ -20,4 +21,7 @@
  unsigned int is_open_drain:1;
 };
 
+/* stores the last duration requested for a pullup wait */
+int last_duration = 0;
+
 #endif /* _LINUX_W1_GPIO_H */


i *think* that's what it took for me. I'll help if i can. If you try it, let me know how it goes!

Cheers
-tmk
« Last Edit: April 25, 2009, 11:06:24 PM by tmk » Logged

alandpearson
Newbie
*

Karma: 0
Posts: 3


View Profile
« Reply #1 on: November 08, 2010, 05:12:04 PM »

Hi

First thanks for all this information, it really helps me get going.
I'm trying to get 1w working on Guruplug on the GPIO pins that are on the U-SNAP connector

I've build kernel 2.6.36, and applied all the necessary stuff to get GPIO working on these pins. That works well and the pins work well as GPIO.

However trying to get 1-wire working is hurting me a lot.
Followed your instructions for Sheeva, and adapted the GPIO pin to be 38 (pin 10 on U-SNAP)

sheevaplug-debian:~# modprobe wire
sheevaplug-debian:~# modprobe w1-gpio-custom bus0=0,38,1

All ok so far Smiley

Then it goes bad with

sheevaplug-debian:~# modprobe w1_gpio


Kernel crashes badly :
Custom GPIO-based W1 driver version 0.1.0
Unable to handle kernel paging request at virtual address bd93df90
pgd = deb34000
[bd93df90] *pgd=00000000
Internal error: Oops: 80000005 [#1] PREEMPT
last sysfs file: /sys/class/gpio/unexport
Modules linked in: w1_gpio(+) w1_gpio_custom wire xt_tcpudp iptable_filter ip_tables x_tables ipv6 libertas_sdio libertas uap8xxx sata_mv mv_cesa [last unloaded: w1_gpio_custom]
CPU: 0    Not tainted  (2.6.36 #2)
PC is at 0xbd93df90
LR is at 0xbf0f1850
pc : [<bd93df90>]    lr : [<bf0f1850>]    psr: a0000013
sp : debd3e98  ip : 00000000  fp : bed97984
r10: 00000040  r9 : debd2000  r8 : bf0f702c
r7 : deb03700  r6 : 00000000  r5 : deb94b00  r4 : df304000
r3 : bf0f10d4  r2 : 00000000  r1 : debd3e64  r0 : 00000001
Flags: NzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 0005397f  Table: 1eb34000  DAC: 00000015
Process modprobe (pid: 3050, stack limit = 0xdebd2270)
Stack: (0xdebd3e98 to 0xdebd4000)
3e80:                                                       deb03700 00001b98
3ea0: debd3e90 deb03708 deb03708 bf0f4190 bf0f4190 c0280828 00000060 c0282850
3ec0: c028283c c0281830 00000000 deb03708 deb0373c bf0f4190 00000000 c0281948
3ee0: bf0f4190 c02818e8 00000000 c0280fe4 df8077b8 deb017b0 bf0f4190 deb01a20
3f00: c057b6c8 c0280940 bf0f414f bf0f414f debd3f10 bf0f4190 00000001 00024400
3f20: 00000000 c002eb24 40061000 c0281c1c bf0f417c 00000001 00024400 00000000
3f40: c002eb24 c0282c3c bf0f41c8 bf0f7000 00024400 c002e42c 00000000 00000001
3f60: bf0f41c8 00000000 00024400 bf0f41c8 00000000 00024400 000014d5 c002eb24
3f80: 40061000 c0075e20 40038000 000014d5 00024400 00009064 00000000 00008edc
3fa0: 00000080 c002e9a0 00009064 00000000 40038000 000014d5 00024400 000014d5
3fc0: 00009064 00000000 00008edc 00000080 00000000 00000000 40061000 bed97984
3fe0: 00000000 bed978fc 0000b6b0 402790c4 60000010 40038000 1710c000 96002400
Code: bad PC value




Ouch. I get variations of the same error when I try to use a free GPIO pin.
If I try to use a used one, module won't load with a 16 error which I believe means it is in use.

Have you any idea at all how I could go about debugging this ?

Tnx
AlanP

Logged

alandpearson
Newbie
*

Karma: 0
Posts: 3


View Profile
« Reply #2 on: November 09, 2010, 01:01:56 PM »

OK, so I've got a little bit further with the help of the nice folks on the ARM mailing list.

Seems that w1_gpio_custom is causing the issue by not setting the platform data properly.

So, adding the correct platform data to arch/arm/mach-kirkwood/guru-setup.c fixes it (the oops) and takes away the need for w1_gpio_custom
The disadvantage is the GPIO line is not user selectable and is complied in. I may look at a way to get gpio_custom working again.

Anyway I'll post the patch tomorrow (don't have access to it now) to help others.

I still haven't got it recognising the 1W bus, but the good news here is that using U-SNAP as GPIO works and w1 should be next.

A use for that silly connector !
Logged

Pages: [1]
Print
Jump to: