Wednesday, April 14, 2010

Recent happening -- OpenPXA, U-Boot, Marvell, Voipac, Zipit,...

Quite a lot happened in recent weeks. Now the time has come to sum this stuff up so expect quite long entry. I divided this entry into some subsections for the sake of readability.

Marvell and OpenPXA
The most important thing first. The OpenPXA project undercame quite big changes. The most significant one being OBM2, which I'll describe further. Besides this, the websites were updated and the u-boot patches were also updated to match the latest GIT HEAD.

As for the OBM, the original OpenPXA OBM turned out to be too less scalable and modular and it was also very hard adding new platforms. Besides understanding the assembly there was not for everyone. Also, this version of OBM didn't use stack and there were no function calls, it was a linear program and everything that looked like functions were macros. This made the work with this OBM even more complicated and basically made the possibility to extend the OBM in some way impossible.

To quench the need for a better OBM, an OBM2 was born. Written completely from scratch in the C language with little bits of inline assembly. Also, this new OBM2 has a very modular design and uses normal function calls which puts no more limitations on developers wanting to work on this. Besides this, new platforms can be easily added through an unified interface where the developer only has to fill in about three easy functions. Moreover, the OBM2 already carries a library of hardware drivers for the PXA3xx CPUs, like driver for UART and driver for NAND flash. Actually, the NAND flash driver is fundamental of course. But enough praise, even this OBM2 has it's draws. Let's take a better look at those now.

Before we take a look at the problems of OBM2, we better describe the boot procedure of a PXA3xx CPU. The CPU loads the first page of NAND into SRAM location 0x5c008000. In case there is a so called NTIM header, which is generated by a program called mkntim (included with the OBM2), the BootROM within the PXA3xx CPU copies the portions of memory according to the NTIM header. In the NTIM header, there is a configuration section called HMIT, a section describing the NTIM header called OBMI and a section with the OBM2 called BOOT. And the BOOT section is executed.

Now to the problem with OBM2. It's actually not really a problem with OBM2 but more with the PXA320 CPU BootROM. The BootROM in the PXA320 is older (v 2.22 in RTPXA320B2) than in the PXA310 I have available (v 3.33 in PXA310 A2). With the newer BootROM in PXA310, there is no problem with the NTIM header, it works fine, but with the PXA320 the NTIM header does not work at all. That's why I dumped the BootROM, started disassembling it and tracing the instruction flow. Not much luck yet though. But the fact the NTIM headers doesn't work on PXA320 doesn't render it unusable with OpenPXA OBM2. There is a way to boot the PXA320 CPU without an NTIM header by putting 8 zero bytes before the OBM2. Interestingly enough, the CPU drops the first two instructions, copies the rest to 0x5c014000 and executes it.

I introduced a variable CPU which determines which kind of image should be generated at compile time. Setting it to PXA320 generates file called 'iplntim.bin' which goes to 0x00 of NAND and is actually the OBM2 prefixed with those 8 zero bytes. Setting it to something else produces normal NTIM header and a OBM2 binary. In both cases, the compile process ends with a small help describing which file should be flashed where.

As for the hardware support on the OpenPXA OBM2 side, currently supported platforms are the Marvell Littleton PXA310 and the Toradex Colibri PXA320. Both of those platforms boot well with the OBM2.

I became the maintainer of U-Boot/PXA. This means fixes will hopefully flow in faster in this area. I'm looking forward to your patches and cooperation. There are a few fixes pending already. The GIT repository is here.

Some time ago, I wrote about a strange bug in U-Boot that caused printf() and NAND driver malfunction when VSPRINTF64 (simply 64bit support for printf()) was enabled. I hit this bug on my first PXA3xx platform, but was unable to debug it. This ended up with various weird workarounds which were in the OpenPXA "U-Boot patches" tree for some time. Just recently, I thought I'd be better if I took another look at the issue as those patches had side effects (like NAND was read-only etc.).

