pxamci.c 16.5 KB
Newer Older
L
Linus Torvalds 已提交
1
/*
P
Pierre Ossman 已提交
2
 *  linux/drivers/mmc/host/pxa.c - PXA MMCI driver
L
Linus Torvalds 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 *  Copyright (C) 2003 Russell King, All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  This hardware is really sick:
 *   - No way to clear interrupts.
 *   - Have to turn off the clock whenever we touch the device.
 *   - Doesn't tell you how many data blocks were transferred.
 *  Yuck!
 *
 *	1 and 3 byte data transfers not supported
 *	max block length up to 1023
 */
#include <linux/module.h>
#include <linux/init.h>
#include <linux/ioport.h>
22
#include <linux/platform_device.h>
L
Linus Torvalds 已提交
23 24 25
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
26 27
#include <linux/clk.h>
#include <linux/err.h>
L
Linus Torvalds 已提交
28
#include <linux/mmc/host.h>
29
#include <linux/io.h>
L
Linus Torvalds 已提交
30 31 32 33

#include <asm/dma.h>
#include <asm/sizes.h>

34
#include <mach/hardware.h>
35 36
#include <mach/pxa-regs.h>
#include <mach/mmc.h>
L
Linus Torvalds 已提交
37 38 39 40 41 42

#include "pxamci.h"

#define DRIVER_NAME	"pxa2xx-mci"

#define NR_SG	1
R
Russell King 已提交
43
#define CLKRT_OFF	(~0)
L
Linus Torvalds 已提交
44 45 46 47 48 49

struct pxamci_host {
	struct mmc_host		*mmc;
	spinlock_t		lock;
	struct resource		*res;
	void __iomem		*base;
50 51
	struct clk		*clk;
	unsigned long		clkrate;
L
Linus Torvalds 已提交
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
	int			irq;
	int			dma;
	unsigned int		clkrt;
	unsigned int		cmdat;
	unsigned int		imask;
	unsigned int		power_mode;
	struct pxamci_platform_data *pdata;

	struct mmc_request	*mrq;
	struct mmc_command	*cmd;
	struct mmc_data		*data;

	dma_addr_t		sg_dma;
	struct pxa_dma_desc	*sg_cpu;
	unsigned int		dma_len;

	unsigned int		dma_dir;
69 70
	unsigned int		dma_drcmrrx;
	unsigned int		dma_drcmrtx;
L
Linus Torvalds 已提交
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
};

static void pxamci_stop_clock(struct pxamci_host *host)
{
	if (readl(host->base + MMC_STAT) & STAT_CLK_EN) {
		unsigned long timeout = 10000;
		unsigned int v;

		writel(STOP_CLOCK, host->base + MMC_STRPCL);

		do {
			v = readl(host->base + MMC_STAT);
			if (!(v & STAT_CLK_EN))
				break;
			udelay(1);
		} while (timeout--);

		if (v & STAT_CLK_EN)
			dev_err(mmc_dev(host->mmc), "unable to stop clock\n");
	}
}

static void pxamci_enable_irq(struct pxamci_host *host, unsigned int mask)
{
	unsigned long flags;

	spin_lock_irqsave(&host->lock, flags);
	host->imask &= ~mask;
	writel(host->imask, host->base + MMC_I_MASK);
	spin_unlock_irqrestore(&host->lock, flags);
}

static void pxamci_disable_irq(struct pxamci_host *host, unsigned int mask)
{
	unsigned long flags;

	spin_lock_irqsave(&host->lock, flags);
	host->imask |= mask;
	writel(host->imask, host->base + MMC_I_MASK);
	spin_unlock_irqrestore(&host->lock, flags);
}

