xenon_sdhci.c 15 KB

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