nexell_dw_mmc.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2016 Nexell
  4. * Youngbok, Park <park@nexell.co.kr>
  5. *
  6. * (C) Copyright 2019 Stefan Bosch <stefan_b@posteo.net>
  7. */
  8. #include <common.h>
  9. #include <dm.h>
  10. #include <dt-structs.h>
  11. #include <dwmmc.h>
  12. #include <log.h>
  13. #include <syscon.h>
  14. #include <asm/arch/reset.h>
  15. #include <asm/arch/clk.h>
  16. #define DWMCI_CLKSEL 0x09C
  17. #define DWMCI_SHIFT_0 0x0
  18. #define DWMCI_SHIFT_1 0x1
  19. #define DWMCI_SHIFT_2 0x2
  20. #define DWMCI_SHIFT_3 0x3
  21. #define DWMCI_SET_SAMPLE_CLK(x) (x)
  22. #define DWMCI_SET_DRV_CLK(x) ((x) << 16)
  23. #define DWMCI_SET_DIV_RATIO(x) ((x) << 24)
  24. #define DWMCI_CLKCTRL 0x114
  25. #define NX_MMC_CLK_DELAY(x, y, a, b) ((((x) & 0xFF) << 0) |\
  26. (((y) & 0x03) << 16) |\
  27. (((a) & 0xFF) << 8) |\
  28. (((b) & 0x03) << 24))
  29. struct nexell_mmc_plat {
  30. struct mmc_config cfg;
  31. struct mmc mmc;
  32. };
  33. struct nexell_dwmmc_priv {
  34. struct clk *clk;
  35. struct dwmci_host host;
  36. int fifo_size;
  37. bool fifo_mode;
  38. int frequency;
  39. u32 min_freq;
  40. u32 max_freq;
  41. int d_delay;
  42. int d_shift;
  43. int s_delay;
  44. int s_shift;
  45. bool mmcboost;
  46. };
  47. struct clk *clk_get(const char *id);
  48. static void nx_dw_mmc_clksel(struct dwmci_host *host)
  49. {
  50. /* host->priv is pointer to "struct udevice" */
  51. struct nexell_dwmmc_priv *priv = dev_get_priv(host->priv);
  52. u32 val;
  53. if (priv->mmcboost)
  54. val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
  55. DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(1);
  56. else
  57. val = DWMCI_SET_SAMPLE_CLK(DWMCI_SHIFT_0) |
  58. DWMCI_SET_DRV_CLK(DWMCI_SHIFT_0) | DWMCI_SET_DIV_RATIO(3);
  59. dwmci_writel(host, DWMCI_CLKSEL, val);
  60. }
  61. static void nx_dw_mmc_reset(int ch)
  62. {
  63. int rst_id = RESET_ID_SDMMC0 + ch;
  64. nx_rstcon_setrst(rst_id, 0);
  65. nx_rstcon_setrst(rst_id, 1);
  66. }
  67. static void nx_dw_mmc_clk_delay(struct udevice *dev)
  68. {
  69. unsigned int delay;
  70. struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
  71. struct dwmci_host *host = &priv->host;
  72. delay = NX_MMC_CLK_DELAY(priv->d_delay,
  73. priv->d_shift, priv->s_delay, priv->s_shift);
  74. writel(delay, (host->ioaddr + DWMCI_CLKCTRL));
  75. debug("%s: Values set: d_delay==%d, d_shift==%d, s_delay==%d, "
  76. "s_shift==%d\n", __func__, priv->d_delay, priv->d_shift,
  77. priv->s_delay, priv->s_shift);
  78. }
  79. static unsigned int nx_dw_mmc_get_clk(struct dwmci_host *host, uint freq)
  80. {
  81. struct clk *clk;
  82. struct udevice *dev = host->priv;
  83. struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
  84. int index = host->dev_index;
  85. char name[50] = { 0, };
  86. clk = priv->clk;
  87. if (!clk) {
  88. sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
  89. clk = clk_get((const char *)name);
  90. if (!clk)
  91. return 0;
  92. priv->clk = clk;
  93. }
  94. return clk_get_rate(clk) / 2;
  95. }
  96. static unsigned long nx_dw_mmc_set_clk(struct dwmci_host *host,
  97. unsigned int rate)
  98. {
  99. struct clk *clk;
  100. char name[50] = { 0, };
  101. struct udevice *dev = host->priv;
  102. struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
  103. int index = host->dev_index;
  104. clk = priv->clk;
  105. if (!clk) {
  106. sprintf(name, "%s.%d", DEV_NAME_SDHC, index);
  107. clk = clk_get((const char *)name);
  108. if (!clk) {
  109. debug("%s: clk_get(\"%s\") failed!\n", __func__, name);
  110. return 0;
  111. }
  112. priv->clk = clk;
  113. }
  114. clk_disable(clk);
  115. rate = clk_set_rate(clk, rate);
  116. clk_enable(clk);
  117. return rate;
  118. }
  119. static int nexell_dwmmc_ofdata_to_platdata(struct udevice *dev)
  120. {
  121. struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
  122. struct dwmci_host *host = &priv->host;
  123. int val = -1;
  124. debug("%s\n", __func__);
  125. host->name = dev->name;
  126. host->ioaddr = dev_read_addr_ptr(dev);
  127. host->buswidth = dev_read_u32_default(dev, "bus-width", 4);
  128. host->get_mmc_clk = nx_dw_mmc_get_clk;
  129. host->clksel = nx_dw_mmc_clksel;
  130. host->priv = dev;
  131. val = dev_read_u32_default(dev, "index", -1);
  132. if (val < 0 || val > 2) {
  133. debug(" 'index' missing/invalid!\n");
  134. return -EINVAL;
  135. }
  136. host->dev_index = val;
  137. priv->fifo_size = dev_read_u32_default(dev, "fifo-size", 0x20);
  138. priv->fifo_mode = dev_read_bool(dev, "fifo-mode");
  139. priv->frequency = dev_read_u32_default(dev, "frequency", 50000000);
  140. priv->max_freq = dev_read_u32_default(dev, "max-frequency", 50000000);
  141. priv->min_freq = 400000; /* 400 kHz */
  142. priv->d_delay = dev_read_u32_default(dev, "drive_dly", 0);
  143. priv->d_shift = dev_read_u32_default(dev, "drive_shift", 3);
  144. priv->s_delay = dev_read_u32_default(dev, "sample_dly", 0);
  145. priv->s_shift = dev_read_u32_default(dev, "sample_shift", 2);
  146. priv->mmcboost = dev_read_u32_default(dev, "mmcboost", 0);
  147. debug(" index==%d, name==%s, ioaddr==0x%08x\n",
  148. host->dev_index, host->name, (u32)host->ioaddr);
  149. return 0;
  150. }
  151. static int nexell_dwmmc_probe(struct udevice *dev)
  152. {
  153. struct nexell_mmc_plat *plat = dev_get_platdata(dev);
  154. struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
  155. struct nexell_dwmmc_priv *priv = dev_get_priv(dev);
  156. struct dwmci_host *host = &priv->host;
  157. struct udevice *pwr_dev __maybe_unused;
  158. host->fifoth_val = MSIZE(0x2) |
  159. RX_WMARK(priv->fifo_size / 2 - 1) |
  160. TX_WMARK(priv->fifo_size / 2);
  161. host->fifo_mode = priv->fifo_mode;
  162. dwmci_setup_cfg(&plat->cfg, host, priv->max_freq, priv->min_freq);
  163. host->mmc = &plat->mmc;
  164. host->mmc->priv = &priv->host;
  165. host->mmc->dev = dev;
  166. upriv->mmc = host->mmc;
  167. if (nx_dw_mmc_set_clk(host, priv->frequency * 4) !=
  168. priv->frequency * 4) {
  169. debug("%s: nx_dw_mmc_set_clk(host, %d) failed!\n",
  170. __func__, priv->frequency * 4);
  171. return -EIO;
  172. }
  173. debug("%s: nx_dw_mmc_set_clk(host, %d) OK\n",
  174. __func__, priv->frequency * 4);
  175. nx_dw_mmc_reset(host->dev_index);
  176. nx_dw_mmc_clk_delay(dev);
  177. return dwmci_probe(dev);
  178. }
  179. static int nexell_dwmmc_bind(struct udevice *dev)
  180. {
  181. struct nexell_mmc_plat *plat = dev_get_platdata(dev);
  182. return dwmci_bind(dev, &plat->mmc, &plat->cfg);
  183. }
  184. static const struct udevice_id nexell_dwmmc_ids[] = {
  185. { .compatible = "nexell,nexell-dwmmc" },
  186. { }
  187. };
  188. U_BOOT_DRIVER(nexell_dwmmc_drv) = {
  189. .name = "nexell_dwmmc",
  190. .id = UCLASS_MMC,
  191. .of_match = nexell_dwmmc_ids,
  192. .ofdata_to_platdata = nexell_dwmmc_ofdata_to_platdata,
  193. .ops = &dm_dwmci_ops,
  194. .bind = nexell_dwmmc_bind,
  195. .probe = nexell_dwmmc_probe,
  196. .priv_auto_alloc_size = sizeof(struct nexell_dwmmc_priv),
  197. .platdata_auto_alloc_size = sizeof(struct nexell_mmc_plat),
  198. };