static void pxamci_setup_data(struct pxamci_host *host, struct mmc_data *data)
{
	unsigned int nob = data->blocks;
116
	unsigned long long clks;
L
Linus Torvalds 已提交
117
	unsigned int timeout;
118
	bool dalgn = 0;
L
Linus Torvalds 已提交
119 120 121 122 123 124 125 126 127
	u32 dcmd;
	int i;

	host->data = data;

	if (data->flags & MMC_DATA_STREAM)
		nob = 0xffff;

	writel(nob, host->base + MMC_NOB);
128
	writel(data->blksz, host->base + MMC_BLKLEN);
L
Linus Torvalds 已提交
129

130
	clks = (unsigned long long)data->timeout_ns * host->clkrate;
131 132
	do_div(clks, 1000000000UL);
	timeout = (unsigned int)clks + (data->timeout_clks << host->clkrt);
L
Linus Torvalds 已提交
133 134 135 136 137
	writel((timeout + 255) / 256, host->base + MMC_RDTO);

	if (data->flags & MMC_DATA_READ) {
		host->dma_dir = DMA_FROM_DEVICE;
		dcmd = DCMD_INCTRGADDR | DCMD_FLOWTRG;
138 139
		DRCMR(host->dma_drcmrtx) = 0;
		DRCMR(host->dma_drcmrrx) = host->dma | DRCMR_MAPVLD;
L
Linus Torvalds 已提交
140 141 142
	} else {
		host->dma_dir = DMA_TO_DEVICE;
		dcmd = DCMD_INCSRCADDR | DCMD_FLOWSRC;
143 144
		DRCMR(host->dma_drcmrrx) = 0;
		DRCMR(host->dma_drcmrtx) = host->dma | DRCMR_MAPVLD;
L
Linus Torvalds 已提交
145 146 147 148 149 150 151 152
	}

	dcmd |= DCMD_BURST32 | DCMD_WIDTH1;

	host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
				   host->dma_dir);

	for (i = 0; i < host->dma_len; i++) {
153 154 155 156
		unsigned int length = sg_dma_len(&data->sg[i]);
		host->sg_cpu[i].dcmd = dcmd | length;
		if (length & 31 && !(data->flags & MMC_DATA_READ))
			host->sg_cpu[i].dcmd |= DCMD_ENDIRQEN;
157 158 159
		/* Not aligned to 8-byte boundary? */
		if (sg_dma_address(&data->sg[i]) & 0x7)
			dalgn = 1;
L
Linus Torvalds 已提交
160 161 162 163 164 165 166 167 168 169 170 171 172
		if (data->flags & MMC_DATA_READ) {
			host->sg_cpu[i].dsadr = host->res->start + MMC_RXFIFO;
			host->sg_cpu[i].dtadr = sg_dma_address(&data->sg[i]);
		} else {
			host->sg_cpu[i].dsadr = sg_dma_address(&data->sg[i]);
			host->sg_cpu[i].dtadr = host->res->start + MMC_TXFIFO;
		}
		host->sg_cpu[i].ddadr = host->sg_dma + (i + 1) *
					sizeof(struct pxa_dma_desc);
	}
	host->sg_cpu[host->dma_len - 1].ddadr = DDADR_STOP;
	wmb();

173 174 175 176 177 178 179 180
	/*
	 * The PXA27x DMA controller encounters overhead when working with
	 * unaligned (to 8-byte boundaries) data, so switch on byte alignment
	 * mode only if we have unaligned data.
	 */
	if (dalgn)
		DALGN |= (1 << host->dma);
	else
181
		DALGN &= ~(1 << host->dma);
L
Linus Torvalds 已提交
182 183 184 185 186 187 188 189 190 191 192 193
	DDADR(host->dma) = host->sg_dma;
	DCSR(host->dma) = DCSR_RUN;
}

