Root/usbboot/xburst_stage2/boothandler.c

1/*
2 * USB_BOOT Handle routines
3 *
4 * Copyright (C) 2009 Qi Hardware Inc.,
5 * Author: Xiangfu Liu <xiangfu@sharism.cc>
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 "target/jz4740.h"
23#include "target/error.h"
24#include "target/usb_boot.h"
25#include "usb_boot_defines.h"
26#include "target/nandflash.h"
27#include "usb/udc.h"
28#include "usb/usb.h"
29
30#define dprintf(x) serial_puts(x)
31
32unsigned int (*nand_query)(u8 *);
33int (*nand_init)(int bus_width, int row_cycle, int page_size, int page_per_block,
34         int,int,int,int);
35int (*nand_fini)(void);
36u32 (*nand_program)(void *context, int spage, int pages,int option);
37u32 (*nand_erase)(int blk_num, int sblk, int force);
38u32 (*nand_read)(void *buf, u32 startpage, u32 pagenum,int option);
39u32 (*nand_read_oob)(void *buf, u32 startpage, u32 pagenum);
40u32 (*nand_read_raw)(void *buf, u32 startpage, u32 pagenum,int);
41u32 (*nand_mark_bad) (int bad);
42void (*nand_enable) (unsigned int csn);
43void (*nand_disable) (unsigned int csn);
44
45struct hand Hand;
46extern u32 Bulk_out_buf[BULK_OUT_BUF_SIZE];
47extern u32 Bulk_in_buf[BULK_IN_BUF_SIZE];
48extern u16 handshake_PKT[4];
49extern udc_state;
50extern void *memset(void *s, int c, size_t count);
51extern void *memcpy(void *dest, const void *src, size_t count);
52
53u32 ret_dat;
54u32 start_addr; /* program operation start address or sector */
55u32 ops_length; /* number of operation unit ,in byte or sector */
56u32 ram_addr;
57
58void dump_data(unsigned int *p, int size)
59{
60    int i;
61    for(i = 0; i < size; i ++)
62        serial_put_hex(*p++);
63}
64
65void config_flash_info()
66{
67}
68
69void config_hand()
70{
71    memcpy(&Hand, (unsigned char *)Bulk_out_buf, sizeof(struct hand));
72}
73
74int GET_CPU_INFO_Handle()
75{
76    dprintf("\n GET_CPU_INFO:\t");
77    serial_put_hex(Hand.fw_args.cpu_id);
78    switch (Hand.fw_args.cpu_id) {
79    case 0x4760:
80        HW_SendPKT(0, "Boot4760", 8);
81        break;
82    case 0x4740:
83        HW_SendPKT(0, "Boot4740", 8);
84        break;
85    default:
86        HW_SendPKT(0, " UNKNOW ", 8);
87        break;
88    }
89    udc_state = IDLE;
90    return ERR_OK;
91}
92           
93int SET_DATA_ADDERSS_Handle(u8 *buf)
94{
95    USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
96    start_addr=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex;
97    dprintf("\n SET ADDRESS:\t");
98    serial_put_hex(start_addr);
99    return ERR_OK;
100}
101        
102int SET_DATA_LENGTH_Handle(u8 *buf)
103{
104    USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
105    ops_length=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex;
106    dprintf("\n DATA_LENGTH:\t");
107    serial_put_hex(ops_length);
108    return ERR_OK;
109}
110
111int FLUSH_CACHES_Handle()
112{
113    return ERR_OK;
114}
115    
116int PROGRAM_START1_Handle(u8 *buf)
117{
118    USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
119    ram_addr=(((u32)dreq->wValue)<<16)+(u32)dreq->wIndex;
120    return ERR_OK;
121}
122
123int PROGRAM_START2_Handle(u8 *buf)
124{
125    void (*f)(void);
126    USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
127    f=(void *) ((((u32)dreq->wValue)<<16)+(u32)dreq->wIndex);
128    __dcache_writeback_all();
129    /* stop udc connet before execute program! */
130    jz_writeb(USB_REG_POWER,0x0); /* High speed */
131
132    f();
133    return ERR_OK;
134}
135          
136int NOR_OPS_Handle(u8 *buf)
137{
138    USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
139    return ERR_OK;
140}
141
142int NAND_OPS_Handle(u8 *buf)
143{
144    USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
145    u32 temp;
146    int option;
147    u8 CSn;
148
149    CSn = (dreq->wValue>>4) & 0xff;
150    option = (dreq->wValue>>12) & 0xff;
151    nand_enable(CSn);
152    switch ((dreq->wValue)&0xf)
153    {
154    case NAND_QUERY:
155        dprintf("\n Request : NAND_QUERY!");
156        nand_query((u8 *)Bulk_in_buf);
157        HW_SendPKT(1, Bulk_in_buf, 8);
158        handshake_PKT[3]=(u16)ERR_OK;
159        udc_state = BULK_IN;
160        break;
161    case NAND_INIT:
162        dprintf("\n Request : NAND_INIT!");
163
164        break;
165    case NAND_MARK_BAD:
166        dprintf("\n Request : NAND_MARK_BAD!");
167        ret_dat = nand_mark_bad(start_addr);
168        handshake_PKT[0] = (u16) ret_dat;
169        handshake_PKT[1] = (u16) (ret_dat>>16);
170        HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
171        udc_state = IDLE;
172
173        break;
174    case NAND_READ_OOB:
175        dprintf("\n Request : NAND_READ_OOB!");
176        memset(Bulk_in_buf,0,ops_length*Hand.nand_ps);
177        ret_dat = nand_read_oob(Bulk_in_buf,start_addr,ops_length);
178        handshake_PKT[0] = (u16) ret_dat;
179        handshake_PKT[1] = (u16) (ret_dat>>16);
180        HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
181        udc_state = BULK_IN;
182        break;
183    case NAND_READ_RAW:
184        dprintf("\n Request : NAND_READ_RAW!");
185        switch (option)
186        {
187        case OOB_ECC:
188            nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
189            HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
190            handshake_PKT[0] = (u16) ret_dat;
191            handshake_PKT[1] = (u16) (ret_dat>>16);
192            udc_state = BULK_IN;
193            break;
194        default:
195            nand_read_raw(Bulk_in_buf,start_addr,ops_length,option);
196            HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
197            handshake_PKT[0] = (u16) ret_dat;
198            handshake_PKT[1] = (u16) (ret_dat>>16);
199            udc_state = BULK_IN;
200            break;
201        }
202        break;
203    case NAND_ERASE:
204        dprintf("\n Request : NAND_ERASE");
205        ret_dat = nand_erase(ops_length,start_addr,
206               Hand.nand_force_erase);
207        handshake_PKT[0] = (u16) ret_dat;
208        handshake_PKT[1] = (u16) (ret_dat>>16);
209        HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
210        udc_state = IDLE;
211        dprintf(" ... finished.");
212        break;
213    case NAND_READ:
214        dprintf("\n Request : NAND_READ!");
215        switch (option) {
216        case OOB_ECC:
217            ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_ECC);
218            handshake_PKT[0] = (u16) ret_dat;
219            handshake_PKT[1] = (u16) (ret_dat>>16);
220            HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os ));
221            udc_state = BULK_IN;
222            break;
223        case OOB_NO_ECC:
224            ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,OOB_NO_ECC);
225            handshake_PKT[0] = (u16) ret_dat;
226            handshake_PKT[1] = (u16) (ret_dat>>16);
227            HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*(Hand.nand_ps + Hand.nand_os));
228            udc_state = BULK_IN;
229            break;
230        case NO_OOB:
231            ret_dat = nand_read(Bulk_in_buf,start_addr,ops_length,NO_OOB);
232            handshake_PKT[0] = (u16) ret_dat;
233            handshake_PKT[1] = (u16) (ret_dat>>16);
234            HW_SendPKT(1,(u8 *)Bulk_in_buf,ops_length*Hand.nand_ps);
235            udc_state = BULK_IN;
236            break;
237        }
238        dprintf(" ... finished.");
239        break;
240    case NAND_PROGRAM:
241        dprintf("\n Request : NAND_PROGRAM!");
242        ret_dat = nand_program((void *)Bulk_out_buf,
243                 start_addr,ops_length,option);
244        handshake_PKT[0] = (u16) ret_dat;
245        handshake_PKT[1] = (u16) (ret_dat>>16);
246        HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
247        udc_state = IDLE;
248        dprintf(" ... finished.");
249        break;
250    case NAND_READ_TO_RAM:
251        dprintf("\n Request : NAND_READ_TO_RAM!");
252        nand_read((u8 *)ram_addr,start_addr,ops_length,NO_OOB);
253        __dcache_writeback_all();
254        handshake_PKT[3]=(u16)ERR_OK;
255        HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
256        udc_state = IDLE;
257        break;
258    default:
259        nand_disable(CSn);
260        return ERR_OPS_NOTSUPPORT;
261    }
262
263    return ERR_OK;
264}
265
266int SDRAM_OPS_Handle(u8 *buf)
267{
268    USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
269    u32 temp,i;
270    u8 *obj;
271
272    switch ((dreq->wValue)&0xf)
273    {
274    case SDRAM_LOAD:
275        ret_dat = (u32)memcpy((u8 *)start_addr,Bulk_out_buf,ops_length);
276        handshake_PKT[0] = (u16) ret_dat;
277        handshake_PKT[1] = (u16) (ret_dat>>16);
278        HW_SendPKT(1,handshake_PKT,sizeof(handshake_PKT));
279        udc_state = IDLE;
280        break;
281    }
282    return ERR_OK;
283}
284
285void Board_Init()
286{
287    dprintf("\n Board_init! ");
288    serial_put_hex(Hand.fw_args.cpu_id);
289    switch (Hand.fw_args.cpu_id)
290    {
291    case 0x4740:
292        nand_init_4740(Hand.nand_bw, Hand.nand_rc, Hand.nand_ps,
293                   Hand.nand_ppb, Hand.nand_bbpage, Hand.nand_bbpos,
294                   Hand.nand_force_erase, Hand.nand_eccpos);
295    
296        nand_program = nand_program_4740;
297        nand_erase = nand_erase_4740;
298        nand_read = nand_read_4740;
299        nand_read_oob = nand_read_oob_4740;
300        nand_read_raw = nand_read_raw_4740;
301        nand_query = nand_query_4740;
302        nand_enable = nand_enable_4740;
303        nand_disable = nand_disable_4740;
304        nand_mark_bad = nand_mark_bad_4740;
305        break;
306    case 0x4760:
307        nand_init_4760(Hand.nand_bw, Hand.nand_rc, Hand.nand_ps,
308                   Hand.nand_ppb, Hand.nand_bchbit, Hand.nand_eccpos,
309                   Hand.nand_bbpos, Hand.nand_bbpage, Hand.nand_force_erase);
310
311        nand_program=nand_program_4760;
312        nand_erase =nand_erase_4760;
313        nand_read =nand_read_4760;
314        nand_read_oob=nand_read_oob_4760;
315        nand_read_raw=nand_read_raw_4760;
316        nand_query = nand_query_4760;
317        nand_enable = nand_enable_4760;
318        nand_disable= nand_disable_4760;
319        nand_mark_bad = nand_mark_bad_4760;
320        break;
321    default:
322        serial_puts("\n Not support CPU ID!");
323    }
324}
325
326int CONFIGRATION_Handle(u8 *buf)
327{
328    dprintf("\n Configuration:\t");
329
330    USB_DeviceRequest *dreq = (USB_DeviceRequest *)buf;
331    switch ((dreq->wValue)&0xf) {
332    case DS_flash_info:
333        dprintf("DS_flash_info_t!");
334        config_flash_info();
335        break;
336
337    case DS_hand:
338        dprintf("DS_hand_t!");
339        config_hand();
340        break;
341    default:
342        ;
343    }
344
345    Board_Init();
346    return ERR_OK;
347}
348
349
350int RESET_Handle(u8 *buf)
351{
352    dprintf("\n RESET Device");
353    __wdt_select_extalclk();
354    __wdt_select_clk_div64();
355    __wdt_set_data(100);
356    __wdt_set_count(0);
357    __tcu_start_wdt_clock();
358    __wdt_start();
359    while(1);
360}
361

Archive Download this file



interactive