OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [cris/] [arch-v32/] [lib/] [nand_init.S] - Rev 3

Compare with Previous | Blame | View Log

##=============================================================================
##
##      nand_init.S
##
##      The bootrom copies data from the NAND flash to the internal RAM but
##      due to a bug/feature we can only trust the 256 first bytes. So this
##      code copies more data from NAND flash to internal RAM. Obvioulsy this
##      code must fit in the first 256 bytes so alter with care.
##
##      Some notes about the bug/feature for future reference:
##        The bootrom copies the first 127 KB from NAND flash to internal
##        memory. The problem is that it does a bytewise copy. NAND flashes
##        does autoincrement on the address so for a 16-bite device each
##        read/write increases the address by two. So the copy loop in the
##        bootrom will discard every second byte. This is solved by inserting
##        zeroes in every second byte in the first erase block.
##
##        The bootrom also incorrectly assumes that it can read the flash
##        linear with only one read command but the flash will actually
##        switch between normal area and spare area if you do that so we
##        can't trust more than the first 256 bytes.
##
##=============================================================================

#include <asm/arch/hwregs/asm/reg_map_asm.h>
#include <asm/arch/hwregs/asm/gio_defs_asm.h>
#include <asm/arch/hwregs/asm/pinmux_defs_asm.h>
#include <asm/arch/hwregs/asm/bif_core_defs_asm.h>
#include <asm/arch/hwregs/asm/config_defs_asm.h>

;; There are 8-bit NAND flashes and 16-bit NAND flashes.
;; We need to treat them slightly different.
#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
#define PAGE_SIZE 256
#else
#error 2
#define PAGE_SIZE 512
#endif
#define ERASE_BLOCK 16384

;; GPIO pins connected to NAND flash
#define CE 4
#define CLE 5
#define ALE 6
#define BY 7

;; Address space for NAND flash
#define NAND_RD_ADDR 0x90000000
#define NAND_WR_ADDR 0x94000000

#define READ_CMD 0x00

;; Readability macros
#define CSP_MASK \
        REG_MASK(bif_core, rw_grp3_cfg, gated_csp0) | \
        REG_MASK(bif_core, rw_grp3_cfg, gated_csp1)
#define CSP_VAL \
        REG_STATE(bif_core, rw_grp3_cfg, gated_csp0, rd) | \
        REG_STATE(bif_core, rw_grp3_cfg, gated_csp1, wr)

;;----------------------------------------------------------------------------
;; Macros to set/clear GPIO bits

.macro SET x
        or.b   (1<<\x),$r9
        move.d $r9, [$r2]
.endm

.macro CLR x
        and.b  ~(1<<\x),$r9
        move.d $r9, [$r2]
.endm

;;----------------------------------------------------------------------------

nand_boot:
        ;; Check if nand boot was selected
        move.d REG_ADDR(config, regi_config, r_bootsel), $r0
        move.d [$r0], $r0
        and.d  REG_MASK(config, r_bootsel, boot_mode), $r0
        cmp.d  REG_STATE(config, r_bootsel, boot_mode, nand), $r0
        bne normal_boot ; No NAND boot
        nop

copy_nand_to_ram:
        ;; copy_nand_to_ram
        ;; Arguments
        ;;   r10 - destination
        ;;   r11 - source offset
        ;;   r12 - size
        ;;   r13 - Address to jump to after completion
        ;; Note : r10-r12 are clobbered on return
        ;; Registers used:
        ;;   r0 - NAND_RD_ADDR
        ;;   r1 - NAND_WR_ADDR
        ;;   r2 - reg_gio_rw_pa_dout
        ;;   r3 - reg_gio_r_pa_din
        ;;   r4 - tmp
        ;;   r5 - byte counter within a page
        ;;   r6 - reg_pinmux_rw_pa
        ;;   r7 - reg_gio_rw_pa_oe
        ;;   r8 - reg_bif_core_rw_grp3_cfg
        ;;   r9 - reg_gio_rw_pa_dout shadow
        move.d 0x90000000, $r0
        move.d 0x94000000, $r1
        move.d REG_ADDR(gio, regi_gio, rw_pa_dout), $r2
        move.d REG_ADDR(gio, regi_gio, r_pa_din), $r3
        move.d REG_ADDR(pinmux, regi_pinmux, rw_pa), $r6
        move.d REG_ADDR(gio, regi_gio, rw_pa_oe), $r7
        move.d REG_ADDR(bif_core, regi_bif_core, rw_grp3_cfg), $r8

#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
        lsrq    1, $r11
#endif
        ;; Set up GPIO
        move.d [$r2], $r9
        move.d [$r7], $r4
        or.b (1<<ALE) | (1 << CLE) | (1<<CE), $r4
        move.d $r4, [$r7]

        ;; Set up bif
        move.d [$r8], $r4
        and.d CSP_MASK, $r4
        or.d CSP_VAL, $r4
        move.d $r4, [$r8]

1:      ;; Copy one page
        CLR CE
        SET CLE
        moveq   READ_CMD, $r4
        move.b  $r4, [$r1]
        moveq   20, $r4
2:      bne     2b
        subq    1, $r4
        CLR CLE
        SET ALE
        clear.w [$r1]           ; Column address = 0
        move.d  $r11, $r4
        lsrq    8, $r4
        move.b  $r4, [$r1]      ; Row address
        lsrq    8, $r4
        move.b  $r4, [$r1]      ; Row adddress
        moveq   20, $r4
2:      bne     2b
        subq    1, $r4
        CLR ALE
2:      move.d  [$r3], $r4
        and.d   1 << BY, $r4
        beq 2b
        movu.w  PAGE_SIZE, $r5
2:      ; Copy one byte/word
#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
        move.w  [$r0], $r4
#else
        move.b  [$r0], $r4
#endif
        subq    1, $r5
        bne     2b
#if CONFIG_ETRAX_FLASH_BUSWIDTH==2
        move.w  $r4, [$r10+]
        subu.w  PAGE_SIZE*2, $r12
#else
        move.b  $r4, [$r10+]
        subu.w  PAGE_SIZE, $r12
#endif
        bpl     1b
        addu.w  PAGE_SIZE, $r11

        ;; End of copy
        jump    $r13
        nop

        ;; This will warn if the code above is too large. If you consider
        ;; to remove this you don't understand the bug/feature.
        .org 256
        .org ERASE_BLOCK

normal_boot:

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.