11c6a0718SPierre Ossman /* 270f10482SPierre Ossman * linux/drivers/mmc/host/pxa.c - PXA MMCI driver 31c6a0718SPierre Ossman * 41c6a0718SPierre Ossman * Copyright (C) 2003 Russell King, All Rights Reserved. 51c6a0718SPierre Ossman * 61c6a0718SPierre Ossman * This program is free software; you can redistribute it and/or modify 71c6a0718SPierre Ossman * it under the terms of the GNU General Public License version 2 as 81c6a0718SPierre Ossman * published by the Free Software Foundation. 91c6a0718SPierre Ossman * 101c6a0718SPierre Ossman * This hardware is really sick: 111c6a0718SPierre Ossman * - No way to clear interrupts. 121c6a0718SPierre Ossman * - Have to turn off the clock whenever we touch the device. 131c6a0718SPierre Ossman * - Doesn't tell you how many data blocks were transferred. 141c6a0718SPierre Ossman * Yuck! 151c6a0718SPierre Ossman * 161c6a0718SPierre Ossman * 1 and 3 byte data transfers not supported 171c6a0718SPierre Ossman * max block length up to 1023 181c6a0718SPierre Ossman */ 191c6a0718SPierre Ossman #include <linux/module.h> 201c6a0718SPierre Ossman #include <linux/init.h> 211c6a0718SPierre Ossman #include <linux/ioport.h> 221c6a0718SPierre Ossman #include <linux/platform_device.h> 231c6a0718SPierre Ossman #include <linux/delay.h> 241c6a0718SPierre Ossman #include <linux/interrupt.h> 256464b714SDaniel Mack #include <linux/dmaengine.h> 261c6a0718SPierre Ossman #include <linux/dma-mapping.h> 27ebebd9b0SRussell King #include <linux/clk.h> 28ebebd9b0SRussell King #include <linux/err.h> 291c6a0718SPierre Ossman #include <linux/mmc/host.h> 30fd546ee6SRobert Jarzmik #include <linux/mmc/slot-gpio.h> 3105678a96SRussell King #include <linux/io.h> 328385f9cbSDaniel Ribeiro #include <linux/regulator/consumer.h> 33b405db6cSRobert Jarzmik #include <linux/gpio.h> 345a0e3ad6STejun Heo #include <linux/gfp.h> 35e6027b46SDaniel Mack #include <linux/of.h> 36e6027b46SDaniel Mack #include <linux/of_gpio.h> 37e6027b46SDaniel Mack #include <linux/of_device.h> 381c6a0718SPierre Ossman 391c6a0718SPierre Ossman #include <asm/sizes.h> 401c6a0718SPierre Ossman 4105678a96SRussell King #include <mach/hardware.h> 42293b2da1SArnd Bergmann #include <linux/platform_data/mmc-pxamci.h> 431c6a0718SPierre Ossman 441c6a0718SPierre Ossman #include "pxamci.h" 451c6a0718SPierre Ossman 461c6a0718SPierre Ossman #define DRIVER_NAME "pxa2xx-mci" 471c6a0718SPierre Ossman 481c6a0718SPierre Ossman #define NR_SG 1 49d8cb70d1SRussell King #define CLKRT_OFF (~0) 501c6a0718SPierre Ossman 51fa3f9938SHaojian Zhuang #define mmc_has_26MHz() (cpu_is_pxa300() || cpu_is_pxa310() \ 52fa3f9938SHaojian Zhuang || cpu_is_pxa935()) 53fa3f9938SHaojian Zhuang 541c6a0718SPierre Ossman struct pxamci_host { 551c6a0718SPierre Ossman struct mmc_host *mmc; 561c6a0718SPierre Ossman spinlock_t lock; 571c6a0718SPierre Ossman struct resource *res; 581c6a0718SPierre Ossman void __iomem *base; 59ebebd9b0SRussell King struct clk *clk; 60ebebd9b0SRussell King unsigned long clkrate; 611c6a0718SPierre Ossman unsigned int clkrt; 621c6a0718SPierre Ossman unsigned int cmdat; 631c6a0718SPierre Ossman unsigned int imask; 641c6a0718SPierre Ossman unsigned int power_mode; 6538a8dda9SDaniel Mack unsigned long detect_delay_ms; 661c6a0718SPierre Ossman struct pxamci_platform_data *pdata; 671c6a0718SPierre Ossman 681c6a0718SPierre Ossman struct mmc_request *mrq; 691c6a0718SPierre Ossman struct mmc_command *cmd; 701c6a0718SPierre Ossman struct mmc_data *data; 711c6a0718SPierre Ossman 726464b714SDaniel Mack struct dma_chan *dma_chan_rx; 736464b714SDaniel Mack struct dma_chan *dma_chan_tx; 746464b714SDaniel Mack dma_cookie_t dma_cookie; 751c6a0718SPierre Ossman unsigned int dma_len; 761c6a0718SPierre Ossman unsigned int dma_dir; 771c6a0718SPierre Ossman }; 781c6a0718SPierre Ossman 7961951fd6SDaniel Mack static int pxamci_init_ocr(struct pxamci_host *host) 808385f9cbSDaniel Ribeiro { 8161951fd6SDaniel Mack struct mmc_host *mmc = host->mmc; 8261951fd6SDaniel Mack int ret; 838385f9cbSDaniel Ribeiro 8461951fd6SDaniel Mack ret = mmc_regulator_get_supply(mmc); 8561951fd6SDaniel Mack if (ret < 0) 8661951fd6SDaniel Mack return ret; 8761951fd6SDaniel Mack 8861951fd6SDaniel Mack if (IS_ERR(mmc->supply.vmmc)) { 898385f9cbSDaniel Ribeiro /* fall-back to platform data */ 9061951fd6SDaniel Mack mmc->ocr_avail = host->pdata ? 918385f9cbSDaniel Ribeiro host->pdata->ocr_mask : 928385f9cbSDaniel Ribeiro MMC_VDD_32_33 | MMC_VDD_33_34; 938385f9cbSDaniel Ribeiro } 9461951fd6SDaniel Mack 9561951fd6SDaniel Mack return 0; 968385f9cbSDaniel Ribeiro } 978385f9cbSDaniel Ribeiro 9899fc5131SLinus Walleij static inline int pxamci_set_power(struct pxamci_host *host, 9999fc5131SLinus Walleij unsigned char power_mode, 10099fc5131SLinus Walleij unsigned int vdd) 1018385f9cbSDaniel Ribeiro { 10261951fd6SDaniel Mack struct mmc_host *mmc = host->mmc; 10361951fd6SDaniel Mack struct regulator *supply = mmc->supply.vmmc; 104b405db6cSRobert Jarzmik int on; 105b405db6cSRobert Jarzmik 10661951fd6SDaniel Mack if (!IS_ERR(supply)) 10761951fd6SDaniel Mack return mmc_regulator_set_ocr(mmc, supply, vdd); 10899fc5131SLinus Walleij 10961951fd6SDaniel Mack if (host->pdata && 110b405db6cSRobert Jarzmik gpio_is_valid(host->pdata->gpio_power)) { 111b405db6cSRobert Jarzmik on = ((1 << vdd) & host->pdata->ocr_mask); 112b405db6cSRobert Jarzmik gpio_set_value(host->pdata->gpio_power, 113b405db6cSRobert Jarzmik !!on ^ host->pdata->gpio_power_invert); 114b405db6cSRobert Jarzmik } 11561951fd6SDaniel Mack 11661951fd6SDaniel Mack if (host->pdata && host->pdata->setpower) 117a829abf8SArnd Bergmann return host->pdata->setpower(mmc_dev(host->mmc), vdd); 11899fc5131SLinus Walleij 11999fc5131SLinus Walleij return 0; 1208385f9cbSDaniel Ribeiro } 1218385f9cbSDaniel Ribeiro 1221c6a0718SPierre Ossman static void pxamci_stop_clock(struct pxamci_host *host) 1231c6a0718SPierre Ossman { 1241c6a0718SPierre Ossman if (readl(host->base + MMC_STAT) & STAT_CLK_EN) { 1251c6a0718SPierre Ossman unsigned long timeout = 10000; 1261c6a0718SPierre Ossman unsigned int v; 1271c6a0718SPierre Ossman 1281c6a0718SPierre Ossman writel(STOP_CLOCK, host->base + MMC_STRPCL); 1291c6a0718SPierre Ossman 1301c6a0718SPierre Ossman do { 1311c6a0718SPierre Ossman v = readl(host->base + MMC_STAT); 1321c6a0718SPierre Ossman if (!(v & STAT_CLK_EN)) 1331c6a0718SPierre Ossman break; 1341c6a0718SPierre Ossman udelay(1); 1351c6a0718SPierre Ossman } while (timeout--); 1361c6a0718SPierre Ossman 1371c6a0718SPierre Ossman if (v & STAT_CLK_EN) 1381c6a0718SPierre Ossman dev_err(mmc_dev(host->mmc), "unable to stop clock\n"); 1391c6a0718SPierre Ossman } 1401c6a0718SPierre Ossman } 1411c6a0718SPierre Ossman 1421c6a0718SPierre Ossman static void pxamci_enable_irq(struct pxamci_host *host, unsigned int mask) 1431c6a0718SPierre Ossman { 1441c6a0718SPierre Ossman unsigned long flags; 1451c6a0718SPierre Ossman 1461c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 1471c6a0718SPierre Ossman host->imask &= ~mask; 1481c6a0718SPierre Ossman writel(host->imask, host->base + MMC_I_MASK); 1491c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1501c6a0718SPierre Ossman } 1511c6a0718SPierre Ossman 1521c6a0718SPierre Ossman static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask) 1531c6a0718SPierre Ossman { 1541c6a0718SPierre Ossman unsigned long flags; 1551c6a0718SPierre Ossman 1561c6a0718SPierre Ossman spin_lock_irqsave(&host->lock, flags); 1571c6a0718SPierre Ossman host->imask |= mask; 1581c6a0718SPierre Ossman writel(host->imask, host->base + MMC_I_MASK); 1591c6a0718SPierre Ossman spin_unlock_irqrestore(&host->lock, flags); 1601c6a0718SPierre Ossman } 1611c6a0718SPierre Ossman 1626464b714SDaniel Mack static void pxamci_dma_irq(void *param); 1636464b714SDaniel Mack 1641c6a0718SPierre Ossman static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data) 1651c6a0718SPierre Ossman { 1666464b714SDaniel Mack struct dma_async_tx_descriptor *tx; 1676464b714SDaniel Mack enum dma_data_direction direction; 1686464b714SDaniel Mack struct dma_slave_config config; 1696464b714SDaniel Mack struct dma_chan *chan; 1701c6a0718SPierre Ossman unsigned int nob = data->blocks; 1711c6a0718SPierre Ossman unsigned long long clks; 1721c6a0718SPierre Ossman unsigned int timeout; 1736464b714SDaniel Mack int ret; 1741c6a0718SPierre Ossman 1751c6a0718SPierre Ossman host->data = data; 1761c6a0718SPierre Ossman 1771c6a0718SPierre Ossman writel(nob, host->base + MMC_NOB); 1781c6a0718SPierre Ossman writel(data->blksz, host->base + MMC_BLKLEN); 1791c6a0718SPierre Ossman 180ebebd9b0SRussell King clks = (unsigned long long)data->timeout_ns * host->clkrate; 1811c6a0718SPierre Ossman do_div(clks, 1000000000UL); 1821c6a0718SPierre Ossman timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt); 1831c6a0718SPierre Ossman writel((timeout + 255) / 256, host->base + MMC_RDTO); 1841c6a0718SPierre Ossman 1856464b714SDaniel Mack memset(&config, 0, sizeof(config)); 1866464b714SDaniel Mack config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 1876464b714SDaniel Mack config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE; 1886464b714SDaniel Mack config.src_addr = host->res->start + MMC_RXFIFO; 1896464b714SDaniel Mack config.dst_addr = host->res->start + MMC_TXFIFO; 1906464b714SDaniel Mack config.src_maxburst = 32; 1916464b714SDaniel Mack config.dst_maxburst = 32; 1926464b714SDaniel Mack 1931c6a0718SPierre Ossman if (data->flags & MMC_DATA_READ) { 1941c6a0718SPierre Ossman host->dma_dir = DMA_FROM_DEVICE; 1956464b714SDaniel Mack direction = DMA_DEV_TO_MEM; 1966464b714SDaniel Mack chan = host->dma_chan_rx; 1971c6a0718SPierre Ossman } else { 1981c6a0718SPierre Ossman host->dma_dir = DMA_TO_DEVICE; 1996464b714SDaniel Mack direction = DMA_MEM_TO_DEV; 2006464b714SDaniel Mack chan = host->dma_chan_tx; 2011c6a0718SPierre Ossman } 2021c6a0718SPierre Ossman 2036464b714SDaniel Mack config.direction = direction; 2041c6a0718SPierre Ossman 2056464b714SDaniel Mack ret = dmaengine_slave_config(chan, &config); 2066464b714SDaniel Mack if (ret < 0) { 2076464b714SDaniel Mack dev_err(mmc_dev(host->mmc), "dma slave config failed\n"); 2086464b714SDaniel Mack return; 2096464b714SDaniel Mack } 2106464b714SDaniel Mack 2116464b714SDaniel Mack host->dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len, 2121c6a0718SPierre Ossman host->dma_dir); 2131c6a0718SPierre Ossman 2146464b714SDaniel Mack tx = dmaengine_prep_slave_sg(chan, data->sg, host->dma_len, direction, 2156464b714SDaniel Mack DMA_PREP_INTERRUPT); 2166464b714SDaniel Mack if (!tx) { 2176464b714SDaniel Mack dev_err(mmc_dev(host->mmc), "prep_slave_sg() failed\n"); 2186464b714SDaniel Mack return; 2191c6a0718SPierre Ossman } 2201c6a0718SPierre Ossman 2216464b714SDaniel Mack if (!(data->flags & MMC_DATA_READ)) { 2226464b714SDaniel Mack tx->callback = pxamci_dma_irq; 2236464b714SDaniel Mack tx->callback_param = host; 2246464b714SDaniel Mack } 2256464b714SDaniel Mack 2266464b714SDaniel Mack host->dma_cookie = dmaengine_submit(tx); 227b6018958SCliff Brake 228b6018958SCliff Brake /* 229b6018958SCliff Brake * workaround for erratum #91: 230b6018958SCliff Brake * only start DMA now if we are doing a read, 231b6018958SCliff Brake * otherwise we wait until CMD/RESP has finished 232b6018958SCliff Brake * before starting DMA. 233b6018958SCliff Brake */ 234b6018958SCliff Brake if (!cpu_is_pxa27x() || data->flags & MMC_DATA_READ) 2356464b714SDaniel Mack dma_async_issue_pending(chan); 2361c6a0718SPierre Ossman } 2371c6a0718SPierre Ossman 2381c6a0718SPierre Ossman static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat) 2391c6a0718SPierre Ossman { 2401c6a0718SPierre Ossman WARN_ON(host->cmd != NULL); 2411c6a0718SPierre Ossman host->cmd = cmd; 2421c6a0718SPierre Ossman 2431c6a0718SPierre Ossman if (cmd->flags & MMC_RSP_BUSY) 2441c6a0718SPierre Ossman cmdat |= CMDAT_BUSY; 2451c6a0718SPierre Ossman 2461c6a0718SPierre Ossman #define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE)) 2471c6a0718SPierre Ossman switch (RSP_TYPE(mmc_resp_type(cmd))) { 2481c6a0718SPierre Ossman case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6, r7 */ 2491c6a0718SPierre Ossman cmdat |= CMDAT_RESP_SHORT; 2501c6a0718SPierre Ossman break; 2511c6a0718SPierre Ossman case RSP_TYPE(MMC_RSP_R3): 2521c6a0718SPierre Ossman cmdat |= CMDAT_RESP_R3; 2531c6a0718SPierre Ossman break; 2541c6a0718SPierre Ossman case RSP_TYPE(MMC_RSP_R2): 2551c6a0718SPierre Ossman cmdat |= CMDAT_RESP_R2; 2561c6a0718SPierre Ossman break; 2571c6a0718SPierre Ossman default: 2581c6a0718SPierre Ossman break; 2591c6a0718SPierre Ossman } 2601c6a0718SPierre Ossman 2611c6a0718SPierre Ossman writel(cmd->opcode, host->base + MMC_CMD); 2621c6a0718SPierre Ossman writel(cmd->arg >> 16, host->base + MMC_ARGH); 2631c6a0718SPierre Ossman writel(cmd->arg & 0xffff, host->base + MMC_ARGL); 2641c6a0718SPierre Ossman writel(cmdat, host->base + MMC_CMDAT); 2651c6a0718SPierre Ossman writel(host->clkrt, host->base + MMC_CLKRT); 2661c6a0718SPierre Ossman 2671c6a0718SPierre Ossman writel(START_CLOCK, host->base + MMC_STRPCL); 2681c6a0718SPierre Ossman 2691c6a0718SPierre Ossman pxamci_enable_irq(host, END_CMD_RES); 2701c6a0718SPierre Ossman } 2711c6a0718SPierre Ossman 2721c6a0718SPierre Ossman static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq) 2731c6a0718SPierre Ossman { 2741c6a0718SPierre Ossman host->mrq = NULL; 2751c6a0718SPierre Ossman host->cmd = NULL; 2761c6a0718SPierre Ossman host->data = NULL; 2771c6a0718SPierre Ossman mmc_request_done(host->mmc, mrq); 2781c6a0718SPierre Ossman } 2791c6a0718SPierre Ossman 2801c6a0718SPierre Ossman static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat) 2811c6a0718SPierre Ossman { 2821c6a0718SPierre Ossman struct mmc_command *cmd = host->cmd; 2831c6a0718SPierre Ossman int i; 2841c6a0718SPierre Ossman u32 v; 2851c6a0718SPierre Ossman 2861c6a0718SPierre Ossman if (!cmd) 2871c6a0718SPierre Ossman return 0; 2881c6a0718SPierre Ossman 2891c6a0718SPierre Ossman host->cmd = NULL; 2901c6a0718SPierre Ossman 2911c6a0718SPierre Ossman /* 2921c6a0718SPierre Ossman * Did I mention this is Sick. We always need to 2931c6a0718SPierre Ossman * discard the upper 8 bits of the first 16-bit word. 2941c6a0718SPierre Ossman */ 2951c6a0718SPierre Ossman v = readl(host->base + MMC_RES) & 0xffff; 2961c6a0718SPierre Ossman for (i = 0; i < 4; i++) { 2971c6a0718SPierre Ossman u32 w1 = readl(host->base + MMC_RES) & 0xffff; 2981c6a0718SPierre Ossman u32 w2 = readl(host->base + MMC_RES) & 0xffff; 2991c6a0718SPierre Ossman cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8; 3001c6a0718SPierre Ossman v = w2; 3011c6a0718SPierre Ossman } 3021c6a0718SPierre Ossman 3031c6a0718SPierre Ossman if (stat & STAT_TIME_OUT_RESPONSE) { 30417b0429dSPierre Ossman cmd->error = -ETIMEDOUT; 3051c6a0718SPierre Ossman } else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) { 3061c6a0718SPierre Ossman /* 3071c6a0718SPierre Ossman * workaround for erratum #42: 3081c6a0718SPierre Ossman * Intel PXA27x Family Processor Specification Update Rev 001 30990e07d9fSNicolas Pitre * A bogus CRC error can appear if the msb of a 136 bit 31090e07d9fSNicolas Pitre * response is a one. 3111c6a0718SPierre Ossman */ 312e10a854cSCliff Brake if (cpu_is_pxa27x() && 313e10a854cSCliff Brake (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000)) 3141c6a0718SPierre Ossman pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode); 315e10a854cSCliff Brake else 31617b0429dSPierre Ossman cmd->error = -EILSEQ; 3171c6a0718SPierre Ossman } 3181c6a0718SPierre Ossman 3191c6a0718SPierre Ossman pxamci_disable_irq(host, END_CMD_RES); 32017b0429dSPierre Ossman if (host->data && !cmd->error) { 3211c6a0718SPierre Ossman pxamci_enable_irq(host, DATA_TRAN_DONE); 322b6018958SCliff Brake /* 323b6018958SCliff Brake * workaround for erratum #91, if doing write 324b6018958SCliff Brake * enable DMA late 325b6018958SCliff Brake */ 326b6018958SCliff Brake if (cpu_is_pxa27x() && host->data->flags & MMC_DATA_WRITE) 3276464b714SDaniel Mack dma_async_issue_pending(host->dma_chan_tx); 3281c6a0718SPierre Ossman } else { 3291c6a0718SPierre Ossman pxamci_finish_request(host, host->mrq); 3301c6a0718SPierre Ossman } 3311c6a0718SPierre Ossman 3321c6a0718SPierre Ossman return 1; 3331c6a0718SPierre Ossman } 3341c6a0718SPierre Ossman 3351c6a0718SPierre Ossman static int pxamci_data_done(struct pxamci_host *host, unsigned int stat) 3361c6a0718SPierre Ossman { 3371c6a0718SPierre Ossman struct mmc_data *data = host->data; 3386464b714SDaniel Mack struct dma_chan *chan; 3391c6a0718SPierre Ossman 3401c6a0718SPierre Ossman if (!data) 3411c6a0718SPierre Ossman return 0; 3421c6a0718SPierre Ossman 3436464b714SDaniel Mack if (data->flags & MMC_DATA_READ) 3446464b714SDaniel Mack chan = host->dma_chan_rx; 3456464b714SDaniel Mack else 3466464b714SDaniel Mack chan = host->dma_chan_tx; 3476464b714SDaniel Mack dma_unmap_sg(chan->device->dev, 3486464b714SDaniel Mack data->sg, data->sg_len, host->dma_dir); 3491c6a0718SPierre Ossman 3501c6a0718SPierre Ossman if (stat & STAT_READ_TIME_OUT) 35117b0429dSPierre Ossman data->error = -ETIMEDOUT; 3521c6a0718SPierre Ossman else if (stat & (STAT_CRC_READ_ERROR|STAT_CRC_WRITE_ERROR)) 35317b0429dSPierre Ossman data->error = -EILSEQ; 3541c6a0718SPierre Ossman 3551c6a0718SPierre Ossman /* 3561c6a0718SPierre Ossman * There appears to be a hardware design bug here. There seems to 3571c6a0718SPierre Ossman * be no way to find out how much data was transferred to the card. 3581c6a0718SPierre Ossman * This means that if there was an error on any block, we mark all 3591c6a0718SPierre Ossman * data blocks as being in error. 3601c6a0718SPierre Ossman */ 36117b0429dSPierre Ossman if (!data->error) 3621c6a0718SPierre Ossman data->bytes_xfered = data->blocks * data->blksz; 3631c6a0718SPierre Ossman else 3641c6a0718SPierre Ossman data->bytes_xfered = 0; 3651c6a0718SPierre Ossman 3661c6a0718SPierre Ossman pxamci_disable_irq(host, DATA_TRAN_DONE); 3671c6a0718SPierre Ossman 3681c6a0718SPierre Ossman host->data = NULL; 3691c6a0718SPierre Ossman if (host->mrq->stop) { 3701c6a0718SPierre Ossman pxamci_stop_clock(host); 371df456f47SBridge Wu pxamci_start_cmd(host, host->mrq->stop, host->cmdat); 3721c6a0718SPierre Ossman } else { 3731c6a0718SPierre Ossman pxamci_finish_request(host, host->mrq); 3741c6a0718SPierre Ossman } 3751c6a0718SPierre Ossman 3761c6a0718SPierre Ossman return 1; 3771c6a0718SPierre Ossman } 3781c6a0718SPierre Ossman 3791c6a0718SPierre Ossman static irqreturn_t pxamci_irq(int irq, void *devid) 3801c6a0718SPierre Ossman { 3811c6a0718SPierre Ossman struct pxamci_host *host = devid; 3821c6a0718SPierre Ossman unsigned int ireg; 3831c6a0718SPierre Ossman int handled = 0; 3841c6a0718SPierre Ossman 38581ab570fSBridge Wu ireg = readl(host->base + MMC_I_REG) & ~readl(host->base + MMC_I_MASK); 3861c6a0718SPierre Ossman 3871c6a0718SPierre Ossman if (ireg) { 3881c6a0718SPierre Ossman unsigned stat = readl(host->base + MMC_STAT); 3891c6a0718SPierre Ossman 3901c6a0718SPierre Ossman pr_debug("PXAMCI: irq %08x stat %08x\n", ireg, stat); 3911c6a0718SPierre Ossman 3921c6a0718SPierre Ossman if (ireg & END_CMD_RES) 3931c6a0718SPierre Ossman handled |= pxamci_cmd_done(host, stat); 3941c6a0718SPierre Ossman if (ireg & DATA_TRAN_DONE) 3951c6a0718SPierre Ossman handled |= pxamci_data_done(host, stat); 3965d3ad4e8SBridge Wu if (ireg & SDIO_INT) { 3975d3ad4e8SBridge Wu mmc_signal_sdio_irq(host->mmc); 3985d3ad4e8SBridge Wu handled = 1; 3995d3ad4e8SBridge Wu } 4001c6a0718SPierre Ossman } 4011c6a0718SPierre Ossman 4021c6a0718SPierre Ossman return IRQ_RETVAL(handled); 4031c6a0718SPierre Ossman } 4041c6a0718SPierre Ossman 4051c6a0718SPierre Ossman static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq) 4061c6a0718SPierre Ossman { 4071c6a0718SPierre Ossman struct pxamci_host *host = mmc_priv(mmc); 4081c6a0718SPierre Ossman unsigned int cmdat; 4091c6a0718SPierre Ossman 4101c6a0718SPierre Ossman WARN_ON(host->mrq != NULL); 4111c6a0718SPierre Ossman 4121c6a0718SPierre Ossman host->mrq = mrq; 4131c6a0718SPierre Ossman 4141c6a0718SPierre Ossman pxamci_stop_clock(host); 4151c6a0718SPierre Ossman 4161c6a0718SPierre Ossman cmdat = host->cmdat; 4171c6a0718SPierre Ossman host->cmdat &= ~CMDAT_INIT; 4181c6a0718SPierre Ossman 4191c6a0718SPierre Ossman if (mrq->data) { 4201c6a0718SPierre Ossman pxamci_setup_data(host, mrq->data); 4211c6a0718SPierre Ossman 4221c6a0718SPierre Ossman cmdat &= ~CMDAT_BUSY; 4231c6a0718SPierre Ossman cmdat |= CMDAT_DATAEN | CMDAT_DMAEN; 4241c6a0718SPierre Ossman if (mrq->data->flags & MMC_DATA_WRITE) 4251c6a0718SPierre Ossman cmdat |= CMDAT_WRITE; 4261c6a0718SPierre Ossman } 4271c6a0718SPierre Ossman 4281c6a0718SPierre Ossman pxamci_start_cmd(host, mrq->cmd, cmdat); 4291c6a0718SPierre Ossman } 4301c6a0718SPierre Ossman 4311c6a0718SPierre Ossman static int pxamci_get_ro(struct mmc_host *mmc) 4321c6a0718SPierre Ossman { 4331c6a0718SPierre Ossman struct pxamci_host *host = mmc_priv(mmc); 4341c6a0718SPierre Ossman 435fd546ee6SRobert Jarzmik if (host->pdata && gpio_is_valid(host->pdata->gpio_card_ro)) 436fd546ee6SRobert Jarzmik return mmc_gpio_get_ro(mmc); 4371c6a0718SPierre Ossman if (host->pdata && host->pdata->get_ro) 43808f80bb5SAnton Vorontsov return !!host->pdata->get_ro(mmc_dev(mmc)); 43908f80bb5SAnton Vorontsov /* 44008f80bb5SAnton Vorontsov * Board doesn't support read only detection; let the mmc core 44108f80bb5SAnton Vorontsov * decide what to do. 44208f80bb5SAnton Vorontsov */ 44308f80bb5SAnton Vorontsov return -ENOSYS; 4441c6a0718SPierre Ossman } 4451c6a0718SPierre Ossman 4461c6a0718SPierre Ossman static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) 4471c6a0718SPierre Ossman { 4481c6a0718SPierre Ossman struct pxamci_host *host = mmc_priv(mmc); 4491c6a0718SPierre Ossman 4501c6a0718SPierre Ossman if (ios->clock) { 451ebebd9b0SRussell King unsigned long rate = host->clkrate; 452ebebd9b0SRussell King unsigned int clk = rate / ios->clock; 453ebebd9b0SRussell King 454d8cb70d1SRussell King if (host->clkrt == CLKRT_OFF) 455e7370819SRobert Jarzmik clk_prepare_enable(host->clk); 456d8cb70d1SRussell King 45764eb036aSBridge Wu if (ios->clock == 26000000) { 458fa3f9938SHaojian Zhuang /* to support 26MHz */ 45964eb036aSBridge Wu host->clkrt = 7; 46064eb036aSBridge Wu } else { 46164eb036aSBridge Wu /* to handle (19.5MHz, 26MHz) */ 46264eb036aSBridge Wu if (!clk) 46364eb036aSBridge Wu clk = 1; 46464eb036aSBridge Wu 465ebebd9b0SRussell King /* 466ebebd9b0SRussell King * clk might result in a lower divisor than we 467ebebd9b0SRussell King * desire. check for that condition and adjust 468ebebd9b0SRussell King * as appropriate. 469ebebd9b0SRussell King */ 470ebebd9b0SRussell King if (rate / clk > ios->clock) 4711c6a0718SPierre Ossman clk <<= 1; 4721c6a0718SPierre Ossman host->clkrt = fls(clk) - 1; 47364eb036aSBridge Wu } 4741c6a0718SPierre Ossman 4751c6a0718SPierre Ossman /* 4761c6a0718SPierre Ossman * we write clkrt on the next command 4771c6a0718SPierre Ossman */ 4781c6a0718SPierre Ossman } else { 4791c6a0718SPierre Ossman pxamci_stop_clock(host); 480d8cb70d1SRussell King if (host->clkrt != CLKRT_OFF) { 481d8cb70d1SRussell King host->clkrt = CLKRT_OFF; 482e7370819SRobert Jarzmik clk_disable_unprepare(host->clk); 4831c6a0718SPierre Ossman } 484d8cb70d1SRussell King } 4851c6a0718SPierre Ossman 4861c6a0718SPierre Ossman if (host->power_mode != ios->power_mode) { 48799fc5131SLinus Walleij int ret; 48899fc5131SLinus Walleij 4891c6a0718SPierre Ossman host->power_mode = ios->power_mode; 4901c6a0718SPierre Ossman 49199fc5131SLinus Walleij ret = pxamci_set_power(host, ios->power_mode, ios->vdd); 49299fc5131SLinus Walleij if (ret) { 49399fc5131SLinus Walleij dev_err(mmc_dev(mmc), "unable to set power\n"); 49499fc5131SLinus Walleij /* 49599fc5131SLinus Walleij * The .set_ios() function in the mmc_host_ops 49699fc5131SLinus Walleij * struct return void, and failing to set the 49799fc5131SLinus Walleij * power should be rare so we print an error and 49899fc5131SLinus Walleij * return here. 49999fc5131SLinus Walleij */ 50099fc5131SLinus Walleij return; 50199fc5131SLinus Walleij } 5021c6a0718SPierre Ossman 5031c6a0718SPierre Ossman if (ios->power_mode == MMC_POWER_ON) 5041c6a0718SPierre Ossman host->cmdat |= CMDAT_INIT; 5051c6a0718SPierre Ossman } 5061c6a0718SPierre Ossman 507df456f47SBridge Wu if (ios->bus_width == MMC_BUS_WIDTH_4) 508df456f47SBridge Wu host->cmdat |= CMDAT_SD_4DAT; 509df456f47SBridge Wu else 510df456f47SBridge Wu host->cmdat &= ~CMDAT_SD_4DAT; 511df456f47SBridge Wu 51299fc5131SLinus Walleij dev_dbg(mmc_dev(mmc), "PXAMCI: clkrt = %x cmdat = %x\n", 5131c6a0718SPierre Ossman host->clkrt, host->cmdat); 5141c6a0718SPierre Ossman } 5151c6a0718SPierre Ossman 5165d3ad4e8SBridge Wu static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable) 5175d3ad4e8SBridge Wu { 5185d3ad4e8SBridge Wu struct pxamci_host *pxa_host = mmc_priv(host); 5195d3ad4e8SBridge Wu 5205d3ad4e8SBridge Wu if (enable) 5215d3ad4e8SBridge Wu pxamci_enable_irq(pxa_host, SDIO_INT); 5225d3ad4e8SBridge Wu else 5235d3ad4e8SBridge Wu pxamci_disable_irq(pxa_host, SDIO_INT); 5245d3ad4e8SBridge Wu } 5255d3ad4e8SBridge Wu 5261c6a0718SPierre Ossman static const struct mmc_host_ops pxamci_ops = { 5271c6a0718SPierre Ossman .request = pxamci_request, 528fd546ee6SRobert Jarzmik .get_cd = mmc_gpio_get_cd, 5291c6a0718SPierre Ossman .get_ro = pxamci_get_ro, 5301c6a0718SPierre Ossman .set_ios = pxamci_set_ios, 5315d3ad4e8SBridge Wu .enable_sdio_irq = pxamci_enable_sdio_irq, 5321c6a0718SPierre Ossman }; 5331c6a0718SPierre Ossman 5346464b714SDaniel Mack static void pxamci_dma_irq(void *param) 5351c6a0718SPierre Ossman { 5366464b714SDaniel Mack struct pxamci_host *host = param; 5376464b714SDaniel Mack struct dma_tx_state state; 5386464b714SDaniel Mack enum dma_status status; 5396464b714SDaniel Mack struct dma_chan *chan; 5406464b714SDaniel Mack unsigned long flags; 541c783837bSNicolas Pitre 5426464b714SDaniel Mack spin_lock_irqsave(&host->lock, flags); 5436464b714SDaniel Mack 5446464b714SDaniel Mack if (!host->data) 5456464b714SDaniel Mack goto out_unlock; 5466464b714SDaniel Mack 5476464b714SDaniel Mack if (host->data->flags & MMC_DATA_READ) 5486464b714SDaniel Mack chan = host->dma_chan_rx; 5496464b714SDaniel Mack else 5506464b714SDaniel Mack chan = host->dma_chan_tx; 5516464b714SDaniel Mack 5526464b714SDaniel Mack status = dmaengine_tx_status(chan, host->dma_cookie, &state); 5536464b714SDaniel Mack 5546464b714SDaniel Mack if (likely(status == DMA_COMPLETE)) { 555c783837bSNicolas Pitre writel(BUF_PART_FULL, host->base + MMC_PRTBUF); 556c783837bSNicolas Pitre } else { 5576464b714SDaniel Mack pr_err("%s: DMA error on %s channel\n", mmc_hostname(host->mmc), 5586464b714SDaniel Mack host->data->flags & MMC_DATA_READ ? "rx" : "tx"); 559c783837bSNicolas Pitre host->data->error = -EIO; 560c783837bSNicolas Pitre pxamci_data_done(host, 0); 561c783837bSNicolas Pitre } 5626464b714SDaniel Mack 5636464b714SDaniel Mack out_unlock: 5646464b714SDaniel Mack spin_unlock_irqrestore(&host->lock, flags); 5651c6a0718SPierre Ossman } 5661c6a0718SPierre Ossman 5671c6a0718SPierre Ossman static irqreturn_t pxamci_detect_irq(int irq, void *devid) 5681c6a0718SPierre Ossman { 5691c6a0718SPierre Ossman struct pxamci_host *host = mmc_priv(devid); 5701c6a0718SPierre Ossman 57138a8dda9SDaniel Mack mmc_detect_change(devid, msecs_to_jiffies(host->detect_delay_ms)); 5721c6a0718SPierre Ossman return IRQ_HANDLED; 5731c6a0718SPierre Ossman } 5741c6a0718SPierre Ossman 575e6027b46SDaniel Mack #ifdef CONFIG_OF 576e6027b46SDaniel Mack static const struct of_device_id pxa_mmc_dt_ids[] = { 577e6027b46SDaniel Mack { .compatible = "marvell,pxa-mmc" }, 578e6027b46SDaniel Mack { } 579e6027b46SDaniel Mack }; 580e6027b46SDaniel Mack 581e6027b46SDaniel Mack MODULE_DEVICE_TABLE(of, pxa_mmc_dt_ids); 582e6027b46SDaniel Mack 583fa3a5115SDaniel Mack static int pxamci_of_init(struct platform_device *pdev, 584fa3a5115SDaniel Mack struct mmc_host *mmc) 585e6027b46SDaniel Mack { 586e6027b46SDaniel Mack struct device_node *np = pdev->dev.of_node; 58738a8dda9SDaniel Mack struct pxamci_host *host = mmc_priv(mmc); 588e6027b46SDaniel Mack u32 tmp; 589fa3a5115SDaniel Mack int ret; 590e6027b46SDaniel Mack 591e6027b46SDaniel Mack if (!np) 592e6027b46SDaniel Mack return 0; 593e6027b46SDaniel Mack 594e6027b46SDaniel Mack /* pxa-mmc specific */ 595e6027b46SDaniel Mack if (of_property_read_u32(np, "pxa-mmc,detect-delay-ms", &tmp) == 0) 59638a8dda9SDaniel Mack host->detect_delay_ms = tmp; 597e6027b46SDaniel Mack 598fa3a5115SDaniel Mack ret = mmc_of_parse(mmc); 599fa3a5115SDaniel Mack if (ret < 0) 600fa3a5115SDaniel Mack return ret; 601fa3a5115SDaniel Mack 602e6027b46SDaniel Mack return 0; 603e6027b46SDaniel Mack } 604e6027b46SDaniel Mack #else 605fa3a5115SDaniel Mack static int pxamci_of_init(struct platform_device *pdev, 606fa3a5115SDaniel Mack struct mmc_host *mmc) 607e6027b46SDaniel Mack { 608e6027b46SDaniel Mack return 0; 609e6027b46SDaniel Mack } 610e6027b46SDaniel Mack #endif 611e6027b46SDaniel Mack 6121c6a0718SPierre Ossman static int pxamci_probe(struct platform_device *pdev) 6131c6a0718SPierre Ossman { 6141c6a0718SPierre Ossman struct mmc_host *mmc; 6151c6a0718SPierre Ossman struct pxamci_host *host = NULL; 6166b3348f9SRobert Jarzmik struct resource *r; 61738a8dda9SDaniel Mack int ret, irq; 6181c6a0718SPierre Ossman 6191c6a0718SPierre Ossman r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 6201c6a0718SPierre Ossman irq = platform_get_irq(pdev, 0); 62107e7716cSRobert Jarzmik if (irq < 0) 62207e7716cSRobert Jarzmik return irq; 6231c6a0718SPierre Ossman 6241c6a0718SPierre Ossman mmc = mmc_alloc_host(sizeof(struct pxamci_host), &pdev->dev); 6251c6a0718SPierre Ossman if (!mmc) { 6261c6a0718SPierre Ossman ret = -ENOMEM; 6271c6a0718SPierre Ossman goto out; 6281c6a0718SPierre Ossman } 6291c6a0718SPierre Ossman 6301c6a0718SPierre Ossman mmc->ops = &pxamci_ops; 6311c6a0718SPierre Ossman 6321c6a0718SPierre Ossman /* 6331c6a0718SPierre Ossman * We can do SG-DMA, but we don't because we never know how much 6341c6a0718SPierre Ossman * data we successfully wrote to the card. 6351c6a0718SPierre Ossman */ 636a36274e0SMartin K. Petersen mmc->max_segs = NR_SG; 6371c6a0718SPierre Ossman 6381c6a0718SPierre Ossman /* 6391c6a0718SPierre Ossman * Our hardware DMA can handle a maximum of one page per SG entry. 6401c6a0718SPierre Ossman */ 6411c6a0718SPierre Ossman mmc->max_seg_size = PAGE_SIZE; 6421c6a0718SPierre Ossman 6431c6a0718SPierre Ossman /* 644fe2dc44eSNicolas Pitre * Block length register is only 10 bits before PXA27x. 6451c6a0718SPierre Ossman */ 6460ffcbfd5SEric Miao mmc->max_blk_size = cpu_is_pxa25x() ? 1023 : 2048; 6471c6a0718SPierre Ossman 6481c6a0718SPierre Ossman /* 6491c6a0718SPierre Ossman * Block count register is 16 bits. 6501c6a0718SPierre Ossman */ 6511c6a0718SPierre Ossman mmc->max_blk_count = 65535; 6521c6a0718SPierre Ossman 653fa3a5115SDaniel Mack ret = pxamci_of_init(pdev, mmc); 654fa3a5115SDaniel Mack if (ret) 655fa3a5115SDaniel Mack return ret; 656fa3a5115SDaniel Mack 6571c6a0718SPierre Ossman host = mmc_priv(mmc); 6581c6a0718SPierre Ossman host->mmc = mmc; 6591c6a0718SPierre Ossman host->pdata = pdev->dev.platform_data; 660d8cb70d1SRussell King host->clkrt = CLKRT_OFF; 661ebebd9b0SRussell King 66207e7716cSRobert Jarzmik host->clk = devm_clk_get(&pdev->dev, NULL); 663ebebd9b0SRussell King if (IS_ERR(host->clk)) { 664ebebd9b0SRussell King ret = PTR_ERR(host->clk); 665ebebd9b0SRussell King host->clk = NULL; 666ebebd9b0SRussell King goto out; 667ebebd9b0SRussell King } 668ebebd9b0SRussell King 669ebebd9b0SRussell King host->clkrate = clk_get_rate(host->clk); 670ebebd9b0SRussell King 671ebebd9b0SRussell King /* 672ebebd9b0SRussell King * Calculate minimum clock rate, rounding up. 673ebebd9b0SRussell King */ 674ebebd9b0SRussell King mmc->f_min = (host->clkrate + 63) / 64; 675fa3f9938SHaojian Zhuang mmc->f_max = (mmc_has_26MHz()) ? 26000000 : host->clkrate; 676ebebd9b0SRussell King 67761951fd6SDaniel Mack ret = pxamci_init_ocr(host); 67861951fd6SDaniel Mack if (ret < 0) 67961951fd6SDaniel Mack return ret; 6808385f9cbSDaniel Ribeiro 681de3ee99bSLinus Walleij mmc->caps = 0; 6825d3ad4e8SBridge Wu host->cmdat = 0; 6830ffcbfd5SEric Miao if (!cpu_is_pxa25x()) { 6845d3ad4e8SBridge Wu mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; 6855d3ad4e8SBridge Wu host->cmdat |= CMDAT_SDIO_INT_EN; 686fa3f9938SHaojian Zhuang if (mmc_has_26MHz()) 68764eb036aSBridge Wu mmc->caps |= MMC_CAP_MMC_HIGHSPEED | 68864eb036aSBridge Wu MMC_CAP_SD_HIGHSPEED; 6895d3ad4e8SBridge Wu } 6901c6a0718SPierre Ossman 6911c6a0718SPierre Ossman spin_lock_init(&host->lock); 6921c6a0718SPierre Ossman host->res = r; 6931c6a0718SPierre Ossman host->imask = MMC_I_MASK_ALL; 6941c6a0718SPierre Ossman 69507e7716cSRobert Jarzmik host->base = devm_ioremap_resource(&pdev->dev, r); 69607e7716cSRobert Jarzmik if (IS_ERR(host->base)) { 69707e7716cSRobert Jarzmik ret = PTR_ERR(host->base); 6981c6a0718SPierre Ossman goto out; 6991c6a0718SPierre Ossman } 7001c6a0718SPierre Ossman 7011c6a0718SPierre Ossman /* 7021c6a0718SPierre Ossman * Ensure that the host controller is shut down, and setup 7031c6a0718SPierre Ossman * with our defaults. 7041c6a0718SPierre Ossman */ 7051c6a0718SPierre Ossman pxamci_stop_clock(host); 7061c6a0718SPierre Ossman writel(0, host->base + MMC_SPI); 7071c6a0718SPierre Ossman writel(64, host->base + MMC_RESTO); 7081c6a0718SPierre Ossman writel(host->imask, host->base + MMC_I_MASK); 7091c6a0718SPierre Ossman 710d92eaf57SDaniel Mack ret = devm_request_irq(&pdev->dev, irq, pxamci_irq, 0, 71107e7716cSRobert Jarzmik DRIVER_NAME, host); 7121c6a0718SPierre Ossman if (ret) 7131c6a0718SPierre Ossman goto out; 7141c6a0718SPierre Ossman 7151c6a0718SPierre Ossman platform_set_drvdata(pdev, mmc); 7161c6a0718SPierre Ossman 7176b3348f9SRobert Jarzmik host->dma_chan_rx = dma_request_slave_channel(&pdev->dev, "rx"); 7186464b714SDaniel Mack if (host->dma_chan_rx == NULL) { 7196464b714SDaniel Mack dev_err(&pdev->dev, "unable to request rx dma channel\n"); 7206464b714SDaniel Mack ret = -ENODEV; 7216464b714SDaniel Mack goto out; 7226464b714SDaniel Mack } 7236464b714SDaniel Mack 7246b3348f9SRobert Jarzmik host->dma_chan_tx = dma_request_slave_channel(&pdev->dev, "tx"); 7256464b714SDaniel Mack if (host->dma_chan_tx == NULL) { 7266464b714SDaniel Mack dev_err(&pdev->dev, "unable to request tx dma channel\n"); 7276464b714SDaniel Mack ret = -ENODEV; 7286464b714SDaniel Mack goto out; 7296464b714SDaniel Mack } 7309a788c6bSBridge Wu 731b405db6cSRobert Jarzmik if (host->pdata) { 73238a8dda9SDaniel Mack int gpio_cd = host->pdata->gpio_card_detect; 73338a8dda9SDaniel Mack int gpio_ro = host->pdata->gpio_card_ro; 73438a8dda9SDaniel Mack int gpio_power = host->pdata->gpio_power; 73538a8dda9SDaniel Mack 73638a8dda9SDaniel Mack host->detect_delay_ms = host->pdata->detect_delay_ms; 73738a8dda9SDaniel Mack 738b405db6cSRobert Jarzmik if (gpio_is_valid(gpio_power)) { 739fd546ee6SRobert Jarzmik ret = devm_gpio_request(&pdev->dev, gpio_power, 740fd546ee6SRobert Jarzmik "mmc card power"); 741b405db6cSRobert Jarzmik if (ret) { 74238a8dda9SDaniel Mack dev_err(&pdev->dev, 74338a8dda9SDaniel Mack "Failed requesting gpio_power %d\n", 744fd546ee6SRobert Jarzmik gpio_power); 745b405db6cSRobert Jarzmik goto out; 746b405db6cSRobert Jarzmik } 747b405db6cSRobert Jarzmik gpio_direction_output(gpio_power, 748b405db6cSRobert Jarzmik host->pdata->gpio_power_invert); 749b405db6cSRobert Jarzmik } 75038a8dda9SDaniel Mack 751b3802db5SRobert Jarzmik if (gpio_is_valid(gpio_ro)) { 752fd546ee6SRobert Jarzmik ret = mmc_gpio_request_ro(mmc, gpio_ro); 753b405db6cSRobert Jarzmik if (ret) { 75438a8dda9SDaniel Mack dev_err(&pdev->dev, 75538a8dda9SDaniel Mack "Failed requesting gpio_ro %d\n", 756b3802db5SRobert Jarzmik gpio_ro); 757fd546ee6SRobert Jarzmik goto out; 758fd546ee6SRobert Jarzmik } else { 75941c89159SRobert Jarzmik mmc->caps2 |= host->pdata->gpio_card_ro_invert ? 76026d49fe7SRobert Jarzmik 0 : MMC_CAP2_RO_ACTIVE_HIGH; 761b405db6cSRobert Jarzmik } 762b3802db5SRobert Jarzmik } 763fd546ee6SRobert Jarzmik 764fd546ee6SRobert Jarzmik if (gpio_is_valid(gpio_cd)) 765fd546ee6SRobert Jarzmik ret = mmc_gpio_request_cd(mmc, gpio_cd, 0); 766b405db6cSRobert Jarzmik if (ret) { 76738a8dda9SDaniel Mack dev_err(&pdev->dev, "Failed requesting gpio_cd %d\n", 76838a8dda9SDaniel Mack gpio_cd); 769fd546ee6SRobert Jarzmik goto out; 770b405db6cSRobert Jarzmik } 771b405db6cSRobert Jarzmik 77238a8dda9SDaniel Mack if (host->pdata->init) 7731c6a0718SPierre Ossman host->pdata->init(&pdev->dev, pxamci_detect_irq, mmc); 7741c6a0718SPierre Ossman 775b405db6cSRobert Jarzmik if (gpio_is_valid(gpio_power) && host->pdata->setpower) 776b405db6cSRobert Jarzmik dev_warn(&pdev->dev, "gpio_power and setpower() both defined\n"); 777b405db6cSRobert Jarzmik if (gpio_is_valid(gpio_ro) && host->pdata->get_ro) 778b405db6cSRobert Jarzmik dev_warn(&pdev->dev, "gpio_ro and get_ro() both defined\n"); 77938a8dda9SDaniel Mack } 780b405db6cSRobert Jarzmik 7811c6a0718SPierre Ossman mmc_add_host(mmc); 7821c6a0718SPierre Ossman 7831c6a0718SPierre Ossman return 0; 7841c6a0718SPierre Ossman 7851c6a0718SPierre Ossman out: 7861c6a0718SPierre Ossman if (host) { 7876464b714SDaniel Mack if (host->dma_chan_rx) 7886464b714SDaniel Mack dma_release_channel(host->dma_chan_rx); 7896464b714SDaniel Mack if (host->dma_chan_tx) 7906464b714SDaniel Mack dma_release_channel(host->dma_chan_tx); 7911c6a0718SPierre Ossman } 7921c6a0718SPierre Ossman if (mmc) 7931c6a0718SPierre Ossman mmc_free_host(mmc); 7941c6a0718SPierre Ossman return ret; 7951c6a0718SPierre Ossman } 7961c6a0718SPierre Ossman 7971c6a0718SPierre Ossman static int pxamci_remove(struct platform_device *pdev) 7981c6a0718SPierre Ossman { 7991c6a0718SPierre Ossman struct mmc_host *mmc = platform_get_drvdata(pdev); 8001c6a0718SPierre Ossman 8011c6a0718SPierre Ossman if (mmc) { 8021c6a0718SPierre Ossman struct pxamci_host *host = mmc_priv(mmc); 8031c6a0718SPierre Ossman 8045d6b1edfSDaniel Mack mmc_remove_host(mmc); 8055d6b1edfSDaniel Mack 8061c6a0718SPierre Ossman if (host->pdata && host->pdata->exit) 8071c6a0718SPierre Ossman host->pdata->exit(&pdev->dev, mmc); 8081c6a0718SPierre Ossman 8091c6a0718SPierre Ossman pxamci_stop_clock(host); 8101c6a0718SPierre Ossman writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD| 8111c6a0718SPierre Ossman END_CMD_RES|PRG_DONE|DATA_TRAN_DONE, 8121c6a0718SPierre Ossman host->base + MMC_I_MASK); 8131c6a0718SPierre Ossman 8146464b714SDaniel Mack dmaengine_terminate_all(host->dma_chan_rx); 8156464b714SDaniel Mack dmaengine_terminate_all(host->dma_chan_tx); 8166464b714SDaniel Mack dma_release_channel(host->dma_chan_rx); 8176464b714SDaniel Mack dma_release_channel(host->dma_chan_tx); 8181c6a0718SPierre Ossman 8191c6a0718SPierre Ossman mmc_free_host(mmc); 8201c6a0718SPierre Ossman } 82152c09186SDaniel Mack 8221c6a0718SPierre Ossman return 0; 8231c6a0718SPierre Ossman } 8241c6a0718SPierre Ossman 8251c6a0718SPierre Ossman static struct platform_driver pxamci_driver = { 8261c6a0718SPierre Ossman .probe = pxamci_probe, 8271c6a0718SPierre Ossman .remove = pxamci_remove, 8281c6a0718SPierre Ossman .driver = { 8291c6a0718SPierre Ossman .name = DRIVER_NAME, 830e6027b46SDaniel Mack .of_match_table = of_match_ptr(pxa_mmc_dt_ids), 8311c6a0718SPierre Ossman }, 8321c6a0718SPierre Ossman }; 8331c6a0718SPierre Ossman 834d1f81a64SAxel Lin module_platform_driver(pxamci_driver); 8351c6a0718SPierre Ossman 8361c6a0718SPierre Ossman MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver"); 8371c6a0718SPierre Ossman MODULE_LICENSE("GPL"); 838bc65c724SKay Sievers MODULE_ALIAS("platform:pxa2xx-mci"); 839