static void pxamci_start_cmd(struct pxamci_host *host, struct mmc_command *cmd, unsigned int cmdat)
{
	WARN_ON(host->cmd != NULL);
	host->cmd = cmd;

	if (cmd->flags & MMC_RSP_BUSY)
		cmdat |= CMDAT_BUSY;

R
Russell King 已提交
194 195
#define RSP_TYPE(x)	((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
	switch (RSP_TYPE(mmc_resp_type(cmd))) {
P
Philip Langdale 已提交
196
	case RSP_TYPE(MMC_RSP_R1): /* r1, r1b, r6, r7 */
L
Linus Torvalds 已提交
197 198
		cmdat |= CMDAT_RESP_SHORT;
		break;
R
Russell King 已提交
199
	case RSP_TYPE(MMC_RSP_R3):
L
Linus Torvalds 已提交
200 201
		cmdat |= CMDAT_RESP_R3;
		break;
R
Russell King 已提交
202
	case RSP_TYPE(MMC_RSP_R2):
L
Linus Torvalds 已提交
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
		cmdat |= CMDAT_RESP_R2;
		break;
	default:
		break;
	}

	writel(cmd->opcode, host->base + MMC_CMD);
	writel(cmd->arg >> 16, host->base + MMC_ARGH);
	writel(cmd->arg & 0xffff, host->base + MMC_ARGL);
	writel(cmdat, host->base + MMC_CMDAT);
	writel(host->clkrt, host->base + MMC_CLKRT);

	writel(START_CLOCK, host->base + MMC_STRPCL);

	pxamci_enable_irq(host, END_CMD_RES);
}

static void pxamci_finish_request(struct pxamci_host *host, struct mmc_request *mrq)
{
	host->mrq = NULL;
	host->cmd = NULL;
	host->data = NULL;
	mmc_request_done(host->mmc, mrq);
}

static int pxamci_cmd_done(struct pxamci_host *host, unsigned int stat)
{
	struct mmc_command *cmd = host->cmd;
	int i;
	u32 v;

	if (!cmd)
		return 0;

	host->cmd = NULL;

	/*
	 * Did I mention this is Sick.  We always need to
	 * discard the upper 8 bits of the first 16-bit word.
	 */
	v = readl(host->base + MMC_RES) & 0xffff;
	for (i = 0; i < 4; i++) {
		u32 w1 = readl(host->base + MMC_RES) & 0xffff;
		u32 w2 = readl(host->base + MMC_RES) & 0xffff;
		cmd->resp[i] = v << 24 | w1 << 8 | w2 >> 8;
		v = w2;
	}

	if (stat & STAT_TIME_OUT_RESPONSE) {
P
Pierre Ossman 已提交
252
		cmd->error = -ETIMEDOUT;
L
Linus Torvalds 已提交
253 254 255 256 257
	} else if (stat & STAT_RES_CRC_ERR && cmd->flags & MMC_RSP_CRC) {
#ifdef CONFIG_PXA27x
		/*
		 * workaround for erratum #42:
		 * Intel PXA27x Family Processor Specification Update Rev 001
258 259
		 * A bogus CRC error can appear if the msb of a 136 bit
		 * response is a one.
L
Linus Torvalds 已提交
260
		 */
261 262 263
		if (cmd->flags & MMC_RSP_136 && cmd->resp[0] & 0x80000000) {
			pr_debug("ignoring CRC from command %d - *risky*\n", cmd->opcode);
		} else
L
Linus Torvalds 已提交
264
#endif
P
Pierre Ossman 已提交
265
		cmd->error = -EILSEQ;
L
Linus Torvalds 已提交
266 267 268
	}

	pxamci_disable_irq(host, END_CMD_RES);
P
Pierre Ossman 已提交
269
	if (host->data && !cmd->error) {
L
Linus Torvalds 已提交
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
		pxamci_enable_irq(host, DATA_TRAN_DONE);
	} else {
		pxamci_finish_request(host, host->mrq);
	}

	return 1;
}

static int pxamci_data_done(struct pxamci_host *host, unsigned int stat)
{
	struct mmc_data *data = host->data;

	if (!data)
		return 0;

	DCSR(host->dma) = 0;
	dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
		     host->dma_dir);

	if (stat & STAT_READ_TIME_OUT)
P
Pierre Ossman 已提交
290
		data->error = -ETIMEDOUT;
L
Linus Torvalds 已提交
291
	else if (stat & (STAT_CRC_READ_ERROR|STAT_CRC_WRITE_ERROR))
P
Pierre Ossman 已提交
292
		data->error = -EILSEQ;
L
Linus Torvalds 已提交
293 294 295 296 297 298 299

	/*
	 * There appears to be a hardware design bug here.  There seems to
	 * be no way to find out how much data was transferred to the card.
	 * This means that if there was an error on any block, we mark all
	 * data blocks as being in error.
	 */
