linux/drivers/mmc/host/sdhci-omap.c
<<
>>
Prefs
   1/**
   2 * SDHCI Controller driver for TI's OMAP SoCs
   3 *
   4 * Copyright (C) 2017 Texas Instruments
   5 * Author: Kishon Vijay Abraham I <kishon@ti.com>
   6 *
   7 * This program is free software: you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 of
   9 * the License as published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License
  17 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include <linux/delay.h>
  21#include <linux/mmc/slot-gpio.h>
  22#include <linux/module.h>
  23#include <linux/of.h>
  24#include <linux/of_device.h>
  25#include <linux/platform_device.h>
  26#include <linux/pm_runtime.h>
  27#include <linux/regulator/consumer.h>
  28
  29#include "sdhci-pltfm.h"
  30
  31#define SDHCI_OMAP_CON          0x12c
  32#define CON_DW8                 BIT(5)
  33#define CON_DMA_MASTER          BIT(20)
  34#define CON_INIT                BIT(1)
  35#define CON_OD                  BIT(0)
  36
  37#define SDHCI_OMAP_CMD          0x20c
  38
  39#define SDHCI_OMAP_HCTL         0x228
  40#define HCTL_SDBP               BIT(8)
  41#define HCTL_SDVS_SHIFT         9
  42#define HCTL_SDVS_MASK          (0x7 << HCTL_SDVS_SHIFT)
  43#define HCTL_SDVS_33            (0x7 << HCTL_SDVS_SHIFT)
  44#define HCTL_SDVS_30            (0x6 << HCTL_SDVS_SHIFT)
  45#define HCTL_SDVS_18            (0x5 << HCTL_SDVS_SHIFT)
  46
  47#define SDHCI_OMAP_SYSCTL       0x22c
  48#define SYSCTL_CEN              BIT(2)
  49#define SYSCTL_CLKD_SHIFT       6
  50#define SYSCTL_CLKD_MASK        0x3ff
  51
  52#define SDHCI_OMAP_STAT         0x230
  53
  54#define SDHCI_OMAP_IE           0x234
  55#define INT_CC_EN               BIT(0)
  56
  57#define SDHCI_OMAP_AC12         0x23c
  58#define AC12_V1V8_SIGEN         BIT(19)
  59
  60#define SDHCI_OMAP_CAPA         0x240
  61#define CAPA_VS33               BIT(24)
  62#define CAPA_VS30               BIT(25)
  63#define CAPA_VS18               BIT(26)
  64
  65#define SDHCI_OMAP_TIMEOUT      1               /* 1 msec */
  66
  67#define SYSCTL_CLKD_MAX         0x3FF
  68
  69#define IOV_1V8                 1800000         /* 180000 uV */
  70#define IOV_3V0                 3000000         /* 300000 uV */
  71#define IOV_3V3                 3300000         /* 330000 uV */
  72
  73struct sdhci_omap_data {
  74        u32 offset;
  75};
  76
  77struct sdhci_omap_host {
  78        void __iomem            *base;
  79        struct device           *dev;
  80        struct  regulator       *pbias;
  81        bool                    pbias_enabled;
  82        struct sdhci_host       *host;
  83        u8                      bus_mode;
  84        u8                      power_mode;
  85};
  86
  87static inline u32 sdhci_omap_readl(struct sdhci_omap_host *host,
  88                                   unsigned int offset)
  89{
  90        return readl(host->base + offset);
  91}
  92
  93static inline void sdhci_omap_writel(struct sdhci_omap_host *host,
  94                                     unsigned int offset, u32 data)
  95{
  96        writel(data, host->base + offset);
  97}
  98
  99static int sdhci_omap_set_pbias(struct sdhci_omap_host *omap_host,
 100                                bool power_on, unsigned int iov)
 101{
 102        int ret;
 103        struct device *dev = omap_host->dev;
 104
 105        if (IS_ERR(omap_host->pbias))
 106                return 0;
 107
 108        if (power_on) {
 109                ret = regulator_set_voltage(omap_host->pbias, iov, iov);
 110                if (ret) {
 111                        dev_err(dev, "pbias set voltage failed\n");
 112                        return ret;
 113                }
 114
 115                if (omap_host->pbias_enabled)
 116                        return 0;
 117
 118                ret = regulator_enable(omap_host->pbias);
 119                if (ret) {
 120                        dev_err(dev, "pbias reg enable fail\n");
 121                        return ret;
 122                }
 123
 124                omap_host->pbias_enabled = true;
 125        } else {
 126                if (!omap_host->pbias_enabled)
 127                        return 0;
 128
 129                ret = regulator_disable(omap_host->pbias);
 130                if (ret) {
 131                        dev_err(dev, "pbias reg disable fail\n");
 132                        return ret;
 133                }
 134                omap_host->pbias_enabled = false;
 135        }
 136
 137        return 0;
 138}
 139
 140static int sdhci_omap_enable_iov(struct sdhci_omap_host *omap_host,
 141                                 unsigned int iov)
 142{
 143        int ret;
 144        struct sdhci_host *host = omap_host->host;
 145        struct mmc_host *mmc = host->mmc;
 146
 147        ret = sdhci_omap_set_pbias(omap_host, false, 0);
 148        if (ret)
 149                return ret;
 150
 151        if (!IS_ERR(mmc->supply.vqmmc)) {
 152                ret = regulator_set_voltage(mmc->supply.vqmmc, iov, iov);
 153                if (ret) {
 154                        dev_err(mmc_dev(mmc), "vqmmc set voltage failed\n");
 155                        return ret;
 156                }
 157        }
 158
 159        ret = sdhci_omap_set_pbias(omap_host, true, iov);
 160        if (ret)
 161                return ret;
 162
 163        return 0;
 164}
 165
 166static void sdhci_omap_conf_bus_power(struct sdhci_omap_host *omap_host,
 167                                      unsigned char signal_voltage)
 168{
 169        u32 reg;
 170        ktime_t timeout;
 171
 172        reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL);
 173        reg &= ~HCTL_SDVS_MASK;
 174
 175        if (signal_voltage == MMC_SIGNAL_VOLTAGE_330)
 176                reg |= HCTL_SDVS_33;
 177        else
 178                reg |= HCTL_SDVS_18;
 179
 180        sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, reg);
 181
 182        reg |= HCTL_SDBP;
 183        sdhci_omap_writel(omap_host, SDHCI_OMAP_HCTL, reg);
 184
 185        /* wait 1ms */
 186        timeout = ktime_add_ms(ktime_get(), SDHCI_OMAP_TIMEOUT);
 187        while (!(sdhci_omap_readl(omap_host, SDHCI_OMAP_HCTL) & HCTL_SDBP)) {
 188                if (WARN_ON(ktime_after(ktime_get(), timeout)))
 189                        return;
 190                usleep_range(5, 10);
 191        }
 192}
 193
 194static int sdhci_omap_start_signal_voltage_switch(struct mmc_host *mmc,
 195                                                  struct mmc_ios *ios)
 196{
 197        u32 reg;
 198        int ret;
 199        unsigned int iov;
 200        struct sdhci_host *host = mmc_priv(mmc);
 201        struct sdhci_pltfm_host *pltfm_host;
 202        struct sdhci_omap_host *omap_host;
 203        struct device *dev;
 204
 205        pltfm_host = sdhci_priv(host);
 206        omap_host = sdhci_pltfm_priv(pltfm_host);
 207        dev = omap_host->dev;
 208
 209        if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) {
 210                reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA);
 211                if (!(reg & CAPA_VS33))
 212                        return -EOPNOTSUPP;
 213
 214                sdhci_omap_conf_bus_power(omap_host, ios->signal_voltage);
 215
 216                reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12);
 217                reg &= ~AC12_V1V8_SIGEN;
 218                sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg);
 219
 220                iov = IOV_3V3;
 221        } else if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
 222                reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA);
 223                if (!(reg & CAPA_VS18))
 224                        return -EOPNOTSUPP;
 225
 226                sdhci_omap_conf_bus_power(omap_host, ios->signal_voltage);
 227
 228                reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_AC12);
 229                reg |= AC12_V1V8_SIGEN;
 230                sdhci_omap_writel(omap_host, SDHCI_OMAP_AC12, reg);
 231
 232                iov = IOV_1V8;
 233        } else {
 234                return -EOPNOTSUPP;
 235        }
 236
 237        ret = sdhci_omap_enable_iov(omap_host, iov);
 238        if (ret) {
 239                dev_err(dev, "failed to switch IO voltage to %dmV\n", iov);
 240                return ret;
 241        }
 242
 243        dev_dbg(dev, "IO voltage switched to %dmV\n", iov);
 244        return 0;
 245}
 246
 247static void sdhci_omap_set_bus_mode(struct sdhci_omap_host *omap_host,
 248                                    unsigned int mode)
 249{
 250        u32 reg;
 251
 252        if (omap_host->bus_mode == mode)
 253                return;
 254
 255        reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON);
 256        if (mode == MMC_BUSMODE_OPENDRAIN)
 257                reg |= CON_OD;
 258        else
 259                reg &= ~CON_OD;
 260        sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg);
 261
 262        omap_host->bus_mode = mode;
 263}
 264
 265static void sdhci_omap_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 266{
 267        struct sdhci_host *host = mmc_priv(mmc);
 268        struct sdhci_pltfm_host *pltfm_host;
 269        struct sdhci_omap_host *omap_host;
 270
 271        pltfm_host = sdhci_priv(host);
 272        omap_host = sdhci_pltfm_priv(pltfm_host);
 273
 274        sdhci_omap_set_bus_mode(omap_host, ios->bus_mode);
 275        sdhci_set_ios(mmc, ios);
 276}
 277
 278static u16 sdhci_omap_calc_divisor(struct sdhci_pltfm_host *host,
 279                                   unsigned int clock)
 280{
 281        u16 dsor;
 282
 283        dsor = DIV_ROUND_UP(clk_get_rate(host->clk), clock);
 284        if (dsor > SYSCTL_CLKD_MAX)
 285                dsor = SYSCTL_CLKD_MAX;
 286
 287        return dsor;
 288}
 289
 290static void sdhci_omap_start_clock(struct sdhci_omap_host *omap_host)
 291{
 292        u32 reg;
 293
 294        reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_SYSCTL);
 295        reg |= SYSCTL_CEN;
 296        sdhci_omap_writel(omap_host, SDHCI_OMAP_SYSCTL, reg);
 297}
 298
 299static void sdhci_omap_stop_clock(struct sdhci_omap_host *omap_host)
 300{
 301        u32 reg;
 302
 303        reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_SYSCTL);
 304        reg &= ~SYSCTL_CEN;
 305        sdhci_omap_writel(omap_host, SDHCI_OMAP_SYSCTL, reg);
 306}
 307
 308static void sdhci_omap_set_clock(struct sdhci_host *host, unsigned int clock)
 309{
 310        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 311        struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host);
 312        unsigned long clkdiv;
 313
 314        sdhci_omap_stop_clock(omap_host);
 315
 316        if (!clock)
 317                return;
 318
 319        clkdiv = sdhci_omap_calc_divisor(pltfm_host, clock);
 320        clkdiv = (clkdiv & SYSCTL_CLKD_MASK) << SYSCTL_CLKD_SHIFT;
 321        sdhci_enable_clk(host, clkdiv);
 322
 323        sdhci_omap_start_clock(omap_host);
 324}
 325
 326static void sdhci_omap_set_power(struct sdhci_host *host, unsigned char mode,
 327                          unsigned short vdd)
 328{
 329        struct mmc_host *mmc = host->mmc;
 330
 331        mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, vdd);
 332}
 333
 334static int sdhci_omap_enable_dma(struct sdhci_host *host)
 335{
 336        u32 reg;
 337        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 338        struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host);
 339
 340        reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON);
 341        reg |= CON_DMA_MASTER;
 342        sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg);
 343
 344        return 0;
 345}
 346
 347static unsigned int sdhci_omap_get_min_clock(struct sdhci_host *host)
 348{
 349        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 350
 351        return clk_get_rate(pltfm_host->clk) / SYSCTL_CLKD_MAX;
 352}
 353
 354static void sdhci_omap_set_bus_width(struct sdhci_host *host, int width)
 355{
 356        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 357        struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host);
 358        u32 reg;
 359
 360        reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON);
 361        if (width == MMC_BUS_WIDTH_8)
 362                reg |= CON_DW8;
 363        else
 364                reg &= ~CON_DW8;
 365        sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg);
 366
 367        sdhci_set_bus_width(host, width);
 368}
 369
 370static void sdhci_omap_init_74_clocks(struct sdhci_host *host, u8 power_mode)
 371{
 372        u32 reg;
 373        ktime_t timeout;
 374        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 375        struct sdhci_omap_host *omap_host = sdhci_pltfm_priv(pltfm_host);
 376
 377        if (omap_host->power_mode == power_mode)
 378                return;
 379
 380        if (power_mode != MMC_POWER_ON)
 381                return;
 382
 383        disable_irq(host->irq);
 384
 385        reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON);
 386        reg |= CON_INIT;
 387        sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg);
 388        sdhci_omap_writel(omap_host, SDHCI_OMAP_CMD, 0x0);
 389
 390        /* wait 1ms */
 391        timeout = ktime_add_ms(ktime_get(), SDHCI_OMAP_TIMEOUT);
 392        while (!(sdhci_omap_readl(omap_host, SDHCI_OMAP_STAT) & INT_CC_EN)) {
 393                if (WARN_ON(ktime_after(ktime_get(), timeout)))
 394                        return;
 395                usleep_range(5, 10);
 396        }
 397
 398        reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CON);
 399        reg &= ~CON_INIT;
 400        sdhci_omap_writel(omap_host, SDHCI_OMAP_CON, reg);
 401        sdhci_omap_writel(omap_host, SDHCI_OMAP_STAT, INT_CC_EN);
 402
 403        enable_irq(host->irq);
 404
 405        omap_host->power_mode = power_mode;
 406}
 407
 408static struct sdhci_ops sdhci_omap_ops = {
 409        .set_clock = sdhci_omap_set_clock,
 410        .set_power = sdhci_omap_set_power,
 411        .enable_dma = sdhci_omap_enable_dma,
 412        .get_max_clock = sdhci_pltfm_clk_get_max_clock,
 413        .get_min_clock = sdhci_omap_get_min_clock,
 414        .set_bus_width = sdhci_omap_set_bus_width,
 415        .platform_send_init_74_clocks = sdhci_omap_init_74_clocks,
 416        .reset = sdhci_reset,
 417        .set_uhs_signaling = sdhci_set_uhs_signaling,
 418};
 419
 420static int sdhci_omap_set_capabilities(struct sdhci_omap_host *omap_host)
 421{
 422        u32 reg;
 423        int ret = 0;
 424        struct device *dev = omap_host->dev;
 425        struct regulator *vqmmc;
 426
 427        vqmmc = regulator_get(dev, "vqmmc");
 428        if (IS_ERR(vqmmc)) {
 429                ret = PTR_ERR(vqmmc);
 430                goto reg_put;
 431        }
 432
 433        /* voltage capabilities might be set by boot loader, clear it */
 434        reg = sdhci_omap_readl(omap_host, SDHCI_OMAP_CAPA);
 435        reg &= ~(CAPA_VS18 | CAPA_VS30 | CAPA_VS33);
 436
 437        if (regulator_is_supported_voltage(vqmmc, IOV_3V3, IOV_3V3))
 438                reg |= CAPA_VS33;
 439        if (regulator_is_supported_voltage(vqmmc, IOV_1V8, IOV_1V8))
 440                reg |= CAPA_VS18;
 441
 442        sdhci_omap_writel(omap_host, SDHCI_OMAP_CAPA, reg);
 443
 444reg_put:
 445        regulator_put(vqmmc);
 446
 447        return ret;
 448}
 449
 450static const struct sdhci_pltfm_data sdhci_omap_pdata = {
 451        .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION |
 452                  SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
 453                  SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN |
 454                  SDHCI_QUIRK_NO_HISPD_BIT |
 455                  SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC,
 456        .quirks2 = SDHCI_QUIRK2_NO_1_8_V |
 457                   SDHCI_QUIRK2_ACMD23_BROKEN |
 458                   SDHCI_QUIRK2_RSP_136_HAS_CRC,
 459        .ops = &sdhci_omap_ops,
 460};
 461
 462static const struct sdhci_omap_data dra7_data = {
 463        .offset = 0x200,
 464};
 465
 466static const struct of_device_id omap_sdhci_match[] = {
 467        { .compatible = "ti,dra7-sdhci", .data = &dra7_data },
 468        {},
 469};
 470MODULE_DEVICE_TABLE(of, omap_sdhci_match);
 471
 472static int sdhci_omap_probe(struct platform_device *pdev)
 473{
 474        int ret;
 475        u32 offset;
 476        struct device *dev = &pdev->dev;
 477        struct sdhci_host *host;
 478        struct sdhci_pltfm_host *pltfm_host;
 479        struct sdhci_omap_host *omap_host;
 480        struct mmc_host *mmc;
 481        const struct of_device_id *match;
 482        struct sdhci_omap_data *data;
 483
 484        match = of_match_device(omap_sdhci_match, dev);
 485        if (!match)
 486                return -EINVAL;
 487
 488        data = (struct sdhci_omap_data *)match->data;
 489        if (!data) {
 490                dev_err(dev, "no sdhci omap data\n");
 491                return -EINVAL;
 492        }
 493        offset = data->offset;
 494
 495        host = sdhci_pltfm_init(pdev, &sdhci_omap_pdata,
 496                                sizeof(*omap_host));
 497        if (IS_ERR(host)) {
 498                dev_err(dev, "Failed sdhci_pltfm_init\n");
 499                return PTR_ERR(host);
 500        }
 501
 502        pltfm_host = sdhci_priv(host);
 503        omap_host = sdhci_pltfm_priv(pltfm_host);
 504        omap_host->host = host;
 505        omap_host->base = host->ioaddr;
 506        omap_host->dev = dev;
 507        host->ioaddr += offset;
 508
 509        mmc = host->mmc;
 510        ret = mmc_of_parse(mmc);
 511        if (ret)
 512                goto err_pltfm_free;
 513
 514        pltfm_host->clk = devm_clk_get(dev, "fck");
 515        if (IS_ERR(pltfm_host->clk)) {
 516                ret = PTR_ERR(pltfm_host->clk);
 517                goto err_pltfm_free;
 518        }
 519
 520        ret = clk_set_rate(pltfm_host->clk, mmc->f_max);
 521        if (ret) {
 522                dev_err(dev, "failed to set clock to %d\n", mmc->f_max);
 523                goto err_pltfm_free;
 524        }
 525
 526        omap_host->pbias = devm_regulator_get_optional(dev, "pbias");
 527        if (IS_ERR(omap_host->pbias)) {
 528                ret = PTR_ERR(omap_host->pbias);
 529                if (ret != -ENODEV)
 530                        goto err_pltfm_free;
 531                dev_dbg(dev, "unable to get pbias regulator %d\n", ret);
 532        }
 533        omap_host->pbias_enabled = false;
 534
 535        /*
 536         * omap_device_pm_domain has callbacks to enable the main
 537         * functional clock, interface clock and also configure the
 538         * SYSCONFIG register of omap devices. The callback will be invoked
 539         * as part of pm_runtime_get_sync.
 540         */
 541        pm_runtime_enable(dev);
 542        ret = pm_runtime_get_sync(dev);
 543        if (ret < 0) {
 544                dev_err(dev, "pm_runtime_get_sync failed\n");
 545                pm_runtime_put_noidle(dev);
 546                goto err_rpm_disable;
 547        }
 548
 549        ret = sdhci_omap_set_capabilities(omap_host);
 550        if (ret) {
 551                dev_err(dev, "failed to set system capabilities\n");
 552                goto err_put_sync;
 553        }
 554
 555        host->mmc_host_ops.get_ro = mmc_gpio_get_ro;
 556        host->mmc_host_ops.start_signal_voltage_switch =
 557                                        sdhci_omap_start_signal_voltage_switch;
 558        host->mmc_host_ops.set_ios = sdhci_omap_set_ios;
 559
 560        sdhci_read_caps(host);
 561        host->caps |= SDHCI_CAN_DO_ADMA2;
 562
 563        ret = sdhci_add_host(host);
 564        if (ret)
 565                goto err_put_sync;
 566
 567        return 0;
 568
 569err_put_sync:
 570        pm_runtime_put_sync(dev);
 571
 572err_rpm_disable:
 573        pm_runtime_disable(dev);
 574
 575err_pltfm_free:
 576        sdhci_pltfm_free(pdev);
 577        return ret;
 578}
 579
 580static int sdhci_omap_remove(struct platform_device *pdev)
 581{
 582        struct device *dev = &pdev->dev;
 583        struct sdhci_host *host = platform_get_drvdata(pdev);
 584
 585        sdhci_remove_host(host, true);
 586        pm_runtime_put_sync(dev);
 587        pm_runtime_disable(dev);
 588        sdhci_pltfm_free(pdev);
 589
 590        return 0;
 591}
 592
 593static struct platform_driver sdhci_omap_driver = {
 594        .probe = sdhci_omap_probe,
 595        .remove = sdhci_omap_remove,
 596        .driver = {
 597                   .name = "sdhci-omap",
 598                   .of_match_table = omap_sdhci_match,
 599                  },
 600};
 601
 602module_platform_driver(sdhci_omap_driver);
 603
 604MODULE_DESCRIPTION("SDHCI driver for OMAP SoCs");
 605MODULE_AUTHOR("Texas Instruments Inc.");
 606MODULE_LICENSE("GPL v2");
 607MODULE_ALIAS("platform:sdhci_omap");
 608