1 /* 2 * Support for SDHCI on STMicroelectronics SoCs 3 * 4 * Copyright (C) 2014 STMicroelectronics Ltd 5 * Author: Giuseppe Cavallaro <peppe.cavallaro@st.com> 6 * Contributors: Peter Griffin <peter.griffin@linaro.org> 7 * 8 * Based on sdhci-cns3xxx.c 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 */ 20 21 #include <linux/io.h> 22 #include <linux/of.h> 23 #include <linux/module.h> 24 #include <linux/err.h> 25 #include <linux/mmc/host.h> 26 27 #include "sdhci-pltfm.h" 28 29 /* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */ 30 31 #define ST_MMC_CCONFIG_REG_1 0x400 32 #define ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT BIT(24) 33 #define ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ BIT(12) 34 #define ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT BIT(8) 35 #define ST_MMC_CCONFIG_ASYNC_WAKEUP BIT(0) 36 #define ST_MMC_CCONFIG_1_DEFAULT \ 37 ((ST_MMC_CCONFIG_TIMEOUT_CLK_UNIT) | \ 38 (ST_MMC_CCONFIG_TIMEOUT_CLK_FREQ) | \ 39 (ST_MMC_CCONFIG_TUNING_COUNT_DEFAULT)) 40 41 #define ST_MMC_CCONFIG_REG_2 0x404 42 #define ST_MMC_CCONFIG_HIGH_SPEED BIT(28) 43 #define ST_MMC_CCONFIG_ADMA2 BIT(24) 44 #define ST_MMC_CCONFIG_8BIT BIT(20) 45 #define ST_MMC_CCONFIG_MAX_BLK_LEN 16 46 #define MAX_BLK_LEN_1024 1 47 #define MAX_BLK_LEN_2048 2 48 #define BASE_CLK_FREQ_200 0xc8 49 #define BASE_CLK_FREQ_100 0x64 50 #define BASE_CLK_FREQ_50 0x32 51 #define ST_MMC_CCONFIG_2_DEFAULT \ 52 (ST_MMC_CCONFIG_HIGH_SPEED | ST_MMC_CCONFIG_ADMA2 | \ 53 ST_MMC_CCONFIG_8BIT | \ 54 (MAX_BLK_LEN_1024 << ST_MMC_CCONFIG_MAX_BLK_LEN)) 55 56 #define ST_MMC_CCONFIG_REG_3 0x408 57 #define ST_MMC_CCONFIG_EMMC_SLOT_TYPE BIT(28) 58 #define ST_MMC_CCONFIG_64BIT BIT(24) 59 #define ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT BIT(20) 60 #define ST_MMC_CCONFIG_1P8_VOLT BIT(16) 61 #define ST_MMC_CCONFIG_3P0_VOLT BIT(12) 62 #define ST_MMC_CCONFIG_3P3_VOLT BIT(8) 63 #define ST_MMC_CCONFIG_SUSP_RES_SUPPORT BIT(4) 64 #define ST_MMC_CCONFIG_SDMA BIT(0) 65 #define ST_MMC_CCONFIG_3_DEFAULT \ 66 (ST_MMC_CCONFIG_ASYNCH_INTR_SUPPORT | \ 67 ST_MMC_CCONFIG_3P3_VOLT | \ 68 ST_MMC_CCONFIG_SUSP_RES_SUPPORT | \ 69 ST_MMC_CCONFIG_SDMA) 70 71 #define ST_MMC_CCONFIG_REG_4 0x40c 72 #define ST_MMC_CCONFIG_D_DRIVER BIT(20) 73 #define ST_MMC_CCONFIG_C_DRIVER BIT(16) 74 #define ST_MMC_CCONFIG_A_DRIVER BIT(12) 75 #define ST_MMC_CCONFIG_DDR50 BIT(8) 76 #define ST_MMC_CCONFIG_SDR104 BIT(4) 77 #define ST_MMC_CCONFIG_SDR50 BIT(0) 78 #define ST_MMC_CCONFIG_4_DEFAULT 0 79 80 #define ST_MMC_CCONFIG_REG_5 0x410 81 #define ST_MMC_CCONFIG_TUNING_FOR_SDR50 BIT(8) 82 #define RETUNING_TIMER_CNT_MAX 0xf 83 #define ST_MMC_CCONFIG_5_DEFAULT 0 84 85 /* I/O configuration for Arasan IP */ 86 #define ST_MMC_GP_OUTPUT 0x450 87 #define ST_MMC_GP_OUTPUT_CD BIT(12) 88 89 #define ST_MMC_STATUS_R 0x460 90 91 #define ST_TOP_MMC_DLY_FIX_OFF(x) (x - 0x8) 92 93 /* TOP config registers to manage static and dynamic delay */ 94 #define ST_TOP_MMC_TX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0x8) 95 #define ST_TOP_MMC_RX_CLK_DLY ST_TOP_MMC_DLY_FIX_OFF(0xc) 96 /* MMC delay control register */ 97 #define ST_TOP_MMC_DLY_CTRL ST_TOP_MMC_DLY_FIX_OFF(0x18) 98 #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_CMD BIT(0) 99 #define ST_TOP_MMC_DLY_CTRL_DLL_BYPASS_PH_SEL BIT(1) 100 #define ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE BIT(8) 101 #define ST_TOP_MMC_DLY_CTRL_RX_DLL_ENABLE BIT(9) 102 #define ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY BIT(10) 103 #define ST_TOP_MMC_START_DLL_LOCK BIT(11) 104 105 /* register to provide the phase-shift value for DLL */ 106 #define ST_TOP_MMC_TX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x1c) 107 #define ST_TOP_MMC_RX_DLL_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x20) 108 #define ST_TOP_MMC_RX_CMD_STEP_DLY ST_TOP_MMC_DLY_FIX_OFF(0x24) 109 110 /* phase shift delay on the tx clk 2.188ns */ 111 #define ST_TOP_MMC_TX_DLL_STEP_DLY_VALID 0x6 112 113 #define ST_TOP_MMC_DLY_MAX 0xf 114 115 #define ST_TOP_MMC_DYN_DLY_CONF \ 116 (ST_TOP_MMC_DLY_CTRL_TX_DLL_ENABLE | \ 117 ST_TOP_MMC_DLY_CTRL_ATUNE_NOT_CFG_DLY | \ 118 ST_TOP_MMC_START_DLL_LOCK) 119 120 static u32 sdhci_st_readl(struct sdhci_host *host, int reg) 121 { 122 u32 ret; 123 124 switch (reg) { 125 case SDHCI_CAPABILITIES: 126 ret = readl_relaxed(host->ioaddr + reg); 127 /* Support 3.3V and 1.8V */ 128 ret &= ~SDHCI_CAN_VDD_300; 129 break; 130 default: 131 ret = readl_relaxed(host->ioaddr + reg); 132 } 133 return ret; 134 } 135 136 static const struct sdhci_ops sdhci_st_ops = { 137 .get_max_clock = sdhci_pltfm_clk_get_max_clock, 138 .set_clock = sdhci_set_clock, 139 .set_bus_width = sdhci_set_bus_width, 140 .read_l = sdhci_st_readl, 141 .reset = sdhci_reset, 142 }; 143 144 static const struct sdhci_pltfm_data sdhci_st_pdata = { 145 .ops = &sdhci_st_ops, 146 .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | 147 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 148 }; 149 150 151 static int sdhci_st_probe(struct platform_device *pdev) 152 { 153 struct sdhci_host *host; 154 struct sdhci_pltfm_host *pltfm_host; 155 struct clk *clk; 156 int ret = 0; 157 u16 host_version; 158 159 clk = devm_clk_get(&pdev->dev, "mmc"); 160 if (IS_ERR(clk)) { 161 dev_err(&pdev->dev, "Peripheral clk not found\n"); 162 return PTR_ERR(clk); 163 } 164 165 host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, 0); 166 if (IS_ERR(host)) { 167 dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n"); 168 return PTR_ERR(host); 169 } 170 171 ret = mmc_of_parse(host->mmc); 172 if (ret) { 173 dev_err(&pdev->dev, "Failed mmc_of_parse\n"); 174 goto err_of; 175 } 176 177 clk_prepare_enable(clk); 178 179 pltfm_host = sdhci_priv(host); 180 pltfm_host->clk = clk; 181 182 ret = sdhci_add_host(host); 183 if (ret) { 184 dev_err(&pdev->dev, "Failed sdhci_add_host\n"); 185 goto err_out; 186 } 187 188 platform_set_drvdata(pdev, host); 189 190 host_version = readw_relaxed((host->ioaddr + SDHCI_HOST_VERSION)); 191 192 dev_info(&pdev->dev, "SDHCI ST Initialised: Host Version: 0x%x Vendor Version 0x%x\n", 193 ((host_version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT), 194 ((host_version & SDHCI_VENDOR_VER_MASK) >> 195 SDHCI_VENDOR_VER_SHIFT)); 196 197 return 0; 198 199 err_out: 200 clk_disable_unprepare(clk); 201 err_of: 202 sdhci_pltfm_free(pdev); 203 204 return ret; 205 } 206 207 #ifdef CONFIG_PM_SLEEP 208 static int sdhci_st_suspend(struct device *dev) 209 { 210 struct sdhci_host *host = dev_get_drvdata(dev); 211 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 212 int ret = sdhci_suspend_host(host); 213 214 if (ret) 215 goto out; 216 217 clk_disable_unprepare(pltfm_host->clk); 218 out: 219 return ret; 220 } 221 222 static int sdhci_st_resume(struct device *dev) 223 { 224 struct sdhci_host *host = dev_get_drvdata(dev); 225 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 226 227 clk_prepare_enable(pltfm_host->clk); 228 229 return sdhci_resume_host(host); 230 } 231 #endif 232 233 static SIMPLE_DEV_PM_OPS(sdhci_st_pmops, sdhci_st_suspend, sdhci_st_resume); 234 235 static const struct of_device_id st_sdhci_match[] = { 236 { .compatible = "st,sdhci" }, 237 {}, 238 }; 239 240 MODULE_DEVICE_TABLE(of, st_sdhci_match); 241 242 static struct platform_driver sdhci_st_driver = { 243 .probe = sdhci_st_probe, 244 .remove = sdhci_pltfm_unregister, 245 .driver = { 246 .name = "sdhci-st", 247 .pm = &sdhci_st_pmops, 248 .of_match_table = of_match_ptr(st_sdhci_match), 249 }, 250 }; 251 252 module_platform_driver(sdhci_st_driver); 253 254 MODULE_DESCRIPTION("SDHCI driver for STMicroelectronics SoCs"); 255 MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); 256 MODULE_LICENSE("GPL v2"); 257 MODULE_ALIAS("platform:st-sdhci"); 258