Thursday, 14 August 2008

Hang on palmt650 first printk

Locks up in kernel/printk.c with time enabled:
asmlinkage int vprintk(const char *fmt, va_list args)
{
...
                        if (printk_time) {
                                /* Follow the token with the time */
                                char tbuf[50], *tp;
                                unsigned tlen;
                                unsigned long long t;
                                unsigned long nanosec_rem;

                                t = cpu_clock(printk_cpu);
                                nanosec_rem = do_div(t, 1000000000);
                                tlen = sprintf(tbuf, "[%5lu.%06lu] ",
                                                (unsigned long) t,
                                                nanosec_rem / 1000);

                                for (tp = tbuf; tp < tbuf + tlen; tp++)
                                        emit_log_char(*tp);
                                printed_len += tlen;
                        }

Friday, 18 April 2008

Palm Tungsten C wifi in Linux

Just noting this before I forget it. Use fc447e3213efb31cb16b5d9a2b0ebb77fbafd131 from git://git.hackndev.com/linux-2.6 with the defconfig. You'll need to load standard RAM prism firmware (pm010102.hex and rf010804.hex should work), but prism2_srec has to be patched as the production data area ("PDA") has an invalid CRC. A patch like this should do the trick:
diff -ru hostap-utils-0.4.7/util.c hostap-utils-0.4.7-hacked/util.c
--- hostap-utils-0.4.7/util.c   2004-02-14 18:50:12.000000000 +0000
+++ hostap-utils-0.4.7-hacked/util.c    2008-04-18 21:32:17.000000000 +0000
 -372,7 +372,7 @@
 
        fclose(f);
 
-       return parse_wlan_pda(pda_info, 0);
+       return parse_wlan_pda(pda_info, 1);
 }
Add to /etc/pcmcia/hostap_cs.conf (or equivalent)
card "PRISM ISL37101P-SSF Adapter"                                                                                                 
  manfid 0x000b, 0x7110
  bind "hostap_cs"
Then start the "cardmgr" daemon. It should detect and bind the card to hostap_cs, so you can see it as "wlan0" and "wifi0" in "ifconfig -a". You should then be able to load firmware using something like:
prism2_srec -gs wlan0 pm010102.hex
prism2_srec -gp wlan0 pm010102.hex
prism2_srec -rp wlan0 rf010804.hex
You can then configure and use as normal:
ifconfig wifi0 up
ifconfig wlan0 up
iwconfig mode wlan0 managed
iwlist scan
...or whatever

Tuesday, 31 July 2007

Hello! Hello?!

Well there's been much progress. I've basically finished off the kernel driver aside from waking the CPU from suspend upon an incoming call. Also adding basic BCM2132 to gsmd turned out to be a fairly simple procedure aside from some strangenesses of the platform. See the gsmd list for my patches. So now we can make and receive calls and SMS with the only remaining problem being routing of audio.

I've setup a skeleton SoC audio driver. This is enough after some fiddling with alsamixer to at least be able to hear what the other person says but outgoing sound doesn't work. The diagram to the left shows how I think things are wired up and should be of use to anyone trying to understand the huge number of alsamixer controls. At the moment I'm trying to get OE building an OpenMoko image with MACHINE=palmt650. :-)

Friday, 27 July 2007

Wake up!

I've been playing around with the Treo's GPIOs and I've finally discovered how to prevent the GSM module from going to sleep! Setting GPIO 57 high seems to force the module to stay awake. I also discovered GPIO 11 is a wake signal from the GSM to the CPU. This GPIO has a rising edge whenever some message is sent (or is ready to be sent) .

Also, while CTS seems to be always set when the GSM is powered, it will queue data while RTS is deasserted. So while in sleep we should probably deassert RTS, wait for GPIO 11 to awaken us (on eg incoming call) and then assert RTS to receive our data.

Trying to put all this information into a driver is going to be interesting. I wonder how pluggable the PXA serial driver is. Maybe I'll have to resort to just keeping the modem constantly awake for now.

Update: On first glance set_txrx() may do the trick.

Sunday, 22 July 2007

*Ring* *Ring*

I figured out the trick to making calls with the GSM modem in the Treo 650, you just need to give it the subsidy unlock code with AT+CPIN="xxxxxxx". I also found something else interesting:

AT+CFUN=6
The handset is in Calibration Mode:
                                   

********Main Menu:********
                          
0  HELP                   
1  ARFCN arfcn
2  MODULATION 0=GMSK/1=8PSK
3  DACVAL FREQ_DAC_ZERO    
4  ALL_RAMPS           
5  RAMP_SELECT txlev(0-19)
6  AGC rxlev              
7  GSYS band step
8  START 0=norm/1=rach
9  STOP               
10 OAKWR addr val
11 ARMWR size addr val
12 ISPCS 1=TRUE       
13 OAKRD? addr 
14 ARMRD? size addr
15 RXLEV?          
16 GSYS? band index
17 MULTISLOT       
18 EN_AUTO_SIM 
19 L1 TEST     
20 EDGE/GPRS TEST 
21 TXDB_WRITE Row(0-7) [v0 v2 v3 ....v15]
22 CHANGEMODE mode :0=normal,1=cal,2=download

