1 /* 2 * Copyright (C) 2010 Google, Inc. 3 * 4 * This software is licensed under the terms of the GNU General Public 5 * License version 2, as published by the Free Software Foundation, and 6 * may be copied, distributed, and modified under those terms. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 */ 14 15 #include <linux/err.h> 16 #include <linux/module.h> 17 #include <linux/init.h> 18 #include <linux/platform_device.h> 19 #include <linux/clk.h> 20 #include <linux/io.h> 21 #include <linux/of.h> 22 #include <linux/of_device.h> 23 #include <linux/of_gpio.h> 24 #include <linux/gpio.h> 25 #include <linux/mmc/card.h> 26 #include <linux/mmc/host.h> 27 #include <linux/mmc/slot-gpio.h> 28 29 #include "sdhci-pltfm.h" 30 31 /* Tegra SDHOST controller vendor register definitions */ 32 #define SDHCI_TEGRA_VENDOR_MISC_CTRL 0x120 33 #define SDHCI_MISC_CTRL_ENABLE_SDR104 0x8 34 #define SDHCI_MISC_CTRL_ENABLE_SDR50 0x10 35 #define SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300 0x20 36 #define SDHCI_MISC_CTRL_ENABLE_DDR50 0x200 37 38 #define NVQUIRK_FORCE_SDHCI_SPEC_200 BIT(0) 39 #define NVQUIRK_ENABLE_BLOCK_GAP_DET BIT(1) 40 #define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2) 41 #define NVQUIRK_DISABLE_SDR50 BIT(3) 42 #define NVQUIRK_DISABLE_SDR104 BIT(4) 43 #define NVQUIRK_DISABLE_DDR50 BIT(5) 44 #define NVQUIRK_SHADOW_XFER_MODE_REG BIT(6) 45 46 struct sdhci_tegra_soc_data { 47 const struct sdhci_pltfm_data *pdata; 48 u32 nvquirks; 49 }; 50 51 struct sdhci_tegra { 52 const struct sdhci_tegra_soc_data *soc_data; 53 int power_gpio; 54 }; 55 56 static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) 57 { 58 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 59 struct sdhci_tegra *tegra_host = pltfm_host->priv; 60 const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 61 62 if (unlikely((soc_data->nvquirks & NVQUIRK_FORCE_SDHCI_SPEC_200) && 63 (reg == SDHCI_HOST_VERSION))) { 64 /* Erratum: Version register is invalid in HW. */ 65 return SDHCI_SPEC_200; 66 } 67 68 return readw(host->ioaddr + reg); 69 } 70 71 static void tegra_sdhci_writew(struct sdhci_host *host, u16 val, int reg) 72 { 73 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 74 struct sdhci_tegra *tegra_host = pltfm_host->priv; 75 const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 76 77 if (soc_data->nvquirks & NVQUIRK_SHADOW_XFER_MODE_REG) { 78 switch (reg) { 79 case SDHCI_TRANSFER_MODE: 80 /* 81 * Postpone this write, we must do it together with a 82 * command write that is down below. 83 */ 84 pltfm_host->xfer_mode_shadow = val; 85 return; 86 case SDHCI_COMMAND: 87 writel((val << 16) | pltfm_host->xfer_mode_shadow, 88 host->ioaddr + SDHCI_TRANSFER_MODE); 89 return; 90 } 91 } 92 93 writew(val, host->ioaddr + reg); 94 } 95 96 static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) 97 { 98 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 99 struct sdhci_tegra *tegra_host = pltfm_host->priv; 100 const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 101 102 /* Seems like we're getting spurious timeout and crc errors, so 103 * disable signalling of them. In case of real errors software 104 * timers should take care of eventually detecting them. 105 */ 106 if (unlikely(reg == SDHCI_SIGNAL_ENABLE)) 107 val &= ~(SDHCI_INT_TIMEOUT|SDHCI_INT_CRC); 108 109 writel(val, host->ioaddr + reg); 110 111 if (unlikely((soc_data->nvquirks & NVQUIRK_ENABLE_BLOCK_GAP_DET) && 112 (reg == SDHCI_INT_ENABLE))) { 113 /* Erratum: Must enable block gap interrupt detection */ 114 u8 gap_ctrl = readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL); 115 if (val & SDHCI_INT_CARD_INT) 116 gap_ctrl |= 0x8; 117 else 118 gap_ctrl &= ~0x8; 119 writeb(gap_ctrl, host->ioaddr + SDHCI_BLOCK_GAP_CONTROL); 120 } 121 } 122 123 static unsigned int tegra_sdhci_get_ro(struct sdhci_host *host) 124 { 125 return mmc_gpio_get_ro(host->mmc); 126 } 127 128 static void tegra_sdhci_reset(struct sdhci_host *host, u8 mask) 129 { 130 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 131 struct sdhci_tegra *tegra_host = pltfm_host->priv; 132 const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data; 133 u32 misc_ctrl; 134 135 sdhci_reset(host, mask); 136 137 if (!(mask & SDHCI_RESET_ALL)) 138 return; 139 140 misc_ctrl = sdhci_readw(host, SDHCI_TEGRA_VENDOR_MISC_CTRL); 141 /* Erratum: Enable SDHCI spec v3.00 support */ 142 if (soc_data->nvquirks & NVQUIRK_ENABLE_SDHCI_SPEC_300) 143 misc_ctrl |= SDHCI_MISC_CTRL_ENABLE_SDHCI_SPEC_300; 144 /* Don't advertise UHS modes which aren't supported yet */ 145 if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR50) 146 misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR50; 147 if (soc_data->nvquirks & NVQUIRK_DISABLE_DDR50) 148 misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_DDR50; 149 if (soc_data->nvquirks & NVQUIRK_DISABLE_SDR104) 150 misc_ctrl &= ~SDHCI_MISC_CTRL_ENABLE_SDR104; 151 sdhci_writew(host, misc_ctrl, SDHCI_TEGRA_VENDOR_MISC_CTRL); 152 } 153 154 static void tegra_sdhci_set_bus_width(struct sdhci_host *host, int bus_width) 155 { 156 u32 ctrl; 157 158 ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); 159 if ((host->mmc->caps & MMC_CAP_8_BIT_DATA) && 160 (bus_width == MMC_BUS_WIDTH_8)) { 161 ctrl &= ~SDHCI_CTRL_4BITBUS; 162 ctrl |= SDHCI_CTRL_8BITBUS; 163 } else { 164 ctrl &= ~SDHCI_CTRL_8BITBUS; 165 if (bus_width == MMC_BUS_WIDTH_4) 166 ctrl |= SDHCI_CTRL_4BITBUS; 167 else 168 ctrl &= ~SDHCI_CTRL_4BITBUS; 169 } 170 sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); 171 } 172 173 static const struct sdhci_ops tegra_sdhci_ops = { 174 .get_ro = tegra_sdhci_get_ro, 175 .read_w = tegra_sdhci_readw, 176 .write_w = tegra_sdhci_writew, 177 .write_l = tegra_sdhci_writel, 178 .set_clock = sdhci_set_clock, 179 .set_bus_width = tegra_sdhci_set_bus_width, 180 .reset = tegra_sdhci_reset, 181 .set_uhs_signaling = sdhci_set_uhs_signaling, 182 .get_max_clock = sdhci_pltfm_clk_get_max_clock, 183 }; 184 185 static const struct sdhci_pltfm_data sdhci_tegra20_pdata = { 186 .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 187 SDHCI_QUIRK_SINGLE_POWER_WRITE | 188 SDHCI_QUIRK_NO_HISPD_BIT | 189 SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 190 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 191 .ops = &tegra_sdhci_ops, 192 }; 193 194 static struct sdhci_tegra_soc_data soc_data_tegra20 = { 195 .pdata = &sdhci_tegra20_pdata, 196 .nvquirks = NVQUIRK_FORCE_SDHCI_SPEC_200 | 197 NVQUIRK_ENABLE_BLOCK_GAP_DET, 198 }; 199 200 static const struct sdhci_pltfm_data sdhci_tegra30_pdata = { 201 .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 202 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 203 SDHCI_QUIRK_SINGLE_POWER_WRITE | 204 SDHCI_QUIRK_NO_HISPD_BIT | 205 SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 206 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 207 .ops = &tegra_sdhci_ops, 208 }; 209 210 static struct sdhci_tegra_soc_data soc_data_tegra30 = { 211 .pdata = &sdhci_tegra30_pdata, 212 .nvquirks = NVQUIRK_ENABLE_SDHCI_SPEC_300 | 213 NVQUIRK_DISABLE_SDR50 | 214 NVQUIRK_DISABLE_SDR104, 215 }; 216 217 static const struct sdhci_pltfm_data sdhci_tegra114_pdata = { 218 .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | 219 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | 220 SDHCI_QUIRK_SINGLE_POWER_WRITE | 221 SDHCI_QUIRK_NO_HISPD_BIT | 222 SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC | 223 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN, 224 .ops = &tegra_sdhci_ops, 225 }; 226 227 static struct sdhci_tegra_soc_data soc_data_tegra114 = { 228 .pdata = &sdhci_tegra114_pdata, 229 .nvquirks = NVQUIRK_DISABLE_SDR50 | 230 NVQUIRK_DISABLE_DDR50 | 231 NVQUIRK_DISABLE_SDR104 | 232 NVQUIRK_SHADOW_XFER_MODE_REG, 233 }; 234 235 static const struct of_device_id sdhci_tegra_dt_match[] = { 236 { .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra114 }, 237 { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 }, 238 { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 }, 239 { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 }, 240 {} 241 }; 242 MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match); 243 244 static int sdhci_tegra_parse_dt(struct device *dev) 245 { 246 struct device_node *np = dev->of_node; 247 struct sdhci_host *host = dev_get_drvdata(dev); 248 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 249 struct sdhci_tegra *tegra_host = pltfm_host->priv; 250 251 tegra_host->power_gpio = of_get_named_gpio(np, "power-gpios", 0); 252 return mmc_of_parse(host->mmc); 253 } 254 255 static int sdhci_tegra_probe(struct platform_device *pdev) 256 { 257 const struct of_device_id *match; 258 const struct sdhci_tegra_soc_data *soc_data; 259 struct sdhci_host *host; 260 struct sdhci_pltfm_host *pltfm_host; 261 struct sdhci_tegra *tegra_host; 262 struct clk *clk; 263 int rc; 264 265 match = of_match_device(sdhci_tegra_dt_match, &pdev->dev); 266 if (!match) 267 return -EINVAL; 268 soc_data = match->data; 269 270 host = sdhci_pltfm_init(pdev, soc_data->pdata, 0); 271 if (IS_ERR(host)) 272 return PTR_ERR(host); 273 pltfm_host = sdhci_priv(host); 274 275 tegra_host = devm_kzalloc(&pdev->dev, sizeof(*tegra_host), GFP_KERNEL); 276 if (!tegra_host) { 277 dev_err(mmc_dev(host->mmc), "failed to allocate tegra_host\n"); 278 rc = -ENOMEM; 279 goto err_alloc_tegra_host; 280 } 281 tegra_host->soc_data = soc_data; 282 pltfm_host->priv = tegra_host; 283 284 rc = sdhci_tegra_parse_dt(&pdev->dev); 285 if (rc) 286 goto err_parse_dt; 287 288 if (gpio_is_valid(tegra_host->power_gpio)) { 289 rc = gpio_request(tegra_host->power_gpio, "sdhci_power"); 290 if (rc) { 291 dev_err(mmc_dev(host->mmc), 292 "failed to allocate power gpio\n"); 293 goto err_power_req; 294 } 295 gpio_direction_output(tegra_host->power_gpio, 1); 296 } 297 298 clk = clk_get(mmc_dev(host->mmc), NULL); 299 if (IS_ERR(clk)) { 300 dev_err(mmc_dev(host->mmc), "clk err\n"); 301 rc = PTR_ERR(clk); 302 goto err_clk_get; 303 } 304 clk_prepare_enable(clk); 305 pltfm_host->clk = clk; 306 307 rc = sdhci_add_host(host); 308 if (rc) 309 goto err_add_host; 310 311 return 0; 312 313 err_add_host: 314 clk_disable_unprepare(pltfm_host->clk); 315 clk_put(pltfm_host->clk); 316 err_clk_get: 317 if (gpio_is_valid(tegra_host->power_gpio)) 318 gpio_free(tegra_host->power_gpio); 319 err_power_req: 320 err_parse_dt: 321 err_alloc_tegra_host: 322 sdhci_pltfm_free(pdev); 323 return rc; 324 } 325 326 static int sdhci_tegra_remove(struct platform_device *pdev) 327 { 328 struct sdhci_host *host = platform_get_drvdata(pdev); 329 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 330 struct sdhci_tegra *tegra_host = pltfm_host->priv; 331 int dead = (readl(host->ioaddr + SDHCI_INT_STATUS) == 0xffffffff); 332 333 sdhci_remove_host(host, dead); 334 335 if (gpio_is_valid(tegra_host->power_gpio)) 336 gpio_free(tegra_host->power_gpio); 337 338 clk_disable_unprepare(pltfm_host->clk); 339 clk_put(pltfm_host->clk); 340 341 sdhci_pltfm_free(pdev); 342 343 return 0; 344 } 345 346 static struct platform_driver sdhci_tegra_driver = { 347 .driver = { 348 .name = "sdhci-tegra", 349 .of_match_table = sdhci_tegra_dt_match, 350 .pm = SDHCI_PLTFM_PMOPS, 351 }, 352 .probe = sdhci_tegra_probe, 353 .remove = sdhci_tegra_remove, 354 }; 355 356 module_platform_driver(sdhci_tegra_driver); 357 358 MODULE_DESCRIPTION("SDHCI driver for Tegra"); 359 MODULE_AUTHOR("Google, Inc."); 360 MODULE_LICENSE("GPL v2"); 361