0001
0002
0003
0004 #include <linux/kernel.h>
0005 #include <linux/module.h>
0006 #include <linux/delay.h>
0007 #include <linux/highmem.h>
0008 #include <linux/platform_device.h>
0009 #include <linux/mmc/host.h>
0010 #include <linux/io.h>
0011 #include <linux/clk.h>
0012 #include <linux/regulator/consumer.h>
0013 #include <linux/of.h>
0014 #include <linux/of_device.h>
0015 #include <linux/mmc/slot-gpio.h>
0016
0017 #include "sdhci-pltfm.h"
0018 #include "sdhci.h"
0019
0020 #define SDHCI_SOFT_RESET 0x01000000
0021 #define KONA_SDHOST_CORECTRL 0x8000
0022 #define KONA_SDHOST_CD_PINCTRL 0x00000008
0023 #define KONA_SDHOST_STOP_HCLK 0x00000004
0024 #define KONA_SDHOST_RESET 0x00000002
0025 #define KONA_SDHOST_EN 0x00000001
0026
0027 #define KONA_SDHOST_CORESTAT 0x8004
0028 #define KONA_SDHOST_WP 0x00000002
0029 #define KONA_SDHOST_CD_SW 0x00000001
0030
0031 #define KONA_SDHOST_COREIMR 0x8008
0032 #define KONA_SDHOST_IP 0x00000001
0033
0034 #define KONA_SDHOST_COREISR 0x800C
0035 #define KONA_SDHOST_COREIMSR 0x8010
0036 #define KONA_SDHOST_COREDBG1 0x8014
0037 #define KONA_SDHOST_COREGPO_MASK 0x8018
0038
0039 #define SD_DETECT_GPIO_DEBOUNCE_128MS 128
0040
0041 #define KONA_MMC_AUTOSUSPEND_DELAY (50)
0042
0043 struct sdhci_bcm_kona_dev {
0044 struct mutex write_lock;
0045 };
0046
0047
0048 static int sdhci_bcm_kona_sd_reset(struct sdhci_host *host)
0049 {
0050 unsigned int val;
0051 unsigned long timeout;
0052
0053
0054 timeout = jiffies + msecs_to_jiffies(100);
0055
0056
0057 val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
0058 val |= KONA_SDHOST_RESET;
0059 sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
0060
0061 while (!(sdhci_readl(host, KONA_SDHOST_CORECTRL) & KONA_SDHOST_RESET)) {
0062 if (time_is_before_jiffies(timeout)) {
0063 pr_err("Error: sd host is stuck in reset!!!\n");
0064 return -EFAULT;
0065 }
0066 }
0067
0068
0069 val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
0070 val &= ~KONA_SDHOST_RESET;
0071
0072
0073
0074
0075
0076
0077
0078 usleep_range(1000, 5000);
0079 sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
0080
0081 return 0;
0082 }
0083
0084 static void sdhci_bcm_kona_sd_init(struct sdhci_host *host)
0085 {
0086 unsigned int val;
0087
0088
0089 val = sdhci_readl(host, KONA_SDHOST_COREIMR);
0090 val |= KONA_SDHOST_IP;
0091 sdhci_writel(host, val, KONA_SDHOST_COREIMR);
0092
0093
0094 val = sdhci_readl(host, KONA_SDHOST_CORECTRL);
0095 val |= KONA_SDHOST_EN;
0096
0097
0098
0099
0100
0101
0102
0103 usleep_range(1000, 5000);
0104 sdhci_writel(host, val, KONA_SDHOST_CORECTRL);
0105 }
0106
0107
0108
0109
0110
0111
0112
0113 static int sdhci_bcm_kona_sd_card_emulate(struct sdhci_host *host, int insert)
0114 {
0115 struct sdhci_pltfm_host *pltfm_priv = sdhci_priv(host);
0116 struct sdhci_bcm_kona_dev *kona_dev = sdhci_pltfm_priv(pltfm_priv);
0117 u32 val;
0118
0119
0120
0121
0122
0123
0124
0125
0126 mutex_lock(&kona_dev->write_lock);
0127 udelay(20);
0128 val = sdhci_readl(host, KONA_SDHOST_CORESTAT);
0129
0130 if (insert) {
0131 int ret;
0132
0133 ret = mmc_gpio_get_ro(host->mmc);
0134 if (ret >= 0)
0135 val = (val & ~KONA_SDHOST_WP) |
0136 ((ret) ? KONA_SDHOST_WP : 0);
0137
0138 val |= KONA_SDHOST_CD_SW;
0139 sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
0140 } else {
0141 val &= ~KONA_SDHOST_CD_SW;
0142 sdhci_writel(host, val, KONA_SDHOST_CORESTAT);
0143 }
0144 mutex_unlock(&kona_dev->write_lock);
0145
0146 return 0;
0147 }
0148
0149
0150
0151
0152 static void sdhci_bcm_kona_card_event(struct sdhci_host *host)
0153 {
0154 if (mmc_gpio_get_cd(host->mmc) > 0) {
0155 dev_dbg(mmc_dev(host->mmc),
0156 "card inserted\n");
0157 sdhci_bcm_kona_sd_card_emulate(host, 1);
0158 } else {
0159 dev_dbg(mmc_dev(host->mmc),
0160 "card removed\n");
0161 sdhci_bcm_kona_sd_card_emulate(host, 0);
0162 }
0163 }
0164
0165 static void sdhci_bcm_kona_init_74_clocks(struct sdhci_host *host,
0166 u8 power_mode)
0167 {
0168
0169
0170
0171
0172
0173 if (power_mode != MMC_POWER_OFF)
0174 udelay(740);
0175 }
0176
0177 static const struct sdhci_ops sdhci_bcm_kona_ops = {
0178 .set_clock = sdhci_set_clock,
0179 .get_max_clock = sdhci_pltfm_clk_get_max_clock,
0180 .get_timeout_clock = sdhci_pltfm_clk_get_max_clock,
0181 .platform_send_init_74_clocks = sdhci_bcm_kona_init_74_clocks,
0182 .set_bus_width = sdhci_set_bus_width,
0183 .reset = sdhci_reset,
0184 .set_uhs_signaling = sdhci_set_uhs_signaling,
0185 .card_event = sdhci_bcm_kona_card_event,
0186 };
0187
0188 static const struct sdhci_pltfm_data sdhci_pltfm_data_kona = {
0189 .ops = &sdhci_bcm_kona_ops,
0190 .quirks = SDHCI_QUIRK_NO_CARD_NO_RESET |
0191 SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | SDHCI_QUIRK_32BIT_DMA_ADDR |
0192 SDHCI_QUIRK_32BIT_DMA_SIZE | SDHCI_QUIRK_32BIT_ADMA_SIZE |
0193 SDHCI_QUIRK_FORCE_BLK_SZ_2048 |
0194 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
0195 };
0196
0197 static const struct of_device_id sdhci_bcm_kona_of_match[] = {
0198 { .compatible = "brcm,kona-sdhci"},
0199 { .compatible = "bcm,kona-sdhci"},
0200 {}
0201 };
0202 MODULE_DEVICE_TABLE(of, sdhci_bcm_kona_of_match);
0203
0204 static int sdhci_bcm_kona_probe(struct platform_device *pdev)
0205 {
0206 struct sdhci_bcm_kona_dev *kona_dev = NULL;
0207 struct sdhci_pltfm_host *pltfm_priv;
0208 struct device *dev = &pdev->dev;
0209 struct sdhci_host *host;
0210 int ret;
0211
0212 ret = 0;
0213
0214 host = sdhci_pltfm_init(pdev, &sdhci_pltfm_data_kona,
0215 sizeof(*kona_dev));
0216 if (IS_ERR(host))
0217 return PTR_ERR(host);
0218
0219 dev_dbg(dev, "%s: inited. IOADDR=%p\n", __func__, host->ioaddr);
0220
0221 pltfm_priv = sdhci_priv(host);
0222
0223 kona_dev = sdhci_pltfm_priv(pltfm_priv);
0224 mutex_init(&kona_dev->write_lock);
0225
0226 ret = mmc_of_parse(host->mmc);
0227 if (ret)
0228 goto err_pltfm_free;
0229
0230 if (!host->mmc->f_max) {
0231 dev_err(&pdev->dev, "Missing max-freq for SDHCI cfg\n");
0232 ret = -ENXIO;
0233 goto err_pltfm_free;
0234 }
0235
0236
0237 pltfm_priv->clk = devm_clk_get(dev, NULL);
0238 if (IS_ERR(pltfm_priv->clk)) {
0239 dev_err(dev, "Failed to get core clock\n");
0240 ret = PTR_ERR(pltfm_priv->clk);
0241 goto err_pltfm_free;
0242 }
0243
0244 ret = clk_set_rate(pltfm_priv->clk, host->mmc->f_max);
0245 if (ret) {
0246 dev_err(dev, "Failed to set rate core clock\n");
0247 goto err_pltfm_free;
0248 }
0249
0250 ret = clk_prepare_enable(pltfm_priv->clk);
0251 if (ret) {
0252 dev_err(dev, "Failed to enable core clock\n");
0253 goto err_pltfm_free;
0254 }
0255
0256 dev_dbg(dev, "non-removable=%c\n",
0257 mmc_card_is_removable(host->mmc) ? 'N' : 'Y');
0258 dev_dbg(dev, "cd_gpio %c, wp_gpio %c\n",
0259 (mmc_gpio_get_cd(host->mmc) != -ENOSYS) ? 'Y' : 'N',
0260 (mmc_gpio_get_ro(host->mmc) != -ENOSYS) ? 'Y' : 'N');
0261
0262 if (!mmc_card_is_removable(host->mmc))
0263 host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
0264
0265 dev_dbg(dev, "is_8bit=%c\n",
0266 (host->mmc->caps & MMC_CAP_8_BIT_DATA) ? 'Y' : 'N');
0267
0268 ret = sdhci_bcm_kona_sd_reset(host);
0269 if (ret)
0270 goto err_clk_disable;
0271
0272 sdhci_bcm_kona_sd_init(host);
0273
0274 ret = sdhci_add_host(host);
0275 if (ret)
0276 goto err_reset;
0277
0278
0279 if (!mmc_card_is_removable(host->mmc)) {
0280 ret = sdhci_bcm_kona_sd_card_emulate(host, 1);
0281 if (ret) {
0282 dev_err(dev,
0283 "unable to emulate card insertion\n");
0284 goto err_remove_host;
0285 }
0286 }
0287
0288
0289
0290
0291
0292 if (mmc_gpio_get_cd(host->mmc) > 0)
0293 sdhci_bcm_kona_sd_card_emulate(host, 1);
0294
0295 dev_dbg(dev, "initialized properly\n");
0296 return 0;
0297
0298 err_remove_host:
0299 sdhci_remove_host(host, 0);
0300
0301 err_reset:
0302 sdhci_bcm_kona_sd_reset(host);
0303
0304 err_clk_disable:
0305 clk_disable_unprepare(pltfm_priv->clk);
0306
0307 err_pltfm_free:
0308 sdhci_pltfm_free(pdev);
0309
0310 dev_err(dev, "Probing of sdhci-pltfm failed: %d\n", ret);
0311 return ret;
0312 }
0313
0314 static struct platform_driver sdhci_bcm_kona_driver = {
0315 .driver = {
0316 .name = "sdhci-kona",
0317 .probe_type = PROBE_PREFER_ASYNCHRONOUS,
0318 .pm = &sdhci_pltfm_pmops,
0319 .of_match_table = sdhci_bcm_kona_of_match,
0320 },
0321 .probe = sdhci_bcm_kona_probe,
0322 .remove = sdhci_pltfm_unregister,
0323 };
0324 module_platform_driver(sdhci_bcm_kona_driver);
0325
0326 MODULE_DESCRIPTION("SDHCI driver for Broadcom Kona platform");
0327 MODULE_AUTHOR("Broadcom");
0328 MODULE_LICENSE("GPL v2");