After a few hours of debugging a redeeming thought arrived. I took a look at the stack alignment, stupid me I didn't thought of this earlier. The LDRD and STRD instructions, which do a data movement between 64bit memory area and 2 following ARM registers need the memory area aligned to 8 bytes. Looking at the address of the variables, they were aligned to four bytes even with GCC attribute for variables __attribute__ ((aligned(8))). It turned out the aligned(8) does not mean it's aligned to 8 bytes from start of memory, but from the top of the stack. Therefore the final patch was simple, it was just a question of aligning the stack to 8 bytes.

Also, there was one more patch that caused problems to users on the PXA CPUs and not only the PXA3xx was affected. It was the PXAMCI driver for the MMC card. The first attempt to detect the card in most cases timed out. It was because the card had different delays for PXA27x than for PXA25x. Removing this shorter loops for PXA27x fixed this problem.

I established cooperation with Voipac Technologies a.s.. This was actually started by a friend of mine who lent me their hardware and said it's a pretty interesting box. The software was too limited though, meaning the preinstalled u-boot only allowed TFTP boot, there were no patches for VPAC270 board in the mainline kernel etc.

So I prepared a patchset for the VPAC270 and pushed it mainline. The only patch remaining outside mainline is for the SparseMEM support on this board. This one needs to be properly reworked probably before merging. And this needs some further thought. The patches that made it in add pretty much all the functionality for the VPAC270 board.

Zipit Z2
I also prepared a patchset for the Aeronix Zipit Z2. The patchset made it into mainline, though it was a slow process because it spanned across multiple kernel trees. There were drivers for various peripherals, that is battery driver and ASoC audio driver.

As for the ASoC driver, Mark Brown pointed out the WM8750 codec still wasn't turned to the new API. I therefore converted it over and then pushed both the conversion patch and a vastly reworked Z2 ASoC audio driver.

And this is it. That's all. I guess I should update this place more often rather than creating such a huge pieces of text once in a few weeks.

Monday, April 5, 2010

ZipitZ2 U-Boot update

I was recently asked by Magon if I could fix an u-boot for his Z2 that'd be able to be operated without a serial console. It took a little bit of investigation to figure out u-boot can run scripts from memory card. Though there still was a problem with the memory card.

The PXAMCI is known to be crappy. Though fixing this bug with the PXAMCI was simple. The problem was the mmc init command had to be called twice (or multiple times as some people reported) before the card was detected. It was just that the card was not fast enough to respond to commands so increasing the delays in the initialization routine fixed the problem.

Next was the scripting. I fixed a small conditional statement into the u-boot bootcmd variable which tries starting the MMC card and in case the card is there, starts a script called uboot.script from it. If the card is not present, it tries to start kernel from 0x60000.

The script for u-boot has to be compiled in a little special way. For that, there's a utility called mkimage. This utility takes input files, adds CRC and various other goodies and spits out an image that u-boot can use. To compile uboot.script, run the command like this (this is a one-liner):

mkimage -A arm -O u-boot -T script -C none -a 0 -e 0 -n uboot.script -d SOURCEFILE uboot.script

where SOURCEFILE is the file with the script and uboot.script is the result that goes onto the memory card. For example, my script that only boots the kernel looks like this:

if fatload mmc 0 0xa0000000 uImage ; then
bootm 0xa0000000 ;

As for the updated u-boot, the patches and a binary are available here:
Compiling and flashing (start from pt. 5) instructions:
  1. Apply all three patches in correct order (use git am)
  2. make CROSS_COMPILE=arm-crosscc- clean mrproper
  3. make CROSS_COMPILE=arm-crosscc- zipitz2_config
  4. make CROSS_COMPILE=arm-crosscc- -j9
  5. Flash u-boot.bin to 0x00 and erase 0x40000 (for environment) in your flash. In old u-boot, run:
    1. loady 0xa0000000 (here send the u-boot.bin over Ymodem)
    2. protect off all
    3. erase 0x00 +0x20000
    4. erase 0x40000 +0x20000
    5. cp.b 0xa0000000 0x0 0x1ea88
    6. reset