Path: blob/master/arch/cris/arch-v32/lib/nand_init.S
15125 views
##=============================================================================1##2## nand_init.S3##4## The bootrom copies data from the NAND flash to the internal RAM but5## due to a bug/feature we can only trust the 256 first bytes. So this6## code copies more data from NAND flash to internal RAM. Obvioulsy this7## code must fit in the first 256 bytes so alter with care.8##9## Some notes about the bug/feature for future reference:10## The bootrom copies the first 127 KB from NAND flash to internal11## memory. The problem is that it does a bytewise copy. NAND flashes12## does autoincrement on the address so for a 16-bite device each13## read/write increases the address by two. So the copy loop in the14## bootrom will discard every second byte. This is solved by inserting15## zeroes in every second byte in the first erase block.16##17## The bootrom also incorrectly assumes that it can read the flash18## linear with only one read command but the flash will actually19## switch between normal area and spare area if you do that so we20## can't trust more than the first 256 bytes.21##22##=============================================================================2324#include <arch/hwregs/asm/reg_map_asm.h>25#include <arch/hwregs/asm/gio_defs_asm.h>26#include <arch/hwregs/asm/pinmux_defs_asm.h>27#include <arch/hwregs/asm/bif_core_defs_asm.h>28#include <arch/hwregs/asm/config_defs_asm.h>2930;; There are 8-bit NAND flashes and 16-bit NAND flashes.31;; We need to treat them slightly different.32#if CONFIG_ETRAX_FLASH_BUSWIDTH==233#define PAGE_SIZE 25634#else35#error 236#define PAGE_SIZE 51237#endif38#define ERASE_BLOCK 163843940;; GPIO pins connected to NAND flash41#define CE 442#define CLE 543#define ALE 644#define BY 74546;; Address space for NAND flash47#define NAND_RD_ADDR 0x9000000048#define NAND_WR_ADDR 0x940000004950#define READ_CMD 0x005152;; Readability macros53#define CSP_MASK \54REG_MASK(bif_core, rw_grp3_cfg, gated_csp0) | \55REG_MASK(bif_core, rw_grp3_cfg, gated_csp1)56#define CSP_VAL \57REG_STATE(bif_core, rw_grp3_cfg, gated_csp0, rd) | \58REG_STATE(bif_core, rw_grp3_cfg, gated_csp1, wr)5960;;----------------------------------------------------------------------------61;; Macros to set/clear GPIO bits6263.macro SET x64or.b (1<<\x),$r965move.d $r9, [$r2]66.endm6768.macro CLR x69and.b ~(1<<\x),$r970move.d $r9, [$r2]71.endm7273;;----------------------------------------------------------------------------7475nand_boot:76;; Check if nand boot was selected77move.d REG_ADDR(config, regi_config, r_bootsel), $r078move.d [$r0], $r079and.d REG_MASK(config, r_bootsel, boot_mode), $r080cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r081bne normal_boot ; No NAND boot82nop8384copy_nand_to_ram:85;; copy_nand_to_ram86;; Arguments87;; r10 - destination88;; r11 - source offset89;; r12 - size90;; r13 - Address to jump to after completion91;; Note : r10-r12 are clobbered on return92;; Registers used:93;; r0 - NAND_RD_ADDR94;; r1 - NAND_WR_ADDR95;; r2 - reg_gio_rw_pa_dout96;; r3 - reg_gio_r_pa_din97;; r4 - tmp98;; r5 - byte counter within a page99;; r6 - reg_pinmux_rw_pa100;; r7 - reg_gio_rw_pa_oe101;; r8 - reg_bif_core_rw_grp3_cfg102;; r9 - reg_gio_rw_pa_dout shadow103move.d 0x90000000, $r0104move.d 0x94000000, $r1105move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r2106move.d REG_ADDR(gio, regi_gio, r_pa_din), $r3107move.d REG_ADDR(pinmux, regi_pinmux, rw_pa), $r6108move.d REG_ADDR(gio, regi_gio, rw_pa_oe), $r7109move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r8110111#if CONFIG_ETRAX_FLASH_BUSWIDTH==2112lsrq 1, $r11113#endif114;; Set up GPIO115move.d [$r2], $r9116move.d [$r7], $r4117or.b (1<<ALE) | (1 << CLE) | (1<<CE), $r4118move.d $r4, [$r7]119120;; Set up bif121move.d [$r8], $r4122and.d CSP_MASK, $r4123or.d CSP_VAL, $r4124move.d $r4, [$r8]1251261: ;; Copy one page127CLR CE128SET CLE129moveq READ_CMD, $r4130move.b $r4, [$r1]131moveq 20, $r41322: bne 2b133subq 1, $r4134CLR CLE135SET ALE136clear.w [$r1] ; Column address = 0137move.d $r11, $r4138lsrq 8, $r4139move.b $r4, [$r1] ; Row address140lsrq 8, $r4141move.b $r4, [$r1] ; Row address142moveq 20, $r41432: bne 2b144subq 1, $r4145CLR ALE1462: move.d [$r3], $r4147and.d 1 << BY, $r4148beq 2b149movu.w PAGE_SIZE, $r51502: ; Copy one byte/word151#if CONFIG_ETRAX_FLASH_BUSWIDTH==2152move.w [$r0], $r4153#else154move.b [$r0], $r4155#endif156subq 1, $r5157bne 2b158#if CONFIG_ETRAX_FLASH_BUSWIDTH==2159move.w $r4, [$r10+]160subu.w PAGE_SIZE*2, $r12161#else162move.b $r4, [$r10+]163subu.w PAGE_SIZE, $r12164#endif165bpl 1b166addu.w PAGE_SIZE, $r11167168;; End of copy169jump $r13170nop171172;; This will warn if the code above is too large. If you consider173;; to remove this you don't understand the bug/feature.174.org 256175.org ERASE_BLOCK176177normal_boot:178179180