P
Pierre Ossman 已提交
300
	if (!data->error)
301
		data->bytes_xfered = data->blocks * data->blksz;
L
Linus Torvalds 已提交
302 303 304 305 306 307
	else
		data->bytes_xfered = 0;

	pxamci_disable_irq(host, DATA_TRAN_DONE);

	host->data = NULL;
308
	if (host->mrq->stop) {
L
Linus Torvalds 已提交
309
		pxamci_stop_clock(host);
310
		pxamci_start_cmd(host, host->mrq->stop, host->cmdat);
L
Linus Torvalds 已提交
311 312 313 314 315 316 317
	} else {
		pxamci_finish_request(host, host->mrq);
	}

	return 1;
}

318
static irqreturn_t pxamci_irq(int irq, void *devid)
L
Linus Torvalds 已提交
319 320 321 322 323
{
	struct pxamci_host *host = devid;
	unsigned int ireg;
	int handled = 0;

324
	ireg = readl(host->base + MMC_I_REG) & ~readl(host->base + MMC_I_MASK);
L
Linus Torvalds 已提交
325 326 327 328

	if (ireg) {
		unsigned stat = readl(host->base + MMC_STAT);

329
		pr_debug("PXAMCI: irq %08x stat %08x\n", ireg, stat);
L
Linus Torvalds 已提交
330 331 332 333 334

		if (ireg & END_CMD_RES)
			handled |= pxamci_cmd_done(host, stat);
		if (ireg & DATA_TRAN_DONE)
			handled |= pxamci_data_done(host, stat);
335 336 337 338
		if (ireg & SDIO_INT) {
			mmc_signal_sdio_irq(host->mmc);
			handled = 1;
		}
L
Linus Torvalds 已提交
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
	}

	return IRQ_RETVAL(handled);
}

static void pxamci_request(struct mmc_host *mmc, struct mmc_request *mrq)
{
	struct pxamci_host *host = mmc_priv(mmc);
	unsigned int cmdat;

	WARN_ON(host->mrq != NULL);

	host->mrq = mrq;

	pxamci_stop_clock(host);

	cmdat = host->cmdat;
	host->cmdat &= ~CMDAT_INIT;

	if (mrq->data) {
		pxamci_setup_data(host, mrq->data);

		cmdat &= ~CMDAT_BUSY;
		cmdat |= CMDAT_DATAEN | CMDAT_DMAEN;
		if (mrq->data->flags & MMC_DATA_WRITE)
			cmdat |= CMDAT_WRITE;

		if (mrq->data->flags & MMC_DATA_STREAM)
			cmdat |= CMDAT_STREAM;
	}

	pxamci_start_cmd(host, mrq->cmd, cmdat);
}

373 374 375 376 377
static int pxamci_get_ro(struct mmc_host *mmc)
{
	struct pxamci_host *host = mmc_priv(mmc);

	if (host->pdata && host->pdata->get_ro)
378 379 380 381 382 383
		return !!host->pdata->get_ro(mmc_dev(mmc));
	/*
	 * Board doesn't support read only detection; let the mmc core
	 * decide what to do.
	 */
	return -ENOSYS;
384 385
}

