Thursday, May 13, 2010

Marvell, Voipac, U-Boot and insomnia

Again the time has come to push out a summary of things that I worked on recently. Mostly, I worked on the Voipac Technologies a.s. hardware, but there are some great news from Marvell as well.

Voipac
In the last entry, I mentioned adding support for the Voipac PXA270 SBC. Most of the support for this device hit mainline and will be available in 2.6.35 probably. The rest will hopefully hit 2.6.36. That's not all, I estabilished cooperation with the corporation itself and they sent me a baseboard and a CPU card equipped with OneNAND memory. This made me busy for a few days until I figured how to properly prepare the OneNAND IPL that is in U-Boot.

Voipac also sent me their JTAG adapter, which I'm very grateful for as it helped me a lot. Support for this JTAG adapter as well as for the Voipac board with NOR flash hit mainline OpenOCD already. It's currently impossible to flash OneNAND directly from OpenOCD, but one can load U-Boot into SRAM using OpenOCD and execute it from there. Then one can simply reflash the board from that U-Boot.

I then hacked on the SparseMEM support for the board a little more. There was a bug in kernel which caused the kernel to crash in very early stages with SparseMEM enabled. The bug was caused by a recent patch that was applied to the tree. Though, Catalin proposed a fix a few days before I finished debugging it, the fix was pending until someone tests it. Giving my ACK for that, the fix was applied and I submitted a SparseMEM support patch. The SparseMEM support is still unapplied though.

Besides, the company told me they have a DMA capable driver for the ParallelATA disk attached to the board. I only used the pata-platform driver which was only PIO capable and giving about 3800 kB/s reads. This was a no-go. The company didn't send me the harddrive extension for that board, so I had to fix myself a hardware hack, which allowed me to connect a CDROM drive. But ATAPI has specific needs when it comes to DMA and I was unable to get the DMA working with CDROM drive. So I made another hardware hack, even worse this time and connected a PATA 2.5" harddrive. Hacking on this driver for a while resulted in a generic pata-pxa driver, which uses the PXA DMA controller and is capable of getting over 11084 kB/s reads, but only for harddrive. For CDROM the driver falls back to PIO, but it's unlikely anyone will connect a CDROM to this SBC.

Hacking on the Voipac platform was great because the hardware is very well documented and the design is very clean.

U-Boot
I prepared a few macros that drop the need for copying so many code between PXA2xx boards in their lowlevel_init.S files. Those macros allow easy GPIO configuration, SDRAM configuration, clock and interrupt configuration as well as wakeup procedure. When using these macros, the lowlevel_init.S file consist of about 6 lines. This is a great achivement in cleaning up the u-boot-pxa. The ZipitZ2 platform was converted to use these new macros and works well.

Besides these macros, I added support for some new platforms. Namely the Voipac PXA270 with OneNAND flash and a Toradex Colibri PXA270. All of this new stuff is available in the u-boot-pxa devel branch. The branches were also recently rebased to bring the newest code from mainline u-boot.

