world leader in high performance signal processing
Trace: » serial-flash-eeprom

Serial NOR Flash and U-Boot

U-Boot supports serial EEPROM NOR flashes which hook up to the Blackfin processor via a 4 wire SPI-compatible interface. Commands are provided for reading/writing of the EEPROM device. Splitting up of requests across pages is handled transparently to the user as is erasing of sectors before writing.

In terms of the command line interface, the eeprom command is the interface to all serial flash operations. It allows you to read/write a sequential range of bytes as well as query the SPI flash.

In terms of U-Boot code, U-Boot only provides the eeprom command. Board developers must write their own backend driver which takes serial read/write calls, handles the SPI communication, as well as sector erasing and splitting of read/writes across page boundaries of the flash.

While that all sounds quite terrible, the good news is that a Blackfin driver exists that should be portable to any Blackfin board without [hardly] any modifications.

There is no limit in terms of flash sizes that the SPI interface can support. U-Boot can work with the SPI flash regardless of its size. The current largest is about 128 megabits / 16 megabytes and it works great!

This page documents the eeprom interface which is used with 2008R1.5 / u-boot-1.1.6 and older. If you're using a newer release, please see the sf page: serial-flash

Configuration

You will need these options selected in your board configuration file in order to enable support for serial flashes.

  • define CONFIG_SPI
  • add CFG_CMD_EEPROM to CONFIG_COMMANDS

Querying

At runtime, you can interrogate the SPI flash to make sure things are detected properly.

bfin> eeprom info
SPI Device: S25LF032 0x01 (Spansion) 0x02 0x16
Parameters: num sectors = 64, sector size = 65536, write size = 256
Flash Size: 32 mbit (4 mbyte)
Status: 0x00

Here we can see that there is a 32 megabit Spansion flash hooked up. Good times.

Reading

You use the eeprom read command to read a range of bytes from the serial flash into memory. From there, you can do anything you like with it. For example, if we want to read 0x1000 bytes at an offset of 0x300 bytes from the start of the serial flash into external memory at 0x2000000, we'd simply run:

bfin> eeprom read 0x2000000 0x300 0x1000
EEPROM @0x0 read: addr 02000000  off 0300  count 4096 ... done
bfin> md.b 0x2000000
02000000: 0e e1 00 10 4e e1 b0 ff 90 61 10 3e 01 60 21 36    ....N....a.>.`!6
02000010: 29 36 31 36 39 36 01 3c 19 3c fc 31 00 e3 56 00    )61696.<.<.1..V.
02000020: 03 60 43 e1 00 20 98 09 03 18 00 e3 91 31 0e 60    .`C.. .......1.`
02000030: 00 e3 4c 00 02 e1 34 00 42 e1 fc 03 03 e1 00 00    ..L...4.B.......

Again, you do not need to worry about how the serial flash is split up into pages, so you could just as easily read multiple pages/sectors/blocks/whatever with one command.

You can ignore the @0x0 output in the output above. It does not apply to serial flashes.

Writing

You use the eeprom write command to write a range of bytes from memory into some offset into the serial flash. For example, if we want to write 0x100000 bytes from external memory at 0x20000000 into the serial flash at an offset of 0x0 bytes, we'd simply run:

bfin> eeprom write 0x20000000 0x0 0x100000
EEPROM @0x0 write: addr 20000000  off 0000  count 1048576 ... ................................done

There is no need for you to issue a separate erase command as the U-Boot driver will take care of that. There is also no need for you to worry about writing out only a page of data at a time.

You can ignore the @0x0 output in the output above. It does not apply to serial flashes.

Booting

When most people talk about booting, they sometimes forget that there are two aspects of booting a system - chip and hardware initialization (done by the bootloader), and booting the kernel.

Booting the Blackfin (U-Boot in SPI Flash)

This is covered in the booting_methods section.

Booting Linux (Linux in SPI Flash)

This is a simple matter of loading a uImage from SPI flash, and doing a bootm command on it. For example the following

bfin> set eepromboot 'eeprom read 0x2000000 0x300 0x100000; bootm 0x2000000'
bfin> set bootcmd run eepromboot
bfin> save

The next time this board boots, it will run the eepromboot command, which loads the image located in offset 0x300, with a length of 0x100000, into memory location 0x2000000, and then does a bootm on it. Simple!

Common Blackfin Driver

The common Blackfin driver can be found at board/bf537-stamp/spi_flash.c. It detects most Atmel, Spansion, ST, and Winbond SPI flashes automatically and handles the difference in op codes, sector sizes, page sizes, and sector count for you.

Even with all this support, the code weighs in at less than 3 kilobytes when compiled. It is recommended that instead of copying the file, you simply create a new file named spi_flash.c in your board directory with this one line:

#include "../bf537-stamp/spi_flash.c"

If you really need to shrink down the code size, then of course you should copy it to your board directory and make modifications there.

There are a few configuration options available when using this driver.

Option Default Meaning
CONFIG_SPI_BAUD 2 Divisor value written into the SPI_BAUD MMR
CONFIG_SPI_BAUD_INITBLOCK 4 Divisor value written into the SPI_BAUD MMR during early boot of the second stage bootloader
CONFIG_SPI_FLASH_SLOW_READ No Use the “slow” read opcode rather than the “fast” read opcode
CONFIG_SPI_FLASH_SSEL 2 (BF533/BF561 families) or 1 (all other parts) The SPI chip select the SPI flash is hooked up to