L
Linus Torvalds 已提交
386 387 388 389 390
static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
{
	struct pxamci_host *host = mmc_priv(mmc);

	if (ios->clock) {
391 392 393
		unsigned long rate = host->clkrate;
		unsigned int clk = rate / ios->clock;

R
Russell King 已提交
394 395 396
		if (host->clkrt == CLKRT_OFF)
			clk_enable(host->clk);

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
		if (ios->clock == 26000000) {
			/* to support 26MHz on pxa300/pxa310 */
			host->clkrt = 7;
		} else {
			/* to handle (19.5MHz, 26MHz) */
			if (!clk)
				clk = 1;

			/*
			 * clk might result in a lower divisor than we
			 * desire.  check for that condition and adjust
			 * as appropriate.
			 */
			if (rate / clk > ios->clock)
				clk <<= 1;
			host->clkrt = fls(clk) - 1;
		}
L
Linus Torvalds 已提交
414 415 416 417 418 419

		/*
		 * we write clkrt on the next command
		 */
	} else {
		pxamci_stop_clock(host);
R
Russell King 已提交
420 421 422 423
		if (host->clkrt != CLKRT_OFF) {
			host->clkrt = CLKRT_OFF;
			clk_disable(host->clk);
		}
L
Linus Torvalds 已提交
424 425 426 427 428 429
	}

	if (host->power_mode != ios->power_mode) {
		host->power_mode = ios->power_mode;

		if (host->pdata && host->pdata->setpower)
S
Sascha Hauer 已提交
430
			host->pdata->setpower(mmc_dev(mmc), ios->vdd);
L
Linus Torvalds 已提交
431 432 433 434 435

		if (ios->power_mode == MMC_POWER_ON)
			host->cmdat |= CMDAT_INIT;
	}

436 437 438 439 440
	if (ios->bus_width == MMC_BUS_WIDTH_4)
		host->cmdat |= CMDAT_SD_4DAT;
	else
		host->cmdat &= ~CMDAT_SD_4DAT;

441
	pr_debug("PXAMCI: clkrt = %x cmdat = %x\n",
442
		 host->clkrt, host->cmdat);
L
Linus Torvalds 已提交
443 444
}

445 446 447 448 449 450 451 452 453 454
static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable)
{
	struct pxamci_host *pxa_host = mmc_priv(host);

	if (enable)
		pxamci_enable_irq(pxa_host, SDIO_INT);
	else
		pxamci_disable_irq(pxa_host, SDIO_INT);
}

455
static const struct mmc_host_ops pxamci_ops = {
456 457 458 459
	.request		= pxamci_request,
	.get_ro			= pxamci_get_ro,
	.set_ios		= pxamci_set_ios,
	.enable_sdio_irq	= pxamci_enable_sdio_irq,
L
Linus Torvalds 已提交
460 461
};

462
static void pxamci_dma_irq(int dma, void *devid)
L
Linus Torvalds 已提交
463
{
464 465 466 467 468 469 470 471 472 473 474 475
	struct pxamci_host *host = devid;
	int dcsr = DCSR(dma);
	DCSR(dma) = dcsr & ~DCSR_STOPIRQEN;

	if (dcsr & DCSR_ENDINTR) {
		writel(BUF_PART_FULL, host->base + MMC_PRTBUF);
	} else {
		printk(KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
		       mmc_hostname(host->mmc), dma, dcsr);
		host->data->error = -EIO;
		pxamci_data_done(host, 0);
	}
L
Linus Torvalds 已提交
476 477
}

478
static irqreturn_t pxamci_detect_irq(int irq, void *devid)
L
Linus Torvalds 已提交
479
{
480 481 482
	struct pxamci_host *host = mmc_priv(devid);

	mmc_detect_change(devid, host->pdata->detect_delay);
L
Linus Torvalds 已提交
483 484 485
	return IRQ_HANDLED;
}

