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.

Saturday, 14 July 2007

Treo650 gpios

Been doing some playing with GPIOs Clearing outputs: 23 turns of backlight, LEDs and causes palmos to think battery is dead. 24 turns off LEDs and causes palmos to think battery is dead. 25 as well... 79 - backlight power 114 - disables usb USB detect is in ASIC: bit 3 of register 0x36. High when disconnected.

Monday, 9 July 2007

Possibly power reg for T650 bluetooth

BT on:
08000044: 001f00fa001800bc
BT off:
08000044: 001f00ff00180080
                        ^^
Writing the ff into 0x44 had no effect, but 0x80 into 0x48 killed the connection. :D
bit 2: no effect
bit 3: no effect
bit 4: breaks connection
bit 5: breaks connection
Bingo! I'd say 4 and 5 are BT power and reset (although which is which?). Overwriting 0x0 (RBR/THR) also kills the connection while powering down BTUART has no effect indicating it's definately connect to ASIC UART.

Saturday, 7 July 2007

LifeDrive necromancy

I've just had some success in bringing my poor LifeDrive back from the grave. While the HDD is still unusable due to a broken cable, I was able to get the Linux kernel to boot. I chopped the end off a Nokia DKU-5 data cable (USB -> TTL serial converter) and soldered it to some test points corresponding to the serial port on the LD's mainboard. You might be able to make out the tiny red wires in bottom-left corner of the photo. (The yellow stuff is Blu Tack, preventing things from moving around). By holding down the hotsync button and resetting the device, minicom at 115200 baud and no flow control on my PC gets me to the "Sandal" recovery console:
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  Sandal
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
>
There are a couple of different commands you can use in the Sandal console but the important ones are "w" which reads and writes memory and "x" which executes code at the given address. I wrote a small script bin2sandal.py which converts a binary image into a series of Sandal commands enabling you to upload and execute a tiny bootloader I wrote in ARM assembly called quickload:
$ ./bin2sandal.py -d quickload.bin > /dev/ttyUSB0
...
>w 0xa00000e8=0xe5950000                                                                                                                                                              
0xA00000E8 : 0xE5950000                                                                                                                                                               
>w 0xa00000ec=0xe1a0f00e                                                                                                                                                              
0xA00000EC : 0xE1A0F00E                                                                                                                                                               
>x 0xa0000000                                                                                                                                                                         
Executing at 0xA0000000                                                                                                                                                               
Q?
The Q? prompt is quickload asking us to upload a kernel image. Well we'd better give it what it wants:
$ ./ql.py < zImage > /dev/ttyUSB0
Q?
  ql.py: uploading image...                                                                                                                                                           
G.............................

A little while later:
.............................D
Uncompressing Linux..........................................
........................... done, booting the kernel.                                                                                           
Linux version 2.6.21-hnd2 (ato@shion) (gcc version 4.1.2) 
#38 Sat Jul 7 12:50:15 EST 2007                                                                                   
CPU: XScale-PXA270 [69054117] revision 7 (ARMv5TE), cr=0000397f                                                                                                                       
Machine: Palm LifeDrive
... boot messages ...
# echo "I'm alive!"
I'm alive!                                                                                                                           
#
Unfortunately neither LCD nor MMC is working. I suspect this is because we normally rely on Palm OS to configure and power them up. I'll try overwriting the GPIO configuration with that from a working device later. The tools I used are in linux4palm/tools/serial-loader in Hack&Dev's SVN. Quickload should work on any PXA device, however you'll need to change the machine code that's passed to the kernel.