diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-05 13:18:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-05 13:18:21 -0400 |
commit | 0a053e8c71d666daf30da2d407147b1293923d8b (patch) | |
tree | 9ba3967845db9053cb2ca045f01a9454eb5e6230 /drivers/mmc | |
parent | 601cc11d054ae4b5e9b5babec3d8e4667a2cb9b5 (diff) | |
parent | 32ab83a56fdf42f543b86c349143c2a86ead9707 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc: (42 commits)
atmel-mci: fix sdc_reg typo
tmio_mmc: add maintainer
mmc: Add OpenFirmware bindings for SDHCI driver
sdhci: Add quirk for forcing maximum block size to 2048 bytes
sdhci: Add quirk for controllers that need IRQ re-init after reset
sdhci: Add quirk for controllers that need small delays for PIO
sdhci: Add set_clock callback and a quirk for nonstandard clocks
sdhci: Add get_{max,timeout}_clock callbacks
sdhci: Add support for hosts reporting inverted write-protect state
sdhci: Add support for card-detection polling
sdhci: Enable only relevant (DMA/PIO) interrupts during transfers
sdhci: Split card-detection IRQs management from sdhci_init()
sdhci: Add support for bus-specific IO memory accessors
mmc_spi: adjust for delayed data token response
omap_hsmmc: Wait for SDBP
omap_hsmmc: Fix MMC3 dma
omap_hsmmc: Disable SDBP at suspend
omap_hsmmc: Do not prefix slot name
omap_hsmmc: Allow cover switch to cause rescan
omap_hsmmc: Add 8-bit bus width mode support
...
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/card/block.c | 2 | ||||
-rw-r--r-- | drivers/mmc/core/bus.c | 8 | ||||
-rw-r--r-- | drivers/mmc/core/core.c | 18 | ||||
-rw-r--r-- | drivers/mmc/core/debugfs.c | 67 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_cis.c | 8 | ||||
-rw-r--r-- | drivers/mmc/core/sdio_ops.c | 8 | ||||
-rw-r--r-- | drivers/mmc/host/Kconfig | 29 | ||||
-rw-r--r-- | drivers/mmc/host/Makefile | 2 | ||||
-rw-r--r-- | drivers/mmc/host/atmel-mci.c | 2 | ||||
-rw-r--r-- | drivers/mmc/host/mmc_spi.c | 40 | ||||
-rw-r--r-- | drivers/mmc/host/mvsdio.c | 885 | ||||
-rw-r--r-- | drivers/mmc/host/mvsdio.h | 190 | ||||
-rw-r--r-- | drivers/mmc/host/omap_hsmmc.c | 355 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-of.c | 309 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 317 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 112 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc.c | 6 | ||||
-rw-r--r-- | drivers/mmc/host/tmio_mmc.h | 3 |
18 files changed, 2090 insertions, 271 deletions
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 513eb09a638f..fe8041e619ea 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -41,6 +41,8 @@ | |||
41 | 41 | ||
42 | #include "queue.h" | 42 | #include "queue.h" |
43 | 43 | ||
44 | MODULE_ALIAS("mmc:block"); | ||
45 | |||
44 | /* | 46 | /* |
45 | * max 8 partitions per card | 47 | * max 8 partitions per card |
46 | */ | 48 | */ |
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index f210a8ee6861..bdb165f93046 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
@@ -84,6 +84,14 @@ mmc_bus_uevent(struct device *dev, struct kobj_uevent_env *env) | |||
84 | } | 84 | } |
85 | 85 | ||
86 | retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); | 86 | retval = add_uevent_var(env, "MMC_NAME=%s", mmc_card_name(card)); |
87 | if (retval) | ||
88 | return retval; | ||
89 | |||
90 | /* | ||
91 | * Request the mmc_block device. Note: that this is a direct request | ||
92 | * for the module it carries no information as to what is inserted. | ||
93 | */ | ||
94 | retval = add_uevent_var(env, "MODALIAS=mmc:block"); | ||
87 | 95 | ||
88 | return retval; | 96 | return retval; |
89 | } | 97 | } |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 1445ea8f10a6..fa073ab3fa34 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -298,6 +298,21 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) | |||
298 | data->timeout_clks = 0; | 298 | data->timeout_clks = 0; |
299 | } | 299 | } |
300 | } | 300 | } |
301 | /* | ||
302 | * Some cards need very high timeouts if driven in SPI mode. | ||
303 | * The worst observed timeout was 900ms after writing a | ||
304 | * continuous stream of data until the internal logic | ||
305 | * overflowed. | ||
306 | */ | ||
307 | if (mmc_host_is_spi(card->host)) { | ||
308 | if (data->flags & MMC_DATA_WRITE) { | ||
309 | if (data->timeout_ns < 1000000000) | ||
310 | data->timeout_ns = 1000000000; /* 1s */ | ||
311 | } else { | ||
312 | if (data->timeout_ns < 100000000) | ||
313 | data->timeout_ns = 100000000; /* 100ms */ | ||
314 | } | ||
315 | } | ||
301 | } | 316 | } |
302 | EXPORT_SYMBOL(mmc_set_data_timeout); | 317 | EXPORT_SYMBOL(mmc_set_data_timeout); |
303 | 318 | ||
@@ -915,6 +930,7 @@ void mmc_stop_host(struct mmc_host *host) | |||
915 | spin_unlock_irqrestore(&host->lock, flags); | 930 | spin_unlock_irqrestore(&host->lock, flags); |
916 | #endif | 931 | #endif |
917 | 932 | ||
933 | cancel_delayed_work(&host->detect); | ||
918 | mmc_flush_scheduled_work(); | 934 | mmc_flush_scheduled_work(); |
919 | 935 | ||
920 | mmc_bus_get(host); | 936 | mmc_bus_get(host); |
@@ -942,6 +958,7 @@ void mmc_stop_host(struct mmc_host *host) | |||
942 | */ | 958 | */ |
943 | int mmc_suspend_host(struct mmc_host *host, pm_message_t state) | 959 | int mmc_suspend_host(struct mmc_host *host, pm_message_t state) |
944 | { | 960 | { |
961 | cancel_delayed_work(&host->detect); | ||
945 | mmc_flush_scheduled_work(); | 962 | mmc_flush_scheduled_work(); |
946 | 963 | ||
947 | mmc_bus_get(host); | 964 | mmc_bus_get(host); |
@@ -975,6 +992,7 @@ int mmc_resume_host(struct mmc_host *host) | |||
975 | mmc_bus_get(host); | 992 | mmc_bus_get(host); |
976 | if (host->bus_ops && !host->bus_dead) { | 993 | if (host->bus_ops && !host->bus_dead) { |
977 | mmc_power_up(host); | 994 | mmc_power_up(host); |
995 | mmc_select_voltage(host, host->ocr); | ||
978 | BUG_ON(!host->bus_ops->resume); | 996 | BUG_ON(!host->bus_ops->resume); |
979 | host->bus_ops->resume(host); | 997 | host->bus_ops->resume(host); |
980 | } | 998 | } |
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 1237bb4c722b..610dbd1fcc82 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c | |||
@@ -184,6 +184,68 @@ static int mmc_dbg_card_status_get(void *data, u64 *val) | |||
184 | DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, | 184 | DEFINE_SIMPLE_ATTRIBUTE(mmc_dbg_card_status_fops, mmc_dbg_card_status_get, |
185 | NULL, "%08llx\n"); | 185 | NULL, "%08llx\n"); |
186 | 186 | ||
187 | #define EXT_CSD_STR_LEN 1025 | ||
188 | |||
189 | static int mmc_ext_csd_open(struct inode *inode, struct file *filp) | ||
190 | { | ||
191 | struct mmc_card *card = inode->i_private; | ||
192 | char *buf; | ||
193 | ssize_t n = 0; | ||
194 | u8 *ext_csd; | ||
195 | int err, i; | ||
196 | |||
197 | buf = kmalloc(EXT_CSD_STR_LEN + 1, GFP_KERNEL); | ||
198 | if (!buf) | ||
199 | return -ENOMEM; | ||
200 | |||
201 | ext_csd = kmalloc(512, GFP_KERNEL); | ||
202 | if (!ext_csd) { | ||
203 | err = -ENOMEM; | ||
204 | goto out_free; | ||
205 | } | ||
206 | |||
207 | mmc_claim_host(card->host); | ||
208 | err = mmc_send_ext_csd(card, ext_csd); | ||
209 | mmc_release_host(card->host); | ||
210 | if (err) | ||
211 | goto out_free; | ||
212 | |||
213 | for (i = 511; i >= 0; i--) | ||
214 | n += sprintf(buf + n, "%02x", ext_csd[i]); | ||
215 | n += sprintf(buf + n, "\n"); | ||
216 | BUG_ON(n != EXT_CSD_STR_LEN); | ||
217 | |||
218 | filp->private_data = buf; | ||
219 | kfree(ext_csd); | ||
220 | return 0; | ||
221 | |||
222 | out_free: | ||
223 | kfree(buf); | ||
224 | kfree(ext_csd); | ||
225 | return err; | ||
226 | } | ||
227 | |||
228 | static ssize_t mmc_ext_csd_read(struct file *filp, char __user *ubuf, | ||
229 | size_t cnt, loff_t *ppos) | ||
230 | { | ||
231 | char *buf = filp->private_data; | ||
232 | |||
233 | return simple_read_from_buffer(ubuf, cnt, ppos, | ||
234 | buf, EXT_CSD_STR_LEN); | ||
235 | } | ||
236 | |||
237 | static int mmc_ext_csd_release(struct inode *inode, struct file *file) | ||
238 | { | ||
239 | kfree(file->private_data); | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static struct file_operations mmc_dbg_ext_csd_fops = { | ||
244 | .open = mmc_ext_csd_open, | ||
245 | .read = mmc_ext_csd_read, | ||
246 | .release = mmc_ext_csd_release, | ||
247 | }; | ||
248 | |||
187 | void mmc_add_card_debugfs(struct mmc_card *card) | 249 | void mmc_add_card_debugfs(struct mmc_card *card) |
188 | { | 250 | { |
189 | struct mmc_host *host = card->host; | 251 | struct mmc_host *host = card->host; |
@@ -211,6 +273,11 @@ void mmc_add_card_debugfs(struct mmc_card *card) | |||
211 | &mmc_dbg_card_status_fops)) | 273 | &mmc_dbg_card_status_fops)) |
212 | goto err; | 274 | goto err; |
213 | 275 | ||
276 | if (mmc_card_mmc(card)) | ||
277 | if (!debugfs_create_file("ext_csd", S_IRUSR, root, card, | ||
278 | &mmc_dbg_ext_csd_fops)) | ||
279 | goto err; | ||
280 | |||
214 | return; | 281 | return; |
215 | 282 | ||
216 | err: | 283 | err: |
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c index 956bd7677502..963f2937c5e3 100644 --- a/drivers/mmc/core/sdio_cis.c +++ b/drivers/mmc/core/sdio_cis.c | |||
@@ -223,10 +223,18 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func) | |||
223 | if (tpl_code == 0xff) | 223 | if (tpl_code == 0xff) |
224 | break; | 224 | break; |
225 | 225 | ||
226 | /* null entries have no link field or data */ | ||
227 | if (tpl_code == 0x00) | ||
228 | continue; | ||
229 | |||
226 | ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link); | 230 | ret = mmc_io_rw_direct(card, 0, 0, ptr++, 0, &tpl_link); |
227 | if (ret) | 231 | if (ret) |
228 | break; | 232 | break; |
229 | 233 | ||
234 | /* a size of 0xff also means we're done */ | ||
235 | if (tpl_link == 0xff) | ||
236 | break; | ||
237 | |||
230 | this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL); | 238 | this = kmalloc(sizeof(*this) + tpl_link, GFP_KERNEL); |
231 | if (!this) | 239 | if (!this) |
232 | return -ENOMEM; | 240 | return -ENOMEM; |
diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c index c8fa095a4488..4eb7825fd1a7 100644 --- a/drivers/mmc/core/sdio_ops.c +++ b/drivers/mmc/core/sdio_ops.c | |||
@@ -76,6 +76,10 @@ int mmc_io_rw_direct(struct mmc_card *card, int write, unsigned fn, | |||
76 | BUG_ON(!card); | 76 | BUG_ON(!card); |
77 | BUG_ON(fn > 7); | 77 | BUG_ON(fn > 7); |
78 | 78 | ||
79 | /* sanity check */ | ||
80 | if (addr & ~0x1FFFF) | ||
81 | return -EINVAL; | ||
82 | |||
79 | memset(&cmd, 0, sizeof(struct mmc_command)); | 83 | memset(&cmd, 0, sizeof(struct mmc_command)); |
80 | 84 | ||
81 | cmd.opcode = SD_IO_RW_DIRECT; | 85 | cmd.opcode = SD_IO_RW_DIRECT; |
@@ -125,6 +129,10 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, | |||
125 | WARN_ON(blocks == 0); | 129 | WARN_ON(blocks == 0); |
126 | WARN_ON(blksz == 0); | 130 | WARN_ON(blksz == 0); |
127 | 131 | ||
132 | /* sanity check */ | ||
133 | if (addr & ~0x1FFFF) | ||
134 | return -EINVAL; | ||
135 | |||
128 | memset(&mrq, 0, sizeof(struct mmc_request)); | 136 | memset(&mrq, 0, sizeof(struct mmc_request)); |
129 | memset(&cmd, 0, sizeof(struct mmc_command)); | 137 | memset(&cmd, 0, sizeof(struct mmc_command)); |
130 | memset(&data, 0, sizeof(struct mmc_data)); | 138 | memset(&data, 0, sizeof(struct mmc_data)); |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 6fbb246c40bb..b4cf691f3f64 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -37,6 +37,13 @@ config MMC_SDHCI | |||
37 | 37 | ||
38 | If unsure, say N. | 38 | If unsure, say N. |
39 | 39 | ||
40 | config MMC_SDHCI_IO_ACCESSORS | ||
41 | bool | ||
42 | depends on MMC_SDHCI | ||
43 | help | ||
44 | This is silent Kconfig symbol that is selected by the drivers that | ||
45 | need to overwrite SDHCI IO memory accessors. | ||
46 | |||
40 | config MMC_SDHCI_PCI | 47 | config MMC_SDHCI_PCI |
41 | tristate "SDHCI support on PCI bus" | 48 | tristate "SDHCI support on PCI bus" |
42 | depends on MMC_SDHCI && PCI | 49 | depends on MMC_SDHCI && PCI |
@@ -65,6 +72,17 @@ config MMC_RICOH_MMC | |||
65 | 72 | ||
66 | If unsure, say Y. | 73 | If unsure, say Y. |
67 | 74 | ||
75 | config MMC_SDHCI_OF | ||
76 | tristate "SDHCI support on OpenFirmware platforms" | ||
77 | depends on MMC_SDHCI && PPC_OF | ||
78 | select MMC_SDHCI_IO_ACCESSORS | ||
79 | help | ||
80 | This selects the OF support for Secure Digital Host Controller | ||
81 | Interfaces. So far, only the Freescale eSDHC controller is known | ||
82 | to exist on OF platforms. | ||
83 | |||
84 | If unsure, say N. | ||
85 | |||
68 | config MMC_OMAP | 86 | config MMC_OMAP |
69 | tristate "TI OMAP Multimedia Card Interface support" | 87 | tristate "TI OMAP Multimedia Card Interface support" |
70 | depends on ARCH_OMAP | 88 | depends on ARCH_OMAP |
@@ -171,6 +189,17 @@ config MMC_TIFM_SD | |||
171 | To compile this driver as a module, choose M here: the | 189 | To compile this driver as a module, choose M here: the |
172 | module will be called tifm_sd. | 190 | module will be called tifm_sd. |
173 | 191 | ||
192 | config MMC_MVSDIO | ||
193 | tristate "Marvell MMC/SD/SDIO host driver" | ||
194 | depends on PLAT_ORION | ||
195 | ---help--- | ||
196 | This selects the Marvell SDIO host driver. | ||
197 | SDIO may currently be found on the Kirkwood 88F6281 and 88F6192 | ||
198 | SoC controllers. | ||
199 | |||
200 | To compile this driver as a module, choose M here: the | ||
201 | module will be called mvsdio. | ||
202 | |||
174 | config MMC_SPI | 203 | config MMC_SPI |
175 | tristate "MMC/SD/SDIO over SPI" | 204 | tristate "MMC/SD/SDIO over SPI" |
176 | depends on SPI_MASTER && !HIGHMEM && HAS_DMA | 205 | depends on SPI_MASTER && !HIGHMEM && HAS_DMA |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index dedec55861d9..970a997620e1 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_MMC_MXC) += mxcmmc.o | |||
13 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o | 13 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o |
14 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o | 14 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o |
15 | obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o | 15 | obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o |
16 | obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o | ||
16 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 17 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
17 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o | 18 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o |
18 | obj-$(CONFIG_MMC_OMAP) += omap.o | 19 | obj-$(CONFIG_MMC_OMAP) += omap.o |
@@ -20,6 +21,7 @@ obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o | |||
20 | obj-$(CONFIG_MMC_AT91) += at91_mci.o | 21 | obj-$(CONFIG_MMC_AT91) += at91_mci.o |
21 | obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o | 22 | obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o |
22 | obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o | 23 | obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o |
24 | obj-$(CONFIG_MMC_MVSDIO) += mvsdio.o | ||
23 | obj-$(CONFIG_MMC_SPI) += mmc_spi.o | 25 | obj-$(CONFIG_MMC_SPI) += mmc_spi.o |
24 | ifeq ($(CONFIG_OF),y) | 26 | ifeq ($(CONFIG_OF),y) |
25 | obj-$(CONFIG_MMC_SPI) += of_mmc_spi.o | 27 | obj-$(CONFIG_MMC_SPI) += of_mmc_spi.o |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index e94e92001e7c..cf6a100bb38f 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -812,7 +812,7 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
812 | slot->sdc_reg |= MCI_SDCBUS_1BIT; | 812 | slot->sdc_reg |= MCI_SDCBUS_1BIT; |
813 | break; | 813 | break; |
814 | case MMC_BUS_WIDTH_4: | 814 | case MMC_BUS_WIDTH_4: |
815 | slot->sdc_reg = MCI_SDCBUS_4BIT; | 815 | slot->sdc_reg |= MCI_SDCBUS_4BIT; |
816 | break; | 816 | break; |
817 | } | 817 | } |
818 | 818 | ||
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 87e211df68ac..72f8bde4877a 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
@@ -279,8 +279,11 @@ static int mmc_spi_response_get(struct mmc_spi_host *host, | |||
279 | * so it can always DMA directly into the target buffer. | 279 | * so it can always DMA directly into the target buffer. |
280 | * It'd probably be better to memcpy() the first chunk and | 280 | * It'd probably be better to memcpy() the first chunk and |
281 | * avoid extra i/o calls... | 281 | * avoid extra i/o calls... |
282 | * | ||
283 | * Note we check for more than 8 bytes, because in practice, | ||
284 | * some SD cards are slow... | ||
282 | */ | 285 | */ |
283 | for (i = 2; i < 9; i++) { | 286 | for (i = 2; i < 16; i++) { |
284 | value = mmc_spi_readbytes(host, 1); | 287 | value = mmc_spi_readbytes(host, 1); |
285 | if (value < 0) | 288 | if (value < 0) |
286 | goto done; | 289 | goto done; |
@@ -609,6 +612,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, | |||
609 | struct spi_device *spi = host->spi; | 612 | struct spi_device *spi = host->spi; |
610 | int status, i; | 613 | int status, i; |
611 | struct scratch *scratch = host->data; | 614 | struct scratch *scratch = host->data; |
615 | u32 pattern; | ||
612 | 616 | ||
613 | if (host->mmc->use_spi_crc) | 617 | if (host->mmc->use_spi_crc) |
614 | scratch->crc_val = cpu_to_be16( | 618 | scratch->crc_val = cpu_to_be16( |
@@ -636,8 +640,27 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, | |||
636 | * doesn't necessarily tell whether the write operation succeeded; | 640 | * doesn't necessarily tell whether the write operation succeeded; |
637 | * it just says if the transmission was ok and whether *earlier* | 641 | * it just says if the transmission was ok and whether *earlier* |
638 | * writes succeeded; see the standard. | 642 | * writes succeeded; see the standard. |
643 | * | ||
644 | * In practice, there are (even modern SDHC-)cards which are late | ||
645 | * in sending the response, and miss the time frame by a few bits, | ||
646 | * so we have to cope with this situation and check the response | ||
647 | * bit-by-bit. Arggh!!! | ||
639 | */ | 648 | */ |
640 | switch (SPI_MMC_RESPONSE_CODE(scratch->status[0])) { | 649 | pattern = scratch->status[0] << 24; |
650 | pattern |= scratch->status[1] << 16; | ||
651 | pattern |= scratch->status[2] << 8; | ||
652 | pattern |= scratch->status[3]; | ||
653 | |||
654 | /* First 3 bit of pattern are undefined */ | ||
655 | pattern |= 0xE0000000; | ||
656 | |||
657 | /* left-adjust to leading 0 bit */ | ||
658 | while (pattern & 0x80000000) | ||
659 | pattern <<= 1; | ||
660 | /* right-adjust for pattern matching. Code is in bit 4..0 now. */ | ||
661 | pattern >>= 27; | ||
662 | |||
663 | switch (pattern) { | ||
641 | case SPI_RESPONSE_ACCEPTED: | 664 | case SPI_RESPONSE_ACCEPTED: |
642 | status = 0; | 665 | status = 0; |
643 | break; | 666 | break; |
@@ -668,8 +691,9 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, | |||
668 | /* Return when not busy. If we didn't collect that status yet, | 691 | /* Return when not busy. If we didn't collect that status yet, |
669 | * we'll need some more I/O. | 692 | * we'll need some more I/O. |
670 | */ | 693 | */ |
671 | for (i = 1; i < sizeof(scratch->status); i++) { | 694 | for (i = 4; i < sizeof(scratch->status); i++) { |
672 | if (scratch->status[i] != 0) | 695 | /* card is non-busy if the most recent bit is 1 */ |
696 | if (scratch->status[i] & 0x01) | ||
673 | return 0; | 697 | return 0; |
674 | } | 698 | } |
675 | return mmc_spi_wait_unbusy(host, timeout); | 699 | return mmc_spi_wait_unbusy(host, timeout); |
@@ -1204,10 +1228,12 @@ static int mmc_spi_probe(struct spi_device *spi) | |||
1204 | 1228 | ||
1205 | /* MMC and SD specs only seem to care that sampling is on the | 1229 | /* MMC and SD specs only seem to care that sampling is on the |
1206 | * rising edge ... meaning SPI modes 0 or 3. So either SPI mode | 1230 | * rising edge ... meaning SPI modes 0 or 3. So either SPI mode |
1207 | * should be legit. We'll use mode 0 since it seems to be a | 1231 | * should be legit. We'll use mode 0 since the steady state is 0, |
1208 | * bit less troublesome on some hardware ... unclear why. | 1232 | * which is appropriate for hotplugging, unless the platform data |
1233 | * specify mode 3 (if hardware is not compatible to mode 0). | ||
1209 | */ | 1234 | */ |
1210 | spi->mode = SPI_MODE_0; | 1235 | if (spi->mode != SPI_MODE_3) |
1236 | spi->mode = SPI_MODE_0; | ||
1211 | spi->bits_per_word = 8; | 1237 | spi->bits_per_word = 8; |
1212 | 1238 | ||
1213 | status = spi_setup(spi); | 1239 | status = spi_setup(spi); |
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c new file mode 100644 index 000000000000..b5c375d94ab3 --- /dev/null +++ b/drivers/mmc/host/mvsdio.c | |||
@@ -0,0 +1,885 @@ | |||
1 | /* | ||
2 | * Marvell MMC/SD/SDIO driver | ||
3 | * | ||
4 | * Authors: Maen Suleiman, Nicolas Pitre | ||
5 | * Copyright (C) 2008-2009 Marvell Ltd. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/mbus.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/dma-mapping.h> | ||
20 | #include <linux/scatterlist.h> | ||
21 | #include <linux/irq.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/mmc/host.h> | ||
24 | |||
25 | #include <asm/sizes.h> | ||
26 | #include <asm/unaligned.h> | ||
27 | #include <plat/mvsdio.h> | ||
28 | |||
29 | #include "mvsdio.h" | ||
30 | |||
31 | #define DRIVER_NAME "mvsdio" | ||
32 | |||
33 | static int maxfreq = MVSD_CLOCKRATE_MAX; | ||
34 | static int nodma; | ||
35 | |||
36 | struct mvsd_host { | ||
37 | void __iomem *base; | ||
38 | struct mmc_request *mrq; | ||
39 | spinlock_t lock; | ||
40 | unsigned int xfer_mode; | ||
41 | unsigned int intr_en; | ||
42 | unsigned int ctrl; | ||
43 | unsigned int pio_size; | ||
44 | void *pio_ptr; | ||
45 | unsigned int sg_frags; | ||
46 | unsigned int ns_per_clk; | ||
47 | unsigned int clock; | ||
48 | unsigned int base_clock; | ||
49 | struct timer_list timer; | ||
50 | struct mmc_host *mmc; | ||
51 | struct device *dev; | ||
52 | struct resource *res; | ||
53 | int irq; | ||
54 | int gpio_card_detect; | ||
55 | int gpio_write_protect; | ||
56 | }; | ||
57 | |||
58 | #define mvsd_write(offs, val) writel(val, iobase + (offs)) | ||
59 | #define mvsd_read(offs) readl(iobase + (offs)) | ||
60 | |||
61 | static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data) | ||
62 | { | ||
63 | void __iomem *iobase = host->base; | ||
64 | unsigned int tmout; | ||
65 | int tmout_index; | ||
66 | |||
67 | /* If timeout=0 then maximum timeout index is used. */ | ||
68 | tmout = DIV_ROUND_UP(data->timeout_ns, host->ns_per_clk); | ||
69 | tmout += data->timeout_clks; | ||
70 | tmout_index = fls(tmout - 1) - 12; | ||
71 | if (tmout_index < 0) | ||
72 | tmout_index = 0; | ||
73 | if (tmout_index > MVSD_HOST_CTRL_TMOUT_MAX) | ||
74 | tmout_index = MVSD_HOST_CTRL_TMOUT_MAX; | ||
75 | |||
76 | dev_dbg(host->dev, "data %s at 0x%08x: blocks=%d blksz=%d tmout=%u (%d)\n", | ||
77 | (data->flags & MMC_DATA_READ) ? "read" : "write", | ||
78 | (u32)sg_virt(data->sg), data->blocks, data->blksz, | ||
79 | tmout, tmout_index); | ||
80 | |||
81 | host->ctrl &= ~MVSD_HOST_CTRL_TMOUT_MASK; | ||
82 | host->ctrl |= MVSD_HOST_CTRL_TMOUT(tmout_index); | ||
83 | mvsd_write(MVSD_HOST_CTRL, host->ctrl); | ||
84 | mvsd_write(MVSD_BLK_COUNT, data->blocks); | ||
85 | mvsd_write(MVSD_BLK_SIZE, data->blksz); | ||
86 | |||
87 | if (nodma || (data->blksz | data->sg->offset) & 3) { | ||
88 | /* | ||
89 | * We cannot do DMA on a buffer which offset or size | ||
90 | * is not aligned on a 4-byte boundary. | ||
91 | */ | ||
92 | host->pio_size = data->blocks * data->blksz; | ||
93 | host->pio_ptr = sg_virt(data->sg); | ||
94 | if (!nodma) | ||
95 | printk(KERN_DEBUG "%s: fallback to PIO for data " | ||
96 | "at 0x%p size %d\n", | ||
97 | mmc_hostname(host->mmc), | ||
98 | host->pio_ptr, host->pio_size); | ||
99 | return 1; | ||
100 | } else { | ||
101 | dma_addr_t phys_addr; | ||
102 | int dma_dir = (data->flags & MMC_DATA_READ) ? | ||
103 | DMA_FROM_DEVICE : DMA_TO_DEVICE; | ||
104 | host->sg_frags = dma_map_sg(mmc_dev(host->mmc), data->sg, | ||
105 | data->sg_len, dma_dir); | ||
106 | phys_addr = sg_dma_address(data->sg); | ||
107 | mvsd_write(MVSD_SYS_ADDR_LOW, (u32)phys_addr & 0xffff); | ||
108 | mvsd_write(MVSD_SYS_ADDR_HI, (u32)phys_addr >> 16); | ||
109 | return 0; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | static void mvsd_request(struct mmc_host *mmc, struct mmc_request *mrq) | ||
114 | { | ||
115 | struct mvsd_host *host = mmc_priv(mmc); | ||
116 | void __iomem *iobase = host->base; | ||
117 | struct mmc_command *cmd = mrq->cmd; | ||
118 | u32 cmdreg = 0, xfer = 0, intr = 0; | ||
119 | unsigned long flags; | ||
120 | |||
121 | BUG_ON(host->mrq != NULL); | ||
122 | host->mrq = mrq; | ||
123 | |||
124 | dev_dbg(host->dev, "cmd %d (hw state 0x%04x)\n", | ||
125 | cmd->opcode, mvsd_read(MVSD_HW_STATE)); | ||
126 | |||
127 | cmdreg = MVSD_CMD_INDEX(cmd->opcode); | ||
128 | |||
129 | if (cmd->flags & MMC_RSP_BUSY) | ||
130 | cmdreg |= MVSD_CMD_RSP_48BUSY; | ||
131 | else if (cmd->flags & MMC_RSP_136) | ||
132 | cmdreg |= MVSD_CMD_RSP_136; | ||
133 | else if (cmd->flags & MMC_RSP_PRESENT) | ||
134 | cmdreg |= MVSD_CMD_RSP_48; | ||
135 | else | ||
136 | cmdreg |= MVSD_CMD_RSP_NONE; | ||
137 | |||
138 | if (cmd->flags & MMC_RSP_CRC) | ||
139 | cmdreg |= MVSD_CMD_CHECK_CMDCRC; | ||
140 | |||
141 | if (cmd->flags & MMC_RSP_OPCODE) | ||
142 | cmdreg |= MVSD_CMD_INDX_CHECK; | ||
143 | |||
144 | if (cmd->flags & MMC_RSP_PRESENT) { | ||
145 | cmdreg |= MVSD_UNEXPECTED_RESP; | ||
146 | intr |= MVSD_NOR_UNEXP_RSP; | ||
147 | } | ||
148 | |||
149 | if (mrq->data) { | ||
150 | struct mmc_data *data = mrq->data; | ||
151 | int pio; | ||
152 | |||
153 | cmdreg |= MVSD_CMD_DATA_PRESENT | MVSD_CMD_CHECK_DATACRC16; | ||
154 | xfer |= MVSD_XFER_MODE_HW_WR_DATA_EN; | ||
155 | if (data->flags & MMC_DATA_READ) | ||
156 | xfer |= MVSD_XFER_MODE_TO_HOST; | ||
157 | |||
158 | pio = mvsd_setup_data(host, data); | ||
159 | if (pio) { | ||
160 | xfer |= MVSD_XFER_MODE_PIO; | ||
161 | /* PIO section of mvsd_irq has comments on those bits */ | ||
162 | if (data->flags & MMC_DATA_WRITE) | ||
163 | intr |= MVSD_NOR_TX_AVAIL; | ||
164 | else if (host->pio_size > 32) | ||
165 | intr |= MVSD_NOR_RX_FIFO_8W; | ||
166 | else | ||
167 | intr |= MVSD_NOR_RX_READY; | ||
168 | } | ||
169 | |||
170 | if (data->stop) { | ||
171 | struct mmc_command *stop = data->stop; | ||
172 | u32 cmd12reg = 0; | ||
173 | |||
174 | mvsd_write(MVSD_AUTOCMD12_ARG_LOW, stop->arg & 0xffff); | ||
175 | mvsd_write(MVSD_AUTOCMD12_ARG_HI, stop->arg >> 16); | ||
176 | |||
177 | if (stop->flags & MMC_RSP_BUSY) | ||
178 | cmd12reg |= MVSD_AUTOCMD12_BUSY; | ||
179 | if (stop->flags & MMC_RSP_OPCODE) | ||
180 | cmd12reg |= MVSD_AUTOCMD12_INDX_CHECK; | ||
181 | cmd12reg |= MVSD_AUTOCMD12_INDEX(stop->opcode); | ||
182 | mvsd_write(MVSD_AUTOCMD12_CMD, cmd12reg); | ||
183 | |||
184 | xfer |= MVSD_XFER_MODE_AUTO_CMD12; | ||
185 | intr |= MVSD_NOR_AUTOCMD12_DONE; | ||
186 | } else { | ||
187 | intr |= MVSD_NOR_XFER_DONE; | ||
188 | } | ||
189 | } else { | ||
190 | intr |= MVSD_NOR_CMD_DONE; | ||
191 | } | ||
192 | |||
193 | mvsd_write(MVSD_ARG_LOW, cmd->arg & 0xffff); | ||
194 | mvsd_write(MVSD_ARG_HI, cmd->arg >> 16); | ||
195 | |||
196 | spin_lock_irqsave(&host->lock, flags); | ||
197 | |||
198 | host->xfer_mode &= MVSD_XFER_MODE_INT_CHK_EN; | ||
199 | host->xfer_mode |= xfer; | ||
200 | mvsd_write(MVSD_XFER_MODE, host->xfer_mode); | ||
201 | |||
202 | mvsd_write(MVSD_NOR_INTR_STATUS, ~MVSD_NOR_CARD_INT); | ||
203 | mvsd_write(MVSD_ERR_INTR_STATUS, 0xffff); | ||
204 | mvsd_write(MVSD_CMD, cmdreg); | ||
205 | |||
206 | host->intr_en &= MVSD_NOR_CARD_INT; | ||
207 | host->intr_en |= intr | MVSD_NOR_ERROR; | ||
208 | mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); | ||
209 | mvsd_write(MVSD_ERR_INTR_EN, 0xffff); | ||
210 | |||
211 | mod_timer(&host->timer, jiffies + 5 * HZ); | ||
212 | |||
213 | spin_unlock_irqrestore(&host->lock, flags); | ||
214 | } | ||
215 | |||
216 | static u32 mvsd_finish_cmd(struct mvsd_host *host, struct mmc_command *cmd, | ||
217 | u32 err_status) | ||
218 | { | ||
219 | void __iomem *iobase = host->base; | ||
220 | |||
221 | if (cmd->flags & MMC_RSP_136) { | ||
222 | unsigned int response[8], i; | ||
223 | for (i = 0; i < 8; i++) | ||
224 | response[i] = mvsd_read(MVSD_RSP(i)); | ||
225 | cmd->resp[0] = ((response[0] & 0x03ff) << 22) | | ||
226 | ((response[1] & 0xffff) << 6) | | ||
227 | ((response[2] & 0xfc00) >> 10); | ||
228 | cmd->resp[1] = ((response[2] & 0x03ff) << 22) | | ||
229 | ((response[3] & 0xffff) << 6) | | ||
230 | ((response[4] & 0xfc00) >> 10); | ||
231 | cmd->resp[2] = ((response[4] & 0x03ff) << 22) | | ||
232 | ((response[5] & 0xffff) << 6) | | ||
233 | ((response[6] & 0xfc00) >> 10); | ||
234 | cmd->resp[3] = ((response[6] & 0x03ff) << 22) | | ||
235 | ((response[7] & 0x3fff) << 8); | ||
236 | } else if (cmd->flags & MMC_RSP_PRESENT) { | ||
237 | unsigned int response[3], i; | ||
238 | for (i = 0; i < 3; i++) | ||
239 | response[i] = mvsd_read(MVSD_RSP(i)); | ||
240 | cmd->resp[0] = ((response[2] & 0x003f) << (8 - 8)) | | ||
241 | ((response[1] & 0xffff) << (14 - 8)) | | ||
242 | ((response[0] & 0x03ff) << (30 - 8)); | ||
243 | cmd->resp[1] = ((response[0] & 0xfc00) >> 10); | ||
244 | cmd->resp[2] = 0; | ||
245 | cmd->resp[3] = 0; | ||
246 | } | ||
247 | |||
248 | if (err_status & MVSD_ERR_CMD_TIMEOUT) { | ||
249 | cmd->error = -ETIMEDOUT; | ||
250 | } else if (err_status & (MVSD_ERR_CMD_CRC | MVSD_ERR_CMD_ENDBIT | | ||
251 | MVSD_ERR_CMD_INDEX | MVSD_ERR_CMD_STARTBIT)) { | ||
252 | cmd->error = -EILSEQ; | ||
253 | } | ||
254 | err_status &= ~(MVSD_ERR_CMD_TIMEOUT | MVSD_ERR_CMD_CRC | | ||
255 | MVSD_ERR_CMD_ENDBIT | MVSD_ERR_CMD_INDEX | | ||
256 | MVSD_ERR_CMD_STARTBIT); | ||
257 | |||
258 | return err_status; | ||
259 | } | ||
260 | |||
261 | static u32 mvsd_finish_data(struct mvsd_host *host, struct mmc_data *data, | ||
262 | u32 err_status) | ||
263 | { | ||
264 | void __iomem *iobase = host->base; | ||
265 | |||
266 | if (host->pio_ptr) { | ||
267 | host->pio_ptr = NULL; | ||
268 | host->pio_size = 0; | ||
269 | } else { | ||
270 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->sg_frags, | ||
271 | (data->flags & MMC_DATA_READ) ? | ||
272 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
273 | } | ||
274 | |||
275 | if (err_status & MVSD_ERR_DATA_TIMEOUT) | ||
276 | data->error = -ETIMEDOUT; | ||
277 | else if (err_status & (MVSD_ERR_DATA_CRC | MVSD_ERR_DATA_ENDBIT)) | ||
278 | data->error = -EILSEQ; | ||
279 | else if (err_status & MVSD_ERR_XFER_SIZE) | ||
280 | data->error = -EBADE; | ||
281 | err_status &= ~(MVSD_ERR_DATA_TIMEOUT | MVSD_ERR_DATA_CRC | | ||
282 | MVSD_ERR_DATA_ENDBIT | MVSD_ERR_XFER_SIZE); | ||
283 | |||
284 | dev_dbg(host->dev, "data done: blocks_left=%d, bytes_left=%d\n", | ||
285 | mvsd_read(MVSD_CURR_BLK_LEFT), mvsd_read(MVSD_CURR_BYTE_LEFT)); | ||
286 | data->bytes_xfered = | ||
287 | (data->blocks - mvsd_read(MVSD_CURR_BLK_LEFT)) * data->blksz; | ||
288 | /* We can't be sure about the last block when errors are detected */ | ||
289 | if (data->bytes_xfered && data->error) | ||
290 | data->bytes_xfered -= data->blksz; | ||
291 | |||
292 | /* Handle Auto cmd 12 response */ | ||
293 | if (data->stop) { | ||
294 | unsigned int response[3], i; | ||
295 | for (i = 0; i < 3; i++) | ||
296 | response[i] = mvsd_read(MVSD_AUTO_RSP(i)); | ||
297 | data->stop->resp[0] = ((response[2] & 0x003f) << (8 - 8)) | | ||
298 | ((response[1] & 0xffff) << (14 - 8)) | | ||
299 | ((response[0] & 0x03ff) << (30 - 8)); | ||
300 | data->stop->resp[1] = ((response[0] & 0xfc00) >> 10); | ||
301 | data->stop->resp[2] = 0; | ||
302 | data->stop->resp[3] = 0; | ||
303 | |||
304 | if (err_status & MVSD_ERR_AUTOCMD12) { | ||
305 | u32 err_cmd12 = mvsd_read(MVSD_AUTOCMD12_ERR_STATUS); | ||
306 | dev_dbg(host->dev, "c12err 0x%04x\n", err_cmd12); | ||
307 | if (err_cmd12 & MVSD_AUTOCMD12_ERR_NOTEXE) | ||
308 | data->stop->error = -ENOEXEC; | ||
309 | else if (err_cmd12 & MVSD_AUTOCMD12_ERR_TIMEOUT) | ||
310 | data->stop->error = -ETIMEDOUT; | ||
311 | else if (err_cmd12) | ||
312 | data->stop->error = -EILSEQ; | ||
313 | err_status &= ~MVSD_ERR_AUTOCMD12; | ||
314 | } | ||
315 | } | ||
316 | |||
317 | return err_status; | ||
318 | } | ||
319 | |||
320 | static irqreturn_t mvsd_irq(int irq, void *dev) | ||
321 | { | ||
322 | struct mvsd_host *host = dev; | ||
323 | void __iomem *iobase = host->base; | ||
324 | u32 intr_status, intr_done_mask; | ||
325 | int irq_handled = 0; | ||
326 | |||
327 | intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); | ||
328 | dev_dbg(host->dev, "intr 0x%04x intr_en 0x%04x hw_state 0x%04x\n", | ||
329 | intr_status, mvsd_read(MVSD_NOR_INTR_EN), | ||
330 | mvsd_read(MVSD_HW_STATE)); | ||
331 | |||
332 | spin_lock(&host->lock); | ||
333 | |||
334 | /* PIO handling, if needed. Messy business... */ | ||
335 | if (host->pio_size && | ||
336 | (intr_status & host->intr_en & | ||
337 | (MVSD_NOR_RX_READY | MVSD_NOR_RX_FIFO_8W))) { | ||
338 | u16 *p = host->pio_ptr; | ||
339 | int s = host->pio_size; | ||
340 | while (s >= 32 && (intr_status & MVSD_NOR_RX_FIFO_8W)) { | ||
341 | readsw(iobase + MVSD_FIFO, p, 16); | ||
342 | p += 16; | ||
343 | s -= 32; | ||
344 | intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); | ||
345 | } | ||
346 | /* | ||
347 | * Normally we'd use < 32 here, but the RX_FIFO_8W bit | ||
348 | * doesn't appear to assert when there is exactly 32 bytes | ||
349 | * (8 words) left to fetch in a transfer. | ||
350 | */ | ||
351 | if (s <= 32) { | ||
352 | while (s >= 4 && (intr_status & MVSD_NOR_RX_READY)) { | ||
353 | put_unaligned(mvsd_read(MVSD_FIFO), p++); | ||
354 | put_unaligned(mvsd_read(MVSD_FIFO), p++); | ||
355 | s -= 4; | ||
356 | intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); | ||
357 | } | ||
358 | if (s && s < 4 && (intr_status & MVSD_NOR_RX_READY)) { | ||
359 | u16 val[2] = {0, 0}; | ||
360 | val[0] = mvsd_read(MVSD_FIFO); | ||
361 | val[1] = mvsd_read(MVSD_FIFO); | ||
362 | memcpy(p, &val, s); | ||
363 | s = 0; | ||
364 | intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); | ||
365 | } | ||
366 | if (s == 0) { | ||
367 | host->intr_en &= | ||
368 | ~(MVSD_NOR_RX_READY | MVSD_NOR_RX_FIFO_8W); | ||
369 | mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); | ||
370 | } else if (host->intr_en & MVSD_NOR_RX_FIFO_8W) { | ||
371 | host->intr_en &= ~MVSD_NOR_RX_FIFO_8W; | ||
372 | host->intr_en |= MVSD_NOR_RX_READY; | ||
373 | mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); | ||
374 | } | ||
375 | } | ||
376 | dev_dbg(host->dev, "pio %d intr 0x%04x hw_state 0x%04x\n", | ||
377 | s, intr_status, mvsd_read(MVSD_HW_STATE)); | ||
378 | host->pio_ptr = p; | ||
379 | host->pio_size = s; | ||
380 | irq_handled = 1; | ||
381 | } else if (host->pio_size && | ||
382 | (intr_status & host->intr_en & | ||
383 | (MVSD_NOR_TX_AVAIL | MVSD_NOR_TX_FIFO_8W))) { | ||
384 | u16 *p = host->pio_ptr; | ||
385 | int s = host->pio_size; | ||
386 | /* | ||
387 | * The TX_FIFO_8W bit is unreliable. When set, bursting | ||
388 | * 16 halfwords all at once in the FIFO drops data. Actually | ||
389 | * TX_AVAIL does go off after only one word is pushed even if | ||
390 | * TX_FIFO_8W remains set. | ||
391 | */ | ||
392 | while (s >= 4 && (intr_status & MVSD_NOR_TX_AVAIL)) { | ||
393 | mvsd_write(MVSD_FIFO, get_unaligned(p++)); | ||
394 | mvsd_write(MVSD_FIFO, get_unaligned(p++)); | ||
395 | s -= 4; | ||
396 | intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); | ||
397 | } | ||
398 | if (s < 4) { | ||
399 | if (s && (intr_status & MVSD_NOR_TX_AVAIL)) { | ||
400 | u16 val[2] = {0, 0}; | ||
401 | memcpy(&val, p, s); | ||
402 | mvsd_write(MVSD_FIFO, val[0]); | ||
403 | mvsd_write(MVSD_FIFO, val[1]); | ||
404 | s = 0; | ||
405 | intr_status = mvsd_read(MVSD_NOR_INTR_STATUS); | ||
406 | } | ||
407 | if (s == 0) { | ||
408 | host->intr_en &= | ||
409 | ~(MVSD_NOR_TX_AVAIL | MVSD_NOR_TX_FIFO_8W); | ||
410 | mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); | ||
411 | } | ||
412 | } | ||
413 | dev_dbg(host->dev, "pio %d intr 0x%04x hw_state 0x%04x\n", | ||
414 | s, intr_status, mvsd_read(MVSD_HW_STATE)); | ||
415 | host->pio_ptr = p; | ||
416 | host->pio_size = s; | ||
417 | irq_handled = 1; | ||
418 | } | ||
419 | |||
420 | mvsd_write(MVSD_NOR_INTR_STATUS, intr_status); | ||
421 | |||
422 | intr_done_mask = MVSD_NOR_CARD_INT | MVSD_NOR_RX_READY | | ||
423 | MVSD_NOR_RX_FIFO_8W | MVSD_NOR_TX_FIFO_8W; | ||
424 | if (intr_status & host->intr_en & ~intr_done_mask) { | ||
425 | struct mmc_request *mrq = host->mrq; | ||
426 | struct mmc_command *cmd = mrq->cmd; | ||
427 | u32 err_status = 0; | ||
428 | |||
429 | del_timer(&host->timer); | ||
430 | host->mrq = NULL; | ||
431 | |||
432 | host->intr_en &= MVSD_NOR_CARD_INT; | ||
433 | mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); | ||
434 | mvsd_write(MVSD_ERR_INTR_EN, 0); | ||
435 | |||
436 | spin_unlock(&host->lock); | ||
437 | |||
438 | if (intr_status & MVSD_NOR_UNEXP_RSP) { | ||
439 | cmd->error = -EPROTO; | ||
440 | } else if (intr_status & MVSD_NOR_ERROR) { | ||
441 | err_status = mvsd_read(MVSD_ERR_INTR_STATUS); | ||
442 | dev_dbg(host->dev, "err 0x%04x\n", err_status); | ||
443 | } | ||
444 | |||
445 | err_status = mvsd_finish_cmd(host, cmd, err_status); | ||
446 | if (mrq->data) | ||
447 | err_status = mvsd_finish_data(host, mrq->data, err_status); | ||
448 | if (err_status) { | ||
449 | printk(KERN_ERR "%s: unhandled error status %#04x\n", | ||
450 | mmc_hostname(host->mmc), err_status); | ||
451 | cmd->error = -ENOMSG; | ||
452 | } | ||
453 | |||
454 | mmc_request_done(host->mmc, mrq); | ||
455 | irq_handled = 1; | ||
456 | } else | ||
457 | spin_unlock(&host->lock); | ||
458 | |||
459 | if (intr_status & MVSD_NOR_CARD_INT) { | ||
460 | mmc_signal_sdio_irq(host->mmc); | ||
461 | irq_handled = 1; | ||
462 | } | ||
463 | |||
464 | if (irq_handled) | ||
465 | return IRQ_HANDLED; | ||
466 | |||
467 | printk(KERN_ERR "%s: unhandled interrupt status=0x%04x en=0x%04x " | ||
468 | "pio=%d\n", mmc_hostname(host->mmc), intr_status, | ||
469 | host->intr_en, host->pio_size); | ||
470 | return IRQ_NONE; | ||
471 | } | ||
472 | |||
473 | static void mvsd_timeout_timer(unsigned long data) | ||
474 | { | ||
475 | struct mvsd_host *host = (struct mvsd_host *)data; | ||
476 | void __iomem *iobase = host->base; | ||
477 | struct mmc_request *mrq; | ||
478 | unsigned long flags; | ||
479 | |||
480 | spin_lock_irqsave(&host->lock, flags); | ||
481 | mrq = host->mrq; | ||
482 | if (mrq) { | ||
483 | printk(KERN_ERR "%s: Timeout waiting for hardware interrupt.\n", | ||
484 | mmc_hostname(host->mmc)); | ||
485 | printk(KERN_ERR "%s: hw_state=0x%04x, intr_status=0x%04x " | ||
486 | "intr_en=0x%04x\n", mmc_hostname(host->mmc), | ||
487 | mvsd_read(MVSD_HW_STATE), | ||
488 | mvsd_read(MVSD_NOR_INTR_STATUS), | ||
489 | mvsd_read(MVSD_NOR_INTR_EN)); | ||
490 | |||
491 | host->mrq = NULL; | ||
492 | |||
493 | mvsd_write(MVSD_SW_RESET, MVSD_SW_RESET_NOW); | ||
494 | |||
495 | host->xfer_mode &= MVSD_XFER_MODE_INT_CHK_EN; | ||
496 | mvsd_write(MVSD_XFER_MODE, host->xfer_mode); | ||
497 | |||
498 | host->intr_en &= MVSD_NOR_CARD_INT; | ||
499 | mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); | ||
500 | mvsd_write(MVSD_ERR_INTR_EN, 0); | ||
501 | mvsd_write(MVSD_ERR_INTR_STATUS, 0xffff); | ||
502 | |||
503 | mrq->cmd->error = -ETIMEDOUT; | ||
504 | mvsd_finish_cmd(host, mrq->cmd, 0); | ||
505 | if (mrq->data) { | ||
506 | mrq->data->error = -ETIMEDOUT; | ||
507 | mvsd_finish_data(host, mrq->data, 0); | ||
508 | } | ||
509 | } | ||
510 | spin_unlock_irqrestore(&host->lock, flags); | ||
511 | |||
512 | if (mrq) | ||
513 | mmc_request_done(host->mmc, mrq); | ||
514 | } | ||
515 | |||
516 | static irqreturn_t mvsd_card_detect_irq(int irq, void *dev) | ||
517 | { | ||
518 | struct mvsd_host *host = dev; | ||
519 | mmc_detect_change(host->mmc, msecs_to_jiffies(100)); | ||
520 | return IRQ_HANDLED; | ||
521 | } | ||
522 | |||
523 | static void mvsd_enable_sdio_irq(struct mmc_host *mmc, int enable) | ||
524 | { | ||
525 | struct mvsd_host *host = mmc_priv(mmc); | ||
526 | void __iomem *iobase = host->base; | ||
527 | unsigned long flags; | ||
528 | |||
529 | spin_lock_irqsave(&host->lock, flags); | ||
530 | if (enable) { | ||
531 | host->xfer_mode |= MVSD_XFER_MODE_INT_CHK_EN; | ||
532 | host->intr_en |= MVSD_NOR_CARD_INT; | ||
533 | } else { | ||
534 | host->xfer_mode &= ~MVSD_XFER_MODE_INT_CHK_EN; | ||
535 | host->intr_en &= ~MVSD_NOR_CARD_INT; | ||
536 | } | ||
537 | mvsd_write(MVSD_XFER_MODE, host->xfer_mode); | ||
538 | mvsd_write(MVSD_NOR_INTR_EN, host->intr_en); | ||
539 | spin_unlock_irqrestore(&host->lock, flags); | ||
540 | } | ||
541 | |||
542 | static int mvsd_get_ro(struct mmc_host *mmc) | ||
543 | { | ||
544 | struct mvsd_host *host = mmc_priv(mmc); | ||
545 | |||
546 | if (host->gpio_write_protect) | ||
547 | return gpio_get_value(host->gpio_write_protect); | ||
548 | |||
549 | /* | ||
550 | * Board doesn't support read only detection; let the mmc core | ||
551 | * decide what to do. | ||
552 | */ | ||
553 | return -ENOSYS; | ||
554 | } | ||
555 | |||
556 | static void mvsd_power_up(struct mvsd_host *host) | ||
557 | { | ||
558 | void __iomem *iobase = host->base; | ||
559 | dev_dbg(host->dev, "power up\n"); | ||
560 | mvsd_write(MVSD_NOR_INTR_EN, 0); | ||
561 | mvsd_write(MVSD_ERR_INTR_EN, 0); | ||
562 | mvsd_write(MVSD_SW_RESET, MVSD_SW_RESET_NOW); | ||
563 | mvsd_write(MVSD_XFER_MODE, 0); | ||
564 | mvsd_write(MVSD_NOR_STATUS_EN, 0xffff); | ||
565 | mvsd_write(MVSD_ERR_STATUS_EN, 0xffff); | ||
566 | mvsd_write(MVSD_NOR_INTR_STATUS, 0xffff); | ||
567 | mvsd_write(MVSD_ERR_INTR_STATUS, 0xffff); | ||
568 | } | ||
569 | |||
570 | static void mvsd_power_down(struct mvsd_host *host) | ||
571 | { | ||
572 | void __iomem *iobase = host->base; | ||
573 | dev_dbg(host->dev, "power down\n"); | ||
574 | mvsd_write(MVSD_NOR_INTR_EN, 0); | ||
575 | mvsd_write(MVSD_ERR_INTR_EN, 0); | ||
576 | mvsd_write(MVSD_SW_RESET, MVSD_SW_RESET_NOW); | ||
577 | mvsd_write(MVSD_XFER_MODE, MVSD_XFER_MODE_STOP_CLK); | ||
578 | mvsd_write(MVSD_NOR_STATUS_EN, 0); | ||
579 | mvsd_write(MVSD_ERR_STATUS_EN, 0); | ||
580 | mvsd_write(MVSD_NOR_INTR_STATUS, 0xffff); | ||
581 | mvsd_write(MVSD_ERR_INTR_STATUS, 0xffff); | ||
582 | } | ||
583 | |||
584 | static void mvsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
585 | { | ||
586 | struct mvsd_host *host = mmc_priv(mmc); | ||
587 | void __iomem *iobase = host->base; | ||
588 | u32 ctrl_reg = 0; | ||
589 | |||
590 | if (ios->power_mode == MMC_POWER_UP) | ||
591 | mvsd_power_up(host); | ||
592 | |||
593 | if (ios->clock == 0) { | ||
594 | mvsd_write(MVSD_XFER_MODE, MVSD_XFER_MODE_STOP_CLK); | ||
595 | mvsd_write(MVSD_CLK_DIV, MVSD_BASE_DIV_MAX); | ||
596 | host->clock = 0; | ||
597 | dev_dbg(host->dev, "clock off\n"); | ||
598 | } else if (ios->clock != host->clock) { | ||
599 | u32 m = DIV_ROUND_UP(host->base_clock, ios->clock) - 1; | ||
600 | if (m > MVSD_BASE_DIV_MAX) | ||
601 | m = MVSD_BASE_DIV_MAX; | ||
602 | mvsd_write(MVSD_CLK_DIV, m); | ||
603 | host->clock = ios->clock; | ||
604 | host->ns_per_clk = 1000000000 / (host->base_clock / (m+1)); | ||
605 | dev_dbg(host->dev, "clock=%d (%d), div=0x%04x\n", | ||
606 | ios->clock, host->base_clock / (m+1), m); | ||
607 | } | ||
608 | |||
609 | /* default transfer mode */ | ||
610 | ctrl_reg |= MVSD_HOST_CTRL_BIG_ENDIAN; | ||
611 | ctrl_reg &= ~MVSD_HOST_CTRL_LSB_FIRST; | ||
612 | |||
613 | /* default to maximum timeout */ | ||
614 | ctrl_reg |= MVSD_HOST_CTRL_TMOUT_MASK; | ||
615 | ctrl_reg |= MVSD_HOST_CTRL_TMOUT_EN; | ||
616 | |||
617 | if (ios->bus_mode == MMC_BUSMODE_PUSHPULL) | ||
618 | ctrl_reg |= MVSD_HOST_CTRL_PUSH_PULL_EN; | ||
619 | |||
620 | if (ios->bus_width == MMC_BUS_WIDTH_4) | ||
621 | ctrl_reg |= MVSD_HOST_CTRL_DATA_WIDTH_4_BITS; | ||
622 | |||
623 | if (ios->timing == MMC_TIMING_MMC_HS || | ||
624 | ios->timing == MMC_TIMING_SD_HS) | ||
625 | ctrl_reg |= MVSD_HOST_CTRL_HI_SPEED_EN; | ||
626 | |||
627 | host->ctrl = ctrl_reg; | ||
628 | mvsd_write(MVSD_HOST_CTRL, ctrl_reg); | ||
629 | dev_dbg(host->dev, "ctrl 0x%04x: %s %s %s\n", ctrl_reg, | ||
630 | (ctrl_reg & MVSD_HOST_CTRL_PUSH_PULL_EN) ? | ||
631 | "push-pull" : "open-drain", | ||
632 | (ctrl_reg & MVSD_HOST_CTRL_DATA_WIDTH_4_BITS) ? | ||
633 | "4bit-width" : "1bit-width", | ||
634 | (ctrl_reg & MVSD_HOST_CTRL_HI_SPEED_EN) ? | ||
635 | "high-speed" : ""); | ||
636 | |||
637 | if (ios->power_mode == MMC_POWER_OFF) | ||
638 | mvsd_power_down(host); | ||
639 | } | ||
640 | |||
641 | static const struct mmc_host_ops mvsd_ops = { | ||
642 | .request = mvsd_request, | ||
643 | .get_ro = mvsd_get_ro, | ||
644 | .set_ios = mvsd_set_ios, | ||
645 | .enable_sdio_irq = mvsd_enable_sdio_irq, | ||
646 | }; | ||
647 | |||
648 | static void __init mv_conf_mbus_windows(struct mvsd_host *host, | ||
649 | struct mbus_dram_target_info *dram) | ||
650 | { | ||
651 | void __iomem *iobase = host->base; | ||
652 | int i; | ||
653 | |||
654 | for (i = 0; i < 4; i++) { | ||
655 | writel(0, iobase + MVSD_WINDOW_CTRL(i)); | ||
656 | writel(0, iobase + MVSD_WINDOW_BASE(i)); | ||
657 | } | ||
658 | |||
659 | for (i = 0; i < dram->num_cs; i++) { | ||
660 | struct mbus_dram_window *cs = dram->cs + i; | ||
661 | writel(((cs->size - 1) & 0xffff0000) | | ||
662 | (cs->mbus_attr << 8) | | ||
663 | (dram->mbus_dram_target_id << 4) | 1, | ||
664 | iobase + MVSD_WINDOW_CTRL(i)); | ||
665 | writel(cs->base, iobase + MVSD_WINDOW_BASE(i)); | ||
666 | } | ||
667 | } | ||
668 | |||
669 | static int __init mvsd_probe(struct platform_device *pdev) | ||
670 | { | ||
671 | struct mmc_host *mmc = NULL; | ||
672 | struct mvsd_host *host = NULL; | ||
673 | const struct mvsdio_platform_data *mvsd_data; | ||
674 | struct resource *r; | ||
675 | int ret, irq; | ||
676 | |||
677 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
678 | irq = platform_get_irq(pdev, 0); | ||
679 | mvsd_data = pdev->dev.platform_data; | ||
680 | if (!r || irq < 0 || !mvsd_data) | ||
681 | return -ENXIO; | ||
682 | |||
683 | r = request_mem_region(r->start, SZ_1K, DRIVER_NAME); | ||
684 | if (!r) | ||
685 | return -EBUSY; | ||
686 | |||
687 | mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); | ||
688 | if (!mmc) { | ||
689 | ret = -ENOMEM; | ||
690 | goto out; | ||
691 | } | ||
692 | |||
693 | host = mmc_priv(mmc); | ||
694 | host->mmc = mmc; | ||
695 | host->dev = &pdev->dev; | ||
696 | host->res = r; | ||
697 | host->base_clock = mvsd_data->clock / 2; | ||
698 | |||
699 | mmc->ops = &mvsd_ops; | ||
700 | |||
701 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
702 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ | | ||
703 | MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED; | ||
704 | |||
705 | mmc->f_min = DIV_ROUND_UP(host->base_clock, MVSD_BASE_DIV_MAX); | ||
706 | mmc->f_max = maxfreq; | ||
707 | |||
708 | mmc->max_blk_size = 2048; | ||
709 | mmc->max_blk_count = 65535; | ||
710 | |||
711 | mmc->max_hw_segs = 1; | ||
712 | mmc->max_phys_segs = 1; | ||
713 | mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; | ||
714 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | ||
715 | |||
716 | spin_lock_init(&host->lock); | ||
717 | |||
718 | host->base = ioremap(r->start, SZ_4K); | ||
719 | if (!host->base) { | ||
720 | ret = -ENOMEM; | ||
721 | goto out; | ||
722 | } | ||
723 | |||
724 | /* (Re-)program MBUS remapping windows if we are asked to. */ | ||
725 | if (mvsd_data->dram != NULL) | ||
726 | mv_conf_mbus_windows(host, mvsd_data->dram); | ||
727 | |||
728 | mvsd_power_down(host); | ||
729 | |||
730 | ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host); | ||
731 | if (ret) { | ||
732 | printk(KERN_ERR "%s: cannot assign irq %d\n", DRIVER_NAME, irq); | ||
733 | goto out; | ||
734 | } else | ||
735 | host->irq = irq; | ||
736 | |||
737 | if (mvsd_data->gpio_card_detect) { | ||
738 | ret = gpio_request(mvsd_data->gpio_card_detect, | ||
739 | DRIVER_NAME " cd"); | ||
740 | if (ret == 0) { | ||
741 | gpio_direction_input(mvsd_data->gpio_card_detect); | ||
742 | irq = gpio_to_irq(mvsd_data->gpio_card_detect); | ||
743 | ret = request_irq(irq, mvsd_card_detect_irq, | ||
744 | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING, | ||
745 | DRIVER_NAME " cd", host); | ||
746 | if (ret == 0) | ||
747 | host->gpio_card_detect = | ||
748 | mvsd_data->gpio_card_detect; | ||
749 | else | ||
750 | gpio_free(mvsd_data->gpio_card_detect); | ||
751 | } | ||
752 | } | ||
753 | if (!host->gpio_card_detect) | ||
754 | mmc->caps |= MMC_CAP_NEEDS_POLL; | ||
755 | |||
756 | if (mvsd_data->gpio_write_protect) { | ||
757 | ret = gpio_request(mvsd_data->gpio_write_protect, | ||
758 | DRIVER_NAME " wp"); | ||
759 | if (ret == 0) { | ||
760 | gpio_direction_input(mvsd_data->gpio_write_protect); | ||
761 | host->gpio_write_protect = | ||
762 | mvsd_data->gpio_write_protect; | ||
763 | } | ||
764 | } | ||
765 | |||
766 | setup_timer(&host->timer, mvsd_timeout_timer, (unsigned long)host); | ||
767 | platform_set_drvdata(pdev, mmc); | ||
768 | ret = mmc_add_host(mmc); | ||
769 | if (ret) | ||
770 | goto out; | ||
771 | |||
772 | printk(KERN_NOTICE "%s: %s driver initialized, ", | ||
773 | mmc_hostname(mmc), DRIVER_NAME); | ||
774 | if (host->gpio_card_detect) | ||
775 | printk("using GPIO %d for card detection\n", | ||
776 | host->gpio_card_detect); | ||
777 | else | ||
778 | printk("lacking card detect (fall back to polling)\n"); | ||
779 | return 0; | ||
780 | |||
781 | out: | ||
782 | if (host) { | ||
783 | if (host->irq) | ||
784 | free_irq(host->irq, host); | ||
785 | if (host->gpio_card_detect) { | ||
786 | free_irq(gpio_to_irq(host->gpio_card_detect), host); | ||
787 | gpio_free(host->gpio_card_detect); | ||
788 | } | ||
789 | if (host->gpio_write_protect) | ||
790 | gpio_free(host->gpio_write_protect); | ||
791 | if (host->base) | ||
792 | iounmap(host->base); | ||
793 | } | ||
794 | if (r) | ||
795 | release_resource(r); | ||
796 | if (mmc) | ||
797 | mmc_free_host(mmc); | ||
798 | |||
799 | return ret; | ||
800 | } | ||
801 | |||
802 | static int __exit mvsd_remove(struct platform_device *pdev) | ||
803 | { | ||
804 | struct mmc_host *mmc = platform_get_drvdata(pdev); | ||
805 | |||
806 | if (mmc) { | ||
807 | struct mvsd_host *host = mmc_priv(mmc); | ||
808 | |||
809 | if (host->gpio_card_detect) { | ||
810 | free_irq(gpio_to_irq(host->gpio_card_detect), host); | ||
811 | gpio_free(host->gpio_card_detect); | ||
812 | } | ||
813 | mmc_remove_host(mmc); | ||
814 | free_irq(host->irq, host); | ||
815 | if (host->gpio_write_protect) | ||
816 | gpio_free(host->gpio_write_protect); | ||
817 | del_timer_sync(&host->timer); | ||
818 | mvsd_power_down(host); | ||
819 | iounmap(host->base); | ||
820 | release_resource(host->res); | ||
821 | mmc_free_host(mmc); | ||
822 | } | ||
823 | platform_set_drvdata(pdev, NULL); | ||
824 | return 0; | ||
825 | } | ||
826 | |||
827 | #ifdef CONFIG_PM | ||
828 | static int mvsd_suspend(struct platform_device *dev, pm_message_t state, | ||
829 | u32 level) | ||
830 | { | ||
831 | struct mmc_host *mmc = platform_get_drvdata(dev); | ||
832 | int ret = 0; | ||
833 | |||
834 | if (mmc && level == SUSPEND_DISABLE) | ||
835 | ret = mmc_suspend_host(mmc, state); | ||
836 | |||
837 | return ret; | ||
838 | } | ||
839 | |||
840 | static int mvsd_resume(struct platform_device *dev, u32 level) | ||
841 | { | ||
842 | struct mmc_host *mmc = platform_dev_get_drvdata(dev); | ||
843 | int ret = 0; | ||
844 | |||
845 | if (mmc && level == RESUME_ENABLE) | ||
846 | ret = mmc_resume_host(mmc); | ||
847 | |||
848 | return ret; | ||
849 | } | ||
850 | #else | ||
851 | #define mvsd_suspend NULL | ||
852 | #define mvsd_resume NULL | ||
853 | #endif | ||
854 | |||
855 | static struct platform_driver mvsd_driver = { | ||
856 | .remove = __exit_p(mvsd_remove), | ||
857 | .suspend = mvsd_suspend, | ||
858 | .resume = mvsd_resume, | ||
859 | .driver = { | ||
860 | .name = DRIVER_NAME, | ||
861 | }, | ||
862 | }; | ||
863 | |||
864 | static int __init mvsd_init(void) | ||
865 | { | ||
866 | return platform_driver_probe(&mvsd_driver, mvsd_probe); | ||
867 | } | ||
868 | |||
869 | static void __exit mvsd_exit(void) | ||
870 | { | ||
871 | platform_driver_unregister(&mvsd_driver); | ||
872 | } | ||
873 | |||
874 | module_init(mvsd_init); | ||
875 | module_exit(mvsd_exit); | ||
876 | |||
877 | /* maximum card clock frequency (default 50MHz) */ | ||
878 | module_param(maxfreq, int, 0); | ||
879 | |||
880 | /* force PIO transfers all the time */ | ||
881 | module_param(nodma, int, 0); | ||
882 | |||
883 | MODULE_AUTHOR("Maen Suleiman, Nicolas Pitre"); | ||
884 | MODULE_DESCRIPTION("Marvell MMC,SD,SDIO Host Controller driver"); | ||
885 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/host/mvsdio.h b/drivers/mmc/host/mvsdio.h new file mode 100644 index 000000000000..7d9727b9f5aa --- /dev/null +++ b/drivers/mmc/host/mvsdio.h | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Marvell Semiconductors, All Rights Reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef __MVSDIO_H | ||
10 | #define __MVSDIO_H | ||
11 | |||
12 | /* | ||
13 | * Clock rates | ||
14 | */ | ||
15 | |||
16 | #define MVSD_CLOCKRATE_MAX 50000000 | ||
17 | #define MVSD_BASE_DIV_MAX 0x7ff | ||
18 | |||
19 | |||
20 | /* | ||
21 | * Register offsets | ||
22 | */ | ||
23 | |||
24 | #define MVSD_SYS_ADDR_LOW 0x000 | ||
25 | #define MVSD_SYS_ADDR_HI 0x004 | ||
26 | #define MVSD_BLK_SIZE 0x008 | ||
27 | #define MVSD_BLK_COUNT 0x00c | ||
28 | #define MVSD_ARG_LOW 0x010 | ||
29 | #define MVSD_ARG_HI 0x014 | ||
30 | #define MVSD_XFER_MODE 0x018 | ||
31 | #define MVSD_CMD 0x01c | ||
32 | #define MVSD_RSP(i) (0x020 + ((i)<<2)) | ||
33 | #define MVSD_RSP0 0x020 | ||
34 | #define MVSD_RSP1 0x024 | ||
35 | #define MVSD_RSP2 0x028 | ||
36 | #define MVSD_RSP3 0x02c | ||
37 | #define MVSD_RSP4 0x030 | ||
38 | #define MVSD_RSP5 0x034 | ||
39 | #define MVSD_RSP6 0x038 | ||
40 | #define MVSD_RSP7 0x03c | ||
41 | #define MVSD_FIFO 0x040 | ||
42 | #define MVSD_RSP_CRC7 0x044 | ||
43 | #define MVSD_HW_STATE 0x048 | ||
44 | #define MVSD_HOST_CTRL 0x050 | ||
45 | #define MVSD_BLK_GAP_CTRL 0x054 | ||
46 | #define MVSD_CLK_CTRL 0x058 | ||
47 | #define MVSD_SW_RESET 0x05c | ||
48 | #define MVSD_NOR_INTR_STATUS 0x060 | ||
49 | #define MVSD_ERR_INTR_STATUS 0x064 | ||
50 | #define MVSD_NOR_STATUS_EN 0x068 | ||
51 | #define MVSD_ERR_STATUS_EN 0x06c | ||
52 | #define MVSD_NOR_INTR_EN 0x070 | ||
53 | #define MVSD_ERR_INTR_EN 0x074 | ||
54 | #define MVSD_AUTOCMD12_ERR_STATUS 0x078 | ||
55 | #define MVSD_CURR_BYTE_LEFT 0x07c | ||
56 | #define MVSD_CURR_BLK_LEFT 0x080 | ||
57 | #define MVSD_AUTOCMD12_ARG_LOW 0x084 | ||
58 | #define MVSD_AUTOCMD12_ARG_HI 0x088 | ||
59 | #define MVSD_AUTOCMD12_CMD 0x08c | ||
60 | #define MVSD_AUTO_RSP(i) (0x090 + ((i)<<2)) | ||
61 | #define MVSD_AUTO_RSP0 0x090 | ||
62 | #define MVSD_AUTO_RSP1 0x094 | ||
63 | #define MVSD_AUTO_RSP2 0x098 | ||
64 | #define MVSD_CLK_DIV 0x128 | ||
65 | |||
66 | #define MVSD_WINDOW_CTRL(i) (0x108 + ((i) << 3)) | ||
67 | #define MVSD_WINDOW_BASE(i) (0x10c + ((i) << 3)) | ||
68 | |||
69 | |||
70 | /* | ||
71 | * MVSD_CMD | ||
72 | */ | ||
73 | |||
74 | #define MVSD_CMD_RSP_NONE (0 << 0) | ||
75 | #define MVSD_CMD_RSP_136 (1 << 0) | ||
76 | #define MVSD_CMD_RSP_48 (2 << 0) | ||
77 | #define MVSD_CMD_RSP_48BUSY (3 << 0) | ||
78 | |||
79 | #define MVSD_CMD_CHECK_DATACRC16 (1 << 2) | ||
80 | #define MVSD_CMD_CHECK_CMDCRC (1 << 3) | ||
81 | #define MVSD_CMD_INDX_CHECK (1 << 4) | ||
82 | #define MVSD_CMD_DATA_PRESENT (1 << 5) | ||
83 | #define MVSD_UNEXPECTED_RESP (1 << 7) | ||
84 | #define MVSD_CMD_INDEX(x) ((x) << 8) | ||
85 | |||
86 | |||
87 | /* | ||
88 | * MVSD_AUTOCMD12_CMD | ||
89 | */ | ||
90 | |||
91 | #define MVSD_AUTOCMD12_BUSY (1 << 0) | ||
92 | #define MVSD_AUTOCMD12_INDX_CHECK (1 << 1) | ||
93 | #define MVSD_AUTOCMD12_INDEX(x) ((x) << 8) | ||
94 | |||
95 | /* | ||
96 | * MVSD_XFER_MODE | ||
97 | */ | ||
98 | |||
99 | #define MVSD_XFER_MODE_WR_DATA_START (1 << 0) | ||
100 | #define MVSD_XFER_MODE_HW_WR_DATA_EN (1 << 1) | ||
101 | #define MVSD_XFER_MODE_AUTO_CMD12 (1 << 2) | ||
102 | #define MVSD_XFER_MODE_INT_CHK_EN (1 << 3) | ||
103 | #define MVSD_XFER_MODE_TO_HOST (1 << 4) | ||
104 | #define MVSD_XFER_MODE_STOP_CLK (1 << 5) | ||
105 | #define MVSD_XFER_MODE_PIO (1 << 6) | ||
106 | |||
107 | |||
108 | /* | ||
109 | * MVSD_HOST_CTRL | ||
110 | */ | ||
111 | |||
112 | #define MVSD_HOST_CTRL_PUSH_PULL_EN (1 << 0) | ||
113 | |||
114 | #define MVSD_HOST_CTRL_CARD_TYPE_MEM_ONLY (0 << 1) | ||
115 | #define MVSD_HOST_CTRL_CARD_TYPE_IO_ONLY (1 << 1) | ||
116 | #define MVSD_HOST_CTRL_CARD_TYPE_IO_MEM_COMBO (2 << 1) | ||
117 | #define MVSD_HOST_CTRL_CARD_TYPE_IO_MMC (3 << 1) | ||
118 | #define MVSD_HOST_CTRL_CARD_TYPE_MASK (3 << 1) | ||
119 | |||
120 | #define MVSD_HOST_CTRL_BIG_ENDIAN (1 << 3) | ||
121 | #define MVSD_HOST_CTRL_LSB_FIRST (1 << 4) | ||
122 | #define MVSD_HOST_CTRL_DATA_WIDTH_4_BITS (1 << 9) | ||
123 | #define MVSD_HOST_CTRL_HI_SPEED_EN (1 << 10) | ||
124 | |||
125 | #define MVSD_HOST_CTRL_TMOUT_MAX 0xf | ||
126 | #define MVSD_HOST_CTRL_TMOUT_MASK (0xf << 11) | ||
127 | #define MVSD_HOST_CTRL_TMOUT(x) ((x) << 11) | ||
128 | #define MVSD_HOST_CTRL_TMOUT_EN (1 << 15) | ||
129 | |||
130 | |||
131 | /* | ||
132 | * MVSD_SW_RESET | ||
133 | */ | ||
134 | |||
135 | #define MVSD_SW_RESET_NOW (1 << 8) | ||
136 | |||
137 | |||
138 | /* | ||
139 | * Normal interrupt status bits | ||
140 | */ | ||
141 | |||
142 | #define MVSD_NOR_CMD_DONE (1 << 0) | ||
143 | #define MVSD_NOR_XFER_DONE (1 << 1) | ||
144 | #define MVSD_NOR_BLK_GAP_EVT (1 << 2) | ||
145 | #define MVSD_NOR_DMA_DONE (1 << 3) | ||
146 | #define MVSD_NOR_TX_AVAIL (1 << 4) | ||
147 | #define MVSD_NOR_RX_READY (1 << 5) | ||
148 | #define MVSD_NOR_CARD_INT (1 << 8) | ||
149 | #define MVSD_NOR_READ_WAIT_ON (1 << 9) | ||
150 | #define MVSD_NOR_RX_FIFO_8W (1 << 10) | ||
151 | #define MVSD_NOR_TX_FIFO_8W (1 << 11) | ||
152 | #define MVSD_NOR_SUSPEND_ON (1 << 12) | ||
153 | #define MVSD_NOR_AUTOCMD12_DONE (1 << 13) | ||
154 | #define MVSD_NOR_UNEXP_RSP (1 << 14) | ||
155 | #define MVSD_NOR_ERROR (1 << 15) | ||
156 | |||
157 | |||
158 | /* | ||
159 | * Error status bits | ||
160 | */ | ||
161 | |||
162 | #define MVSD_ERR_CMD_TIMEOUT (1 << 0) | ||
163 | #define MVSD_ERR_CMD_CRC (1 << 1) | ||
164 | #define MVSD_ERR_CMD_ENDBIT (1 << 2) | ||
165 | #define MVSD_ERR_CMD_INDEX (1 << 3) | ||
166 | #define MVSD_ERR_DATA_TIMEOUT (1 << 4) | ||
167 | #define MVSD_ERR_DATA_CRC (1 << 5) | ||
168 | #define MVSD_ERR_DATA_ENDBIT (1 << 6) | ||
169 | #define MVSD_ERR_AUTOCMD12 (1 << 8) | ||
170 | #define MVSD_ERR_CMD_STARTBIT (1 << 9) | ||
171 | #define MVSD_ERR_XFER_SIZE (1 << 10) | ||
172 | #define MVSD_ERR_RESP_T_BIT (1 << 11) | ||
173 | #define MVSD_ERR_CRC_ENDBIT (1 << 12) | ||
174 | #define MVSD_ERR_CRC_STARTBIT (1 << 13) | ||
175 | #define MVSD_ERR_CRC_STATUS (1 << 14) | ||
176 | |||
177 | |||
178 | /* | ||
179 | * CMD12 error status bits | ||
180 | */ | ||
181 | |||
182 | #define MVSD_AUTOCMD12_ERR_NOTEXE (1 << 0) | ||
183 | #define MVSD_AUTOCMD12_ERR_TIMEOUT (1 << 1) | ||
184 | #define MVSD_AUTOCMD12_ERR_CRC (1 << 2) | ||
185 | #define MVSD_AUTOCMD12_ERR_ENDBIT (1 << 3) | ||
186 | #define MVSD_AUTOCMD12_ERR_INDEX (1 << 4) | ||
187 | #define MVSD_AUTOCMD12_ERR_RESP_T_BIT (1 << 5) | ||
188 | #define MVSD_AUTOCMD12_ERR_RESP_STARTBIT (1 << 6) | ||
189 | |||
190 | #endif | ||
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 3916a5618e28..d183be6f2a5f 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #define SDVS18 (0x5 << 9) | 56 | #define SDVS18 (0x5 << 9) |
57 | #define SDVS30 (0x6 << 9) | 57 | #define SDVS30 (0x6 << 9) |
58 | #define SDVS33 (0x7 << 9) | 58 | #define SDVS33 (0x7 << 9) |
59 | #define SDVS_MASK 0x00000E00 | ||
59 | #define SDVSCLR 0xFFFFF1FF | 60 | #define SDVSCLR 0xFFFFF1FF |
60 | #define SDVSDET 0x00000400 | 61 | #define SDVSDET 0x00000400 |
61 | #define AUTOIDLE 0x1 | 62 | #define AUTOIDLE 0x1 |
@@ -76,6 +77,7 @@ | |||
76 | #define MSBS (1 << 5) | 77 | #define MSBS (1 << 5) |
77 | #define BCE (1 << 1) | 78 | #define BCE (1 << 1) |
78 | #define FOUR_BIT (1 << 1) | 79 | #define FOUR_BIT (1 << 1) |
80 | #define DW8 (1 << 5) | ||
79 | #define CC 0x1 | 81 | #define CC 0x1 |
80 | #define TC 0x02 | 82 | #define TC 0x02 |
81 | #define OD 0x1 | 83 | #define OD 0x1 |
@@ -98,10 +100,8 @@ | |||
98 | */ | 100 | */ |
99 | #define OMAP_MMC1_DEVID 0 | 101 | #define OMAP_MMC1_DEVID 0 |
100 | #define OMAP_MMC2_DEVID 1 | 102 | #define OMAP_MMC2_DEVID 1 |
103 | #define OMAP_MMC3_DEVID 2 | ||
101 | 104 | ||
102 | #define OMAP_MMC_DATADIR_NONE 0 | ||
103 | #define OMAP_MMC_DATADIR_READ 1 | ||
104 | #define OMAP_MMC_DATADIR_WRITE 2 | ||
105 | #define MMC_TIMEOUT_MS 20 | 105 | #define MMC_TIMEOUT_MS 20 |
106 | #define OMAP_MMC_MASTER_CLOCK 96000000 | 106 | #define OMAP_MMC_MASTER_CLOCK 96000000 |
107 | #define DRIVER_NAME "mmci-omap-hs" | 107 | #define DRIVER_NAME "mmci-omap-hs" |
@@ -137,18 +137,18 @@ struct mmc_omap_host { | |||
137 | resource_size_t mapbase; | 137 | resource_size_t mapbase; |
138 | unsigned int id; | 138 | unsigned int id; |
139 | unsigned int dma_len; | 139 | unsigned int dma_len; |
140 | unsigned int dma_dir; | 140 | unsigned int dma_sg_idx; |
141 | unsigned char bus_mode; | 141 | unsigned char bus_mode; |
142 | unsigned char datadir; | ||
143 | u32 *buffer; | 142 | u32 *buffer; |
144 | u32 bytesleft; | 143 | u32 bytesleft; |
145 | int suspended; | 144 | int suspended; |
146 | int irq; | 145 | int irq; |
147 | int carddetect; | 146 | int carddetect; |
148 | int use_dma, dma_ch; | 147 | int use_dma, dma_ch; |
149 | int initstr; | 148 | int dma_line_tx, dma_line_rx; |
150 | int slot_id; | 149 | int slot_id; |
151 | int dbclk_enabled; | 150 | int dbclk_enabled; |
151 | int response_busy; | ||
152 | struct omap_mmc_platform_data *pdata; | 152 | struct omap_mmc_platform_data *pdata; |
153 | }; | 153 | }; |
154 | 154 | ||
@@ -218,7 +218,7 @@ mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr, | |||
218 | struct mmc_omap_host *host = mmc_priv(mmc); | 218 | struct mmc_omap_host *host = mmc_priv(mmc); |
219 | struct omap_mmc_slot_data slot = host->pdata->slots[host->slot_id]; | 219 | struct omap_mmc_slot_data slot = host->pdata->slots[host->slot_id]; |
220 | 220 | ||
221 | return sprintf(buf, "slot:%s\n", slot.name); | 221 | return sprintf(buf, "%s\n", slot.name); |
222 | } | 222 | } |
223 | 223 | ||
224 | static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL); | 224 | static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL); |
@@ -243,10 +243,14 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd, | |||
243 | OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); | 243 | OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); |
244 | OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | 244 | OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); |
245 | 245 | ||
246 | host->response_busy = 0; | ||
246 | if (cmd->flags & MMC_RSP_PRESENT) { | 247 | if (cmd->flags & MMC_RSP_PRESENT) { |
247 | if (cmd->flags & MMC_RSP_136) | 248 | if (cmd->flags & MMC_RSP_136) |
248 | resptype = 1; | 249 | resptype = 1; |
249 | else | 250 | else if (cmd->flags & MMC_RSP_BUSY) { |
251 | resptype = 3; | ||
252 | host->response_busy = 1; | ||
253 | } else | ||
250 | resptype = 2; | 254 | resptype = 2; |
251 | } | 255 | } |
252 | 256 | ||
@@ -275,19 +279,35 @@ mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd, | |||
275 | OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); | 279 | OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); |
276 | } | 280 | } |
277 | 281 | ||
282 | static int | ||
283 | mmc_omap_get_dma_dir(struct mmc_omap_host *host, struct mmc_data *data) | ||
284 | { | ||
285 | if (data->flags & MMC_DATA_WRITE) | ||
286 | return DMA_TO_DEVICE; | ||
287 | else | ||
288 | return DMA_FROM_DEVICE; | ||
289 | } | ||
290 | |||
278 | /* | 291 | /* |
279 | * Notify the transfer complete to MMC core | 292 | * Notify the transfer complete to MMC core |
280 | */ | 293 | */ |
281 | static void | 294 | static void |
282 | mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) | 295 | mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) |
283 | { | 296 | { |
297 | if (!data) { | ||
298 | struct mmc_request *mrq = host->mrq; | ||
299 | |||
300 | host->mrq = NULL; | ||
301 | mmc_omap_fclk_lazy_disable(host); | ||
302 | mmc_request_done(host->mmc, mrq); | ||
303 | return; | ||
304 | } | ||
305 | |||
284 | host->data = NULL; | 306 | host->data = NULL; |
285 | 307 | ||
286 | if (host->use_dma && host->dma_ch != -1) | 308 | if (host->use_dma && host->dma_ch != -1) |
287 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, | 309 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, |
288 | host->dma_dir); | 310 | mmc_omap_get_dma_dir(host, data)); |
289 | |||
290 | host->datadir = OMAP_MMC_DATADIR_NONE; | ||
291 | 311 | ||
292 | if (!data->error) | 312 | if (!data->error) |
293 | data->bytes_xfered += data->blocks * (data->blksz); | 313 | data->bytes_xfered += data->blocks * (data->blksz); |
@@ -322,7 +342,7 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd) | |||
322 | cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10); | 342 | cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10); |
323 | } | 343 | } |
324 | } | 344 | } |
325 | if (host->data == NULL || cmd->error) { | 345 | if ((host->data == NULL && !host->response_busy) || cmd->error) { |
326 | host->mrq = NULL; | 346 | host->mrq = NULL; |
327 | mmc_request_done(host->mmc, cmd->mrq); | 347 | mmc_request_done(host->mmc, cmd->mrq); |
328 | } | 348 | } |
@@ -331,19 +351,18 @@ mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd) | |||
331 | /* | 351 | /* |
332 | * DMA clean up for command errors | 352 | * DMA clean up for command errors |
333 | */ | 353 | */ |
334 | static void mmc_dma_cleanup(struct mmc_omap_host *host) | 354 | static void mmc_dma_cleanup(struct mmc_omap_host *host, int errno) |
335 | { | 355 | { |
336 | host->data->error = -ETIMEDOUT; | 356 | host->data->error = errno; |
337 | 357 | ||
338 | if (host->use_dma && host->dma_ch != -1) { | 358 | if (host->use_dma && host->dma_ch != -1) { |
339 | dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len, | 359 | dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len, |
340 | host->dma_dir); | 360 | mmc_omap_get_dma_dir(host, host->data)); |
341 | omap_free_dma(host->dma_ch); | 361 | omap_free_dma(host->dma_ch); |
342 | host->dma_ch = -1; | 362 | host->dma_ch = -1; |
343 | up(&host->sem); | 363 | up(&host->sem); |
344 | } | 364 | } |
345 | host->data = NULL; | 365 | host->data = NULL; |
346 | host->datadir = OMAP_MMC_DATADIR_NONE; | ||
347 | } | 366 | } |
348 | 367 | ||
349 | /* | 368 | /* |
@@ -412,7 +431,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
412 | struct mmc_data *data; | 431 | struct mmc_data *data; |
413 | int end_cmd = 0, end_trans = 0, status; | 432 | int end_cmd = 0, end_trans = 0, status; |
414 | 433 | ||
415 | if (host->cmd == NULL && host->data == NULL) { | 434 | if (host->mrq == NULL) { |
416 | OMAP_HSMMC_WRITE(host->base, STAT, | 435 | OMAP_HSMMC_WRITE(host->base, STAT, |
417 | OMAP_HSMMC_READ(host->base, STAT)); | 436 | OMAP_HSMMC_READ(host->base, STAT)); |
418 | return IRQ_HANDLED; | 437 | return IRQ_HANDLED; |
@@ -437,18 +456,24 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
437 | } | 456 | } |
438 | end_cmd = 1; | 457 | end_cmd = 1; |
439 | } | 458 | } |
440 | if (host->data) { | 459 | if (host->data || host->response_busy) { |
441 | mmc_dma_cleanup(host); | 460 | if (host->data) |
461 | mmc_dma_cleanup(host, -ETIMEDOUT); | ||
462 | host->response_busy = 0; | ||
442 | mmc_omap_reset_controller_fsm(host, SRD); | 463 | mmc_omap_reset_controller_fsm(host, SRD); |
443 | } | 464 | } |
444 | } | 465 | } |
445 | if ((status & DATA_TIMEOUT) || | 466 | if ((status & DATA_TIMEOUT) || |
446 | (status & DATA_CRC)) { | 467 | (status & DATA_CRC)) { |
447 | if (host->data) { | 468 | if (host->data || host->response_busy) { |
448 | if (status & DATA_TIMEOUT) | 469 | int err = (status & DATA_TIMEOUT) ? |
449 | mmc_dma_cleanup(host); | 470 | -ETIMEDOUT : -EILSEQ; |
471 | |||
472 | if (host->data) | ||
473 | mmc_dma_cleanup(host, err); | ||
450 | else | 474 | else |
451 | host->data->error = -EILSEQ; | 475 | host->mrq->cmd->error = err; |
476 | host->response_busy = 0; | ||
452 | mmc_omap_reset_controller_fsm(host, SRD); | 477 | mmc_omap_reset_controller_fsm(host, SRD); |
453 | end_trans = 1; | 478 | end_trans = 1; |
454 | } | 479 | } |
@@ -473,6 +498,19 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
473 | return IRQ_HANDLED; | 498 | return IRQ_HANDLED; |
474 | } | 499 | } |
475 | 500 | ||
501 | static void set_sd_bus_power(struct mmc_omap_host *host) | ||
502 | { | ||
503 | unsigned long i; | ||
504 | |||
505 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
506 | OMAP_HSMMC_READ(host->base, HCTL) | SDBP); | ||
507 | for (i = 0; i < loops_per_jiffy; i++) { | ||
508 | if (OMAP_HSMMC_READ(host->base, HCTL) & SDBP) | ||
509 | break; | ||
510 | cpu_relax(); | ||
511 | } | ||
512 | } | ||
513 | |||
476 | /* | 514 | /* |
477 | * Switch MMC interface voltage ... only relevant for MMC1. | 515 | * Switch MMC interface voltage ... only relevant for MMC1. |
478 | * | 516 | * |
@@ -485,9 +523,6 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd) | |||
485 | u32 reg_val = 0; | 523 | u32 reg_val = 0; |
486 | int ret; | 524 | int ret; |
487 | 525 | ||
488 | if (host->id != OMAP_MMC1_DEVID) | ||
489 | return 0; | ||
490 | |||
491 | /* Disable the clocks */ | 526 | /* Disable the clocks */ |
492 | clk_disable(host->fclk); | 527 | clk_disable(host->fclk); |
493 | clk_disable(host->iclk); | 528 | clk_disable(host->iclk); |
@@ -532,9 +567,7 @@ static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd) | |||
532 | reg_val |= SDVS30; | 567 | reg_val |= SDVS30; |
533 | 568 | ||
534 | OMAP_HSMMC_WRITE(host->base, HCTL, reg_val); | 569 | OMAP_HSMMC_WRITE(host->base, HCTL, reg_val); |
535 | 570 | set_sd_bus_power(host); | |
536 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
537 | OMAP_HSMMC_READ(host->base, HCTL) | SDBP); | ||
538 | 571 | ||
539 | return 0; | 572 | return 0; |
540 | err: | 573 | err: |
@@ -551,7 +584,10 @@ static void mmc_omap_detect(struct work_struct *work) | |||
551 | mmc_carddetect_work); | 584 | mmc_carddetect_work); |
552 | struct omap_mmc_slot_data *slot = &mmc_slot(host); | 585 | struct omap_mmc_slot_data *slot = &mmc_slot(host); |
553 | 586 | ||
554 | host->carddetect = slot->card_detect(slot->card_detect_irq); | 587 | if (mmc_slot(host).card_detect) |
588 | host->carddetect = slot->card_detect(slot->card_detect_irq); | ||
589 | else | ||
590 | host->carddetect = -ENOSYS; | ||
555 | 591 | ||
556 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); | 592 | sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); |
557 | if (host->carddetect) { | 593 | if (host->carddetect) { |
@@ -574,6 +610,48 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id) | |||
574 | return IRQ_HANDLED; | 610 | return IRQ_HANDLED; |
575 | } | 611 | } |
576 | 612 | ||
613 | static int mmc_omap_get_dma_sync_dev(struct mmc_omap_host *host, | ||
614 | struct mmc_data *data) | ||
615 | { | ||
616 | int sync_dev; | ||
617 | |||
618 | if (data->flags & MMC_DATA_WRITE) | ||
619 | sync_dev = host->dma_line_tx; | ||
620 | else | ||
621 | sync_dev = host->dma_line_rx; | ||
622 | return sync_dev; | ||
623 | } | ||
624 | |||
625 | static void mmc_omap_config_dma_params(struct mmc_omap_host *host, | ||
626 | struct mmc_data *data, | ||
627 | struct scatterlist *sgl) | ||
628 | { | ||
629 | int blksz, nblk, dma_ch; | ||
630 | |||
631 | dma_ch = host->dma_ch; | ||
632 | if (data->flags & MMC_DATA_WRITE) { | ||
633 | omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, | ||
634 | (host->mapbase + OMAP_HSMMC_DATA), 0, 0); | ||
635 | omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, | ||
636 | sg_dma_address(sgl), 0, 0); | ||
637 | } else { | ||
638 | omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, | ||
639 | (host->mapbase + OMAP_HSMMC_DATA), 0, 0); | ||
640 | omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, | ||
641 | sg_dma_address(sgl), 0, 0); | ||
642 | } | ||
643 | |||
644 | blksz = host->data->blksz; | ||
645 | nblk = sg_dma_len(sgl) / blksz; | ||
646 | |||
647 | omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, | ||
648 | blksz / 4, nblk, OMAP_DMA_SYNC_FRAME, | ||
649 | mmc_omap_get_dma_sync_dev(host, data), | ||
650 | !(data->flags & MMC_DATA_WRITE)); | ||
651 | |||
652 | omap_start_dma(dma_ch); | ||
653 | } | ||
654 | |||
577 | /* | 655 | /* |
578 | * DMA call back function | 656 | * DMA call back function |
579 | */ | 657 | */ |
@@ -587,6 +665,14 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data) | |||
587 | if (host->dma_ch < 0) | 665 | if (host->dma_ch < 0) |
588 | return; | 666 | return; |
589 | 667 | ||
668 | host->dma_sg_idx++; | ||
669 | if (host->dma_sg_idx < host->dma_len) { | ||
670 | /* Fire up the next transfer. */ | ||
671 | mmc_omap_config_dma_params(host, host->data, | ||
672 | host->data->sg + host->dma_sg_idx); | ||
673 | return; | ||
674 | } | ||
675 | |||
590 | omap_free_dma(host->dma_ch); | 676 | omap_free_dma(host->dma_ch); |
591 | host->dma_ch = -1; | 677 | host->dma_ch = -1; |
592 | /* | 678 | /* |
@@ -597,38 +683,28 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data) | |||
597 | } | 683 | } |
598 | 684 | ||
599 | /* | 685 | /* |
600 | * Configure dma src and destination parameters | ||
601 | */ | ||
602 | static int mmc_omap_config_dma_param(int sync_dir, struct mmc_omap_host *host, | ||
603 | struct mmc_data *data) | ||
604 | { | ||
605 | if (sync_dir == 0) { | ||
606 | omap_set_dma_dest_params(host->dma_ch, 0, | ||
607 | OMAP_DMA_AMODE_CONSTANT, | ||
608 | (host->mapbase + OMAP_HSMMC_DATA), 0, 0); | ||
609 | omap_set_dma_src_params(host->dma_ch, 0, | ||
610 | OMAP_DMA_AMODE_POST_INC, | ||
611 | sg_dma_address(&data->sg[0]), 0, 0); | ||
612 | } else { | ||
613 | omap_set_dma_src_params(host->dma_ch, 0, | ||
614 | OMAP_DMA_AMODE_CONSTANT, | ||
615 | (host->mapbase + OMAP_HSMMC_DATA), 0, 0); | ||
616 | omap_set_dma_dest_params(host->dma_ch, 0, | ||
617 | OMAP_DMA_AMODE_POST_INC, | ||
618 | sg_dma_address(&data->sg[0]), 0, 0); | ||
619 | } | ||
620 | return 0; | ||
621 | } | ||
622 | /* | ||
623 | * Routine to configure and start DMA for the MMC card | 686 | * Routine to configure and start DMA for the MMC card |
624 | */ | 687 | */ |
625 | static int | 688 | static int |
626 | mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req) | 689 | mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req) |
627 | { | 690 | { |
628 | int sync_dev, sync_dir = 0; | 691 | int dma_ch = 0, ret = 0, err = 1, i; |
629 | int dma_ch = 0, ret = 0, err = 1; | ||
630 | struct mmc_data *data = req->data; | 692 | struct mmc_data *data = req->data; |
631 | 693 | ||
694 | /* Sanity check: all the SG entries must be aligned by block size. */ | ||
695 | for (i = 0; i < host->dma_len; i++) { | ||
696 | struct scatterlist *sgl; | ||
697 | |||
698 | sgl = data->sg + i; | ||
699 | if (sgl->length % data->blksz) | ||
700 | return -EINVAL; | ||
701 | } | ||
702 | if ((data->blksz % 4) != 0) | ||
703 | /* REVISIT: The MMC buffer increments only when MSB is written. | ||
704 | * Return error for blksz which is non multiple of four. | ||
705 | */ | ||
706 | return -EINVAL; | ||
707 | |||
632 | /* | 708 | /* |
633 | * If for some reason the DMA transfer is still active, | 709 | * If for some reason the DMA transfer is still active, |
634 | * we wait for timeout period and free the dma | 710 | * we wait for timeout period and free the dma |
@@ -647,49 +723,22 @@ mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req) | |||
647 | return err; | 723 | return err; |
648 | } | 724 | } |
649 | 725 | ||
650 | if (!(data->flags & MMC_DATA_WRITE)) { | 726 | ret = omap_request_dma(mmc_omap_get_dma_sync_dev(host, data), "MMC/SD", |
651 | host->dma_dir = DMA_FROM_DEVICE; | 727 | mmc_omap_dma_cb,host, &dma_ch); |
652 | if (host->id == OMAP_MMC1_DEVID) | ||
653 | sync_dev = OMAP24XX_DMA_MMC1_RX; | ||
654 | else | ||
655 | sync_dev = OMAP24XX_DMA_MMC2_RX; | ||
656 | } else { | ||
657 | host->dma_dir = DMA_TO_DEVICE; | ||
658 | if (host->id == OMAP_MMC1_DEVID) | ||
659 | sync_dev = OMAP24XX_DMA_MMC1_TX; | ||
660 | else | ||
661 | sync_dev = OMAP24XX_DMA_MMC2_TX; | ||
662 | } | ||
663 | |||
664 | ret = omap_request_dma(sync_dev, "MMC/SD", mmc_omap_dma_cb, | ||
665 | host, &dma_ch); | ||
666 | if (ret != 0) { | 728 | if (ret != 0) { |
667 | dev_dbg(mmc_dev(host->mmc), | 729 | dev_err(mmc_dev(host->mmc), |
668 | "%s: omap_request_dma() failed with %d\n", | 730 | "%s: omap_request_dma() failed with %d\n", |
669 | mmc_hostname(host->mmc), ret); | 731 | mmc_hostname(host->mmc), ret); |
670 | return ret; | 732 | return ret; |
671 | } | 733 | } |
672 | 734 | ||
673 | host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, | 735 | host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, |
674 | data->sg_len, host->dma_dir); | 736 | data->sg_len, mmc_omap_get_dma_dir(host, data)); |
675 | host->dma_ch = dma_ch; | 737 | host->dma_ch = dma_ch; |
738 | host->dma_sg_idx = 0; | ||
676 | 739 | ||
677 | if (!(data->flags & MMC_DATA_WRITE)) | 740 | mmc_omap_config_dma_params(host, data, data->sg); |
678 | mmc_omap_config_dma_param(1, host, data); | ||
679 | else | ||
680 | mmc_omap_config_dma_param(0, host, data); | ||
681 | |||
682 | if ((data->blksz % 4) == 0) | ||
683 | omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, | ||
684 | (data->blksz / 4), data->blocks, OMAP_DMA_SYNC_FRAME, | ||
685 | sync_dev, sync_dir); | ||
686 | else | ||
687 | /* REVISIT: The MMC buffer increments only when MSB is written. | ||
688 | * Return error for blksz which is non multiple of four. | ||
689 | */ | ||
690 | return -EINVAL; | ||
691 | 741 | ||
692 | omap_start_dma(dma_ch); | ||
693 | return 0; | 742 | return 0; |
694 | } | 743 | } |
695 | 744 | ||
@@ -739,7 +788,6 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) | |||
739 | host->data = req->data; | 788 | host->data = req->data; |
740 | 789 | ||
741 | if (req->data == NULL) { | 790 | if (req->data == NULL) { |
742 | host->datadir = OMAP_MMC_DATADIR_NONE; | ||
743 | OMAP_HSMMC_WRITE(host->base, BLK, 0); | 791 | OMAP_HSMMC_WRITE(host->base, BLK, 0); |
744 | return 0; | 792 | return 0; |
745 | } | 793 | } |
@@ -748,9 +796,6 @@ mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) | |||
748 | | (req->data->blocks << 16)); | 796 | | (req->data->blocks << 16)); |
749 | set_data_timeout(host, req); | 797 | set_data_timeout(host, req); |
750 | 798 | ||
751 | host->datadir = (req->data->flags & MMC_DATA_WRITE) ? | ||
752 | OMAP_MMC_DATADIR_WRITE : OMAP_MMC_DATADIR_READ; | ||
753 | |||
754 | if (host->use_dma) { | 799 | if (host->use_dma) { |
755 | ret = mmc_omap_start_dma_transfer(host, req); | 800 | ret = mmc_omap_start_dma_transfer(host, req); |
756 | if (ret != 0) { | 801 | if (ret != 0) { |
@@ -782,36 +827,29 @@ static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
782 | u16 dsor = 0; | 827 | u16 dsor = 0; |
783 | unsigned long regval; | 828 | unsigned long regval; |
784 | unsigned long timeout; | 829 | unsigned long timeout; |
830 | u32 con; | ||
785 | 831 | ||
786 | switch (ios->power_mode) { | 832 | switch (ios->power_mode) { |
787 | case MMC_POWER_OFF: | 833 | case MMC_POWER_OFF: |
788 | mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); | 834 | mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); |
789 | /* | ||
790 | * Reset interface voltage to 3V if it's 1.8V now; | ||
791 | * only relevant on MMC-1, the others always use 1.8V. | ||
792 | * | ||
793 | * REVISIT: If we are able to detect cards after unplugging | ||
794 | * a 1.8V card, this code should not be needed. | ||
795 | */ | ||
796 | if (host->id != OMAP_MMC1_DEVID) | ||
797 | break; | ||
798 | if (!(OMAP_HSMMC_READ(host->base, HCTL) & SDVSDET)) { | ||
799 | int vdd = fls(host->mmc->ocr_avail) - 1; | ||
800 | if (omap_mmc_switch_opcond(host, vdd) != 0) | ||
801 | host->mmc->ios.vdd = vdd; | ||
802 | } | ||
803 | break; | 835 | break; |
804 | case MMC_POWER_UP: | 836 | case MMC_POWER_UP: |
805 | mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd); | 837 | mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd); |
806 | break; | 838 | break; |
807 | } | 839 | } |
808 | 840 | ||
841 | con = OMAP_HSMMC_READ(host->base, CON); | ||
809 | switch (mmc->ios.bus_width) { | 842 | switch (mmc->ios.bus_width) { |
843 | case MMC_BUS_WIDTH_8: | ||
844 | OMAP_HSMMC_WRITE(host->base, CON, con | DW8); | ||
845 | break; | ||
810 | case MMC_BUS_WIDTH_4: | 846 | case MMC_BUS_WIDTH_4: |
847 | OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8); | ||
811 | OMAP_HSMMC_WRITE(host->base, HCTL, | 848 | OMAP_HSMMC_WRITE(host->base, HCTL, |
812 | OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT); | 849 | OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT); |
813 | break; | 850 | break; |
814 | case MMC_BUS_WIDTH_1: | 851 | case MMC_BUS_WIDTH_1: |
852 | OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8); | ||
815 | OMAP_HSMMC_WRITE(host->base, HCTL, | 853 | OMAP_HSMMC_WRITE(host->base, HCTL, |
816 | OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT); | 854 | OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT); |
817 | break; | 855 | break; |
@@ -891,6 +929,33 @@ static int omap_hsmmc_get_ro(struct mmc_host *mmc) | |||
891 | return pdata->slots[0].get_ro(host->dev, 0); | 929 | return pdata->slots[0].get_ro(host->dev, 0); |
892 | } | 930 | } |
893 | 931 | ||
932 | static void omap_hsmmc_init(struct mmc_omap_host *host) | ||
933 | { | ||
934 | u32 hctl, capa, value; | ||
935 | |||
936 | /* Only MMC1 supports 3.0V */ | ||
937 | if (host->id == OMAP_MMC1_DEVID) { | ||
938 | hctl = SDVS30; | ||
939 | capa = VS30 | VS18; | ||
940 | } else { | ||
941 | hctl = SDVS18; | ||
942 | capa = VS18; | ||
943 | } | ||
944 | |||
945 | value = OMAP_HSMMC_READ(host->base, HCTL) & ~SDVS_MASK; | ||
946 | OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl); | ||
947 | |||
948 | value = OMAP_HSMMC_READ(host->base, CAPA); | ||
949 | OMAP_HSMMC_WRITE(host->base, CAPA, value | capa); | ||
950 | |||
951 | /* Set the controller to AUTO IDLE mode */ | ||
952 | value = OMAP_HSMMC_READ(host->base, SYSCONFIG); | ||
953 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE); | ||
954 | |||
955 | /* Set SD bus power bit */ | ||
956 | set_sd_bus_power(host); | ||
957 | } | ||
958 | |||
894 | static struct mmc_host_ops mmc_omap_ops = { | 959 | static struct mmc_host_ops mmc_omap_ops = { |
895 | .request = omap_mmc_request, | 960 | .request = omap_mmc_request, |
896 | .set_ios = omap_mmc_set_ios, | 961 | .set_ios = omap_mmc_set_ios, |
@@ -906,7 +971,6 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
906 | struct mmc_omap_host *host = NULL; | 971 | struct mmc_omap_host *host = NULL; |
907 | struct resource *res; | 972 | struct resource *res; |
908 | int ret = 0, irq; | 973 | int ret = 0, irq; |
909 | u32 hctl, capa; | ||
910 | 974 | ||
911 | if (pdata == NULL) { | 975 | if (pdata == NULL) { |
912 | dev_err(&pdev->dev, "Platform Data is missing\n"); | 976 | dev_err(&pdev->dev, "Platform Data is missing\n"); |
@@ -996,10 +1060,11 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
996 | else | 1060 | else |
997 | host->dbclk_enabled = 1; | 1061 | host->dbclk_enabled = 1; |
998 | 1062 | ||
999 | #ifdef CONFIG_MMC_BLOCK_BOUNCE | 1063 | /* Since we do only SG emulation, we can have as many segs |
1000 | mmc->max_phys_segs = 1; | 1064 | * as we want. */ |
1001 | mmc->max_hw_segs = 1; | 1065 | mmc->max_phys_segs = 1024; |
1002 | #endif | 1066 | mmc->max_hw_segs = 1024; |
1067 | |||
1003 | mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ | 1068 | mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ |
1004 | mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ | 1069 | mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ |
1005 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | 1070 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; |
@@ -1008,31 +1073,31 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
1008 | mmc->ocr_avail = mmc_slot(host).ocr_mask; | 1073 | mmc->ocr_avail = mmc_slot(host).ocr_mask; |
1009 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; | 1074 | mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; |
1010 | 1075 | ||
1011 | if (pdata->slots[host->slot_id].wires >= 4) | 1076 | if (pdata->slots[host->slot_id].wires >= 8) |
1077 | mmc->caps |= MMC_CAP_8_BIT_DATA; | ||
1078 | else if (pdata->slots[host->slot_id].wires >= 4) | ||
1012 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1079 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
1013 | 1080 | ||
1014 | /* Only MMC1 supports 3.0V */ | 1081 | omap_hsmmc_init(host); |
1015 | if (host->id == OMAP_MMC1_DEVID) { | ||
1016 | hctl = SDVS30; | ||
1017 | capa = VS30 | VS18; | ||
1018 | } else { | ||
1019 | hctl = SDVS18; | ||
1020 | capa = VS18; | ||
1021 | } | ||
1022 | |||
1023 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
1024 | OMAP_HSMMC_READ(host->base, HCTL) | hctl); | ||
1025 | |||
1026 | OMAP_HSMMC_WRITE(host->base, CAPA, | ||
1027 | OMAP_HSMMC_READ(host->base, CAPA) | capa); | ||
1028 | |||
1029 | /* Set the controller to AUTO IDLE mode */ | ||
1030 | OMAP_HSMMC_WRITE(host->base, SYSCONFIG, | ||
1031 | OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE); | ||
1032 | 1082 | ||
1033 | /* Set SD bus power bit */ | 1083 | /* Select DMA lines */ |
1034 | OMAP_HSMMC_WRITE(host->base, HCTL, | 1084 | switch (host->id) { |
1035 | OMAP_HSMMC_READ(host->base, HCTL) | SDBP); | 1085 | case OMAP_MMC1_DEVID: |
1086 | host->dma_line_tx = OMAP24XX_DMA_MMC1_TX; | ||
1087 | host->dma_line_rx = OMAP24XX_DMA_MMC1_RX; | ||
1088 | break; | ||
1089 | case OMAP_MMC2_DEVID: | ||
1090 | host->dma_line_tx = OMAP24XX_DMA_MMC2_TX; | ||
1091 | host->dma_line_rx = OMAP24XX_DMA_MMC2_RX; | ||
1092 | break; | ||
1093 | case OMAP_MMC3_DEVID: | ||
1094 | host->dma_line_tx = OMAP34XX_DMA_MMC3_TX; | ||
1095 | host->dma_line_rx = OMAP34XX_DMA_MMC3_RX; | ||
1096 | break; | ||
1097 | default: | ||
1098 | dev_err(mmc_dev(host->mmc), "Invalid MMC id\n"); | ||
1099 | goto err_irq; | ||
1100 | } | ||
1036 | 1101 | ||
1037 | /* Request IRQ for MMC operations */ | 1102 | /* Request IRQ for MMC operations */ |
1038 | ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED, | 1103 | ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED, |
@@ -1051,7 +1116,7 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
1051 | } | 1116 | } |
1052 | 1117 | ||
1053 | /* Request IRQ for card detect */ | 1118 | /* Request IRQ for card detect */ |
1054 | if ((mmc_slot(host).card_detect_irq) && (mmc_slot(host).card_detect)) { | 1119 | if ((mmc_slot(host).card_detect_irq)) { |
1055 | ret = request_irq(mmc_slot(host).card_detect_irq, | 1120 | ret = request_irq(mmc_slot(host).card_detect_irq, |
1056 | omap_mmc_cd_handler, | 1121 | omap_mmc_cd_handler, |
1057 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | 1122 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
@@ -1074,8 +1139,8 @@ static int __init omap_mmc_probe(struct platform_device *pdev) | |||
1074 | if (ret < 0) | 1139 | if (ret < 0) |
1075 | goto err_slot_name; | 1140 | goto err_slot_name; |
1076 | } | 1141 | } |
1077 | if (mmc_slot(host).card_detect_irq && mmc_slot(host).card_detect && | 1142 | if (mmc_slot(host).card_detect_irq && |
1078 | host->pdata->slots[host->slot_id].get_cover_state) { | 1143 | host->pdata->slots[host->slot_id].get_cover_state) { |
1079 | ret = device_create_file(&mmc->class_dev, | 1144 | ret = device_create_file(&mmc->class_dev, |
1080 | &dev_attr_cover_switch); | 1145 | &dev_attr_cover_switch); |
1081 | if (ret < 0) | 1146 | if (ret < 0) |
@@ -1173,20 +1238,8 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state) | |||
1173 | " level suspend\n"); | 1238 | " level suspend\n"); |
1174 | } | 1239 | } |
1175 | 1240 | ||
1176 | if (host->id == OMAP_MMC1_DEVID | 1241 | OMAP_HSMMC_WRITE(host->base, HCTL, |
1177 | && !(OMAP_HSMMC_READ(host->base, HCTL) | 1242 | OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); |
1178 | & SDVSDET)) { | ||
1179 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
1180 | OMAP_HSMMC_READ(host->base, HCTL) | ||
1181 | & SDVSCLR); | ||
1182 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
1183 | OMAP_HSMMC_READ(host->base, HCTL) | ||
1184 | | SDVS30); | ||
1185 | OMAP_HSMMC_WRITE(host->base, HCTL, | ||
1186 | OMAP_HSMMC_READ(host->base, HCTL) | ||
1187 | | SDBP); | ||
1188 | } | ||
1189 | |||
1190 | clk_disable(host->fclk); | 1243 | clk_disable(host->fclk); |
1191 | clk_disable(host->iclk); | 1244 | clk_disable(host->iclk); |
1192 | clk_disable(host->dbclk); | 1245 | clk_disable(host->dbclk); |
@@ -1222,6 +1275,8 @@ static int omap_mmc_resume(struct platform_device *pdev) | |||
1222 | dev_dbg(mmc_dev(host->mmc), | 1275 | dev_dbg(mmc_dev(host->mmc), |
1223 | "Enabling debounce clk failed\n"); | 1276 | "Enabling debounce clk failed\n"); |
1224 | 1277 | ||
1278 | omap_hsmmc_init(host); | ||
1279 | |||
1225 | if (host->pdata->resume) { | 1280 | if (host->pdata->resume) { |
1226 | ret = host->pdata->resume(&pdev->dev, host->slot_id); | 1281 | ret = host->pdata->resume(&pdev->dev, host->slot_id); |
1227 | if (ret) | 1282 | if (ret) |
diff --git a/drivers/mmc/host/sdhci-of.c b/drivers/mmc/host/sdhci-of.c new file mode 100644 index 000000000000..3ff4ac3abe8b --- /dev/null +++ b/drivers/mmc/host/sdhci-of.c | |||
@@ -0,0 +1,309 @@ | |||
1 | /* | ||
2 | * OpenFirmware bindings for Secure Digital Host Controller Interface. | ||
3 | * | ||
4 | * Copyright (c) 2007 Freescale Semiconductor, Inc. | ||
5 | * Copyright (c) 2009 MontaVista Software, Inc. | ||
6 | * | ||
7 | * Authors: Xiaobo Xie <X.Xie@freescale.com> | ||
8 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2 of the License, or (at | ||
13 | * your option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/init.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/of_platform.h> | ||
23 | #include <linux/mmc/host.h> | ||
24 | #include "sdhci.h" | ||
25 | |||
26 | struct sdhci_of_data { | ||
27 | unsigned int quirks; | ||
28 | struct sdhci_ops ops; | ||
29 | }; | ||
30 | |||
31 | struct sdhci_of_host { | ||
32 | unsigned int clock; | ||
33 | u16 xfer_mode_shadow; | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * Ops and quirks for the Freescale eSDHC controller. | ||
38 | */ | ||
39 | |||
40 | #define ESDHC_DMA_SYSCTL 0x40c | ||
41 | #define ESDHC_DMA_SNOOP 0x00000040 | ||
42 | |||
43 | #define ESDHC_SYSTEM_CONTROL 0x2c | ||
44 | #define ESDHC_CLOCK_MASK 0x0000fff0 | ||
45 | #define ESDHC_PREDIV_SHIFT 8 | ||
46 | #define ESDHC_DIVIDER_SHIFT 4 | ||
47 | #define ESDHC_CLOCK_PEREN 0x00000004 | ||
48 | #define ESDHC_CLOCK_HCKEN 0x00000002 | ||
49 | #define ESDHC_CLOCK_IPGEN 0x00000001 | ||
50 | |||
51 | static u32 esdhc_readl(struct sdhci_host *host, int reg) | ||
52 | { | ||
53 | return in_be32(host->ioaddr + reg); | ||
54 | } | ||
55 | |||
56 | static u16 esdhc_readw(struct sdhci_host *host, int reg) | ||
57 | { | ||
58 | return in_be16(host->ioaddr + (reg ^ 0x2)); | ||
59 | } | ||
60 | |||
61 | static u8 esdhc_readb(struct sdhci_host *host, int reg) | ||
62 | { | ||
63 | return in_8(host->ioaddr + (reg ^ 0x3)); | ||
64 | } | ||
65 | |||
66 | static void esdhc_writel(struct sdhci_host *host, u32 val, int reg) | ||
67 | { | ||
68 | out_be32(host->ioaddr + reg, val); | ||
69 | } | ||
70 | |||
71 | static void esdhc_writew(struct sdhci_host *host, u16 val, int reg) | ||
72 | { | ||
73 | struct sdhci_of_host *of_host = sdhci_priv(host); | ||
74 | int base = reg & ~0x3; | ||
75 | int shift = (reg & 0x2) * 8; | ||
76 | |||
77 | switch (reg) { | ||
78 | case SDHCI_TRANSFER_MODE: | ||
79 | /* | ||
80 | * Postpone this write, we must do it together with a | ||
81 | * command write that is down below. | ||
82 | */ | ||
83 | of_host->xfer_mode_shadow = val; | ||
84 | return; | ||
85 | case SDHCI_COMMAND: | ||
86 | esdhc_writel(host, val << 16 | of_host->xfer_mode_shadow, | ||
87 | SDHCI_TRANSFER_MODE); | ||
88 | return; | ||
89 | case SDHCI_BLOCK_SIZE: | ||
90 | /* | ||
91 | * Two last DMA bits are reserved, and first one is used for | ||
92 | * non-standard blksz of 4096 bytes that we don't support | ||
93 | * yet. So clear the DMA boundary bits. | ||
94 | */ | ||
95 | val &= ~SDHCI_MAKE_BLKSZ(0x7, 0); | ||
96 | /* fall through */ | ||
97 | } | ||
98 | clrsetbits_be32(host->ioaddr + base, 0xffff << shift, val << shift); | ||
99 | } | ||
100 | |||
101 | static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) | ||
102 | { | ||
103 | int base = reg & ~0x3; | ||
104 | int shift = (reg & 0x3) * 8; | ||
105 | |||
106 | clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift); | ||
107 | } | ||
108 | |||
109 | static void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) | ||
110 | { | ||
111 | int div; | ||
112 | int pre_div = 2; | ||
113 | |||
114 | clrbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN | | ||
115 | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); | ||
116 | |||
117 | if (clock == 0) | ||
118 | goto out; | ||
119 | |||
120 | if (host->max_clk / 16 > clock) { | ||
121 | for (; pre_div < 256; pre_div *= 2) { | ||
122 | if (host->max_clk / pre_div < clock * 16) | ||
123 | break; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | for (div = 1; div <= 16; div++) { | ||
128 | if (host->max_clk / (div * pre_div) <= clock) | ||
129 | break; | ||
130 | } | ||
131 | |||
132 | pre_div >>= 1; | ||
133 | |||
134 | setbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN | | ||
135 | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | | ||
136 | div << ESDHC_DIVIDER_SHIFT | pre_div << ESDHC_PREDIV_SHIFT); | ||
137 | mdelay(100); | ||
138 | out: | ||
139 | host->clock = clock; | ||
140 | } | ||
141 | |||
142 | static int esdhc_enable_dma(struct sdhci_host *host) | ||
143 | { | ||
144 | setbits32(host->ioaddr + ESDHC_DMA_SYSCTL, ESDHC_DMA_SNOOP); | ||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static unsigned int esdhc_get_max_clock(struct sdhci_host *host) | ||
149 | { | ||
150 | struct sdhci_of_host *of_host = sdhci_priv(host); | ||
151 | |||
152 | return of_host->clock; | ||
153 | } | ||
154 | |||
155 | static unsigned int esdhc_get_timeout_clock(struct sdhci_host *host) | ||
156 | { | ||
157 | struct sdhci_of_host *of_host = sdhci_priv(host); | ||
158 | |||
159 | return of_host->clock / 1000; | ||
160 | } | ||
161 | |||
162 | static struct sdhci_of_data sdhci_esdhc = { | ||
163 | .quirks = SDHCI_QUIRK_FORCE_BLK_SZ_2048 | | ||
164 | SDHCI_QUIRK_BROKEN_CARD_DETECTION | | ||
165 | SDHCI_QUIRK_INVERTED_WRITE_PROTECT | | ||
166 | SDHCI_QUIRK_NO_BUSY_IRQ | | ||
167 | SDHCI_QUIRK_NONSTANDARD_CLOCK | | ||
168 | SDHCI_QUIRK_PIO_NEEDS_DELAY | | ||
169 | SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | | ||
170 | SDHCI_QUIRK_NO_CARD_NO_RESET, | ||
171 | .ops = { | ||
172 | .readl = esdhc_readl, | ||
173 | .readw = esdhc_readw, | ||
174 | .readb = esdhc_readb, | ||
175 | .writel = esdhc_writel, | ||
176 | .writew = esdhc_writew, | ||
177 | .writeb = esdhc_writeb, | ||
178 | .set_clock = esdhc_set_clock, | ||
179 | .enable_dma = esdhc_enable_dma, | ||
180 | .get_max_clock = esdhc_get_max_clock, | ||
181 | .get_timeout_clock = esdhc_get_timeout_clock, | ||
182 | }, | ||
183 | }; | ||
184 | |||
185 | #ifdef CONFIG_PM | ||
186 | |||
187 | static int sdhci_of_suspend(struct of_device *ofdev, pm_message_t state) | ||
188 | { | ||
189 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); | ||
190 | |||
191 | return mmc_suspend_host(host->mmc, state); | ||
192 | } | ||
193 | |||
194 | static int sdhci_of_resume(struct of_device *ofdev) | ||
195 | { | ||
196 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); | ||
197 | |||
198 | return mmc_resume_host(host->mmc); | ||
199 | } | ||
200 | |||
201 | #else | ||
202 | |||
203 | #define sdhci_of_suspend NULL | ||
204 | #define sdhci_of_resume NULL | ||
205 | |||
206 | #endif | ||
207 | |||
208 | static int __devinit sdhci_of_probe(struct of_device *ofdev, | ||
209 | const struct of_device_id *match) | ||
210 | { | ||
211 | struct device_node *np = ofdev->node; | ||
212 | struct sdhci_of_data *sdhci_of_data = match->data; | ||
213 | struct sdhci_host *host; | ||
214 | struct sdhci_of_host *of_host; | ||
215 | const u32 *clk; | ||
216 | int size; | ||
217 | int ret; | ||
218 | |||
219 | if (!of_device_is_available(np)) | ||
220 | return -ENODEV; | ||
221 | |||
222 | host = sdhci_alloc_host(&ofdev->dev, sizeof(*of_host)); | ||
223 | if (!host) | ||
224 | return -ENOMEM; | ||
225 | |||
226 | of_host = sdhci_priv(host); | ||
227 | dev_set_drvdata(&ofdev->dev, host); | ||
228 | |||
229 | host->ioaddr = of_iomap(np, 0); | ||
230 | if (!host->ioaddr) { | ||
231 | ret = -ENOMEM; | ||
232 | goto err_addr_map; | ||
233 | } | ||
234 | |||
235 | host->irq = irq_of_parse_and_map(np, 0); | ||
236 | if (!host->irq) { | ||
237 | ret = -EINVAL; | ||
238 | goto err_no_irq; | ||
239 | } | ||
240 | |||
241 | host->hw_name = dev_name(&ofdev->dev); | ||
242 | if (sdhci_of_data) { | ||
243 | host->quirks = sdhci_of_data->quirks; | ||
244 | host->ops = &sdhci_of_data->ops; | ||
245 | } | ||
246 | |||
247 | clk = of_get_property(np, "clock-frequency", &size); | ||
248 | if (clk && size == sizeof(*clk) && *clk) | ||
249 | of_host->clock = *clk; | ||
250 | |||
251 | ret = sdhci_add_host(host); | ||
252 | if (ret) | ||
253 | goto err_add_host; | ||
254 | |||
255 | return 0; | ||
256 | |||
257 | err_add_host: | ||
258 | irq_dispose_mapping(host->irq); | ||
259 | err_no_irq: | ||
260 | iounmap(host->ioaddr); | ||
261 | err_addr_map: | ||
262 | sdhci_free_host(host); | ||
263 | return ret; | ||
264 | } | ||
265 | |||
266 | static int __devexit sdhci_of_remove(struct of_device *ofdev) | ||
267 | { | ||
268 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); | ||
269 | |||
270 | sdhci_remove_host(host, 0); | ||
271 | sdhci_free_host(host); | ||
272 | irq_dispose_mapping(host->irq); | ||
273 | iounmap(host->ioaddr); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static const struct of_device_id sdhci_of_match[] = { | ||
278 | { .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, }, | ||
279 | { .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, }, | ||
280 | { .compatible = "generic-sdhci", }, | ||
281 | {}, | ||
282 | }; | ||
283 | MODULE_DEVICE_TABLE(of, sdhci_of_match); | ||
284 | |||
285 | static struct of_platform_driver sdhci_of_driver = { | ||
286 | .driver.name = "sdhci-of", | ||
287 | .match_table = sdhci_of_match, | ||
288 | .probe = sdhci_of_probe, | ||
289 | .remove = __devexit_p(sdhci_of_remove), | ||
290 | .suspend = sdhci_of_suspend, | ||
291 | .resume = sdhci_of_resume, | ||
292 | }; | ||
293 | |||
294 | static int __init sdhci_of_init(void) | ||
295 | { | ||
296 | return of_register_platform_driver(&sdhci_of_driver); | ||
297 | } | ||
298 | module_init(sdhci_of_init); | ||
299 | |||
300 | static void __exit sdhci_of_exit(void) | ||
301 | { | ||
302 | of_unregister_platform_driver(&sdhci_of_driver); | ||
303 | } | ||
304 | module_exit(sdhci_of_exit); | ||
305 | |||
306 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface OF driver"); | ||
307 | MODULE_AUTHOR("Xiaobo Xie <X.Xie@freescale.com>, " | ||
308 | "Anton Vorontsov <avorontsov@ru.mvista.com>"); | ||
309 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index accb592764ed..30d8e3d4e6fd 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -48,35 +48,35 @@ static void sdhci_dumpregs(struct sdhci_host *host) | |||
48 | printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n"); | 48 | printk(KERN_DEBUG DRIVER_NAME ": ============== REGISTER DUMP ==============\n"); |
49 | 49 | ||
50 | printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", | 50 | printk(KERN_DEBUG DRIVER_NAME ": Sys addr: 0x%08x | Version: 0x%08x\n", |
51 | readl(host->ioaddr + SDHCI_DMA_ADDRESS), | 51 | sdhci_readl(host, SDHCI_DMA_ADDRESS), |
52 | readw(host->ioaddr + SDHCI_HOST_VERSION)); | 52 | sdhci_readw(host, SDHCI_HOST_VERSION)); |
53 | printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", | 53 | printk(KERN_DEBUG DRIVER_NAME ": Blk size: 0x%08x | Blk cnt: 0x%08x\n", |
54 | readw(host->ioaddr + SDHCI_BLOCK_SIZE), | 54 | sdhci_readw(host, SDHCI_BLOCK_SIZE), |
55 | readw(host->ioaddr + SDHCI_BLOCK_COUNT)); | 55 | sdhci_readw(host, SDHCI_BLOCK_COUNT)); |
56 | printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", | 56 | printk(KERN_DEBUG DRIVER_NAME ": Argument: 0x%08x | Trn mode: 0x%08x\n", |
57 | readl(host->ioaddr + SDHCI_ARGUMENT), | 57 | sdhci_readl(host, SDHCI_ARGUMENT), |
58 | readw(host->ioaddr + SDHCI_TRANSFER_MODE)); | 58 | sdhci_readw(host, SDHCI_TRANSFER_MODE)); |
59 | printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", | 59 | printk(KERN_DEBUG DRIVER_NAME ": Present: 0x%08x | Host ctl: 0x%08x\n", |
60 | readl(host->ioaddr + SDHCI_PRESENT_STATE), | 60 | sdhci_readl(host, SDHCI_PRESENT_STATE), |
61 | readb(host->ioaddr + SDHCI_HOST_CONTROL)); | 61 | sdhci_readb(host, SDHCI_HOST_CONTROL)); |
62 | printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", | 62 | printk(KERN_DEBUG DRIVER_NAME ": Power: 0x%08x | Blk gap: 0x%08x\n", |
63 | readb(host->ioaddr + SDHCI_POWER_CONTROL), | 63 | sdhci_readb(host, SDHCI_POWER_CONTROL), |
64 | readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL)); | 64 | sdhci_readb(host, SDHCI_BLOCK_GAP_CONTROL)); |
65 | printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", | 65 | printk(KERN_DEBUG DRIVER_NAME ": Wake-up: 0x%08x | Clock: 0x%08x\n", |
66 | readb(host->ioaddr + SDHCI_WAKE_UP_CONTROL), | 66 | sdhci_readb(host, SDHCI_WAKE_UP_CONTROL), |
67 | readw(host->ioaddr + SDHCI_CLOCK_CONTROL)); | 67 | sdhci_readw(host, SDHCI_CLOCK_CONTROL)); |
68 | printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", | 68 | printk(KERN_DEBUG DRIVER_NAME ": Timeout: 0x%08x | Int stat: 0x%08x\n", |
69 | readb(host->ioaddr + SDHCI_TIMEOUT_CONTROL), | 69 | sdhci_readb(host, SDHCI_TIMEOUT_CONTROL), |
70 | readl(host->ioaddr + SDHCI_INT_STATUS)); | 70 | sdhci_readl(host, SDHCI_INT_STATUS)); |
71 | printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", | 71 | printk(KERN_DEBUG DRIVER_NAME ": Int enab: 0x%08x | Sig enab: 0x%08x\n", |
72 | readl(host->ioaddr + SDHCI_INT_ENABLE), | 72 | sdhci_readl(host, SDHCI_INT_ENABLE), |
73 | readl(host->ioaddr + SDHCI_SIGNAL_ENABLE)); | 73 | sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); |
74 | printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", | 74 | printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", |
75 | readw(host->ioaddr + SDHCI_ACMD12_ERR), | 75 | sdhci_readw(host, SDHCI_ACMD12_ERR), |
76 | readw(host->ioaddr + SDHCI_SLOT_INT_STATUS)); | 76 | sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); |
77 | printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n", | 77 | printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n", |
78 | readl(host->ioaddr + SDHCI_CAPABILITIES), | 78 | sdhci_readl(host, SDHCI_CAPABILITIES), |
79 | readl(host->ioaddr + SDHCI_MAX_CURRENT)); | 79 | sdhci_readl(host, SDHCI_MAX_CURRENT)); |
80 | 80 | ||
81 | printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n"); | 81 | printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n"); |
82 | } | 82 | } |
@@ -87,17 +87,65 @@ static void sdhci_dumpregs(struct sdhci_host *host) | |||
87 | * * | 87 | * * |
88 | \*****************************************************************************/ | 88 | \*****************************************************************************/ |
89 | 89 | ||
90 | static void sdhci_clear_set_irqs(struct sdhci_host *host, u32 clear, u32 set) | ||
91 | { | ||
92 | u32 ier; | ||
93 | |||
94 | ier = sdhci_readl(host, SDHCI_INT_ENABLE); | ||
95 | ier &= ~clear; | ||
96 | ier |= set; | ||
97 | sdhci_writel(host, ier, SDHCI_INT_ENABLE); | ||
98 | sdhci_writel(host, ier, SDHCI_SIGNAL_ENABLE); | ||
99 | } | ||
100 | |||
101 | static void sdhci_unmask_irqs(struct sdhci_host *host, u32 irqs) | ||
102 | { | ||
103 | sdhci_clear_set_irqs(host, 0, irqs); | ||
104 | } | ||
105 | |||
106 | static void sdhci_mask_irqs(struct sdhci_host *host, u32 irqs) | ||
107 | { | ||
108 | sdhci_clear_set_irqs(host, irqs, 0); | ||
109 | } | ||
110 | |||
111 | static void sdhci_set_card_detection(struct sdhci_host *host, bool enable) | ||
112 | { | ||
113 | u32 irqs = SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT; | ||
114 | |||
115 | if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) | ||
116 | return; | ||
117 | |||
118 | if (enable) | ||
119 | sdhci_unmask_irqs(host, irqs); | ||
120 | else | ||
121 | sdhci_mask_irqs(host, irqs); | ||
122 | } | ||
123 | |||
124 | static void sdhci_enable_card_detection(struct sdhci_host *host) | ||
125 | { | ||
126 | sdhci_set_card_detection(host, true); | ||
127 | } | ||
128 | |||
129 | static void sdhci_disable_card_detection(struct sdhci_host *host) | ||
130 | { | ||
131 | sdhci_set_card_detection(host, false); | ||
132 | } | ||
133 | |||
90 | static void sdhci_reset(struct sdhci_host *host, u8 mask) | 134 | static void sdhci_reset(struct sdhci_host *host, u8 mask) |
91 | { | 135 | { |
92 | unsigned long timeout; | 136 | unsigned long timeout; |
137 | u32 uninitialized_var(ier); | ||
93 | 138 | ||
94 | if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { | 139 | if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { |
95 | if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & | 140 | if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & |
96 | SDHCI_CARD_PRESENT)) | 141 | SDHCI_CARD_PRESENT)) |
97 | return; | 142 | return; |
98 | } | 143 | } |
99 | 144 | ||
100 | writeb(mask, host->ioaddr + SDHCI_SOFTWARE_RESET); | 145 | if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) |
146 | ier = sdhci_readl(host, SDHCI_INT_ENABLE); | ||
147 | |||
148 | sdhci_writeb(host, mask, SDHCI_SOFTWARE_RESET); | ||
101 | 149 | ||
102 | if (mask & SDHCI_RESET_ALL) | 150 | if (mask & SDHCI_RESET_ALL) |
103 | host->clock = 0; | 151 | host->clock = 0; |
@@ -106,7 +154,7 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) | |||
106 | timeout = 100; | 154 | timeout = 100; |
107 | 155 | ||
108 | /* hw clears the bit when it's done */ | 156 | /* hw clears the bit when it's done */ |
109 | while (readb(host->ioaddr + SDHCI_SOFTWARE_RESET) & mask) { | 157 | while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) { |
110 | if (timeout == 0) { | 158 | if (timeout == 0) { |
111 | printk(KERN_ERR "%s: Reset 0x%x never completed.\n", | 159 | printk(KERN_ERR "%s: Reset 0x%x never completed.\n", |
112 | mmc_hostname(host->mmc), (int)mask); | 160 | mmc_hostname(host->mmc), (int)mask); |
@@ -116,42 +164,44 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) | |||
116 | timeout--; | 164 | timeout--; |
117 | mdelay(1); | 165 | mdelay(1); |
118 | } | 166 | } |
167 | |||
168 | if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET) | ||
169 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, ier); | ||
119 | } | 170 | } |
120 | 171 | ||
121 | static void sdhci_init(struct sdhci_host *host) | 172 | static void sdhci_init(struct sdhci_host *host) |
122 | { | 173 | { |
123 | u32 intmask; | ||
124 | |||
125 | sdhci_reset(host, SDHCI_RESET_ALL); | 174 | sdhci_reset(host, SDHCI_RESET_ALL); |
126 | 175 | ||
127 | intmask = SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | | 176 | sdhci_clear_set_irqs(host, SDHCI_INT_ALL_MASK, |
177 | SDHCI_INT_BUS_POWER | SDHCI_INT_DATA_END_BIT | | ||
128 | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | | 178 | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX | |
129 | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | | 179 | SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT | |
130 | SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT | | 180 | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE); |
131 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | | 181 | } |
132 | SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE | | ||
133 | SDHCI_INT_ADMA_ERROR; | ||
134 | 182 | ||
135 | writel(intmask, host->ioaddr + SDHCI_INT_ENABLE); | 183 | static void sdhci_reinit(struct sdhci_host *host) |
136 | writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE); | 184 | { |
185 | sdhci_init(host); | ||
186 | sdhci_enable_card_detection(host); | ||
137 | } | 187 | } |
138 | 188 | ||
139 | static void sdhci_activate_led(struct sdhci_host *host) | 189 | static void sdhci_activate_led(struct sdhci_host *host) |
140 | { | 190 | { |
141 | u8 ctrl; | 191 | u8 ctrl; |
142 | 192 | ||
143 | ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); | 193 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
144 | ctrl |= SDHCI_CTRL_LED; | 194 | ctrl |= SDHCI_CTRL_LED; |
145 | writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); | 195 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); |
146 | } | 196 | } |
147 | 197 | ||
148 | static void sdhci_deactivate_led(struct sdhci_host *host) | 198 | static void sdhci_deactivate_led(struct sdhci_host *host) |
149 | { | 199 | { |
150 | u8 ctrl; | 200 | u8 ctrl; |
151 | 201 | ||
152 | ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); | 202 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
153 | ctrl &= ~SDHCI_CTRL_LED; | 203 | ctrl &= ~SDHCI_CTRL_LED; |
154 | writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); | 204 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); |
155 | } | 205 | } |
156 | 206 | ||
157 | #ifdef SDHCI_USE_LEDS_CLASS | 207 | #ifdef SDHCI_USE_LEDS_CLASS |
@@ -205,7 +255,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) | |||
205 | 255 | ||
206 | while (len) { | 256 | while (len) { |
207 | if (chunk == 0) { | 257 | if (chunk == 0) { |
208 | scratch = readl(host->ioaddr + SDHCI_BUFFER); | 258 | scratch = sdhci_readl(host, SDHCI_BUFFER); |
209 | chunk = 4; | 259 | chunk = 4; |
210 | } | 260 | } |
211 | 261 | ||
@@ -257,7 +307,7 @@ static void sdhci_write_block_pio(struct sdhci_host *host) | |||
257 | len--; | 307 | len--; |
258 | 308 | ||
259 | if ((chunk == 4) || ((len == 0) && (blksize == 0))) { | 309 | if ((chunk == 4) || ((len == 0) && (blksize == 0))) { |
260 | writel(scratch, host->ioaddr + SDHCI_BUFFER); | 310 | sdhci_writel(host, scratch, SDHCI_BUFFER); |
261 | chunk = 0; | 311 | chunk = 0; |
262 | scratch = 0; | 312 | scratch = 0; |
263 | } | 313 | } |
@@ -292,7 +342,10 @@ static void sdhci_transfer_pio(struct sdhci_host *host) | |||
292 | (host->data->blocks == 1)) | 342 | (host->data->blocks == 1)) |
293 | mask = ~0; | 343 | mask = ~0; |
294 | 344 | ||
295 | while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) { | 345 | while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { |
346 | if (host->quirks & SDHCI_QUIRK_PIO_NEEDS_DELAY) | ||
347 | udelay(100); | ||
348 | |||
296 | if (host->data->flags & MMC_DATA_READ) | 349 | if (host->data->flags & MMC_DATA_READ) |
297 | sdhci_read_block_pio(host); | 350 | sdhci_read_block_pio(host); |
298 | else | 351 | else |
@@ -561,6 +614,17 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) | |||
561 | return count; | 614 | return count; |
562 | } | 615 | } |
563 | 616 | ||
617 | static void sdhci_set_transfer_irqs(struct sdhci_host *host) | ||
618 | { | ||
619 | u32 pio_irqs = SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL; | ||
620 | u32 dma_irqs = SDHCI_INT_DMA_END | SDHCI_INT_ADMA_ERROR; | ||
621 | |||
622 | if (host->flags & SDHCI_REQ_USE_DMA) | ||
623 | sdhci_clear_set_irqs(host, pio_irqs, dma_irqs); | ||
624 | else | ||
625 | sdhci_clear_set_irqs(host, dma_irqs, pio_irqs); | ||
626 | } | ||
627 | |||
564 | static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | 628 | static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) |
565 | { | 629 | { |
566 | u8 count; | 630 | u8 count; |
@@ -581,7 +645,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
581 | host->data_early = 0; | 645 | host->data_early = 0; |
582 | 646 | ||
583 | count = sdhci_calc_timeout(host, data); | 647 | count = sdhci_calc_timeout(host, data); |
584 | writeb(count, host->ioaddr + SDHCI_TIMEOUT_CONTROL); | 648 | sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); |
585 | 649 | ||
586 | if (host->flags & SDHCI_USE_DMA) | 650 | if (host->flags & SDHCI_USE_DMA) |
587 | host->flags |= SDHCI_REQ_USE_DMA; | 651 | host->flags |= SDHCI_REQ_USE_DMA; |
@@ -661,8 +725,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
661 | WARN_ON(1); | 725 | WARN_ON(1); |
662 | host->flags &= ~SDHCI_REQ_USE_DMA; | 726 | host->flags &= ~SDHCI_REQ_USE_DMA; |
663 | } else { | 727 | } else { |
664 | writel(host->adma_addr, | 728 | sdhci_writel(host, host->adma_addr, |
665 | host->ioaddr + SDHCI_ADMA_ADDRESS); | 729 | SDHCI_ADMA_ADDRESS); |
666 | } | 730 | } |
667 | } else { | 731 | } else { |
668 | int sg_cnt; | 732 | int sg_cnt; |
@@ -681,8 +745,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
681 | host->flags &= ~SDHCI_REQ_USE_DMA; | 745 | host->flags &= ~SDHCI_REQ_USE_DMA; |
682 | } else { | 746 | } else { |
683 | WARN_ON(sg_cnt != 1); | 747 | WARN_ON(sg_cnt != 1); |
684 | writel(sg_dma_address(data->sg), | 748 | sdhci_writel(host, sg_dma_address(data->sg), |
685 | host->ioaddr + SDHCI_DMA_ADDRESS); | 749 | SDHCI_DMA_ADDRESS); |
686 | } | 750 | } |
687 | } | 751 | } |
688 | } | 752 | } |
@@ -693,14 +757,14 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
693 | * is ADMA. | 757 | * is ADMA. |
694 | */ | 758 | */ |
695 | if (host->version >= SDHCI_SPEC_200) { | 759 | if (host->version >= SDHCI_SPEC_200) { |
696 | ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); | 760 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
697 | ctrl &= ~SDHCI_CTRL_DMA_MASK; | 761 | ctrl &= ~SDHCI_CTRL_DMA_MASK; |
698 | if ((host->flags & SDHCI_REQ_USE_DMA) && | 762 | if ((host->flags & SDHCI_REQ_USE_DMA) && |
699 | (host->flags & SDHCI_USE_ADMA)) | 763 | (host->flags & SDHCI_USE_ADMA)) |
700 | ctrl |= SDHCI_CTRL_ADMA32; | 764 | ctrl |= SDHCI_CTRL_ADMA32; |
701 | else | 765 | else |
702 | ctrl |= SDHCI_CTRL_SDMA; | 766 | ctrl |= SDHCI_CTRL_SDMA; |
703 | writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); | 767 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); |
704 | } | 768 | } |
705 | 769 | ||
706 | if (!(host->flags & SDHCI_REQ_USE_DMA)) { | 770 | if (!(host->flags & SDHCI_REQ_USE_DMA)) { |
@@ -709,10 +773,11 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
709 | host->blocks = data->blocks; | 773 | host->blocks = data->blocks; |
710 | } | 774 | } |
711 | 775 | ||
776 | sdhci_set_transfer_irqs(host); | ||
777 | |||
712 | /* We do not handle DMA boundaries, so set it to max (512 KiB) */ | 778 | /* We do not handle DMA boundaries, so set it to max (512 KiB) */ |
713 | writew(SDHCI_MAKE_BLKSZ(7, data->blksz), | 779 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, data->blksz), SDHCI_BLOCK_SIZE); |
714 | host->ioaddr + SDHCI_BLOCK_SIZE); | 780 | sdhci_writew(host, data->blocks, SDHCI_BLOCK_COUNT); |
715 | writew(data->blocks, host->ioaddr + SDHCI_BLOCK_COUNT); | ||
716 | } | 781 | } |
717 | 782 | ||
718 | static void sdhci_set_transfer_mode(struct sdhci_host *host, | 783 | static void sdhci_set_transfer_mode(struct sdhci_host *host, |
@@ -733,7 +798,7 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host, | |||
733 | if (host->flags & SDHCI_REQ_USE_DMA) | 798 | if (host->flags & SDHCI_REQ_USE_DMA) |
734 | mode |= SDHCI_TRNS_DMA; | 799 | mode |= SDHCI_TRNS_DMA; |
735 | 800 | ||
736 | writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE); | 801 | sdhci_writew(host, mode, SDHCI_TRANSFER_MODE); |
737 | } | 802 | } |
738 | 803 | ||
739 | static void sdhci_finish_data(struct sdhci_host *host) | 804 | static void sdhci_finish_data(struct sdhci_host *host) |
@@ -802,7 +867,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
802 | if (host->mrq->data && (cmd == host->mrq->data->stop)) | 867 | if (host->mrq->data && (cmd == host->mrq->data->stop)) |
803 | mask &= ~SDHCI_DATA_INHIBIT; | 868 | mask &= ~SDHCI_DATA_INHIBIT; |
804 | 869 | ||
805 | while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) { | 870 | while (sdhci_readl(host, SDHCI_PRESENT_STATE) & mask) { |
806 | if (timeout == 0) { | 871 | if (timeout == 0) { |
807 | printk(KERN_ERR "%s: Controller never released " | 872 | printk(KERN_ERR "%s: Controller never released " |
808 | "inhibit bit(s).\n", mmc_hostname(host->mmc)); | 873 | "inhibit bit(s).\n", mmc_hostname(host->mmc)); |
@@ -821,7 +886,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
821 | 886 | ||
822 | sdhci_prepare_data(host, cmd->data); | 887 | sdhci_prepare_data(host, cmd->data); |
823 | 888 | ||
824 | writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT); | 889 | sdhci_writel(host, cmd->arg, SDHCI_ARGUMENT); |
825 | 890 | ||
826 | sdhci_set_transfer_mode(host, cmd->data); | 891 | sdhci_set_transfer_mode(host, cmd->data); |
827 | 892 | ||
@@ -849,8 +914,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
849 | if (cmd->data) | 914 | if (cmd->data) |
850 | flags |= SDHCI_CMD_DATA; | 915 | flags |= SDHCI_CMD_DATA; |
851 | 916 | ||
852 | writew(SDHCI_MAKE_CMD(cmd->opcode, flags), | 917 | sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); |
853 | host->ioaddr + SDHCI_COMMAND); | ||
854 | } | 918 | } |
855 | 919 | ||
856 | static void sdhci_finish_command(struct sdhci_host *host) | 920 | static void sdhci_finish_command(struct sdhci_host *host) |
@@ -863,15 +927,15 @@ static void sdhci_finish_command(struct sdhci_host *host) | |||
863 | if (host->cmd->flags & MMC_RSP_136) { | 927 | if (host->cmd->flags & MMC_RSP_136) { |
864 | /* CRC is stripped so we need to do some shifting. */ | 928 | /* CRC is stripped so we need to do some shifting. */ |
865 | for (i = 0;i < 4;i++) { | 929 | for (i = 0;i < 4;i++) { |
866 | host->cmd->resp[i] = readl(host->ioaddr + | 930 | host->cmd->resp[i] = sdhci_readl(host, |
867 | SDHCI_RESPONSE + (3-i)*4) << 8; | 931 | SDHCI_RESPONSE + (3-i)*4) << 8; |
868 | if (i != 3) | 932 | if (i != 3) |
869 | host->cmd->resp[i] |= | 933 | host->cmd->resp[i] |= |
870 | readb(host->ioaddr + | 934 | sdhci_readb(host, |
871 | SDHCI_RESPONSE + (3-i)*4-1); | 935 | SDHCI_RESPONSE + (3-i)*4-1); |
872 | } | 936 | } |
873 | } else { | 937 | } else { |
874 | host->cmd->resp[0] = readl(host->ioaddr + SDHCI_RESPONSE); | 938 | host->cmd->resp[0] = sdhci_readl(host, SDHCI_RESPONSE); |
875 | } | 939 | } |
876 | } | 940 | } |
877 | 941 | ||
@@ -895,7 +959,13 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
895 | if (clock == host->clock) | 959 | if (clock == host->clock) |
896 | return; | 960 | return; |
897 | 961 | ||
898 | writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL); | 962 | if (host->ops->set_clock) { |
963 | host->ops->set_clock(host, clock); | ||
964 | if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK) | ||
965 | return; | ||
966 | } | ||
967 | |||
968 | sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); | ||
899 | 969 | ||
900 | if (clock == 0) | 970 | if (clock == 0) |
901 | goto out; | 971 | goto out; |
@@ -908,11 +978,11 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
908 | 978 | ||
909 | clk = div << SDHCI_DIVIDER_SHIFT; | 979 | clk = div << SDHCI_DIVIDER_SHIFT; |
910 | clk |= SDHCI_CLOCK_INT_EN; | 980 | clk |= SDHCI_CLOCK_INT_EN; |
911 | writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); | 981 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); |
912 | 982 | ||
913 | /* Wait max 10 ms */ | 983 | /* Wait max 10 ms */ |
914 | timeout = 10; | 984 | timeout = 10; |
915 | while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL)) | 985 | while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) |
916 | & SDHCI_CLOCK_INT_STABLE)) { | 986 | & SDHCI_CLOCK_INT_STABLE)) { |
917 | if (timeout == 0) { | 987 | if (timeout == 0) { |
918 | printk(KERN_ERR "%s: Internal clock never " | 988 | printk(KERN_ERR "%s: Internal clock never " |
@@ -925,7 +995,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
925 | } | 995 | } |
926 | 996 | ||
927 | clk |= SDHCI_CLOCK_CARD_EN; | 997 | clk |= SDHCI_CLOCK_CARD_EN; |
928 | writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); | 998 | sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); |
929 | 999 | ||
930 | out: | 1000 | out: |
931 | host->clock = clock; | 1001 | host->clock = clock; |
@@ -939,7 +1009,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
939 | return; | 1009 | return; |
940 | 1010 | ||
941 | if (power == (unsigned short)-1) { | 1011 | if (power == (unsigned short)-1) { |
942 | writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); | 1012 | sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); |
943 | goto out; | 1013 | goto out; |
944 | } | 1014 | } |
945 | 1015 | ||
@@ -948,7 +1018,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
948 | * a new value. Some controllers don't seem to like this though. | 1018 | * a new value. Some controllers don't seem to like this though. |
949 | */ | 1019 | */ |
950 | if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) | 1020 | if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) |
951 | writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); | 1021 | sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); |
952 | 1022 | ||
953 | pwr = SDHCI_POWER_ON; | 1023 | pwr = SDHCI_POWER_ON; |
954 | 1024 | ||
@@ -973,10 +1043,9 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
973 | * and set turn on power at the same time, so set the voltage first. | 1043 | * and set turn on power at the same time, so set the voltage first. |
974 | */ | 1044 | */ |
975 | if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)) | 1045 | if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)) |
976 | writeb(pwr & ~SDHCI_POWER_ON, | 1046 | sdhci_writeb(host, pwr & ~SDHCI_POWER_ON, SDHCI_POWER_CONTROL); |
977 | host->ioaddr + SDHCI_POWER_CONTROL); | ||
978 | 1047 | ||
979 | writeb(pwr, host->ioaddr + SDHCI_POWER_CONTROL); | 1048 | sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); |
980 | 1049 | ||
981 | out: | 1050 | out: |
982 | host->power = power; | 1051 | host->power = power; |
@@ -991,6 +1060,7 @@ out: | |||
991 | static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | 1060 | static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) |
992 | { | 1061 | { |
993 | struct sdhci_host *host; | 1062 | struct sdhci_host *host; |
1063 | bool present; | ||
994 | unsigned long flags; | 1064 | unsigned long flags; |
995 | 1065 | ||
996 | host = mmc_priv(mmc); | 1066 | host = mmc_priv(mmc); |
@@ -1005,8 +1075,14 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1005 | 1075 | ||
1006 | host->mrq = mrq; | 1076 | host->mrq = mrq; |
1007 | 1077 | ||
1008 | if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT) | 1078 | /* If polling, assume that the card is always present. */ |
1009 | || (host->flags & SDHCI_DEVICE_DEAD)) { | 1079 | if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) |
1080 | present = true; | ||
1081 | else | ||
1082 | present = sdhci_readl(host, SDHCI_PRESENT_STATE) & | ||
1083 | SDHCI_CARD_PRESENT; | ||
1084 | |||
1085 | if (!present || host->flags & SDHCI_DEVICE_DEAD) { | ||
1010 | host->mrq->cmd->error = -ENOMEDIUM; | 1086 | host->mrq->cmd->error = -ENOMEDIUM; |
1011 | tasklet_schedule(&host->finish_tasklet); | 1087 | tasklet_schedule(&host->finish_tasklet); |
1012 | } else | 1088 | } else |
@@ -1034,8 +1110,8 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1034 | * Should clear out any weird states. | 1110 | * Should clear out any weird states. |
1035 | */ | 1111 | */ |
1036 | if (ios->power_mode == MMC_POWER_OFF) { | 1112 | if (ios->power_mode == MMC_POWER_OFF) { |
1037 | writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE); | 1113 | sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); |
1038 | sdhci_init(host); | 1114 | sdhci_reinit(host); |
1039 | } | 1115 | } |
1040 | 1116 | ||
1041 | sdhci_set_clock(host, ios->clock); | 1117 | sdhci_set_clock(host, ios->clock); |
@@ -1045,7 +1121,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1045 | else | 1121 | else |
1046 | sdhci_set_power(host, ios->vdd); | 1122 | sdhci_set_power(host, ios->vdd); |
1047 | 1123 | ||
1048 | ctrl = readb(host->ioaddr + SDHCI_HOST_CONTROL); | 1124 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); |
1049 | 1125 | ||
1050 | if (ios->bus_width == MMC_BUS_WIDTH_4) | 1126 | if (ios->bus_width == MMC_BUS_WIDTH_4) |
1051 | ctrl |= SDHCI_CTRL_4BITBUS; | 1127 | ctrl |= SDHCI_CTRL_4BITBUS; |
@@ -1057,7 +1133,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1057 | else | 1133 | else |
1058 | ctrl &= ~SDHCI_CTRL_HISPD; | 1134 | ctrl &= ~SDHCI_CTRL_HISPD; |
1059 | 1135 | ||
1060 | writeb(ctrl, host->ioaddr + SDHCI_HOST_CONTROL); | 1136 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); |
1061 | 1137 | ||
1062 | /* | 1138 | /* |
1063 | * Some (ENE) controllers go apeshit on some ios operation, | 1139 | * Some (ENE) controllers go apeshit on some ios operation, |
@@ -1085,10 +1161,12 @@ static int sdhci_get_ro(struct mmc_host *mmc) | |||
1085 | if (host->flags & SDHCI_DEVICE_DEAD) | 1161 | if (host->flags & SDHCI_DEVICE_DEAD) |
1086 | present = 0; | 1162 | present = 0; |
1087 | else | 1163 | else |
1088 | present = readl(host->ioaddr + SDHCI_PRESENT_STATE); | 1164 | present = sdhci_readl(host, SDHCI_PRESENT_STATE); |
1089 | 1165 | ||
1090 | spin_unlock_irqrestore(&host->lock, flags); | 1166 | spin_unlock_irqrestore(&host->lock, flags); |
1091 | 1167 | ||
1168 | if (host->quirks & SDHCI_QUIRK_INVERTED_WRITE_PROTECT) | ||
1169 | return !!(present & SDHCI_WRITE_PROTECT); | ||
1092 | return !(present & SDHCI_WRITE_PROTECT); | 1170 | return !(present & SDHCI_WRITE_PROTECT); |
1093 | } | 1171 | } |
1094 | 1172 | ||
@@ -1096,7 +1174,6 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
1096 | { | 1174 | { |
1097 | struct sdhci_host *host; | 1175 | struct sdhci_host *host; |
1098 | unsigned long flags; | 1176 | unsigned long flags; |
1099 | u32 ier; | ||
1100 | 1177 | ||
1101 | host = mmc_priv(mmc); | 1178 | host = mmc_priv(mmc); |
1102 | 1179 | ||
@@ -1105,15 +1182,10 @@ static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
1105 | if (host->flags & SDHCI_DEVICE_DEAD) | 1182 | if (host->flags & SDHCI_DEVICE_DEAD) |
1106 | goto out; | 1183 | goto out; |
1107 | 1184 | ||
1108 | ier = readl(host->ioaddr + SDHCI_INT_ENABLE); | ||
1109 | |||
1110 | ier &= ~SDHCI_INT_CARD_INT; | ||
1111 | if (enable) | 1185 | if (enable) |
1112 | ier |= SDHCI_INT_CARD_INT; | 1186 | sdhci_unmask_irqs(host, SDHCI_INT_CARD_INT); |
1113 | 1187 | else | |
1114 | writel(ier, host->ioaddr + SDHCI_INT_ENABLE); | 1188 | sdhci_mask_irqs(host, SDHCI_INT_CARD_INT); |
1115 | writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE); | ||
1116 | |||
1117 | out: | 1189 | out: |
1118 | mmiowb(); | 1190 | mmiowb(); |
1119 | 1191 | ||
@@ -1142,7 +1214,7 @@ static void sdhci_tasklet_card(unsigned long param) | |||
1142 | 1214 | ||
1143 | spin_lock_irqsave(&host->lock, flags); | 1215 | spin_lock_irqsave(&host->lock, flags); |
1144 | 1216 | ||
1145 | if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { | 1217 | if (!(sdhci_readl(host, SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) { |
1146 | if (host->mrq) { | 1218 | if (host->mrq) { |
1147 | printk(KERN_ERR "%s: Card removed during transfer!\n", | 1219 | printk(KERN_ERR "%s: Card removed during transfer!\n", |
1148 | mmc_hostname(host->mmc)); | 1220 | mmc_hostname(host->mmc)); |
@@ -1346,8 +1418,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | |||
1346 | * we need to at least restart the transfer. | 1418 | * we need to at least restart the transfer. |
1347 | */ | 1419 | */ |
1348 | if (intmask & SDHCI_INT_DMA_END) | 1420 | if (intmask & SDHCI_INT_DMA_END) |
1349 | writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS), | 1421 | sdhci_writel(host, sdhci_readl(host, SDHCI_DMA_ADDRESS), |
1350 | host->ioaddr + SDHCI_DMA_ADDRESS); | 1422 | SDHCI_DMA_ADDRESS); |
1351 | 1423 | ||
1352 | if (intmask & SDHCI_INT_DATA_END) { | 1424 | if (intmask & SDHCI_INT_DATA_END) { |
1353 | if (host->cmd) { | 1425 | if (host->cmd) { |
@@ -1373,7 +1445,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) | |||
1373 | 1445 | ||
1374 | spin_lock(&host->lock); | 1446 | spin_lock(&host->lock); |
1375 | 1447 | ||
1376 | intmask = readl(host->ioaddr + SDHCI_INT_STATUS); | 1448 | intmask = sdhci_readl(host, SDHCI_INT_STATUS); |
1377 | 1449 | ||
1378 | if (!intmask || intmask == 0xffffffff) { | 1450 | if (!intmask || intmask == 0xffffffff) { |
1379 | result = IRQ_NONE; | 1451 | result = IRQ_NONE; |
@@ -1384,22 +1456,22 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) | |||
1384 | mmc_hostname(host->mmc), intmask); | 1456 | mmc_hostname(host->mmc), intmask); |
1385 | 1457 | ||
1386 | if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { | 1458 | if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) { |
1387 | writel(intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE), | 1459 | sdhci_writel(host, intmask & (SDHCI_INT_CARD_INSERT | |
1388 | host->ioaddr + SDHCI_INT_STATUS); | 1460 | SDHCI_INT_CARD_REMOVE), SDHCI_INT_STATUS); |
1389 | tasklet_schedule(&host->card_tasklet); | 1461 | tasklet_schedule(&host->card_tasklet); |
1390 | } | 1462 | } |
1391 | 1463 | ||
1392 | intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); | 1464 | intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE); |
1393 | 1465 | ||
1394 | if (intmask & SDHCI_INT_CMD_MASK) { | 1466 | if (intmask & SDHCI_INT_CMD_MASK) { |
1395 | writel(intmask & SDHCI_INT_CMD_MASK, | 1467 | sdhci_writel(host, intmask & SDHCI_INT_CMD_MASK, |
1396 | host->ioaddr + SDHCI_INT_STATUS); | 1468 | SDHCI_INT_STATUS); |
1397 | sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); | 1469 | sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK); |
1398 | } | 1470 | } |
1399 | 1471 | ||
1400 | if (intmask & SDHCI_INT_DATA_MASK) { | 1472 | if (intmask & SDHCI_INT_DATA_MASK) { |
1401 | writel(intmask & SDHCI_INT_DATA_MASK, | 1473 | sdhci_writel(host, intmask & SDHCI_INT_DATA_MASK, |
1402 | host->ioaddr + SDHCI_INT_STATUS); | 1474 | SDHCI_INT_STATUS); |
1403 | sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); | 1475 | sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK); |
1404 | } | 1476 | } |
1405 | 1477 | ||
@@ -1410,7 +1482,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) | |||
1410 | if (intmask & SDHCI_INT_BUS_POWER) { | 1482 | if (intmask & SDHCI_INT_BUS_POWER) { |
1411 | printk(KERN_ERR "%s: Card is consuming too much power!\n", | 1483 | printk(KERN_ERR "%s: Card is consuming too much power!\n", |
1412 | mmc_hostname(host->mmc)); | 1484 | mmc_hostname(host->mmc)); |
1413 | writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS); | 1485 | sdhci_writel(host, SDHCI_INT_BUS_POWER, SDHCI_INT_STATUS); |
1414 | } | 1486 | } |
1415 | 1487 | ||
1416 | intmask &= ~SDHCI_INT_BUS_POWER; | 1488 | intmask &= ~SDHCI_INT_BUS_POWER; |
@@ -1425,7 +1497,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id) | |||
1425 | mmc_hostname(host->mmc), intmask); | 1497 | mmc_hostname(host->mmc), intmask); |
1426 | sdhci_dumpregs(host); | 1498 | sdhci_dumpregs(host); |
1427 | 1499 | ||
1428 | writel(intmask, host->ioaddr + SDHCI_INT_STATUS); | 1500 | sdhci_writel(host, intmask, SDHCI_INT_STATUS); |
1429 | } | 1501 | } |
1430 | 1502 | ||
1431 | result = IRQ_HANDLED; | 1503 | result = IRQ_HANDLED; |
@@ -1455,6 +1527,8 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) | |||
1455 | { | 1527 | { |
1456 | int ret; | 1528 | int ret; |
1457 | 1529 | ||
1530 | sdhci_disable_card_detection(host); | ||
1531 | |||
1458 | ret = mmc_suspend_host(host->mmc, state); | 1532 | ret = mmc_suspend_host(host->mmc, state); |
1459 | if (ret) | 1533 | if (ret) |
1460 | return ret; | 1534 | return ret; |
@@ -1487,6 +1561,8 @@ int sdhci_resume_host(struct sdhci_host *host) | |||
1487 | if (ret) | 1561 | if (ret) |
1488 | return ret; | 1562 | return ret; |
1489 | 1563 | ||
1564 | sdhci_enable_card_detection(host); | ||
1565 | |||
1490 | return 0; | 1566 | return 0; |
1491 | } | 1567 | } |
1492 | 1568 | ||
@@ -1537,7 +1613,7 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1537 | 1613 | ||
1538 | sdhci_reset(host, SDHCI_RESET_ALL); | 1614 | sdhci_reset(host, SDHCI_RESET_ALL); |
1539 | 1615 | ||
1540 | host->version = readw(host->ioaddr + SDHCI_HOST_VERSION); | 1616 | host->version = sdhci_readw(host, SDHCI_HOST_VERSION); |
1541 | host->version = (host->version & SDHCI_SPEC_VER_MASK) | 1617 | host->version = (host->version & SDHCI_SPEC_VER_MASK) |
1542 | >> SDHCI_SPEC_VER_SHIFT; | 1618 | >> SDHCI_SPEC_VER_SHIFT; |
1543 | if (host->version > SDHCI_SPEC_200) { | 1619 | if (host->version > SDHCI_SPEC_200) { |
@@ -1546,7 +1622,7 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1546 | host->version); | 1622 | host->version); |
1547 | } | 1623 | } |
1548 | 1624 | ||
1549 | caps = readl(host->ioaddr + SDHCI_CAPABILITIES); | 1625 | caps = sdhci_readl(host, SDHCI_CAPABILITIES); |
1550 | 1626 | ||
1551 | if (host->quirks & SDHCI_QUIRK_FORCE_DMA) | 1627 | if (host->quirks & SDHCI_QUIRK_FORCE_DMA) |
1552 | host->flags |= SDHCI_USE_DMA; | 1628 | host->flags |= SDHCI_USE_DMA; |
@@ -1614,19 +1690,27 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1614 | 1690 | ||
1615 | host->max_clk = | 1691 | host->max_clk = |
1616 | (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; | 1692 | (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; |
1693 | host->max_clk *= 1000000; | ||
1617 | if (host->max_clk == 0) { | 1694 | if (host->max_clk == 0) { |
1618 | printk(KERN_ERR "%s: Hardware doesn't specify base clock " | 1695 | if (!host->ops->get_max_clock) { |
1619 | "frequency.\n", mmc_hostname(mmc)); | 1696 | printk(KERN_ERR |
1620 | return -ENODEV; | 1697 | "%s: Hardware doesn't specify base clock " |
1698 | "frequency.\n", mmc_hostname(mmc)); | ||
1699 | return -ENODEV; | ||
1700 | } | ||
1701 | host->max_clk = host->ops->get_max_clock(host); | ||
1621 | } | 1702 | } |
1622 | host->max_clk *= 1000000; | ||
1623 | 1703 | ||
1624 | host->timeout_clk = | 1704 | host->timeout_clk = |
1625 | (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; | 1705 | (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; |
1626 | if (host->timeout_clk == 0) { | 1706 | if (host->timeout_clk == 0) { |
1627 | printk(KERN_ERR "%s: Hardware doesn't specify timeout clock " | 1707 | if (!host->ops->get_timeout_clock) { |
1628 | "frequency.\n", mmc_hostname(mmc)); | 1708 | printk(KERN_ERR |
1629 | return -ENODEV; | 1709 | "%s: Hardware doesn't specify timeout clock " |
1710 | "frequency.\n", mmc_hostname(mmc)); | ||
1711 | return -ENODEV; | ||
1712 | } | ||
1713 | host->timeout_clk = host->ops->get_timeout_clock(host); | ||
1630 | } | 1714 | } |
1631 | if (caps & SDHCI_TIMEOUT_CLK_UNIT) | 1715 | if (caps & SDHCI_TIMEOUT_CLK_UNIT) |
1632 | host->timeout_clk *= 1000; | 1716 | host->timeout_clk *= 1000; |
@@ -1642,6 +1726,9 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1642 | if (caps & SDHCI_CAN_DO_HISPD) | 1726 | if (caps & SDHCI_CAN_DO_HISPD) |
1643 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; | 1727 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; |
1644 | 1728 | ||
1729 | if (host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) | ||
1730 | mmc->caps |= MMC_CAP_NEEDS_POLL; | ||
1731 | |||
1645 | mmc->ocr_avail = 0; | 1732 | mmc->ocr_avail = 0; |
1646 | if (caps & SDHCI_CAN_VDD_330) | 1733 | if (caps & SDHCI_CAN_VDD_330) |
1647 | mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; | 1734 | mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; |
@@ -1690,13 +1777,19 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1690 | * Maximum block size. This varies from controller to controller and | 1777 | * Maximum block size. This varies from controller to controller and |
1691 | * is specified in the capabilities register. | 1778 | * is specified in the capabilities register. |
1692 | */ | 1779 | */ |
1693 | mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT; | 1780 | if (host->quirks & SDHCI_QUIRK_FORCE_BLK_SZ_2048) { |
1694 | if (mmc->max_blk_size >= 3) { | 1781 | mmc->max_blk_size = 2; |
1695 | printk(KERN_WARNING "%s: Invalid maximum block size, " | 1782 | } else { |
1696 | "assuming 512 bytes\n", mmc_hostname(mmc)); | 1783 | mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> |
1697 | mmc->max_blk_size = 512; | 1784 | SDHCI_MAX_BLOCK_SHIFT; |
1698 | } else | 1785 | if (mmc->max_blk_size >= 3) { |
1699 | mmc->max_blk_size = 512 << mmc->max_blk_size; | 1786 | printk(KERN_WARNING "%s: Invalid maximum block size, " |
1787 | "assuming 512 bytes\n", mmc_hostname(mmc)); | ||
1788 | mmc->max_blk_size = 0; | ||
1789 | } | ||
1790 | } | ||
1791 | |||
1792 | mmc->max_blk_size = 512 << mmc->max_blk_size; | ||
1700 | 1793 | ||
1701 | /* | 1794 | /* |
1702 | * Maximum block count. | 1795 | * Maximum block count. |
@@ -1746,6 +1839,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1746 | (host->flags & SDHCI_USE_ADMA)?"A":"", | 1839 | (host->flags & SDHCI_USE_ADMA)?"A":"", |
1747 | (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); | 1840 | (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); |
1748 | 1841 | ||
1842 | sdhci_enable_card_detection(host); | ||
1843 | |||
1749 | return 0; | 1844 | return 0; |
1750 | 1845 | ||
1751 | #ifdef SDHCI_USE_LEDS_CLASS | 1846 | #ifdef SDHCI_USE_LEDS_CLASS |
@@ -1782,6 +1877,8 @@ void sdhci_remove_host(struct sdhci_host *host, int dead) | |||
1782 | spin_unlock_irqrestore(&host->lock, flags); | 1877 | spin_unlock_irqrestore(&host->lock, flags); |
1783 | } | 1878 | } |
1784 | 1879 | ||
1880 | sdhci_disable_card_detection(host); | ||
1881 | |||
1785 | mmc_remove_host(host->mmc); | 1882 | mmc_remove_host(host->mmc); |
1786 | 1883 | ||
1787 | #ifdef SDHCI_USE_LEDS_CLASS | 1884 | #ifdef SDHCI_USE_LEDS_CLASS |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 43c37c68d07a..f20a834f4309 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -10,6 +10,9 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/scatterlist.h> | 12 | #include <linux/scatterlist.h> |
13 | #include <linux/compiler.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/io.h> | ||
13 | 16 | ||
14 | /* | 17 | /* |
15 | * Controller registers | 18 | * Controller registers |
@@ -123,6 +126,7 @@ | |||
123 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ | 126 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ |
124 | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ | 127 | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ |
125 | SDHCI_INT_DATA_END_BIT) | 128 | SDHCI_INT_DATA_END_BIT) |
129 | #define SDHCI_INT_ALL_MASK ((unsigned int)-1) | ||
126 | 130 | ||
127 | #define SDHCI_ACMD12_ERR 0x3C | 131 | #define SDHCI_ACMD12_ERR 0x3C |
128 | 132 | ||
@@ -210,6 +214,18 @@ struct sdhci_host { | |||
210 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) | 214 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) |
211 | /* Controller does not provide transfer-complete interrupt when not busy */ | 215 | /* Controller does not provide transfer-complete interrupt when not busy */ |
212 | #define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14) | 216 | #define SDHCI_QUIRK_NO_BUSY_IRQ (1<<14) |
217 | /* Controller has unreliable card detection */ | ||
218 | #define SDHCI_QUIRK_BROKEN_CARD_DETECTION (1<<15) | ||
219 | /* Controller reports inverted write-protect state */ | ||
220 | #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT (1<<16) | ||
221 | /* Controller has nonstandard clock management */ | ||
222 | #define SDHCI_QUIRK_NONSTANDARD_CLOCK (1<<17) | ||
223 | /* Controller does not like fast PIO transfers */ | ||
224 | #define SDHCI_QUIRK_PIO_NEEDS_DELAY (1<<18) | ||
225 | /* Controller losing signal/interrupt enable states after reset */ | ||
226 | #define SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET (1<<19) | ||
227 | /* Controller has to be forced to use block size of 2048 bytes */ | ||
228 | #define SDHCI_QUIRK_FORCE_BLK_SZ_2048 (1<<20) | ||
213 | 229 | ||
214 | int irq; /* Device IRQ */ | 230 | int irq; /* Device IRQ */ |
215 | void __iomem * ioaddr; /* Mapped address */ | 231 | void __iomem * ioaddr; /* Mapped address */ |
@@ -267,9 +283,105 @@ struct sdhci_host { | |||
267 | 283 | ||
268 | 284 | ||
269 | struct sdhci_ops { | 285 | struct sdhci_ops { |
286 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS | ||
287 | u32 (*readl)(struct sdhci_host *host, int reg); | ||
288 | u16 (*readw)(struct sdhci_host *host, int reg); | ||
289 | u8 (*readb)(struct sdhci_host *host, int reg); | ||
290 | void (*writel)(struct sdhci_host *host, u32 val, int reg); | ||
291 | void (*writew)(struct sdhci_host *host, u16 val, int reg); | ||
292 | void (*writeb)(struct sdhci_host *host, u8 val, int reg); | ||
293 | #endif | ||
294 | |||
295 | void (*set_clock)(struct sdhci_host *host, unsigned int clock); | ||
296 | |||
270 | int (*enable_dma)(struct sdhci_host *host); | 297 | int (*enable_dma)(struct sdhci_host *host); |
298 | unsigned int (*get_max_clock)(struct sdhci_host *host); | ||
299 | unsigned int (*get_timeout_clock)(struct sdhci_host *host); | ||
271 | }; | 300 | }; |
272 | 301 | ||
302 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS | ||
303 | |||
304 | static inline void sdhci_writel(struct sdhci_host *host, u32 val, int reg) | ||
305 | { | ||
306 | if (unlikely(host->ops->writel)) | ||
307 | host->ops->writel(host, val, reg); | ||
308 | else | ||
309 | writel(val, host->ioaddr + reg); | ||
310 | } | ||
311 | |||
312 | static inline void sdhci_writew(struct sdhci_host *host, u16 val, int reg) | ||
313 | { | ||
314 | if (unlikely(host->ops->writew)) | ||
315 | host->ops->writew(host, val, reg); | ||
316 | else | ||
317 | writew(val, host->ioaddr + reg); | ||
318 | } | ||
319 | |||
320 | static inline void sdhci_writeb(struct sdhci_host *host, u8 val, int reg) | ||
321 | { | ||
322 | if (unlikely(host->ops->writeb)) | ||
323 | host->ops->writeb(host, val, reg); | ||
324 | else | ||
325 | writeb(val, host->ioaddr + reg); | ||
326 | } | ||
327 | |||
328 | static inline u32 sdhci_readl(struct sdhci_host *host, int reg) | ||
329 | { | ||
330 | if (unlikely(host->ops->readl)) | ||
331 | return host->ops->readl(host, reg); | ||
332 | else | ||
333 | return readl(host->ioaddr + reg); | ||
334 | } | ||
335 | |||
336 | static inline u16 sdhci_readw(struct sdhci_host *host, int reg) | ||
337 | { | ||
338 | if (unlikely(host->ops->readw)) | ||
339 | return host->ops->readw(host, reg); | ||
340 | else | ||
341 | return readw(host->ioaddr + reg); | ||
342 | } | ||
343 | |||
344 | static inline u8 sdhci_readb(struct sdhci_host *host, int reg) | ||
345 | { | ||
346 | if (unlikely(host->ops->readb)) | ||
347 | return host->ops->readb(host, reg); | ||
348 | else | ||
349 | return readb(host->ioaddr + reg); | ||
350 | } | ||
351 | |||
352 | #else | ||
353 | |||
354 | static inline void sdhci_writel(struct sdhci_host *host, u32 val, int reg) | ||
355 | { | ||
356 | writel(val, host->ioaddr + reg); | ||
357 | } | ||
358 | |||
359 | static inline void sdhci_writew(struct sdhci_host *host, u16 val, int reg) | ||
360 | { | ||
361 | writew(val, host->ioaddr + reg); | ||
362 | } | ||
363 | |||
364 | static inline void sdhci_writeb(struct sdhci_host *host, u8 val, int reg) | ||
365 | { | ||
366 | writeb(val, host->ioaddr + reg); | ||
367 | } | ||
368 | |||
369 | static inline u32 sdhci_readl(struct sdhci_host *host, int reg) | ||
370 | { | ||
371 | return readl(host->ioaddr + reg); | ||
372 | } | ||
373 | |||
374 | static inline u16 sdhci_readw(struct sdhci_host *host, int reg) | ||
375 | { | ||
376 | return readw(host->ioaddr + reg); | ||
377 | } | ||
378 | |||
379 | static inline u8 sdhci_readb(struct sdhci_host *host, int reg) | ||
380 | { | ||
381 | return readb(host->ioaddr + reg); | ||
382 | } | ||
383 | |||
384 | #endif /* CONFIG_MMC_SDHCI_IO_ACCESSORS */ | ||
273 | 385 | ||
274 | extern struct sdhci_host *sdhci_alloc_host(struct device *dev, | 386 | extern struct sdhci_host *sdhci_alloc_host(struct device *dev, |
275 | size_t priv_size); | 387 | size_t priv_size); |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 6a7a61904833..63fbd5b7d312 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
@@ -568,11 +568,11 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) | |||
568 | host->mmc = mmc; | 568 | host->mmc = mmc; |
569 | platform_set_drvdata(dev, mmc); | 569 | platform_set_drvdata(dev, mmc); |
570 | 570 | ||
571 | host->ctl = ioremap(res_ctl->start, res_ctl->end - res_ctl->start); | 571 | host->ctl = ioremap(res_ctl->start, resource_size(res_ctl)); |
572 | if (!host->ctl) | 572 | if (!host->ctl) |
573 | goto host_free; | 573 | goto host_free; |
574 | 574 | ||
575 | host->cnf = ioremap(res_cnf->start, res_cnf->end - res_cnf->start); | 575 | host->cnf = ioremap(res_cnf->start, resource_size(res_cnf)); |
576 | if (!host->cnf) | 576 | if (!host->cnf) |
577 | goto unmap_ctl; | 577 | goto unmap_ctl; |
578 | 578 | ||
@@ -650,10 +650,10 @@ static int __devexit tmio_mmc_remove(struct platform_device *dev) | |||
650 | if (mmc) { | 650 | if (mmc) { |
651 | struct tmio_mmc_host *host = mmc_priv(mmc); | 651 | struct tmio_mmc_host *host = mmc_priv(mmc); |
652 | mmc_remove_host(mmc); | 652 | mmc_remove_host(mmc); |
653 | mmc_free_host(mmc); | ||
654 | free_irq(host->irq, host); | 653 | free_irq(host->irq, host); |
655 | iounmap(host->ctl); | 654 | iounmap(host->ctl); |
656 | iounmap(host->cnf); | 655 | iounmap(host->cnf); |
656 | mmc_free_host(mmc); | ||
657 | } | 657 | } |
658 | 658 | ||
659 | return 0; | 659 | return 0; |
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index ba2b4240a86a..9c831ab2ece6 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h | |||
@@ -8,6 +8,9 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | * | 9 | * |
10 | */ | 10 | */ |
11 | |||
12 | #include <linux/highmem.h> | ||
13 | |||
11 | #define CNF_CMD 0x04 | 14 | #define CNF_CMD 0x04 |
12 | #define CNF_CTL_BASE 0x10 | 15 | #define CNF_CTL_BASE 0x10 |
13 | #define CNF_INT_PIN 0x3d | 16 | #define CNF_INT_PIN 0x3d |