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#msg647Now that it's all working, i can read my 2 temp sensors on the shared bus:
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

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.cI had to apply the following patch to it to get it to load.
--- 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
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:
--- 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
--- 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.
--- 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
--- 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.
--- 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