iproc_sdhci.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Copyright 2019 Broadcom.
  4. *
  5. */
  6. #include <common.h>
  7. #include <dm.h>
  8. #include <errno.h>
  9. #include <malloc.h>
  10. #include <sdhci.h>
  11. #include <linux/delay.h>
  12. DECLARE_GLOBAL_DATA_PTR;
  13. struct sdhci_iproc_host {
  14. struct sdhci_host host;
  15. u32 shadow_cmd;
  16. u32 shadow_blk;
  17. };
  18. #define REG_OFFSET_IN_BITS(reg) ((reg) << 3 & 0x18)
  19. static inline struct sdhci_iproc_host *to_iproc(struct sdhci_host *host)
  20. {
  21. return (struct sdhci_iproc_host *)host;
  22. }
  23. #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
  24. static u32 sdhci_iproc_readl(struct sdhci_host *host, int reg)
  25. {
  26. u32 val = readl(host->ioaddr + reg);
  27. #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS_TRACE
  28. printf("%s %d: readl [0x%02x] 0x%08x\n",
  29. host->name, host->index, reg, val);
  30. #endif
  31. return val;
  32. }
  33. static u16 sdhci_iproc_readw(struct sdhci_host *host, int reg)
  34. {
  35. u32 val = sdhci_iproc_readl(host, (reg & ~3));
  36. u16 word = val >> REG_OFFSET_IN_BITS(reg) & 0xffff;
  37. return word;
  38. }
  39. static u8 sdhci_iproc_readb(struct sdhci_host *host, int reg)
  40. {
  41. u32 val = sdhci_iproc_readl(host, (reg & ~3));
  42. u8 byte = val >> REG_OFFSET_IN_BITS(reg) & 0xff;
  43. return byte;
  44. }
  45. static void sdhci_iproc_writel(struct sdhci_host *host, u32 val, int reg)
  46. {
  47. u32 clock = 0;
  48. #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS_TRACE
  49. printf("%s %d: writel [0x%02x] 0x%08x\n",
  50. host->name, host->index, reg, val);
  51. #endif
  52. writel(val, host->ioaddr + reg);
  53. if (host->mmc)
  54. clock = host->mmc->clock;
  55. if (clock <= 400000) {
  56. /* Round up to micro-second four SD clock delay */
  57. if (clock)
  58. udelay((4 * 1000000 + clock - 1) / clock);
  59. else
  60. udelay(10);
  61. }
  62. }
  63. /*
  64. * The Arasan has a bugette whereby it may lose the content of successive
  65. * writes to the same register that are within two SD-card clock cycles of
  66. * each other (a clock domain crossing problem). The data
  67. * register does not have this problem, which is just as well - otherwise we'd
  68. * have to nobble the DMA engine too.
  69. *
  70. * This wouldn't be a problem with the code except that we can only write the
  71. * controller with 32-bit writes. So two different 16-bit registers are
  72. * written back to back creates the problem.
  73. *
  74. * In reality, this only happens when SDHCI_BLOCK_SIZE and SDHCI_BLOCK_COUNT
  75. * are written followed by SDHCI_TRANSFER_MODE and SDHCI_COMMAND.
  76. * The BLOCK_SIZE and BLOCK_COUNT are meaningless until a command issued so
  77. * the work around can be further optimized. We can keep shadow values of
  78. * BLOCK_SIZE, BLOCK_COUNT, and TRANSFER_MODE until a COMMAND is issued.
  79. * Then, write the BLOCK_SIZE+BLOCK_COUNT in a single 32-bit write followed
  80. * by the TRANSFER+COMMAND in another 32-bit write.
  81. */
  82. static void sdhci_iproc_writew(struct sdhci_host *host, u16 val, int reg)
  83. {
  84. struct sdhci_iproc_host *iproc_host = to_iproc(host);
  85. u32 word_shift = REG_OFFSET_IN_BITS(reg);
  86. u32 mask = 0xffff << word_shift;
  87. u32 oldval, newval;
  88. if (reg == SDHCI_COMMAND) {
  89. /* Write the block now as we are issuing a command */
  90. if (iproc_host->shadow_blk != 0) {
  91. sdhci_iproc_writel(host, iproc_host->shadow_blk,
  92. SDHCI_BLOCK_SIZE);
  93. iproc_host->shadow_blk = 0;
  94. }
  95. oldval = iproc_host->shadow_cmd;
  96. } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) {
  97. /* Block size and count are stored in shadow reg */
  98. oldval = iproc_host->shadow_blk;
  99. } else {
  100. /* Read reg, all other registers are not shadowed */
  101. oldval = sdhci_iproc_readl(host, (reg & ~3));
  102. }
  103. newval = (oldval & ~mask) | (val << word_shift);
  104. if (reg == SDHCI_TRANSFER_MODE) {
  105. /* Save the transfer mode until the command is issued */
  106. iproc_host->shadow_cmd = newval;
  107. } else if (reg == SDHCI_BLOCK_SIZE || reg == SDHCI_BLOCK_COUNT) {
  108. /* Save the block info until the command is issued */
  109. iproc_host->shadow_blk = newval;
  110. } else {
  111. /* Command or other regular 32-bit write */
  112. sdhci_iproc_writel(host, newval, reg & ~3);
  113. }
  114. }
  115. static void sdhci_iproc_writeb(struct sdhci_host *host, u8 val, int reg)
  116. {
  117. u32 oldval = sdhci_iproc_readl(host, (reg & ~3));
  118. u32 byte_shift = REG_OFFSET_IN_BITS(reg);
  119. u32 mask = 0xff << byte_shift;
  120. u32 newval = (oldval & ~mask) | (val << byte_shift);
  121. sdhci_iproc_writel(host, newval, reg & ~3);
  122. }
  123. #endif
  124. static int sdhci_iproc_set_ios_post(struct sdhci_host *host)
  125. {
  126. u32 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
  127. /* Reset UHS mode bits */
  128. ctrl &= ~SDHCI_CTRL_UHS_MASK;
  129. if (host->mmc->ddr_mode)
  130. ctrl |= UHS_DDR50_BUS_SPEED;
  131. sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2);
  132. return 0;
  133. }
  134. static struct sdhci_ops sdhci_platform_ops = {
  135. #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS
  136. .read_l = sdhci_iproc_readl,
  137. .read_w = sdhci_iproc_readw,
  138. .read_b = sdhci_iproc_readb,
  139. .write_l = sdhci_iproc_writel,
  140. .write_w = sdhci_iproc_writew,
  141. .write_b = sdhci_iproc_writeb,
  142. #endif
  143. .set_ios_post = sdhci_iproc_set_ios_post,
  144. };
  145. struct iproc_sdhci_plat {
  146. struct mmc_config cfg;
  147. struct mmc mmc;
  148. };
  149. static int iproc_sdhci_probe(struct udevice *dev)
  150. {
  151. struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
  152. struct iproc_sdhci_plat *plat = dev_get_platdata(dev);
  153. struct sdhci_host *host = dev_get_priv(dev);
  154. struct sdhci_iproc_host *iproc_host;
  155. int node = dev_of_offset(dev);
  156. u32 f_min_max[2];
  157. int ret;
  158. iproc_host = malloc(sizeof(struct sdhci_iproc_host));
  159. if (!iproc_host) {
  160. printf("%s: sdhci host malloc fail!\n", __func__);
  161. return -ENOMEM;
  162. }
  163. iproc_host->shadow_cmd = 0;
  164. iproc_host->shadow_blk = 0;
  165. host->name = dev->name;
  166. host->ioaddr = dev_read_addr_ptr(dev);
  167. host->voltages = MMC_VDD_165_195 |
  168. MMC_VDD_32_33 | MMC_VDD_33_34;
  169. host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B;
  170. host->host_caps = MMC_MODE_DDR_52MHz;
  171. host->index = fdtdec_get_uint(gd->fdt_blob, node, "index", 0);
  172. host->ops = &sdhci_platform_ops;
  173. host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
  174. ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
  175. "clock-freq-min-max", f_min_max, 2);
  176. if (ret) {
  177. printf("sdhci: clock-freq-min-max not found\n");
  178. free(iproc_host);
  179. return ret;
  180. }
  181. host->max_clk = f_min_max[1];
  182. host->bus_width = fdtdec_get_int(gd->fdt_blob,
  183. dev_of_offset(dev), "bus-width", 4);
  184. /* Update host_caps for 8 bit bus width */
  185. if (host->bus_width == 8)
  186. host->host_caps |= MMC_MODE_8BIT;
  187. memcpy(&iproc_host->host, host, sizeof(struct sdhci_host));
  188. iproc_host->host.mmc = &plat->mmc;
  189. iproc_host->host.mmc->dev = dev;
  190. iproc_host->host.mmc->priv = &iproc_host->host;
  191. upriv->mmc = iproc_host->host.mmc;
  192. ret = sdhci_setup_cfg(&plat->cfg, &iproc_host->host,
  193. f_min_max[1], f_min_max[0]);
  194. if (ret) {
  195. free(iproc_host);
  196. return ret;
  197. }
  198. return sdhci_probe(dev);
  199. }
  200. static int iproc_sdhci_bind(struct udevice *dev)
  201. {
  202. struct iproc_sdhci_plat *plat = dev_get_platdata(dev);
  203. return sdhci_bind(dev, &plat->mmc, &plat->cfg);
  204. }
  205. static const struct udevice_id iproc_sdhci_ids[] = {
  206. { .compatible = "brcm,iproc-sdhci" },
  207. { }
  208. };
  209. U_BOOT_DRIVER(iproc_sdhci_drv) = {
  210. .name = "iproc_sdhci",
  211. .id = UCLASS_MMC,
  212. .of_match = iproc_sdhci_ids,
  213. .ops = &sdhci_ops,
  214. .bind = iproc_sdhci_bind,
  215. .probe = iproc_sdhci_probe,
  216. .priv_auto_alloc_size = sizeof(struct sdhci_host),
  217. .platdata_auto_alloc_size = sizeof(struct iproc_sdhci_plat),
  218. };