Root/
Source at commit 836fade86804815721468716b72c5d5786add5d0 created 14 years 3 months ago. By Lars-Peter Clausen, Massive cleanup | |
---|---|
1 | /* |
2 | * USB_BOOT Handle routines |
3 | * |
4 | * Copyright (C) 2009 Qi Hardware Inc., |
5 | * Author: Xiangfu Liu <xiangfu@qi-hardware.com> |
6 | * |
7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License |
9 | * version 3 as published by the Free Software Foundation. |
10 | * |
11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | * GNU General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU General Public License |
17 | * along with this program; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | * Boston, MA 02110-1301, USA |
20 | */ |
21 | |
22 | #include "jz4740.h" |
23 | #include "usb.h" |
24 | #include "error.h" |
25 | #include "usb_boot.h" |
26 | #include "usb_boot_defines.h" |
27 | #include "nandflash.h" |
28 | #include "udc.h" |
29 | #define dprintf(x) serial_puts(x) |
30 | |
31 | #define MEM_WRITE 0 |
32 | #define MEM_READ 1 |
33 | |
34 | #define MEM_8BIT (0 << 1) |
35 | #define MEM_16BIT (1 << 1) |
36 | #define MEM_32BIT (2 << 1) |
37 | |
38 | #define MEM_WRITE8 (MEM_WRITE | MEM_8BIT) |
39 | #define MEM_WRITE16 (MEM_WRITE | MEM_16BIT) |
40 | #define MEM_WRITE32 (MEM_WRITE | MEM_32BIT) |
41 | #define MEM_READ8 (MEM_READ | MEM_8BIT) |
42 | #define MEM_READ16 (MEM_READ | MEM_16BIT) |
43 | #define MEM_READ32 (MEM_READ | MEM_32BIT) |
44 | |
45 | |
46 | |
47 | unsigned int (*nand_query)(u8 *); |
48 | int (*nand_init)(int bus_width, int row_cycle, int page_size, int page_per_block, |
49 | int,int,int,int); |
50 | int (*nand_fini)(void); |
51 | u32 (*nand_program)(void *context, int spage, int pages,int option); |
52 | u32 (*nand_erase)(int blk_num, int sblk, int force); |
53 | u32 (*nand_read)(void *buf, u32 startpage, u32 pagenum,int option); |
54 | u32 (*nand_read_oob)(void *buf, u32 startpage, u32 pagenum); |
55 | u32 (*nand_read_raw)(void *buf, u32 startpage, u32 pagenum,int); |
56 | u32 (*nand_mark_bad) (int bad); |
57 | void (*nand_enable) (unsigned int csn); |
58 | void (*nand_disable) (unsigned int csn); |
59 | |
60 | struct hand Hand,*Hand_p; |
61 | extern u32 Bulk_buf[BULK_BUF_SIZE]; |
62 | extern u16 handshake_PKT[4]; |
63 | extern udc_state; |
64 | extern void *memset(void *s, int c, size_t count); |
65 | extern void *memcpy(void *dest, const void *src, size_t count); |
66 | |
67 | u32 ret_dat; |
68 | u32 start_addr; //program operation start address or sector |
69 | u32 ops_length; //number of operation unit ,in byte or sector |
70 | u32 ram_addr; |
71 | |
72 | void config_flash_info() |
73 | { |
74 | } |
75 | |
76 | void dump_data(unsigned int *p, int size) |
77 | { |
78 | int i; |
79 | for(i = 0; i < size; i ++) |
80 | serial_put_hex(*p++); |
81 | } |
82 | |
83 | void config_hand() |
84 | { |
85 | struct hand *hand_p; |
86 | hand_p=(struct hand *)Bulk_buf; |
87 | memcpy(&Hand, (unsigned char *)Bulk_buf, sizeof(struct hand)); |
88 | |
89 | #if 0 |
90 | Hand.nand_bw=hand_p->nand_bw; |
91 | Hand.nand_rc=hand_p->nand_rc; |
92 | Hand.nand_ps=hand_p->nand_ps; |
93 | Hand.nand_ppb=hand_p->nand_ppb; |
94 | Hand.nand_force_erase=hand_p->nand_force_erase; |
95 | Hand.nand_pn=hand_p->nand_pn; |
96 | Hand.nand_os=hand_p->nand_os; |
97 | |
98 | Hand.nand_eccpos=hand_p->nand_eccpos; |
99 | Hand.nand_bbpos=hand_p->nand_bbpos; |
100 | Hand.nand_bbpage=hand_p->nand_bbpage; |
101 | // memcpy( &Hand.fw_args, (unsigned char *)(start_addr + 0x8), 32 ); |
102 | |
103 | // serial_putc(Hand.nand_eccpos + 48); |
104 | // serial_putc(Hand.nand_bbpos + 48); |
105 | // serial_putc(Hand.nand_bbpage + 48); |
106 | /* dprintf("\n Hand : bw %d rc %d ps %d ppb %d erase %d pn %d os %d", */ |
107 | /* Hand.nand_bw,Hand.nand_rc,Hand.nand_ps,Hand.nand_ppb,Hand.nand_force_erase,Hand.nand_pn,Hand.nand_os); */ |
108 | serial_put_hex(Hand.fw_args.cpu_id); |
109 | serial_put_hex(Hand.fw_args.ext_clk); |
110 | #endif |
111 | } |
112 | |
113 | int GET_CUP_INFO_Handle() |
114 | { |
115 | char temp1[8]="Boot4740",temp2[8]="Boot4750"; |
116 | dprintf("\n GET_CPU_INFO!"); |
117 | if ( Hand.fw_args.cpu_id == 0x4740 ) |
118 | HW_SendPKT(0,temp1,8); |
119 | else |
120 | HW_SendPKT(0,temp2,8); |
121 | udc_state = IDLE; |
122 | return ERR_OK; |
123 | } |
124 | |
125 | int SET_DATA_ADDERSS_Handle(u8 *buf) |
126 | { |
127 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
128 | start_addr=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex; |
129 | dprintf("\n SET ADDRESS:"); |
130 | serial_put_hex(start_addr); |
131 | return ERR_OK; |
132 | } |
133 | |
134 | int SET_DATA_LENGTH_Handle(u8 *buf) |
135 | { |
136 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
137 | ops_length=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex; |
138 | dprintf("\n DATA_LENGTH :"); |
139 | serial_put_hex(ops_length); |
140 | return ERR_OK; |
141 | } |
142 | |
143 | int FLUSH_CACHES_Handle() |
144 | { |
145 | return ERR_OK; |
146 | } |
147 | |
148 | int PROGRAM_START1_Handle(u8 *buf) |
149 | { |
150 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
151 | ram_addr=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex; |
152 | //dprintf("\n RAM ADDRESS :%x", ram_addr); |
153 | return ERR_OK; |
154 | } |
155 | |
156 | int PROGRAM_START2_Handle(u8 *buf) |
157 | { |
158 | void (*f)(void); |
159 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
160 | f=(void *) ((((u32)dreq->wValue)<<16)+(u32)dreq->wIndex); |
161 | __dcache_writeback_all(); |
162 | //stop udc connet before execute program! |
163 | jz_writeb(USB_REG_POWER,0x0); //High speed |
164 | //dprintf("\n Execute program at %x",(u32)f); |
165 | f(); |
166 | return ERR_OK; |
167 | } |
168 | |
169 | int MEM_OPS_Handle(u8 *buf) |
170 | { |
171 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
172 | u32 val; |
173 | |
174 | switch (dreq->wValue) { |
175 | case MEM_WRITE8: |
176 | *((volatile u8*)(start_addr)) = (u8)ops_length; |
177 | handshake_PKT[0] = ops_length & 0xff; |
178 | handshake_PKT[1] = 8; |
179 | break; |
180 | case MEM_WRITE16: |
181 | *((volatile u16*)(start_addr)) = (u16)ops_length; |
182 | handshake_PKT[0] = ops_length & 0xffff; |
183 | handshake_PKT[1] = 16; |
184 | break; |
185 | case MEM_WRITE32: |
186 | *((volatile u32*)(start_addr)) = ops_length; |
187 | handshake_PKT[0] = ops_length; |
188 | handshake_PKT[1] = ops_length >> 16; |
189 | break; |
190 | case MEM_READ8: |
191 | val = *((volatile u8*)(start_addr)); |
192 | handshake_PKT[0] = (u16)val; |
193 | handshake_PKT[1] = (u16)(val >> 16); |
194 | break; |
195 | case MEM_READ16: |
196 | val = *((volatile u16*)(start_addr)); |
197 | handshake_PKT[0] = (u16)val; |
198 | handshake_PKT[1] = (u16)(val >> 16); |
199 | break; |
200 | case MEM_READ32: |
201 | val = *((volatile u32*)(start_addr)); |
202 | handshake_PKT[0] = (u16)val; |
203 | handshake_PKT[1] = (u16)(val >> 16); |
204 | break; |
205 | default: |
206 | handshake_PKT[0] = 0xDEAD; |
207 | handshake_PKT[1] = 0xC0DE; |
208 | break; |
209 | } |
210 | handshake_PKT[2] = 0; |
211 | handshake_PKT[3] = 0; |
212 | HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT)); |
213 | return ERR_OK; |
214 | } |
215 | |
216 | int NOR_OPS_Handle(u8 *buf) |
217 | { |
218 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
219 | udc_state = IDLE; |
220 | return ERR_OK; |
221 | } |
222 | |
223 | int NAND_OPS_Handle(u8 *buf) |
224 | { |
225 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
226 | u32 temp; |
227 | int option; |
228 | u8 CSn; |
229 | |
230 | CSn = (dreq->wValue>>4) & 0xff; |
231 | option = (dreq->wValue>>12) & 0xff; |
232 | nand_enable(CSn); |
233 | switch ((dreq->wValue)&0xf) |
234 | { |
235 | case NAND_QUERY: |
236 | dprintf("\n Request : NAND_QUERY!"); |
237 | nand_query((u8 *)Bulk_buf); |
238 | HW_SendPKT(1, Bulk_buf, 8); |
239 | handshake_PKT[3]=(u16)ERR_OK; |
240 | udc_state = BULK_IN; |
241 | break; |
242 | case NAND_INIT: |
243 | dprintf("\n Request : NAND_INIT!"); |
244 | |
245 | break; |
246 | case NAND_MARK_BAD: |
247 | dprintf("\n Request : NAND_MARK_BAD!"); |
248 | ret_dat = nand_mark_bad(start_addr); |
249 | handshake_PKT[0] = (u16) ret_dat; |
250 | handshake_PKT[1] = (u16) (ret_dat>>16); |
251 | HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT)); |
252 | udc_state = IDLE; |
253 | |
254 | break; |
255 | case NAND_READ_OOB: |
256 | dprintf("\n Request : NAND_READ_OOB!"); |
257 | memset(Bulk_buf,0,ops_length*Hand.nand_ps); |
258 | ret_dat = nand_read_oob(Bulk_buf,start_addr,ops_length); |
259 | handshake_PKT[0] = (u16) ret_dat; |
260 | handshake_PKT[1] = (u16) (ret_dat>>16); |
261 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps); |
262 | udc_state = BULK_IN; |
263 | break; |
264 | case NAND_READ_RAW: |
265 | dprintf("\n Request : NAND_READ_RAW!"); |
266 | switch (option) |
267 | { |
268 | case OOB_ECC: |
269 | nand_read_raw(Bulk_buf,start_addr,ops_length,option); |
270 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os)); |
271 | handshake_PKT[0] = (u16) ret_dat; |
272 | handshake_PKT[1] = (u16) (ret_dat>>16); |
273 | udc_state = BULK_IN; |
274 | break; |
275 | default: |
276 | nand_read_raw(Bulk_buf,start_addr,ops_length,option); |
277 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps); |
278 | handshake_PKT[0] = (u16) ret_dat; |
279 | handshake_PKT[1] = (u16) (ret_dat>>16); |
280 | udc_state = BULK_IN; |
281 | break; |
282 | } |
283 | break; |
284 | case NAND_ERASE: |
285 | dprintf("\n Request : NAND_ERASE!"); |
286 | ret_dat = nand_erase(ops_length,start_addr, |
287 | Hand.nand_force_erase); |
288 | handshake_PKT[0] = (u16) ret_dat; |
289 | handshake_PKT[1] = (u16) (ret_dat>>16); |
290 | HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT)); |
291 | udc_state = IDLE; |
292 | dprintf("\n Request : NAND_ERASE_FINISH!"); |
293 | break; |
294 | case NAND_READ: |
295 | dprintf("\n Request : NAND_READ!"); |
296 | // dprintf("\n Option : %x",option); |
297 | switch (option) |
298 | { |
299 | case OOB_ECC: |
300 | ret_dat = nand_read(Bulk_buf,start_addr,ops_length,OOB_ECC); |
301 | handshake_PKT[0] = (u16) ret_dat; |
302 | handshake_PKT[1] = (u16) (ret_dat>>16); |
303 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os )); |
304 | udc_state = BULK_IN; |
305 | break; |
306 | case OOB_NO_ECC: |
307 | ret_dat = nand_read(Bulk_buf,start_addr,ops_length,OOB_NO_ECC); |
308 | handshake_PKT[0] = (u16) ret_dat; |
309 | handshake_PKT[1] = (u16) (ret_dat>>16); |
310 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*(Hand.nand_ps + Hand.nand_os)); |
311 | udc_state = BULK_IN; |
312 | break; |
313 | case NO_OOB: |
314 | ret_dat = nand_read(Bulk_buf,start_addr,ops_length,NO_OOB); |
315 | handshake_PKT[0] = (u16) ret_dat; |
316 | handshake_PKT[1] = (u16) (ret_dat>>16); |
317 | HW_SendPKT(1,(u8 *)Bulk_buf,ops_length*Hand.nand_ps); |
318 | udc_state = BULK_IN; |
319 | break; |
320 | } |
321 | dprintf("\n Request : NAND_READ_FUNISH!"); |
322 | break; |
323 | case NAND_PROGRAM: |
324 | dprintf("\n Request : NAND_PROGRAM!"); |
325 | // dprintf("\n Option : %x",option); |
326 | ret_dat = nand_program((void *)Bulk_buf, |
327 | start_addr,ops_length,option); |
328 | dprintf("\n NAND_PROGRAM finish!"); |
329 | handshake_PKT[0] = (u16) ret_dat; |
330 | handshake_PKT[1] = (u16) (ret_dat>>16); |
331 | HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT)); |
332 | udc_state = IDLE; |
333 | break; |
334 | case NAND_READ_TO_RAM: |
335 | dprintf("\n Request : NAND_READNAND!"); |
336 | nand_read((u8 *)ram_addr,start_addr,ops_length,NO_OOB); |
337 | __dcache_writeback_all(); |
338 | handshake_PKT[3]=(u16)ERR_OK; |
339 | HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT)); |
340 | udc_state = IDLE; |
341 | break; |
342 | default: |
343 | nand_disable(CSn); |
344 | return ERR_OPS_NOTSUPPORT; |
345 | } |
346 | |
347 | return ERR_OK; |
348 | } |
349 | |
350 | int SDRAM_OPS_Handle(u8 *buf) |
351 | { |
352 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
353 | u32 temp,i; |
354 | u8 *obj; |
355 | |
356 | switch ((dreq->wValue)&0xf) |
357 | { |
358 | case SDRAM_LOAD: |
359 | // dprintf("\n Request : SDRAM_LOAD!"); |
360 | ret_dat = (u32)memcpy((u8 *)start_addr,Bulk_buf,ops_length); |
361 | handshake_PKT[0] = (u16) ret_dat; |
362 | handshake_PKT[1] = (u16) (ret_dat>>16); |
363 | HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT)); |
364 | udc_state = IDLE; |
365 | break; |
366 | } |
367 | return ERR_OK; |
368 | } |
369 | |
370 | void Borad_Init() |
371 | { |
372 | dprintf("\n Borad_init! "); |
373 | serial_put_hex(Hand.fw_args.cpu_id); |
374 | switch (Hand.fw_args.cpu_id) |
375 | { |
376 | case 0x4740: |
377 | //Init nand flash |
378 | nand_init_4740(Hand.nand_bw,Hand.nand_rc,Hand.nand_ps,Hand.nand_ppb, |
379 | Hand.nand_bbpage,Hand.nand_bbpos,Hand.nand_force_erase,Hand.nand_eccpos); |
380 | |
381 | dprintf("\nnand_ps, nand_ppb, nand_bbpage, nand_bbpos, nand_eccpos\n"); |
382 | serial_put_hex(Hand.nand_ps); |
383 | serial_put_hex(Hand.nand_ppb); |
384 | serial_put_hex(Hand.nand_bbpage); |
385 | serial_put_hex(Hand.nand_bbpos); |
386 | serial_put_hex(Hand.nand_eccpos); |
387 | |
388 | nand_program = nand_program_4740; |
389 | nand_erase = nand_erase_4740; |
390 | nand_read = nand_read_4740; |
391 | nand_read_oob = nand_read_oob_4740; |
392 | nand_read_raw = nand_read_raw_4740; |
393 | nand_query = nand_query_4740; |
394 | nand_enable = nand_enable_4740; |
395 | nand_disable = nand_disable_4740; |
396 | nand_mark_bad = nand_mark_bad_4740; |
397 | break; |
398 | case 0x4750: |
399 | //Init nand flash |
400 | nand_init_4750(Hand.nand_bw, Hand.nand_rc, Hand.nand_ps, |
401 | Hand.nand_ppb, Hand.nand_bchbit, Hand.nand_eccpos, |
402 | Hand.nand_bbpos, Hand.nand_bbpage, Hand.nand_force_erase); |
403 | |
404 | nand_program = nand_program_4750; |
405 | nand_erase = nand_erase_4750; |
406 | nand_read = nand_read_4750; |
407 | nand_read_oob = nand_read_oob_4750; |
408 | nand_read_raw = nand_read_raw_4750; |
409 | nand_query = nand_query_4750; |
410 | nand_enable = nand_enable_4750; |
411 | nand_disable = nand_disable_4750; |
412 | nand_mark_bad = nand_mark_bad_4750; |
413 | break; |
414 | default: |
415 | serial_puts("Not support CPU ID!"); |
416 | } |
417 | } |
418 | |
419 | int CONFIGRATION_Handle(u8 *buf) |
420 | { |
421 | USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf; |
422 | switch ((dreq->wValue)&0xf) |
423 | { |
424 | case DS_flash_info: |
425 | dprintf("\n configration :DS_flash_info_t!"); |
426 | config_flash_info(); |
427 | break; |
428 | |
429 | case DS_hand: |
430 | dprintf("\n configration :DS_hand_t!"); |
431 | config_hand(); |
432 | break; |
433 | default:; |
434 | } |
435 | Borad_Init(); |
436 | return ERR_OK; |
437 | } |
438 | |
439 | |
440 |