xenon_sdhci.c 13 KB

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