sdhci-xenon.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Driver for Marvell Xenon SDHC as a platform device
  4. *
  5. * Copyright (C) 2016 Marvell, All Rights Reserved.
  6. *
  7. * Author: Hu Ziji <[email protected]>
  8. * Date: 2016-8-24
  9. *
  10. * Inspired by Jisheng Zhang <[email protected]>
  11. * Special thanks to Video BG4 project team.
  12. */
  13. #include <linux/acpi.h>
  14. #include <linux/delay.h>
  15. #include <linux/ktime.h>
  16. #include <linux/module.h>
  17. #include <linux/of.h>
  18. #include <linux/pm.h>
  19. #include <linux/pm_runtime.h>
  20. #include "sdhci-pltfm.h"
  21. #include "sdhci-xenon.h"
  22. static int xenon_enable_internal_clk(struct sdhci_host *host)
  23. {
  24. u32 reg;
  25. ktime_t timeout;
  26. reg = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
  27. reg |= SDHCI_CLOCK_INT_EN;
  28. sdhci_writel(host, reg, SDHCI_CLOCK_CONTROL);
  29. /* Wait max 20 ms */
  30. timeout = ktime_add_ms(ktime_get(), 20);
  31. while (1) {
  32. bool timedout = ktime_after(ktime_get(), timeout);
  33. reg = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
  34. if (reg & SDHCI_CLOCK_INT_STABLE)
  35. break;
  36. if (timedout) {
  37. dev_err(mmc_dev(host->mmc), "Internal clock never stabilised.\n");
  38. return -ETIMEDOUT;
  39. }
  40. usleep_range(900, 1100);
  41. }
  42. return 0;
  43. }
  44. /* Set SDCLK-off-while-idle */
  45. static void xenon_set_sdclk_off_idle(struct sdhci_host *host,
  46. unsigned char sdhc_id, bool enable)
  47. {
  48. u32 reg;
  49. u32 mask;
  50. reg = sdhci_readl(host, XENON_SYS_OP_CTRL);
  51. /* Get the bit shift basing on the SDHC index */
  52. mask = (0x1 << (XENON_SDCLK_IDLEOFF_ENABLE_SHIFT + sdhc_id));
  53. if (enable)
  54. reg |= mask;
  55. else
  56. reg &= ~mask;
  57. sdhci_writel(host, reg, XENON_SYS_OP_CTRL);
  58. }
  59. /* Enable/Disable the Auto Clock Gating function */
  60. static void xenon_set_acg(struct sdhci_host *host, bool enable)
  61. {
  62. u32 reg;
  63. reg = sdhci_readl(host, XENON_SYS_OP_CTRL);
  64. if (enable)
  65. reg &= ~XENON_AUTO_CLKGATE_DISABLE_MASK;
  66. else
  67. reg |= XENON_AUTO_CLKGATE_DISABLE_MASK;
  68. sdhci_writel(host, reg, XENON_SYS_OP_CTRL);
  69. }
  70. /* Enable this SDHC */
  71. static void xenon_enable_sdhc(struct sdhci_host *host,
  72. unsigned char sdhc_id)
  73. {
  74. u32 reg;
  75. reg = sdhci_readl(host, XENON_SYS_OP_CTRL);
  76. reg |= (BIT(sdhc_id) << XENON_SLOT_ENABLE_SHIFT);
  77. sdhci_writel(host, reg, XENON_SYS_OP_CTRL);
  78. host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY;
  79. /*
  80. * Force to clear BUS_TEST to
  81. * skip bus_test_pre and bus_test_post
  82. */
  83. host->mmc->caps &= ~MMC_CAP_BUS_WIDTH_TEST;
  84. }
  85. /* Disable this SDHC */
  86. static void xenon_disable_sdhc(struct sdhci_host *host,
  87. unsigned char sdhc_id)
  88. {
  89. u32 reg;
  90. reg = sdhci_readl(host, XENON_SYS_OP_CTRL);
  91. reg &= ~(BIT(sdhc_id) << XENON_SLOT_ENABLE_SHIFT);
  92. sdhci_writel(host, reg, XENON_SYS_OP_CTRL);
  93. }
  94. /* Enable Parallel Transfer Mode */
  95. static void xenon_enable_sdhc_parallel_tran(struct sdhci_host *host,
  96. unsigned char sdhc_id)
  97. {
  98. u32 reg;
  99. reg = sdhci_readl(host, XENON_SYS_EXT_OP_CTRL);
  100. reg |= BIT(sdhc_id);
  101. sdhci_writel(host, reg, XENON_SYS_EXT_OP_CTRL);
  102. }
  103. /* Mask command conflict error */
  104. static void xenon_mask_cmd_conflict_err(struct sdhci_host *host)
  105. {
  106. u32 reg;
  107. reg = sdhci_readl(host, XENON_SYS_EXT_OP_CTRL);
  108. reg |= XENON_MASK_CMD_CONFLICT_ERR;
  109. sdhci_writel(host, reg, XENON_SYS_EXT_OP_CTRL);
  110. }
  111. static void xenon_retune_setup(struct sdhci_host *host)
  112. {
  113. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  114. struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  115. u32 reg;
  116. /* Disable the Re-Tuning Request functionality */
  117. reg = sdhci_readl(host, XENON_SLOT_RETUNING_REQ_CTRL);
  118. reg &= ~XENON_RETUNING_COMPATIBLE;
  119. sdhci_writel(host, reg, XENON_SLOT_RETUNING_REQ_CTRL);
  120. /* Disable the Re-tuning Interrupt */
  121. reg = sdhci_readl(host, SDHCI_SIGNAL_ENABLE);
  122. reg &= ~SDHCI_INT_RETUNE;
  123. sdhci_writel(host, reg, SDHCI_SIGNAL_ENABLE);
  124. reg = sdhci_readl(host, SDHCI_INT_ENABLE);
  125. reg &= ~SDHCI_INT_RETUNE;
  126. sdhci_writel(host, reg, SDHCI_INT_ENABLE);
  127. /* Force to use Tuning Mode 1 */
  128. host->tuning_mode = SDHCI_TUNING_MODE_1;
  129. /* Set re-tuning period */
  130. host->tuning_count = 1 << (priv->tuning_count - 1);
  131. }
  132. /*
  133. * Operations inside struct sdhci_ops
  134. */
  135. /* Recover the Register Setting cleared during SOFTWARE_RESET_ALL */
  136. static void xenon_reset_exit(struct sdhci_host *host,
  137. unsigned char sdhc_id, u8 mask)
  138. {
  139. /* Only SOFTWARE RESET ALL will clear the register setting */
  140. if (!(mask & SDHCI_RESET_ALL))
  141. return;
  142. /* Disable tuning request and auto-retuning again */
  143. xenon_retune_setup(host);
  144. /*
  145. * The ACG should be turned off at the early init time, in order
  146. * to solve a possible issues with the 1.8V regulator stabilization.
  147. * The feature is enabled in later stage.
  148. */
  149. xenon_set_acg(host, false);
  150. xenon_set_sdclk_off_idle(host, sdhc_id, false);
  151. xenon_mask_cmd_conflict_err(host);
  152. }
  153. static void xenon_reset(struct sdhci_host *host, u8 mask)
  154. {
  155. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  156. struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  157. sdhci_reset(host, mask);
  158. xenon_reset_exit(host, priv->sdhc_id, mask);
  159. }
  160. /*
  161. * Xenon defines different values for HS200 and HS400
  162. * in Host_Control_2
  163. */
  164. static void xenon_set_uhs_signaling(struct sdhci_host *host,
  165. unsigned int timing)
  166. {
  167. u16 ctrl_2;
  168. ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
  169. /* Select Bus Speed Mode for host */
  170. ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
  171. if (timing == MMC_TIMING_MMC_HS200)
  172. ctrl_2 |= XENON_CTRL_HS200;
  173. else if (timing == MMC_TIMING_UHS_SDR104)
  174. ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
  175. else if (timing == MMC_TIMING_UHS_SDR12)
  176. ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
  177. else if (timing == MMC_TIMING_UHS_SDR25)
  178. ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
  179. else if (timing == MMC_TIMING_UHS_SDR50)
  180. ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
  181. else if ((timing == MMC_TIMING_UHS_DDR50) ||
  182. (timing == MMC_TIMING_MMC_DDR52))
  183. ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
  184. else if (timing == MMC_TIMING_MMC_HS400)
  185. ctrl_2 |= XENON_CTRL_HS400;
  186. sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
  187. }
  188. static void xenon_set_power(struct sdhci_host *host, unsigned char mode,
  189. unsigned short vdd)
  190. {
  191. struct mmc_host *mmc = host->mmc;
  192. u8 pwr = host->pwr;
  193. sdhci_set_power_noreg(host, mode, vdd);
  194. if (host->pwr == pwr)
  195. return;
  196. if (host->pwr == 0)
  197. vdd = 0;
  198. if (!IS_ERR(mmc->supply.vmmc))
  199. mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
  200. }
  201. static void xenon_voltage_switch(struct sdhci_host *host)
  202. {
  203. /* Wait for 5ms after set 1.8V signal enable bit */
  204. usleep_range(5000, 5500);
  205. }
  206. static unsigned int xenon_get_max_clock(struct sdhci_host *host)
  207. {
  208. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  209. if (pltfm_host->clk)
  210. return sdhci_pltfm_clk_get_max_clock(host);
  211. else
  212. return pltfm_host->clock;
  213. }
  214. static const struct sdhci_ops sdhci_xenon_ops = {
  215. .voltage_switch = xenon_voltage_switch,
  216. .set_clock = sdhci_set_clock,
  217. .set_power = xenon_set_power,
  218. .set_bus_width = sdhci_set_bus_width,
  219. .reset = xenon_reset,
  220. .set_uhs_signaling = xenon_set_uhs_signaling,
  221. .get_max_clock = xenon_get_max_clock,
  222. };
  223. static const struct sdhci_pltfm_data sdhci_xenon_pdata = {
  224. .ops = &sdhci_xenon_ops,
  225. .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC |
  226. SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
  227. SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
  228. };
  229. /*
  230. * Xenon Specific Operations in mmc_host_ops
  231. */
  232. static void xenon_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
  233. {
  234. struct sdhci_host *host = mmc_priv(mmc);
  235. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  236. struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  237. u32 reg;
  238. /*
  239. * HS400/HS200/eMMC HS doesn't have Preset Value register.
  240. * However, sdhci_set_ios will read HS400/HS200 Preset register.
  241. * Disable Preset Value register for HS400/HS200.
  242. * eMMC HS with preset_enabled set will trigger a bug in
  243. * get_preset_value().
  244. */
  245. if ((ios->timing == MMC_TIMING_MMC_HS400) ||
  246. (ios->timing == MMC_TIMING_MMC_HS200) ||
  247. (ios->timing == MMC_TIMING_MMC_HS)) {
  248. host->preset_enabled = false;
  249. host->quirks2 |= SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
  250. host->flags &= ~SDHCI_PV_ENABLED;
  251. reg = sdhci_readw(host, SDHCI_HOST_CONTROL2);
  252. reg &= ~SDHCI_CTRL_PRESET_VAL_ENABLE;
  253. sdhci_writew(host, reg, SDHCI_HOST_CONTROL2);
  254. } else {
  255. host->quirks2 &= ~SDHCI_QUIRK2_PRESET_VALUE_BROKEN;
  256. }
  257. sdhci_set_ios(mmc, ios);
  258. xenon_phy_adj(host, ios);
  259. if (host->clock > XENON_DEFAULT_SDCLK_FREQ)
  260. xenon_set_sdclk_off_idle(host, priv->sdhc_id, true);
  261. }
  262. static int xenon_start_signal_voltage_switch(struct mmc_host *mmc,
  263. struct mmc_ios *ios)
  264. {
  265. struct sdhci_host *host = mmc_priv(mmc);
  266. /*
  267. * Before SD/SDIO set signal voltage, SD bus clock should be
  268. * disabled. However, sdhci_set_clock will also disable the Internal
  269. * clock in mmc_set_signal_voltage().
  270. * If Internal clock is disabled, the 3.3V/1.8V bit can not be updated.
  271. * Thus here manually enable internal clock.
  272. *
  273. * After switch completes, it is unnecessary to disable internal clock,
  274. * since keeping internal clock active obeys SD spec.
  275. */
  276. xenon_enable_internal_clk(host);
  277. xenon_soc_pad_ctrl(host, ios->signal_voltage);
  278. /*
  279. * If Vqmmc is fixed on platform, vqmmc regulator should be unavailable.
  280. * Thus SDHCI_CTRL_VDD_180 bit might not work then.
  281. * Skip the standard voltage switch to avoid any issue.
  282. */
  283. if (PTR_ERR(mmc->supply.vqmmc) == -ENODEV)
  284. return 0;
  285. return sdhci_start_signal_voltage_switch(mmc, ios);
  286. }
  287. /*
  288. * Update card type.
  289. * priv->init_card_type will be used in PHY timing adjustment.
  290. */
  291. static void xenon_init_card(struct mmc_host *mmc, struct mmc_card *card)
  292. {
  293. struct sdhci_host *host = mmc_priv(mmc);
  294. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  295. struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  296. /* Update card type*/
  297. priv->init_card_type = card->type;
  298. }
  299. static int xenon_execute_tuning(struct mmc_host *mmc, u32 opcode)
  300. {
  301. struct sdhci_host *host = mmc_priv(mmc);
  302. if (host->timing == MMC_TIMING_UHS_DDR50 ||
  303. host->timing == MMC_TIMING_MMC_DDR52)
  304. return 0;
  305. /*
  306. * Currently force Xenon driver back to support mode 1 only,
  307. * even though Xenon might claim to support mode 2 or mode 3.
  308. * It requires more time to test mode 2/mode 3 on more platforms.
  309. */
  310. if (host->tuning_mode != SDHCI_TUNING_MODE_1)
  311. xenon_retune_setup(host);
  312. return sdhci_execute_tuning(mmc, opcode);
  313. }
  314. static void xenon_enable_sdio_irq(struct mmc_host *mmc, int enable)
  315. {
  316. struct sdhci_host *host = mmc_priv(mmc);
  317. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  318. struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  319. u32 reg;
  320. u8 sdhc_id = priv->sdhc_id;
  321. sdhci_enable_sdio_irq(mmc, enable);
  322. if (enable) {
  323. /*
  324. * Set SDIO Card Inserted indication
  325. * to enable detecting SDIO async irq.
  326. */
  327. reg = sdhci_readl(host, XENON_SYS_CFG_INFO);
  328. reg |= (1 << (sdhc_id + XENON_SLOT_TYPE_SDIO_SHIFT));
  329. sdhci_writel(host, reg, XENON_SYS_CFG_INFO);
  330. } else {
  331. /* Clear SDIO Card Inserted indication */
  332. reg = sdhci_readl(host, XENON_SYS_CFG_INFO);
  333. reg &= ~(1 << (sdhc_id + XENON_SLOT_TYPE_SDIO_SHIFT));
  334. sdhci_writel(host, reg, XENON_SYS_CFG_INFO);
  335. }
  336. }
  337. static void xenon_replace_mmc_host_ops(struct sdhci_host *host)
  338. {
  339. host->mmc_host_ops.set_ios = xenon_set_ios;
  340. host->mmc_host_ops.start_signal_voltage_switch =
  341. xenon_start_signal_voltage_switch;
  342. host->mmc_host_ops.init_card = xenon_init_card;
  343. host->mmc_host_ops.execute_tuning = xenon_execute_tuning;
  344. host->mmc_host_ops.enable_sdio_irq = xenon_enable_sdio_irq;
  345. }
  346. /*
  347. * Parse Xenon specific DT properties:
  348. * sdhc-id: the index of current SDHC.
  349. * Refer to XENON_SYS_CFG_INFO register
  350. * tun-count: the interval between re-tuning
  351. */
  352. static int xenon_probe_params(struct platform_device *pdev)
  353. {
  354. struct device *dev = &pdev->dev;
  355. struct sdhci_host *host = platform_get_drvdata(pdev);
  356. struct mmc_host *mmc = host->mmc;
  357. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  358. struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  359. u32 sdhc_id, nr_sdhc;
  360. u32 tuning_count;
  361. /* Disable HS200 on Armada AP806 */
  362. if (priv->hw_version == XENON_AP806)
  363. host->quirks2 |= SDHCI_QUIRK2_BROKEN_HS200;
  364. sdhc_id = 0x0;
  365. if (!device_property_read_u32(dev, "marvell,xenon-sdhc-id", &sdhc_id)) {
  366. nr_sdhc = sdhci_readl(host, XENON_SYS_CFG_INFO);
  367. nr_sdhc &= XENON_NR_SUPPORTED_SLOT_MASK;
  368. if (unlikely(sdhc_id > nr_sdhc)) {
  369. dev_err(mmc_dev(mmc), "SDHC Index %d exceeds Number of SDHCs %d\n",
  370. sdhc_id, nr_sdhc);
  371. return -EINVAL;
  372. }
  373. }
  374. priv->sdhc_id = sdhc_id;
  375. tuning_count = XENON_DEF_TUNING_COUNT;
  376. if (!device_property_read_u32(dev, "marvell,xenon-tun-count",
  377. &tuning_count)) {
  378. if (unlikely(tuning_count >= XENON_TMR_RETUN_NO_PRESENT)) {
  379. dev_err(mmc_dev(mmc), "Wrong Re-tuning Count. Set default value %d\n",
  380. XENON_DEF_TUNING_COUNT);
  381. tuning_count = XENON_DEF_TUNING_COUNT;
  382. }
  383. }
  384. priv->tuning_count = tuning_count;
  385. return xenon_phy_parse_params(dev, host);
  386. }
  387. static int xenon_sdhc_prepare(struct sdhci_host *host)
  388. {
  389. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  390. struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  391. u8 sdhc_id = priv->sdhc_id;
  392. /* Enable SDHC */
  393. xenon_enable_sdhc(host, sdhc_id);
  394. /* Enable ACG */
  395. xenon_set_acg(host, true);
  396. /* Enable Parallel Transfer Mode */
  397. xenon_enable_sdhc_parallel_tran(host, sdhc_id);
  398. /* Disable SDCLK-Off-While-Idle before card init */
  399. xenon_set_sdclk_off_idle(host, sdhc_id, false);
  400. xenon_mask_cmd_conflict_err(host);
  401. return 0;
  402. }
  403. static void xenon_sdhc_unprepare(struct sdhci_host *host)
  404. {
  405. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  406. struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  407. u8 sdhc_id = priv->sdhc_id;
  408. /* disable SDHC */
  409. xenon_disable_sdhc(host, sdhc_id);
  410. }
  411. static int xenon_probe(struct platform_device *pdev)
  412. {
  413. struct sdhci_pltfm_host *pltfm_host;
  414. struct device *dev = &pdev->dev;
  415. struct sdhci_host *host;
  416. struct xenon_priv *priv;
  417. int err;
  418. host = sdhci_pltfm_init(pdev, &sdhci_xenon_pdata,
  419. sizeof(struct xenon_priv));
  420. if (IS_ERR(host))
  421. return PTR_ERR(host);
  422. pltfm_host = sdhci_priv(host);
  423. priv = sdhci_pltfm_priv(pltfm_host);
  424. priv->hw_version = (unsigned long)device_get_match_data(&pdev->dev);
  425. /*
  426. * Link Xenon specific mmc_host_ops function,
  427. * to replace standard ones in sdhci_ops.
  428. */
  429. xenon_replace_mmc_host_ops(host);
  430. if (dev->of_node) {
  431. pltfm_host->clk = devm_clk_get(&pdev->dev, "core");
  432. if (IS_ERR(pltfm_host->clk)) {
  433. err = PTR_ERR(pltfm_host->clk);
  434. dev_err(&pdev->dev, "Failed to setup input clk: %d\n", err);
  435. goto free_pltfm;
  436. }
  437. err = clk_prepare_enable(pltfm_host->clk);
  438. if (err)
  439. goto free_pltfm;
  440. priv->axi_clk = devm_clk_get(&pdev->dev, "axi");
  441. if (IS_ERR(priv->axi_clk)) {
  442. err = PTR_ERR(priv->axi_clk);
  443. if (err == -EPROBE_DEFER)
  444. goto err_clk;
  445. } else {
  446. err = clk_prepare_enable(priv->axi_clk);
  447. if (err)
  448. goto err_clk;
  449. }
  450. }
  451. err = mmc_of_parse(host->mmc);
  452. if (err)
  453. goto err_clk_axi;
  454. sdhci_get_property(pdev);
  455. xenon_set_acg(host, false);
  456. /* Xenon specific parameters parse */
  457. err = xenon_probe_params(pdev);
  458. if (err)
  459. goto err_clk_axi;
  460. err = xenon_sdhc_prepare(host);
  461. if (err)
  462. goto err_clk_axi;
  463. pm_runtime_get_noresume(&pdev->dev);
  464. pm_runtime_set_active(&pdev->dev);
  465. pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
  466. pm_runtime_use_autosuspend(&pdev->dev);
  467. pm_runtime_enable(&pdev->dev);
  468. pm_suspend_ignore_children(&pdev->dev, 1);
  469. err = sdhci_add_host(host);
  470. if (err)
  471. goto remove_sdhc;
  472. pm_runtime_put_autosuspend(&pdev->dev);
  473. return 0;
  474. remove_sdhc:
  475. pm_runtime_disable(&pdev->dev);
  476. pm_runtime_put_noidle(&pdev->dev);
  477. xenon_sdhc_unprepare(host);
  478. err_clk_axi:
  479. clk_disable_unprepare(priv->axi_clk);
  480. err_clk:
  481. clk_disable_unprepare(pltfm_host->clk);
  482. free_pltfm:
  483. sdhci_pltfm_free(pdev);
  484. return err;
  485. }
  486. static int xenon_remove(struct platform_device *pdev)
  487. {
  488. struct sdhci_host *host = platform_get_drvdata(pdev);
  489. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  490. struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  491. pm_runtime_get_sync(&pdev->dev);
  492. pm_runtime_disable(&pdev->dev);
  493. pm_runtime_put_noidle(&pdev->dev);
  494. sdhci_remove_host(host, 0);
  495. xenon_sdhc_unprepare(host);
  496. clk_disable_unprepare(priv->axi_clk);
  497. clk_disable_unprepare(pltfm_host->clk);
  498. sdhci_pltfm_free(pdev);
  499. return 0;
  500. }
  501. #ifdef CONFIG_PM_SLEEP
  502. static int xenon_suspend(struct device *dev)
  503. {
  504. struct sdhci_host *host = dev_get_drvdata(dev);
  505. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  506. struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  507. int ret;
  508. ret = pm_runtime_force_suspend(dev);
  509. priv->restore_needed = true;
  510. return ret;
  511. }
  512. #endif
  513. #ifdef CONFIG_PM
  514. static int xenon_runtime_suspend(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 xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  519. int ret;
  520. ret = sdhci_runtime_suspend_host(host);
  521. if (ret)
  522. return ret;
  523. if (host->tuning_mode != SDHCI_TUNING_MODE_3)
  524. mmc_retune_needed(host->mmc);
  525. clk_disable_unprepare(pltfm_host->clk);
  526. /*
  527. * Need to update the priv->clock here, or when runtime resume
  528. * back, phy don't aware the clock change and won't adjust phy
  529. * which will cause cmd err
  530. */
  531. priv->clock = 0;
  532. return 0;
  533. }
  534. static int xenon_runtime_resume(struct device *dev)
  535. {
  536. struct sdhci_host *host = dev_get_drvdata(dev);
  537. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  538. struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host);
  539. int ret;
  540. ret = clk_prepare_enable(pltfm_host->clk);
  541. if (ret) {
  542. dev_err(dev, "can't enable mainck\n");
  543. return ret;
  544. }
  545. if (priv->restore_needed) {
  546. ret = xenon_sdhc_prepare(host);
  547. if (ret)
  548. goto out;
  549. priv->restore_needed = false;
  550. }
  551. ret = sdhci_runtime_resume_host(host, 0);
  552. if (ret)
  553. goto out;
  554. return 0;
  555. out:
  556. clk_disable_unprepare(pltfm_host->clk);
  557. return ret;
  558. }
  559. #endif /* CONFIG_PM */
  560. static const struct dev_pm_ops sdhci_xenon_dev_pm_ops = {
  561. SET_SYSTEM_SLEEP_PM_OPS(xenon_suspend,
  562. pm_runtime_force_resume)
  563. SET_RUNTIME_PM_OPS(xenon_runtime_suspend,
  564. xenon_runtime_resume,
  565. NULL)
  566. };
  567. static const struct of_device_id sdhci_xenon_dt_ids[] = {
  568. { .compatible = "marvell,armada-ap806-sdhci", .data = (void *)XENON_AP806},
  569. { .compatible = "marvell,armada-ap807-sdhci", .data = (void *)XENON_AP807},
  570. { .compatible = "marvell,armada-cp110-sdhci", .data = (void *)XENON_CP110},
  571. { .compatible = "marvell,armada-3700-sdhci", .data = (void *)XENON_A3700},
  572. {}
  573. };
  574. MODULE_DEVICE_TABLE(of, sdhci_xenon_dt_ids);
  575. #ifdef CONFIG_ACPI
  576. static const struct acpi_device_id sdhci_xenon_acpi_ids[] = {
  577. { .id = "MRVL0002", XENON_AP806},
  578. { .id = "MRVL0003", XENON_AP807},
  579. { .id = "MRVL0004", XENON_CP110},
  580. {}
  581. };
  582. MODULE_DEVICE_TABLE(acpi, sdhci_xenon_acpi_ids);
  583. #endif
  584. static struct platform_driver sdhci_xenon_driver = {
  585. .driver = {
  586. .name = "xenon-sdhci",
  587. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  588. .of_match_table = sdhci_xenon_dt_ids,
  589. .acpi_match_table = ACPI_PTR(sdhci_xenon_acpi_ids),
  590. .pm = &sdhci_xenon_dev_pm_ops,
  591. },
  592. .probe = xenon_probe,
  593. .remove = xenon_remove,
  594. };
  595. module_platform_driver(sdhci_xenon_driver);
  596. MODULE_DESCRIPTION("SDHCI platform driver for Marvell Xenon SDHC");
  597. MODULE_AUTHOR("Hu Ziji <[email protected]>");
  598. MODULE_LICENSE("GPL v2");