1##============================================================================= 2## 3## nand_init.S 4## 5## The bootrom copies data from the NAND flash to the internal RAM but 6## due to a bug/feature we can only trust the 256 first bytes. So this 7## code copies more data from NAND flash to internal RAM. Obvioulsy this 8## code must fit in the first 256 bytes so alter with care. 9## 10## Some notes about the bug/feature for future reference: 11## The bootrom copies the first 127 KB from NAND flash to internal 12## memory. The problem is that it does a bytewise copy. NAND flashes 13## does autoincrement on the address so for a 16-bite device each 14## read/write increases the address by two. So the copy loop in the 15## bootrom will discard every second byte. This is solved by inserting 16## zeroes in every second byte in the first erase block. 17## 18## The bootrom also incorrectly assumes that it can read the flash 19## linear with only one read command but the flash will actually 20## switch between normal area and spare area if you do that so we 21## can't trust more than the first 256 bytes. 22## 23##============================================================================= 24 25#include <asm/arch/hwregs/asm/reg_map_asm.h> 26#include <asm/arch/hwregs/asm/gio_defs_asm.h> 27#include <asm/arch/hwregs/asm/pinmux_defs_asm.h> 28#include <asm/arch/hwregs/asm/bif_core_defs_asm.h> 29#include <asm/arch/hwregs/asm/config_defs_asm.h> 30 31;; There are 8-bit NAND flashes and 16-bit NAND flashes. 32;; We need to treat them slightly different. 33#if CONFIG_ETRAX_FLASH_BUSWIDTH==2 34#define PAGE_SIZE 256 35#else 36#error 2 37#define PAGE_SIZE 512 38#endif 39#define ERASE_BLOCK 16384 40 41;; GPIO pins connected to NAND flash 42#define CE 4 43#define CLE 5 44#define ALE 6 45#define BY 7 46 47;; Address space for NAND flash 48#define NAND_RD_ADDR 0x90000000 49#define NAND_WR_ADDR 0x94000000 50 51#define READ_CMD 0x00 52 53;; Readability macros 54#define CSP_MASK \ 55 REG_MASK(bif_core, rw_grp3_cfg, gated_csp0) | \ 56 REG_MASK(bif_core, rw_grp3_cfg, gated_csp1) 57#define CSP_VAL \ 58 REG_STATE(bif_core, rw_grp3_cfg, gated_csp0, rd) | \ 59 REG_STATE(bif_core, rw_grp3_cfg, gated_csp1, wr) 60 61;;---------------------------------------------------------------------------- 62;; Macros to set/clear GPIO bits 63 64.macro SET x 65 or.b (1<<\x),$r9 66 move.d $r9, [$r2] 67.endm 68 69.macro CLR x 70 and.b ~(1<<\x),$r9 71 move.d $r9, [$r2] 72.endm 73 74;;---------------------------------------------------------------------------- 75 76nand_boot: 77 ;; Check if nand boot was selected 78 move.d REG_ADDR(config, regi_config, r_bootsel), $r0 79 move.d [$r0], $r0 80 and.d REG_MASK(config, r_bootsel, boot_mode), $r0 81 cmp.d REG_STATE(config, r_bootsel, boot_mode, nand), $r0 82 bne normal_boot ; No NAND boot 83 nop 84 85copy_nand_to_ram: 86 ;; copy_nand_to_ram 87 ;; Arguments 88 ;; r10 - destination 89 ;; r11 - source offset 90 ;; r12 - size 91 ;; r13 - Address to jump to after completion 92 ;; Note : r10-r12 are clobbered on return 93 ;; Registers used: 94 ;; r0 - NAND_RD_ADDR 95 ;; r1 - NAND_WR_ADDR 96 ;; r2 - reg_gio_rw_pa_dout 97 ;; r3 - reg_gio_r_pa_din 98 ;; r4 - tmp 99 ;; r5 - byte counter within a page 100 ;; r6 - reg_pinmux_rw_pa 101 ;; r7 - reg_gio_rw_pa_oe 102 ;; r8 - reg_bif_core_rw_grp3_cfg 103 ;; r9 - reg_gio_rw_pa_dout shadow 104 move.d 0x90000000, $r0 105 move.d 0x94000000, $r1 106 move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r2 107 move.d REG_ADDR(gio, regi_gio, r_pa_din), $r3 108 move.d REG_ADDR(pinmux, regi_pinmux, rw_pa), $r6 109 move.d REG_ADDR(gio, regi_gio, rw_pa_oe), $r7 110 move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r8 111 112#if CONFIG_ETRAX_FLASH_BUSWIDTH==2 113 lsrq 1, $r11 114#endif 115 ;; Set up GPIO 116 move.d [$r2], $r9 117 move.d [$r7], $r4 118 or.b (1<<ALE) | (1 << CLE) | (1<<CE), $r4 119 move.d $r4, [$r7] 120 121 ;; Set up bif 122 move.d [$r8], $r4 123 and.d CSP_MASK, $r4 124 or.d CSP_VAL, $r4 125 move.d $r4, [$r8] 126 1271: ;; Copy one page 128 CLR CE 129 SET CLE 130 moveq READ_CMD, $r4 131 move.b $r4, [$r1] 132 moveq 20, $r4 1332: bne 2b 134 subq 1, $r4 135 CLR CLE 136 SET ALE 137 clear.w [$r1] ; Column address = 0 138 move.d $r11, $r4 139 lsrq 8, $r4 140 move.b $r4, [$r1] ; Row address 141 lsrq 8, $r4 142 move.b $r4, [$r1] ; Row adddress 143 moveq 20, $r4 1442: bne 2b 145 subq 1, $r4 146 CLR ALE 1472: move.d [$r3], $r4 148 and.d 1 << BY, $r4 149 beq 2b 150 movu.w PAGE_SIZE, $r5 1512: ; Copy one byte/word 152#if CONFIG_ETRAX_FLASH_BUSWIDTH==2 153 move.w [$r0], $r4 154#else 155 move.b [$r0], $r4 156#endif 157 subq 1, $r5 158 bne 2b 159#if CONFIG_ETRAX_FLASH_BUSWIDTH==2 160 move.w $r4, [$r10+] 161 subu.w PAGE_SIZE*2, $r12 162#else 163 move.b $r4, [$r10+] 164 subu.w PAGE_SIZE, $r12 165#endif 166 bpl 1b 167 addu.w PAGE_SIZE, $r11 168 169 ;; End of copy 170 jump $r13 171 nop 172 173 ;; This will warn if the code above is too large. If you consider 174 ;; to remove this you don't understand the bug/feature. 175 .org 256 176 .org ERASE_BLOCK 177 178normal_boot: 179