It doesn't respond to commands after that. I guess it may be expecting some binary protocol.

I'm still having the problem of after receiving *MRDY: 3 after powering on the radio the connection seems to freeze up. Messages are still received it's just outgoing keypresses that seem to be ignored. I found if I hold down a key long enough it'll eventually receive it and I can issue commands like that. Something strange must be going, perhaps there's some time window which it will receive in.

If I pull out the SIM the device will drop to MRDY: 5 and the AT console becomes usable again. Curious.

Update: Ah. I've found references to something called cyclic sleep mode. So perhaps the baseband goes to sleep for some cycles and then wakes up and can receive commands again.

Saturday, 21 July 2007

A cure for insomnia

Our qemu tree has finally made itself really useful. By running the Treo's bootloader inside it I was able to figure out how to get suspend to ram working properly. It turns out to be really easy, all you have to do is set PSPR to some non-zero value and put the code you want to run on resume at 0xa000000.

Also after a lot of messing with qemu, Sergey Lapin and I also figured out how to resume Zire 72. Probably. It's untested on a physical device yet. On going to sleep you need to point PSPR at the physical address of the structure below. Set resume_addr to the argument passed into pxa_ll_pm_suspend(). It may be the same or similar for other devices with the "SmallROM" bootloader (such as T3).

static struct {                                                                                                                                                                       
        u32 magic0;             /* 0x0 */                                                                                                                                             
        u32 magic1;             /* 0x4 */                                                                                                                                             
        u32 resume_addr;        /* 0x8 */                                                                                                                                             
        u32 pad[11];            /* 0xc..0x37 */                                                                                                                                       
                                                                                                                                                                                      
        /* bootloader will configure co-processor 15 with these values: */
        u32 arm_control;        /* 0x38 */                                                                                                                                            
        u32 aux_control;        /* 0x3c */                                                                                                                                            
        u32 ttb;                /* 0x40 */                                                                                                                                            
        u32 domain_access;      /* 0x44 */                                                                                                                                            
        u32 process_id;         /* 0x48 */                                                                                                                                            
} palmz72_resume_info = {                                                                                                                                                             
        .magic0 = 0xb4e6,                                                                                                                                                             
        .magic1 = 1,                                                                                                                                                                  
                                                                                                                                                                                      
        /* reset state, MMU off etc */                                                                                                                                                
        .arm_control = 0,                                                                                                                                                             
        .aux_control = 0,                                                                                                                                                             
        .ttb = 0,                                                                                                                                                                     
        .domain_access = 0,                                                                                                                                                           
        .process_id = 0,                                                                                                                                                              
}; 

How to bake a loopy initramfs

If you follow Paul Sokolovsky's blog you'll know we've been developing some recipes for building initramfs images using OE. I won't repeat the details here, check Paul's blog for an overview but I will describe the loopback booting module (since he hinted so politely).

First, why would you want to boot off a loopback device? The most difficult thing for new users coming to Linux is probably installing it. You have to understand how to partition a disk and hope you don't accidentally wipe all your data in the first place. To make things quick for testing and easy for new users, over at Hack&Dev we usually release a boot pack which contains a kernel zImage, an initramfs and a root filesytem image. The user just unpacks all these files into the root directory of a memory card, installs Cocoboot and taps boot, no dangerous and confusing partitioning required. So after Paul showed me his nifty method for building an NFS booting initramfs I couldn't resist adding another recipe that you can use for loopback booting. We later went on to merge them into a nice modular system that you can plug in whatever boot methods you need.

Okay, how to use it? First build an initramfs image with the initramfs-module-loop package installed. The easiest way to do this is just bitbake initramfs-image. Next pop the initramfs in the appropriate place for your bootloader (or compile it into the kernel) and add to the kernel command-line something like

root=/dev/loop looproot=/dev/mmcblk0p1:rootfs.ext2

The initramfs will note the root option and start the loopboot module which will mount partition one of the MMC card (mmcblk0p1), then loopback mount the rootfs.ext2 and finally switch_root to it. The full syntax for the looproot option is

looproot=[device:]file[:offset]

device is the device file resides on, file is a filesystem image and offset is the offset into the image to mount from (see losetup(8) manpage, the -o option). In theory you should be able to include multiple looproot options and to allow recursive mounting (ie an image within an image), but this is untested. So to boot an image off the LifeDrive's data partition you might use something like:

root=/dev/loop
looproot=:/dev/hda:91814912
looproot=rootfs.ext2

Note I'm giving a block device as the file argument here. This is because Palm OS writes an invalid partition table (their partition start/end offset calculations are wrong) to the HDD so we have to use a loopback device to manually specify the offset into the disk. The second looproot option then will mount the filesystem image.