Thursday, 6 November 2008

Kernel changes for USB host

Oh, in case anyone wants to experiment with this, just add this to your machine file (arch/arm/mach-pxa/palmXX.c). I'm not going to post binaries or even a full patch now as this is still pretty experimental and you'll need to compile your own kernel with the drivers for whatever you want to connect anyway. Add the following headers, functions and a call in machine_init(). This should work on most of the PXA270 Palms.

#include <mach/pxa27x-udc.h>
#include <mach/ohci.h>

/*
 * USB Host (OHCI)
 */
static int palmt650_ohci_init(struct device *dev)
{
       UP2OCR = UP2OCR_HXS | UP2OCR_HXOE;
       UHCRHDA |= UHCRHDA_NOCP;
       UHCHR &= ~(UHCHR_SSEP2 | UHCHR_SSE);
       return 0;
}

static struct pxaohci_platform_data palmt650_ohci_platform_data = {
       .port_mode      = PMM_NPS_MODE,
       .init           = palmt650_ohci_init,
};

static void __init palmt650_init(void)
{
        ...
        pxa_set_ohci_info(&palmt650_ohci_platform_data);
}

You'll need to enable OHCI under USB host. I have been disabling USB gadget (client) support and I haven't tested what happens if you have both host and client enabled. I assume though that host probably takes precedence.

The easiest way to get a full speed device to enumerate is to plug the device in and use the "USB console" menu in Cocoboot before starting Linux. That'll turn on the USB pullups which will trick Linux into realizing there's a full speed device connected. You can also try turning on/off the pullups directly in Linux (GPIO 114 on the Treo 650). You can use gpio-val.c to control them within Linux (or a kernel module like GPIOed if you're using our older linux-hnd kernels).

Plus, someone was asking for a copy of the rootfs I use. For development work I just have an SD card with Debian/armel installed on it. This is not completely suitable for mobile devices but Debian has a ton of precompiled packages which you can just install with apt-get. This saves mucking around compiling. A few weeks ago I wrote some instructions in the forum including a tarball of a bare bones Debian image. I just install gcc, git-core and such on there and compile stuff on the device itself must of the time.

First attempt at a wifi dongle

...was unfortunately only partially successful. I picked up a few cheap link cables and the smallest USB wifi dongle I found in a brief search. The wifi dongles turned out to be based on the Zydas ZD1211 chipset (actually rebranded as Atheros AR5524) which is excellent for two reasons: they have drivers in the mainstream Linux kernel and they can run fine off a 3.3V power source. I went for the cheap after-market link cables (actually retractable ones) as they have easy to solder connectors which have all the pins.

I chopped the ends off one of each and soldered the GND, USB+ and USB- appropriately. For the dongles' power supply I tried the "EXT_POWER" pin on the multiconnector, which is supposed to be for powering accessories. To make Palm OS activate the power pin, tie the serial pins on the multiconnector to ground. In Linux on the Treo 650 you can toggle it with GPIO 37.

The dongle was detected fine by Linux and the driver sucessfully uploaded the firmware. Unfortunately on powering up the radio though the device appears to hang and the driver starts reporting timeouts. My guess was the "EXT_POWER" pin cannot supply enough current. To check this, I used my usual trick of stealing power from a molex connector in my PC. Sure enough, it started working fine and I was able to scan and connect to a network and then SSH in from my PC.

This is unfortunate as I'll probably end up having to add a battery pack of some sort. It's much neater a tidier without one. Oh well, probably a smallish Polymer Lithium-ion battery would be suitable. However, the fact that the device enumerates and can have the firmware uploaded while powered by "EXT_POWER" means it may be suitable for lower power USB devices, like flash drives or mice.

Yes, I have heard of SDIO, but it's more fun this way.