Monday, June 21, 2010

Zaurus hacking

Just a quick update on the problems I described on Zaurus. I've been hacking a little bit further into it and figured there's a problem in PCMCIA. Actually, there was always a warning in the pxa2xx_base.c stating that the timing recomputation for the PCMCIA devices is based off the CPU core frequency and that's probably wrong. I changed this and based the timing off the CPU bus frequency, which fixed one of the problems with Zaurus. It fixed the problem where at 312MHz the harddrive died. The other problem with weird lines on the LCD still persists, though not in such a big scale.

On the other hand, the LCD problem now appears even on 416 MHz which makes me think the PCMCIA timing recomputation has some other bug. Maybe, the timing is now too tight so the PCMCIA device takes too much bus bandwidth, triggering the LCDs FIFOs underruns.

There is one more thing that brings me to that conclusion, that is, when I ran a hdpart -T /dev/sda on the harddrive attached to PCMCIA, I got the following results:

FrequencyRead speed without fixRead speed with fix
416 MHz8 MB/s12 MB/s
208 MHz2 MB/s4 MB/s

Thursday, June 17, 2010

Recent XScale hacking

About a month passed since my last post so it's probably time for a recap. The last month was again very busy and the number of platforms that undercame changes overgrew the size of the header for this entry. For starters, let's just say that even the always so popular and beloved Zaurus got some cosmetic changes. There were also some changes in the PXA3xx land and the ZipitZ2 land wasn't left intact either.

ZipitZ2
The first turning point on this platform was a release of the U-Boot bootloader update kit for public testing. Some people installed this and reported me various bugs. There was for example a grave typo in the new U-Boot macros for pxa2xx which made wake-up from suspend-to-mem impossible. That was easily located and fixed right away. The new version of update kit was obviously uploaded very fast. Actually, there were no more bugs reported since then.

The only drawback is that U-Boot doesn't support booting from SDHC cards, only SD and MMC are supported. This can be easily worked around by flashing the kernel into the NOR to an address 0x60000. In case the U-Boot bootloader is unable to either detect a card or find a script on the card, it boots the kernel from the 0x60000 location.

The other changes related to ZipitZ2 happened within the Linux kernel. Firstly, the NOR flash layout was standardized. It is incompatible with the old layout, though on the other hand, now there are strict rules on how the NOR flash layout will look and no more anarchy will take place. The final layout is like this:
  • 0x0-0x40000 -- U-Boot bootloader
  • 0x40000-0x60000 -- U-Boot environment
  • 0x60000-END -- Linux kernel or possibly some small filesystem
I was also reported a bug in the screen blanking on ZipitZ2. Not long ago, Alberto Panizzo wrote a driver for his LCD based on my LMS283GF05 driver (the LCD in ZipitZ2). Though back when I wrote this driver, I made a mistake and screen blanking wasn't working correctly. Sadly, the same mistake got into the new driver by Alberto as well. I therefore sent a patch for both of the drivers.

In the end, I must not forget to mention, that the WM8750 codec is now finally registered in the platform definition file for both ZipitZ2 and Sharp Zaurus/Spitz. This brings the conversion of the WM8750 codec which I started before the 2.6.34 was out to an end.

Income SBC
In one of the older entries here, I mentioned I got my hands on the Income SBC and that my patch started some discussion in the Linux-ARM kernel mailing list. Just to explain what this Income SBC device is, it is a custom-made board with a LCD which is powered by the Toradex Colibri PXA270 module. The conclusion of the discussion was so that we need to separate the board support code from the module support code.

A friend of mine, Daniel Mack, took the Income SBC patch and the Colibri PXA270 code and did the split, which was very helpful. Before the split, I sent a pile of patches which added support for various devices on the Toradex Colibri PXA270 module/baseboard as the support was quite incomplete in mainline.

Sharp Zaurus
Just recently, a friend of mine, Metan, was complaining that the LCD screen on his Sharp Zaurus goes crazy when he uses the mainline Linux kernel and changes frequency of the CPU with CPUfreq to just about anything but 416MHz. He also complained, that if he changes the frequency to 312MHz, the harddrive in the machine fails. He lent me the machine for a while with an explanation on how to boot kernel on it.

