blob: 40244f2022c6cd639e4d6fbd6011566819799287 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/*******************************************************************************
2* °æÈ¨ËùÓÐ (C)2010, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
3*
4* ÎļþÃû³Æ£º sdio.c
5* ÄÚÈÝÕªÒª£º
6* ÆäËü˵Ã÷£º
7* µ±Ç°°æ±¾£º 1.0
8* ×÷¡¡¡¡Õߣºcaidaofang
9* Íê³ÉÈÕÆÚ£º
10*
11*
12*******************************************************************************/
13
14#include <common.h>
15#include <errno.h>
16#include <command.h>
17#include <malloc.h>
18#include <jffs2/load_kernel.h>
19#include <linux/list.h>
20#include <linux/ctype.h>
21#include <linux/err.h>
22#include <linux/mtd/mtd.h>
23#include <load_image.h>
24#include <linux/byteorder/generic.h>
25#include <sdio.h>
26#include <image.h>
27#include <config.h>
28
29
30#define CFG_TEMP_ADDR 0x22000000
31
32#define CFG_SDIO_SLAVE_PACKAGE_LEN 0xD800 /* K */
33#define CFG_SDIO_SLAVE_ALIGN_LEN 0x200 /* 512byte */
34
35
36
37#define SYS_STD_CRM_BASE 0x1307000
38#define DMA_BUFFER_SIZE_16K (0x2<<1)
39
40#define DMA_BUFFER_SIZE_32K (0x3<<1)
41#define DMA_BUFFER_SIZE_64K (0x4<<1)
42
43#define DMA_BUFFER_SIZE_256K (0x6<<1)
44#define DMA_BUFFER_SIZE_512K (0x7<<1)
45#define SDIO_ERR -1
46#define SDIO_INPROGRESS -2
47
48static void usdelay(uint32_t delay)
49{
50 uint32_t i = 0;
51 for( ; i<delay*200; i++ );
52}
53
54static void sdio_clk_reset(void)
55{
56// enable sdio clk 16,17 hclk
57 REG32(SYS_STD_CRM_BASE+0x44) |= (0x3<<16);
58 usdelay(80);
59// release reset sdio clk 16 ahb clk
60 REG32(SYS_STD_CRM_BASE+0x48) |= (0x1<<16);
61 usdelay(80);
62}
63
64/*²ÉÓÃCPU¶ÁÈ¡FIFO£¬½ûÖ¹ÖжÏ*/
65static void sdio_initial_setup(void)
66{
67 u32 val = 0;
68 // REG32(SDIO_SLAVE_IOREADY) |= 0x3e;//ÅäÖÃ1-5bit
69
70 REG32(SDIO_SLAVE_INTSTATUS_EN) = 0; //mask sdio int
71 REG32(SDIO_SLAVE_INTSTATUS) = 0xffffffff;//clear int
72
73 REG32(SDIO_SLAVE_INTSTATUS_EN) = 0xffffffff; //enable status int
74
75 //REG32(SDIO_SLAVE_INTSTATUS_EN) = 0x33C0181B; //enable status int
76 REG32(SDIO_SLAVE_INTSIGNAL_EN) = 0; //maskedÖжÏÐźÅ1£¬²»Éϱ¨¸øÖжϿØÖÆÆ÷
77 REG32(SDIO_SLAVE_INT_SIGNAL_EN2) = 0; //maskedÖжÏÐźÅ2£¬²»Éϱ¨¸øÖжϿØÖÆÆ÷
78 // val = REG32(SDIO_SLAVE_SDIO_CCCR_CTRL);
79 /* REG32(SDIO_SLAVE_SDIO_CCCR_CTRL) = 0x3FF3E343;
80
81 REG32(0x1307080)= 0x7ffe0;
82
83 memset((u8*)0x20000000,0,1024*180);
84
85 val = REG32(SDIO_SLAVE_CARD_OCR);
86
87 REG32(SDIO_SLAVE_CARD_OCR) = val|0x01000000; */
88
89/*dma*/
90 /*dma1 address register config*/
91 // REG32(SDIO_SLAVE_DMA1ADDR) = CFG_SDIO_LOAD_BASE; //set dma address
92 /*adma/dma1 address register and buffer size is 0:not valid 1:valid,buffer size is 4K(default)*/
93 // REG32(SDIO_SLAVE_DMA1CTRL) |=0x1|DMA_BUFFER_SIZE_256K; //enable dma address
94 /*disable adma£¬enable dma ,sel one*/
95
96 /*REG32(SDIO_SLAVE_CTRL2) &=(~0x4); */
97
98/*sdio slave config ready operate*/
99 // REG32(SDIO_SLAVE_CTRL) |=0x4; //ÅäÖõÚ2bit£¬±íʾ׼±¸²Ù×÷
100
101
102
103}
104
105int Sdio_Slave_Read_32K(const u32 load_addr,u32 len)
106{
107 u32 status =0 ;
108 int ret = 0;
109
110 u32 dma_addr = (u32)CFG_SDIO_LOAD_BASE;
111
112 REG32(SDIO_SLAVE_DMA1ADDR) = CFG_SDIO_LOAD_BASE; //CFG_SDIO_LOAD_BASE;
113 REG32(SDIO_SLAVE_DMA1CTRL) |= 0x1|DMA_BUFFER_SIZE_32K; //|DMA_BUFFER_SIZE_512K; //256K
114
115 while(1)
116 {
117 status = REG32(SDIO_SLAVE_INTSTATUS);
118
119 if((status &SDIO_STS_DMA1)!=0)
120 {
121
122 dma_addr += 0x8000;
123 /*1,mask*/
124 REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_DMA1);
125 /*2,clear*/
126
127 REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_DMA1;
128 /*3,enalbe*/
129 REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_DMA1;
130
131 REG32(SDIO_SLAVE_DMA1ADDR) = dma_addr ;//CFG_SDIO_LOAD_BASE;
132 REG32(SDIO_SLAVE_DMA1CTRL) |= 0x1|DMA_BUFFER_SIZE_32K;
133
134 }
135
136
137 if((status &SDIO_STS_TC)!=0)
138 {
139 // printf("SDIO xfer OK!\n");
140 break;
141 }
142
143 if((status &SDIO_STS_F_CRC_E)!=0)
144 {
145 printf("SDIO CRC Error!\n");
146
147 /*1,mask*/
148 REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_CRC_E);
149 /*2,clear*/
150 REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_CRC_E;
151 /*3,enalbe*/
152 REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_CRC_E;
153
154 ret = SDIO_ERR;
155 }
156
157 if((status &SDIO_STS_F_A)!=0)
158 {
159
160 /*1,mask*/
161 REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_A);
162 /*2,clear*/
163 //status = REG32(SDIO_SLAVE_INTSTATUS);
164 REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_A;
165 /*3,enalbe*/
166 REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_A;
167
168
169 printf("SDIO ABORT Xfer!\n");
170
171 }
172
173
174 }
175/*thansfer complete,write program done*/
176 REG32(SDIO_SLAVE_CTRL) |= 0x1;
177/*clear int status*/
178 /*1,mask*/
179 // REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~(SDIO_STS_TC|SDIO_STS_WS|SDIO_STS_DMA1|SDIO_STS_F_A|SDIO_STS_F_CRC_E));
180
181 REG32(SDIO_SLAVE_INTSTATUS_EN) = 0;
182 /*2,clear*/
183 status = REG32(SDIO_SLAVE_INTSTATUS);
184 REG32(SDIO_SLAVE_INTSTATUS) = status;
185 /*3,enalbe*/
186 REG32(SDIO_SLAVE_INTSTATUS_EN) = 0xffffffff;
187
188 /*thansfer complete,write program done*/
189 // REG32(SDIO_SLAVE_CTRL) |= 0x1;
190
191 // REG32(SDIO_SLAVE_INTSTATUS_EN) = 0x33C0181B; //enable status int;
192 memcpy(load_addr,(u32)CFG_SDIO_LOAD_BASE,len);
193
194
195 return ret;
196}
197
198int Sdio_Slave_Write_Ack(void)
199{
200
201
202 u32 status = 0;
203 int ret = 0;
204
205 // u32 ack[2] = {0x11223344,0xAABBCCDD};
206
207 char *ack ="rxok";
208
209 memcpy((u32)CFG_SDIO_LOAD_BASE,ack,4);
210
211 printf("SDIO write ack\n");
212
213 REG32(SDIO_SLAVE_DMA1ADDR) = CFG_SDIO_LOAD_BASE;
214 REG32(SDIO_SLAVE_DMA1CTRL) |= 0x1;
215
216 while(1)
217 {
218 status = REG32(SDIO_SLAVE_INTSTATUS);
219
220
221 if((status &SDIO_STS_TC)!=0)
222 {
223 // printf("SDIO xfer OK!\n");
224 break;
225 }
226
227 if((status &SDIO_STS_F_CRC_E)!=0)
228 {
229 printf("SDIO CRC Error!\n");
230
231 /*1,mask*/
232 REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_CRC_E);
233 /*2,clear*/
234 REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_CRC_E;
235 /*3,enalbe*/
236 REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_CRC_E;
237
238 ret = SDIO_ERR;
239 }
240
241 if((status &SDIO_STS_F_A)!=0)
242 {
243
244 /*1,mask*/
245 REG32(SDIO_SLAVE_INTSTATUS_EN)&=(~SDIO_STS_F_A);
246 /*2,clear*/
247 //status = REG32(SDIO_SLAVE_INTSTATUS);
248 REG32(SDIO_SLAVE_INTSTATUS) |= SDIO_STS_F_A;
249 /*3,enalbe*/
250 REG32(SDIO_SLAVE_INTSTATUS_EN) |= SDIO_STS_F_A;
251
252
253 printf("SDIO ABORT Xfer!\n");
254
255 }
256
257
258 }
259/*thansfer complete,write program done*/
260 // REG32(SDIO_SLAVE_CTRL) |= 0x1;
261/*clear int status*/
262 /*1,mask*/
263
264 REG32(SDIO_SLAVE_INTSTATUS_EN) = 0;
265 /*2,clear*/
266 status = REG32(SDIO_SLAVE_INTSTATUS);
267 REG32(SDIO_SLAVE_INTSTATUS) = status;
268 /*3,enalbe*/
269 REG32(SDIO_SLAVE_INTSTATUS_EN) = 0xffffffff;
270
271 return ret;
272
273}
274
275static int sdio_slave_init(void)
276{
277
278 // SDIOÉèÖÃCPRMÄ£¿éµÄ´úÂë
279 // sdio_clk_reset();
280
281 // Initialize controller
282 sdio_initial_setup();
283
284 return 0;
285}
286
287static int slave_size = 0;
288
289/************** success :return boot size ***********/
290int sdio_slave_read(const u32 load_addr)
291{
292 u32 dwInt_status = 0;
293 u32 dwCurrent_Cmd = 0;
294 u32 cmdreg =0;
295 u32 argreg = 0;
296 u32 cmd = 0;
297 u32 blksize = 0;
298 u32 blkcnt = 0;
299 u32 boot_size = 0;
300
301 int ret = SDIO_INPROGRESS;
302
303 while(1)
304 {
305 // dwCurrent_CmdΪ53ʱ£¬½øÐÐÊý¾Ýдor¶Á²Ù×÷
306
307 dwCurrent_Cmd = ((REG32(SDIO_SLAVE_CMD)>>13) & 0x3F);
308
309 switch(dwCurrent_Cmd)
310 {
311 case SDIO_CMD53:
312 {
313
314 dwInt_status = REG32(SDIO_SLAVE_INTSTATUS);
315
316
317 if((dwInt_status & SDIO_STS_WS) == SDIO_STS_WS)
318 {
319 cmdreg = REG32(SDIO_SLAVE_CMD);
320 argreg = REG32(SDIO_SLAVE_ARGU);
321
322 blksize = (cmdreg >>1) &0xFFF;
323
324 blkcnt = argreg & 0x1FF;
325
326 if(!(argreg & 0x08000000))
327 {
328
329 boot_size =blksize;
330 }
331 else
332 {
333 boot_size =blkcnt * blksize;
334 }
335
336 slave_size = boot_size;
337
338
339 ret = Sdio_Slave_Read_32K(load_addr,boot_size);
340
341 if(!ret)
342 return boot_size;
343 else //if(ret == SDIO_ERR)
344 return SDIO_ERR;
345
346 }
347
348 break;
349 }
350 default:
351 break;
352 }
353
354 }
355
356 return boot_size;
357}
358
359int sdio_slave_write(void)
360{
361
362
363 u32 dwInt_status = 0;
364 u32 dwCurrent_Cmd = 0;
365 u32 cmdreg =0;
366 u32 argreg = 0;
367 u32 cmd = 0;
368 u32 blksize = 0;
369 u32 blkcnt = 0;
370 u32 boot_size = 0;
371
372 int ret = SDIO_INPROGRESS;
373
374
375 REG32(SDIO_SLAVE_FUN1CTRL) |= (0x4 & 0xFFFF);
376
377 while(1)
378 {
379 dwCurrent_Cmd = ((REG32(SDIO_SLAVE_CMD)>>13) & 0x3F);
380
381 switch(dwCurrent_Cmd)
382 {
383 case SDIO_CMD53:
384 {
385
386 dwInt_status = REG32(SDIO_SLAVE_INTSTATUS);
387
388
389 if((dwInt_status & SDIO_STS_RS) == SDIO_STS_RS)
390 {
391 cmdreg = REG32(SDIO_SLAVE_CMD);
392 argreg = REG32(SDIO_SLAVE_ARGU);
393
394 blksize = (cmdreg >>1) &0xFFF;
395
396 blkcnt = argreg & 0x1FF;
397
398 if(!(argreg & 0x08000000))
399 {
400
401 boot_size =blksize;
402 }
403 else
404 {
405 boot_size =blkcnt * blksize;
406 }
407
408
409 ret = Sdio_Slave_Write_Ack();
410
411 if(!ret)
412 return boot_size;
413 else //if(ret == SDIO_ERR)
414 return SDIO_ERR;
415
416 }
417
418 break;
419 }
420 default:
421 break;
422 }
423
424
425 }
426
427 return boot_size;
428
429}
430
431
432/*******************************************************************************
433 * Function:
434 * Description:
435 * Parameters:
436 * Input:
437 *
438 * Output:
439 *
440 * Returns:
441 *
442 *
443 * Others:
444 ********************************************************************************/
445int sdio_slave_read_bin()
446{
447 int32_t len = 0;
448 uint32_t i =0;
449
450 /*1.µÚÒ»´Î½ÓÊÕ */
451 len = sdio_slave_read((u32)CFG_TEMP_ADDR);
452 if( len < 0 )
453 {
454 printf("sdio_slave: read first error\n");
455 goto sdio_error1;
456 }
457
458 /*2.»ñÈ¡°æ±¾ÐÅÏ¢ */
459 image_header_t *header = NULL;
460 header = (image_header_t *)CFG_TEMP_ADDR;
461 uint32_t header_size = sizeof(image_header_t);
462 uint32_t size = ___htonl(header->ih_size);
463 uint32_t load_addr = ___htonl(header->ih_load);
464 uint32_t entry_point = ___htonl(header->ih_ep);
465
466 printf("size = %d\n", (int)size);
467 printf("load_addr = 0x%0x\n", (unsigned int)load_addr);
468 printf("entry_point = 0x%0x\n", (unsigned int)entry_point);
469
470
471 /*3.¿½±´µÚÒ»´ÎÊý¾Ý */
472 memcpy(load_addr, CFG_TEMP_ADDR+sizeof(image_header_t), len);
473 load_addr = load_addr + len - header_size;
474
475 /*4.¼ÆËã´«Êä´ÎÊý */
476 /* Èç¹ûµÚÒ»´Î´«ÊäµÄ×Ö½Ú´óÓÚ»òµÈÓÚ°æ±¾µÄ´óС£¬Ôò´«ÊäÍê³ÉÖ±½Ó·µ»Ø */
477 if( (len > size) || (len == size) )
478 {
479 printf("sdio_slave: first finsh and return\n");
480 return 0;
481 }
482
483 uint32_t left_times = size/CFG_SDIO_SLAVE_PACKAGE_LEN;
484 uint32_t mod = size%CFG_SDIO_SLAVE_PACKAGE_LEN;
485 if( mod == 0 )
486 {
487 left_times--;
488 }
489
490 /* debug */
491 printf("sdio_slave: times = %d\n", (int)(left_times+1));
492
493
494
495 /*5.½ÓÊÕÆäÓàµÄÊý¾Ý */
496 for( i=0; i<(left_times); i++ )
497 {
498 //printf("sdio_slave: load_addr = 0x%0x\n",load_addr);
499 len = sdio_slave_read(load_addr);
500 if( len < 0 )
501 {
502 printf("sdio_slave: read others error\n");
503 goto sdio_error1;
504 }
505 load_addr += len;
506 }
507
508 return 0;
509 sdio_error1:
510 return -1;
511}
512
513/*******************************************************************************
514 * Function:
515 * Description:
516 * Parameters:
517 * Input:
518 *
519 * Output:
520 *
521 * Returns:
522 *
523 *
524 * Others:
525 ********************************************************************************/
526void sdio_slave_process(void)
527{
528 int ret = 0;
529
530 //sdio_slave_init();
531
532
533/* 1. ½ÓÊÕ */
534 ret = sdio_slave_read_bin();
535 if( ret != 0 )
536 {
537 printf("sdio_slave: read big bin error\n");
538 goto wait_error;
539 }
540
541 ret = sdio_slave_write();
542 if(ret > 0)
543 {
544
545 printf("sdio_slave: write ack success\n");
546 }
547
548
549 printf("sdio_slave: read big bin OK\n");
550
551 while(1);
552
553wait_error:
554 printf("sdio_slave: error wait\n");
555 while(1);
556}
557