1 /*********************************************************************
\r
2 ** File Name: sdio_phy.c
\r
3 ** Author: yanping.xie
\r
5 ** Copyright: 2004 Spreadtrum, Incoporated. All Rights Reserved.
\r
6 ** Description: This file describe operation of sdio host.
\r
7 *********************************************************************
\r
9 *********************************************************************
\r
11 ** ------------------------------------------------------------------------- **
\r
12 ** DATE NAME DESCRIPTION
\r
13 ** 09/05/2013 ypxie Create.
\r
14 ********************************************************************/
\r
16 #include "sdio_reg.h"
\r
17 #include "sdio_phy.h"
\r
19 PUBLIC void sdhost_delayus(uint32 usec)
\r
22 /* current is 800MHZ, when usec =1, the mean is delay 1 us */
\r
23 for (i = 0; i < (usec << 1); i++);
\r
26 PUBLIC uint32 sdhost_get_pin_state (sdio_reg_ptr p_cfg)
\r
28 return p_cfg->pres_state;
\r
31 /*********************************************************************
\r
33 ** This function used to enable pause function of host.
\r
35 ** p_cfg : sdio control reg.
\r
38 ** Date Author Operation
\r
39 ** 2013/09/05 ypxie create
\r
40 *********************************************************************/
\r
41 PUBLIC void sdhost_read_wait_ctl_en (sdio_reg_ptr p_cfg)
\r
43 p_cfg->sd_ctrl1 |= BIT_18;
\r
46 /*********************************************************************
\r
48 ** This function used to set break point the transmition.
\r
50 ** sdhost_handler : sdio control reg.
\r
53 ** Date Author Operation
\r
54 ** 2013/09/05 ypxie create
\r
55 *********************************************************************/
\r
56 PUBLIC void sdhost_stop_at_blk_gap_req (sdio_reg_ptr p_cfg)
\r
58 p_cfg->sd_ctrl1 |= BIT_16;
\r
61 PUBLIC void sdhost_clear_at_blk_gap_req (sdio_reg_ptr p_cfg)
\r
63 p_cfg->sd_ctrl1 &= ~BIT_16;
\r
66 PUBLIC void sdhost_blk_gap_int_en(sdio_reg_ptr p_cfg)
\r
68 p_cfg->sd_ctrl1 |= BIT_19;
\r
71 PUBLIC uint32 sdhost_get_transfer_status(sdio_reg_ptr p_cfg)
\r
73 return (p_cfg->pres_state & (BIT_8|BIT_9));
\r
76 /*********************************************************************
\r
78 ** This function used to when transmission is paused ,this function can resume the
\r
81 ** p_cfg : sdio control reg.
\r
84 ** Date Author Operation
\r
85 ** 2013/09/05 ypxie create
\r
86 *********************************************************************/
\r
87 PUBLIC void sdhost_continue(sdio_reg_ptr p_cfg)
\r
89 p_cfg->sd_ctrl1 &= ~(BIT_16 | BIT_17);
\r
90 p_cfg->sd_ctrl1 |= BIT_17;
\r
93 /*********************************************************************
\r
95 ** This function used to set controller bus width.
\r
97 ** p_cfg : sdio control reg.
\r
98 ** width : data bus width,only 1bit ,4bit and 8bit canbe used.
\r
101 ** Date Author Operation
\r
102 ** 2013/09/05 ypxie create
\r
103 *********************************************************************/
\r
104 PUBLIC void sdhost_set_bus_width_v20(sdio_reg_ptr p_cfg, sdio_buswidth_e width)
\r
107 tmp_reg = p_cfg->sd_ctrl1;
\r
112 case SDIO_BUS_4_BIT:
\r
116 case SDIO_BUS_1_BIT:
\r
121 p_cfg->sd_ctrl1 = tmp_reg;
\r
122 } /* end of sdhost_set_bus_width */
\r
124 PUBLIC void sdhost_set_bus_width_v30(sdio_reg_ptr p_cfg, sdio_buswidth_e width)
\r
127 sdio_reg_v30_ptr p_tmp_cfg;
\r
129 p_tmp_cfg = (sdio_reg_v30_ptr) p_cfg;
\r
131 tmp_reg = p_tmp_cfg->sd_ctrl1;
\r
137 case SDIO_BUS_4_BIT:
\r
141 case SDIO_BUS_8_BIT:
\r
145 case SDIO_BUS_1_BIT:
\r
150 p_tmp_cfg->sd_ctrl1 = tmp_reg;
\r
151 } /* end of sdhost_set_bus_width */
\r
153 /*********************************************************************
\r
155 ** This function used to set controller speed mode.
\r
157 ** p_cfg : sdio control reg.
\r
158 ** speed : data bus width, only sdr13, sdr26, sdr52, ddr52, hs200 used.
\r
161 ** Date Author Operation
\r
162 ** 2013/09/05 ypxie create
\r
163 *********************************************************************/
\r
164 PUBLIC void sdhost_set_speed_mode_v20 (sdio_reg_ptr p_cfg, sdio_speedmode_e speed_mode)
\r
168 tmp_reg = p_cfg->sd_ctrl1;
\r
171 switch (speed_mode) {
\r
172 case SDIO_HIGHSPEED:
\r
176 case SDIO_LOWSPEED:
\r
181 p_cfg->sd_ctrl1 = tmp_reg;
\r
182 } /* end of sdhost_set_speed_mode */
\r
184 PUBLIC void sdhost_set_speed_mode_v30 (sdio_reg_ptr p_cfg, sdio_speedmode_e speed_mode)
\r
187 sdio_reg_v30_ptr p_tmp_cfg;
\r
189 p_tmp_cfg = (sdio_reg_v30_ptr) p_cfg;
\r
191 /* clear high speed bit in controller version3.0. */
\r
192 p_tmp_cfg->sd_ctrl1 &= ~BIT_2;
\r
194 tmp_reg = p_tmp_cfg->sd_ctrl3;
\r
195 tmp_reg &= ~( BIT_16 | BIT_17 | BIT_18 );
\r
197 switch (speed_mode) {
\r
199 case SDIO_HIGHSPEED:
\r
209 tmp_reg |= (BIT_16 | BIT_17);
\r
217 case SDIO_LOWSPEED:
\r
222 p_tmp_cfg->sd_ctrl3 = tmp_reg;
\r
223 } /* end of sdhost_set_speed_mode */
\r
225 /*********************************************************************
\r
227 ** This function used to set internal clock on or off and wait set over.
\r
229 ** p_cfg : sdio control reg.
\r
230 ** onoff : enable or disable.
\r
233 ** Date Author Operation
\r
234 ** 2013/09/05 ypxie create
\r
235 *********************************************************************/
\r
236 PUBLIC void sdhost_set_internal_clk (sdio_reg_ptr p_cfg, sdio_onoff_e onoff)
\r
238 uint32 timeout, chk_val;
\r
242 /* Enable internal clock */
\r
243 p_cfg->sd_ctrl2 |= BIT_0;
\r
249 p_cfg->sd_ctrl2 &= (~BIT_0);
\r
254 /* wait set over for bit_1 */
\r
256 while ((chk_val == (p_cfg->sd_ctrl2 & BIT_1)) && timeout) {
\r
257 sdhost_delayus(50);
\r
260 } /* end of sdhost_set_internal_clk */
\r
262 /*********************************************************************
\r
264 ** This function used to set sd clock on or off and wait set over.
\r
266 ** p_cfg : sdio control reg.
\r
267 ** onoff : enable or disable.
\r
270 ** Date Author Operation
\r
271 ** 2013/09/05 ypxie create
\r
272 *********************************************************************/
\r
273 PUBLIC void sdhost_set_sd_clk (sdio_reg_ptr p_cfg, sdio_onoff_e onoff)
\r
277 /* Enable internal clock */
\r
278 p_cfg->sd_ctrl2 |= BIT_2;
\r
283 if ((p_cfg->sd_ctrl2 & BIT_2) != 0) {
\r
284 p_cfg->sd_ctrl2 &= ~BIT_2;
\r
286 /* used to wait two clocks for clear glitch in clk line. */
\r
287 SDHOST_Delayus(200);
\r
292 } /* end of sdhost_set_sd_clk */
\r
294 /*********************************************************************
296 ** This function used to set sd clock.
298 ** p_cfg : sdio control reg.
\r
299 ** base_clk : base clock.
\r
300 ** clk : want sdio controller runing clock.
\r
303 ** Date Author Operation
304 ** 2013/09/05 ypxie create
\r
305 *********************************************************************/
306 PUBLIC uint32 sdhost_set_clk_freq_v20 (sdio_reg_ptr p_cfg, uint32 base_clk, uint32 clk)
\r
308 volatile uint32 tmp_reg;
\r
309 uint32 clk_div, sd_clk, i;
\r
311 /* SDCLK Frequency Select ,Configure SDCLK select */
312 clk_div = base_clk / clk;
\r
313 if (0 != base_clk % clk) {
\r
317 tmp_reg = p_cfg->sd_ctrl2;
\r
318 tmp_reg &= ~(0xff<<8);
\r
320 for (i = 0; i < 8; i++) {
\r
321 if (((clk_div > (1 << i)) && (clk_div <= (1 << (i + 1)))) || (i == 7)) {
\r
322 clk_div = (1 << (i + 1));
\r
323 tmp_reg |= (i << 8);
\r
328 sd_clk = base_clk/clk_div;
\r
329 p_cfg->sd_ctrl2 = tmp_reg;
\r
332 } /* end of sdhost_set_clk_freq_v20 */
\r
334 PUBLIC uint32 sdhost_set_clk_freq_v30 (sdio_reg_ptr p_cfg, uint32 base_clk, uint32 clk)
\r
336 volatile uint32 tmp_reg;
\r
337 uint32 clk_div, sd_clk;
\r
338 sdio_reg_v30_ptr p_tmp_cfg;
\r
340 p_tmp_cfg = (sdio_reg_v30_ptr) p_cfg;
\r
342 /* SDCLK Frequency Select ,Configure SDCLK select */
343 clk_div = base_clk / clk;
\r
345 if (0 != base_clk % clk) {
\r
349 tmp_reg = p_tmp_cfg->sd_ctrl2;
\r
354 tmp_reg &= ~(0x3ff << 6);
\r
355 tmp_reg |= ((clk_div >> 8) & 0x3) << 6;
\r
356 tmp_reg |= (clk_div & 0xff) << 8;
\r
358 sd_clk = base_clk / (2 * (clk_div + 1));
\r
360 p_tmp_cfg->sd_ctrl2 = tmp_reg;
\r
363 } /* end of sdhost_set_clk_freq_v30 */
\r
365 /*********************************************************************
367 ** This function used to set timeout value for transfer cmd.
\r
369 ** p_cfg : sdio control reg.
\r
370 ** clk_cnt : current clock freq num.
\r
373 ** Date Author Operation
374 ** 2013/09/05 ypxie create
\r
375 *********************************************************************/
\r
376 PUBLIC void sdhost_set_data_timeout_value (sdio_reg_ptr p_cfg, uint32 clk_cnt)
\r
378 volatile uint32 tmp_reg, tmp_int_reg;
\r
380 tmp_int_reg = p_cfg->int_st_en;
\r
382 /* cfg the data timeout clk */
\r
383 p_cfg->int_st_en &= ~BIT_20;
\r
385 tmp_reg = p_cfg->sd_ctrl2;
\r
386 tmp_reg &= ~(BIT_16 | BIT_17 | BIT_18 | BIT_19);
\r
387 tmp_reg |= (clk_cnt & 0x0F) << 16;
\r
388 p_cfg->sd_ctrl2 = tmp_reg;
\r
390 p_cfg->int_st_en = tmp_int_reg;
\r
393 /*********************************************************************
395 ** This function used to reset data line.
\r
397 ** p_cfg : sdio control reg.
\r
400 ** Date Author Operation
401 ** 2013/09/05 ypxie create
\r
402 *********************************************************************/
\r
403 LOCAL void _reset_data_line (sdio_reg_ptr p_cfg)
\r
405 p_cfg->sd_ctrl2 |= BIT_26;
\r
407 while (0 != (p_cfg->sd_ctrl2 & BIT_26));
\r
410 /*********************************************************************
412 ** This function used to reset cmd line.
\r
414 ** p_cfg : sdio control reg.
\r
417 ** Date Author Operation
418 ** 2013/09/05 ypxie create
\r
419 *********************************************************************/
\r
420 LOCAL void _reset_cmd_line (sdio_reg_ptr p_cfg)
\r
422 p_cfg->sd_ctrl2 |= BIT_25;
\r
424 while (0 != (p_cfg->sd_ctrl2 & BIT_25));
\r
427 LOCAL void _reset_data_cmd_line (sdio_reg_ptr p_cfg)
\r
429 p_cfg->sd_ctrl2 |= (BIT_25 | BIT_26);
\r
431 while (0 != (p_cfg->sd_ctrl2 & (BIT_25 | BIT_26)));
\r
434 /*********************************************************************
436 ** This function used to reset cmd line.
\r
438 ** p_cfg : sdio control reg.
\r
441 ** Date Author Operation
442 ** 2013/09/05 ypxie create
\r
443 *********************************************************************/
\r
444 LOCAL void _reset_all (sdio_reg_ptr p_cfg)
\r
446 p_cfg->sd_ctrl2 |= BIT_24;
\r
448 while (0 != (p_cfg->sd_ctrl2 & BIT_24));
\r
451 /*********************************************************************
453 ** This function used to reset the specify module of host.
\r
455 ** p_cfg : sdio control reg.
\r
456 ** rst_type : select reset type.
\r
459 ** Date Author Operation
460 ** 2013/09/05 ypxie create
\r
461 *********************************************************************/
\r
462 PUBLIC void sdhost_reset (sdio_reg_ptr p_cfg, sdio_rst_type_e rst_type)
\r
464 switch (rst_type) {
\r
466 _reset_cmd_line(p_cfg);
\r
470 _reset_data_line(p_cfg);
\r
473 case RST_CMD_DAT_LINE:
\r
474 _reset_data_cmd_line(p_cfg);
\r
478 sdhost_set_sd_clk(p_cfg, SDIO_OFF);
\r
487 } /* end of sdhost_reset */
\r
489 /*********************************************************************
491 ** This function used to set dma transfer information.
\r
493 ** p_cfg : sdio control reg.
\r
494 ** blk_size : set block size.
\r
495 ** blk_cnt : block count.
\r
496 ** dma_size : select dma size.
\r
499 ** Date Author Operation
500 ** 2013/09/05 ypxie create
\r
501 *********************************************************************/
\r
502 PUBLIC void sdhost_set_data_param (sdio_reg_ptr p_cfg,
\r
505 sdio_dma_size_e dma_size)
\r
507 volatile uint32 tmp_reg;
\r
509 tmp_reg = p_cfg->blk_size_cnt;
\r
511 /* Set Block Size */
\r
512 tmp_reg &= ~BIT_15;
\r
514 if (0x1000 >= blk_size) {
\r
518 tmp_reg |= blk_size;
\r
521 /* Set Block Cnt [31 : 16] */
\r
522 tmp_reg &= ~0xFFFF0000;
\r
523 tmp_reg |= blk_cnt << 16;
\r
525 /* Set DMA Buf Size [14 : 12] */
\r
526 tmp_reg &= ~(BIT_12 | BIT_13 | BIT_14);
\r
528 switch (dma_size) {
\r
538 tmp_reg |= (BIT_12 | BIT_13);
\r
545 case SDIO_DMA_128K:
\r
546 tmp_reg |= (BIT_12 | BIT_14);
\r
549 case SDIO_DMA_256K:
\r
550 tmp_reg |= (BIT_13 | BIT_14);
\r
553 case SDIO_DMA_512K:
\r
554 tmp_reg |= (BIT_12 | BIT_13 | BIT_14);
\r
562 p_cfg->blk_size_cnt = tmp_reg;
\r
563 } /* end of sdhost_set_data_param */
\r
565 /*********************************************************************
567 ** This function used to get dma transfer information.
\r
569 ** p_cfg : sdio control reg.
\r
570 ** blk_size : get block size.
\r
571 ** blk_cnt : get block count.
\r
572 ** dma_addr : get dma address.
\r
575 ** Date Author Operation
576 ** 2013/09/05 ypxie create
\r
577 *********************************************************************/
\r
578 PUBLIC void sdhost_get_data_param (sdio_reg_ptr p_cfg,
\r
585 size_cnt = p_cfg->blk_size_cnt;
\r
587 if ((size_cnt & BIT_15) != 0) {
\r
588 *blk_size = 0x1000;
\r
591 *blk_size = size_cnt & 0xFFF;
\r
594 *blk_cnt = (size_cnt & 0xFFFF0000) >>16;
\r
595 *dma_addr = p_cfg->dma_addr;
\r
598 /*********************************************************************
600 ** This function used to set start address of dma buffer.
\r
602 ** p_cfg : sdio control reg.
\r
603 ** dma_addr : set dma address.
\r
606 ** Date Author Operation
607 ** 2013/09/05 ypxie create
\r
608 *********************************************************************/
\r
609 PUBLIC void sdhost_set_dma_addr (sdio_reg_ptr p_cfg, uint32 dma_addr)
\r
611 p_cfg->dma_addr = dma_addr;
\r
614 /*********************************************************************
616 ** This function used to get start address of dma buffer.
\r
618 ** p_cfg : sdio control reg.
\r
621 ** Date Author Operation
622 ** 2013/09/05 ypxie create
\r
623 *********************************************************************/
\r
624 PUBLIC uint32 sdhost_get_dma_addr (sdio_reg_ptr p_cfg)
\r
626 return p_cfg->dma_addr;
\r
629 /*********************************************************************
631 ** This function used to set the argument of command.
\r
633 ** p_cfg : sdio control reg.
\r
634 ** argument : send to card argument.
\r
637 ** Date Author Operation
638 ** 2013/09/05 ypxie create
\r
639 *********************************************************************/
\r
640 PUBLIC void sdhost_set_cmd_argu (sdio_reg_ptr p_cfg, uint32 argument)
\r
642 p_cfg->cmd_argu = argument;
\r
645 /*********************************************************************
647 ** This function used to set the mode of command.
\r
649 ** p_cfg : sdio control reg
\r
650 ** cmd_index : cmd index
\r
651 ** transmode : SDIO_BOOT_ACK
\r
652 ** SDIO_CMD_LINE_BOOT
\r
654 ** SDIO_TRANS_DIS_AUTO
\r
655 ** SDIO_TRANS_AUTO_CMD12_EN
\r
656 ** SDIO_TRANS_AUTO_CMD23_EN
\r
657 ** SDIO_TRANS_COMP_ATA
\r
658 ** SDIO_TRANS_MULTIBLK
\r
659 ** SDIO_TRANS_DIR_READ
\r
660 ** SDIO_TRANS_BLK_CNT_EN
\r
661 ** SDIO_TRANS_DMA_EN
\r
662 ** cmd_type : SDIO_CMD_TYPE_NML
\r
663 ** SDIO_CMD_TYPE_SUSPEND
\r
664 ** SDIO_CMD_TYPE_RESUME
\r
665 ** SDIO_CMD_TYPE_ABORT
\r
666 ** response : SDIO_NO_RSP
\r
678 ** Date Author Operation
679 ** 2013/09/06 ypxie create
\r
680 *********************************************************************/
\r
681 PUBLIC void sdhost_set_cmd (sdio_reg_ptr p_cfg,
\r
687 volatile uint32 tmp_reg;
\r
689 /* tmp_reg &= (~(0x7F | 0x30000 | 0x3FF80000)); */
\r
690 tmp_reg &= ~(0x7F | 0x30000 | 0x3FF80700 | BIT_30 | BIT_31);
\r
692 /* [transmode] bit[6:0], bit[21], bit[30], bit[31] */
\r
693 /* bit[3], bit[30], bit[31] is used by v30 */
\r
694 tmp_reg |= transmode & (0x7F | BIT_21 | BIT_30 | BIT_31);
\r
696 /* [cmd_type] bit[23:22] */
\r
697 tmp_reg |= cmd_type & (BIT_22 | BIT_23);
\r
699 /* [response] bit[17:16], bit[20], bit[19] */
\r
700 tmp_reg |= response & (BIT_16 | BIT_17 | BIT_19 | BIT_20);
\r
702 /* [cmd_index] bit[29:24] */
\r
703 tmp_reg |= (cmd_index & 0x3F) << 24;
\r
705 p_cfg->tr_mode = tmp_reg;
\r
706 } /* end of sdhost_set_cmd */
\r
708 /*********************************************************************
\r
710 ** This function used to get content from host response register.
\r
712 ** p_cfg : sdio control reg
\r
713 ** response : SDIO_NO_RSP
\r
723 ** rsp_buf : store response buffer
\r
726 ** Date Author Operation
727 ** 2013/09/06 ypxie create
\r
728 *********************************************************************/
\r
729 PUBLIC void sdhost_get_response (sdio_reg_ptr p_cfg, uint32 response, uint8 *rsp_buf)
\r
734 tmp_buf[0] = p_cfg->resp0;
\r
735 tmp_buf[1] = p_cfg->resp1;
\r
736 tmp_buf[2] = p_cfg->resp2;
\r
737 tmp_buf[3] = p_cfg->resp3;
\r
739 switch (response) {
\r
748 rsp_buf[0] = (uint8) ( (tmp_buf[0] >> 24) & 0xFF);
\r
749 rsp_buf[1] = (uint8) ( (tmp_buf[0] >> 16) & 0xFF);
\r
750 rsp_buf[2] = (uint8) ( (tmp_buf[0] >> 8) & 0xFF);
\r
751 rsp_buf[3] = (uint8) ( tmp_buf[0] & 0xFF);
\r
755 rsp_buf[0] = (uint8) ( (tmp_buf[3] >> 16) & 0xFF);
\r
756 rsp_buf[1] = (uint8) ( (tmp_buf[3] >> 8) & 0xFF);
\r
757 rsp_buf[2] = (uint8) (tmp_buf[3] & 0xFF);
\r
759 rsp_buf[3] = (uint8) ( (tmp_buf[2] >> 24) & 0xFF);
\r
760 rsp_buf[4] = (uint8) ( (tmp_buf[2] >> 16) & 0xFF);
\r
761 rsp_buf[5] = (uint8) ( (tmp_buf[2] >> 8) & 0xFF);
\r
762 rsp_buf[6] = (uint8) (tmp_buf[2] & 0xFF);
\r
764 rsp_buf[7] = (uint8) ( (tmp_buf[1] >> 24) & 0xFF);
\r
765 rsp_buf[8] = (uint8) ( (tmp_buf[1] >> 16) & 0xFF);
\r
766 rsp_buf[9] = (uint8) ( (tmp_buf[1] >> 8) & 0xFF);
\r
767 rsp_buf[10] = (uint8) (tmp_buf[1] & 0xFF);
\r
769 rsp_buf[11] = (uint8) ( (tmp_buf[0] >> 24) & 0xFF);
\r
770 rsp_buf[12] = (uint8) ( (tmp_buf[0] >> 16) & 0xFF);
\r
771 rsp_buf[13] = (uint8) ( (tmp_buf[0] >> 8) & 0xFF);
\r
772 rsp_buf[14] = (uint8) (tmp_buf[0] & 0xFF);
\r
779 }/* end of sdhost_get_response */
\r
781 /*********************************************************************
\r
783 ** This function used to get function that host can be support.
\r
785 ** p_cfg : sdio control reg
\r
786 ** cap_buf : size is 3*32bits.
\r
789 ** Date Author Operation
790 ** 2013/09/06 ypxie create
\r
791 *********************************************************************/
\r
792 LOCAL void sdhost_get_capability (sdio_reg_ptr p_cfg, uint32 *cap_buf)
\r
794 cap_buf[0] = p_cfg->cap1;
\r
795 cap_buf[1] = p_cfg->cap2;
\r
796 cap_buf[2] = p_cfg->cur_cap1;
\r
799 /*********************************************************************
\r
801 ** This function used to clear Normal int Status register ,if event is happed ,host will set
\r
802 ** status in register.
\r
804 ** p_cfg : sdio control reg
\r
805 ** msg : int status bit.
\r
806 ** INT_CMD_CMPLT BIT_0
\r
807 ** INT_TR_CMPLT BIT_1
\r
808 ** INT_CAP_EVENT BIT_2
\r
809 ** INT_DMA_INT BIT_3
\r
810 ** INT_BUF_WR_RDY BIT_4
\r
811 ** INT_BUF_RD_RDY BIT_5
\r
812 ** INT_CARD_INT BIT_8
\r
815 ** Date Author Operation
816 ** 2013/09/09 ypxie create
\r
817 *********************************************************************/
\r
818 PUBLIC void sdhost_int_st_clr (sdio_reg_ptr p_cfg, uint32 msg)
\r
820 volatile uint32 tmp_reg;
\r
823 /* if err, clr all error bit. */
\r
824 if (0 != (msg & INT_ERR_INT)) {
\r
825 tmp_reg |= (INT_CMD_TIMEOUT | INT_CMD_CRC | INT_CMD_END_BIT
\r
826 | INT_CMD_IND | INT_DATA_TIMEOUT | INT_DATA_CRC
\r
827 | INT_DATA_END_BIT | INT_CUR_LMT | INT_AUTO_CMD12
\r
832 p_cfg->int_st = tmp_reg;
\r
833 } /* end of sdhost_int_st_clr */
\r
835 /*********************************************************************
\r
837 ** This function used to get interrupt status.
\r
839 ** p_cfg : sdio control reg
\r
842 ** Date Author Operation
843 ** 2013/09/09 ypxie create
\r
844 *********************************************************************/
\r
845 PUBLIC uint32 sdhost_get_int_st (sdio_reg_ptr p_cfg)
\r
847 volatile uint32 tmp_reg;
\r
849 tmp_reg = p_cfg->int_st;
\r
854 /*********************************************************************
\r
856 ** This function used to enable interrupt.
\r
858 ** p_cfg : sdio control reg
\r
859 ** err_msg : int err bit status.
\r
860 ** INT_CMD_TIMEOUT BIT_16
\r
861 ** INT_CMD_CRC BIT_17
\r
862 ** INT_CMD_END_BIT BIT_18
\r
863 ** INT_CMD_IND BIT_19
\r
864 ** INT_DATA_TIMEOUT BIT_20
\r
865 ** INT_DATA_CRC BIT_21
\r
866 ** INT_DATA_END_BIT BIT_22
\r
867 ** INT_CUR_LMT BIT_23
\r
868 ** INT_AUTO_CMD12 BIT_24
\r
869 ** INT_TRGT_RESP BIT_28
\r
870 ** msg : int status bit.
\r
871 ** INT_CMD_CMPLT BIT_0
\r
872 ** INT_TR_CMPLT BIT_1
\r
873 ** INT_CAP_EVENT BIT_2
\r
874 ** INT_DMA_INT BIT_3
\r
875 ** INT_BUF_WR_RDY BIT_4
\r
876 ** INT_BUF_RD_RDY BIT_5
\r
877 ** INT_CARD_INT BIT_8
\r
880 ** Date Author Operation
881 ** 2013/09/09 ypxie create
\r
882 *********************************************************************/
\r
883 PUBLIC void sdhost_int_st_sig_en (sdio_reg_ptr p_cfg, uint32 msg)
\r
885 volatile uint32 tmp_reg;
\r
889 /* enable error bit. */
\r
890 /* enable status and err int bit*/
\r
893 p_cfg->int_st_en |= tmp_reg;
\r
894 p_cfg->int_sig_en |= tmp_reg;
\r
897 PUBLIC void sdhost_int_st_sig_dis (sdio_reg_ptr p_cfg, uint32 msg)
\r
899 volatile uint32 tmp_reg;
\r
903 /* clr all error bit. */
\r
904 if (0 != (msg & INT_ERR_INT)) {
\r
905 tmp_reg |= (INT_CMD_TIMEOUT | INT_CMD_CRC | INT_CMD_END_BIT
\r
906 | INT_CMD_IND | INT_DATA_TIMEOUT | INT_DATA_CRC
\r
907 | INT_DATA_END_BIT | INT_CUR_LMT | INT_AUTO_CMD12
\r
914 p_cfg->int_st_en &= ~tmp_reg;
\r
915 p_cfg->int_sig_en &= ~tmp_reg;
\r
918 /*********************************************************************
\r
920 ** This function used to slot select.
\r
922 ** slot_no : select slot number.
\r
923 ** S1 ,S2 ,slave sdio controller
\r
924 ** 0 ,1 ,2 SDIO0 (SD)
\r
925 ** 3 ,4 ,5 SDIO1 (WIFI)
\r
926 ** 6 ,7 ,8 SDIO2 (MASTER)
\r
927 ** 9 ,10 ,11 SDIO3 (EMMC)
\r
930 ** Date Author Operation
931 ** 2013/09/10 ypxie create
\r
932 *********************************************************************/
\r
933 PUBLIC void sdhost_slot_select (uint32 slot_no)
\r
937 REG32(AHB_SDIO_CTRL) = SLOT0_SEL;
\r
940 REG32(AHB_SDIO_CTRL) = SLOT1_SEL;
\r
943 REG32(AHB_SDIO_CTRL) = SLOT2_SEL;
\r
946 REG32(AHB_SDIO_CTRL) = SLOT3_SEL;
\r
949 REG32(AHB_SDIO_CTRL) = SLOT4_SEL;
\r
952 REG32(AHB_SDIO_CTRL) = SLOT5_SEL;
\r
955 REG32(AHB_SDIO_CTRL) = SLOT6_SEL;
\r
958 REG32(AHB_SDIO_CTRL) = SLOT7_SEL;
\r
961 REG32(AHB_SDIO_CTRL) = SLOT8_SEL;
\r
964 REG32(AHB_SDIO_CTRL) = SLOT9_SEL;
\r
967 REG32(AHB_SDIO_CTRL) = SLOT10_SEL;
\r
970 REG32(AHB_SDIO_CTRL) = SLOT11_SEL;
\r
975 } /* end of sdhost_slot_select */
\r
977 /*********************************************************************
\r
979 ** This function used to get emmc controller register base address.
\r
981 ** slot_no : select slot number.
\r
982 ** S1 ,S2 ,slave sdio controller
\r
983 ** 0 ,1 ,2 SDIO0 (SD)
\r
984 ** 3 ,4 ,5 SDIO1 (WIFI)
\r
985 ** 6 ,7 ,8 SDIO2 (MASTER)
\r
986 ** 9 ,10 ,11 SDIO3 (EMMC)
\r
988 ** reg_addr : sdio base register address
\r
989 ** Date Author Operation
990 ** 2013/09/11 ypxie create
\r
991 *********************************************************************/
\r
992 PUBLIC uint32 sdhost_get_base_addr (uint32 slot_no)
\r
994 uint32 reg_addr = 0;
\r
998 reg_addr = SLOT0_BASE_ADDR;
\r
1001 reg_addr = SLOT1_BASE_ADDR;
\r
1004 reg_addr = SLOT2_BASE_ADDR;
\r
1007 reg_addr = SLOT3_BASE_ADDR;
\r
1010 reg_addr = SLOT4_BASE_ADDR;
\r
1013 reg_addr = SLOT5_BASE_ADDR;
\r
1016 reg_addr = SLOT6_BASE_ADDR;
\r
1019 reg_addr = SLOT7_BASE_ADDR;
\r
1022 reg_addr = SLOT8_BASE_ADDR;
\r
1025 reg_addr = SLOT9_BASE_ADDR;
\r
1028 reg_addr = SLOT10_BASE_ADDR;
\r
1031 reg_addr = SLOT11_BASE_ADDR;
\r
1038 } /* end of sdhost_get_base_addr */
\r
1040 /*********************************************************************
\r
1042 ** This function used to enable sdio clock in ahb.
\r
1044 ** slot_no : select slot number.
\r
1045 ** S1 ,S2 ,slave sdio controller
\r
1046 ** 0 ,1 ,2 SDIO0 (SD)
\r
1047 ** 3 ,4 ,5 SDIO1 (WIFI)
\r
1048 ** 6 ,7 ,8 SDIO2 (MASTER)
\r
1049 ** 9 ,10 ,11 SDIO3 (EMMC)
\r
1052 ** Date Author Operation
1053 ** 2013/09/11 ypxie create
\r
1054 *********************************************************************/
\r
1055 PUBLIC void sdhost_ahb_sdio_en (uint32 slot_no)
\r
1058 sdio_base_info_t *p_tb;
\r
1060 p_tb = sdio_resource_detail;
\r
1063 REG32(p_tb[id].ahb_en) |= p_tb[id].ahb_en_bit;
\r
1066 /*********************************************************************
\r
1068 ** This function used to rst sdio controller in ahb.
\r
1070 ** slot_no : select slot number.
\r
1071 ** S1 ,S2 ,slave sdio controller
\r
1072 ** 0 ,1 ,2 SDIO0 (SD)
\r
1073 ** 3 ,4 ,5 SDIO1 (WIFI)
\r
1074 ** 6 ,7 ,8 SDIO2 (MASTER)
\r
1075 ** 9 ,10 ,11 SDIO3 (EMMC)
\r
1078 ** Date Author Operation
1079 ** 2013/09/11 ypxie create
\r
1080 *********************************************************************/
\r
1081 PUBLIC void sdhost_ahb_sdio_rst (uint32 slot_no)
\r
1084 sdio_base_info_t *p_tb;
\r
1086 p_tb = sdio_resource_detail;
\r
1089 REG32(p_tb[id].ahb_rst) |= p_tb[id].ahb_rst_bit;
\r
1090 sdhost_delayus(200);
\r
1091 REG32(p_tb[id].ahb_rst) &= ~(p_tb[id].ahb_rst_bit);
\r
1094 /*********************************************************************
\r
1096 ** This function used to set sdio base clock.
\r
1098 ** slot_no : select slot number.
\r
1099 ** S1 ,S2 ,slave sdio controller
\r
1100 ** 0 ,1 ,2 SDIO0 (SD)
\r
1101 ** 3 ,4 ,5 SDIO1 (WIFI)
\r
1102 ** 6 ,7 ,8 SDIO2 (MASTER)
\r
1103 ** 9 ,10 ,11 SDIO3 (EMMC)
\r
1104 ** base_clk : base clock value. must the same as the value in table .
\r
1107 ** Date Author Operation
1108 ** 2013/09/11 ypxie create
\r
1109 *********************************************************************/
\r
1110 PUBLIC uint32 sdhost_set_base_clk (uint32 slot_no, uint32 base_clk)
\r
1113 sdio_base_info_t *p_tb;
\r
1115 p_tb = sdio_resource_detail;
\r
1119 REG32(p_tb[id].clk_reg) &= ~(p_tb[id].clk_mask);
\r
1121 for (i = 0; i < 4; i++) {
\r
1122 if (base_clk == p_tb[id].clk_sel[i].val) {
\r
1123 REG32(p_tb[id].clk_reg) |= p_tb[id].clk_sel[i].step << p_tb[id].clk_shft;
\r
1131 /*********************************************************************
\r
1133 ** This function used to set sdio base clock.
\r
1135 ** slot_no : select slot number.
\r
1136 ** S1 ,S2 ,slave sdio controller
\r
1137 ** 0 ,1 ,2 SDIO0 (SD)
\r
1138 ** 3 ,4 ,5 SDIO1 (WIFI)
\r
1139 ** 6 ,7 ,8 SDIO2 (MASTER)
\r
1140 ** 9 ,10 ,11 SDIO3 (EMMC)
\r
1141 ** pwr_flg : on or off flag.
\r
1144 ** Date Author Operation
1145 ** 2013/09/11 ypxie create
\r
1146 *********************************************************************/
\r
1147 PUBLIC uint32 sdhost_set_power (uint32 slot_no, sdio_onoff_e pwr_flg)
\r
1150 sdio_base_info_t *p_tb;
\r
1152 p_tb = sdio_resource_detail;
\r
1155 if (pwr_flg == SDIO_ON) {
\r
1156 if (p_tb[id].pwr_io.pd_set != 0) {
\r
1157 REG32(p_tb[id].pwr_io.pd_set) &= ~(p_tb[id].pwr_io.pd_set_bit);
\r
1159 if (p_tb[id].pwr_io.pd_clr != 0) {
\r
1160 REG32(p_tb[id].pwr_io.pd_clr) |= (p_tb[id].pwr_io.pd_clr_bit);
\r
1164 if (p_tb[id].pwr_core.pd_set != 0) {
\r
1165 REG32(p_tb[id].pwr_core.pd_set) &= ~(p_tb[id].pwr_core.pd_set_bit);
\r
1167 if (p_tb[id].pwr_core.pd_clr != 0) {
\r
1168 REG32(p_tb[id].pwr_core.pd_clr) |= (p_tb[id].pwr_core.pd_clr_bit);
\r
1172 else if (pwr_flg == SDIO_OFF) {
\r
1173 if (p_tb[id].pwr_io.pd_set != 0) {
\r
1174 REG32(p_tb[id].pwr_io.pd_set) |= (p_tb[id].pwr_io.pd_set_bit);
\r
1176 if (p_tb[id].pwr_io.pd_clr != 0) {
\r
1177 REG32(p_tb[id].pwr_io.pd_clr) &= ~(p_tb[id].pwr_io.pd_clr_bit);
\r
1181 if (p_tb[id].pwr_core.pd_set != 0) {
\r
1182 REG32(p_tb[id].pwr_core.pd_set) |= (p_tb[id].pwr_core.pd_set_bit);
\r
1184 if (p_tb[id].pwr_core.pd_clr != 0) {
\r
1185 REG32(p_tb[id].pwr_core.pd_clr) &= ~(p_tb[id].pwr_core.pd_clr_bit);
\r
1189 } /* end of sdhost_set_power */
\r
1191 /*********************************************************************
\r
1193 ** This function used to select sdio power_io, power_core voltage.
\r
1195 ** slot_no : select slot number.
\r
1196 ** S1 ,S2 ,slave sdio controller
\r
1197 ** 0 ,1 ,2 SDIO0 (SD)
\r
1198 ** 3 ,4 ,5 SDIO1 (WIFI)
\r
1199 ** 6 ,7 ,8 SDIO2 (MASTER)
\r
1200 ** 9 ,10 ,11 SDIO3 (EMMC)
\r
1201 ** io_volt : io voltage, unit: mV.
\r
1202 ** core_volt : core voltage, unit: mV. if not, set 0.
\r
1205 ** Date Author Operation
1206 ** 2013/09/11 ypxie create
\r
1207 *********************************************************************/
\r
1208 PUBLIC uint32 sdhost_set_voltage (uint32 slot_no, uint32 io_volt, uint32 core_volt)
\r
1211 sdio_base_info_t *p_tb;
\r
1212 sdio_pwr_info_t *pwr;
\r
1214 p_tb = sdio_resource_detail;
\r
1217 pwr = &(p_tb[id].pwr_io);
\r
1218 if ( pwr->pwr_sel_reg != 0 ) {
\r
1219 REG32(pwr->pwr_sel_reg) &= ~(pwr->pwr_mask);
\r
1221 for (i = 0; i < 4; i++) {
\r
1222 if (io_volt == pwr->pwr_sel[i].val) {
\r
1223 REG32(pwr->pwr_sel_reg) |= pwr->pwr_sel[i].step << pwr->pwr_shft;
\r
1228 pwr = &(p_tb[id].pwr_core);
\r
1229 if ( pwr->pwr_sel_reg != 0 ) {
\r
1230 REG32(pwr->pwr_sel_reg) &= ~(pwr->pwr_mask);
\r
1232 for (i = 0; i < 4; i++) {
\r
1233 if (core_volt == pwr->pwr_sel[i].val) {
\r
1234 REG32(pwr->pwr_sel_reg) |= pwr->pwr_sel[i].step << pwr->pwr_shft;
\r
1238 } /* end of sdhost_set_voltage */
\r
1240 /*********************************************************************
\r
1242 ** This function used to get sdio controller version.
\r
1244 ** slot_no : select slot number.
\r
1245 ** S1 ,S2 ,slave sdio controller
\r
1246 ** 0 ,1 ,2 SDIO0 (SD)
\r
1247 ** 3 ,4 ,5 SDIO1 (WIFI)
\r
1248 ** 6 ,7 ,8 SDIO2 (MASTER)
\r
1249 ** 9 ,10 ,11 SDIO3 (EMMC)
\r
1251 ** sdio_ver : sdio version.
\r
1252 ** Date Author Operation
1253 ** 2013/09/22 ypxie create
\r
1254 *********************************************************************/
\r
1255 LOCAL uint32 sdhost_get_sdio_version(uint32 slot_no)
\r
1264 else if (id == 1) {
\r
1267 else if (id == 2) {
\r
1270 else if (id == 3) {
\r
1275 /*********************************************************************
\r
1277 ** This function used to select sdio power_io, power_core voltage.
\r
1279 ** slot_no : select slot number.
\r
1280 ** S1 ,S2 ,slave sdio controller
\r
1281 ** 0 ,1 ,2 SDIO0 (SD)
\r
1282 ** 3 ,4 ,5 SDIO1 (WIFI)
\r
1283 ** 6 ,7 ,8 SDIO2 (MASTER)
\r
1284 ** 9 ,10 ,11 SDIO3 (EMMC)
\r
1287 ** Date Author Operation
1288 ** 2013/09/12 ypxie create
\r
1289 *********************************************************************/
\r
1290 LOCAL void sdhost_pin_select(uint32 slot_no)
\r