linux/drivers/mmc/host/sdhci-pxav3.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2010 Marvell International Ltd.
   3 *              Zhangfei Gao <zhangfei.gao@marvell.com>
   4 *              Kevin Wang <dwang4@marvell.com>
   5 *              Mingwei Wang <mwwang@marvell.com>
   6 *              Philip Rakity <prakity@marvell.com>
   7 *              Mark Brown <markb@marvell.com>
   8 *
   9 * This software is licensed under the terms of the GNU General Public
  10 * License version 2, as published by the Free Software Foundation, and
  11 * may be copied, distributed, and modified under those terms.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 */
  19#include <linux/err.h>
  20#include <linux/init.h>
  21#include <linux/platform_device.h>
  22#include <linux/clk.h>
  23#include <linux/io.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#include <linux/platform_data/pxa_sdhci.h>
  29#include <linux/slab.h>
  30#include <linux/delay.h>
  31#include <linux/module.h>
  32#include <linux/of.h>
  33#include <linux/of_device.h>
  34#include <linux/of_gpio.h>
  35#include <linux/pm.h>
  36#include <linux/pm_runtime.h>
  37
  38#include "sdhci.h"
  39#include "sdhci-pltfm.h"
  40
  41#define PXAV3_RPM_DELAY_MS     50
  42
  43#define SD_CLOCK_BURST_SIZE_SETUP               0x10A
  44#define SDCLK_SEL       0x100
  45#define SDCLK_DELAY_SHIFT       9
  46#define SDCLK_DELAY_MASK        0x1f
  47
  48#define SD_CFG_FIFO_PARAM       0x100
  49#define SDCFG_GEN_PAD_CLK_ON    (1<<6)
  50#define SDCFG_GEN_PAD_CLK_CNT_MASK      0xFF
  51#define SDCFG_GEN_PAD_CLK_CNT_SHIFT     24
  52
  53#define SD_SPI_MODE          0x108
  54#define SD_CE_ATA_1          0x10C
  55
  56#define SD_CE_ATA_2          0x10E
  57#define SDCE_MISC_INT           (1<<2)
  58#define SDCE_MISC_INT_EN        (1<<1)
  59
  60static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask)
  61{
  62        struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
  63        struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
  64
  65        if (mask == SDHCI_RESET_ALL) {
  66                /*
  67                 * tune timing of read data/command when crc error happen
  68                 * no performance impact
  69                 */
  70                if (pdata && 0 != pdata->clk_delay_cycles) {
  71                        u16 tmp;
  72
  73                        tmp = readw(host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
  74                        tmp |= (pdata->clk_delay_cycles & SDCLK_DELAY_MASK)
  75                                << SDCLK_DELAY_SHIFT;
  76                        tmp |= SDCLK_SEL;
  77                        writew(tmp, host->ioaddr + SD_CLOCK_BURST_SIZE_SETUP);
  78                }
  79        }
  80}
  81
  82#define MAX_WAIT_COUNT 5
  83static void pxav3_gen_init_74_clocks(struct sdhci_host *host, u8 power_mode)
  84{
  85        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
  86        struct sdhci_pxa *pxa = pltfm_host->priv;
  87        u16 tmp;
  88        int count;
  89
  90        if (pxa->power_mode == MMC_POWER_UP
  91                        && power_mode == MMC_POWER_ON) {
  92
  93                dev_dbg(mmc_dev(host->mmc),
  94                                "%s: slot->power_mode = %d,"
  95                                "ios->power_mode = %d\n",
  96                                __func__,
  97                                pxa->power_mode,
  98                                power_mode);
  99
 100                /* set we want notice of when 74 clocks are sent */
 101                tmp = readw(host->ioaddr + SD_CE_ATA_2);
 102                tmp |= SDCE_MISC_INT_EN;
 103                writew(tmp, host->ioaddr + SD_CE_ATA_2);
 104
 105                /* start sending the 74 clocks */
 106                tmp = readw(host->ioaddr + SD_CFG_FIFO_PARAM);
 107                tmp |= SDCFG_GEN_PAD_CLK_ON;
 108                writew(tmp, host->ioaddr + SD_CFG_FIFO_PARAM);
 109
 110                /* slowest speed is about 100KHz or 10usec per clock */
 111                udelay(740);
 112                count = 0;
 113
 114                while (count++ < MAX_WAIT_COUNT) {
 115                        if ((readw(host->ioaddr + SD_CE_ATA_2)
 116                                                & SDCE_MISC_INT) == 0)
 117                                break;
 118                        udelay(10);
 119                }
 120
 121                if (count == MAX_WAIT_COUNT)
 122                        dev_warn(mmc_dev(host->mmc), "74 clock interrupt not cleared\n");
 123
 124                /* clear the interrupt bit if posted */
 125                tmp = readw(host->ioaddr + SD_CE_ATA_2);
 126                tmp |= SDCE_MISC_INT;
 127                writew(tmp, host->ioaddr + SD_CE_ATA_2);
 128        }
 129        pxa->power_mode = power_mode;
 130}
 131
 132static int pxav3_set_uhs_signaling(struct sdhci_host *host, unsigned int uhs)
 133{
 134        u16 ctrl_2;
 135
 136        /*
 137         * Set V18_EN -- UHS modes do not work without this.
 138         * does not change signaling voltage
 139         */
 140        ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
 141
 142        /* Select Bus Speed Mode for host */
 143        ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
 144        switch (uhs) {
 145        case MMC_TIMING_UHS_SDR12:
 146                ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
 147                break;
 148        case MMC_TIMING_UHS_SDR25:
 149                ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
 150                break;
 151        case MMC_TIMING_UHS_SDR50:
 152                ctrl_2 |= SDHCI_CTRL_UHS_SDR50 | SDHCI_CTRL_VDD_180;
 153                break;
 154        case MMC_TIMING_UHS_SDR104:
 155                ctrl_2 |= SDHCI_CTRL_UHS_SDR104 | SDHCI_CTRL_VDD_180;
 156                break;
 157        case MMC_TIMING_UHS_DDR50:
 158                ctrl_2 |= SDHCI_CTRL_UHS_DDR50 | SDHCI_CTRL_VDD_180;
 159                break;
 160        }
 161
 162        sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
 163        dev_dbg(mmc_dev(host->mmc),
 164                "%s uhs = %d, ctrl_2 = %04X\n",
 165                __func__, uhs, ctrl_2);
 166
 167        return 0;
 168}
 169
 170static const struct sdhci_ops pxav3_sdhci_ops = {
 171        .platform_reset_exit = pxav3_set_private_registers,
 172        .set_uhs_signaling = pxav3_set_uhs_signaling,
 173        .platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
 174        .get_max_clock = sdhci_pltfm_clk_get_max_clock,
 175};
 176
 177static struct sdhci_pltfm_data sdhci_pxav3_pdata = {
 178        .quirks = SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK
 179                | SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC
 180                | SDHCI_QUIRK_32BIT_ADMA_SIZE
 181                | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
 182        .ops = &pxav3_sdhci_ops,
 183};
 184
 185#ifdef CONFIG_OF
 186static const struct of_device_id sdhci_pxav3_of_match[] = {
 187        {
 188                .compatible = "mrvl,pxav3-mmc",
 189        },
 190        {},
 191};
 192MODULE_DEVICE_TABLE(of, sdhci_pxav3_of_match);
 193
 194static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
 195{
 196        struct sdhci_pxa_platdata *pdata;
 197        struct device_node *np = dev->of_node;
 198        u32 clk_delay_cycles;
 199
 200        pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
 201        if (!pdata)
 202                return NULL;
 203
 204        of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles);
 205        if (clk_delay_cycles > 0)
 206                pdata->clk_delay_cycles = clk_delay_cycles;
 207
 208        return pdata;
 209}
 210#else
 211static inline struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
 212{
 213        return NULL;
 214}
 215#endif
 216
 217static int sdhci_pxav3_probe(struct platform_device *pdev)
 218{
 219        struct sdhci_pltfm_host *pltfm_host;
 220        struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
 221        struct device *dev = &pdev->dev;
 222        struct sdhci_host *host = NULL;
 223        struct sdhci_pxa *pxa = NULL;
 224        const struct of_device_id *match;
 225
 226        int ret;
 227        struct clk *clk;
 228
 229        pxa = kzalloc(sizeof(struct sdhci_pxa), GFP_KERNEL);
 230        if (!pxa)
 231                return -ENOMEM;
 232
 233        host = sdhci_pltfm_init(pdev, &sdhci_pxav3_pdata, 0);
 234        if (IS_ERR(host)) {
 235                kfree(pxa);
 236                return PTR_ERR(host);
 237        }
 238        pltfm_host = sdhci_priv(host);
 239        pltfm_host->priv = pxa;
 240
 241        clk = clk_get(dev, NULL);
 242        if (IS_ERR(clk)) {
 243                dev_err(dev, "failed to get io clock\n");
 244                ret = PTR_ERR(clk);
 245                goto err_clk_get;
 246        }
 247        pltfm_host->clk = clk;
 248        clk_prepare_enable(clk);
 249
 250        /* enable 1/8V DDR capable */
 251        host->mmc->caps |= MMC_CAP_1_8V_DDR;
 252
 253        match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev);
 254        if (match) {
 255                ret = mmc_of_parse(host->mmc);
 256                if (ret)
 257                        goto err_of_parse;
 258                sdhci_get_of_property(pdev);
 259                pdata = pxav3_get_mmc_pdata(dev);
 260        } else if (pdata) {
 261                /* on-chip device */
 262                if (pdata->flags & PXA_FLAG_CARD_PERMANENT)
 263                        host->mmc->caps |= MMC_CAP_NONREMOVABLE;
 264
 265                /* If slot design supports 8 bit data, indicate this to MMC. */
 266                if (pdata->flags & PXA_FLAG_SD_8_BIT_CAPABLE_SLOT)
 267                        host->mmc->caps |= MMC_CAP_8_BIT_DATA;
 268
 269                if (pdata->quirks)
 270                        host->quirks |= pdata->quirks;
 271                if (pdata->quirks2)
 272                        host->quirks2 |= pdata->quirks2;
 273                if (pdata->host_caps)
 274                        host->mmc->caps |= pdata->host_caps;
 275                if (pdata->host_caps2)
 276                        host->mmc->caps2 |= pdata->host_caps2;
 277                if (pdata->pm_caps)
 278                        host->mmc->pm_caps |= pdata->pm_caps;
 279
 280                if (gpio_is_valid(pdata->ext_cd_gpio)) {
 281                        ret = mmc_gpio_request_cd(host->mmc, pdata->ext_cd_gpio);
 282                        if (ret) {
 283                                dev_err(mmc_dev(host->mmc),
 284                                        "failed to allocate card detect gpio\n");
 285                                goto err_cd_req;
 286                        }
 287                }
 288        }
 289
 290        pm_runtime_enable(&pdev->dev);
 291        pm_runtime_get_sync(&pdev->dev);
 292        pm_runtime_set_autosuspend_delay(&pdev->dev, PXAV3_RPM_DELAY_MS);
 293        pm_runtime_use_autosuspend(&pdev->dev);
 294        pm_suspend_ignore_children(&pdev->dev, 1);
 295
 296        ret = sdhci_add_host(host);
 297        if (ret) {
 298                dev_err(&pdev->dev, "failed to add host\n");
 299                goto err_add_host;
 300        }
 301
 302        platform_set_drvdata(pdev, host);
 303
 304        if (host->mmc->pm_caps & MMC_PM_KEEP_POWER) {
 305                device_init_wakeup(&pdev->dev, 1);
 306                host->mmc->pm_flags |= MMC_PM_WAKE_SDIO_IRQ;
 307        } else {
 308                device_init_wakeup(&pdev->dev, 0);
 309        }
 310
 311        pm_runtime_put_autosuspend(&pdev->dev);
 312
 313        return 0;
 314
 315err_of_parse:
 316err_cd_req:
 317err_add_host:
 318        pm_runtime_put_sync(&pdev->dev);
 319        pm_runtime_disable(&pdev->dev);
 320        clk_disable_unprepare(clk);
 321        clk_put(clk);
 322err_clk_get:
 323        sdhci_pltfm_free(pdev);
 324        kfree(pxa);
 325        return ret;
 326}
 327
 328static int sdhci_pxav3_remove(struct platform_device *pdev)
 329{
 330        struct sdhci_host *host = platform_get_drvdata(pdev);
 331        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 332        struct sdhci_pxa *pxa = pltfm_host->priv;
 333
 334        pm_runtime_get_sync(&pdev->dev);
 335        sdhci_remove_host(host, 1);
 336        pm_runtime_disable(&pdev->dev);
 337
 338        clk_disable_unprepare(pltfm_host->clk);
 339        clk_put(pltfm_host->clk);
 340
 341        sdhci_pltfm_free(pdev);
 342        kfree(pxa);
 343
 344        return 0;
 345}
 346
 347#ifdef CONFIG_PM_SLEEP
 348static int sdhci_pxav3_suspend(struct device *dev)
 349{
 350        int ret;
 351        struct sdhci_host *host = dev_get_drvdata(dev);
 352
 353        pm_runtime_get_sync(dev);
 354        ret = sdhci_suspend_host(host);
 355        pm_runtime_mark_last_busy(dev);
 356        pm_runtime_put_autosuspend(dev);
 357
 358        return ret;
 359}
 360
 361static int sdhci_pxav3_resume(struct device *dev)
 362{
 363        int ret;
 364        struct sdhci_host *host = dev_get_drvdata(dev);
 365
 366        pm_runtime_get_sync(dev);
 367        ret = sdhci_resume_host(host);
 368        pm_runtime_mark_last_busy(dev);
 369        pm_runtime_put_autosuspend(dev);
 370
 371        return ret;
 372}
 373#endif
 374
 375#ifdef CONFIG_PM_RUNTIME
 376static int sdhci_pxav3_runtime_suspend(struct device *dev)
 377{
 378        struct sdhci_host *host = dev_get_drvdata(dev);
 379        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 380        unsigned long flags;
 381
 382        if (pltfm_host->clk) {
 383                spin_lock_irqsave(&host->lock, flags);
 384                host->runtime_suspended = true;
 385                spin_unlock_irqrestore(&host->lock, flags);
 386
 387                clk_disable_unprepare(pltfm_host->clk);
 388        }
 389
 390        return 0;
 391}
 392
 393static int sdhci_pxav3_runtime_resume(struct device *dev)
 394{
 395        struct sdhci_host *host = dev_get_drvdata(dev);
 396        struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
 397        unsigned long flags;
 398
 399        if (pltfm_host->clk) {
 400                clk_prepare_enable(pltfm_host->clk);
 401
 402                spin_lock_irqsave(&host->lock, flags);
 403                host->runtime_suspended = false;
 404                spin_unlock_irqrestore(&host->lock, flags);
 405        }
 406
 407        return 0;
 408}
 409#endif
 410
 411#ifdef CONFIG_PM
 412static const struct dev_pm_ops sdhci_pxav3_pmops = {
 413        SET_SYSTEM_SLEEP_PM_OPS(sdhci_pxav3_suspend, sdhci_pxav3_resume)
 414        SET_RUNTIME_PM_OPS(sdhci_pxav3_runtime_suspend,
 415                sdhci_pxav3_runtime_resume, NULL)
 416};
 417
 418#define SDHCI_PXAV3_PMOPS (&sdhci_pxav3_pmops)
 419
 420#else
 421#define SDHCI_PXAV3_PMOPS NULL
 422#endif
 423
 424static struct platform_driver sdhci_pxav3_driver = {
 425        .driver         = {
 426                .name   = "sdhci-pxav3",
 427#ifdef CONFIG_OF
 428                .of_match_table = sdhci_pxav3_of_match,
 429#endif
 430                .owner  = THIS_MODULE,
 431                .pm     = SDHCI_PXAV3_PMOPS,
 432        },
 433        .probe          = sdhci_pxav3_probe,
 434        .remove         = sdhci_pxav3_remove,
 435};
 436
 437module_platform_driver(sdhci_pxav3_driver);
 438
 439MODULE_DESCRIPTION("SDHCI driver for pxav3");
 440MODULE_AUTHOR("Marvell International Ltd.");
 441MODULE_LICENSE("GPL v2");
 442
 443