xenon_sdhci.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Driver for Marvell SOC Platform Group Xenon SDHC as a platform device
  4. *
  5. * Copyright (C) 2016 Marvell, All Rights Reserved.
  6. *
  7. * Author: Victor Gu <xigu@marvell.com>
  8. * Date: 2016-8-24
  9. *
  10. * Included parts of the Linux driver version which was written by:
  11. * Hu Ziji <huziji@marvell.com>
  12. *
  13. * Ported to from Marvell 2015.01 to mainline U-Boot 2017.01:
  14. * Stefan Roese <sr@denx.de>
  15. */
  16. #include <common.h>
  17. #include <dm.h>
  18. #include <fdtdec.h>
  19. #include <linux/bitops.h>
  20. #include <linux/delay.h>
  21. #include <linux/libfdt.h>
  22. #include <malloc.h>
  23. #include <sdhci.h>
  24. #include <power/regulator.h>
  25. DECLARE_GLOBAL_DATA_PTR;
  26. /* Register Offset of SD Host Controller SOCP self-defined register */
  27. #define SDHC_SYS_CFG_INFO 0x0104
  28. #define SLOT_TYPE_SDIO_SHIFT 24
  29. #define SLOT_TYPE_EMMC_MASK 0xFF
  30. #define SLOT_TYPE_EMMC_SHIFT 16
  31. #define SLOT_TYPE_SD_SDIO_MMC_MASK 0xFF
  32. #define SLOT_TYPE_SD_SDIO_MMC_SHIFT 8
  33. #define NR_SUPPORTED_SLOT_MASK 0x7
  34. #define SDHC_SYS_OP_CTRL 0x0108
  35. #define AUTO_CLKGATE_DISABLE_MASK BIT(20)
  36. #define SDCLK_IDLEOFF_ENABLE_SHIFT 8
  37. #define SLOT_ENABLE_SHIFT 0
  38. #define SDHC_SYS_EXT_OP_CTRL 0x010C
  39. #define MASK_CMD_CONFLICT_ERROR BIT(8)
  40. #define SDHC_SLOT_EMMC_CTRL 0x0130
  41. #define ENABLE_DATA_STROBE_SHIFT 24
  42. #define SET_EMMC_RSTN_SHIFT 16
  43. #define EMMC_VCCQ_MASK 0x3
  44. #define EMMC_VCCQ_1_8V 0x1
  45. #define EMMC_VCCQ_1_2V 0x2
  46. #define EMMC_VCCQ_3_3V 0x3
  47. #define SDHC_SLOT_RETUNING_REQ_CTRL 0x0144
  48. /* retuning compatible */
  49. #define RETUNING_COMPATIBLE 0x1
  50. /* Xenon specific Mode Select value */
  51. #define XENON_SDHCI_CTRL_HS200 0x5
  52. #define XENON_SDHCI_CTRL_HS400 0x6
  53. #define EMMC_PHY_REG_BASE 0x170
  54. #define EMMC_PHY_TIMING_ADJUST EMMC_PHY_REG_BASE
  55. #define OUTPUT_QSN_PHASE_SELECT BIT(17)
  56. #define SAMPL_INV_QSP_PHASE_SELECT BIT(18)
  57. #define SAMPL_INV_QSP_PHASE_SELECT_SHIFT 18
  58. #define EMMC_PHY_SLOW_MODE BIT(29)
  59. #define PHY_INITIALIZAION BIT(31)
  60. #define WAIT_CYCLE_BEFORE_USING_MASK 0xf
  61. #define WAIT_CYCLE_BEFORE_USING_SHIFT 12
  62. #define FC_SYNC_EN_DURATION_MASK 0xf
  63. #define FC_SYNC_EN_DURATION_SHIFT 8
  64. #define FC_SYNC_RST_EN_DURATION_MASK 0xf
  65. #define FC_SYNC_RST_EN_DURATION_SHIFT 4
  66. #define FC_SYNC_RST_DURATION_MASK 0xf
  67. #define FC_SYNC_RST_DURATION_SHIFT 0
  68. #define EMMC_PHY_FUNC_CONTROL (EMMC_PHY_REG_BASE + 0x4)
  69. #define DQ_ASYNC_MODE BIT(4)
  70. #define DQ_DDR_MODE_SHIFT 8
  71. #define DQ_DDR_MODE_MASK 0xff
  72. #define CMD_DDR_MODE BIT(16)
  73. #define EMMC_PHY_PAD_CONTROL (EMMC_PHY_REG_BASE + 0x8)
  74. #define REC_EN_SHIFT 24
  75. #define REC_EN_MASK 0xf
  76. #define FC_DQ_RECEN BIT(24)
  77. #define FC_CMD_RECEN BIT(25)
  78. #define FC_QSP_RECEN BIT(26)
  79. #define FC_QSN_RECEN BIT(27)
  80. #define OEN_QSN BIT(28)
  81. #define AUTO_RECEN_CTRL BIT(30)
  82. #define EMMC_PHY_PAD_CONTROL1 (EMMC_PHY_REG_BASE + 0xc)
  83. #define EMMC5_1_FC_QSP_PD BIT(9)
  84. #define EMMC5_1_FC_QSP_PU BIT(25)
  85. #define EMMC5_1_FC_CMD_PD BIT(8)
  86. #define EMMC5_1_FC_CMD_PU BIT(24)
  87. #define EMMC5_1_FC_DQ_PD 0xff
  88. #define EMMC5_1_FC_DQ_PU (0xff << 16)
  89. #define SDHCI_RETUNE_EVT_INTSIG 0x00001000
  90. /* Hyperion only have one slot 0 */
  91. #define XENON_MMC_SLOT_ID_HYPERION 0
  92. #define MMC_TIMING_LEGACY 0
  93. #define MMC_TIMING_MMC_HS 1
  94. #define MMC_TIMING_SD_HS 2
  95. #define MMC_TIMING_UHS_SDR12 3
  96. #define MMC_TIMING_UHS_SDR25 4
  97. #define MMC_TIMING_UHS_SDR50 5
  98. #define MMC_TIMING_UHS_SDR104 6
  99. #define MMC_TIMING_UHS_DDR50 7
  100. #define MMC_TIMING_MMC_DDR52 8
  101. #define MMC_TIMING_MMC_HS200 9
  102. #define MMC_TIMING_MMC_HS400 10
  103. #define XENON_MMC_MAX_CLK 400000000
  104. #define XENON_MMC_3V3_UV 3300000
  105. #define XENON_MMC_1V8_UV 1800000
  106. enum soc_pad_ctrl_type {
  107. SOC_PAD_SD,
  108. SOC_PAD_FIXED_1_8V,
  109. };
  110. struct xenon_sdhci_plat {
  111. struct mmc_config cfg;
  112. struct mmc mmc;
  113. };
  114. struct xenon_sdhci_priv {
  115. struct sdhci_host host;
  116. u8 timing;
  117. unsigned int clock;
  118. void *pad_ctrl_reg;
  119. int pad_type;
  120. struct udevice *vqmmc;
  121. };
  122. static int xenon_mmc_phy_init(struct sdhci_host *host)
  123. {
  124. struct xenon_sdhci_priv *priv = host->mmc->priv;
  125. u32 clock = priv->clock;
  126. u32 time;
  127. u32 var;
  128. /* Enable QSP PHASE SELECT */
  129. var = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST);
  130. var |= SAMPL_INV_QSP_PHASE_SELECT;
  131. if ((priv->timing == MMC_TIMING_UHS_SDR50) ||
  132. (priv->timing == MMC_TIMING_UHS_SDR25) ||
  133. (priv->timing == MMC_TIMING_UHS_SDR12) ||
  134. (priv->timing == MMC_TIMING_SD_HS) ||
  135. (priv->timing == MMC_TIMING_LEGACY))
  136. var |= EMMC_PHY_SLOW_MODE;
  137. sdhci_writel(host, var, EMMC_PHY_TIMING_ADJUST);
  138. /* Poll for host MMC PHY clock init to be stable */
  139. /* Wait up to 10ms */
  140. time = 100;
  141. while (time--) {
  142. var = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
  143. if (var & SDHCI_CLOCK_INT_STABLE)
  144. break;
  145. udelay(100);
  146. }
  147. if (time <= 0) {
  148. pr_err("Failed to enable MMC internal clock in time\n");
  149. return -ETIMEDOUT;
  150. }
  151. /* Init PHY */
  152. var = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST);
  153. var |= PHY_INITIALIZAION;
  154. sdhci_writel(host, var, EMMC_PHY_TIMING_ADJUST);
  155. if (clock == 0) {
  156. /* Use the possibly slowest bus frequency value */
  157. clock = 100000;
  158. }
  159. /* Poll for host eMMC PHY init to complete */
  160. /* Wait up to 10ms */
  161. time = 100;
  162. while (time--) {
  163. var = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST);
  164. var &= PHY_INITIALIZAION;
  165. if (!var)
  166. break;
  167. /* wait for host eMMC PHY init to complete */
  168. udelay(100);
  169. }
  170. if (time <= 0) {
  171. pr_err("Failed to init MMC PHY in time\n");
  172. return -ETIMEDOUT;
  173. }
  174. return 0;
  175. }
  176. #define ARMADA_3700_SOC_PAD_1_8V 0x1
  177. #define ARMADA_3700_SOC_PAD_3_3V 0x0
  178. static void armada_3700_soc_pad_voltage_set(struct sdhci_host *host)
  179. {
  180. struct xenon_sdhci_priv *priv = host->mmc->priv;
  181. if (priv->pad_type == SOC_PAD_FIXED_1_8V)
  182. writel(ARMADA_3700_SOC_PAD_1_8V, priv->pad_ctrl_reg);
  183. else if (priv->pad_type == SOC_PAD_SD)
  184. writel(ARMADA_3700_SOC_PAD_3_3V, priv->pad_ctrl_reg);
  185. }
  186. static int xenon_mmc_start_signal_voltage_switch(struct sdhci_host *host)
  187. {
  188. struct xenon_sdhci_priv *priv = host->mmc->priv;
  189. u8 voltage;
  190. u32 ctrl;
  191. int ret = 0;
  192. /* If there is no vqmmc regulator, return */
  193. if (!priv->vqmmc)
  194. return 0;
  195. if (priv->pad_type == SOC_PAD_FIXED_1_8V) {
  196. /* Switch to 1.8v */
  197. ret = regulator_set_value(priv->vqmmc,
  198. XENON_MMC_1V8_UV);
  199. } else if (priv->pad_type == SOC_PAD_SD) {
  200. /* Get voltage info */
  201. voltage = sdhci_readb(host, SDHCI_POWER_CONTROL);
  202. voltage &= ~SDHCI_POWER_ON;
  203. if (voltage == SDHCI_POWER_330) {
  204. /* Switch to 3.3v */
  205. ret = regulator_set_value(priv->vqmmc,
  206. XENON_MMC_3V3_UV);
  207. } else {
  208. /* Switch to 1.8v */
  209. ret = regulator_set_value(priv->vqmmc,
  210. XENON_MMC_1V8_UV);
  211. }
  212. }
  213. /* Set VCCQ, eMMC mode: 1.8V; SD/SDIO mode: 3.3V */
  214. ctrl = sdhci_readl(host, SDHC_SLOT_EMMC_CTRL);
  215. if (IS_SD(host->mmc))
  216. ctrl |= EMMC_VCCQ_3_3V;
  217. else
  218. ctrl |= EMMC_VCCQ_1_8V;
  219. sdhci_writel(host, ctrl, SDHC_SLOT_EMMC_CTRL);
  220. if (ret)
  221. printf("Signal voltage switch fail\n");
  222. return ret;
  223. }
  224. static void xenon_mmc_phy_set(struct sdhci_host *host)
  225. {
  226. struct xenon_sdhci_priv *priv = host->mmc->priv;
  227. u32 var;
  228. /* Setup pad, set bit[30], bit[28] and bits[26:24] */
  229. var = sdhci_readl(host, EMMC_PHY_PAD_CONTROL);
  230. var |= AUTO_RECEN_CTRL | OEN_QSN | FC_QSP_RECEN |
  231. FC_CMD_RECEN | FC_DQ_RECEN;
  232. sdhci_writel(host, var, EMMC_PHY_PAD_CONTROL);
  233. /* Set CMD and DQ Pull Up */
  234. var = sdhci_readl(host, EMMC_PHY_PAD_CONTROL1);
  235. var |= (EMMC5_1_FC_CMD_PU | EMMC5_1_FC_DQ_PU);
  236. var &= ~(EMMC5_1_FC_CMD_PD | EMMC5_1_FC_DQ_PD);
  237. sdhci_writel(host, var, EMMC_PHY_PAD_CONTROL1);
  238. /*
  239. * If timing belongs to high speed, set bit[17] of
  240. * EMMC_PHY_TIMING_ADJUST register
  241. */
  242. if ((priv->timing == MMC_TIMING_MMC_HS400) ||
  243. (priv->timing == MMC_TIMING_MMC_HS200) ||
  244. (priv->timing == MMC_TIMING_UHS_SDR50) ||
  245. (priv->timing == MMC_TIMING_UHS_SDR104) ||
  246. (priv->timing == MMC_TIMING_UHS_DDR50) ||
  247. (priv->timing == MMC_TIMING_UHS_SDR25) ||
  248. (priv->timing == MMC_TIMING_MMC_DDR52)) {
  249. var = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST);
  250. var |= OUTPUT_QSN_PHASE_SELECT;
  251. sdhci_writel(host, var, EMMC_PHY_TIMING_ADJUST);
  252. }
  253. /*
  254. * When setting EMMC_PHY_FUNC_CONTROL register,
  255. * SD clock should be disabled
  256. */
  257. var = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
  258. var &= ~SDHCI_CLOCK_CARD_EN;
  259. sdhci_writew(host, var, SDHCI_CLOCK_CONTROL);
  260. var = sdhci_readl(host, EMMC_PHY_FUNC_CONTROL);
  261. if (host->mmc->ddr_mode) {
  262. var |= (DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | CMD_DDR_MODE;
  263. } else {
  264. var &= ~((DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) |
  265. CMD_DDR_MODE);
  266. }
  267. sdhci_writel(host, var, EMMC_PHY_FUNC_CONTROL);
  268. /* Enable bus clock */
  269. var = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
  270. var |= SDHCI_CLOCK_CARD_EN;
  271. sdhci_writew(host, var, SDHCI_CLOCK_CONTROL);
  272. xenon_mmc_phy_init(host);
  273. }
  274. /* Enable/Disable the Auto Clock Gating function of this slot */
  275. static void xenon_mmc_set_acg(struct sdhci_host *host, bool enable)
  276. {
  277. u32 var;
  278. var = sdhci_readl(host, SDHC_SYS_OP_CTRL);
  279. if (enable)
  280. var &= ~AUTO_CLKGATE_DISABLE_MASK;
  281. else
  282. var |= AUTO_CLKGATE_DISABLE_MASK;
  283. sdhci_writel(host, var, SDHC_SYS_OP_CTRL);
  284. }
  285. #define SLOT_MASK(slot) BIT(slot)
  286. /* Enable specific slot */
  287. static void xenon_mmc_enable_slot(struct sdhci_host *host, u8 slot)
  288. {
  289. u32 var;
  290. var = sdhci_readl(host, SDHC_SYS_OP_CTRL);
  291. var |= SLOT_MASK(slot) << SLOT_ENABLE_SHIFT;
  292. sdhci_writel(host, var, SDHC_SYS_OP_CTRL);
  293. }
  294. /* Enable Parallel Transfer Mode */
  295. static void xenon_mmc_enable_parallel_tran(struct sdhci_host *host, u8 slot)
  296. {
  297. u32 var;
  298. var = sdhci_readl(host, SDHC_SYS_EXT_OP_CTRL);
  299. var |= SLOT_MASK(slot);
  300. sdhci_writel(host, var, SDHC_SYS_EXT_OP_CTRL);
  301. }
  302. static void xenon_mmc_disable_tuning(struct sdhci_host *host, u8 slot)
  303. {
  304. u32 var;
  305. /* Clear the Re-Tuning Request functionality */
  306. var = sdhci_readl(host, SDHC_SLOT_RETUNING_REQ_CTRL);
  307. var &= ~RETUNING_COMPATIBLE;
  308. sdhci_writel(host, var, SDHC_SLOT_RETUNING_REQ_CTRL);
  309. /* Clear the Re-tuning Event Signal Enable */
  310. var = sdhci_readl(host, SDHCI_SIGNAL_ENABLE);
  311. var &= ~SDHCI_RETUNE_EVT_INTSIG;
  312. sdhci_writel(host, var, SDHCI_SIGNAL_ENABLE);
  313. }
  314. /* Mask command conflict error */
  315. static void xenon_mask_cmd_conflict_err(struct sdhci_host *host)
  316. {
  317. u32 reg;
  318. reg = sdhci_readl(host, SDHC_SYS_EXT_OP_CTRL);
  319. reg |= MASK_CMD_CONFLICT_ERROR;
  320. sdhci_writel(host, reg, SDHC_SYS_EXT_OP_CTRL);
  321. }
  322. /* Platform specific function for post set_ios configuration */
  323. static int xenon_sdhci_set_ios_post(struct sdhci_host *host)
  324. {
  325. struct xenon_sdhci_priv *priv = host->mmc->priv;
  326. uint speed = host->mmc->tran_speed;
  327. int pwr_18v = 0;
  328. /*
  329. * Signal Voltage Switching is only applicable for Host Controllers
  330. * v3.00 and above.
  331. */
  332. if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
  333. xenon_mmc_start_signal_voltage_switch(host);
  334. if ((sdhci_readb(host, SDHCI_POWER_CONTROL) & ~SDHCI_POWER_ON) ==
  335. SDHCI_POWER_180)
  336. pwr_18v = 1;
  337. /* Set timing variable according to the configured speed */
  338. if (IS_SD(host->mmc)) {
  339. /* SD/SDIO */
  340. if (pwr_18v) {
  341. if (host->mmc->ddr_mode)
  342. priv->timing = MMC_TIMING_UHS_DDR50;
  343. else if (speed <= 25000000)
  344. priv->timing = MMC_TIMING_UHS_SDR25;
  345. else
  346. priv->timing = MMC_TIMING_UHS_SDR50;
  347. } else {
  348. if (speed <= 25000000)
  349. priv->timing = MMC_TIMING_LEGACY;
  350. else
  351. priv->timing = MMC_TIMING_SD_HS;
  352. }
  353. } else {
  354. /* eMMC */
  355. if (host->mmc->ddr_mode)
  356. priv->timing = MMC_TIMING_MMC_DDR52;
  357. else if (speed <= 26000000)
  358. priv->timing = MMC_TIMING_LEGACY;
  359. else
  360. priv->timing = MMC_TIMING_MMC_HS;
  361. }
  362. /* Re-init the PHY */
  363. xenon_mmc_phy_set(host);
  364. return 0;
  365. }
  366. /* Install a driver specific handler for post set_ios configuration */
  367. static const struct sdhci_ops xenon_sdhci_ops = {
  368. .set_ios_post = xenon_sdhci_set_ios_post
  369. };
  370. static int xenon_sdhci_probe(struct udevice *dev)
  371. {
  372. struct xenon_sdhci_plat *plat = dev_get_platdata(dev);
  373. struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
  374. struct xenon_sdhci_priv *priv = dev_get_priv(dev);
  375. struct sdhci_host *host = dev_get_priv(dev);
  376. int ret;
  377. host->mmc = &plat->mmc;
  378. host->mmc->priv = host;
  379. host->mmc->dev = dev;
  380. upriv->mmc = host->mmc;
  381. /* Set quirks */
  382. host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR;
  383. /* Set default timing */
  384. priv->timing = MMC_TIMING_LEGACY;
  385. /* Get the vqmmc regulator if there is */
  386. device_get_supply_regulator(dev, "vqmmc-supply", &priv->vqmmc);
  387. /* Set the initial voltage value to 3.3V if there is regulator */
  388. if (priv->vqmmc) {
  389. ret = regulator_set_value(priv->vqmmc,
  390. XENON_MMC_3V3_UV);
  391. if (ret) {
  392. printf("Failed to set VQMMC regulator to 3.3V\n");
  393. return ret;
  394. }
  395. }
  396. /* Disable auto clock gating during init */
  397. xenon_mmc_set_acg(host, false);
  398. /* Enable slot */
  399. xenon_mmc_enable_slot(host, XENON_MMC_SLOT_ID_HYPERION);
  400. /*
  401. * Set default power on SoC PHY PAD register (currently only
  402. * available on the Armada 3700)
  403. */
  404. if (priv->pad_ctrl_reg)
  405. armada_3700_soc_pad_voltage_set(host);
  406. host->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_DDR_52MHz;
  407. ret = mmc_of_parse(dev, &plat->cfg);
  408. if (ret)
  409. return ret;
  410. host->ops = &xenon_sdhci_ops;
  411. host->max_clk = XENON_MMC_MAX_CLK;
  412. ret = sdhci_setup_cfg(&plat->cfg, host, XENON_MMC_MAX_CLK, 0);
  413. if (ret)
  414. return ret;
  415. ret = sdhci_probe(dev);
  416. if (ret)
  417. return ret;
  418. /* Enable parallel transfer */
  419. xenon_mmc_enable_parallel_tran(host, XENON_MMC_SLOT_ID_HYPERION);
  420. /* Disable tuning functionality of this slot */
  421. xenon_mmc_disable_tuning(host, XENON_MMC_SLOT_ID_HYPERION);
  422. /* Enable auto clock gating after init */
  423. xenon_mmc_set_acg(host, true);
  424. xenon_mask_cmd_conflict_err(host);
  425. return ret;
  426. }
  427. static int xenon_sdhci_ofdata_to_platdata(struct udevice *dev)
  428. {
  429. struct sdhci_host *host = dev_get_priv(dev);
  430. struct xenon_sdhci_priv *priv = dev_get_priv(dev);
  431. const char *name;
  432. host->name = dev->name;
  433. host->ioaddr = dev_read_addr_ptr(dev);
  434. if (device_is_compatible(dev, "marvell,armada-3700-sdhci"))
  435. priv->pad_ctrl_reg = (void *)devfdt_get_addr_index(dev, 1);
  436. name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "marvell,pad-type",
  437. NULL);
  438. if (name) {
  439. if (0 == strncmp(name, "sd", 2)) {
  440. priv->pad_type = SOC_PAD_SD;
  441. } else if (0 == strncmp(name, "fixed-1-8v", 10)) {
  442. priv->pad_type = SOC_PAD_FIXED_1_8V;
  443. } else {
  444. printf("Unsupported SOC PHY PAD ctrl type %s\n", name);
  445. return -EINVAL;
  446. }
  447. }
  448. return 0;
  449. }
  450. static int xenon_sdhci_bind(struct udevice *dev)
  451. {
  452. struct xenon_sdhci_plat *plat = dev_get_platdata(dev);
  453. return sdhci_bind(dev, &plat->mmc, &plat->cfg);
  454. }
  455. static const struct udevice_id xenon_sdhci_ids[] = {
  456. { .compatible = "marvell,armada-8k-sdhci",},
  457. { .compatible = "marvell,armada-3700-sdhci",},
  458. { }
  459. };
  460. U_BOOT_DRIVER(xenon_sdhci_drv) = {
  461. .name = "xenon_sdhci",
  462. .id = UCLASS_MMC,
  463. .of_match = xenon_sdhci_ids,
  464. .ofdata_to_platdata = xenon_sdhci_ofdata_to_platdata,
  465. .ops = &sdhci_ops,
  466. .bind = xenon_sdhci_bind,
  467. .probe = xenon_sdhci_probe,
  468. .priv_auto_alloc_size = sizeof(struct xenon_sdhci_priv),
  469. .platdata_auto_alloc_size = sizeof(struct xenon_sdhci_plat),
  470. };