xref: /openbmc/linux/drivers/mmc/host/pxamci.c (revision 21b2cec6)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21c6a0718SPierre Ossman /*
370f10482SPierre Ossman  *  linux/drivers/mmc/host/pxa.c - PXA MMCI driver
41c6a0718SPierre Ossman  *
51c6a0718SPierre Ossman  *  Copyright (C) 2003 Russell King, All Rights Reserved.
61c6a0718SPierre Ossman  *
71c6a0718SPierre Ossman  *  This hardware is really sick:
81c6a0718SPierre Ossman  *   - No way to clear interrupts.
91c6a0718SPierre Ossman  *   - Have to turn off the clock whenever we touch the device.
101c6a0718SPierre Ossman  *   - Doesn't tell you how many data blocks were transferred.
111c6a0718SPierre Ossman  *  Yuck!
121c6a0718SPierre Ossman  *
131c6a0718SPierre Ossman  *	1 and 3 byte data transfers not supported
141c6a0718SPierre Ossman  *	max block length up to 1023
151c6a0718SPierre Ossman  */
161c6a0718SPierre Ossman #include <linux/module.h>
171c6a0718SPierre Ossman #include <linux/init.h>
181c6a0718SPierre Ossman #include <linux/ioport.h>
191c6a0718SPierre Ossman #include <linux/platform_device.h>
201c6a0718SPierre Ossman #include <linux/delay.h>
211c6a0718SPierre Ossman #include <linux/interrupt.h>
226464b714SDaniel Mack #include <linux/dmaengine.h>
231c6a0718SPierre Ossman #include <linux/dma-mapping.h>
24ebebd9b0SRussell King #include <linux/clk.h>
25ebebd9b0SRussell King #include <linux/err.h>
261c6a0718SPierre Ossman #include <linux/mmc/host.h>
27fd546ee6SRobert Jarzmik #include <linux/mmc/slot-gpio.h>
2805678a96SRussell King #include <linux/io.h>
298385f9cbSDaniel Ribeiro #include <linux/regulator/consumer.h>
30f54005b5SLinus Walleij #include <linux/gpio/consumer.h>
315a0e3ad6STejun Heo #include <linux/gfp.h>
32e6027b46SDaniel Mack #include <linux/of.h>
33e6027b46SDaniel Mack #include <linux/of_device.h>
341c6a0718SPierre Ossman 
3587dfb311SMasahiro Yamada #include <linux/sizes.h>
361c6a0718SPierre Ossman 
3705678a96SRussell King #include <mach/hardware.h>
38293b2da1SArnd Bergmann #include <linux/platform_data/mmc-pxamci.h>
391c6a0718SPierre Ossman 
401c6a0718SPierre Ossman #include "pxamci.h"
411c6a0718SPierre Ossman 
421c6a0718SPierre Ossman #define DRIVER_NAME	"pxa2xx-mci"
431c6a0718SPierre Ossman 
441c6a0718SPierre Ossman #define NR_SG	1
45d8cb70d1SRussell King #define CLKRT_OFF	(~0)
461c6a0718SPierre Ossman 
47fa3f9938SHaojian Zhuang #define mmc_has_26MHz()		(cpu_is_pxa300() || cpu_is_pxa310() \
48fa3f9938SHaojian Zhuang 				|| cpu_is_pxa935())
49fa3f9938SHaojian Zhuang 
501c6a0718SPierre Ossman struct pxamci_host {
511c6a0718SPierre Ossman 	struct mmc_host		*mmc;
521c6a0718SPierre Ossman 	spinlock_t		lock;
531c6a0718SPierre Ossman 	struct resource		*res;
541c6a0718SPierre Ossman 	void __iomem		*base;
55ebebd9b0SRussell King 	struct clk		*clk;
56ebebd9b0SRussell King 	unsigned long		clkrate;
571c6a0718SPierre Ossman 	unsigned int		clkrt;
581c6a0718SPierre Ossman 	unsigned int		cmdat;
591c6a0718SPierre Ossman 	unsigned int		imask;
601c6a0718SPierre Ossman 	unsigned int		power_mode;
6138a8dda9SDaniel Mack 	unsigned long		detect_delay_ms;
62c914a27cSLinus Walleij 	bool			use_ro_gpio;
63f54005b5SLinus Walleij 	struct gpio_desc	*power;
641c6a0718SPierre Ossman 	struct pxamci_platform_data *pdata;
651c6a0718SPierre Ossman 
661c6a0718SPierre Ossman 	struct mmc_request	*mrq;
671c6a0718SPierre Ossman 	struct mmc_command	*cmd;
681c6a0718SPierre Ossman 	struct mmc_data		*data;
691c6a0718SPierre Ossman 
706464b714SDaniel Mack 	struct dma_chan		*dma_chan_rx;
716464b714SDaniel Mack 	struct dma_chan		*dma_chan_tx;
726464b714SDaniel Mack 	dma_cookie_t		dma_cookie;
731c6a0718SPierre Ossman 	unsigned int		dma_len;
741c6a0718SPierre Ossman 	unsigned int		dma_dir;
751c6a0718SPierre Ossman };
761c6a0718SPierre Ossman 
7761951fd6SDaniel Mack static int pxamci_init_ocr(struct pxamci_host *host)
788385f9cbSDaniel Ribeiro {
7961951fd6SDaniel Mack 	struct mmc_host *mmc = host->mmc;
8061951fd6SDaniel Mack 	int ret;
818385f9cbSDaniel Ribeiro 
8261951fd6SDaniel Mack 	ret = mmc_regulator_get_supply(mmc);
8361951fd6SDaniel Mack 	if (ret < 0)
8461951fd6SDaniel Mack 		return ret;
8561951fd6SDaniel Mack 
8661951fd6SDaniel Mack 	if (IS_ERR(mmc->supply.vmmc)) {
878385f9cbSDaniel Ribeiro 		/* fall-back to platform data */
8861951fd6SDaniel Mack 		mmc->ocr_avail = host->pdata ?
898385f9cbSDaniel Ribeiro 			host->pdata->ocr_mask :
908385f9cbSDaniel Ribeiro 			MMC_VDD_32_33 | MMC_VDD_33_34;
918385f9cbSDaniel Ribeiro 	}
9261951fd6SDaniel Mack 
9361951fd6SDaniel Mack 	return 0;
948385f9cbSDaniel Ribeiro }
958385f9cbSDaniel Ribeiro 
9699fc5131SLinus Walleij static inline int pxamci_set_power(struct pxamci_host *host,
9799fc5131SLinus Walleij 				    unsigned char power_mode,
9899fc5131SLinus Walleij 				    unsigned int vdd)
998385f9cbSDaniel Ribeiro {
10061951fd6SDaniel Mack 	struct mmc_host *mmc = host->mmc;
10161951fd6SDaniel Mack 	struct regulator *supply = mmc->supply.vmmc;
102b405db6cSRobert Jarzmik 
10361951fd6SDaniel Mack 	if (!IS_ERR(supply))
10461951fd6SDaniel Mack 		return mmc_regulator_set_ocr(mmc, supply, vdd);
10599fc5131SLinus Walleij 
106f54005b5SLinus Walleij 	if (host->power) {
107f54005b5SLinus Walleij 		bool on = !!((1 << vdd) & host->pdata->ocr_mask);
108f54005b5SLinus Walleij 		gpiod_set_value(host->power, on);
109b405db6cSRobert Jarzmik 	}
11061951fd6SDaniel Mack 
11161951fd6SDaniel Mack 	if (host->pdata && host->pdata->setpower)
112a829abf8SArnd Bergmann 		return host->pdata->setpower(mmc_dev(host->mmc), vdd);
11399fc5131SLinus Walleij 
11499fc5131SLinus Walleij 	return 0;
1158385f9cbSDaniel Ribeiro }
1168385f9cbSDaniel Ribeiro 
1171c6a0718SPierre Ossman static void pxamci_stop_clock(struct pxamci_host *host)
1181c6a0718SPierre Ossman {
1191c6a0718SPierre Ossman 	if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
1201c6a0718SPierre Ossman 		unsigned long timeout = 10000;
1211c6a0718SPierre Ossman 		unsigned int v;
1221c6a0718SPierre Ossman 
1231c6a0718SPierre Ossman 		writel(STOP_CLOCK, host->base + MMC_STRPCL);
1241c6a0718SPierre Ossman 
1251c6a0718SPierre Ossman 		do {
1261c6a0718SPierre Ossman 			v = readl(host->base + MMC_STAT);
1271c6a0718SPierre Ossman 			if (!(v & STAT_CLK_EN))
1281c6a0718SPierre Ossman 				break;
1291c6a0718SPierre Ossman 			udelay(1);
1301c6a0718SPierre Ossman 		} while (timeout--);
1311c6a0718SPierre Ossman 
1321c6a0718SPierre Ossman 		if (v & STAT_CLK_EN)
1331c6a0718SPierre Ossman 			dev_err(mmc_dev(host->mmc), "unable to stop clock\n");
1341c6a0718SPierre Ossman 	}
1351c6a0718SPierre Ossman }
1361c6a0718SPierre Ossman 
1371c6a0718SPierre Ossman static void pxamci_enable_irq(struct pxamci_host *host, unsigned int mask)
1381c6a0718SPierre Ossman {
1391c6a0718SPierre Ossman 	unsigned long flags;
1401c6a0718SPierre Ossman 
1411c6a0718SPierre Ossman 	spin_lock_irqsave(&host->lock, flags);
1421c6a0718SPierre Ossman 	host->imask &= ~mask;
1431c6a0718SPierre Ossman 	writel(host->imask, host->base + MMC_I_MASK);
1441c6a0718SPierre Ossman 	spin_unlock_irqrestore(&host->lock, flags);
1451c6a0718SPierre Ossman }
1461c6a0718SPierre Ossman 
1471c6a0718SPierre Ossman static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)
1481c6a0718SPierre Ossman {
1491c6a0718SPierre Ossman 	unsigned long flags;
1501c6a0718SPierre Ossman 
1511c6a0718SPierre Ossman 	spin_lock_irqsave(&host->lock, flags);
1521c6a0718SPierre Ossman 	host->imask |= mask;
1531c6a0718SPierre Ossman 	writel(host->imask, host->base + MMC_I_MASK);
1541c6a0718SPierre Ossman 	spin_unlock_irqrestore(&host->lock, flags);
1551c6a0718SPierre Ossman }
1561c6a0718SPierre Ossman 
1576464b714SDaniel Mack static void pxamci_dma_irq(void *param);
1586464b714SDaniel Mack 
1591c6a0718SPierre Ossman static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
1601c6a0718SPierre Ossman {
1616464b714SDaniel Mack 	struct dma_async_tx_descriptor *tx;
162e60a582bSArnd Bergmann 	enum dma_transfer_direction direction;
1636464b714SDaniel Mack 	struct dma_slave_config	config;
1646464b714SDaniel Mack 	struct dma_chan *chan;
1651c6a0718SPierre Ossman 	unsigned int nob = data->blocks;
1661c6a0718SPierre Ossman 	unsigned long long clks;
1671c6a0718SPierre Ossman 	unsigned int timeout;
1686464b714SDaniel Mack 	int ret;
1691c6a0718SPierre Ossman 
1701c6a0718SPierre Ossman 	host->data = data;
1711c6a0718SPierre Ossman 
1721c6a0718SPierre Ossman 	writel(nob, host->base + MMC_NOB);
1731c6a0718SPierre Ossman 	writel(data->blksz, host->base + MMC_BLKLEN);
1741c6a0718SPierre Ossman 
175ebebd9b0SRussell King 	clks = (unsigned long long)data->timeout_ns * host->clkrate;
1761c6a0718SPierre Ossman 	do_div(clks, 1000000000UL);
1771c6a0718SPierre Ossman 	timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt);
1781c6a0718SPierre Ossman 	writel((timeout + 255) / 256, host->base + MMC_RDTO);
1791c6a0718SPierre Ossman 
1806464b714SDaniel Mack 	memset(&config, 0, sizeof(config));
1816464b714SDaniel Mack 	config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
1826464b714SDaniel Mack 	config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
1836464b714SDaniel Mack 	config.src_addr = host->res->start + MMC_RXFIFO;
1846464b714SDaniel Mack 	config.dst_addr = host->res->start + MMC_TXFIFO;
1856464b714SDaniel Mack 	config.src_maxburst = 32;
1866464b714SDaniel Mack 	config.dst_maxburst = 32;
1876464b714SDaniel Mack 
1881c6a0718SPierre Ossman 	if (data->flags & MMC_DATA_READ) {
1891c6a0718SPierre Ossman 		host->dma_dir = DMA_FROM_DEVICE;
1906464b714SDaniel Mack 		direction = DMA_DEV_TO_MEM;
1916464b714SDaniel Mack 		chan = host->dma_chan_rx;
1921c6a0718SPierre Ossman 	} else {
1931c6a0718SPierre Ossman 		host->dma_dir = DMA_TO_DEVICE;
1946464b714SDaniel Mack 		direction = DMA_MEM_TO_DEV;
1956464b714SDaniel Mack 		chan = host->dma_chan_tx;
1961c6a0718SPierre Ossman 	}
1971c6a0718SPierre Ossman 
1986464b714SDaniel Mack 	config.direction = direction;
1991c6a0718SPierre Ossman 
2006464b714SDaniel Mack 	ret = dmaengine_slave_config(chan, &config);
2016464b714SDaniel Mack 	if (ret < 0) {
2026464b714SDaniel Mack 		dev_err(mmc_dev(host->mmc), "dma slave config failed\n");
2036464b714SDaniel Mack 		return;
2046464b714SDaniel Mack 	}
2056464b714SDaniel Mack 
2066464b714SDaniel Mack 	host->dma_len = dma_map_sg(chan->device->dev, data->sg, data->sg_len,
2071c6a0718SPierre Ossman 				   host->dma_dir);
2081c6a0718SPierre Ossman 
2096464b714SDaniel Mack 	tx = dmaengine_prep_slave_sg(chan, data->sg, host->dma_len, direction,
2106464b714SDaniel Mack 				     DMA_PREP_INTERRUPT);
2116464b714SDaniel Mack 	if (!tx) {
2126464b714SDaniel Mack 		dev_err(mmc_dev(host->mmc), "prep_slave_sg() failed\n");
2136464b714SDaniel Mack 		return;
2141c6a0718SPierre Ossman 	}
2151c6a0718SPierre Ossman 
2166464b714SDaniel Mack 	if (!(data->flags & MMC_DATA_READ)) {
2176464b714SDaniel Mack 		tx->callback = pxamci_dma_irq;
2186464b714SDaniel Mack 		tx->callback_param = host;
2196464b714SDaniel Mack 	}
2206464b714SDaniel Mack 
2216464b714SDaniel Mack 	host->dma_cookie = dmaengine_submit(tx);
222b6018958SCliff Brake 
223b6018958SCliff Brake 	/*
224b6018958SCliff Brake 	 * workaround for erratum #91:
225b6018958SCliff Brake 	 * only start DMA now if we are doing a read,
226b6018958SCliff Brake 	 * otherwise we wait until CMD/RESP has finished
227b6018958SCliff Brake 	 * before starting DMA.
228b6018958SCliff Brake 	 */
229b6018958SCliff Brake 	if (!cpu_is_pxa27x() || data->flags & MMC_DATA_READ)
2306464b714SDaniel Mack 		dma_async_issue_pending(chan);
2311c6a0718SPierre Ossman }
2321c6a0718SPierre Ossman 
2331c6a0718SPierre Ossman static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat)
2341c6a0718SPierre Ossman {
2351c6a0718SPierre Ossman 	WARN_ON(host->cmd != NULL);
2361c6a0718SPierre Ossman 	host->cmd = cmd;
2371c6a0718SPierre Ossman 
2381c6a0718SPierre Ossman 	if (cmd->flags & MMC_RSP_BUSY)
2391c6a0718SPierre Ossman 		cmdat |= CMDAT_BUSY;
2401c6a0718SPierre Ossman 
2411c6a0718SPierre Ossman #define RSP_TYPE(x)	((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
2421c6a0718SPierre Ossman 	switch (RSP_TYPE(mmc_resp_type(cmd))) {
2431c6a0718SPierre Ossman 	case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6, r7 */
2441c6a0718SPierre Ossman 		cmdat |= CMDAT_RESP_SHORT;
2451c6a0718SPierre Ossman 		break;
2461c6a0718SPierre Ossman 	case RSP_TYPE(MMC_RSP_R3):
2471c6a0718SPierre Ossman 		cmdat |= CMDAT_RESP_R3;
2481c6a0718SPierre Ossman 		break;
2491c6a0718SPierre Ossman 	case RSP_TYPE(MMC_RSP_R2):
2501c6a0718SPierre Ossman 		cmdat |= CMDAT_RESP_R2;
2511c6a0718SPierre Ossman 		break;
2521c6a0718SPierre Ossman 	default:
2531c6a0718SPierre Ossman 		break;
2541c6a0718SPierre Ossman 	}
2551c6a0718SPierre Ossman 
2561c6a0718SPierre Ossman 	writel(cmd->opcode, host->base + MMC_CMD);
2571c6a0718SPierre Ossman 	writel(cmd->arg >> 16, host->base + MMC_ARGH);
2581c6a0718SPierre Ossman 	writel(cmd->arg & 0xffff, host->base + MMC_ARGL);
2591c6a0718SPierre Ossman 	writel(cmdat, host->base + MMC_CMDAT);
2601c6a0718SPierre Ossman 	writel(host->clkrt, host->base + MMC_CLKRT);
2611c6a0718SPierre Ossman 
2621c6a0718SPierre Ossman 	writel(START_CLOCK, host->base + MMC_STRPCL);
2631c6a0718SPierre Ossman 
2641c6a0718SPierre Ossman 	pxamci_enable_irq(host, END_CMD_RES);
2651c6a0718SPierre Ossman }
2661c6a0718SPierre Ossman 
2671c6a0718SPierre Ossman static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq)
2681c6a0718SPierre Ossman {
2691c6a0718SPierre Ossman 	host->mrq = NULL;
2701c6a0718SPierre Ossman 	host->cmd = NULL;
2711c6a0718SPierre Ossman 	host->data = NULL;
2721c6a0718SPierre Ossman 	mmc_request_done(host->mmc, mrq);
2731c6a0718SPierre Ossman }
2741c6a0718SPierre Ossman 
2751c6a0718SPierre Ossman static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)
2761c6a0718SPierre Ossman {
2771c6a0718SPierre Ossman 	struct mmc_command *cmd = host->cmd;
2781c6a0718SPierre Ossman 	int i;
2791c6a0718SPierre Ossman 	u32 v;
2801c6a0718SPierre Ossman 
2811c6a0718SPierre Ossman 	if (!cmd)
2821c6a0718SPierre Ossman 		return 0;
2831c6a0718SPierre Ossman 
2841c6a0718SPierre Ossman 	host->cmd = NULL;
2851c6a0718SPierre Ossman 
2861c6a0718SPierre Ossman 	/*
2871c6a0718SPierre Ossman 	 * Did I mention this is Sick.  We always need to
2881c6a0718SPierre Ossman 	 * discard the upper 8 bits of the first 16-bit word.
2891c6a0718SPierre Ossman 	 */
2901c6a0718SPierre Ossman 	v = readl(host->base + MMC_RES) & 0xffff;
2911c6a0718SPierre Ossman 	for (i = 0; i < 4; i++) {
2921c6a0718SPierre Ossman 		u32 w1 = readl(host->base + MMC_RES) & 0xffff;
2931c6a0718SPierre Ossman 		u32 w2 = readl(host->base + MMC_RES) & 0xffff;
2941c6a0718SPierre Ossman 		cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8;
2951c6a0718SPierre Ossman 		v = w2;
2961c6a0718SPierre Ossman 	}
2971c6a0718SPierre Ossman 
2981c6a0718SPierre Ossman 	if (stat & STAT_TIME_OUT_RESPONSE) {
29917b0429dSPierre Ossman 		cmd->error = -ETIMEDOUT;
3001c6a0718SPierre Ossman 	} else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
3011c6a0718SPierre Ossman 		/*
3021c6a0718SPierre Ossman 		 * workaround for erratum #42:
3031c6a0718SPierre Ossman 		 * Intel PXA27x Family Processor Specification Update Rev 001
30490e07d9fSNicolas Pitre 		 * A bogus CRC error can appear if the msb of a 136 bit
30590e07d9fSNicolas Pitre 		 * response is a one.
3061c6a0718SPierre Ossman 		 */
307e10a854cSCliff Brake 		if (cpu_is_pxa27x() &&
308e10a854cSCliff Brake 		    (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000))
3091c6a0718SPierre Ossman 			pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode);
310e10a854cSCliff Brake 		else
31117b0429dSPierre Ossman 			cmd->error = -EILSEQ;
3121c6a0718SPierre Ossman 	}
3131c6a0718SPierre Ossman 
3141c6a0718SPierre Ossman 	pxamci_disable_irq(host, END_CMD_RES);
31517b0429dSPierre Ossman 	if (host->data && !cmd->error) {
3161c6a0718SPierre Ossman 		pxamci_enable_irq(host, DATA_TRAN_DONE);
317b6018958SCliff Brake 		/*
318b6018958SCliff Brake 		 * workaround for erratum #91, if doing write
319b6018958SCliff Brake 		 * enable DMA late
320b6018958SCliff Brake 		 */
321b6018958SCliff Brake 		if (cpu_is_pxa27x() && host->data->flags & MMC_DATA_WRITE)
3226464b714SDaniel Mack 			dma_async_issue_pending(host->dma_chan_tx);
3231c6a0718SPierre Ossman 	} else {
3241c6a0718SPierre Ossman 		pxamci_finish_request(host, host->mrq);
3251c6a0718SPierre Ossman 	}
3261c6a0718SPierre Ossman 
3271c6a0718SPierre Ossman 	return 1;
3281c6a0718SPierre Ossman }
3291c6a0718SPierre Ossman 
3301c6a0718SPierre Ossman static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
3311c6a0718SPierre Ossman {
3321c6a0718SPierre Ossman 	struct mmc_data *data = host->data;
3336464b714SDaniel Mack 	struct dma_chan *chan;
3341c6a0718SPierre Ossman 
3351c6a0718SPierre Ossman 	if (!data)
3361c6a0718SPierre Ossman 		return 0;
3371c6a0718SPierre Ossman 
3386464b714SDaniel Mack 	if (data->flags & MMC_DATA_READ)
3396464b714SDaniel Mack 		chan = host->dma_chan_rx;
3406464b714SDaniel Mack 	else
3416464b714SDaniel Mack 		chan = host->dma_chan_tx;
3426464b714SDaniel Mack 	dma_unmap_sg(chan->device->dev,
3436464b714SDaniel Mack 		     data->sg, data->sg_len, host->dma_dir);
3441c6a0718SPierre Ossman 
3451c6a0718SPierre Ossman 	if (stat & STAT_READ_TIME_OUT)
34617b0429dSPierre Ossman 		data->error = -ETIMEDOUT;
3471c6a0718SPierre Ossman 	else if (stat & (STAT_CRC_READ_ERROR|STAT_CRC_WRITE_ERROR))
34817b0429dSPierre Ossman 		data->error = -EILSEQ;
3491c6a0718SPierre Ossman 
3501c6a0718SPierre Ossman 	/*
3511c6a0718SPierre Ossman 	 * There appears to be a hardware design bug here.  There seems to
3521c6a0718SPierre Ossman 	 * be no way to find out how much data was transferred to the card.
3531c6a0718SPierre Ossman 	 * This means that if there was an error on any block, we mark all
3541c6a0718SPierre Ossman 	 * data blocks as being in error.
3551c6a0718SPierre Ossman 	 */
35617b0429dSPierre Ossman 	if (!data->error)
3571c6a0718SPierre Ossman 		data->bytes_xfered = data->blocks * data->blksz;
3581c6a0718SPierre Ossman 	else
3591c6a0718SPierre Ossman 		data->bytes_xfered = 0;
3601c6a0718SPierre Ossman 
3611c6a0718SPierre Ossman 	pxamci_disable_irq(host, DATA_TRAN_DONE);
3621c6a0718SPierre Ossman 
3631c6a0718SPierre Ossman 	host->data = NULL;
3641c6a0718SPierre Ossman 	if (host->mrq->stop) {
3651c6a0718SPierre Ossman 		pxamci_stop_clock(host);
366df456f47SBridge Wu 		pxamci_start_cmd(host, host->mrq->stop, host->cmdat);
3671c6a0718SPierre Ossman 	} else {
3681c6a0718SPierre Ossman 		pxamci_finish_request(host, host->mrq);
3691c6a0718SPierre Ossman 	}
3701c6a0718SPierre Ossman 
3711c6a0718SPierre Ossman 	return 1;
3721c6a0718SPierre Ossman }
3731c6a0718SPierre Ossman 
3741c6a0718SPierre Ossman static irqreturn_t pxamci_irq(int irq, void *devid)
3751c6a0718SPierre Ossman {
3761c6a0718SPierre Ossman 	struct pxamci_host *host = devid;
3771c6a0718SPierre Ossman 	unsigned int ireg;
3781c6a0718SPierre Ossman 	int handled = 0;
3791c6a0718SPierre Ossman 
38081ab570fSBridge Wu 	ireg = readl(host->base + MMC_I_REG) & ~readl(host->base + MMC_I_MASK);
3811c6a0718SPierre Ossman 
3821c6a0718SPierre Ossman 	if (ireg) {
3831c6a0718SPierre Ossman 		unsigned stat = readl(host->base + MMC_STAT);
3841c6a0718SPierre Ossman 
3851c6a0718SPierre Ossman 		pr_debug("PXAMCI: irq %08x stat %08x\n", ireg, stat);
3861c6a0718SPierre Ossman 
3871c6a0718SPierre Ossman 		if (ireg & END_CMD_RES)
3881c6a0718SPierre Ossman 			handled |= pxamci_cmd_done(host, stat);
3891c6a0718SPierre Ossman 		if (ireg & DATA_TRAN_DONE)
3901c6a0718SPierre Ossman 			handled |= pxamci_data_done(host, stat);
3915d3ad4e8SBridge Wu 		if (ireg & SDIO_INT) {
3925d3ad4e8SBridge Wu 			mmc_signal_sdio_irq(host->mmc);
3935d3ad4e8SBridge Wu 			handled = 1;
3945d3ad4e8SBridge Wu 		}
3951c6a0718SPierre Ossman 	}
3961c6a0718SPierre Ossman 
3971c6a0718SPierre Ossman 	return IRQ_RETVAL(handled);
3981c6a0718SPierre Ossman }
3991c6a0718SPierre Ossman 
4001c6a0718SPierre Ossman static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq)
4011c6a0718SPierre Ossman {
4021c6a0718SPierre Ossman 	struct pxamci_host *host = mmc_priv(mmc);
4031c6a0718SPierre Ossman 	unsigned int cmdat;
4041c6a0718SPierre Ossman 
4051c6a0718SPierre Ossman 	WARN_ON(host->mrq != NULL);
4061c6a0718SPierre Ossman 
4071c6a0718SPierre Ossman 	host->mrq = mrq;
4081c6a0718SPierre Ossman 
4091c6a0718SPierre Ossman 	pxamci_stop_clock(host);
4101c6a0718SPierre Ossman 
4111c6a0718SPierre Ossman 	cmdat = host->cmdat;
4121c6a0718SPierre Ossman 	host->cmdat &= ~CMDAT_INIT;
4131c6a0718SPierre Ossman 
4141c6a0718SPierre Ossman 	if (mrq->data) {
4151c6a0718SPierre Ossman 		pxamci_setup_data(host, mrq->data);
4161c6a0718SPierre Ossman 
4171c6a0718SPierre Ossman 		cmdat &= ~CMDAT_BUSY;
4181c6a0718SPierre Ossman 		cmdat |= CMDAT_DATAEN | CMDAT_DMAEN;
4191c6a0718SPierre Ossman 		if (mrq->data->flags & MMC_DATA_WRITE)
4201c6a0718SPierre Ossman 			cmdat |= CMDAT_WRITE;
4211c6a0718SPierre Ossman 	}
4221c6a0718SPierre Ossman 
4231c6a0718SPierre Ossman 	pxamci_start_cmd(host, mrq->cmd, cmdat);
4241c6a0718SPierre Ossman }
4251c6a0718SPierre Ossman 
4261c6a0718SPierre Ossman static int pxamci_get_ro(struct mmc_host *mmc)
4271c6a0718SPierre Ossman {
4281c6a0718SPierre Ossman 	struct pxamci_host *host = mmc_priv(mmc);
4291c6a0718SPierre Ossman 
430c914a27cSLinus Walleij 	if (host->use_ro_gpio)
431fd546ee6SRobert Jarzmik 		return mmc_gpio_get_ro(mmc);
4321c6a0718SPierre Ossman 	if (host->pdata && host->pdata->get_ro)
43308f80bb5SAnton Vorontsov 		return !!host->pdata->get_ro(mmc_dev(mmc));
43408f80bb5SAnton Vorontsov 	/*
43508f80bb5SAnton Vorontsov 	 * Board doesn't support read only detection; let the mmc core
43608f80bb5SAnton Vorontsov 	 * decide what to do.
43708f80bb5SAnton Vorontsov 	 */
43808f80bb5SAnton Vorontsov 	return -ENOSYS;
4391c6a0718SPierre Ossman }
4401c6a0718SPierre Ossman 
4411c6a0718SPierre Ossman static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
4421c6a0718SPierre Ossman {
4431c6a0718SPierre Ossman 	struct pxamci_host *host = mmc_priv(mmc);
4441c6a0718SPierre Ossman 
4451c6a0718SPierre Ossman 	if (ios->clock) {
446ebebd9b0SRussell King 		unsigned long rate = host->clkrate;
447ebebd9b0SRussell King 		unsigned int clk = rate / ios->clock;
448ebebd9b0SRussell King 
449d8cb70d1SRussell King 		if (host->clkrt == CLKRT_OFF)
450e7370819SRobert Jarzmik 			clk_prepare_enable(host->clk);
451d8cb70d1SRussell King 
45264eb036aSBridge Wu 		if (ios->clock == 26000000) {
453fa3f9938SHaojian Zhuang 			/* to support 26MHz */
45464eb036aSBridge Wu 			host->clkrt = 7;
45564eb036aSBridge Wu 		} else {
45664eb036aSBridge Wu 			/* to handle (19.5MHz, 26MHz) */
45764eb036aSBridge Wu 			if (!clk)
45864eb036aSBridge Wu 				clk = 1;
45964eb036aSBridge Wu 
460ebebd9b0SRussell King 			/*
461ebebd9b0SRussell King 			 * clk might result in a lower divisor than we
462ebebd9b0SRussell King 			 * desire.  check for that condition and adjust
463ebebd9b0SRussell King 			 * as appropriate.
464ebebd9b0SRussell King 			 */
465ebebd9b0SRussell King 			if (rate / clk > ios->clock)
4661c6a0718SPierre Ossman 				clk <<= 1;
4671c6a0718SPierre Ossman 			host->clkrt = fls(clk) - 1;
46864eb036aSBridge Wu 		}
4691c6a0718SPierre Ossman 
4701c6a0718SPierre Ossman 		/*
4711c6a0718SPierre Ossman 		 * we write clkrt on the next command
4721c6a0718SPierre Ossman 		 */
4731c6a0718SPierre Ossman 	} else {
4741c6a0718SPierre Ossman 		pxamci_stop_clock(host);
475d8cb70d1SRussell King 		if (host->clkrt != CLKRT_OFF) {
476d8cb70d1SRussell King 			host->clkrt = CLKRT_OFF;
477e7370819SRobert Jarzmik 			clk_disable_unprepare(host->clk);
4781c6a0718SPierre Ossman 		}
479d8cb70d1SRussell King 	}
4801c6a0718SPierre Ossman 
4811c6a0718SPierre Ossman 	if (host->power_mode != ios->power_mode) {
48299fc5131SLinus Walleij 		int ret;
48399fc5131SLinus Walleij 
4841c6a0718SPierre Ossman 		host->power_mode = ios->power_mode;
4851c6a0718SPierre Ossman 
48699fc5131SLinus Walleij 		ret = pxamci_set_power(host, ios->power_mode, ios->vdd);
48799fc5131SLinus Walleij 		if (ret) {
48899fc5131SLinus Walleij 			dev_err(mmc_dev(mmc), "unable to set power\n");
48999fc5131SLinus Walleij 			/*
49099fc5131SLinus Walleij 			 * The .set_ios() function in the mmc_host_ops
49199fc5131SLinus Walleij 			 * struct return void, and failing to set the
49299fc5131SLinus Walleij 			 * power should be rare so we print an error and
49399fc5131SLinus Walleij 			 * return here.
49499fc5131SLinus Walleij 			 */
49599fc5131SLinus Walleij 			return;
49699fc5131SLinus Walleij 		}
4971c6a0718SPierre Ossman 
4981c6a0718SPierre Ossman 		if (ios->power_mode == MMC_POWER_ON)
4991c6a0718SPierre Ossman 			host->cmdat |= CMDAT_INIT;
5001c6a0718SPierre Ossman 	}
5011c6a0718SPierre Ossman 
502df456f47SBridge Wu 	if (ios->bus_width == MMC_BUS_WIDTH_4)
503df456f47SBridge Wu 		host->cmdat |= CMDAT_SD_4DAT;
504df456f47SBridge Wu 	else
505df456f47SBridge Wu 		host->cmdat &= ~CMDAT_SD_4DAT;
506df456f47SBridge Wu 
50799fc5131SLinus Walleij 	dev_dbg(mmc_dev(mmc), "PXAMCI: clkrt = %x cmdat = %x\n",
5081c6a0718SPierre Ossman 		host->clkrt, host->cmdat);
5091c6a0718SPierre Ossman }
5101c6a0718SPierre Ossman 
5115d3ad4e8SBridge Wu static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable)
5125d3ad4e8SBridge Wu {
5135d3ad4e8SBridge Wu 	struct pxamci_host *pxa_host = mmc_priv(host);
5145d3ad4e8SBridge Wu 
5155d3ad4e8SBridge Wu 	if (enable)
5165d3ad4e8SBridge Wu 		pxamci_enable_irq(pxa_host, SDIO_INT);
5175d3ad4e8SBridge Wu 	else
5185d3ad4e8SBridge Wu 		pxamci_disable_irq(pxa_host, SDIO_INT);
5195d3ad4e8SBridge Wu }
5205d3ad4e8SBridge Wu 
5211c6a0718SPierre Ossman static const struct mmc_host_ops pxamci_ops = {
5221c6a0718SPierre Ossman 	.request		= pxamci_request,
523fd546ee6SRobert Jarzmik 	.get_cd			= mmc_gpio_get_cd,
5241c6a0718SPierre Ossman 	.get_ro			= pxamci_get_ro,
5251c6a0718SPierre Ossman 	.set_ios		= pxamci_set_ios,
5265d3ad4e8SBridge Wu 	.enable_sdio_irq	= pxamci_enable_sdio_irq,
5271c6a0718SPierre Ossman };
5281c6a0718SPierre Ossman 
5296464b714SDaniel Mack static void pxamci_dma_irq(void *param)
5301c6a0718SPierre Ossman {
5316464b714SDaniel Mack 	struct pxamci_host *host = param;
5326464b714SDaniel Mack 	struct dma_tx_state state;
5336464b714SDaniel Mack 	enum dma_status status;
5346464b714SDaniel Mack 	struct dma_chan *chan;
5356464b714SDaniel Mack 	unsigned long flags;
536c783837bSNicolas Pitre 
5376464b714SDaniel Mack 	spin_lock_irqsave(&host->lock, flags);
5386464b714SDaniel Mack 
5396464b714SDaniel Mack 	if (!host->data)
5406464b714SDaniel Mack 		goto out_unlock;
5416464b714SDaniel Mack 
5426464b714SDaniel Mack 	if (host->data->flags & MMC_DATA_READ)
5436464b714SDaniel Mack 		chan = host->dma_chan_rx;
5446464b714SDaniel Mack 	else
5456464b714SDaniel Mack 		chan = host->dma_chan_tx;
5466464b714SDaniel Mack 
5476464b714SDaniel Mack 	status = dmaengine_tx_status(chan, host->dma_cookie, &state);
5486464b714SDaniel Mack 
5496464b714SDaniel Mack 	if (likely(status == DMA_COMPLETE)) {
550c783837bSNicolas Pitre 		writel(BUF_PART_FULL, host->base + MMC_PRTBUF);
551c783837bSNicolas Pitre 	} else {
5526464b714SDaniel Mack 		pr_err("%s: DMA error on %s channel\n", mmc_hostname(host->mmc),
5536464b714SDaniel Mack 			host->data->flags & MMC_DATA_READ ? "rx" : "tx");
554c783837bSNicolas Pitre 		host->data->error = -EIO;
555c783837bSNicolas Pitre 		pxamci_data_done(host, 0);
556c783837bSNicolas Pitre 	}
5576464b714SDaniel Mack 
5586464b714SDaniel Mack out_unlock:
5596464b714SDaniel Mack 	spin_unlock_irqrestore(&host->lock, flags);
5601c6a0718SPierre Ossman }
5611c6a0718SPierre Ossman 
5621c6a0718SPierre Ossman static irqreturn_t pxamci_detect_irq(int irq, void *devid)
5631c6a0718SPierre Ossman {
5641c6a0718SPierre Ossman 	struct pxamci_host *host = mmc_priv(devid);
5651c6a0718SPierre Ossman 
56638a8dda9SDaniel Mack 	mmc_detect_change(devid, msecs_to_jiffies(host->detect_delay_ms));
5671c6a0718SPierre Ossman 	return IRQ_HANDLED;
5681c6a0718SPierre Ossman }
5691c6a0718SPierre Ossman 
570e6027b46SDaniel Mack #ifdef CONFIG_OF
571e6027b46SDaniel Mack static const struct of_device_id pxa_mmc_dt_ids[] = {
572e6027b46SDaniel Mack         { .compatible = "marvell,pxa-mmc" },
573e6027b46SDaniel Mack         { }
574e6027b46SDaniel Mack };
575e6027b46SDaniel Mack 
576e6027b46SDaniel Mack MODULE_DEVICE_TABLE(of, pxa_mmc_dt_ids);
577e6027b46SDaniel Mack 
578fa3a5115SDaniel Mack static int pxamci_of_init(struct platform_device *pdev,
579fa3a5115SDaniel Mack 			  struct mmc_host *mmc)
580e6027b46SDaniel Mack {
581e6027b46SDaniel Mack 	struct device_node *np = pdev->dev.of_node;
58238a8dda9SDaniel Mack 	struct pxamci_host *host = mmc_priv(mmc);
583e6027b46SDaniel Mack 	u32 tmp;
584fa3a5115SDaniel Mack 	int ret;
585e6027b46SDaniel Mack 
586e6027b46SDaniel Mack 	if (!np)
587e6027b46SDaniel Mack 		return 0;
588e6027b46SDaniel Mack 
589e6027b46SDaniel Mack 	/* pxa-mmc specific */
590e6027b46SDaniel Mack 	if (of_property_read_u32(np, "pxa-mmc,detect-delay-ms", &tmp) == 0)
59138a8dda9SDaniel Mack 		host->detect_delay_ms = tmp;
592e6027b46SDaniel Mack 
593fa3a5115SDaniel Mack 	ret = mmc_of_parse(mmc);
594fa3a5115SDaniel Mack 	if (ret < 0)
595fa3a5115SDaniel Mack 		return ret;
596fa3a5115SDaniel Mack 
597e6027b46SDaniel Mack 	return 0;
598e6027b46SDaniel Mack }
599e6027b46SDaniel Mack #else
600fa3a5115SDaniel Mack static int pxamci_of_init(struct platform_device *pdev,
601fa3a5115SDaniel Mack 			  struct mmc_host *mmc)
602e6027b46SDaniel Mack {
603e6027b46SDaniel Mack         return 0;
604e6027b46SDaniel Mack }
605e6027b46SDaniel Mack #endif
606e6027b46SDaniel Mack 
6071c6a0718SPierre Ossman static int pxamci_probe(struct platform_device *pdev)
6081c6a0718SPierre Ossman {
6091c6a0718SPierre Ossman 	struct mmc_host *mmc;
6101c6a0718SPierre Ossman 	struct pxamci_host *host = NULL;
61123f3ff72SDaniel Mack 	struct device *dev = &pdev->dev;
6126b3348f9SRobert Jarzmik 	struct resource *r;
61338a8dda9SDaniel Mack 	int ret, irq;
6141c6a0718SPierre Ossman 
6151c6a0718SPierre Ossman 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
6161c6a0718SPierre Ossman 	irq = platform_get_irq(pdev, 0);
61707e7716cSRobert Jarzmik 	if (irq < 0)
61807e7716cSRobert Jarzmik 		return irq;
6191c6a0718SPierre Ossman 
62023f3ff72SDaniel Mack 	mmc = mmc_alloc_host(sizeof(struct pxamci_host), dev);
6211c6a0718SPierre Ossman 	if (!mmc) {
6221c6a0718SPierre Ossman 		ret = -ENOMEM;
6231c6a0718SPierre Ossman 		goto out;
6241c6a0718SPierre Ossman 	}
6251c6a0718SPierre Ossman 
6261c6a0718SPierre Ossman 	mmc->ops = &pxamci_ops;
6271c6a0718SPierre Ossman 
6281c6a0718SPierre Ossman 	/*
6291c6a0718SPierre Ossman 	 * We can do SG-DMA, but we don't because we never know how much
6301c6a0718SPierre Ossman 	 * data we successfully wrote to the card.
6311c6a0718SPierre Ossman 	 */
632a36274e0SMartin K. Petersen 	mmc->max_segs = NR_SG;
6331c6a0718SPierre Ossman 
6341c6a0718SPierre Ossman 	/*
6351c6a0718SPierre Ossman 	 * Our hardware DMA can handle a maximum of one page per SG entry.
6361c6a0718SPierre Ossman 	 */
6371c6a0718SPierre Ossman 	mmc->max_seg_size = PAGE_SIZE;
6381c6a0718SPierre Ossman 
6391c6a0718SPierre Ossman 	/*
640fe2dc44eSNicolas Pitre 	 * Block length register is only 10 bits before PXA27x.
6411c6a0718SPierre Ossman 	 */
6420ffcbfd5SEric Miao 	mmc->max_blk_size = cpu_is_pxa25x() ? 1023 : 2048;
6431c6a0718SPierre Ossman 
6441c6a0718SPierre Ossman 	/*
6451c6a0718SPierre Ossman 	 * Block count register is 16 bits.
6461c6a0718SPierre Ossman 	 */
6471c6a0718SPierre Ossman 	mmc->max_blk_count = 65535;
6481c6a0718SPierre Ossman 
649fa3a5115SDaniel Mack 	ret = pxamci_of_init(pdev, mmc);
650fa3a5115SDaniel Mack 	if (ret)
651fa3a5115SDaniel Mack 		return ret;
652fa3a5115SDaniel Mack 
6531c6a0718SPierre Ossman 	host = mmc_priv(mmc);
6541c6a0718SPierre Ossman 	host->mmc = mmc;
6551c6a0718SPierre Ossman 	host->pdata = pdev->dev.platform_data;
656d8cb70d1SRussell King 	host->clkrt = CLKRT_OFF;
657ebebd9b0SRussell King 
65823f3ff72SDaniel Mack 	host->clk = devm_clk_get(dev, NULL);
659ebebd9b0SRussell King 	if (IS_ERR(host->clk)) {
660ebebd9b0SRussell King 		ret = PTR_ERR(host->clk);
661ebebd9b0SRussell King 		host->clk = NULL;
662ebebd9b0SRussell King 		goto out;
663ebebd9b0SRussell King 	}
664ebebd9b0SRussell King 
665ebebd9b0SRussell King 	host->clkrate = clk_get_rate(host->clk);
666ebebd9b0SRussell King 
667ebebd9b0SRussell King 	/*
668ebebd9b0SRussell King 	 * Calculate minimum clock rate, rounding up.
669ebebd9b0SRussell King 	 */
670ebebd9b0SRussell King 	mmc->f_min = (host->clkrate + 63) / 64;
671fa3f9938SHaojian Zhuang 	mmc->f_max = (mmc_has_26MHz()) ? 26000000 : host->clkrate;
672ebebd9b0SRussell King 
67361951fd6SDaniel Mack 	ret = pxamci_init_ocr(host);
67461951fd6SDaniel Mack 	if (ret < 0)
67561951fd6SDaniel Mack 		return ret;
6768385f9cbSDaniel Ribeiro 
677de3ee99bSLinus Walleij 	mmc->caps = 0;
6785d3ad4e8SBridge Wu 	host->cmdat = 0;
6790ffcbfd5SEric Miao 	if (!cpu_is_pxa25x()) {
6805d3ad4e8SBridge Wu 		mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
6815d3ad4e8SBridge Wu 		host->cmdat |= CMDAT_SDIO_INT_EN;
682fa3f9938SHaojian Zhuang 		if (mmc_has_26MHz())
68364eb036aSBridge Wu 			mmc->caps |= MMC_CAP_MMC_HIGHSPEED |
68464eb036aSBridge Wu 				     MMC_CAP_SD_HIGHSPEED;
6855d3ad4e8SBridge Wu 	}
6861c6a0718SPierre Ossman 
6871c6a0718SPierre Ossman 	spin_lock_init(&host->lock);
6881c6a0718SPierre Ossman 	host->res = r;
6891c6a0718SPierre Ossman 	host->imask = MMC_I_MASK_ALL;
6901c6a0718SPierre Ossman 
69123f3ff72SDaniel Mack 	host->base = devm_ioremap_resource(dev, r);
69207e7716cSRobert Jarzmik 	if (IS_ERR(host->base)) {
69307e7716cSRobert Jarzmik 		ret = PTR_ERR(host->base);
6941c6a0718SPierre Ossman 		goto out;
6951c6a0718SPierre Ossman 	}
6961c6a0718SPierre Ossman 
6971c6a0718SPierre Ossman 	/*
6981c6a0718SPierre Ossman 	 * Ensure that the host controller is shut down, and setup
6991c6a0718SPierre Ossman 	 * with our defaults.
7001c6a0718SPierre Ossman 	 */
7011c6a0718SPierre Ossman 	pxamci_stop_clock(host);
7021c6a0718SPierre Ossman 	writel(0, host->base + MMC_SPI);
7031c6a0718SPierre Ossman 	writel(64, host->base + MMC_RESTO);
7041c6a0718SPierre Ossman 	writel(host->imask, host->base + MMC_I_MASK);
7051c6a0718SPierre Ossman 
70623f3ff72SDaniel Mack 	ret = devm_request_irq(dev, irq, pxamci_irq, 0,
70707e7716cSRobert Jarzmik 			       DRIVER_NAME, host);
7081c6a0718SPierre Ossman 	if (ret)
7091c6a0718SPierre Ossman 		goto out;
7101c6a0718SPierre Ossman 
7111c6a0718SPierre Ossman 	platform_set_drvdata(pdev, mmc);
7121c6a0718SPierre Ossman 
713e1ebb456SPeter Ujfalusi 	host->dma_chan_rx = dma_request_chan(dev, "rx");
714e1ebb456SPeter Ujfalusi 	if (IS_ERR(host->dma_chan_rx)) {
71523f3ff72SDaniel Mack 		dev_err(dev, "unable to request rx dma channel\n");
716e1ebb456SPeter Ujfalusi 		ret = PTR_ERR(host->dma_chan_rx);
717e1ebb456SPeter Ujfalusi 		host->dma_chan_rx = NULL;
7186464b714SDaniel Mack 		goto out;
7196464b714SDaniel Mack 	}
7206464b714SDaniel Mack 
721e1ebb456SPeter Ujfalusi 	host->dma_chan_tx = dma_request_chan(dev, "tx");
722e1ebb456SPeter Ujfalusi 	if (IS_ERR(host->dma_chan_tx)) {
72323f3ff72SDaniel Mack 		dev_err(dev, "unable to request tx dma channel\n");
724e1ebb456SPeter Ujfalusi 		ret = PTR_ERR(host->dma_chan_tx);
725e1ebb456SPeter Ujfalusi 		host->dma_chan_tx = NULL;
7266464b714SDaniel Mack 		goto out;
7276464b714SDaniel Mack 	}
7289a788c6bSBridge Wu 
729b405db6cSRobert Jarzmik 	if (host->pdata) {
73038a8dda9SDaniel Mack 		host->detect_delay_ms = host->pdata->detect_delay_ms;
73138a8dda9SDaniel Mack 
732f54005b5SLinus Walleij 		host->power = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
733f54005b5SLinus Walleij 		if (IS_ERR(host->power)) {
734f54005b5SLinus Walleij 			dev_err(dev, "Failed requesting gpio_power\n");
735b405db6cSRobert Jarzmik 			goto out;
736b405db6cSRobert Jarzmik 		}
73738a8dda9SDaniel Mack 
738c914a27cSLinus Walleij 		/* FIXME: should we pass detection delay to debounce? */
739d0052ad9SMichał Mirosław 		ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0);
740c914a27cSLinus Walleij 		if (ret && ret != -ENOENT) {
741c914a27cSLinus Walleij 			dev_err(dev, "Failed requesting gpio_cd\n");
742c914a27cSLinus Walleij 			goto out;
743c914a27cSLinus Walleij 		}
744c914a27cSLinus Walleij 
7459073d10bSMichał Mirosław 		if (!host->pdata->gpio_card_ro_invert)
7469073d10bSMichał Mirosław 			mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
7479073d10bSMichał Mirosław 
748d0052ad9SMichał Mirosław 		ret = mmc_gpiod_request_ro(mmc, "wp", 0, 0);
749c914a27cSLinus Walleij 		if (ret && ret != -ENOENT) {
750c914a27cSLinus Walleij 			dev_err(dev, "Failed requesting gpio_ro\n");
751c914a27cSLinus Walleij 			goto out;
752c914a27cSLinus Walleij 		}
7539073d10bSMichał Mirosław 		if (!ret)
754c914a27cSLinus Walleij 			host->use_ro_gpio = true;
755b405db6cSRobert Jarzmik 
75638a8dda9SDaniel Mack 		if (host->pdata->init)
75723f3ff72SDaniel Mack 			host->pdata->init(dev, pxamci_detect_irq, mmc);
7581c6a0718SPierre Ossman 
759f54005b5SLinus Walleij 		if (host->power && host->pdata->setpower)
76023f3ff72SDaniel Mack 			dev_warn(dev, "gpio_power and setpower() both defined\n");
761c914a27cSLinus Walleij 		if (host->use_ro_gpio && host->pdata->get_ro)
76223f3ff72SDaniel Mack 			dev_warn(dev, "gpio_ro and get_ro() both defined\n");
76338a8dda9SDaniel Mack 	}
764b405db6cSRobert Jarzmik 
7651c6a0718SPierre Ossman 	mmc_add_host(mmc);
7661c6a0718SPierre Ossman 
7671c6a0718SPierre Ossman 	return 0;
7681c6a0718SPierre Ossman 
7691c6a0718SPierre Ossman out:
7701c6a0718SPierre Ossman 	if (host) {
7716464b714SDaniel Mack 		if (host->dma_chan_rx)
7726464b714SDaniel Mack 			dma_release_channel(host->dma_chan_rx);
7736464b714SDaniel Mack 		if (host->dma_chan_tx)
7746464b714SDaniel Mack 			dma_release_channel(host->dma_chan_tx);
7751c6a0718SPierre Ossman 	}
7761c6a0718SPierre Ossman 	if (mmc)
7771c6a0718SPierre Ossman 		mmc_free_host(mmc);
7781c6a0718SPierre Ossman 	return ret;
7791c6a0718SPierre Ossman }
7801c6a0718SPierre Ossman 
7811c6a0718SPierre Ossman static int pxamci_remove(struct platform_device *pdev)
7821c6a0718SPierre Ossman {
7831c6a0718SPierre Ossman 	struct mmc_host *mmc = platform_get_drvdata(pdev);
7841c6a0718SPierre Ossman 
7851c6a0718SPierre Ossman 	if (mmc) {
7861c6a0718SPierre Ossman 		struct pxamci_host *host = mmc_priv(mmc);
7871c6a0718SPierre Ossman 
7885d6b1edfSDaniel Mack 		mmc_remove_host(mmc);
7895d6b1edfSDaniel Mack 
7901c6a0718SPierre Ossman 		if (host->pdata && host->pdata->exit)
7911c6a0718SPierre Ossman 			host->pdata->exit(&pdev->dev, mmc);
7921c6a0718SPierre Ossman 
7931c6a0718SPierre Ossman 		pxamci_stop_clock(host);
7941c6a0718SPierre Ossman 		writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD|
7951c6a0718SPierre Ossman 		       END_CMD_RES|PRG_DONE|DATA_TRAN_DONE,
7961c6a0718SPierre Ossman 		       host->base + MMC_I_MASK);
7971c6a0718SPierre Ossman 
7986464b714SDaniel Mack 		dmaengine_terminate_all(host->dma_chan_rx);
7996464b714SDaniel Mack 		dmaengine_terminate_all(host->dma_chan_tx);
8006464b714SDaniel Mack 		dma_release_channel(host->dma_chan_rx);
8016464b714SDaniel Mack 		dma_release_channel(host->dma_chan_tx);
8021c6a0718SPierre Ossman 
8031c6a0718SPierre Ossman 		mmc_free_host(mmc);
8041c6a0718SPierre Ossman 	}
80552c09186SDaniel Mack 
8061c6a0718SPierre Ossman 	return 0;
8071c6a0718SPierre Ossman }
8081c6a0718SPierre Ossman 
8091c6a0718SPierre Ossman static struct platform_driver pxamci_driver = {
8101c6a0718SPierre Ossman 	.probe		= pxamci_probe,
8111c6a0718SPierre Ossman 	.remove		= pxamci_remove,
8121c6a0718SPierre Ossman 	.driver		= {
8131c6a0718SPierre Ossman 		.name	= DRIVER_NAME,
81421b2cec6SDouglas Anderson 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
815e6027b46SDaniel Mack 		.of_match_table = of_match_ptr(pxa_mmc_dt_ids),
8161c6a0718SPierre Ossman 	},
8171c6a0718SPierre Ossman };
8181c6a0718SPierre Ossman 
819d1f81a64SAxel Lin module_platform_driver(pxamci_driver);
8201c6a0718SPierre Ossman 
8211c6a0718SPierre Ossman MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver");
8221c6a0718SPierre Ossman MODULE_LICENSE("GPL");
823bc65c724SKay Sievers MODULE_ALIAS("platform:pxa2xx-mci");
824