mmci.c revision 768fbc1876b3239f4c463c00ea1e78725554cf21
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
270f10482c668301c483acded13bf68780ad352b9Pierre Ossman *  linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
5c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King *  Copyright (C) 2010 ST-Ericsson SA
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or modify
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * it under the terms of the GNU General Public License version 2 as
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * published by the Free Software Foundation.
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/moduleparam.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
17613b152c63e35095a929f9bb80441cbe91ff5e80Russell King#include <linux/kernel.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/err.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/highmem.h>
21019a5f56ec195aceadada18aaaad0f67294bdaefNicolas Pitre#include <linux/log2.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mmc/host.h>
2334177802001894e064c857cac2759f68119550cdLinus Walleij#include <linux/mmc/card.h>
24a62c80e559809e6c7851ec04d30575e85ad6f6edRussell King#include <linux/amba/bus.h>
25f8ce25476d5f12ffa29b885e49c38cd95053437eRussell King#include <linux/clk.h>
26bd6dee6f30a0f6943df190b387b5f8fe98a848f3Jens Axboe#include <linux/scatterlist.h>
2789001446925d6da8785c3265a71316e34c6d15deRussell King#include <linux/gpio.h>
2834e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij#include <linux/regulator/consumer.h>
29c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#include <linux/dmaengine.h>
30c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#include <linux/dma-mapping.h>
31c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#include <linux/amba/mmci.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
337b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King#include <asm/div64.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
35c6b8fdad144bbb915d124ffd95011ad55730bf9fRussell King#include <asm/sizes.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "mmci.h"
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DRIVER_NAME "mmci-pl18x"
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int fmax = 515633;
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
434956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent/**
444956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent * struct variant_data - MMCI variant-specific quirks
454956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent * @clkreg: default value for MCICLOCK register
464380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent * @clkreg_enable: enable value for MMCICLOCK register
4708458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent * @datalength_bits: number of bits in the MMCIDATALENGTH register
488301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY
498301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent *	      is asserted (likewise for RX)
508301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
518301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent *		  is asserted (likewise for RX)
5234177802001894e064c857cac2759f68119550cdLinus Walleij * @sdio: variant supports SDIO
53b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij * @st_clkdiv: true if using a ST-specific clock divider algorithm
544956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent */
554956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstruct variant_data {
564956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent	unsigned int		clkreg;
574380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent	unsigned int		clkreg_enable;
5808458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent	unsigned int		datalength_bits;
598301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent	unsigned int		fifosize;
608301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent	unsigned int		fifohalfsize;
6134177802001894e064c857cac2759f68119550cdLinus Walleij	bool			sdio;
62b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij	bool			st_clkdiv;
634956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent};
644956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent
654956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstatic struct variant_data variant_arm = {
668301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent	.fifosize		= 16 * 4,
678301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent	.fifohalfsize		= 8 * 4,
6808458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent	.datalength_bits	= 16,
694956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent};
704956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent
71768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Mollstatic struct variant_data variant_arm_extended_fifo = {
72768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll	.fifosize		= 128 * 4,
73768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll	.fifohalfsize		= 64 * 4,
74768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll	.datalength_bits	= 16,
75768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll};
76768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll
774956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstatic struct variant_data variant_u300 = {
788301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent	.fifosize		= 16 * 4,
798301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent	.fifohalfsize		= 8 * 4,
804380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent	.clkreg_enable		= 1 << 13, /* HWFCEN */
8108458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent	.datalength_bits	= 16,
8234177802001894e064c857cac2759f68119550cdLinus Walleij	.sdio			= true,
834956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent};
844956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent
854956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincentstatic struct variant_data variant_ux500 = {
868301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent	.fifosize		= 30 * 4,
878301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent	.fifohalfsize		= 8 * 4,
884956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent	.clkreg			= MCI_CLK_ENABLE,
894380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent	.clkreg_enable		= 1 << 14, /* HWFCEN */
9008458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent	.datalength_bits	= 24,
9134177802001894e064c857cac2759f68119550cdLinus Walleij	.sdio			= true,
92b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij	.st_clkdiv		= true,
934956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent};
94b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij
95a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij/*
96a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij * This must be called with host->lock held
97a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij */
98a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleijstatic void mmci_set_clkreg(struct mmci_host *host, unsigned int desired)
99a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij{
1004956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent	struct variant_data *variant = host->variant;
1014956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent	u32 clk = variant->clkreg;
102a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij
103a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij	if (desired) {
104a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij		if (desired >= host->mclk) {
105991a86e182203913b71607f0695955d7e23075d7Linus Walleij			clk = MCI_CLK_BYPASS;
106a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij			host->cclk = host->mclk;
107b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij		} else if (variant->st_clkdiv) {
108b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			/*
109b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			 * DB8500 TRM says f = mclk / (clkdiv + 2)
110b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			 * => clkdiv = (mclk / f) - 2
111b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			 * Round the divider up so we don't exceed the max
112b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			 * frequency
113b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			 */
114b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			clk = DIV_ROUND_UP(host->mclk, desired) - 2;
115b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			if (clk >= 256)
116b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij				clk = 255;
117b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			host->cclk = host->mclk / (clk + 2);
118a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij		} else {
119b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			/*
120b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			 * PL180 TRM says f = mclk / (2 * (clkdiv + 1))
121b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			 * => clkdiv = mclk / (2 * f) - 1
122b70a67f938e4a7544ca4dea2856b88f3c47669ffLinus Walleij			 */
123a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij			clk = host->mclk / (2 * desired) - 1;
124a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij			if (clk >= 256)
125a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij				clk = 255;
126a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij			host->cclk = host->mclk / (2 * (clk + 1));
127a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij		}
1284380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent
1294380c14fd77338bac9d1da4dc5dd9f6eb4966c82Rabin Vincent		clk |= variant->clkreg_enable;
130a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij		clk |= MCI_CLK_ENABLE;
131a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij		/* This hasn't proven to be worthwhile */
132a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij		/* clk |= MCI_CLK_PWRSAVE; */
133a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij	}
134a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij
1359e6c82cd3e1a739ef48bf8c1decc8e7a7d8de3acLinus Walleij	if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4)
136771dc157e06d69fcece0b2c8a29b9010345d8e9aLinus Walleij		clk |= MCI_4BIT_BUS;
137771dc157e06d69fcece0b2c8a29b9010345d8e9aLinus Walleij	if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8)
138771dc157e06d69fcece0b2c8a29b9010345d8e9aLinus Walleij		clk |= MCI_ST_8BIT_BUS;
1399e6c82cd3e1a739ef48bf8c1decc8e7a7d8de3acLinus Walleij
140a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij	writel(clk, host->base + MMCICLOCK);
141a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij}
142a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(0, host->base + MMCICOMMAND);
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
148e47c222b22cd53c317a5573e1dc5f9e0cbd46380Russell King	BUG_ON(host->data);
149e47c222b22cd53c317a5573e1dc5f9e0cbd46380Russell King
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->mrq = NULL;
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->cmd = NULL;
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Need to drop the host lock here; mmc_request_done may call
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * back into the driver...
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&host->lock);
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_request_done(host->mmc, mrq);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&host->lock);
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1622686b4b408c25349aee7b35558722d5730d67224Linus Walleijstatic void mmci_set_mask1(struct mmci_host *host, unsigned int mask)
1632686b4b408c25349aee7b35558722d5730d67224Linus Walleij{
1642686b4b408c25349aee7b35558722d5730d67224Linus Walleij	void __iomem *base = host->base;
1652686b4b408c25349aee7b35558722d5730d67224Linus Walleij
1662686b4b408c25349aee7b35558722d5730d67224Linus Walleij	if (host->singleirq) {
1672686b4b408c25349aee7b35558722d5730d67224Linus Walleij		unsigned int mask0 = readl(base + MMCIMASK0);
1682686b4b408c25349aee7b35558722d5730d67224Linus Walleij
1692686b4b408c25349aee7b35558722d5730d67224Linus Walleij		mask0 &= ~MCI_IRQ1MASK;
1702686b4b408c25349aee7b35558722d5730d67224Linus Walleij		mask0 |= mask;
1712686b4b408c25349aee7b35558722d5730d67224Linus Walleij
1722686b4b408c25349aee7b35558722d5730d67224Linus Walleij		writel(mask0, base + MMCIMASK0);
1732686b4b408c25349aee7b35558722d5730d67224Linus Walleij	}
1742686b4b408c25349aee7b35558722d5730d67224Linus Walleij
1752686b4b408c25349aee7b35558722d5730d67224Linus Walleij	writel(mask, base + MMCIMASK1);
1762686b4b408c25349aee7b35558722d5730d67224Linus Walleij}
1772686b4b408c25349aee7b35558722d5730d67224Linus Walleij
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_stop_data(struct mmci_host *host)
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(0, host->base + MMCIDATACTRL);
1812686b4b408c25349aee7b35558722d5730d67224Linus Walleij	mmci_set_mask1(host, 0);
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->data = NULL;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1854ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincentstatic void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
1864ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent{
1874ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent	unsigned int flags = SG_MITER_ATOMIC;
1884ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent
1894ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent	if (data->flags & MMC_DATA_READ)
1904ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent		flags |= SG_MITER_TO_SG;
1914ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent	else
1924ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent		flags |= SG_MITER_FROM_SG;
1934ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent
1944ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent	sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
1954ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent}
1964ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent
197c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King/*
198c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * All the DMA operation mode stuff goes inside this ifdef.
199c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * This assumes that you have a generic DMA device interface,
200c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * no custom DMA interfaces are supported.
201c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */
202c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#ifdef CONFIG_DMA_ENGINE
203c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic void __devinit mmci_dma_setup(struct mmci_host *host)
204c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{
205c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	struct mmci_platform_data *plat = host->plat;
206c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	const char *rxname, *txname;
207c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dma_cap_mask_t mask;
208c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
209c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (!plat || !plat->dma_filter) {
210c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		dev_info(mmc_dev(host->mmc), "no DMA platform data\n");
211c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		return;
212c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	}
213c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
214c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/* Try to acquire a generic DMA engine slave channel */
215c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dma_cap_zero(mask);
216c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dma_cap_set(DMA_SLAVE, mask);
217c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
218c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/*
219c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * If only an RX channel is specified, the driver will
220c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * attempt to use it bidirectionally, however if it is
221c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * is specified but cannot be located, DMA will be disabled.
222c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 */
223c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (plat->dma_rx_param) {
224c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		host->dma_rx_channel = dma_request_channel(mask,
225c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King							   plat->dma_filter,
226c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King							   plat->dma_rx_param);
227c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		/* E.g if no DMA hardware is present */
228c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		if (!host->dma_rx_channel)
229c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King			dev_err(mmc_dev(host->mmc), "no RX DMA channel\n");
230c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	}
231c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
232c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (plat->dma_tx_param) {
233c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		host->dma_tx_channel = dma_request_channel(mask,
234c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King							   plat->dma_filter,
235c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King							   plat->dma_tx_param);
236c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		if (!host->dma_tx_channel)
237c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King			dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n");
238c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	} else {
239c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		host->dma_tx_channel = host->dma_rx_channel;
240c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	}
241c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
242c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (host->dma_rx_channel)
243c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		rxname = dma_chan_name(host->dma_rx_channel);
244c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	else
245c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		rxname = "none";
246c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
247c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (host->dma_tx_channel)
248c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		txname = dma_chan_name(host->dma_tx_channel);
249c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	else
250c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		txname = "none";
251c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
252c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dev_info(mmc_dev(host->mmc), "DMA channels RX %s, TX %s\n",
253c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		 rxname, txname);
254c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
255c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/*
256c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * Limit the maximum segment size in any SG entry according to
257c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * the parameters of the DMA engine device.
258c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 */
259c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (host->dma_tx_channel) {
260c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		struct device *dev = host->dma_tx_channel->device->dev;
261c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		unsigned int max_seg_size = dma_get_max_seg_size(dev);
262c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
263c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		if (max_seg_size < host->mmc->max_seg_size)
264c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King			host->mmc->max_seg_size = max_seg_size;
265c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	}
266c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (host->dma_rx_channel) {
267c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		struct device *dev = host->dma_rx_channel->device->dev;
268c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		unsigned int max_seg_size = dma_get_max_seg_size(dev);
269c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
270c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		if (max_seg_size < host->mmc->max_seg_size)
271c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King			host->mmc->max_seg_size = max_seg_size;
272c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	}
273c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King}
274c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
275c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King/*
276c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * This is used in __devinit or __devexit so inline it
277c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King * so it can be discarded.
278c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King */
279c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_release(struct mmci_host *host)
280c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{
281c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	struct mmci_platform_data *plat = host->plat;
282c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
283c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (host->dma_rx_channel)
284c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		dma_release_channel(host->dma_rx_channel);
285c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (host->dma_tx_channel && plat->dma_tx_param)
286c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		dma_release_channel(host->dma_tx_channel);
287c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	host->dma_rx_channel = host->dma_tx_channel = NULL;
288c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King}
289c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
290c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
291c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{
292c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	struct dma_chan *chan = host->dma_current;
293c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	enum dma_data_direction dir;
294c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	u32 status;
295c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	int i;
296c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
297c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/* Wait up to 1ms for the DMA to complete */
298c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	for (i = 0; ; i++) {
299c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		status = readl(host->base + MMCISTATUS);
300c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		if (!(status & MCI_RXDATAAVLBLMASK) || i >= 100)
301c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King			break;
302c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		udelay(10);
303c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	}
304c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
305c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/*
306c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * Check to see whether we still have some data left in the FIFO -
307c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * this catches DMA controllers which are unable to monitor the
308c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * DMALBREQ and DMALSREQ signals while allowing us to DMA to non-
309c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * contiguous buffers.  On TX, we'll get a FIFO underrun error.
310c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 */
311c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (status & MCI_RXDATAAVLBLMASK) {
312c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		dmaengine_terminate_all(chan);
313c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		if (!data->error)
314c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King			data->error = -EIO;
315c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	}
316c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
317c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (data->flags & MMC_DATA_WRITE) {
318c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		dir = DMA_TO_DEVICE;
319c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	} else {
320c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		dir = DMA_FROM_DEVICE;
321c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	}
322c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
323c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir);
324c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
325c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/*
326c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * Use of DMA with scatter-gather is impossible.
327c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * Give up with DMA and switch back to PIO mode.
328c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 */
329c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (status & MCI_RXDATAAVLBLMASK) {
330c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		dev_err(mmc_dev(host->mmc), "buggy DMA detected. Taking evasive action.\n");
331c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		mmci_dma_release(host);
332c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	}
333c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King}
334c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
335c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic void mmci_dma_data_error(struct mmci_host *host)
336c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{
337c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n");
338c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dmaengine_terminate_all(host->dma_current);
339c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King}
340c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
341c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
342c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{
343c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	struct variant_data *variant = host->variant;
344c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	struct dma_slave_config conf = {
345c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		.src_addr = host->phybase + MMCIFIFO,
346c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		.dst_addr = host->phybase + MMCIFIFO,
347c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
348c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
349c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		.src_maxburst = variant->fifohalfsize >> 2, /* # of words */
350c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		.dst_maxburst = variant->fifohalfsize >> 2, /* # of words */
351c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	};
352c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	struct mmc_data *data = host->data;
353c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	struct dma_chan *chan;
354c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	struct dma_device *device;
355c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	struct dma_async_tx_descriptor *desc;
356c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	int nr_sg;
357c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
358c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	host->dma_current = NULL;
359c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
360c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (data->flags & MMC_DATA_READ) {
361c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		conf.direction = DMA_FROM_DEVICE;
362c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		chan = host->dma_rx_channel;
363c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	} else {
364c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		conf.direction = DMA_TO_DEVICE;
365c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		chan = host->dma_tx_channel;
366c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	}
367c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
368c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/* If there's no DMA channel, fall back to PIO */
369c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (!chan)
370c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		return -EINVAL;
371c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
372c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/* If less than or equal to the fifo size, don't bother with DMA */
373c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (host->size <= variant->fifosize)
374c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		return -EINVAL;
375c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
376c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	device = chan->device;
377c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, conf.direction);
378c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (nr_sg == 0)
379c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		return -EINVAL;
380c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
381c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dmaengine_slave_config(chan, &conf);
382c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	desc = device->device_prep_slave_sg(chan, data->sg, nr_sg,
383c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King					    conf.direction, DMA_CTRL_ACK);
384c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (!desc)
385c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		goto unmap_exit;
386c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
387c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/* Okay, go for it. */
388c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	host->dma_current = chan;
389c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
390c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dev_vdbg(mmc_dev(host->mmc),
391c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		 "Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n",
392c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		 data->sg_len, data->blksz, data->blocks, data->flags);
393c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dmaengine_submit(desc);
394c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dma_async_issue_pending(chan);
395c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
396c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	datactrl |= MCI_DPSM_DMAENABLE;
397c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
398c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/* Trigger the DMA transfer */
399c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	writel(datactrl, host->base + MMCIDATACTRL);
400c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
401c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/*
402c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * Let the MMCI say when the data is ended and it's time
403c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * to fire next DMA request. When that happens, MMCI will
404c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * call mmci_data_end()
405c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 */
406c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK,
407c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	       host->base + MMCIMASK0);
408c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	return 0;
409c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
410c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingunmap_exit:
411c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dmaengine_terminate_all(chan);
412c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction);
413c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	return -ENOMEM;
414c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King}
415c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#else
416c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King/* Blank functions if the DMA engine is not available */
417c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_setup(struct mmci_host *host)
418c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{
419c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King}
420c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
421c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_release(struct mmci_host *host)
422c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{
423c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King}
424c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
425c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
426c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{
427c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King}
428c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
429c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline void mmci_dma_data_error(struct mmci_host *host)
430c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{
431c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King}
432c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
433c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell Kingstatic inline int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
434c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King{
435c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	return -ENOSYS;
436c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King}
437c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King#endif
438c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4418301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent	struct variant_data *variant = host->variant;
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int datactrl, timeout, irqmask;
4437b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King	unsigned long long clks;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *base;
4453bc87f243f64c953717bea058f4b458a57fc1a29Russell King	int blksz_bits;
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44764de028948f449af17cf387f45a45f36ffd3c960Linus Walleij	dev_dbg(mmc_dev(host->mmc), "blksz %04x blks %04x flags %08x\n",
44864de028948f449af17cf387f45a45f36ffd3c960Linus Walleij		data->blksz, data->blocks, data->flags);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->data = data;
451528320db013b687c5f0150fd77eb4dc02ca328d1Rabin Vincent	host->size = data->blksz * data->blocks;
45251d4375dd72f352594f1a4f1d7598bf9a75b8dfeRussell King	data->bytes_xfered = 0;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4547b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King	clks = (unsigned long long)data->timeout_ns * host->cclk;
4557b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King	do_div(clks, 1000000000UL);
4567b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King
4577b09cdac5af1e13ab4b30421ae5c4b7953c26841Russell King	timeout = data->timeout_clks + (unsigned int)clks;
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	base = host->base;
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(timeout, base + MMCIDATATIMER);
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(host->size, base + MMCIDATALENGTH);
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4633bc87f243f64c953717bea058f4b458a57fc1a29Russell King	blksz_bits = ffs(data->blksz) - 1;
4643bc87f243f64c953717bea058f4b458a57fc1a29Russell King	BUG_ON(1 << blksz_bits != data->blksz);
4653bc87f243f64c953717bea058f4b458a57fc1a29Russell King
4663bc87f243f64c953717bea058f4b458a57fc1a29Russell King	datactrl = MCI_DPSM_ENABLE | blksz_bits << 4;
467c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
468c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (data->flags & MMC_DATA_READ)
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		datactrl |= MCI_DPSM_DIRECTION;
470c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
471c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/*
472c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * Attempt to use DMA operation mode, if this
473c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 * should fail, fall back to PIO mode
474c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	 */
475c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (!mmci_dma_start_data(host, datactrl))
476c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		return;
477c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
478c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	/* IRQ mode, map the SG list for CPU reading/writing */
479c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	mmci_init_sg(host, data);
480c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
481c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	if (data->flags & MMC_DATA_READ) {
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irqmask = MCI_RXFIFOHALFFULLMASK;
4830425a14213f373595bd23cacdc675f2b973a28d4Russell King
4840425a14213f373595bd23cacdc675f2b973a28d4Russell King		/*
485c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King		 * If we have less than the fifo 'half-full' threshold to
486c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King		 * transfer, trigger a PIO interrupt as soon as any data
487c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King		 * is available.
4880425a14213f373595bd23cacdc675f2b973a28d4Russell King		 */
489c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King		if (host->size < variant->fifohalfsize)
4900425a14213f373595bd23cacdc675f2b973a28d4Russell King			irqmask |= MCI_RXDATAAVLBLMASK;
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * We don't actually need to include "FIFO empty" here
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * since its implicit in "FIFO half empty".
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		irqmask = MCI_TXFIFOHALFEMPTYMASK;
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49934177802001894e064c857cac2759f68119550cdLinus Walleij	/* The ST Micro variants has a special bit to enable SDIO */
50034177802001894e064c857cac2759f68119550cdLinus Walleij	if (variant->sdio && host->mmc->card)
50134177802001894e064c857cac2759f68119550cdLinus Walleij		if (mmc_card_sdio(host->mmc->card))
50234177802001894e064c857cac2759f68119550cdLinus Walleij			datactrl |= MCI_ST_DPSM_SDIOEN;
50334177802001894e064c857cac2759f68119550cdLinus Walleij
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(datactrl, base + MMCIDATACTRL);
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0);
5062686b4b408c25349aee7b35558722d5730d67224Linus Walleij	mmci_set_mask1(host, irqmask);
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *base = host->base;
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51464de028948f449af17cf387f45a45f36ffd3c960Linus Walleij	dev_dbg(mmc_dev(host->mmc), "op %02x arg %08x flags %08x\n",
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    cmd->opcode, cmd->arg, cmd->flags);
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) {
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(0, base + MMCICOMMAND);
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(1);
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	c |= cmd->opcode | MCI_CPSM_ENABLE;
523e92251762d02a46177d4105d1744041e3f8bc465Russell King	if (cmd->flags & MMC_RSP_PRESENT) {
524e92251762d02a46177d4105d1744041e3f8bc465Russell King		if (cmd->flags & MMC_RSP_136)
525e92251762d02a46177d4105d1744041e3f8bc465Russell King			c |= MCI_CPSM_LONGRSP;
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		c |= MCI_CPSM_RESPONSE;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (/*interrupt*/0)
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		c |= MCI_CPSM_INTERRUPT;
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->cmd = cmd;
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(cmd->arg, base + MMCIARGUMENT);
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(c, base + MMCICOMMAND);
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_data_irq(struct mmci_host *host, struct mmc_data *data,
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	      unsigned int status)
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
541f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij	/* First check for errors */
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
5438cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij		u32 remain, success;
544f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij
545c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		/* Terminate the DMA transfer */
546c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		if (dma_inprogress(host))
547c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King			mmci_dma_data_error(host);
548e9c091b47409255cefa1672041479d850b7b991aRussell King
549e9c091b47409255cefa1672041479d850b7b991aRussell King		/*
550c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King		 * Calculate how far we are into the transfer.  Note that
551c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King		 * the data counter gives the number of bytes transferred
552c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King		 * on the MMC bus, not on the host side.  On reads, this
553c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King		 * can be as much as a FIFO-worth of data ahead.  This
554c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King		 * matters for FIFO overruns only.
555e9c091b47409255cefa1672041479d850b7b991aRussell King		 */
556f5a106d9e2a5d947e106c3caace373ded1a695edLinus Walleij		remain = readl(host->base + MMCIDATACNT);
5578cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij		success = data->blksz * data->blocks - remain;
5588cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij
559c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King		dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ, status 0x%08x at 0x%08x\n",
560c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King			status, success);
5618cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij		if (status & MCI_DATACRCFAIL) {
5628cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij			/* Last block was not successful */
563c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King			success -= 1;
56417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman			data->error = -EILSEQ;
5658cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij		} else if (status & MCI_DATATIMEOUT) {
56617b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman			data->error = -ETIMEDOUT;
567c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King		} else if (status & MCI_TXUNDERRUN) {
568c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King			data->error = -EIO;
569c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King		} else if (status & MCI_RXOVERRUN) {
570c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King			if (success > host->variant->fifosize)
571c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King				success -= host->variant->fifosize;
572c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King			else
573c8afc9d59ce1100d3f7704e86fda5a25361c45bfRussell King				success = 0;
57417b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman			data->error = -EIO;
5754ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent		}
57651d4375dd72f352594f1a4f1d7598bf9a75b8dfeRussell King		data->bytes_xfered = round_down(success, data->blksz);
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
578f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij
5798cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij	if (status & MCI_DATABLOCKEND)
5808cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij		dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n");
581f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij
582ccff9b51825b7335889b780bdf7de84ca803e291Russell King	if (status & MCI_DATAEND || data->error) {
583c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		if (dma_inprogress(host))
584c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King			mmci_dma_unmap(host, data);
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmci_stop_data(host);
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5878cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij		if (!data->error)
5888cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij			/* The error clause is handled above, success! */
58951d4375dd72f352594f1a4f1d7598bf9a75b8dfeRussell King			data->bytes_xfered = data->blksz * data->blocks;
590f20f8f21e0402c785c342547f7e49eafc42cfb52Linus Walleij
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!data->stop) {
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mmci_request_end(host, data->mrq);
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mmci_start_command(host, data->stop, 0);
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	     unsigned int status)
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *base = host->base;
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->cmd = NULL;
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (status & MCI_CMDTIMEOUT) {
60817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman		cmd->error = -ETIMEDOUT;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) {
61017b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman		cmd->error = -EILSEQ;
6119047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux	} else {
6129047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux		cmd->resp[0] = readl(base + MMCIRESPONSE0);
6139047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux		cmd->resp[1] = readl(base + MMCIRESPONSE1);
6149047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux		cmd->resp[2] = readl(base + MMCIRESPONSE2);
6159047b435a0b43952f5d1f7eb15a9b63a36efc7f2Russell King - ARM Linux		cmd->resp[3] = readl(base + MMCIRESPONSE3);
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
61817b0429dde9ab60f9cee8e07ab28c7dc6cfe6efdPierre Ossman	if (!cmd->data || cmd->error) {
619e47c222b22cd53c317a5573e1dc5f9e0cbd46380Russell King		if (host->data)
620e47c222b22cd53c317a5573e1dc5f9e0cbd46380Russell King			mmci_stop_data(host);
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmci_request_end(host, cmd->mrq);
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (!(cmd->data->flags & MMC_DATA_READ)) {
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmci_start_data(host, cmd->data);
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int remain)
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *base = host->base;
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *ptr = buffer;
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 status;
63226eed9a5c61edd93d88e147188d4feae6770174eLinus Walleij	int host_remain = host->size;
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
63526eed9a5c61edd93d88e147188d4feae6770174eLinus Walleij		int count = host_remain - (readl(base + MMCIFIFOCNT) << 2);
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (count > remain)
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count = remain;
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (count <= 0)
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		readsl(base + MMCIFIFO, ptr, count >> 2);
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ptr += count;
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		remain -= count;
64726eed9a5c61edd93d88e147188d4feae6770174eLinus Walleij		host_remain -= count;
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (remain == 0)
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = readl(base + MMCISTATUS);
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (status & MCI_RXDATAAVLBL);
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ptr - buffer;
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status)
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6608301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent	struct variant_data *variant = host->variant;
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *base = host->base;
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *ptr = buffer;
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned int count, maxcnt;
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6678301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent		maxcnt = status & MCI_TXFIFOEMPTY ?
6688301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent			 variant->fifosize : variant->fifohalfsize;
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count = min(remain, maxcnt);
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
67134177802001894e064c857cac2759f68119550cdLinus Walleij		/*
67234177802001894e064c857cac2759f68119550cdLinus Walleij		 * The ST Micro variant for SDIO transfer sizes
67334177802001894e064c857cac2759f68119550cdLinus Walleij		 * less then 8 bytes should have clock H/W flow
67434177802001894e064c857cac2759f68119550cdLinus Walleij		 * control disabled.
67534177802001894e064c857cac2759f68119550cdLinus Walleij		 */
67634177802001894e064c857cac2759f68119550cdLinus Walleij		if (variant->sdio &&
67734177802001894e064c857cac2759f68119550cdLinus Walleij		    mmc_card_sdio(host->mmc->card)) {
67834177802001894e064c857cac2759f68119550cdLinus Walleij			if (count < 8)
67934177802001894e064c857cac2759f68119550cdLinus Walleij				writel(readl(host->base + MMCICLOCK) &
68034177802001894e064c857cac2759f68119550cdLinus Walleij					~variant->clkreg_enable,
68134177802001894e064c857cac2759f68119550cdLinus Walleij					host->base + MMCICLOCK);
68234177802001894e064c857cac2759f68119550cdLinus Walleij			else
68334177802001894e064c857cac2759f68119550cdLinus Walleij				writel(readl(host->base + MMCICLOCK) |
68434177802001894e064c857cac2759f68119550cdLinus Walleij					variant->clkreg_enable,
68534177802001894e064c857cac2759f68119550cdLinus Walleij					host->base + MMCICLOCK);
68634177802001894e064c857cac2759f68119550cdLinus Walleij		}
68734177802001894e064c857cac2759f68119550cdLinus Walleij
68834177802001894e064c857cac2759f68119550cdLinus Walleij		/*
68934177802001894e064c857cac2759f68119550cdLinus Walleij		 * SDIO especially may want to send something that is
69034177802001894e064c857cac2759f68119550cdLinus Walleij		 * not divisible by 4 (as opposed to card sectors
69134177802001894e064c857cac2759f68119550cdLinus Walleij		 * etc), and the FIFO only accept full 32-bit writes.
69234177802001894e064c857cac2759f68119550cdLinus Walleij		 * So compensate by adding +3 on the count, a single
69334177802001894e064c857cac2759f68119550cdLinus Walleij		 * byte become a 32bit write, 7 bytes will be two
69434177802001894e064c857cac2759f68119550cdLinus Walleij		 * 32bit writes etc.
69534177802001894e064c857cac2759f68119550cdLinus Walleij		 */
69634177802001894e064c857cac2759f68119550cdLinus Walleij		writesl(base + MMCIFIFO, ptr, (count + 3) >> 2);
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ptr += count;
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		remain -= count;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (remain == 0)
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = readl(base + MMCISTATUS);
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (status & MCI_TXFIFOHALFEMPTY);
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ptr - buffer;
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PIO data transfer IRQ handler.
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7137d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mmci_pio_irq(int irq, void *dev_id)
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmci_host *host = dev_id;
7164ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent	struct sg_mapping_iter *sg_miter = &host->sg_miter;
7178301bb68c6bb9836889641a47443aeb97b763f6cRabin Vincent	struct variant_data *variant = host->variant;
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	void __iomem *base = host->base;
7194ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent	unsigned long flags;
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 status;
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	status = readl(base + MMCISTATUS);
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
72464de028948f449af17cf387f45a45f36ffd3c960Linus Walleij	dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status);
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7264ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent	local_irq_save(flags);
7274ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		unsigned int remain, len;
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		char *buffer;
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/*
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * For write, we only need to test the half-empty flag
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * here - if the FIFO is completely empty, then by
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * definition it is more than half empty.
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 *
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * For read, check for data available.
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL)))
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7424ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent		if (!sg_miter_next(sg_miter))
7434ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent			break;
7444ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent
7454ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent		buffer = sg_miter->addr;
7464ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent		remain = sg_miter->length;
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len = 0;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status & MCI_RXACTIVE)
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len = mmci_pio_read(host, buffer, remain);
7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status & MCI_TXACTIVE)
7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			len = mmci_pio_write(host, buffer, remain, status);
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7544ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent		sg_miter->consumed = len;
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		host->size -= len;
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		remain -= len;
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (remain)
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = readl(base + MMCISTATUS);
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (1);
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7654ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent	sg_miter_stop(sg_miter);
7664ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent
7674ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent	local_irq_restore(flags);
7684ce1d6cbf07271ab8f7cc47c3e27edeac08b58a7Rabin Vincent
7691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
770c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King	 * If we have less than the fifo 'half-full' threshold to transfer,
771c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King	 * trigger a PIO interrupt as soon as any data is available.
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
773c4d877c1b3df58d89f01d7b211f58b944356eea3Russell King	if (status & MCI_RXACTIVE && host->size < variant->fifohalfsize)
7742686b4b408c25349aee7b35558722d5730d67224Linus Walleij		mmci_set_mask1(host, MCI_RXDATAAVLBLMASK);
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * If we run out of data, disable the data IRQs; this
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * prevents a race where the FIFO becomes empty before
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the chip itself has disabled the data path, and
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * stops us racing with our data end IRQ.
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (host->size == 0) {
7832686b4b408c25349aee7b35558722d5730d67224Linus Walleij		mmci_set_mask1(host, 0);
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0);
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_HANDLED;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Handle completion of command and data transfers.
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7937d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t mmci_irq(int irq, void *dev_id)
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmci_host *host = dev_id;
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 status;
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock(&host->lock);
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	do {
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct mmc_command *cmd;
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct mmc_data *data;
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status = readl(host->base + MMCISTATUS);
8062686b4b408c25349aee7b35558722d5730d67224Linus Walleij
8072686b4b408c25349aee7b35558722d5730d67224Linus Walleij		if (host->singleirq) {
8082686b4b408c25349aee7b35558722d5730d67224Linus Walleij			if (status & readl(host->base + MMCIMASK1))
8092686b4b408c25349aee7b35558722d5730d67224Linus Walleij				mmci_pio_irq(irq, dev_id);
8102686b4b408c25349aee7b35558722d5730d67224Linus Walleij
8112686b4b408c25349aee7b35558722d5730d67224Linus Walleij			status &= ~MCI_IRQ1MASK;
8122686b4b408c25349aee7b35558722d5730d67224Linus Walleij		}
8132686b4b408c25349aee7b35558722d5730d67224Linus Walleij
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		status &= readl(host->base + MMCIMASK0);
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(status, host->base + MMCICLEAR);
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
81764de028948f449af17cf387f45a45f36ffd3c960Linus Walleij		dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		data = host->data;
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			      MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND) && data)
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mmci_data_irq(host, data, status);
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cmd = host->cmd;
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd)
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mmci_cmd_irq(host, cmd, status);
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = 1;
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} while (status);
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock(&host->lock);
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_RETVAL(ret);
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq)
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmci_host *host = mmc_priv(mmc);
8399e9430213f85ebdaf40026ec790295420efd0f91Linus Walleij	unsigned long flags;
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	WARN_ON(host->mrq != NULL);
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
843019a5f56ec195aceadada18aaaad0f67294bdaefNicolas Pitre	if (mrq->data && !is_power_of_2(mrq->data->blksz)) {
84464de028948f449af17cf387f45a45f36ffd3c960Linus Walleij		dev_err(mmc_dev(mmc), "unsupported block size (%d bytes)\n",
84564de028948f449af17cf387f45a45f36ffd3c960Linus Walleij			mrq->data->blksz);
846255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman		mrq->cmd->error = -EINVAL;
847255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman		mmc_request_done(mmc, mrq);
848255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman		return;
849255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman	}
850255d01af9a990fd5166f04ed0cc0b30b7b67e81ePierre Ossman
8519e9430213f85ebdaf40026ec790295420efd0f91Linus Walleij	spin_lock_irqsave(&host->lock, flags);
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->mrq = mrq;
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mrq->data && mrq->data->flags & MMC_DATA_READ)
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmci_start_data(host, mrq->data);
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmci_start_command(host, mrq->cmd, 0);
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8609e9430213f85ebdaf40026ec790295420efd0f91Linus Walleij	spin_unlock_irqrestore(&host->lock, flags);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmci_host *host = mmc_priv(mmc);
866a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij	u32 pwr = 0;
867a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij	unsigned long flags;
86899fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij	int ret;
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (ios->power_mode) {
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MMC_POWER_OFF:
87299fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij		if (host->vcc)
87399fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij			ret = mmc_regulator_set_ocr(mmc, host->vcc, 0);
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MMC_POWER_UP:
87699fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij		if (host->vcc) {
87799fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij			ret = mmc_regulator_set_ocr(mmc, host->vcc, ios->vdd);
87899fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij			if (ret) {
87999fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij				dev_err(mmc_dev(mmc), "unable to set OCR\n");
88099fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij				/*
88199fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij				 * The .set_ios() function in the mmc_host_ops
88299fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij				 * struct return void, and failing to set the
88399fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij				 * power should be rare so we print an error
88499fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij				 * and return here.
88599fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij				 */
88699fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij				return;
88799fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij			}
88899fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij		}
889bb8f563c848faa113059973f68c24a3bb6a9585eRabin Vincent		if (host->plat->vdd_handler)
890bb8f563c848faa113059973f68c24a3bb6a9585eRabin Vincent			pwr |= host->plat->vdd_handler(mmc_dev(mmc), ios->vdd,
891bb8f563c848faa113059973f68c24a3bb6a9585eRabin Vincent						       ios->power_mode);
892cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij		/* The ST version does not have this, fall through to POWER_ON */
893f17a1f06d2fa93f4825be572622eb02c4894db4eLinus Walleij		if (host->hw_designer != AMBA_VENDOR_ST) {
894cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij			pwr |= MCI_PWR_UP;
895cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij			break;
896cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij		}
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case MMC_POWER_ON:
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		pwr |= MCI_PWR_ON;
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
902cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
903f17a1f06d2fa93f4825be572622eb02c4894db4eLinus Walleij		if (host->hw_designer != AMBA_VENDOR_ST)
904cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij			pwr |= MCI_ROD;
905cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij		else {
906cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij			/*
907cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij			 * The ST Micro variant use the ROD bit for something
908cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij			 * else and only has OD (Open Drain).
909cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij			 */
910cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij			pwr |= MCI_OD;
911cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij		}
912cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij	}
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
914a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij	spin_lock_irqsave(&host->lock, flags);
915a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij
916a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij	mmci_set_clkreg(host, ios->clock);
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (host->pwr != pwr) {
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		host->pwr = pwr;
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(pwr, host->base + MMCIPOWER);
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
922a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij
923a6a6464a0ecd20c5f1594a4fe5b24af6181b7366Linus Walleij	spin_unlock_irqrestore(&host->lock, flags);
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
92689001446925d6da8785c3265a71316e34c6d15deRussell Kingstatic int mmci_get_ro(struct mmc_host *mmc)
92789001446925d6da8785c3265a71316e34c6d15deRussell King{
92889001446925d6da8785c3265a71316e34c6d15deRussell King	struct mmci_host *host = mmc_priv(mmc);
92989001446925d6da8785c3265a71316e34c6d15deRussell King
93089001446925d6da8785c3265a71316e34c6d15deRussell King	if (host->gpio_wp == -ENOSYS)
93189001446925d6da8785c3265a71316e34c6d15deRussell King		return -ENOSYS;
93289001446925d6da8785c3265a71316e34c6d15deRussell King
93318a06301158b5e4e9fae29e477f468e23f3eda90Linus Walleij	return gpio_get_value_cansleep(host->gpio_wp);
93489001446925d6da8785c3265a71316e34c6d15deRussell King}
93589001446925d6da8785c3265a71316e34c6d15deRussell King
93689001446925d6da8785c3265a71316e34c6d15deRussell Kingstatic int mmci_get_cd(struct mmc_host *mmc)
93789001446925d6da8785c3265a71316e34c6d15deRussell King{
93889001446925d6da8785c3265a71316e34c6d15deRussell King	struct mmci_host *host = mmc_priv(mmc);
9392971944582ff43b7dedbb460777052243ac9915aRabin Vincent	struct mmci_platform_data *plat = host->plat;
94089001446925d6da8785c3265a71316e34c6d15deRussell King	unsigned int status;
94189001446925d6da8785c3265a71316e34c6d15deRussell King
9424b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent	if (host->gpio_cd == -ENOSYS) {
9434b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent		if (!plat->status)
9444b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent			return 1; /* Assume always present */
9454b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent
9462971944582ff43b7dedbb460777052243ac9915aRabin Vincent		status = plat->status(mmc_dev(host->mmc));
9474b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent	} else
94818a06301158b5e4e9fae29e477f468e23f3eda90Linus Walleij		status = !!gpio_get_value_cansleep(host->gpio_cd)
94918a06301158b5e4e9fae29e477f468e23f3eda90Linus Walleij			^ plat->cd_invert;
95089001446925d6da8785c3265a71316e34c6d15deRussell King
95174bc80931c8bc34d24545f992a35349ad548897cRussell King	/*
95274bc80931c8bc34d24545f992a35349ad548897cRussell King	 * Use positive logic throughout - status is zero for no card,
95374bc80931c8bc34d24545f992a35349ad548897cRussell King	 * non-zero for card inserted.
95474bc80931c8bc34d24545f992a35349ad548897cRussell King	 */
95574bc80931c8bc34d24545f992a35349ad548897cRussell King	return status;
95689001446925d6da8785c3265a71316e34c6d15deRussell King}
95789001446925d6da8785c3265a71316e34c6d15deRussell King
958148b8b39c156424da22693d26adcb69800faf95eRabin Vincentstatic irqreturn_t mmci_cd_irq(int irq, void *dev_id)
959148b8b39c156424da22693d26adcb69800faf95eRabin Vincent{
960148b8b39c156424da22693d26adcb69800faf95eRabin Vincent	struct mmci_host *host = dev_id;
961148b8b39c156424da22693d26adcb69800faf95eRabin Vincent
962148b8b39c156424da22693d26adcb69800faf95eRabin Vincent	mmc_detect_change(host->mmc, msecs_to_jiffies(500));
963148b8b39c156424da22693d26adcb69800faf95eRabin Vincent
964148b8b39c156424da22693d26adcb69800faf95eRabin Vincent	return IRQ_HANDLED;
965148b8b39c156424da22693d26adcb69800faf95eRabin Vincent}
966148b8b39c156424da22693d26adcb69800faf95eRabin Vincent
967ab7aefd0b38297e6d2d71f43e8f81f9f4a36cdaeDavid Brownellstatic const struct mmc_host_ops mmci_ops = {
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.request	= mmci_request,
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.set_ios	= mmci_set_ios,
97089001446925d6da8785c3265a71316e34c6d15deRussell King	.get_ro		= mmci_get_ro,
97189001446925d6da8785c3265a71316e34c6d15deRussell King	.get_cd		= mmci_get_cd,
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
974aa25afad2ca60d19457849ea75e9c31236f4e174Russell Kingstatic int __devinit mmci_probe(struct amba_device *dev,
975aa25afad2ca60d19457849ea75e9c31236f4e174Russell King	const struct amba_id *id)
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9776ef297f86b62f187c59475784208f75c2ed8ccd8Linus Walleij	struct mmci_platform_data *plat = dev->dev.platform_data;
9784956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent	struct variant_data *variant = id->data;
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmci_host *host;
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_host *mmc;
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* must have platform data */
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!plat) {
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -EINVAL;
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = amba_request_regions(dev, DRIVER_NAME);
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret)
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev);
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!mmc) {
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENOMEM;
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto rel_regions;
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host = mmc_priv(mmc);
10004ea580f1db62c5419e6690878fd61a740f3aae8eRabin Vincent	host->mmc = mmc;
1001012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King
100289001446925d6da8785c3265a71316e34c6d15deRussell King	host->gpio_wp = -ENOSYS;
100389001446925d6da8785c3265a71316e34c6d15deRussell King	host->gpio_cd = -ENOSYS;
1004148b8b39c156424da22693d26adcb69800faf95eRabin Vincent	host->gpio_cd_irq = -1;
100589001446925d6da8785c3265a71316e34c6d15deRussell King
1006012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King	host->hw_designer = amba_manf(dev);
1007012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King	host->hw_revision = amba_rev(dev);
100864de028948f449af17cf387f45a45f36ffd3c960Linus Walleij	dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer);
100964de028948f449af17cf387f45a45f36ffd3c960Linus Walleij	dev_dbg(mmc_dev(mmc), "revision = 0x%01x\n", host->hw_revision);
1010012b7d339ce8c42d41e35b35c4acc3dd29501d52Russell King
1011ee569c43e340202fb0ba427c57b77568a32b9a3aRussell King	host->clk = clk_get(&dev->dev, NULL);
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (IS_ERR(host->clk)) {
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = PTR_ERR(host->clk);
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		host->clk = NULL;
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto host_free;
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = clk_enable(host->clk);
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret)
1020a8d3584a2df28827094f6338cde1303c467bc1f0Russell King		goto clk_free;
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->plat = plat;
10234956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent	host->variant = variant;
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	host->mclk = clk_get_rate(host->clk);
1025c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij	/*
1026c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij	 * According to the spec, mclk is max 100 MHz,
1027c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij	 * so we try to adjust the clock down to this,
1028c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij	 * (if possible).
1029c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij	 */
1030c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij	if (host->mclk > 100000000) {
1031c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij		ret = clk_set_rate(host->clk, 100000000);
1032c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij		if (ret < 0)
1033c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij			goto clk_disable;
1034c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij		host->mclk = clk_get_rate(host->clk);
103564de028948f449af17cf387f45a45f36ffd3c960Linus Walleij		dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n",
103664de028948f449af17cf387f45a45f36ffd3c960Linus Walleij			host->mclk);
1037c8df9a53e8d16877fc0b268b002af2a47a14643aLinus Walleij	}
1038c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	host->phybase = dev->res.start;
1039dc890c2dcd63a90de68ee5f0253eefbb89d725f0Linus Walleij	host->base = ioremap(dev->res.start, resource_size(&dev->res));
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!host->base) {
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = -ENOMEM;
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto clk_disable;
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc->ops = &mmci_ops;
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc->f_min = (host->mclk + 511) / 512;
1047808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij	/*
1048808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij	 * If the platform data supplies a maximum operating
1049808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij	 * frequency, this takes precedence. Else, we fall back
1050808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij	 * to using the module parameter, which has a (low)
1051808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij	 * default value in case it is not specified. Either
1052808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij	 * value must not exceed the clock rate into the block,
1053808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij	 * of course.
1054808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij	 */
1055808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij	if (plat->f_max)
1056808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij		mmc->f_max = min(host->mclk, plat->f_max);
1057808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij	else
1058808d97ccbe8e8251b1435e86c762965fd7e8a75eLinus Walleij		mmc->f_max = min(host->mclk, fmax);
105964de028948f449af17cf387f45a45f36ffd3c960Linus Walleij	dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
106064de028948f449af17cf387f45a45f36ffd3c960Linus Walleij
106134e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij#ifdef CONFIG_REGULATOR
106234e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij	/* If we're using the regulator framework, try to fetch a regulator */
106334e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij	host->vcc = regulator_get(&dev->dev, "vmmc");
106434e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij	if (IS_ERR(host->vcc))
106534e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij		host->vcc = NULL;
106634e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij	else {
106734e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij		int mask = mmc_regulator_get_ocrmask(host->vcc);
106834e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij
106934e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij		if (mask < 0)
107034e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij			dev_err(&dev->dev, "error getting OCR mask (%d)\n",
107134e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij				mask);
107234e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij		else {
107334e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij			host->mmc->ocr_avail = (u32) mask;
107434e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij			if (plat->ocr_mask)
107534e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij				dev_warn(&dev->dev,
107634e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij				 "Provided ocr_mask/setpower will not be used "
107734e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij				 "(using regulator instead)\n");
107834e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij		}
107934e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij	}
108034e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij#endif
108134e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij	/* Fall back to platform data if no regulator is found */
108234e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij	if (host->vcc == NULL)
108334e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij		mmc->ocr_avail = plat->ocr_mask;
10849e6c82cd3e1a739ef48bf8c1decc8e7a7d8de3acLinus Walleij	mmc->caps = plat->capabilities;
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * We can do SGIO
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
1089a36274e0184193e393fb82957925c3981a6b0477Martin K. Petersen	mmc->max_segs = NR_SG;
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
109208458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent	 * Since only a certain number of bits are valid in the data length
109308458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent	 * register, we must ensure that we don't exceed 2^num-1 bytes in a
109408458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent	 * single request.
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
109608458ef6eede6cf7d5a33c3a7c8bcdc3943012c2Rabin Vincent	mmc->max_req_size = (1 << variant->datalength_bits) - 1;
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * Set the maximum segment size.  Since we aren't doing DMA
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * (yet) we are only limited by the data length register.
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
110255db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman	mmc->max_seg_size = mmc->max_req_size;
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1104fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman	/*
1105fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman	 * Block size can be up to 2048 bytes, but must be a power of two.
1106fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman	 */
1107fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman	mmc->max_blk_size = 2048;
1108fe4a3c7a20f14d86022a8132adbf6ddb98e7197cPierre Ossman
110955db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman	/*
111055db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman	 * No limit on the number of blocks transferred.
111155db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman	 */
111255db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman	mmc->max_blk_count = mmc->max_req_size;
111355db890a838c7b37256241b1fc53d6344aa79cc0Pierre Ossman
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_init(&host->lock);
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(0, host->base + MMCIMASK0);
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(0, host->base + MMCIMASK1);
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	writel(0xfff, host->base + MMCICLEAR);
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
112089001446925d6da8785c3265a71316e34c6d15deRussell King	if (gpio_is_valid(plat->gpio_cd)) {
112189001446925d6da8785c3265a71316e34c6d15deRussell King		ret = gpio_request(plat->gpio_cd, DRIVER_NAME " (cd)");
112289001446925d6da8785c3265a71316e34c6d15deRussell King		if (ret == 0)
112389001446925d6da8785c3265a71316e34c6d15deRussell King			ret = gpio_direction_input(plat->gpio_cd);
112489001446925d6da8785c3265a71316e34c6d15deRussell King		if (ret == 0)
112589001446925d6da8785c3265a71316e34c6d15deRussell King			host->gpio_cd = plat->gpio_cd;
112689001446925d6da8785c3265a71316e34c6d15deRussell King		else if (ret != -ENOSYS)
112789001446925d6da8785c3265a71316e34c6d15deRussell King			goto err_gpio_cd;
1128148b8b39c156424da22693d26adcb69800faf95eRabin Vincent
1129148b8b39c156424da22693d26adcb69800faf95eRabin Vincent		ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd),
1130148b8b39c156424da22693d26adcb69800faf95eRabin Vincent					      mmci_cd_irq, 0,
1131148b8b39c156424da22693d26adcb69800faf95eRabin Vincent					      DRIVER_NAME " (cd)", host);
1132148b8b39c156424da22693d26adcb69800faf95eRabin Vincent		if (ret >= 0)
1133148b8b39c156424da22693d26adcb69800faf95eRabin Vincent			host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd);
113489001446925d6da8785c3265a71316e34c6d15deRussell King	}
113589001446925d6da8785c3265a71316e34c6d15deRussell King	if (gpio_is_valid(plat->gpio_wp)) {
113689001446925d6da8785c3265a71316e34c6d15deRussell King		ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)");
113789001446925d6da8785c3265a71316e34c6d15deRussell King		if (ret == 0)
113889001446925d6da8785c3265a71316e34c6d15deRussell King			ret = gpio_direction_input(plat->gpio_wp);
113989001446925d6da8785c3265a71316e34c6d15deRussell King		if (ret == 0)
114089001446925d6da8785c3265a71316e34c6d15deRussell King			host->gpio_wp = plat->gpio_wp;
114189001446925d6da8785c3265a71316e34c6d15deRussell King		else if (ret != -ENOSYS)
114289001446925d6da8785c3265a71316e34c6d15deRussell King			goto err_gpio_wp;
114389001446925d6da8785c3265a71316e34c6d15deRussell King	}
114489001446925d6da8785c3265a71316e34c6d15deRussell King
11454b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent	if ((host->plat->status || host->gpio_cd != -ENOSYS)
11464b8caec09562ce7e6e3aaf2954eef8ea73ba67b8Rabin Vincent	    && host->gpio_cd_irq < 0)
1147148b8b39c156424da22693d26adcb69800faf95eRabin Vincent		mmc->caps |= MMC_CAP_NEEDS_POLL;
1148148b8b39c156424da22693d26adcb69800faf95eRabin Vincent
1149dace145374b8e39aeb920304c358ab5e220341abThomas Gleixner	ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret)
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto unmap;
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11532686b4b408c25349aee7b35558722d5730d67224Linus Walleij	if (dev->irq[1] == NO_IRQ)
11542686b4b408c25349aee7b35558722d5730d67224Linus Walleij		host->singleirq = true;
11552686b4b408c25349aee7b35558722d5730d67224Linus Walleij	else {
11562686b4b408c25349aee7b35558722d5730d67224Linus Walleij		ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED,
11572686b4b408c25349aee7b35558722d5730d67224Linus Walleij				  DRIVER_NAME " (pio)", host);
11582686b4b408c25349aee7b35558722d5730d67224Linus Walleij		if (ret)
11592686b4b408c25349aee7b35558722d5730d67224Linus Walleij			goto irq0_free;
11602686b4b408c25349aee7b35558722d5730d67224Linus Walleij	}
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11628cb2815574278a1bf966f041cbfe5b7c91472dcdLinus Walleij	writel(MCI_IRQENABLE, host->base + MMCIMASK0);
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	amba_set_drvdata(dev, mmc);
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1166c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	dev_info(&dev->dev, "%s: PL%03x manf %x rev%u at 0x%08llx irq %d,%d (pio)\n",
1167c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		 mmc_hostname(mmc), amba_part(dev), amba_manf(dev),
1168c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		 amba_rev(dev), (unsigned long long)dev->res.start,
1169c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		 dev->irq[0], dev->irq[1]);
1170c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King
1171c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King	mmci_dma_setup(host);
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11738c11a94d86eb5489dc665bc566bf624e329d89faRussell King	mmc_add_host(mmc);
11748c11a94d86eb5489dc665bc566bf624e329d89faRussell King
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds irq0_free:
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(dev->irq[0], host);
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unmap:
118089001446925d6da8785c3265a71316e34c6d15deRussell King	if (host->gpio_wp != -ENOSYS)
118189001446925d6da8785c3265a71316e34c6d15deRussell King		gpio_free(host->gpio_wp);
118289001446925d6da8785c3265a71316e34c6d15deRussell King err_gpio_wp:
1183148b8b39c156424da22693d26adcb69800faf95eRabin Vincent	if (host->gpio_cd_irq >= 0)
1184148b8b39c156424da22693d26adcb69800faf95eRabin Vincent		free_irq(host->gpio_cd_irq, host);
118589001446925d6da8785c3265a71316e34c6d15deRussell King	if (host->gpio_cd != -ENOSYS)
118689001446925d6da8785c3265a71316e34c6d15deRussell King		gpio_free(host->gpio_cd);
118789001446925d6da8785c3265a71316e34c6d15deRussell King err_gpio_cd:
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(host->base);
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_disable:
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clk_disable(host->clk);
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds clk_free:
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	clk_put(host->clk);
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds host_free:
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mmc_free_host(mmc);
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds rel_regions:
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	amba_release_regions(dev);
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out:
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12016dc4a47a0cf423879b505af0e29997fca4088630Linus Walleijstatic int __devexit mmci_remove(struct amba_device *dev)
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_host *mmc = amba_get_drvdata(dev);
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	amba_set_drvdata(dev, NULL);
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mmc) {
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct mmci_host *host = mmc_priv(mmc);
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmc_remove_host(mmc);
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(0, host->base + MMCIMASK0);
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(0, host->base + MMCIMASK1);
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(0, host->base + MMCICOMMAND);
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(0, host->base + MMCIDATACTRL);
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1218c8ebae37034c0ead62eb4df8ef88e999ddb8d5cfRussell King		mmci_dma_release(host);
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		free_irq(dev->irq[0], host);
12202686b4b408c25349aee7b35558722d5730d67224Linus Walleij		if (!host->singleirq)
12212686b4b408c25349aee7b35558722d5730d67224Linus Walleij			free_irq(dev->irq[1], host);
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
122389001446925d6da8785c3265a71316e34c6d15deRussell King		if (host->gpio_wp != -ENOSYS)
122489001446925d6da8785c3265a71316e34c6d15deRussell King			gpio_free(host->gpio_wp);
1225148b8b39c156424da22693d26adcb69800faf95eRabin Vincent		if (host->gpio_cd_irq >= 0)
1226148b8b39c156424da22693d26adcb69800faf95eRabin Vincent			free_irq(host->gpio_cd_irq, host);
122789001446925d6da8785c3265a71316e34c6d15deRussell King		if (host->gpio_cd != -ENOSYS)
122889001446925d6da8785c3265a71316e34c6d15deRussell King			gpio_free(host->gpio_cd);
122989001446925d6da8785c3265a71316e34c6d15deRussell King
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iounmap(host->base);
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clk_disable(host->clk);
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		clk_put(host->clk);
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
123499fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij		if (host->vcc)
123599fc5131018cbdc3cf42ce09fb394a4e8b053c74Linus Walleij			mmc_regulator_set_ocr(mmc, host->vcc, 0);
123634e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij		regulator_put(host->vcc);
123734e84f39a27d059a3e6ec6e8b94aafa702e6f220Linus Walleij
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mmc_free_host(mmc);
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		amba_release_regions(dev);
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_PM
1247e5378ca8c0ab684bd9339dc6827dd5a042f9e6fcPavel Machekstatic int mmci_suspend(struct amba_device *dev, pm_message_t state)
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_host *mmc = amba_get_drvdata(dev);
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mmc) {
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct mmci_host *host = mmc_priv(mmc);
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12551a13f8fa76c880be41d6b1e6a2b44404bcbfdf9eMatt Fleming		ret = mmc_suspend_host(mmc);
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (ret == 0)
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			writel(0, host->base + MMCIMASK0);
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int mmci_resume(struct amba_device *dev)
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct mmc_host *mmc = amba_get_drvdata(dev);
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = 0;
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mmc) {
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct mmci_host *host = mmc_priv(mmc);
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		writel(MCI_IRQENABLE, host->base + MMCIMASK0);
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = mmc_resume_host(mmc);
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmci_suspend	NULL
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define mmci_resume	NULL
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct amba_id mmci_ids[] = {
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.id	= 0x00041180,
1286768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll		.mask	= 0xff0fffff,
12874956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent		.data	= &variant_arm,
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1290768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll		.id	= 0x01041180,
1291768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll		.mask	= 0xff0fffff,
1292768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll		.data	= &variant_arm_extended_fifo,
1293768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll	},
1294768fbc1876b3239f4c463c00ea1e78725554cf21Pawel Moll	{
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.id	= 0x00041181,
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.mask	= 0x000fffff,
12974956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent		.data	= &variant_arm,
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
1299cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij	/* ST Micro variants */
1300cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij	{
1301cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij		.id     = 0x00180180,
1302cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij		.mask   = 0x00ffffff,
13034956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent		.data	= &variant_u300,
1304cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij	},
1305cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij	{
1306cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij		.id     = 0x00280180,
1307cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij		.mask   = 0x00ffffff,
13084956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent		.data	= &variant_u300,
13094956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent	},
13104956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent	{
13114956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent		.id     = 0x00480180,
13124956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent		.mask   = 0x00ffffff,
13134956e10903fd3459306dd9438c1e714ba3068a2aRabin Vincent		.data	= &variant_ux500,
1314cc30d60e4ca0b68e7e3f906eddd1e5b995d349f8Linus Walleij	},
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ 0, 0 },
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct amba_driver mmci_driver = {
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.drv		= {
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		.name	= DRIVER_NAME,
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	},
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.probe		= mmci_probe,
13236dc4a47a0cf423879b505af0e29997fca4088630Linus Walleij	.remove		= __devexit_p(mmci_remove),
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.suspend	= mmci_suspend,
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.resume		= mmci_resume,
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id_table	= mmci_ids,
13271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init mmci_init(void)
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return amba_driver_register(&mmci_driver);
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit mmci_exit(void)
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	amba_driver_unregister(&mmci_driver);
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(mmci_init);
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(mmci_exit);
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(fmax, uint, 0444);
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ARM PrimeCell PL180/181 Multimedia Card Interface driver");
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1345