bfin_sdh.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * Driver for Blackfin on-chip SDH controller
  3. *
  4. * Copyright (c) 2008-2009 Analog Devices Inc.
  5. *
  6. * Licensed under the GPL-2 or later.
  7. */
  8. #include <common.h>
  9. #include <malloc.h>
  10. #include <part.h>
  11. #include <mmc.h>
  12. #include <asm/io.h>
  13. #include <asm/errno.h>
  14. #include <asm/byteorder.h>
  15. #include <asm/blackfin.h>
  16. #include <asm/portmux.h>
  17. #include <asm/mach-common/bits/sdh.h>
  18. #include <asm/mach-common/bits/dma.h>
  19. #if defined(__ADSPBF50x__) || defined(__ADSPBF51x__) || defined(__ADSPBF60x__)
  20. # define bfin_read_SDH_CLK_CTL bfin_read_RSI_CLK_CONTROL
  21. # define bfin_write_SDH_CLK_CTL bfin_write_RSI_CLK_CONTROL
  22. # define bfin_write_SDH_ARGUMENT bfin_write_RSI_ARGUMENT
  23. # define bfin_write_SDH_COMMAND bfin_write_RSI_COMMAND
  24. # define bfin_read_SDH_RESPONSE0 bfin_read_RSI_RESPONSE0
  25. # define bfin_read_SDH_RESPONSE1 bfin_read_RSI_RESPONSE1
  26. # define bfin_read_SDH_RESPONSE2 bfin_read_RSI_RESPONSE2
  27. # define bfin_read_SDH_RESPONSE3 bfin_read_RSI_RESPONSE3
  28. # define bfin_write_SDH_DATA_TIMER bfin_write_RSI_DATA_TIMER
  29. # define bfin_write_SDH_DATA_LGTH bfin_write_RSI_DATA_LGTH
  30. # define bfin_read_SDH_DATA_CTL bfin_read_RSI_DATA_CONTROL
  31. # define bfin_write_SDH_DATA_CTL bfin_write_RSI_DATA_CONTROL
  32. # define bfin_read_SDH_STATUS bfin_read_RSI_STATUS
  33. # define bfin_write_SDH_STATUS_CLR bfin_write_RSI_STATUSCL
  34. # define bfin_read_SDH_CFG bfin_read_RSI_CONFIG
  35. # define bfin_write_SDH_CFG bfin_write_RSI_CONFIG
  36. # if defined(__ADSPBF60x__)
  37. # define bfin_read_SDH_BLK_SIZE bfin_read_RSI_BLKSZ
  38. # define bfin_write_SDH_BLK_SIZE bfin_write_RSI_BLKSZ
  39. # define bfin_write_DMA_START_ADDR bfin_write_DMA10_START_ADDR
  40. # define bfin_write_DMA_X_COUNT bfin_write_DMA10_X_COUNT
  41. # define bfin_write_DMA_X_MODIFY bfin_write_DMA10_X_MODIFY
  42. # define bfin_write_DMA_CONFIG bfin_write_DMA10_CONFIG
  43. # else
  44. # define bfin_read_SDH_PWR_CTL bfin_read_RSI_PWR_CONTROL
  45. # define bfin_write_SDH_PWR_CTL bfin_write_RSI_PWR_CONTROL
  46. # define bfin_write_DMA_START_ADDR bfin_write_DMA4_START_ADDR
  47. # define bfin_write_DMA_X_COUNT bfin_write_DMA4_X_COUNT
  48. # define bfin_write_DMA_X_MODIFY bfin_write_DMA4_X_MODIFY
  49. # define bfin_write_DMA_CONFIG bfin_write_DMA4_CONFIG
  50. # endif
  51. # define PORTMUX_PINS \
  52. { P_RSI_DATA0, P_RSI_DATA1, P_RSI_DATA2, P_RSI_DATA3, P_RSI_CMD, P_RSI_CLK, 0 }
  53. #elif defined(__ADSPBF54x__)
  54. # define bfin_write_DMA_START_ADDR bfin_write_DMA22_START_ADDR
  55. # define bfin_write_DMA_X_COUNT bfin_write_DMA22_X_COUNT
  56. # define bfin_write_DMA_X_MODIFY bfin_write_DMA22_X_MODIFY
  57. # define bfin_write_DMA_CONFIG bfin_write_DMA22_CONFIG
  58. # define PORTMUX_PINS \
  59. { P_SD_D0, P_SD_D1, P_SD_D2, P_SD_D3, P_SD_CLK, P_SD_CMD, 0 }
  60. #else
  61. # error no support for this proc yet
  62. #endif
  63. static int
  64. sdh_send_cmd(struct mmc *mmc, struct mmc_cmd *mmc_cmd)
  65. {
  66. unsigned int status, timeout;
  67. int cmd = mmc_cmd->cmdidx;
  68. int flags = mmc_cmd->resp_type;
  69. int arg = mmc_cmd->cmdarg;
  70. int ret;
  71. u16 sdh_cmd;
  72. sdh_cmd = cmd | CMD_E;
  73. if (flags & MMC_RSP_PRESENT)
  74. sdh_cmd |= CMD_RSP;
  75. if (flags & MMC_RSP_136)
  76. sdh_cmd |= CMD_L_RSP;
  77. #ifdef RSI_BLKSZ
  78. sdh_cmd |= CMD_DATA0_BUSY;
  79. #endif
  80. bfin_write_SDH_ARGUMENT(arg);
  81. bfin_write_SDH_COMMAND(sdh_cmd);
  82. /* wait for a while */
  83. timeout = 0;
  84. do {
  85. if (++timeout > 1000000) {
  86. status = CMD_TIME_OUT;
  87. break;
  88. }
  89. udelay(1);
  90. status = bfin_read_SDH_STATUS();
  91. } while (!(status & (CMD_SENT | CMD_RESP_END | CMD_TIME_OUT |
  92. CMD_CRC_FAIL)));
  93. if (flags & MMC_RSP_PRESENT) {
  94. mmc_cmd->response[0] = bfin_read_SDH_RESPONSE0();
  95. if (flags & MMC_RSP_136) {
  96. mmc_cmd->response[1] = bfin_read_SDH_RESPONSE1();
  97. mmc_cmd->response[2] = bfin_read_SDH_RESPONSE2();
  98. mmc_cmd->response[3] = bfin_read_SDH_RESPONSE3();
  99. }
  100. }
  101. if (status & CMD_TIME_OUT)
  102. ret = TIMEOUT;
  103. else if (status & CMD_CRC_FAIL && flags & MMC_RSP_CRC)
  104. ret = COMM_ERR;
  105. else
  106. ret = 0;
  107. bfin_write_SDH_STATUS_CLR(CMD_SENT_STAT | CMD_RESP_END_STAT |
  108. CMD_TIMEOUT_STAT | CMD_CRC_FAIL_STAT);
  109. #ifdef RSI_BLKSZ
  110. /* wait till card ready */
  111. while (!(bfin_read_RSI_ESTAT() & SD_CARD_READY))
  112. continue;
  113. bfin_write_RSI_ESTAT(SD_CARD_READY);
  114. #endif
  115. return ret;
  116. }
  117. /* set data for single block transfer */
  118. static int sdh_setup_data(struct mmc *mmc, struct mmc_data *data)
  119. {
  120. u16 data_ctl = 0;
  121. u16 dma_cfg = 0;
  122. unsigned long data_size = data->blocksize * data->blocks;
  123. /* Don't support write yet. */
  124. if (data->flags & MMC_DATA_WRITE)
  125. return UNUSABLE_ERR;
  126. #ifndef RSI_BLKSZ
  127. data_ctl |= ((ffs(data_size) - 1) << 4);
  128. #else
  129. bfin_write_SDH_BLK_SIZE(data_size);
  130. #endif
  131. data_ctl |= DTX_DIR;
  132. bfin_write_SDH_DATA_CTL(data_ctl);
  133. dma_cfg = WDSIZE_32 | PSIZE_32 | RESTART | WNR | DMAEN;
  134. bfin_write_SDH_DATA_TIMER(-1);
  135. blackfin_dcache_flush_invalidate_range(data->dest,
  136. data->dest + data_size);
  137. /* configure DMA */
  138. bfin_write_DMA_START_ADDR(data->dest);
  139. bfin_write_DMA_X_COUNT(data_size / 4);
  140. bfin_write_DMA_X_MODIFY(4);
  141. bfin_write_DMA_CONFIG(dma_cfg);
  142. bfin_write_SDH_DATA_LGTH(data_size);
  143. /* kick off transfer */
  144. bfin_write_SDH_DATA_CTL(bfin_read_SDH_DATA_CTL() | DTX_DMA_E | DTX_E);
  145. return 0;
  146. }
  147. static int bfin_sdh_request(struct mmc *mmc, struct mmc_cmd *cmd,
  148. struct mmc_data *data)
  149. {
  150. u32 status;
  151. int ret = 0;
  152. if (data) {
  153. ret = sdh_setup_data(mmc, data);
  154. if (ret)
  155. return ret;
  156. }
  157. ret = sdh_send_cmd(mmc, cmd);
  158. if (ret) {
  159. bfin_write_SDH_COMMAND(0);
  160. bfin_write_DMA_CONFIG(0);
  161. bfin_write_SDH_DATA_CTL(0);
  162. SSYNC();
  163. printf("sending CMD%d failed\n", cmd->cmdidx);
  164. return ret;
  165. }
  166. if (data) {
  167. do {
  168. udelay(1);
  169. status = bfin_read_SDH_STATUS();
  170. } while (!(status & (DAT_BLK_END | DAT_END | DAT_TIME_OUT | DAT_CRC_FAIL | RX_OVERRUN)));
  171. if (status & DAT_TIME_OUT) {
  172. bfin_write_SDH_STATUS_CLR(DAT_TIMEOUT_STAT);
  173. ret |= TIMEOUT;
  174. } else if (status & (DAT_CRC_FAIL | RX_OVERRUN)) {
  175. bfin_write_SDH_STATUS_CLR(DAT_CRC_FAIL_STAT | RX_OVERRUN_STAT);
  176. ret |= COMM_ERR;
  177. } else
  178. bfin_write_SDH_STATUS_CLR(DAT_BLK_END_STAT | DAT_END_STAT);
  179. if (ret) {
  180. printf("tranfering data failed\n");
  181. return ret;
  182. }
  183. }
  184. return 0;
  185. }
  186. static void sdh_set_clk(unsigned long clk)
  187. {
  188. unsigned long sys_clk;
  189. unsigned long clk_div;
  190. u16 clk_ctl = 0;
  191. clk_ctl = bfin_read_SDH_CLK_CTL();
  192. if (clk) {
  193. /* setting SD_CLK */
  194. sys_clk = get_sclk();
  195. bfin_write_SDH_CLK_CTL(clk_ctl & ~CLK_E);
  196. if (sys_clk % (2 * clk) == 0)
  197. clk_div = sys_clk / (2 * clk) - 1;
  198. else
  199. clk_div = sys_clk / (2 * clk);
  200. if (clk_div > 0xff)
  201. clk_div = 0xff;
  202. clk_ctl |= (clk_div & 0xff);
  203. clk_ctl |= CLK_E;
  204. bfin_write_SDH_CLK_CTL(clk_ctl);
  205. } else
  206. bfin_write_SDH_CLK_CTL(clk_ctl & ~CLK_E);
  207. }
  208. static void bfin_sdh_set_ios(struct mmc *mmc)
  209. {
  210. u16 cfg = 0;
  211. u16 clk_ctl = 0;
  212. if (mmc->bus_width == 4) {
  213. cfg = bfin_read_SDH_CFG();
  214. #ifndef RSI_BLKSZ
  215. cfg &= ~PD_SDDAT3;
  216. #endif
  217. cfg |= PUP_SDDAT3;
  218. bfin_write_SDH_CFG(cfg);
  219. clk_ctl |= WIDE_BUS_4;
  220. }
  221. bfin_write_SDH_CLK_CTL(clk_ctl);
  222. sdh_set_clk(mmc->clock);
  223. }
  224. static int bfin_sdh_init(struct mmc *mmc)
  225. {
  226. const unsigned short pins[] = PORTMUX_PINS;
  227. int ret;
  228. /* Initialize sdh controller */
  229. ret = peripheral_request_list(pins, "bfin_sdh");
  230. if (ret < 0)
  231. return ret;
  232. #if defined(__ADSPBF54x__)
  233. bfin_write_DMAC1_PERIMUX(bfin_read_DMAC1_PERIMUX() | 0x1);
  234. #endif
  235. bfin_write_SDH_CFG(bfin_read_SDH_CFG() | CLKS_EN);
  236. /* Disable card detect pin */
  237. bfin_write_SDH_CFG((bfin_read_SDH_CFG() & 0x1F) | 0x60);
  238. #ifndef RSI_BLKSZ
  239. bfin_write_SDH_PWR_CTL(PWR_ON | ROD_CTL);
  240. #else
  241. bfin_write_SDH_CFG(bfin_read_SDH_CFG() | PWR_ON);
  242. #endif
  243. return 0;
  244. }
  245. int bfin_mmc_init(bd_t *bis)
  246. {
  247. struct mmc *mmc = NULL;
  248. mmc = malloc(sizeof(struct mmc));
  249. if (!mmc)
  250. return -ENOMEM;
  251. sprintf(mmc->name, "Blackfin SDH");
  252. mmc->send_cmd = bfin_sdh_request;
  253. mmc->set_ios = bfin_sdh_set_ios;
  254. mmc->init = bfin_sdh_init;
  255. mmc->getcd = NULL;
  256. mmc->getwp = NULL;
  257. mmc->host_caps = MMC_MODE_4BIT;
  258. mmc->voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
  259. mmc->f_max = get_sclk();
  260. mmc->f_min = mmc->f_max >> 9;
  261. mmc->b_max = 0;
  262. mmc_register(mmc);
  263. return 0;
  264. }