sdhci-cadence.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2016 Socionext Inc.
  4. * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  5. */
  6. #include <linux/bitfield.h>
  7. #include <linux/bits.h>
  8. #include <linux/iopoll.h>
  9. #include <linux/module.h>
  10. #include <linux/mmc/host.h>
  11. #include <linux/mmc/mmc.h>
  12. #include <linux/of.h>
  13. #include <linux/platform_device.h>
  14. #include <linux/reset.h>
  15. #include "sdhci-pltfm.h"
  16. /* HRS - Host Register Set (specific to Cadence) */
  17. #define SDHCI_CDNS_HRS04 0x10 /* PHY access port */
  18. #define SDHCI_CDNS_HRS04_ACK BIT(26)
  19. #define SDHCI_CDNS_HRS04_RD BIT(25)
  20. #define SDHCI_CDNS_HRS04_WR BIT(24)
  21. #define SDHCI_CDNS_HRS04_RDATA GENMASK(23, 16)
  22. #define SDHCI_CDNS_HRS04_WDATA GENMASK(15, 8)
  23. #define SDHCI_CDNS_HRS04_ADDR GENMASK(5, 0)
  24. #define SDHCI_CDNS_HRS06 0x18 /* eMMC control */
  25. #define SDHCI_CDNS_HRS06_TUNE_UP BIT(15)
  26. #define SDHCI_CDNS_HRS06_TUNE GENMASK(13, 8)
  27. #define SDHCI_CDNS_HRS06_MODE GENMASK(2, 0)
  28. #define SDHCI_CDNS_HRS06_MODE_SD 0x0
  29. #define SDHCI_CDNS_HRS06_MODE_MMC_SDR 0x2
  30. #define SDHCI_CDNS_HRS06_MODE_MMC_DDR 0x3
  31. #define SDHCI_CDNS_HRS06_MODE_MMC_HS200 0x4
  32. #define SDHCI_CDNS_HRS06_MODE_MMC_HS400 0x5
  33. #define SDHCI_CDNS_HRS06_MODE_MMC_HS400ES 0x6
  34. /* Read block gap */
  35. #define SDHCI_CDNS_HRS37 0x94 /* interface mode select */
  36. #define SDHCI_CDNS_HRS37_MODE_DS 0x0
  37. #define SDHCI_CDNS_HRS37_MODE_HS 0x1
  38. #define SDHCI_CDNS_HRS37_MODE_UDS_SDR12 0x8
  39. #define SDHCI_CDNS_HRS37_MODE_UDS_SDR25 0x9
  40. #define SDHCI_CDNS_HRS37_MODE_UDS_SDR50 0xa
  41. #define SDHCI_CDNS_HRS37_MODE_UDS_SDR104 0xb
  42. #define SDHCI_CDNS_HRS37_MODE_UDS_DDR50 0xc
  43. #define SDHCI_CDNS_HRS37_MODE_MMC_LEGACY 0x20
  44. #define SDHCI_CDNS_HRS37_MODE_MMC_SDR 0x21
  45. #define SDHCI_CDNS_HRS37_MODE_MMC_DDR 0x22
  46. #define SDHCI_CDNS_HRS37_MODE_MMC_HS200 0x23
  47. #define SDHCI_CDNS_HRS37_MODE_MMC_HS400 0x24
  48. #define SDHCI_CDNS_HRS37_MODE_MMC_HS400ES 0x25
  49. #define SDHCI_CDNS_HRS38 0x98 /* Read block gap coefficient */
  50. #define SDHCI_CDNS_HRS38_BLKGAP_MAX 0xf
  51. /* SRS - Slot Register Set (SDHCI-compatible) */
  52. #define SDHCI_CDNS_SRS_BASE 0x200
  53. /* PHY */
  54. #define SDHCI_CDNS_PHY_DLY_SD_HS 0x00
  55. #define SDHCI_CDNS_PHY_DLY_SD_DEFAULT 0x01
  56. #define SDHCI_CDNS_PHY_DLY_UHS_SDR12 0x02
  57. #define SDHCI_CDNS_PHY_DLY_UHS_SDR25 0x03
  58. #define SDHCI_CDNS_PHY_DLY_UHS_SDR50 0x04
  59. #define SDHCI_CDNS_PHY_DLY_UHS_DDR50 0x05
  60. #define SDHCI_CDNS_PHY_DLY_EMMC_LEGACY 0x06
  61. #define SDHCI_CDNS_PHY_DLY_EMMC_SDR 0x07
  62. #define SDHCI_CDNS_PHY_DLY_EMMC_DDR 0x08
  63. #define SDHCI_CDNS_PHY_DLY_SDCLK 0x0b
  64. #define SDHCI_CDNS_PHY_DLY_HSMMC 0x0c
  65. #define SDHCI_CDNS_PHY_DLY_STROBE 0x0d
  66. /*
  67. * The tuned val register is 6 bit-wide, but not the whole of the range is
  68. * available. The range 0-42 seems to be available (then 43 wraps around to 0)
  69. * but I am not quite sure if it is official. Use only 0 to 39 for safety.
  70. */
  71. #define SDHCI_CDNS_MAX_TUNING_LOOP 40
  72. struct sdhci_cdns_phy_param {
  73. u8 addr;
  74. u8 data;
  75. };
  76. struct sdhci_cdns_priv {
  77. void __iomem *hrs_addr;
  78. void __iomem *ctl_addr; /* write control */
  79. spinlock_t wrlock; /* write lock */
  80. bool enhanced_strobe;
  81. void (*priv_writel)(struct sdhci_cdns_priv *priv, u32 val, void __iomem *reg);
  82. struct reset_control *rst_hw;
  83. unsigned int nr_phy_params;
  84. struct sdhci_cdns_phy_param phy_params[];
  85. };
  86. struct sdhci_cdns_phy_cfg {
  87. const char *property;
  88. u8 addr;
  89. };
  90. struct sdhci_cdns_drv_data {
  91. int (*init)(struct platform_device *pdev);
  92. const struct sdhci_pltfm_data pltfm_data;
  93. };
  94. static const struct sdhci_cdns_phy_cfg sdhci_cdns_phy_cfgs[] = {
  95. { "cdns,phy-input-delay-sd-highspeed", SDHCI_CDNS_PHY_DLY_SD_HS, },
  96. { "cdns,phy-input-delay-legacy", SDHCI_CDNS_PHY_DLY_SD_DEFAULT, },
  97. { "cdns,phy-input-delay-sd-uhs-sdr12", SDHCI_CDNS_PHY_DLY_UHS_SDR12, },
  98. { "cdns,phy-input-delay-sd-uhs-sdr25", SDHCI_CDNS_PHY_DLY_UHS_SDR25, },
  99. { "cdns,phy-input-delay-sd-uhs-sdr50", SDHCI_CDNS_PHY_DLY_UHS_SDR50, },
  100. { "cdns,phy-input-delay-sd-uhs-ddr50", SDHCI_CDNS_PHY_DLY_UHS_DDR50, },
  101. { "cdns,phy-input-delay-mmc-highspeed", SDHCI_CDNS_PHY_DLY_EMMC_SDR, },
  102. { "cdns,phy-input-delay-mmc-ddr", SDHCI_CDNS_PHY_DLY_EMMC_DDR, },
  103. { "cdns,phy-dll-delay-sdclk", SDHCI_CDNS_PHY_DLY_SDCLK, },
  104. { "cdns,phy-dll-delay-sdclk-hsmmc", SDHCI_CDNS_PHY_DLY_HSMMC, },
  105. { "cdns,phy-dll-delay-strobe", SDHCI_CDNS_PHY_DLY_STROBE, },
  106. };
  107. static inline void cdns_writel(struct sdhci_cdns_priv *priv, u32 val,
  108. void __iomem *reg)
  109. {
  110. writel(val, reg);
  111. }
  112. static int sdhci_cdns_write_phy_reg(struct sdhci_cdns_priv *priv,
  113. u8 addr, u8 data)
  114. {
  115. void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS04;
  116. u32 tmp;
  117. int ret;
  118. ret = readl_poll_timeout(reg, tmp, !(tmp & SDHCI_CDNS_HRS04_ACK),
  119. 0, 10);
  120. if (ret)
  121. return ret;
  122. tmp = FIELD_PREP(SDHCI_CDNS_HRS04_WDATA, data) |
  123. FIELD_PREP(SDHCI_CDNS_HRS04_ADDR, addr);
  124. priv->priv_writel(priv, tmp, reg);
  125. tmp |= SDHCI_CDNS_HRS04_WR;
  126. priv->priv_writel(priv, tmp, reg);
  127. ret = readl_poll_timeout(reg, tmp, tmp & SDHCI_CDNS_HRS04_ACK, 0, 10);
  128. if (ret)
  129. return ret;
  130. tmp &= ~SDHCI_CDNS_HRS04_WR;
  131. priv->priv_writel(priv, tmp, reg);
  132. ret = readl_poll_timeout(reg, tmp, !(tmp & SDHCI_CDNS_HRS04_ACK),
  133. 0, 10);
  134. return ret;
  135. }
  136. static unsigned int sdhci_cdns_phy_param_count(struct device_node *np)
  137. {
  138. unsigned int count = 0;
  139. int i;
  140. for (i = 0; i < ARRAY_SIZE(sdhci_cdns_phy_cfgs); i++)
  141. if (of_property_present(np, sdhci_cdns_phy_cfgs[i].property))
  142. count++;
  143. return count;
  144. }
  145. static void sdhci_cdns_phy_param_parse(struct device_node *np,
  146. struct sdhci_cdns_priv *priv)
  147. {
  148. struct sdhci_cdns_phy_param *p = priv->phy_params;
  149. u32 val;
  150. int ret, i;
  151. for (i = 0; i < ARRAY_SIZE(sdhci_cdns_phy_cfgs); i++) {
  152. ret = of_property_read_u32(np, sdhci_cdns_phy_cfgs[i].property,
  153. &val);
  154. if (ret)
  155. continue;
  156. p->addr = sdhci_cdns_phy_cfgs[i].addr;
  157. p->data = val;
  158. p++;
  159. }
  160. }
  161. static int sdhci_cdns_phy_init(struct sdhci_cdns_priv *priv)
  162. {
  163. int ret, i;
  164. for (i = 0; i < priv->nr_phy_params; i++) {
  165. ret = sdhci_cdns_write_phy_reg(priv, priv->phy_params[i].addr,
  166. priv->phy_params[i].data);
  167. if (ret)
  168. return ret;
  169. }
  170. return 0;
  171. }
  172. static void *sdhci_cdns_priv(struct sdhci_host *host)
  173. {
  174. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  175. return sdhci_pltfm_priv(pltfm_host);
  176. }
  177. static unsigned int sdhci_cdns_get_timeout_clock(struct sdhci_host *host)
  178. {
  179. /*
  180. * Cadence's spec says the Timeout Clock Frequency is the same as the
  181. * Base Clock Frequency.
  182. */
  183. return host->max_clk;
  184. }
  185. static void sdhci_cdns_set_emmc_mode(struct sdhci_cdns_priv *priv, u32 mode)
  186. {
  187. u32 tmp;
  188. /* The speed mode for eMMC is selected by HRS06 register */
  189. tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
  190. tmp &= ~SDHCI_CDNS_HRS06_MODE;
  191. tmp |= FIELD_PREP(SDHCI_CDNS_HRS06_MODE, mode);
  192. priv->priv_writel(priv, tmp, priv->hrs_addr + SDHCI_CDNS_HRS06);
  193. }
  194. static u32 sdhci_cdns_get_emmc_mode(struct sdhci_cdns_priv *priv)
  195. {
  196. u32 tmp;
  197. tmp = readl(priv->hrs_addr + SDHCI_CDNS_HRS06);
  198. return FIELD_GET(SDHCI_CDNS_HRS06_MODE, tmp);
  199. }
  200. static int sdhci_cdns_set_tune_val(struct sdhci_host *host, unsigned int val)
  201. {
  202. struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
  203. void __iomem *reg = priv->hrs_addr + SDHCI_CDNS_HRS06;
  204. u32 tmp;
  205. int i, ret;
  206. if (WARN_ON(!FIELD_FIT(SDHCI_CDNS_HRS06_TUNE, val)))
  207. return -EINVAL;
  208. tmp = readl(reg);
  209. tmp &= ~SDHCI_CDNS_HRS06_TUNE;
  210. tmp |= FIELD_PREP(SDHCI_CDNS_HRS06_TUNE, val);
  211. /*
  212. * Workaround for IP errata:
  213. * The IP6116 SD/eMMC PHY design has a timing issue on receive data
  214. * path. Send tune request twice.
  215. */
  216. for (i = 0; i < 2; i++) {
  217. tmp |= SDHCI_CDNS_HRS06_TUNE_UP;
  218. priv->priv_writel(priv, tmp, reg);
  219. ret = readl_poll_timeout(reg, tmp,
  220. !(tmp & SDHCI_CDNS_HRS06_TUNE_UP),
  221. 0, 1);
  222. if (ret)
  223. return ret;
  224. }
  225. return 0;
  226. }
  227. /**
  228. * sdhci_cdns_tune_blkgap() - tune multi-block read gap
  229. * @mmc: MMC host
  230. *
  231. * Tune delay used in multi block read. To do so,
  232. * try sending multi-block read command with incremented gap, unless
  233. * it succeeds.
  234. *
  235. * Return: error code
  236. */
  237. static int sdhci_cdns_tune_blkgap(struct mmc_host *mmc)
  238. {
  239. struct sdhci_host *host = mmc_priv(mmc);
  240. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  241. struct sdhci_cdns_priv *priv = sdhci_pltfm_priv(pltfm_host);
  242. void __iomem *hrs37_reg = priv->hrs_addr + SDHCI_CDNS_HRS37;
  243. void __iomem *hrs38_reg = priv->hrs_addr + SDHCI_CDNS_HRS38;
  244. int ret;
  245. u32 gap;
  246. /* Currently only needed in HS200 mode */
  247. if (host->timing != MMC_TIMING_MMC_HS200)
  248. return 0;
  249. writel(SDHCI_CDNS_HRS37_MODE_MMC_HS200, hrs37_reg);
  250. for (gap = 0; gap <= SDHCI_CDNS_HRS38_BLKGAP_MAX; gap++) {
  251. writel(gap, hrs38_reg);
  252. ret = mmc_read_tuning(mmc, 512, 32);
  253. if (!ret)
  254. break;
  255. }
  256. dev_dbg(mmc_dev(mmc), "read block gap tune %s, gap %d\n", ret ? "failed" : "OK", gap);
  257. return ret;
  258. }
  259. /*
  260. * In SD mode, software must not use the hardware tuning and instead perform
  261. * an almost identical procedure to eMMC.
  262. */
  263. static int sdhci_cdns_execute_tuning(struct sdhci_host *host, u32 opcode)
  264. {
  265. int cur_streak = 0;
  266. int max_streak = 0;
  267. int end_of_streak = 0;
  268. int i;
  269. int ret;
  270. /*
  271. * Do not execute tuning for UHS_SDR50 or UHS_DDR50.
  272. * The delay is set by probe, based on the DT properties.
  273. */
  274. if (host->timing != MMC_TIMING_MMC_HS200 &&
  275. host->timing != MMC_TIMING_UHS_SDR104)
  276. return 0;
  277. for (i = 0; i < SDHCI_CDNS_MAX_TUNING_LOOP; i++) {
  278. if (sdhci_cdns_set_tune_val(host, i) ||
  279. mmc_send_tuning(host->mmc, opcode, NULL)) { /* bad */
  280. cur_streak = 0;
  281. } else { /* good */
  282. cur_streak++;
  283. if (cur_streak > max_streak) {
  284. max_streak = cur_streak;
  285. end_of_streak = i;
  286. }
  287. }
  288. }
  289. if (!max_streak) {
  290. dev_err(mmc_dev(host->mmc), "no tuning point found\n");
  291. return -EIO;
  292. }
  293. ret = sdhci_cdns_set_tune_val(host, end_of_streak - max_streak / 2);
  294. if (ret)
  295. return ret;
  296. return sdhci_cdns_tune_blkgap(host->mmc);
  297. }
  298. static void sdhci_cdns_set_uhs_signaling(struct sdhci_host *host,
  299. unsigned int timing)
  300. {
  301. struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
  302. u32 mode;
  303. switch (timing) {
  304. case MMC_TIMING_MMC_HS:
  305. mode = SDHCI_CDNS_HRS06_MODE_MMC_SDR;
  306. break;
  307. case MMC_TIMING_MMC_DDR52:
  308. mode = SDHCI_CDNS_HRS06_MODE_MMC_DDR;
  309. break;
  310. case MMC_TIMING_MMC_HS200:
  311. mode = SDHCI_CDNS_HRS06_MODE_MMC_HS200;
  312. break;
  313. case MMC_TIMING_MMC_HS400:
  314. if (priv->enhanced_strobe)
  315. mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400ES;
  316. else
  317. mode = SDHCI_CDNS_HRS06_MODE_MMC_HS400;
  318. break;
  319. default:
  320. mode = SDHCI_CDNS_HRS06_MODE_SD;
  321. break;
  322. }
  323. sdhci_cdns_set_emmc_mode(priv, mode);
  324. /* For SD, fall back to the default handler */
  325. if (mode == SDHCI_CDNS_HRS06_MODE_SD)
  326. sdhci_set_uhs_signaling(host, timing);
  327. }
  328. /* Elba control register bits [6:3] are byte-lane enables */
  329. #define ELBA_BYTE_ENABLE_MASK(x) ((x) << 3)
  330. /*
  331. * The Pensando Elba SoC explicitly controls byte-lane enabling on writes
  332. * which includes writes to the HRS registers. The write lock (wrlock)
  333. * is used to ensure byte-lane enable, using write control (ctl_addr),
  334. * occurs before the data write.
  335. */
  336. static void elba_priv_writel(struct sdhci_cdns_priv *priv, u32 val,
  337. void __iomem *reg)
  338. {
  339. unsigned long flags;
  340. spin_lock_irqsave(&priv->wrlock, flags);
  341. writel(GENMASK(7, 3), priv->ctl_addr);
  342. writel(val, reg);
  343. spin_unlock_irqrestore(&priv->wrlock, flags);
  344. }
  345. static void elba_write_l(struct sdhci_host *host, u32 val, int reg)
  346. {
  347. elba_priv_writel(sdhci_cdns_priv(host), val, host->ioaddr + reg);
  348. }
  349. static void elba_write_w(struct sdhci_host *host, u16 val, int reg)
  350. {
  351. struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
  352. u32 shift = reg & GENMASK(1, 0);
  353. unsigned long flags;
  354. u32 byte_enables;
  355. byte_enables = GENMASK(1, 0) << shift;
  356. spin_lock_irqsave(&priv->wrlock, flags);
  357. writel(ELBA_BYTE_ENABLE_MASK(byte_enables), priv->ctl_addr);
  358. writew(val, host->ioaddr + reg);
  359. spin_unlock_irqrestore(&priv->wrlock, flags);
  360. }
  361. static void elba_write_b(struct sdhci_host *host, u8 val, int reg)
  362. {
  363. struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
  364. u32 shift = reg & GENMASK(1, 0);
  365. unsigned long flags;
  366. u32 byte_enables;
  367. byte_enables = BIT(0) << shift;
  368. spin_lock_irqsave(&priv->wrlock, flags);
  369. writel(ELBA_BYTE_ENABLE_MASK(byte_enables), priv->ctl_addr);
  370. writeb(val, host->ioaddr + reg);
  371. spin_unlock_irqrestore(&priv->wrlock, flags);
  372. }
  373. static const struct sdhci_ops sdhci_elba_ops = {
  374. .write_l = elba_write_l,
  375. .write_w = elba_write_w,
  376. .write_b = elba_write_b,
  377. .set_clock = sdhci_set_clock,
  378. .get_timeout_clock = sdhci_cdns_get_timeout_clock,
  379. .set_bus_width = sdhci_set_bus_width,
  380. .reset = sdhci_reset,
  381. .set_uhs_signaling = sdhci_cdns_set_uhs_signaling,
  382. };
  383. static int elba_drv_init(struct platform_device *pdev)
  384. {
  385. struct sdhci_host *host = platform_get_drvdata(pdev);
  386. struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
  387. void __iomem *ioaddr;
  388. host->mmc->caps |= MMC_CAP_1_8V_DDR | MMC_CAP_8_BIT_DATA;
  389. spin_lock_init(&priv->wrlock);
  390. /* Byte-lane control register */
  391. ioaddr = devm_platform_ioremap_resource(pdev, 1);
  392. if (IS_ERR(ioaddr))
  393. return PTR_ERR(ioaddr);
  394. priv->ctl_addr = ioaddr;
  395. priv->priv_writel = elba_priv_writel;
  396. writel(ELBA_BYTE_ENABLE_MASK(0xf), priv->ctl_addr);
  397. return 0;
  398. }
  399. static const struct sdhci_ops sdhci_cdns_ops = {
  400. .set_clock = sdhci_set_clock,
  401. .get_timeout_clock = sdhci_cdns_get_timeout_clock,
  402. .set_bus_width = sdhci_set_bus_width,
  403. .reset = sdhci_reset,
  404. .platform_execute_tuning = sdhci_cdns_execute_tuning,
  405. .set_uhs_signaling = sdhci_cdns_set_uhs_signaling,
  406. };
  407. static const struct sdhci_cdns_drv_data sdhci_cdns_uniphier_drv_data = {
  408. .pltfm_data = {
  409. .ops = &sdhci_cdns_ops,
  410. .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
  411. },
  412. };
  413. static const struct sdhci_cdns_drv_data sdhci_elba_drv_data = {
  414. .init = elba_drv_init,
  415. .pltfm_data = {
  416. .ops = &sdhci_elba_ops,
  417. },
  418. };
  419. static const struct sdhci_cdns_drv_data sdhci_eyeq_drv_data = {
  420. .pltfm_data = {
  421. .ops = &sdhci_cdns_ops,
  422. .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
  423. },
  424. };
  425. static const struct sdhci_cdns_drv_data sdhci_cdns_drv_data = {
  426. .pltfm_data = {
  427. .ops = &sdhci_cdns_ops,
  428. },
  429. };
  430. static void sdhci_cdns_hs400_enhanced_strobe(struct mmc_host *mmc,
  431. struct mmc_ios *ios)
  432. {
  433. struct sdhci_host *host = mmc_priv(mmc);
  434. struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
  435. u32 mode;
  436. priv->enhanced_strobe = ios->enhanced_strobe;
  437. mode = sdhci_cdns_get_emmc_mode(priv);
  438. if (mode == SDHCI_CDNS_HRS06_MODE_MMC_HS400 && ios->enhanced_strobe)
  439. sdhci_cdns_set_emmc_mode(priv,
  440. SDHCI_CDNS_HRS06_MODE_MMC_HS400ES);
  441. if (mode == SDHCI_CDNS_HRS06_MODE_MMC_HS400ES && !ios->enhanced_strobe)
  442. sdhci_cdns_set_emmc_mode(priv,
  443. SDHCI_CDNS_HRS06_MODE_MMC_HS400);
  444. }
  445. static void sdhci_cdns_mmc_hw_reset(struct mmc_host *mmc)
  446. {
  447. struct sdhci_host *host = mmc_priv(mmc);
  448. struct sdhci_cdns_priv *priv = sdhci_cdns_priv(host);
  449. dev_dbg(mmc_dev(host->mmc), "emmc hardware reset\n");
  450. reset_control_assert(priv->rst_hw);
  451. /* For eMMC, minimum is 1us but give it 3us for good measure */
  452. udelay(3);
  453. reset_control_deassert(priv->rst_hw);
  454. /* For eMMC, minimum is 200us but give it 300us for good measure */
  455. usleep_range(300, 1000);
  456. }
  457. static int sdhci_cdns_probe(struct platform_device *pdev)
  458. {
  459. struct sdhci_host *host;
  460. const struct sdhci_cdns_drv_data *data;
  461. struct sdhci_pltfm_host *pltfm_host;
  462. struct sdhci_cdns_priv *priv;
  463. struct clk *clk;
  464. unsigned int nr_phy_params;
  465. int ret;
  466. struct device *dev = &pdev->dev;
  467. static const u16 version = SDHCI_SPEC_400 << SDHCI_SPEC_VER_SHIFT;
  468. clk = devm_clk_get_enabled(dev, NULL);
  469. if (IS_ERR(clk))
  470. return PTR_ERR(clk);
  471. data = of_device_get_match_data(dev);
  472. if (!data)
  473. data = &sdhci_cdns_drv_data;
  474. nr_phy_params = sdhci_cdns_phy_param_count(dev->of_node);
  475. host = sdhci_pltfm_init(pdev, &data->pltfm_data,
  476. struct_size(priv, phy_params, nr_phy_params));
  477. if (IS_ERR(host))
  478. return PTR_ERR(host);
  479. pltfm_host = sdhci_priv(host);
  480. pltfm_host->clk = clk;
  481. priv = sdhci_pltfm_priv(pltfm_host);
  482. priv->nr_phy_params = nr_phy_params;
  483. priv->hrs_addr = host->ioaddr;
  484. priv->enhanced_strobe = false;
  485. priv->priv_writel = cdns_writel;
  486. host->ioaddr += SDHCI_CDNS_SRS_BASE;
  487. host->mmc_host_ops.hs400_enhanced_strobe =
  488. sdhci_cdns_hs400_enhanced_strobe;
  489. if (data->init) {
  490. ret = data->init(pdev);
  491. if (ret)
  492. return ret;
  493. }
  494. sdhci_enable_v4_mode(host);
  495. __sdhci_read_caps(host, &version, NULL, NULL);
  496. sdhci_get_of_property(pdev);
  497. ret = mmc_of_parse(host->mmc);
  498. if (ret)
  499. return ret;
  500. sdhci_cdns_phy_param_parse(dev->of_node, priv);
  501. ret = sdhci_cdns_phy_init(priv);
  502. if (ret)
  503. return ret;
  504. if (host->mmc->caps & MMC_CAP_HW_RESET) {
  505. priv->rst_hw = devm_reset_control_get_optional_exclusive(dev, NULL);
  506. if (IS_ERR(priv->rst_hw))
  507. return dev_err_probe(mmc_dev(host->mmc), PTR_ERR(priv->rst_hw),
  508. "reset controller error\n");
  509. if (priv->rst_hw)
  510. host->mmc_host_ops.card_hw_reset = sdhci_cdns_mmc_hw_reset;
  511. }
  512. return sdhci_add_host(host);
  513. }
  514. static int sdhci_cdns_resume(struct device *dev)
  515. {
  516. struct sdhci_host *host = dev_get_drvdata(dev);
  517. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  518. struct sdhci_cdns_priv *priv = sdhci_pltfm_priv(pltfm_host);
  519. int ret;
  520. ret = clk_prepare_enable(pltfm_host->clk);
  521. if (ret)
  522. return ret;
  523. ret = sdhci_cdns_phy_init(priv);
  524. if (ret)
  525. goto disable_clk;
  526. ret = sdhci_resume_host(host);
  527. if (ret)
  528. goto disable_clk;
  529. return 0;
  530. disable_clk:
  531. clk_disable_unprepare(pltfm_host->clk);
  532. return ret;
  533. }
  534. static DEFINE_SIMPLE_DEV_PM_OPS(sdhci_cdns_pm_ops, sdhci_pltfm_suspend, sdhci_cdns_resume);
  535. static const struct of_device_id sdhci_cdns_match[] = {
  536. {
  537. .compatible = "socionext,uniphier-sd4hc",
  538. .data = &sdhci_cdns_uniphier_drv_data,
  539. },
  540. {
  541. .compatible = "amd,pensando-elba-sd4hc",
  542. .data = &sdhci_elba_drv_data,
  543. },
  544. {
  545. .compatible = "mobileye,eyeq-sd4hc",
  546. .data = &sdhci_eyeq_drv_data,
  547. },
  548. { .compatible = "cdns,sd4hc" },
  549. { /* sentinel */ }
  550. };
  551. MODULE_DEVICE_TABLE(of, sdhci_cdns_match);
  552. static struct platform_driver sdhci_cdns_driver = {
  553. .driver = {
  554. .name = "sdhci-cdns",
  555. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  556. .pm = pm_sleep_ptr(&sdhci_cdns_pm_ops),
  557. .of_match_table = sdhci_cdns_match,
  558. },
  559. .probe = sdhci_cdns_probe,
  560. .remove = sdhci_pltfm_remove,
  561. };
  562. module_platform_driver(sdhci_cdns_driver);
  563. MODULE_AUTHOR("Masahiro Yamada <yamada.masahiro@socionext.com>");
  564. MODULE_DESCRIPTION("Cadence SD/SDIO/eMMC Host Controller Driver");
  565. MODULE_LICENSE("GPL");