Marvell
Recently, a friend of mine in Marvell arranged it so I was able receive two Marvell Zylonite units, one with Marvell PXA320 CPU and one with Intel PXA300 (the CPU was apparently made in Intel factory and is possibly even a prototype, though I'm unsure). This will be a great help for the OpenPXA project and he deserves a big thanks.

Also, I was told that PXA320 does not support NTIM header because the CPU is old (and has BootROM v2.22), which means I don't have to RE the BootROM anymore probably and I'd better focus on implementing a single NTIM header for both PXA320 and PXA310/300 (BootROM v3.xx). This is very likely doable through some a little non-standard alternations to the NTIM header. Though it's also likely I'll still continue to RE the BootROM just for curiousity's sake. For example I found out that WTM registers are mapped at 0x43000000 (this is undocumented in PXA3xx manual).

Others
I got my hands on one more platform -- the smarthouse.cz SH-Dmaster. It's a platform based on Toradex Colibri PXA270 module, but uses it's own baseboard. The patch for this platform is pending and is uncertain to be applied as it started a discussion about splitting development platforms to hardware that's on the mainboard and hardware that's on the CPU card.

I must not forget one more thing, I added support for the Guillemot Jet Leader Force Feedback joystick into the iforce driver. I had the patch lying around from the times of 2.6.16 or so, but never got around to sending it. Now it's already applied in linux-input. As I didn't want to reboot my PC to test the driver, I debugged it on the Voipac board.

Conclusion
Well, it's getting pretty busy recently, but I'm happy with the direction things are taking. Also, most of the hardware I have available now works well.

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.

U-Boot
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.

Voipac
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.

Conclusion
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 ;
fi

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

Sunday, December 13, 2009

OpenOCD: PXA3xx NAND flash driver

Just a quick entry today. Recently, I was hacking on a PXA3xx NAND flash support for OpenOCD. It's finally ready, though it has a few limitations. The preliminary version is available in the OpenPXA GIT as always, though the patches are being pushed into mainline OpenOCD. The limitations mentioned before are that you can't erase multiple blocks as once, you have to do it one after another for now. Also, this driver for now works only for large block devices, but adding support for small block ones should be easy. And the driver is quite slow too, so it's probably only useful for flashing in the bootloader.

A quick howto on reflashing the bootloader using the NAND code in OpenOCD follows:
  • run OpenOCD with the following command: openocd -s tcl -f board/colibri_pxa320.cfg -f interface/jtagkey.cfg (for Colibri/PXA3xx board and Amontec JTAGkey)
  • connect to OpenOCD using telnet: telnet localhost 4444
  • Issue the following commands, one after another:
    • reset halt
    • nand probe 0
    • nand erase 0 0x0 0x20000 ; nand erase 0x20000 0x20000 (erase first two blocks)
    • nand write 0 bootloader.img 0x0
  • To read data from NAND, use: nand dump 0 dump.img 0x0 0x800 (0x0 is base address, 0x800 is amount of bytes)

Sunday, November 29, 2009

Colibri/PXA320 meets OpenOCD, becomes free

In the last blog entry, I mentioned getting a development kit. It's cool and all, but as the Colibri/PXA320 and other PXA3xx boards, it has one really bad flaw -- all of the flashing tools for PXA3xx are for certain proprietary OS only. Moreover this particular overly proprietary debugger/flasher I got with the board was so choosy about adapters it supported it really went on my nerves badly especially since the adapter I got was not working properly and I couldn't use any other of those I had. So there was no way to reflash PXA3xx boards from Linux ... until recently.

I took a look at OpenOCD project, which is a Free Software JTAG Debugger, and figured it'd be actually quite simple to update it to support PXA3xx by looking into the PXA3xx documentation and comparing it with PXA2xx one. Apparently, the only differences there were the Instruction Length (which was 7 for PXA2xx and 11 for PXA3xx) and - the more weird change - that PXA3xx has the instruction codes shifted by 4 to the left in some cases. After fixing these, I was able to connect to the CPU using my FTDI FT2232 based fake-amontec JTAG cable and operate with it normally. The patches are available in the OpenPXA GIT.

Maybe someone would like to see a howto for loading new software into the board using the OpenOCD, so here it is. Firstly, download the OpenOCD patches from OpenPXA GIT and do:
  • git clone git://openocd.git.sourceforge.net/gitroot/openocd/openocd # download OpenOCD sources
  • cd openocd # enter the OpenOCD directory
  • apply OpenPXA patches for OpenOCD
  • ./bootstrap # prepare files necessary for OpenOCD compilation
  • ./configure --enable-maintainer-mode --enable-ft2232_libftdi # the first option is necessary (dunno why), the other one enables support for the ft2232-based cables
  • make # compiles OpenOCD
  • ./src/openocd -s tcl -f board/colibri_pxa320.cfg -f interface/jtagkey.cfg # executes the OpenOCD debugger; tells it to search for configuration scripts in directory tcl, to use colibri_pxa320.cfg board support file and jtagkey.cfg cable support file
  • telnet localhost 4444 # connect to the OpenOCD
Once connected using the telnet, we can start issuing commands. We'll want to load a program to a particular location in SRAM:
  • reset halt # reset the CPU and stop executing instructions
  • fast_load_image /path/to/file 0x5c080000 bin # prepare to load binary file to address 0x5c080000 (NOTE: 0x5c080000 is valid SRAM only for PXA320, for other CPUs use 0x5c000000 or something)
  • fast_load # actually upload the file
  • resume 0x5c080000 # continue instruction execution at address 0x5c080000 (about the address used, see previous note)
And now that you can load a file into SRAM and execute it, you can use this technique to load a bootloader there and control it over UART or something. Once you succeed in running the bootloader, you can do whatever you want with the hardware (for example flash the bootloader into NAND).

Tuesday, November 10, 2009

Colibri/PXA320 Ethernet, OpenPXA IPL v2.0 and UCB1400

Just a quick summary to keep possibly interested people in the loop today. I got the ethernet working on the Colibri/PXA320 board in u-boot. The problem was with the way the ax88796 driver was accessing the registers of the ethernet chip. It was actually accessing them in some weird 16bit mode, which caused two registers to be read at one time and the contents of the upper one was sometimes lost, caused malfunction of the driver. So I supplied my own access functions the same way as some Renesas board did and that eventually fixed the issues. Now the ethernet controller is working happily.

I recently started working on making the OpenPXA IPL more generic in preparation for supporting more devices. As I explained in an earlier post, the NAND is configured to some sane defaults and some of it's characteristics are determined by the BootROM already when the IPL is being executed. So I make use of this information and don't reconfigure the NAND, but just reset the chip and do READ0 and READYREAD commands. Also, I'm working on cleaning up the code and fixing some of it's possible issues.

Moreover, I plan to add debugging functionality into the IPL, which would probably allow the user to load some code into SRAM through serial console (XMODEM possibly or something) instead of NAND as it's now. Such thing will eventually allow the user to restore pretty much any system without NAND page number 0 being wiped out.

And the last thing today is about the UCB1400. I sent a patch upstream, that allows the UCB1400 to accept touchscreen IRQ GPIO through platform data. I also explained the reason for this in the previous post so read it there.

Saturday, November 7, 2009

Recent happening - PXA3xx, u-boot etc.

I just want to write some sum of what happened since last time I posted something here as stuff actually pretty piled up and I'm overly busy now. Expect somehow longer entry as quite a bit happened actually.

All this machinery started back in late September, when I got a Toradex Colibri carrier board with a PXA320 CPU card from INCOME s.r.o. and was instructed to prepare a decent bootloader for it and possibly make Linux kernel run smoothly on it. Sure, sounds easy, it's a Marvell CPU afterall and U-Boot already has some support for a few boards with PXA3xx too. Moreover, it's not too different from PXA2xx series, right? Yes sure, it's not, but there are a few changes.

I was suffering for some time, trying to make use of the preinstalled EBOOT bootloader to load Linux and even wrote some wrapper so it loads the kernel correctly at least, but I gave up on this idea as it turned out EBOOT is a worthless piece of crap. Not to mention, EBOOT is a proprietary goo. So I figured I need to replace it. U-Boot was the only choice here of course, but here came the first difference between PXA2xx and PXA3xx. The PXA3xx CPU does not need a NOR flash to boot from, it can boot directly from the NAND flash. Actually, there is something called BootROM buried in the CPU as I figured out later, but it's not possible to read it's contents without electron microscopy I think. Well this BootROM apparently configures the NAND properly, copies it's first sector to SRAM and executes it. But here popped in another problem, I managed to overwrite the first sector with not working code rendering the board unusable. Sadly, there is no utility for Linux that can flash the PXA3xx board so I had to use their proprietary one to reflash the board.

After numerous reflashes and testing, digging through the bootloader images Toradex released publicly and analyzing them, I managed to put together an open source GPLed IPL (initial program loader) that can be stored in the first sector of NAND with a sole purpose of loading further sectors from NAND, copying them to SRAM and then jumping to the beginning of these copied data. For this IPL, I established the OpenPXA project hosted on SourceForge as the plan is to extend it's support to other boards as you'll figure out later. Well, the data I mentioned a while ago that are being copied and executed are actually U-Boot. Maybe you are asking -- why is it so complicated. That's because the BootROM can apparently load only the first sector from NAND, the rest has to be done by the IPL, that's how the chip is.

Back to the U-Boot. There was one more obstacle I had to fight, it was the RAM. The PXA3xx supports DDR DRAM besides some other types of DRAM and the hardware I have has the DDR DRAM. That's why I had to write the initialization routine, which soon turned out to be one hell of a hard work to be done properly. As a side story, I made a decision to stick most of the hardware initialization into the U-Boot and keep the IPL size to the minimum. That's also why the IPL is loading the U-Boot into SRAM, to avoid initializing the DRAM controller.

After all this suffering, the current status of U-Boot for the Colibri/PXA320 is such that it's usable to boot Linux from MMC or NAND, the CPU is properly configured, DRAM works just fine. There are still a few problems though. The most noticable one is that the NAND can't be written from U-Boot, but I suspect that's because of a GCC bug that produces wrong code causing the U-Boot to hang. The other problem is that the ethernet adapter doesn't work in U-Boot, but that's being worked on now. It actually works from Linux so that's not much of a problem. Just as a side note, I sometimes update the patches for U-Boot in the OpenPXA git so if you are interested, you can find them there.

Mentioning GCC bugs, let me warn you that you should not even try compiling U-Boot with >= GCC4.3. It produces weird code and makes the U-Boot not work properly, like unexpectedly hang and such. I tried fixing some of those issues in U-Boot, but there are still many so stick with GCC4.2 for the time being. The exceptionally nasty one was with 64bit division. In the end, I ripped the code for 64bit division from Linux kernel and stick it into U-Boot, but that's more like a workaround.

Before I disclose my future plans with U-Boot on PXA3xx, I first need to explain why I'm so into it probably. That's because somewhere along the process of fixing U-Boot, I made some negotiations with a certain corporation that makes CPUs and such (I'm not sure if I can disclose anything more here, sorry) and was supplied some hardware to hack on. So that's why I'm sticking very closely to this and why I'm investing such a load of my time to this low-level stuff. Also I have to say, the people I communicated with so far are awesome and I like it the way it is.

So to the plans I have with the IPL and U-Boot. Firstly, I'll have to hack on the IPL a bit to make it support PXA310, Monahans LV CPU. Then there was an idea to use the values from BootROM to auto-configure the NAND in the IPL and possibly even later in U-Boot and Linux, which is awesome as the NAND will be technically auto-detected and we won't have to care for it much. Next of course will be fixing of the ethernet on the Colibri/PXA320, ok, maybe this will be first as I'm getting close here. What I'd also like to have working is the USB host in U-Boot so the thing can also boot from an USB thumb-drive or something.

Besides these plans with IPL and U-Boot, I have an idea that there needs to be an improvement made in the Linux kernel concerning the UCB1400 chip driver which is integrated on the Colibri/PXA320 module. This improvement would make use of the recently merged possibility of passing platform data through the AC97 bus. Let me explain properly. I recently got an email from someone that the pseudo-auto-detection routine which somehow should detect the proper touchscreen IRQ GPIO for UCB1400 doesn't work on his hardware. Well that sucks and it was unavoidable anyway I think. So this patch would pertain to removal of this routine altogether and modifying all the platforms that use the UCB1400 driver to supply the touchscreen IRQ GPIO as AC97 bus platform data. There are just two or three such platforms so it's not much of a problem anyway.

Well this is about it, life was pretty busy recently and the article actually grew quite long, sorry to hold you here for so long. I hope you enjoyed your stay at least.