486
static int pxamci_probe(struct platform_device *pdev)
L
Linus Torvalds 已提交
487 488 489
{
	struct mmc_host *mmc;
	struct pxamci_host *host = NULL;
490
	struct resource *r, *dmarx, *dmatx;
L
Linus Torvalds 已提交
491 492 493 494
	int ret, irq;

	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	irq = platform_get_irq(pdev, 0);
495
	if (!r || irq < 0)
L
Linus Torvalds 已提交
496 497 498 499 500 501
		return -ENXIO;

	r = request_mem_region(r->start, SZ_4K, DRIVER_NAME);
	if (!r)
		return -EBUSY;

502
	mmc = mmc_alloc_host(sizeof(struct pxamci_host), &pdev->dev);
L
Linus Torvalds 已提交
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
	if (!mmc) {
		ret = -ENOMEM;
		goto out;
	}

	mmc->ops = &pxamci_ops;

	/*
	 * We can do SG-DMA, but we don't because we never know how much
	 * data we successfully wrote to the card.
	 */
	mmc->max_phys_segs = NR_SG;

	/*
	 * Our hardware DMA can handle a maximum of one page per SG entry.
	 */
	mmc->max_seg_size = PAGE_SIZE;

521
	/*
522
	 * Block length register is only 10 bits before PXA27x.
523
	 */
524
	mmc->max_blk_size = cpu_is_pxa25x() ? 1023 : 2048;
525

526 527 528 529 530
	/*
	 * Block count register is 16 bits.
	 */
	mmc->max_blk_count = 65535;

L
Linus Torvalds 已提交
531 532 533 534
	host = mmc_priv(mmc);
	host->mmc = mmc;
	host->dma = -1;
	host->pdata = pdev->dev.platform_data;
R
Russell King 已提交
535
	host->clkrt = CLKRT_OFF;
536

537
	host->clk = clk_get(&pdev->dev, NULL);
538 539 540 541 542 543 544 545 546 547 548 549
	if (IS_ERR(host->clk)) {
		ret = PTR_ERR(host->clk);
		host->clk = NULL;
		goto out;
	}

	host->clkrate = clk_get_rate(host->clk);

	/*
	 * Calculate minimum clock rate, rounding up.
	 */
	mmc->f_min = (host->clkrate + 63) / 64;
550 551
	mmc->f_max = (cpu_is_pxa300() || cpu_is_pxa310()) ? 26000000
							  : host->clkrate;
552

L
Linus Torvalds 已提交
553 554 555
	mmc->ocr_avail = host->pdata ?
			 host->pdata->ocr_mask :
			 MMC_VDD_32_33|MMC_VDD_33_34;
556
	mmc->caps = 0;
557
	host->cmdat = 0;
558
	if (!cpu_is_pxa25x()) {
559 560
		mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
		host->cmdat |= CMDAT_SDIO_INT_EN;
561 562 563
		if (cpu_is_pxa300() || cpu_is_pxa310())
			mmc->caps |= MMC_CAP_MMC_HIGHSPEED |
				     MMC_CAP_SD_HIGHSPEED;
564
	}
L
Linus Torvalds 已提交
565

566
	host->sg_cpu = dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &host->sg_dma, GFP_KERNEL);
L
Linus Torvalds 已提交
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602
	if (!host->sg_cpu) {
		ret = -ENOMEM;
		goto out;
	}

	spin_lock_init(&host->lock);
	host->res = r;
	host->irq = irq;
	host->imask = MMC_I_MASK_ALL;

	host->base = ioremap(r->start, SZ_4K);
	if (!host->base) {
		ret = -ENOMEM;
		goto out;
	}

	/*
	 * Ensure that the host controller is shut down, and setup
	 * with our defaults.
	 */
	pxamci_stop_clock(host);
	writel(0, host->base + MMC_SPI);
	writel(64, host->base + MMC_RESTO);
	writel(host->imask, host->base + MMC_I_MASK);

	host->dma = pxa_request_dma(DRIVER_NAME, DMA_PRIO_LOW,
				    pxamci_dma_irq, host);
	if (host->dma < 0) {
		ret = -EBUSY;
		goto out;
	}

	ret = request_irq(host->irq, pxamci_irq, 0, DRIVER_NAME, host);
	if (ret)
		goto out;

603
	platform_set_drvdata(pdev, mmc);
L
Linus Torvalds 已提交
604

605 606 607 608 609 610 611 612 613 614 615 616 617 618
	dmarx = platform_get_resource(pdev, IORESOURCE_DMA, 0);
	if (!dmarx) {
		ret = -ENXIO;
		goto out;
	}
	host->dma_drcmrrx = dmarx->start;

	dmatx = platform_get_resource(pdev, IORESOURCE_DMA, 1);
	if (!dmatx) {
		ret = -ENXIO;
		goto out;
	}
	host->dma_drcmrtx = dmatx->start;

L
Linus Torvalds 已提交
619
	if (host->pdata && host->pdata->init)
620
		host->pdata->init(&pdev->dev, pxamci_detect_irq, mmc);
