sdhci-pxav3.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. /*
  2. * Copyright (C) 2010 Marvell International Ltd.
  3. * Zhangfei Gao <zhangfei.gao@marvell.com>
  4. * Kevin Wang <dwang4@marvell.com>
  5. * Mingwei Wang <mwwang@marvell.com>
  6. * Philip Rakity <prakity@marvell.com>
  7. * Mark Brown <markb@marvell.com>
  8. *
  9. * This software is licensed under the terms of the GNU General Public
  10. * License version 2, as published by the Free Software Foundation, and
  11. * may be copied, distributed, and modified under those terms.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. */
  19. #include <linux/err.h>
  20. #include <linux/init.h>
  21. #include <linux/platform_device.h>
  22. #include <linux/clk.h>
  23. #include <linux/io.h>
  24. #include <linux/mmc/card.h>
  25. #include <linux/mmc/host.h>
  26. #include <linux/platform_data/pxa_sdhci.h>
  27. #include <linux/slab.h>
  28. #include <linux/delay.h>
  29. #include <linux/module.h>
  30. #include <linux/of.h>
  31. #include <linux/of_device.h>
  32. #include <linux/pm.h>
  33. #include <linux/pm_runtime.h>
  34. #include <linux/mbus.h>
  35. #include "sdhci.h"
  36. #include "sdhci-pltfm.h"
  37. #define PXAV3_RPM_DELAY_MS 50
  38. #define SD_CLOCK_BURST_SIZE_SETUP 0x10A
  39. #define SDCLK_SEL 0x100
  40. #define SDCLK_DELAY_SHIFT 9
  41. #define SDCLK_DELAY_MASK 0x1f
  42. #define SD_CFG_FIFO_PARAM 0x100
  43. #define SDCFG_GEN_PAD_CLK_ON (1<<6)
  44. #define SDCFG_GEN_PAD_CLK_CNT_MASK 0xFF
  45. #define SDCFG_GEN_PAD_CLK_CNT_SHIFT 24
  46. #define SD_SPI_MODE 0x108
  47. #define SD_CE_ATA_1 0x10C
  48. #define SD_CE_ATA_2 0x10E
  49. #define SDCE_MISC_INT (1<<2)
  50. #define SDCE_MISC_INT_EN (1<<1)
  51. struct sdhci_pxa {
  52. struct clk *clk_core;
  53. struct clk *clk_io;
  54. u8 power_mode;
  55. void __iomem *sdio3_conf_reg;
  56. };
  57. /*
  58. * These registers are relative to the second register region, for the
  59. * MBus bridge.
  60. */
  61. #define SDHCI_WINDOW_CTRL(i) (0x80 + ((i) << 3))
  62. #define SDHCI_WINDOW_BASE(i) (0x84 + ((i) << 3))
  63. #define SDHCI_MAX_WIN_NUM 8
  64. /*
  65. * Fields below belong to SDIO3 Configuration Register (third register
  66. * region for the Armada 38x flavor)
  67. */
  68. #define SDIO3_CONF_CLK_INV BIT(0)
  69. #define SDIO3_CONF_SD_FB_CLK BIT(2)
  70. static int mv_conf_mbus_windows(struct platform_device *pdev,
  71. const struct mbus_dram_target_info *dram)
  72. {
  73. int i;
  74. void __iomem *regs;
  75. struct resource *res;
  76. if (!dram) {
  77. dev_err(&pdev->dev, "no mbus dram info\n");
  78. return -EINVAL;
  79. }
  80. res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
  81. if (!res) {
  82. dev_err(&pdev->dev, "cannot get mbus registers\n");
  83. return -EINVAL;
  84. }
  85. regs = ioremap(res->start, resource_size(res));
  86. if (!regs) {
  87. dev_err(&pdev->dev, "cannot map mbus registers\n");
  88. return -ENOMEM;
  89. }
  90. for (i = 0; i < SDHCI_MAX_WIN_NUM; i++) {
  91. writel(0, regs + SDHCI_WINDOW_CTRL(i));
  92. writel(0, regs + SDHCI_WINDOW_BASE(i));
  93. }
  94. for (i = 0; i < dram->num_cs; i++) {
  95. const struct mbus_dram_window *cs = dram->cs + i;
  96. /* Write size, attributes and target id to control register */
  97. writel(((cs->size - 1) & 0xffff0000) |
  98. (cs->mbus_attr << 8) |
  99. (dram->mbus_dram_target_id << 4) | 1,
  100. regs + SDHCI_WINDOW_CTRL(i));
  101. /* Write base address to base register */
  102. writel(cs->base, regs + SDHCI_WINDOW_BASE(i));
  103. }
  104. iounmap(regs);
  105. return 0;
  106. }
  107. static int armada_38x_quirks(struct platform_device *pdev,
  108. struct sdhci_host *host)
  109. {
  110. struct device_node *np = pdev->dev.of_node;
  111. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  112. struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
  113. struct resource *res;
  114. host->quirks &= ~SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
  115. host->quirks |= SDHCI_QUIRK_MISSING_CAPS;
  116. host->caps = sdhci_readl(host, SDHCI_CAPABILITIES);
  117. host->caps1 = sdhci_readl(host, SDHCI_CAPABILITIES_1);
  118. res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
  119. "conf-sdio3");
  120. if (res) {
  121. pxa->sdio3_conf_reg = devm_ioremap_resource(&pdev->dev, res);
  122. if (IS_ERR(pxa->sdio3_conf_reg))
  123. return PTR_ERR(pxa->sdio3_conf_reg);
  124. } else {
  125. /*
  126. * According to erratum 'FE-2946959' both SDR50 and DDR50
  127. * modes require specific clock adjustments in SDIO3
  128. * Configuration register, if the adjustment is not done,
  129. * remove them from the capabilities.
  130. */
  131. host->caps1 &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50);
  132. dev_warn(&pdev->dev, "conf-sdio3 register not found: disabling SDR50 and DDR50 modes.\nConsider updating your dtb\n");
  133. }
  134. /*
  135. * According to erratum 'ERR-7878951' Armada 38x SDHCI
  136. * controller has different capabilities than the ones shown
  137. * in its registers
  138. */
  139. if (of_property_read_bool(np, "no-1-8-v")) {
  140. host->caps &= ~SDHCI_CAN_VDD_180;
  141. host->mmc->caps &= ~MMC_CAP_1_8V_DDR;
  142. } else {
  143. host->caps &= ~SDHCI_CAN_VDD_330;
  144. }
  145. host->caps1 &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_USE_SDR50_TUNING);
  146. return 0;
  147. }
  148. static void pxav3_reset(struct sdhci_host *host, u8 mask)
  149. {
  150. struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
  151. struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
  152. sdhci_reset(host, mask);
  153. if (mask == SDHCI_RESET_ALL) {
  154. /*
  155. * tune timing of read data/command when crc error happen
  156. * no performance impact
  157. */
  158. if (pdata && 0 != pdata->clk_delay_cycles) {
  159. u16 tmp;
  160. tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
  161. tmp |= (pdata->clk_delay_cycles & SDCLK_DELAY_MASK)
  162. << SDCLK_DELAY_SHIFT;
  163. tmp |= SDCLK_SEL;
  164. writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
  165. }
  166. }
  167. }
  168. #define MAX_WAIT_COUNT 5
  169. static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode)
  170. {
  171. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  172. struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
  173. u16 tmp;
  174. int count;
  175. if (pxa->power_mode == MMC_POWER_UP
  176. && power_mode == MMC_POWER_ON) {
  177. dev_dbg(mmc_dev(host->mmc),
  178. "%s: slot->power_mode = %d,"
  179. "ios->power_mode = %d\n",
  180. __func__,
  181. pxa->power_mode,
  182. power_mode);
  183. /* set we want notice of when 74 clocks are sent */
  184. tmp = readw(host->ioaddr + SD_CE_ATA_2);
  185. tmp |= SDCE_MISC_INT_EN;
  186. writew(tmp, host->ioaddr + SD_CE_ATA_2);
  187. /* start sending the 74 clocks */
  188. tmp = readw(host->ioaddr + SD_CFG_FIFO_PARAM);
  189. tmp |= SDCFG_GEN_PAD_CLK_ON;
  190. writew(tmp, host->ioaddr + SD_CFG_FIFO_PARAM);
  191. /* slowest speed is about 100KHz or 10usec per clock */
  192. udelay(740);
  193. count = 0;
  194. while (count++ < MAX_WAIT_COUNT) {
  195. if ((readw(host->ioaddr + SD_CE_ATA_2)
  196. & SDCE_MISC_INT) == 0)
  197. break;
  198. udelay(10);
  199. }
  200. if (count == MAX_WAIT_COUNT)
  201. dev_warn(mmc_dev(host->mmc), "74 clock interrupt not cleared\n");
  202. /* clear the interrupt bit if posted */
  203. tmp = readw(host->ioaddr + SD_CE_ATA_2);
  204. tmp |= SDCE_MISC_INT;
  205. writew(tmp, host->ioaddr + SD_CE_ATA_2);
  206. }
  207. pxa->power_mode = power_mode;
  208. }
  209. static void pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
  210. {
  211. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  212. struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
  213. u16 ctrl_2;
  214. /*
  215. * Set V18_EN -- UHS modes do not work without this.
  216. * does not change signaling voltage
  217. */
  218. ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
  219. /* Select Bus Speed Mode for host */
  220. ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
  221. switch (uhs) {
  222. case MMC_TIMING_UHS_SDR12:
  223. ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
  224. break;
  225. case MMC_TIMING_UHS_SDR25:
  226. ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
  227. break;
  228. case MMC_TIMING_UHS_SDR50:
  229. ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
  230. break;
  231. case MMC_TIMING_UHS_SDR104:
  232. ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
  233. break;
  234. case MMC_TIMING_MMC_DDR52:
  235. case MMC_TIMING_UHS_DDR50:
  236. ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
  237. break;
  238. }
  239. /*
  240. * Update SDIO3 Configuration register according to erratum
  241. * FE-2946959
  242. */
  243. if (pxa->sdio3_conf_reg) {
  244. u8 reg_val = readb(pxa->sdio3_conf_reg);
  245. if (uhs == MMC_TIMING_UHS_SDR50 ||
  246. uhs == MMC_TIMING_UHS_DDR50) {
  247. reg_val &= ~SDIO3_CONF_CLK_INV;
  248. reg_val |= SDIO3_CONF_SD_FB_CLK;
  249. } else if (uhs == MMC_TIMING_MMC_HS) {
  250. reg_val &= ~SDIO3_CONF_CLK_INV;
  251. reg_val &= ~SDIO3_CONF_SD_FB_CLK;
  252. } else {
  253. reg_val |= SDIO3_CONF_CLK_INV;
  254. reg_val &= ~SDIO3_CONF_SD_FB_CLK;
  255. }
  256. writeb(reg_val, pxa->sdio3_conf_reg);
  257. }
  258. sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
  259. dev_dbg(mmc_dev(host->mmc),
  260. "%s uhs = %d, ctrl_2 = %04X\n",
  261. __func__, uhs, ctrl_2);
  262. }
  263. static void pxav3_set_power(struct sdhci_host *host, unsigned char mode,
  264. unsigned short vdd)
  265. {
  266. struct mmc_host *mmc = host->mmc;
  267. u8 pwr = host->pwr;
  268. sdhci_set_power_noreg(host, mode, vdd);
  269. if (host->pwr == pwr)
  270. return;
  271. if (host->pwr == 0)
  272. vdd = 0;
  273. if (!IS_ERR(mmc->supply.vmmc))
  274. mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
  275. }
  276. static const struct sdhci_ops pxav3_sdhci_ops = {
  277. .set_clock = sdhci_set_clock,
  278. .set_power = pxav3_set_power,
  279. .platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
  280. .get_max_clock = sdhci_pltfm_clk_get_max_clock,
  281. .set_bus_width = sdhci_set_bus_width,
  282. .reset = pxav3_reset,
  283. .set_uhs_signaling = pxav3_set_uhs_signaling,
  284. };
  285. static const struct sdhci_pltfm_data sdhci_pxav3_pdata = {
  286. .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK
  287. | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
  288. | SDHCI_QUIRK_32BIT_ADMA_SIZE
  289. | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
  290. .ops = &pxav3_sdhci_ops,
  291. };
  292. #ifdef CONFIG_OF
  293. static const struct of_device_id sdhci_pxav3_of_match[] = {
  294. {
  295. .compatible = "mrvl,pxav3-mmc",
  296. },
  297. {
  298. .compatible = "marvell,armada-380-sdhci",
  299. },
  300. {},
  301. };
  302. MODULE_DEVICE_TABLE(of, sdhci_pxav3_of_match);
  303. static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
  304. {
  305. struct sdhci_pxa_platdata *pdata;
  306. struct device_node *np = dev->of_node;
  307. u32 clk_delay_cycles;
  308. pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
  309. if (!pdata)
  310. return NULL;
  311. if (!of_property_read_u32(np, "mrvl,clk-delay-cycles",
  312. &clk_delay_cycles))
  313. pdata->clk_delay_cycles = clk_delay_cycles;
  314. return pdata;
  315. }
  316. #else
  317. static inline struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
  318. {
  319. return NULL;
  320. }
  321. #endif
  322. static int sdhci_pxav3_probe(struct platform_device *pdev)
  323. {
  324. struct sdhci_pltfm_host *pltfm_host;
  325. struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
  326. struct device *dev = &pdev->dev;
  327. struct device_node *np = pdev->dev.of_node;
  328. struct sdhci_host *host = NULL;
  329. struct sdhci_pxa *pxa = NULL;
  330. const struct of_device_id *match;
  331. int ret;
  332. host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata, sizeof(*pxa));
  333. if (IS_ERR(host))
  334. return PTR_ERR(host);
  335. pltfm_host = sdhci_priv(host);
  336. pxa = sdhci_pltfm_priv(pltfm_host);
  337. pxa->clk_io = devm_clk_get(dev, "io");
  338. if (IS_ERR(pxa->clk_io))
  339. pxa->clk_io = devm_clk_get(dev, NULL);
  340. if (IS_ERR(pxa->clk_io)) {
  341. dev_err(dev, "failed to get io clock\n");
  342. ret = PTR_ERR(pxa->clk_io);
  343. goto err_clk_get;
  344. }
  345. pltfm_host->clk = pxa->clk_io;
  346. clk_prepare_enable(pxa->clk_io);
  347. pxa->clk_core = devm_clk_get(dev, "core");
  348. if (!IS_ERR(pxa->clk_core))
  349. clk_prepare_enable(pxa->clk_core);
  350. /* enable 1/8V DDR capable */
  351. host->mmc->caps |= MMC_CAP_1_8V_DDR;
  352. if (of_device_is_compatible(np, "marvell,armada-380-sdhci")) {
  353. ret = armada_38x_quirks(pdev, host);
  354. if (ret < 0)
  355. goto err_mbus_win;
  356. ret = mv_conf_mbus_windows(pdev, mv_mbus_dram_info());
  357. if (ret < 0)
  358. goto err_mbus_win;
  359. }
  360. match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev);
  361. if (match) {
  362. ret = mmc_of_parse(host->mmc);
  363. if (ret)
  364. goto err_of_parse;
  365. sdhci_get_of_property(pdev);
  366. pdata = pxav3_get_mmc_pdata(dev);
  367. pdev->dev.platform_data = pdata;
  368. } else if (pdata) {
  369. /* on-chip device */
  370. if (pdata->flags & PXA_FLAG_CARD_PERMANENT)
  371. host->mmc->caps |= MMC_CAP_NONREMOVABLE;
  372. /* If slot design supports 8 bit data, indicate this to MMC. */
  373. if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
  374. host->mmc->caps |= MMC_CAP_8_BIT_DATA;
  375. if (pdata->quirks)
  376. host->quirks |= pdata->quirks;
  377. if (pdata->quirks2)
  378. host->quirks2 |= pdata->quirks2;
  379. if (pdata->host_caps)
  380. host->mmc->caps |= pdata->host_caps;
  381. if (pdata->host_caps2)
  382. host->mmc->caps2 |= pdata->host_caps2;
  383. if (pdata->pm_caps)
  384. host->mmc->pm_caps |= pdata->pm_caps;
  385. }
  386. pm_runtime_get_noresume(&pdev->dev);
  387. pm_runtime_set_active(&pdev->dev);
  388. pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS);
  389. pm_runtime_use_autosuspend(&pdev->dev);
  390. pm_runtime_enable(&pdev->dev);
  391. pm_suspend_ignore_children(&pdev->dev, 1);
  392. ret = sdhci_add_host(host);
  393. if (ret)
  394. goto err_add_host;
  395. if (host->mmc->pm_caps & MMC_PM_WAKE_SDIO_IRQ)
  396. device_init_wakeup(&pdev->dev, 1);
  397. pm_runtime_put_autosuspend(&pdev->dev);
  398. return 0;
  399. err_add_host:
  400. pm_runtime_disable(&pdev->dev);
  401. pm_runtime_put_noidle(&pdev->dev);
  402. err_of_parse:
  403. err_mbus_win:
  404. clk_disable_unprepare(pxa->clk_io);
  405. clk_disable_unprepare(pxa->clk_core);
  406. err_clk_get:
  407. sdhci_pltfm_free(pdev);
  408. return ret;
  409. }
  410. static int sdhci_pxav3_remove(struct platform_device *pdev)
  411. {
  412. struct sdhci_host *host = platform_get_drvdata(pdev);
  413. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  414. struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
  415. pm_runtime_get_sync(&pdev->dev);
  416. pm_runtime_disable(&pdev->dev);
  417. pm_runtime_put_noidle(&pdev->dev);
  418. sdhci_remove_host(host, 1);
  419. clk_disable_unprepare(pxa->clk_io);
  420. clk_disable_unprepare(pxa->clk_core);
  421. sdhci_pltfm_free(pdev);
  422. return 0;
  423. }
  424. #ifdef CONFIG_PM_SLEEP
  425. static int sdhci_pxav3_suspend(struct device *dev)
  426. {
  427. int ret;
  428. struct sdhci_host *host = dev_get_drvdata(dev);
  429. pm_runtime_get_sync(dev);
  430. if (host->tuning_mode != SDHCI_TUNING_MODE_3)
  431. mmc_retune_needed(host->mmc);
  432. ret = sdhci_suspend_host(host);
  433. pm_runtime_mark_last_busy(dev);
  434. pm_runtime_put_autosuspend(dev);
  435. return ret;
  436. }
  437. static int sdhci_pxav3_resume(struct device *dev)
  438. {
  439. int ret;
  440. struct sdhci_host *host = dev_get_drvdata(dev);
  441. pm_runtime_get_sync(dev);
  442. ret = sdhci_resume_host(host);
  443. pm_runtime_mark_last_busy(dev);
  444. pm_runtime_put_autosuspend(dev);
  445. return ret;
  446. }
  447. #endif
  448. #ifdef CONFIG_PM
  449. static int sdhci_pxav3_runtime_suspend(struct device *dev)
  450. {
  451. struct sdhci_host *host = dev_get_drvdata(dev);
  452. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  453. struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
  454. int ret;
  455. ret = sdhci_runtime_suspend_host(host);
  456. if (ret)
  457. return ret;
  458. if (host->tuning_mode != SDHCI_TUNING_MODE_3)
  459. mmc_retune_needed(host->mmc);
  460. clk_disable_unprepare(pxa->clk_io);
  461. if (!IS_ERR(pxa->clk_core))
  462. clk_disable_unprepare(pxa->clk_core);
  463. return 0;
  464. }
  465. static int sdhci_pxav3_runtime_resume(struct device *dev)
  466. {
  467. struct sdhci_host *host = dev_get_drvdata(dev);
  468. struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  469. struct sdhci_pxa *pxa = sdhci_pltfm_priv(pltfm_host);
  470. clk_prepare_enable(pxa->clk_io);
  471. if (!IS_ERR(pxa->clk_core))
  472. clk_prepare_enable(pxa->clk_core);
  473. return sdhci_runtime_resume_host(host);
  474. }
  475. #endif
  476. static const struct dev_pm_ops sdhci_pxav3_pmops = {
  477. SET_SYSTEM_SLEEP_PM_OPS(sdhci_pxav3_suspend, sdhci_pxav3_resume)
  478. SET_RUNTIME_PM_OPS(sdhci_pxav3_runtime_suspend,
  479. sdhci_pxav3_runtime_resume, NULL)
  480. };
  481. static struct platform_driver sdhci_pxav3_driver = {
  482. .driver = {
  483. .name = "sdhci-pxav3",
  484. .of_match_table = of_match_ptr(sdhci_pxav3_of_match),
  485. .pm = &sdhci_pxav3_pmops,
  486. },
  487. .probe = sdhci_pxav3_probe,
  488. .remove = sdhci_pxav3_remove,
  489. };
  490. module_platform_driver(sdhci_pxav3_driver);
  491. MODULE_DESCRIPTION("SDHCI driver for pxav3");
  492. MODULE_AUTHOR("Marvell International Ltd.");
  493. MODULE_LICENSE("GPL v2");