It didn't take long and I came up with a first patch. That was actually just a cleanup. The Zaurus support code in mainline Linux kernel was in a terrible state. The first patch therefore only improved the readability of the code. Actually, there was also a minor revamp of the CF/SD power control function. All in all, the patch was pretty much a complete rewrite of the file.

Then, there was another patch. The Zaurus contains an Intersil ISL6271A PMIC for the CPU. Even before I got my hands on the Zaurus device, I implemented a driver for it and asked Metan if he can test it. Well in the end, he lent me the Zaurus instead. The initial version of the ISL6271A driver contained bugs, but after about three revisions of the patch, the driver was clean and was applied to the regulator tree.

There was still the LCD going crazy though. I discussed this with Eric Miao and he explained to me, that the CPU bus probably isn't capable of transferring so many data and therefore the LCD FIFOs underrun. I checked this by enabling the Input and Output FIFO Underrun interrupt in the PXAFB driver. And bingo, the underruns really happened. This means there is either something, that consumes the bus bandwidth or the bus is simply slow. I also tested some other kernels which supported CPUfreq and noticed the issues was there as well. Sadly, I wasn't able to get CPUfreq working with a stock Zaurus ROM.

Also there is still a lingering issue with the harddrive and 312MHz CPU speed. This will need further investigation. It'll probably involve the Sharp SCOOP chip and PCMCIA drivers undergoing a rewrite.

Marvell
Apparently, the popularity of the OpenPXA project is rising. I assume this from a fact that I get more requests for help and bug reports. There were some that helped the project greatly, even if there was no patch included with them. What's even better is the project actually gets testers and that really helps.

The first important bug report that arrived was from some person from HCLTech. He had issues with saving the U-Boot environment into the NAND on the Marvell Littleton PXA310 board. The whole problem was that the size of the environment sector differed from the size of NAND block and the U-Boot MTD subsystem can only write whole blocks. Also, the environment position wasn't aligned to block boundary.
That was quickly solved and a patch was applied on top of u-boot-pxa, openpxa branch.

Though he then wanted to do a TFTP boot and figured out the ethernet chip doesn't work in U-Boot. This took some further investigation. I figured out, that if I flash a Marvell BBU into the board and execute U-Boot from it, the ethernet magically works. I dumped various interesting registers from this setup and bisected the one which caused the problems with ethernet. The most funny part that the problem was caused by a bit marked as "SETALWAYS" not being set. Apparently, these bits marked as "SETALWAYS" mean something Marvell doesn't want other people to know. Obviously, armed with this knowledge, I fixed the ethernet and applied a patch.

The other batch of problems came from a guy owning a Colibri PXA320 board. He complained that he can't even boot a kernel from U-Boot. I figured this issue was only there if the kernel was compiled with a built-in initramfs. In the end, it was fixed by a quick patch. The problem was a mess in the RAM base addresses. It's an agreement in Linux-ARM, that the RAM on XScale starts at 0xa0000000. On PXA3xx though, the RAM is mirrored from 0x80000000 to 0xa0000000 by default for compatibility reasons. The U-Boot contained mess in this and both of these 0x80000000 and 0xa0000000 addresses were used. Unifying these addresses to 0xa0000000 fixed the problem.

Furthermore, this person complained, that the Colibri PXA320 board doesn't support USB device mode in Linux. A quick hack fixed that and patch already hit LAKML. With this guy happy and not considering buying a very expensive BSP from a certain corporation, I could have taken a rest. Though, I noticed some things worth fixing in U-Boot for this board along the way. I fixed the ethernet support on the Colibri PXA320 board in U-Boot and added USB host support.