L
Linus Torvalds 已提交
621 622 623 624 625 626 627 628 629 630 631 632

	mmc_add_host(mmc);

	return 0;

 out:
	if (host) {
		if (host->dma >= 0)
			pxa_free_dma(host->dma);
		if (host->base)
			iounmap(host->base);
		if (host->sg_cpu)
633
			dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
634 635
		if (host->clk)
			clk_put(host->clk);
L
Linus Torvalds 已提交
636 637 638 639 640 641 642
	}
	if (mmc)
		mmc_free_host(mmc);
	release_resource(r);
	return ret;
}

643
static int pxamci_remove(struct platform_device *pdev)
L
Linus Torvalds 已提交
644
{
645
	struct mmc_host *mmc = platform_get_drvdata(pdev);
L
Linus Torvalds 已提交
646

647
	platform_set_drvdata(pdev, NULL);
L
Linus Torvalds 已提交
648 649 650 651 652

	if (mmc) {
		struct pxamci_host *host = mmc_priv(mmc);

		if (host->pdata && host->pdata->exit)
653
			host->pdata->exit(&pdev->dev, mmc);
L
Linus Torvalds 已提交
654 655 656 657 658 659 660 661

		mmc_remove_host(mmc);

		pxamci_stop_clock(host);
		writel(TXFIFO_WR_REQ|RXFIFO_RD_REQ|CLK_IS_OFF|STOP_CMD|
		       END_CMD_RES|PRG_DONE|DATA_TRAN_DONE,
		       host->base + MMC_I_MASK);

662 663
		DRCMR(host->dma_drcmrrx) = 0;
		DRCMR(host->dma_drcmrtx) = 0;
L
Linus Torvalds 已提交
664 665 666 667

		free_irq(host->irq, host);
		pxa_free_dma(host->dma);
		iounmap(host->base);
668
		dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
L
Linus Torvalds 已提交
669

670 671
		clk_put(host->clk);

L
Linus Torvalds 已提交
672 673 674 675 676 677 678 679
		release_resource(host->res);

		mmc_free_host(mmc);
	}
	return 0;
}

#ifdef CONFIG_PM
680
static int pxamci_suspend(struct platform_device *dev, pm_message_t state)
L
Linus Torvalds 已提交
681
{
682
	struct mmc_host *mmc = platform_get_drvdata(dev);
L
Linus Torvalds 已提交
683 684
	int ret = 0;

685
	if (mmc)
L
Linus Torvalds 已提交
686 687 688 689 690
		ret = mmc_suspend_host(mmc, state);

	return ret;
}

691
static int pxamci_resume(struct platform_device *dev)
L
Linus Torvalds 已提交
692
{
693
	struct mmc_host *mmc = platform_get_drvdata(dev);
L
Linus Torvalds 已提交
694 695
	int ret = 0;

696
	if (mmc)
L
Linus Torvalds 已提交
697 698 699 700 701 702 703 704 705
		ret = mmc_resume_host(mmc);

	return ret;
}
#else
#define pxamci_suspend	NULL
#define pxamci_resume	NULL
#endif

706
static struct platform_driver pxamci_driver = {
L
Linus Torvalds 已提交
707 708 709 710
	.probe		= pxamci_probe,
	.remove		= pxamci_remove,
	.suspend	= pxamci_suspend,
	.resume		= pxamci_resume,
711 712
	.driver		= {
		.name	= DRIVER_NAME,
713
		.owner	= THIS_MODULE,
714
	},
L
Linus Torvalds 已提交
715 716 717 718
};

static int __init pxamci_init(void)
{
719
	return platform_driver_register(&pxamci_driver);
L
Linus Torvalds 已提交
720 721 722 723
}

static void __exit pxamci_exit(void)
{
724
	platform_driver_unregister(&pxamci_driver);
L
Linus Torvalds 已提交
725 726 727 728 729 730 731
}

module_init(pxamci_init);
module_exit(pxamci_exit);

MODULE_DESCRIPTION("PXA Multimedia Card Interface Driver");
MODULE_LICENSE("GPL");
732
MODULE_ALIAS("platform:pxa2xx-mci");