sdhci-of-dwcmshc.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Driver for Synopsys DesignWare Cores Mobile Storage Host Controller
  4. *
  5. * Copyright (C) 2018 Synaptics Incorporated
  6. *
  7. * Author: Jisheng Zhang <[email protected]>
  8. */
  9. #include <linux/acpi.h>
  10. #include <linux/clk.h>
  11. #include <linux/dma-mapping.h>
  12. #include <linux/iopoll.h>
  13. #include <linux/kernel.h>
  14. #include <linux/module.h>
  15. #include <linux/of.h>
  16. #include <linux/of_device.h>
  17. #include <linux/reset.h>
  18. #include <linux/sizes.h>
  19. #include "sdhci-pltfm.h"
  20. #define SDHCI_DWCMSHC_ARG2_STUFF GENMASK(31, 16)
  21. /* DWCMSHC specific Mode Select value */
  22. #define DWCMSHC_CTRL_HS400 0x7
  23. /* DWC IP vendor area 1 pointer */
  24. #define DWCMSHC_P_VENDOR_AREA1 0xe8
  25. #define DWCMSHC_AREA1_MASK GENMASK(11, 0)
  26. /* Offset inside the vendor area 1 */
  27. #define DWCMSHC_HOST_CTRL3 0x8
  28. #define DWCMSHC_EMMC_CONTROL 0x2c
  29. #define DWCMSHC_CARD_IS_EMMC BIT(0)
  30. #define DWCMSHC_ENHANCED_STROBE BIT(8)
  31. #define DWCMSHC_EMMC_ATCTRL 0x40
  32. /* Rockchip specific Registers */
  33. #define DWCMSHC_EMMC_DLL_CTRL 0x800
  34. #define DWCMSHC_EMMC_DLL_RXCLK 0x804
  35. #define DWCMSHC_EMMC_DLL_TXCLK 0x808
  36. #define DWCMSHC_EMMC_DLL_STRBIN 0x80c
  37. #define DECMSHC_EMMC_DLL_CMDOUT 0x810
  38. #define DWCMSHC_EMMC_DLL_STATUS0 0x840
  39. #define DWCMSHC_EMMC_DLL_START BIT(0)
  40. #define DWCMSHC_EMMC_DLL_LOCKED BIT(8)
  41. #define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9)
  42. #define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29
  43. #define DWCMSHC_EMMC_DLL_START_POINT 16
  44. #define DWCMSHC_EMMC_DLL_INC 8
  45. #define DWCMSHC_EMMC_DLL_DLYENA BIT(27)
  46. #define DLL_TXCLK_TAPNUM_DEFAULT 0x10
  47. #define DLL_TXCLK_TAPNUM_90_DEGREES 0xA
  48. #define DLL_TXCLK_TAPNUM_FROM_SW BIT(24)
  49. #define DLL_STRBIN_TAPNUM_DEFAULT 0x8
  50. #define DLL_STRBIN_TAPNUM_FROM_SW BIT(24)
  51. #define DLL_STRBIN_DELAY_NUM_SEL BIT(26)
  52. #define DLL_STRBIN_DELAY_NUM_OFFSET 16
  53. #define DLL_STRBIN_DELAY_NUM_DEFAULT 0x16
  54. #define DLL_RXCLK_NO_INVERTER 1
  55. #define DLL_RXCLK_INVERTER 0
  56. #define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8
  57. #define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24)
  58. #define DLL_CMDOUT_SRC_CLK_NEG BIT(28)
  59. #define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29)
  60. #define DLL_LOCK_WO_TMOUT(x) \
  61. ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \
  62. (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0))
  63. #define RK35xx_MAX_CLKS 3
  64. #define BOUNDARY_OK(addr, len) \
  65. ((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1)))
  66. enum dwcmshc_rk_type {
  67. DWCMSHC_RK3568,
  68. DWCMSHC_RK3588,
  69. };
  70. struct rk35xx_priv {
  71. /* Rockchip specified optional clocks */
  72. struct clk_bulk_data rockchip_clks[RK35xx_MAX_CLKS];
  73. struct reset_control *reset;
  74. enum dwcmshc_rk_type devtype;
  75. u8 txclk_tapnum;
  76. };
  77. struct dwcmshc_priv {
  78. struct clk *bus_clk;
  79. int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */
  80. void *priv; /* pointer to SoC private stuff */
  81. };
  82. /*
  83. * If DMA addr spans 128MB boundary, we split the DMA transfer into two
  84. * so that each DMA transfer doesn't exceed the boundary.
  85. */
  86. static void dwcmshc_adma_write_desc(struct sdhci_host *host, void **desc,
  87. dma_addr_t addr, int len, unsigned int cmd)
  88. {
  89. int tmplen, offset;
  90. if (likely(!len || BOUNDARY_OK(addr, len))) {
  91. sdhci_adma_write_desc(host, desc, addr, len, cmd);
  92. return;
  93. }
  94. offset = addr & (SZ_128M - 1);
  95. tmplen = SZ_128M - offset;
  96. sdhci_adma_write_desc(host, desc, addr, tmplen, cmd);
  97. addr += tmplen;
  98. len -= tmplen;
  99. sdhci_adma_write_desc(host, desc, addr, len, cmd);
  100. }
  101. static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host)
  102. {
  103. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  104. if (pltfm_host->clk)
  105. return sdhci_pltfm_clk_get_max_clock(host);
  106. else
  107. return pltfm_host->clock;
  108. }
  109. static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc,
  110. struct mmc_request *mrq)
  111. {
  112. struct sdhci_host *host = mmc_priv(mmc);
  113. /*
  114. * No matter V4 is enabled or not, ARGUMENT2 register is 32-bit
  115. * block count register which doesn't support stuff bits of
  116. * CMD23 argument on dwcmsch host controller.
  117. */
  118. if (mrq->sbc && (mrq->sbc->arg & SDHCI_DWCMSHC_ARG2_STUFF))
  119. host->flags &= ~SDHCI_AUTO_CMD23;
  120. else
  121. host->flags |= SDHCI_AUTO_CMD23;
  122. }
  123. static void dwcmshc_request(struct mmc_host *mmc, struct mmc_request *mrq)
  124. {
  125. dwcmshc_check_auto_cmd23(mmc, mrq);
  126. sdhci_request(mmc, mrq);
  127. }
  128. static void dwcmshc_set_uhs_signaling(struct sdhci_host *host,
  129. unsigned int timing)
  130. {
  131. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  132. struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
  133. u16 ctrl, ctrl_2;
  134. ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
  135. /* Select Bus Speed Mode for host */
  136. ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
  137. if ((timing == MMC_TIMING_MMC_HS200) ||
  138. (timing == MMC_TIMING_UHS_SDR104))
  139. ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
  140. else if (timing == MMC_TIMING_UHS_SDR12)
  141. ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
  142. else if ((timing == MMC_TIMING_UHS_SDR25) ||
  143. (timing == MMC_TIMING_MMC_HS))
  144. ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
  145. else if (timing == MMC_TIMING_UHS_SDR50)
  146. ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
  147. else if ((timing == MMC_TIMING_UHS_DDR50) ||
  148. (timing == MMC_TIMING_MMC_DDR52))
  149. ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
  150. else if (timing == MMC_TIMING_MMC_HS400) {
  151. /* set CARD_IS_EMMC bit to enable Data Strobe for HS400 */
  152. ctrl = sdhci_readw(host, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL);
  153. ctrl |= DWCMSHC_CARD_IS_EMMC;
  154. sdhci_writew(host, ctrl, priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL);
  155. ctrl_2 |= DWCMSHC_CTRL_HS400;
  156. }
  157. sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
  158. }
  159. static void dwcmshc_hs400_enhanced_strobe(struct mmc_host *mmc,
  160. struct mmc_ios *ios)
  161. {
  162. u32 vendor;
  163. struct sdhci_host *host = mmc_priv(mmc);
  164. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  165. struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
  166. int reg = priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL;
  167. vendor = sdhci_readl(host, reg);
  168. if (ios->enhanced_strobe)
  169. vendor |= DWCMSHC_ENHANCED_STROBE;
  170. else
  171. vendor &= ~DWCMSHC_ENHANCED_STROBE;
  172. sdhci_writel(host, vendor, reg);
  173. }
  174. static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock)
  175. {
  176. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  177. struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
  178. struct rk35xx_priv *priv = dwc_priv->priv;
  179. u8 txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT;
  180. u32 extra, reg;
  181. int err;
  182. host->mmc->actual_clock = 0;
  183. if (clock == 0) {
  184. /* Disable interface clock at initial state. */
  185. sdhci_set_clock(host, clock);
  186. return;
  187. }
  188. /* Rockchip platform only support 375KHz for identify mode */
  189. if (clock <= 400000)
  190. clock = 375000;
  191. err = clk_set_rate(pltfm_host->clk, clock);
  192. if (err)
  193. dev_err(mmc_dev(host->mmc), "fail to set clock %d", clock);
  194. sdhci_set_clock(host, clock);
  195. /* Disable cmd conflict check */
  196. reg = dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3;
  197. extra = sdhci_readl(host, reg);
  198. extra &= ~BIT(0);
  199. sdhci_writel(host, extra, reg);
  200. if (clock <= 52000000) {
  201. /* Disable DLL and reset both of sample and drive clock */
  202. sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
  203. sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_RXCLK);
  204. sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
  205. sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
  206. /*
  207. * Before switching to hs400es mode, the driver will enable
  208. * enhanced strobe first. PHY needs to configure the parameters
  209. * of enhanced strobe first.
  210. */
  211. extra = DWCMSHC_EMMC_DLL_DLYENA |
  212. DLL_STRBIN_DELAY_NUM_SEL |
  213. DLL_STRBIN_DELAY_NUM_DEFAULT << DLL_STRBIN_DELAY_NUM_OFFSET;
  214. sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
  215. return;
  216. }
  217. /* Reset DLL */
  218. sdhci_writel(host, BIT(1), DWCMSHC_EMMC_DLL_CTRL);
  219. udelay(1);
  220. sdhci_writel(host, 0x0, DWCMSHC_EMMC_DLL_CTRL);
  221. /*
  222. * We shouldn't set DLL_RXCLK_NO_INVERTER for identify mode but
  223. * we must set it in higher speed mode.
  224. */
  225. extra = DWCMSHC_EMMC_DLL_DLYENA;
  226. if (priv->devtype == DWCMSHC_RK3568)
  227. extra |= DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
  228. sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
  229. /* Init DLL settings */
  230. extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT |
  231. 0x2 << DWCMSHC_EMMC_DLL_INC |
  232. DWCMSHC_EMMC_DLL_START;
  233. sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL);
  234. err = readl_poll_timeout(host->ioaddr + DWCMSHC_EMMC_DLL_STATUS0,
  235. extra, DLL_LOCK_WO_TMOUT(extra), 1,
  236. 500 * USEC_PER_MSEC);
  237. if (err) {
  238. dev_err(mmc_dev(host->mmc), "DLL lock timeout!\n");
  239. return;
  240. }
  241. extra = 0x1 << 16 | /* tune clock stop en */
  242. 0x2 << 17 | /* pre-change delay */
  243. 0x3 << 19; /* post-change delay */
  244. sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL);
  245. if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
  246. host->mmc->ios.timing == MMC_TIMING_MMC_HS400)
  247. txclk_tapnum = priv->txclk_tapnum;
  248. if ((priv->devtype == DWCMSHC_RK3588) && host->mmc->ios.timing == MMC_TIMING_MMC_HS400) {
  249. txclk_tapnum = DLL_TXCLK_TAPNUM_90_DEGREES;
  250. extra = DLL_CMDOUT_SRC_CLK_NEG |
  251. DLL_CMDOUT_EN_SRC_CLK_NEG |
  252. DWCMSHC_EMMC_DLL_DLYENA |
  253. DLL_CMDOUT_TAPNUM_90_DEGREES |
  254. DLL_CMDOUT_TAPNUM_FROM_SW;
  255. sdhci_writel(host, extra, DECMSHC_EMMC_DLL_CMDOUT);
  256. }
  257. extra = DWCMSHC_EMMC_DLL_DLYENA |
  258. DLL_TXCLK_TAPNUM_FROM_SW |
  259. DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL |
  260. txclk_tapnum;
  261. sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
  262. extra = DWCMSHC_EMMC_DLL_DLYENA |
  263. DLL_STRBIN_TAPNUM_DEFAULT |
  264. DLL_STRBIN_TAPNUM_FROM_SW;
  265. sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
  266. }
  267. static void rk35xx_sdhci_reset(struct sdhci_host *host, u8 mask)
  268. {
  269. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  270. struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host);
  271. struct rk35xx_priv *priv = dwc_priv->priv;
  272. if (mask & SDHCI_RESET_ALL && priv->reset) {
  273. reset_control_assert(priv->reset);
  274. udelay(1);
  275. reset_control_deassert(priv->reset);
  276. }
  277. sdhci_reset(host, mask);
  278. }
  279. static const struct sdhci_ops sdhci_dwcmshc_ops = {
  280. .set_clock = sdhci_set_clock,
  281. .set_bus_width = sdhci_set_bus_width,
  282. .set_uhs_signaling = dwcmshc_set_uhs_signaling,
  283. .get_max_clock = dwcmshc_get_max_clock,
  284. .reset = sdhci_reset,
  285. .adma_write_desc = dwcmshc_adma_write_desc,
  286. };
  287. static const struct sdhci_ops sdhci_dwcmshc_rk35xx_ops = {
  288. .set_clock = dwcmshc_rk3568_set_clock,
  289. .set_bus_width = sdhci_set_bus_width,
  290. .set_uhs_signaling = dwcmshc_set_uhs_signaling,
  291. .get_max_clock = sdhci_pltfm_clk_get_max_clock,
  292. .reset = rk35xx_sdhci_reset,
  293. .adma_write_desc = dwcmshc_adma_write_desc,
  294. };
  295. static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = {
  296. .ops = &sdhci_dwcmshc_ops,
  297. .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
  298. .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
  299. };
  300. #ifdef CONFIG_ACPI
  301. static const struct sdhci_pltfm_data sdhci_dwcmshc_bf3_pdata = {
  302. .ops = &sdhci_dwcmshc_ops,
  303. .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
  304. .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
  305. SDHCI_QUIRK2_ACMD23_BROKEN,
  306. };
  307. #endif
  308. static const struct sdhci_pltfm_data sdhci_dwcmshc_rk35xx_pdata = {
  309. .ops = &sdhci_dwcmshc_rk35xx_ops,
  310. .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
  311. SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
  312. .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
  313. SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN,
  314. };
  315. static int dwcmshc_rk35xx_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
  316. {
  317. int err;
  318. struct rk35xx_priv *priv = dwc_priv->priv;
  319. priv->reset = devm_reset_control_array_get_optional_exclusive(mmc_dev(host->mmc));
  320. if (IS_ERR(priv->reset)) {
  321. err = PTR_ERR(priv->reset);
  322. dev_err(mmc_dev(host->mmc), "failed to get reset control %d\n", err);
  323. return err;
  324. }
  325. priv->rockchip_clks[0].id = "axi";
  326. priv->rockchip_clks[1].id = "block";
  327. priv->rockchip_clks[2].id = "timer";
  328. err = devm_clk_bulk_get_optional(mmc_dev(host->mmc), RK35xx_MAX_CLKS,
  329. priv->rockchip_clks);
  330. if (err) {
  331. dev_err(mmc_dev(host->mmc), "failed to get clocks %d\n", err);
  332. return err;
  333. }
  334. err = clk_bulk_prepare_enable(RK35xx_MAX_CLKS, priv->rockchip_clks);
  335. if (err) {
  336. dev_err(mmc_dev(host->mmc), "failed to enable clocks %d\n", err);
  337. return err;
  338. }
  339. if (of_property_read_u8(mmc_dev(host->mmc)->of_node, "rockchip,txclk-tapnum",
  340. &priv->txclk_tapnum))
  341. priv->txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT;
  342. /* Disable cmd conflict check */
  343. sdhci_writel(host, 0x0, dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3);
  344. /* Reset previous settings */
  345. sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
  346. sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN);
  347. return 0;
  348. }
  349. static void dwcmshc_rk35xx_postinit(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv)
  350. {
  351. /*
  352. * Don't support highspeed bus mode with low clk speed as we
  353. * cannot use DLL for this condition.
  354. */
  355. if (host->mmc->f_max <= 52000000) {
  356. dev_info(mmc_dev(host->mmc), "Disabling HS200/HS400, frequency too low (%d)\n",
  357. host->mmc->f_max);
  358. host->mmc->caps2 &= ~(MMC_CAP2_HS200 | MMC_CAP2_HS400);
  359. host->mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR);
  360. }
  361. }
  362. static const struct of_device_id sdhci_dwcmshc_dt_ids[] = {
  363. {
  364. .compatible = "rockchip,rk3588-dwcmshc",
  365. .data = &sdhci_dwcmshc_rk35xx_pdata,
  366. },
  367. {
  368. .compatible = "rockchip,rk3568-dwcmshc",
  369. .data = &sdhci_dwcmshc_rk35xx_pdata,
  370. },
  371. {
  372. .compatible = "snps,dwcmshc-sdhci",
  373. .data = &sdhci_dwcmshc_pdata,
  374. },
  375. {},
  376. };
  377. MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids);
  378. #ifdef CONFIG_ACPI
  379. static const struct acpi_device_id sdhci_dwcmshc_acpi_ids[] = {
  380. {
  381. .id = "MLNXBF30",
  382. .driver_data = (kernel_ulong_t)&sdhci_dwcmshc_bf3_pdata,
  383. },
  384. {}
  385. };
  386. #endif
  387. static int dwcmshc_probe(struct platform_device *pdev)
  388. {
  389. struct device *dev = &pdev->dev;
  390. struct sdhci_pltfm_host *pltfm_host;
  391. struct sdhci_host *host;
  392. struct dwcmshc_priv *priv;
  393. struct rk35xx_priv *rk_priv = NULL;
  394. const struct sdhci_pltfm_data *pltfm_data;
  395. int err;
  396. u32 extra;
  397. pltfm_data = device_get_match_data(&pdev->dev);
  398. if (!pltfm_data) {
  399. dev_err(&pdev->dev, "Error: No device match data found\n");
  400. return -ENODEV;
  401. }
  402. host = sdhci_pltfm_init(pdev, pltfm_data,
  403. sizeof(struct dwcmshc_priv));
  404. if (IS_ERR(host))
  405. return PTR_ERR(host);
  406. /*
  407. * extra adma table cnt for cross 128M boundary handling.
  408. */
  409. extra = DIV_ROUND_UP_ULL(dma_get_required_mask(dev), SZ_128M);
  410. if (extra > SDHCI_MAX_SEGS)
  411. extra = SDHCI_MAX_SEGS;
  412. host->adma_table_cnt += extra;
  413. pltfm_host = sdhci_priv(host);
  414. priv = sdhci_pltfm_priv(pltfm_host);
  415. if (dev->of_node) {
  416. pltfm_host->clk = devm_clk_get(dev, "core");
  417. if (IS_ERR(pltfm_host->clk)) {
  418. err = PTR_ERR(pltfm_host->clk);
  419. dev_err(dev, "failed to get core clk: %d\n", err);
  420. goto free_pltfm;
  421. }
  422. err = clk_prepare_enable(pltfm_host->clk);
  423. if (err)
  424. goto free_pltfm;
  425. priv->bus_clk = devm_clk_get(dev, "bus");
  426. if (!IS_ERR(priv->bus_clk))
  427. clk_prepare_enable(priv->bus_clk);
  428. }
  429. err = mmc_of_parse(host->mmc);
  430. if (err)
  431. goto err_clk;
  432. sdhci_get_of_property(pdev);
  433. priv->vendor_specific_area1 =
  434. sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK;
  435. host->mmc_host_ops.request = dwcmshc_request;
  436. host->mmc_host_ops.hs400_enhanced_strobe = dwcmshc_hs400_enhanced_strobe;
  437. if (pltfm_data == &sdhci_dwcmshc_rk35xx_pdata) {
  438. rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk35xx_priv), GFP_KERNEL);
  439. if (!rk_priv) {
  440. err = -ENOMEM;
  441. goto err_clk;
  442. }
  443. if (of_device_is_compatible(pdev->dev.of_node, "rockchip,rk3588-dwcmshc"))
  444. rk_priv->devtype = DWCMSHC_RK3588;
  445. else
  446. rk_priv->devtype = DWCMSHC_RK3568;
  447. priv->priv = rk_priv;
  448. err = dwcmshc_rk35xx_init(host, priv);
  449. if (err)
  450. goto err_clk;
  451. }
  452. host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
  453. err = sdhci_setup_host(host);
  454. if (err)
  455. goto err_clk;
  456. if (rk_priv)
  457. dwcmshc_rk35xx_postinit(host, priv);
  458. err = __sdhci_add_host(host);
  459. if (err)
  460. goto err_setup_host;
  461. return 0;
  462. err_setup_host:
  463. sdhci_cleanup_host(host);
  464. err_clk:
  465. clk_disable_unprepare(pltfm_host->clk);
  466. clk_disable_unprepare(priv->bus_clk);
  467. if (rk_priv)
  468. clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
  469. rk_priv->rockchip_clks);
  470. free_pltfm:
  471. sdhci_pltfm_free(pdev);
  472. return err;
  473. }
  474. static int dwcmshc_remove(struct platform_device *pdev)
  475. {
  476. struct sdhci_host *host = platform_get_drvdata(pdev);
  477. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  478. struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
  479. struct rk35xx_priv *rk_priv = priv->priv;
  480. sdhci_remove_host(host, 0);
  481. clk_disable_unprepare(pltfm_host->clk);
  482. clk_disable_unprepare(priv->bus_clk);
  483. if (rk_priv)
  484. clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
  485. rk_priv->rockchip_clks);
  486. sdhci_pltfm_free(pdev);
  487. return 0;
  488. }
  489. #ifdef CONFIG_PM_SLEEP
  490. static int dwcmshc_suspend(struct device *dev)
  491. {
  492. struct sdhci_host *host = dev_get_drvdata(dev);
  493. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  494. struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
  495. struct rk35xx_priv *rk_priv = priv->priv;
  496. int ret;
  497. ret = sdhci_suspend_host(host);
  498. if (ret)
  499. return ret;
  500. clk_disable_unprepare(pltfm_host->clk);
  501. if (!IS_ERR(priv->bus_clk))
  502. clk_disable_unprepare(priv->bus_clk);
  503. if (rk_priv)
  504. clk_bulk_disable_unprepare(RK35xx_MAX_CLKS,
  505. rk_priv->rockchip_clks);
  506. return ret;
  507. }
  508. static int dwcmshc_resume(struct device *dev)
  509. {
  510. struct sdhci_host *host = dev_get_drvdata(dev);
  511. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  512. struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host);
  513. struct rk35xx_priv *rk_priv = priv->priv;
  514. int ret;
  515. ret = clk_prepare_enable(pltfm_host->clk);
  516. if (ret)
  517. return ret;
  518. if (!IS_ERR(priv->bus_clk)) {
  519. ret = clk_prepare_enable(priv->bus_clk);
  520. if (ret)
  521. return ret;
  522. }
  523. if (rk_priv) {
  524. ret = clk_bulk_prepare_enable(RK35xx_MAX_CLKS,
  525. rk_priv->rockchip_clks);
  526. if (ret)
  527. return ret;
  528. }
  529. return sdhci_resume_host(host);
  530. }
  531. #endif
  532. static SIMPLE_DEV_PM_OPS(dwcmshc_pmops, dwcmshc_suspend, dwcmshc_resume);
  533. static struct platform_driver sdhci_dwcmshc_driver = {
  534. .driver = {
  535. .name = "sdhci-dwcmshc",
  536. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  537. .of_match_table = sdhci_dwcmshc_dt_ids,
  538. .acpi_match_table = ACPI_PTR(sdhci_dwcmshc_acpi_ids),
  539. .pm = &dwcmshc_pmops,
  540. },
  541. .probe = dwcmshc_probe,
  542. .remove = dwcmshc_remove,
  543. };
  544. module_platform_driver(sdhci_dwcmshc_driver);
  545. MODULE_DESCRIPTION("SDHCI platform driver for Synopsys DWC MSHC");
  546. MODULE_AUTHOR("Jisheng Zhang <[email protected]>");
  547. MODULE_LICENSE("GPL v2");