This is still not all though. I mentioned in one of the older entries, that I got those Marvell Zylonites. I decided to take a look at those, particularly on the one with PXA320 C0 CPU. Firstly, I figured the CPU contains BootROM v3.38. This was a big surprise as this implies the CPU supports the NTIM header. Furthermore U-Boot apparently supported this board, but with the ongoing changes in the U-Boot bootloader, the platform was broken. I therefore took it and rewrote it from scratch, reusing just some of the static memory controller configuration values from it. The U-Boot works just fine. There is still a problem with this board though.

With the Zylonite320, I decided to try a new approach. I pushed all of the low-level init into the OpenPXA OBM2. I also implemented a DDR DRAM initialization code in the OBM2. This should in the end allow me, to totally skip and remove lowlevel_init.S in U-Boot. With just a few tweaks in the OpenPXA OBM2 and the NTIM header, I managed to get this working on the Zylonite320 as well.

And now to the problem. The expected behavior would be that if a power supply is attached to the device, it'd power up and U-Boot will come up. For some unknown reason, this doesn't happen on the Zylonite320. The only way I was able to get the Zylonite320 boot from NAND was to issue a "reset run" in the OpenOCD shell over JTAG. Then the board booted, no problem. I was slightly investigating this with a Marvell XDB and figured the NFC is maybe misconfigured in a way the NAND is detected as x16 instead of x8 by the BootROM. Though maybe there are just some switches that toggle the boot-up behaviour of the CPU.

Other
This month was quite rich in finishing conversions. Not only was the WM8750 conversion finished, but also the final removal of wm97xx_batt.h happened. The file was lingering in the kernel tree for about a year now, to be accurate ever since it was possible to pass platform data through the AC97 bus. So now the file is gone and all the platforms that used this file are now fixed.

In the end, I must not forget I got into a little fight with Russell King. We exchanged a few rough mails etc. Also, if I mention Pavel Machek was involved, I believe no further explanation is necessary. Actually, I was only teasing Russell a bit, but he probably took it personally.

I hope you enjoyed the reading, it was quite a lot of boring text as always.

Friday, May 14, 2010

Today's OpenPXA progress

I got to hacking on OpenPXA today. This brought some noticable progress. For some time already, there was a bothersome issue where one had to prepare a NTIM and IPL binary for the PXA300/PXA310 and a special combined IPLNTIM for PXA320.

Knowing it's most probably no use trying to get NTIM working on PXA320, I used a horrible hack. Firstly, lets recapitulate the facts. The first important fact is, that the first four bytes of the NTIM contain minimal version of BootROM this image will run on. The second important fact is that the four bytes at offset 0xc contain a date when the NTIM was created and is ignored by the BootROM.

On PXA300 and PXA310 which have BootROM v3.xx, the version string is compared to the BootROM version and if it's lower, the NTIM header is used to further control the boot process. On PXA320 on the other side, the code at 0x0 is copied to SRAM and normally executed. So the trick with unified NTIM now seems simple. It has a problem though.

Firstly I thought placing a branch instruction at offset 0x0 which would just jump past the NTIM should do the trick. How mistaken I was. The branch instruction was encoded as 0xea000028, if converted to LE it is 0x280000ea, whereas the version string in LE is 0x00030102 for BootROM v3.12, so this can't possibly work. Though there is a solution.

Branch which jumps eight bytes forward is encoded as 0xea000000, in LE 0x000000ea, which is lower than the version string. With this trick, I used the date entry and inserted an instruction which branches right past the NTIM header. You probably noticed by now, that the branch jumps 8 bytes forward, but the date entry is at 0xc. This is no problem as the entry at 0x8 is the HMIT section offset, which is zero and zero means nop.

This change has one more advantage. The IPL is now stored in block 0 of NAND just past the NTIM. It was necessary to patch the linker command so it'd correctly adjust the location of built in variables. But the result now is, one more block is free and can contain U-Boot most likely and there's no need to explicitly choose which CPU will the NTIM run at. As of today, the CPU parameter is dropped and only file called iplntim.bin is generated, holding the contents of NAND block 0.

Besides this crucial change, I moved the stack setup into a self standing function which then calls the main function of the IPL. This allows the main function to have it's variables on the stack and correctly allocated.

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)