Root/xbboot/target-stage1/stage1.c

1//
2// Authors: Wolfgang Spraul <wolfgang@qi-hardware.com>
3//
4// This program is free software; you can redistribute it and/or
5// modify it under the terms of the GNU General Public License
6// as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version.
8//
9
10#include <inttypes.h>
11#include "../target-common/jz4740.h"
12#include "../target-common/serial.h"
13
14#define STAGE1_ARGS_ADDR 0x80002008
15
16struct stage1_args {
17    // PLL
18    unsigned char ext_clk; // external crystal in MHz
19    unsigned char cpu_speed; // PLL output frequency=cpu_speed * ext_clk Mhz
20    unsigned char phm_div; // frequency divider ratio of PLL=CCLK:PCLK=HCLK=MCLK
21
22    // UART
23    unsigned char uart_num; // which UART to use (default: 0)
24    unsigned int uart_baud; // default: 57600
25
26    // SDRAM
27    unsigned char bus_width_16; // bus width of SDRAM is 16-bit (default is 32-bit)
28    unsigned char bank_addr_2bit; // 2-bit bank address width (=4 banks each chip select), default is 1-bit bank address=2 banks
29    unsigned char row_addr; // row address width in bits (11-13)
30    unsigned char col_addr; // column address width in bits (8-12)
31} __attribute__((packed));
32
33void load_args();
34void gpio_init();
35void pll_init();
36void serial_init();
37void sdram_init();
38
39void c_main(void)
40{
41    load_args();
42    gpio_init();
43    pll_init();
44    serial_init();
45    serial_puts("XBurst boot stage1...\n");
46    sdram_init();
47    serial_puts("stage 1 finished: GPIO, clocks, SDRAM, UART setup - now jump back to BOOT ROM...\n");
48}
49
50// tbd: do they have to be copied into globals? or just reference STAGE1_ARGS_ADDR?
51volatile u32 ARG_EXTAL;
52volatile u32 ARG_CPU_SPEED;
53volatile u8 ARG_PHM_DIV;
54volatile u32 ARG_UART_BASE;
55volatile u32 ARG_UART_BAUD;
56volatile u8 ARG_BUS_WIDTH_16;
57volatile u8 ARG_BANK_ADDR_2BIT;
58volatile u8 ARG_ROW_ADDR;
59volatile u8 ARG_COL_ADDR;
60
61void load_args()
62{
63    struct stage1_args* args = (struct stage1_args*) STAGE1_ARGS_ADDR;
64// NanoNote defaults
65args->ext_clk = 12;
66args->cpu_speed = 21;
67args->phm_div = 3;
68args->uart_num = 0;
69args->uart_baud = 57600;
70args->bus_width_16 = 1;
71args->bank_addr_2bit = 1;
72args->row_addr = 13;
73args->col_addr = 9;
74// END NanoNote defaults
75    ARG_EXTAL = args->ext_clk * 1000000;
76    ARG_CPU_SPEED = args->cpu_speed * ARG_EXTAL;
77    ARG_PHM_DIV = args->phm_div;
78    ARG_UART_BASE = UART0_BASE + args->uart_num * UART_OFF;
79    UART_BASE = ARG_UART_BASE; // for ../target-common/serial.c
80    ARG_UART_BAUD = args->uart_baud;
81    ARG_BUS_WIDTH_16 = args->bus_width_16;
82    ARG_BANK_ADDR_2BIT = args->bank_addr_2bit;
83    ARG_ROW_ADDR = args->row_addr;
84    ARG_COL_ADDR = args->col_addr;
85}
86
87void gpio_init()
88{
89    __gpio_as_nand();
90    __gpio_as_sdram_32bit();
91    __gpio_as_uart0();
92    __gpio_as_uart1();
93}
94
95void pll_init()
96{
97    register unsigned int cfcr, plcr1;
98    int n2FR[33] = {
99        0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
100        7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
101        9
102    };
103    /* int div[5] = {1, 4, 4, 4, 4}; */ /* divisors of I:S:P:L:M */
104    int nf, pllout2;
105
106    cfcr = CPM_CPCCR_CLKOEN |
107        (n2FR[1] << CPM_CPCCR_CDIV_BIT) |
108        (n2FR[ARG_PHM_DIV] << CPM_CPCCR_HDIV_BIT) |
109        (n2FR[ARG_PHM_DIV] << CPM_CPCCR_PDIV_BIT) |
110        (n2FR[ARG_PHM_DIV] << CPM_CPCCR_MDIV_BIT) |
111        (n2FR[ARG_PHM_DIV] << CPM_CPCCR_LDIV_BIT);
112
113    pllout2 = (cfcr & CPM_CPCCR_PCS) ? ARG_CPU_SPEED : (ARG_CPU_SPEED / 2);
114
115    /* Init UHC clock */
116    REG_CPM_UHCCDR = pllout2 / 48000000 - 1;
117
118    nf = ARG_CPU_SPEED * 2 / ARG_EXTAL;
119    plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */
120        (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */
121        (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */
122        (0x20 << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */
123        CPM_CPPCR_PLLEN; /* enable PLL */
124
125    /* init PLL */
126    REG_CPM_CPCCR = cfcr;
127    REG_CPM_CPPCR = plcr1;
128}
129
130static void serial_setbaud()
131{
132    volatile u8* uart_lcr = (volatile u8*)(ARG_UART_BASE + OFF_LCR);
133    volatile u8* uart_dlhr = (volatile u8*)(ARG_UART_BASE + OFF_DLHR);
134    volatile u8* uart_dllr = (volatile u8*)(ARG_UART_BASE + OFF_DLLR);
135    u32 baud_div, tmp;
136
137    baud_div = ARG_EXTAL / 16 / ARG_UART_BAUD;
138    tmp = *uart_lcr;
139    tmp |= UART_LCR_DLAB;
140    *uart_lcr = tmp;
141
142    *uart_dlhr = (baud_div >> 8) & 0xff;
143    *uart_dllr = baud_div & 0xff;
144
145    tmp &= ~UART_LCR_DLAB;
146    *uart_lcr = tmp;
147}
148
149void serial_init()
150{
151    volatile u8* uart_fcr = (volatile u8*)(ARG_UART_BASE + OFF_FCR);
152    volatile u8* uart_lcr = (volatile u8*)(ARG_UART_BASE + OFF_LCR);
153    volatile u8* uart_ier = (volatile u8*)(ARG_UART_BASE + OFF_IER);
154    volatile u8* uart_sircr = (volatile u8*)(ARG_UART_BASE + OFF_SIRCR);
155
156    /* Disable port interrupts while changing hardware */
157    *uart_ier = 0;
158
159    /* Disable UART unit function */
160    *uart_fcr = ~UART_FCR_UUE;
161
162    /* Set both receiver and transmitter in UART mode (not SIR) */
163    *uart_sircr = ~(SIRCR_RSIRE | SIRCR_TSIRE);
164
165    /* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
166    *uart_lcr = UART_LCR_WLEN_8 | UART_LCR_STOP_1;
167
168    /* Set baud rate */
169    serial_setbaud();
170
171    /* Enable UART unit, enable and clear FIFO */
172    *uart_fcr = UART_FCR_UUE | UART_FCR_FE | UART_FCR_TFLS | UART_FCR_RFLS;
173}
174
175#define SDRAM_CASL 3 /* CAS latency: 2 or 3 */
176// SDRAM Timings, unit: ns
177#define SDRAM_TRAS 45 /* RAS# Active Time */
178#define SDRAM_RCD 20 /* RAS# to CAS# Delay */
179#define SDRAM_TPC 20 /* RAS# Precharge Time */
180#define SDRAM_TRWL 7 /* Write Latency Time */
181#define SDRAM_TREF 15625 /* Refresh period: 4096 refresh cycles/64ms */
182
183void sdram_init()
184{
185    register unsigned int dmcr0, dmcr, sdmode, tmp, cpu_clk, mem_clk, ns;
186
187    unsigned int cas_latency_sdmr[2] = {
188        EMC_SDMR_CAS_2,
189        EMC_SDMR_CAS_3,
190    };
191    unsigned int cas_latency_dmcr[2] = {
192        1 << EMC_DMCR_TCL_BIT, /* CAS latency is 2 */
193        2 << EMC_DMCR_TCL_BIT /* CAS latency is 3 */
194    };
195
196    int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
197
198    cpu_clk = ARG_CPU_SPEED;
199    mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
200
201    REG_EMC_BCR = 0; /* Disable bus release */
202    REG_EMC_RTCSR = 0; /* Disable clock for counting */
203
204    /* Fault DMCR value for mode register setting*/
205    dmcr0 = (ARG_BUS_WIDTH_16<<EMC_DMCR_BW_BIT) |
206        EMC_DMCR_EPIN |
207        cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
208
209    /* Basic DMCR value */
210    dmcr = ((ARG_ROW_ADDR-11)<<EMC_DMCR_RA_BIT) |
211        ((ARG_COL_ADDR-8)<<EMC_DMCR_CA_BIT) |
212        (ARG_BANK_ADDR_2BIT<<EMC_DMCR_BA_BIT) |
213        (ARG_BUS_WIDTH_16<<EMC_DMCR_BW_BIT) |
214        EMC_DMCR_EPIN |
215        cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
216
217    /* SDRAM timimg */
218    ns = 1000000000 / mem_clk;
219    tmp = SDRAM_TRAS/ns;
220    if (tmp < 4) tmp = 4;
221    if (tmp > 11) tmp = 11;
222    dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);
223    tmp = SDRAM_RCD/ns;
224    if (tmp > 3) tmp = 3;
225    dmcr |= (tmp << EMC_DMCR_RCD_BIT);
226    tmp = SDRAM_TPC/ns;
227    if (tmp > 7) tmp = 7;
228    dmcr |= (tmp << EMC_DMCR_TPC_BIT);
229    tmp = SDRAM_TRWL/ns;
230    if (tmp > 3) tmp = 3;
231    dmcr |= (tmp << EMC_DMCR_TRWL_BIT);
232    tmp = (SDRAM_TRAS + SDRAM_TPC)/ns;
233    if (tmp > 14) tmp = 14;
234    dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);
235
236    /* SDRAM mode value */
237    sdmode = EMC_SDMR_BT_SEQ |
238         EMC_SDMR_OM_NORMAL |
239         EMC_SDMR_BL_4 |
240         cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
241
242    /* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
243    REG_EMC_DMCR = dmcr;
244    REG8(EMC_SDMR0|sdmode) = 0;
245
246    /* Wait for precharge, > 200us */
247    tmp = (cpu_clk / 1000000) * 1000;
248    while (tmp--);
249
250    /* Stage 2. Enable auto-refresh */
251    REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH;
252
253    tmp = SDRAM_TREF/ns;
254    tmp = tmp/64 + 1;
255    if (tmp > 0xff) tmp = 0xff;
256    REG_EMC_RTCOR = tmp;
257    REG_EMC_RTCNT = 0;
258    REG_EMC_RTCSR = EMC_RTCSR_CKS_64; /* Divisor is 64, CKO/64 */
259
260    /* Wait for number of auto-refresh cycles */
261    tmp = (cpu_clk / 1000000) * 1000;
262    while (tmp--);
263
264     /* Stage 3. Mode Register Set */
265    REG_EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
266    REG8(EMC_SDMR0|sdmode) = 0;
267
268        /* Set back to basic DMCR value */
269    REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
270
271    /* everything is ok now */
272}
273

Archive Download this file



interactive