Root/nandboot/src/nand_boot.c

1/*
2 * nand_boot.c
3 *
4 * NAND boot routine.
5 *
6 * Then nand boot loader can load the zImage type to execute.
7 * To get the zImage, build the kernel by 'make zImage'.
8 *
9 * Copyright (c) 2005-2008 Ingenic Semiconductor Inc.
10 * Author: <jlwei@ingenic.cn>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation; either version 2 of
15 * the License, or (at your option) any later version.
16 */
17
18#include <config.h>
19#include <nand.h>
20
21#ifdef CONFIG_JZ4730
22#include <jz4730.h>
23#include <jz4730_board.h>
24#endif
25
26#ifdef CONFIG_JZ4740
27#include <jz4740.h>
28#include <jz4740_board.h>
29#endif
30
31/*
32 * NAND Flash parameters (must be conformed to the NAND being used)
33 */
34static struct nand_param nand_p = {
35    .bus_width = 8, /* data bus width: 8-bit/16-bit */
36    .row_cycle = 3, /* row address cycles: 2/3 */
37    .page_size = 2048, /* page size in bytes: 512/2048 */
38    .oob_size = 64, /* oob size in bytes: 16/64 */
39    .page_per_block = 128, /* pages per block: 32/64/128 */
40    .bad_block_pos = 0 /* bad block pos in oob: 0/5 */
41};
42
43#define SIZE_KB (1 * 1024)
44#define SIZE_MB (1 * 1024 * 1024)
45
46/*
47 * Kernel image
48 */
49#define CFG_KERNEL_OFFS (256 * SIZE_KB) /* NAND offset of kernel image being loaded, has to be aligned to a block address! */
50#define CFG_KERNEL_SIZE (2 * SIZE_MB) /* Size of kernel image, has to be integer multiply of a block size! */
51#define CFG_KERNEL_DST 0x80600000 /* Load kernel to this addr */
52#define CFG_KERNEL_START 0x80600000 /* Start kernel from this addr */
53
54/*
55 * Kernel parameters
56 */
57#define PARAM_BASE 0x80004000
58
59/*
60 * Local variables
61 */
62static u32 *param_addr = 0;
63static u8 *tmpbuf = 0;
64
65static u8 cmdline[256] = CFG_CMDLINE;
66
67extern void gpio_init(void);
68extern int serial_init (void);
69extern void pll_init(void);
70extern void sdram_init(void);
71
72/*
73 * Load kernel image from NAND into RAM
74 */
75static int nand_load(struct nand_param *nandp, int offs, int kernel_size, u8 *dst)
76{
77    int page_size, page_per_block;
78    int block;
79    int block_size;
80    int blockcopy_count;
81    int page;
82
83    page_size = nandp->page_size;
84    page_per_block = nandp->page_per_block;
85
86    /*
87     * Enable NANDFlash controller
88     */
89    nand_enable();
90
91    /*
92     * offs has to be aligned to a block address!
93     */
94    block_size = page_size * page_per_block;
95    block = offs / block_size;
96    blockcopy_count = 0;
97
98    while (blockcopy_count < (kernel_size / block_size)) {
99        for (page = 0; page < page_per_block; page++) {
100            if (page == 0) {
101                /*
102                 * New block
103                 */
104                if (block_is_bad(nandp, block)) {
105                    block++;
106
107                    /*
108                     * Skip bad block
109                     */
110                    continue;
111                }
112            }
113
114            nand_read_page(nandp, block, page, dst);
115
116            dst += page_size;
117        }
118
119        block++;
120        blockcopy_count++;
121    }
122
123    /*
124     * Disable NANDFlash controller
125     */
126    nand_disable();
127
128    return 0;
129}
130
131/*
132 * NAND Boot routine
133 */
134void nand_boot(void)
135{
136    unsigned int boot_sel, i;
137
138    void (*kernel)(int, char **, char *);
139
140    /*
141     * Init gpio, serial, pll and sdram
142     */
143    gpio_init();
144    serial_init();
145
146    serial_puts("\n\nNAND Secondary Program Loader\n\n");
147
148    pll_init();
149    sdram_init();
150
151#ifdef CONFIG_JZ4740
152    /*
153     * JZ4740 can detect some NAND parameters from the boot select
154     */
155    boot_sel = REG_EMC_BCR >> 30;
156    if (boot_sel == 0x2)
157        nand_p.page_size = 512;
158    else
159        nand_p.page_size = 2048;
160#endif
161
162#ifdef CONFIG_JZ4730
163    /*
164     * JZ4730 can detect some NAND parameters from the boot select
165     */
166    boot_sel = (REG_EMC_NFCSR & 0x70) >> 4;
167
168    nand_p.bus_width = (boot_sel & 0x1) ? 16 : 8;
169    nand_p.page_size = (boot_sel & 0x2) ? 2048 : 512;
170    nand_p.row_cycle = (boot_sel & 0x4) ? 3 : 2;
171#endif
172
173    /*
174     * Load kernel image from NAND into RAM
175     */
176    nand_load(&nand_p, CFG_KERNEL_OFFS, CFG_KERNEL_SIZE, (u8 *)CFG_KERNEL_DST);
177
178    serial_puts("Starting kernel ...\n\n");
179
180    /*
181     * Prepare kernel parameters and environment
182     */
183    param_addr = (u32 *)PARAM_BASE;
184    param_addr[0] = 0; /* might be address of ascii-z string: "memsize" */
185    param_addr[1] = 0; /* might be address of ascii-z string: "0x01000000" */
186    param_addr[2] = 0;
187    param_addr[3] = 0;
188    param_addr[4] = 0;
189    param_addr[5] = PARAM_BASE + 32;
190    param_addr[6] = CFG_KERNEL_START;
191    tmpbuf = (u8 *)(PARAM_BASE + 32);
192
193    for (i = 0; i < 256; i++)
194        tmpbuf[i] = cmdline[i]; /* linux command line */
195
196    kernel = (void (*)(int, char **, char *))CFG_KERNEL_START;
197
198    /*
199     * Flush caches
200     */
201    flush_cache_all();
202
203    /*
204     * Jump to kernel image
205     */
206    (*kernel)(2, (char **)(PARAM_BASE + 16), (char *)PARAM_BASE);
207}
208

Archive Download this file



interactive