diff options
author | Benn Pörscke <benn.porscke@stericsson.com> | 2011-10-07 15:31:57 +0200 |
---|---|---|
committer | Benn Pörscke <benn.porscke@stericsson.com> | 2011-10-07 15:31:57 +0200 |
commit | 47a4dbf83a75014d6b3467be18997894f1c617db (patch) | |
tree | 7f5d116db48205309fbc4ae0954f20ab8a651e46 /drivers/mmc | |
parent | ea8a52f9f4bcc3420c38ae07f8378a2f18443970 (diff) |
Squashandroid-20111012
Change-Id: If0ae9fa8067740ab2ede33703c79ec134f204a5e
Diffstat (limited to 'drivers/mmc')
38 files changed, 2142 insertions, 527 deletions
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig index 3f2a912659a..cc9d7e77c25 100644 --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig @@ -14,6 +14,23 @@ config MMC_BLOCK mount the filesystem. Almost everyone wishing MMC support should say Y or M here. +config MMC_BLOCK_MINORS + int "Number of minors per block device" + range 4 256 + default 8 + help + Number of minors per block device. One is needed for every + partition on the disk (plus one for the whole disk). + + Number of total MMC minors available is 256, so your number + of supported block devices will be limited to 256 divided + by this number. + + Default is 8 to be backwards compatible with previous + hardwired device numbering. + + If unsure, say 8 here. + config MMC_BLOCK_BOUNCE bool "Use bounce buffer for simple hosts" depends on MMC_BLOCK @@ -32,6 +49,15 @@ config MMC_BLOCK_BOUNCE If unsure, say Y here. +config MMC_BLOCK_DEFERRED_RESUME + bool "Deferr MMC layer resume until I/O is requested" + depends on MMC_BLOCK + default n + help + Say Y here to enable deferred MMC resume until I/O + is requested. This will reduce overall resume latency and + save power when theres an SD card inserted but not being used. + config SDIO_UART tristate "SDIO UART/GPS class support" help diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index cb9fbc83b09..ed17a3d1499 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -43,14 +43,27 @@ #include "queue.h" MODULE_ALIAS("mmc:block"); +#ifdef MODULE_PARAM_PREFIX +#undef MODULE_PARAM_PREFIX +#endif +#define MODULE_PARAM_PREFIX "mmcblk." + +static DEFINE_MUTEX(block_mutex); /* - * max 8 partitions per card + * The defaults come from config options but can be overriden by module + * or bootarg options. */ -#define MMC_SHIFT 3 -#define MMC_NUM_MINORS (256 >> MMC_SHIFT) +static int perdev_minors = CONFIG_MMC_BLOCK_MINORS; -static DECLARE_BITMAP(dev_use, MMC_NUM_MINORS); +/* + * We've only got one major, so number of mmcblk devices is + * limited to 256 / number of minors per device. + */ +static int max_devices; + +/* 256 minors, so at most 256 separate devices */ +static DECLARE_BITMAP(dev_use, 256); /* * There is one mmc_blk_data per slot. @@ -66,6 +79,9 @@ struct mmc_blk_data { static DEFINE_MUTEX(open_lock); +module_param(perdev_minors, int, 0444); +MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device"); + static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk) { struct mmc_blk_data *md; @@ -87,10 +103,10 @@ static void mmc_blk_put(struct mmc_blk_data *md) md->usage--; if (md->usage == 0) { int devmaj = MAJOR(disk_devt(md->disk)); - int devidx = MINOR(disk_devt(md->disk)) >> MMC_SHIFT; + int devidx = MINOR(disk_devt(md->disk)) / perdev_minors; if (!devmaj) - devidx = md->disk->first_minor >> MMC_SHIFT; + devidx = md->disk->first_minor / perdev_minors; blk_cleanup_queue(md->queue.queue); @@ -242,6 +258,24 @@ static u32 get_card_status(struct mmc_card *card, struct request *req) return cmd.resp[0]; } +static int +mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) +{ + int err; + + mmc_claim_host(card->host); + err = mmc_set_blocklen(card, 512); + mmc_release_host(card->host); + + if (err) { + printk(KERN_ERR "%s: unable to set block size to 512: %d\n", + md->disk->disk_name, err); + return -EINVAL; + } + + return 0; +} + static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) { struct mmc_blk_data *md = mq->data; @@ -249,6 +283,13 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) struct mmc_blk_request brq; int ret = 1, disable_multi = 0; +#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME + if (mmc_bus_needs_resume(card->host)) { + mmc_resume_bus(card->host); + mmc_blk_set_blksize(md, card); + } +#endif + mmc_claim_host(card->host); do { @@ -299,7 +340,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) readcmd = MMC_READ_SINGLE_BLOCK; writecmd = MMC_WRITE_BLOCK; } - if (rq_data_dir(req) == READ) { brq.cmd.opcode = readcmd; brq.data.flags |= MMC_DATA_READ; @@ -352,6 +392,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) continue; } status = get_card_status(card, req); + } else if (disable_multi == 1) { + disable_multi = 0; } if (brq.cmd.error) { @@ -482,8 +524,8 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) struct mmc_blk_data *md; int devidx, ret; - devidx = find_first_zero_bit(dev_use, MMC_NUM_MINORS); - if (devidx >= MMC_NUM_MINORS) + devidx = find_first_zero_bit(dev_use, max_devices); + if (devidx >= max_devices) return ERR_PTR(-ENOSPC); __set_bit(devidx, dev_use); @@ -500,7 +542,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) */ md->read_only = mmc_blk_readonly(card); - md->disk = alloc_disk(1 << MMC_SHIFT); + md->disk = alloc_disk(perdev_minors); if (md->disk == NULL) { ret = -ENOMEM; goto err_kfree; @@ -517,11 +559,12 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) md->queue.data = md; md->disk->major = MMC_BLOCK_MAJOR; - md->disk->first_minor = devidx << MMC_SHIFT; + md->disk->first_minor = devidx * perdev_minors; md->disk->fops = &mmc_bdops; md->disk->private_data = md; md->disk->queue = md->queue.queue; md->disk->driverfs_dev = &card->dev; + md->disk->flags = GENHD_FL_EXT_DEVT; /* * As discussed on lkml, GENHD_FL_REMOVABLE should: @@ -563,37 +606,10 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) return ERR_PTR(ret); } -static int -mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) -{ - struct mmc_command cmd; - int err; - - /* Block-addressed cards ignore MMC_SET_BLOCKLEN. */ - if (mmc_card_blockaddr(card)) - return 0; - - mmc_claim_host(card->host); - cmd.opcode = MMC_SET_BLOCKLEN; - cmd.arg = 512; - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; - err = mmc_wait_for_cmd(card->host, &cmd, 5); - mmc_release_host(card->host); - - if (err) { - printk(KERN_ERR "%s: unable to set block size to %d: %d\n", - md->disk->disk_name, cmd.arg, err); - return -EINVAL; - } - - return 0; -} - static int mmc_blk_probe(struct mmc_card *card) { struct mmc_blk_data *md; int err; - char cap_str[10]; /* @@ -617,6 +633,9 @@ static int mmc_blk_probe(struct mmc_card *card) cap_str, md->read_only ? "(ro)" : ""); mmc_set_drvdata(card, md); +#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME + mmc_set_bus_resume_policy(card->host, 1); +#endif add_disk(md->disk); return 0; @@ -641,6 +660,9 @@ static void mmc_blk_remove(struct mmc_card *card) mmc_blk_put(md); } mmc_set_drvdata(card, NULL); +#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME + mmc_set_bus_resume_policy(card->host, 0); +#endif } #ifdef CONFIG_PM @@ -659,7 +681,9 @@ static int mmc_blk_resume(struct mmc_card *card) struct mmc_blk_data *md = mmc_get_drvdata(card); if (md) { +#ifndef CONFIG_MMC_BLOCK_DEFERRED_RESUME mmc_blk_set_blksize(md, card); +#endif mmc_queue_resume(&md->queue); } return 0; @@ -683,6 +707,11 @@ static int __init mmc_blk_init(void) { int res; + if (perdev_minors != CONFIG_MMC_BLOCK_MINORS) + pr_info("mmcblk: using %d minors per device\n", perdev_minors); + + max_devices = 256 / perdev_minors; + res = register_blkdev(MMC_BLOCK_MAJOR, "mmc"); if (res) goto out; diff --git a/drivers/mmc/card/mmc_test.c b/drivers/mmc/card/mmc_test.c index 445d7db2277..785b4822a0a 100644 --- a/drivers/mmc/card/mmc_test.c +++ b/drivers/mmc/card/mmc_test.c @@ -44,17 +44,7 @@ struct mmc_test_card { */ static int mmc_test_set_blksize(struct mmc_test_card *test, unsigned size) { - struct mmc_command cmd; - int ret; - - cmd.opcode = MMC_SET_BLOCKLEN; - cmd.arg = size; - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - ret = mmc_wait_for_cmd(test->card->host, &cmd, 0); - if (ret) - return ret; - - return 0; + return mmc_set_blocklen(test->card, size); } /* diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index d6ded247d94..bd7da55cce4 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -132,7 +132,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mq->queue); #ifdef CONFIG_MMC_BLOCK_BOUNCE - if (host->max_hw_segs == 1) { + if (host->max_segs == 1) { unsigned int bouncesz; bouncesz = MMC_QUEUE_BOUNCESZ; @@ -182,16 +182,16 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock blk_queue_bounce_limit(mq->queue, limit); blk_queue_max_hw_sectors(mq->queue, min(host->max_blk_count, host->max_req_size / 512)); - blk_queue_max_segments(mq->queue, host->max_hw_segs); + blk_queue_max_segments(mq->queue, host->max_segs); blk_queue_max_segment_size(mq->queue, host->max_seg_size); mq->sg = kmalloc(sizeof(struct scatterlist) * - host->max_phys_segs, GFP_KERNEL); + host->max_segs, GFP_KERNEL); if (!mq->sg) { ret = -ENOMEM; goto cleanup_queue; } - sg_init_table(mq->sg, host->max_phys_segs); + sg_init_table(mq->sg, host->max_segs); } init_MUTEX(&mq->thread_sem); diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index bb22ffd76ef..0eba6658233 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig @@ -16,3 +16,20 @@ config MMC_UNSAFE_RESUME This option sets a default which can be overridden by the module parameter "removable=0" or "removable=1". + +config MMC_EMBEDDED_SDIO + boolean "MMC embedded SDIO device support (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + If you say Y here, support will be added for embedded SDIO + devices which do not contain the necessary enumeration + support in hardware to be properly detected. + +config MMC_PARANOID_SD_INIT + bool "Enable paranoid SD card initialization (EXPERIMENTAL)" + depends on EXPERIMENTAL + help + If you say Y here, the MMC layer will be extra paranoid + about re-trying SD init requests. This can be a useful + work-around for buggy controllers and hardware. Enable + if you are experiencing issues with SD detection. diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index 49d9dcaeca4..58adef173ba 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c @@ -245,14 +245,16 @@ int mmc_add_card(struct mmc_card *card) } if (mmc_host_is_spi(card->host)) { - printk(KERN_INFO "%s: new %s%s card on SPI\n", + printk(KERN_INFO "%s: new %s%s%s card on SPI\n", mmc_hostname(card->host), mmc_card_highspeed(card) ? "high speed " : "", + mmc_card_ddr_mode(card) ? "DDR " : "", type); } else { - printk(KERN_INFO "%s: new %s%s card at address %04x\n", + printk(KERN_INFO "%s: new %s%s%s card at address %04x\n", mmc_hostname(card->host), mmc_card_highspeed(card) ? "high speed " : "", + mmc_card_ddr_mode(card) ? "DDR " : "", type, card->rca); } diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 83e7543b55d..221e0e76384 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -22,6 +22,7 @@ #include <linux/scatterlist.h> #include <linux/log2.h> #include <linux/regulator/consumer.h> +#include <linux/wakelock.h> #include <linux/mmc/card.h> #include <linux/mmc/host.h> @@ -386,6 +387,8 @@ int mmc_host_enable(struct mmc_host *host) if (host->ops->enable) { int err; + wake_lock(&host->wakelock); + host->en_dis_recurs = 1; err = host->ops->enable(host); host->en_dis_recurs = 0; @@ -393,6 +396,7 @@ int mmc_host_enable(struct mmc_host *host) if (err) { pr_debug("%s: enable error %d\n", mmc_hostname(host), err); + wake_unlock(&host->wakelock); return err; } } @@ -420,6 +424,8 @@ static int mmc_host_do_disable(struct mmc_host *host, int lazy) mmc_schedule_delayed_work(&host->disable, delay); } + if (err == 0) + wake_unlock(&host->wakelock); } host->enabled = 0; return 0; @@ -522,7 +528,7 @@ int mmc_try_claim_host(struct mmc_host *host) } EXPORT_SYMBOL(mmc_try_claim_host); -static void mmc_do_release_host(struct mmc_host *host) +void mmc_do_release_host(struct mmc_host *host) { unsigned long flags; @@ -537,6 +543,7 @@ static void mmc_do_release_host(struct mmc_host *host) wake_up(&host->wq); } } +EXPORT_SYMBOL(mmc_do_release_host); void mmc_host_deeper_disable(struct work_struct *work) { @@ -650,14 +657,24 @@ void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode) } /* - * Change data bus width of a host. + * Change data bus width and DDR mode of a host. */ -void mmc_set_bus_width(struct mmc_host *host, unsigned int width) +void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, + unsigned int ddr) { host->ios.bus_width = width; + host->ios.ddr = ddr; mmc_set_ios(host); } +/* + * Change data bus width of a host. + */ +void mmc_set_bus_width(struct mmc_host *host, unsigned int width) +{ + mmc_set_bus_width_ddr(host, width, MMC_SDR_MODE); +} + /** * mmc_vdd_to_ocrbitnum - Convert a voltage to the OCR bit number * @vdd: voltage (mV) @@ -771,8 +788,9 @@ EXPORT_SYMBOL(mmc_regulator_get_ocrmask); /** * mmc_regulator_set_ocr - set regulator to match host->ios voltage - * @vdd_bit: zero for power off, else a bit number (host->ios.vdd) + * @mmc: the host to regulate * @supply: regulator to use + * @vdd_bit: zero for power off, else a bit number (host->ios.vdd) * * Returns zero on success, else negative errno. * @@ -780,15 +798,12 @@ EXPORT_SYMBOL(mmc_regulator_get_ocrmask); * a particular supply voltage. This would normally be called from the * set_ios() method. */ -int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit) +int mmc_regulator_set_ocr(struct mmc_host *mmc, + struct regulator *supply, + unsigned short vdd_bit) { int result = 0; int min_uV, max_uV; - int enabled; - - enabled = regulator_is_enabled(supply); - if (enabled < 0) - return enabled; if (vdd_bit) { int tmp; @@ -819,17 +834,25 @@ int mmc_regulator_set_ocr(struct regulator *supply, unsigned short vdd_bit) else result = 0; - if (result == 0 && !enabled) + if (result == 0 && !mmc->regulator_enabled) { result = regulator_enable(supply); - } else if (enabled) { + if (!result) + mmc->regulator_enabled = true; + } + } else if (mmc->regulator_enabled) { result = regulator_disable(supply); + if (result == 0) + mmc->regulator_enabled = false; } + if (result) + dev_err(mmc_dev(mmc), + "could not set regulator OCR (%d)\n", result); return result; } EXPORT_SYMBOL(mmc_regulator_set_ocr); -#endif +#endif /* CONFIG_REGULATOR */ /* * Mask off any voltages we don't support and select @@ -907,12 +930,7 @@ static void mmc_power_up(struct mmc_host *host) */ mmc_delay(10); - if (host->f_min > 400000) { - pr_warning("%s: Minimum clock frequency too high for " - "identification mode\n", mmc_hostname(host)); - host->ios.clock = host->f_min; - } else - host->ios.clock = 400000; + host->ios.clock = host->f_min; host->ios.power_mode = MMC_POWER_ON; mmc_set_ios(host); @@ -928,6 +946,13 @@ static void mmc_power_off(struct mmc_host *host) { host->ios.clock = 0; host->ios.vdd = 0; + + /* + * Reset ocr mask to be the highest possible voltage supported for + * this mmc host. This value will be used at next power up. + */ + host->ocr = 1 << (fls(host->ocr_avail) - 1); + if (!mmc_host_is_spi(host)) { host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; host->ios.chip_select = MMC_CS_DONTCARE; @@ -977,6 +1002,36 @@ static inline void mmc_bus_put(struct mmc_host *host) spin_unlock_irqrestore(&host->lock, flags); } +int mmc_resume_bus(struct mmc_host *host) +{ + unsigned long flags; + + if (!mmc_bus_needs_resume(host)) + return -EINVAL; + + printk("%s: Starting deferred resume\n", mmc_hostname(host)); + spin_lock_irqsave(&host->lock, flags); + host->bus_resume_flags &= ~MMC_BUSRESUME_NEEDS_RESUME; + host->rescan_disable = 0; + spin_unlock_irqrestore(&host->lock, flags); + + mmc_bus_get(host); + if (host->bus_ops && !host->bus_dead) { + mmc_power_up(host); + BUG_ON(!host->bus_ops->resume); + host->bus_ops->resume(host); + } + + if (host->bus_ops->detect && !host->bus_dead) + host->bus_ops->detect(host); + + mmc_bus_put(host); + printk("%s: Deferred resume completed\n", mmc_hostname(host)); + return 0; +} + +EXPORT_SYMBOL(mmc_resume_bus); + /* * Assign a mmc bus handler to a host. Only one bus handler may control a * host at any given time. @@ -1050,6 +1105,20 @@ void mmc_detect_change(struct mmc_host *host, unsigned long delay) EXPORT_SYMBOL(mmc_detect_change); +int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) +{ + struct mmc_command cmd; + + if (mmc_card_blockaddr(card) || mmc_card_ddr_mode(card)) + return 0; + + memset(&cmd, 0, sizeof(struct mmc_command)); + cmd.opcode = MMC_SET_BLOCKLEN; + cmd.arg = blocklen; + cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; + return mmc_wait_for_cmd(card->host, &cmd, 5); +} +EXPORT_SYMBOL(mmc_set_blocklen); void mmc_rescan(struct work_struct *work) { @@ -1058,6 +1127,7 @@ void mmc_rescan(struct work_struct *work) u32 ocr; int err; unsigned long flags; + int extend_wakelock = 0; spin_lock_irqsave(&host->lock, flags); @@ -1075,6 +1145,12 @@ void mmc_rescan(struct work_struct *work) if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) host->bus_ops->detect(host); + /* If the card was removed the bus will be marked + * as dead - extend the wakelock so userspace + * can respond */ + if (host->bus_dead) + extend_wakelock = 1; + mmc_bus_put(host); @@ -1112,6 +1188,7 @@ void mmc_rescan(struct work_struct *work) if (!err) { if (mmc_attach_sdio(host, ocr)) mmc_power_off(host); + extend_wakelock = 1; goto out; } @@ -1122,6 +1199,7 @@ void mmc_rescan(struct work_struct *work) if (!err) { if (mmc_attach_sd(host, ocr)) mmc_power_off(host); + extend_wakelock = 1; goto out; } @@ -1132,6 +1210,7 @@ void mmc_rescan(struct work_struct *work) if (!err) { if (mmc_attach_mmc(host, ocr)) mmc_power_off(host); + extend_wakelock = 1; goto out; } @@ -1139,6 +1218,9 @@ void mmc_rescan(struct work_struct *work) mmc_power_off(host); out: + if (extend_wakelock) + wake_lock_timeout(&host->wakelock, HZ / 2); + if (host->caps & MMC_CAP_NEEDS_POLL) mmc_schedule_delayed_work(&host->detect, HZ); } @@ -1268,6 +1350,9 @@ int mmc_suspend_host(struct mmc_host *host) { int err = 0; + if (mmc_bus_needs_resume(host)) + return 0; + if (host->caps & MMC_CAP_DISABLE) cancel_delayed_work(&host->disable); cancel_delayed_work(&host->detect); @@ -1275,7 +1360,8 @@ int mmc_suspend_host(struct mmc_host *host) mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { - if (host->bus_ops->suspend) + if (host->bus_ops->suspend && + (host->bus_resume_flags & MMC_NEEDS_UNSAFE_RESUME)) err = host->bus_ops->suspend(host); } mmc_bus_put(host); @@ -1297,6 +1383,12 @@ int mmc_resume_host(struct mmc_host *host) int err = 0; mmc_bus_get(host); + if (mmc_bus_manual_resume(host)) { + host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME; + mmc_bus_put(host); + return 0; + } + if (host->bus_ops && !host->bus_dead) { if (!(host->pm_flags & MMC_PM_KEEP_POWER)) { mmc_power_up(host); @@ -1334,6 +1426,10 @@ int mmc_pm_notify(struct notifier_block *notify_block, case PM_SUSPEND_PREPARE: spin_lock_irqsave(&host->lock, flags); + if (mmc_bus_needs_resume(host)) { + spin_unlock_irqrestore(&host->lock, flags); + break; + } host->rescan_disable = 1; spin_unlock_irqrestore(&host->lock, flags); cancel_delayed_work_sync(&host->detect); @@ -1355,6 +1451,10 @@ int mmc_pm_notify(struct notifier_block *notify_block, case PM_POST_HIBERNATION: spin_lock_irqsave(&host->lock, flags); + if (mmc_bus_manual_resume(host)) { + spin_unlock_irqrestore(&host->lock, flags); + break; + } host->rescan_disable = 0; spin_unlock_irqrestore(&host->lock, flags); mmc_detect_change(host, 0); @@ -1365,6 +1465,22 @@ int mmc_pm_notify(struct notifier_block *notify_block, } #endif +#ifdef CONFIG_MMC_EMBEDDED_SDIO +void mmc_set_embedded_sdio_data(struct mmc_host *host, + struct sdio_cis *cis, + struct sdio_cccr *cccr, + struct sdio_embedded_func *funcs, + int num_funcs) +{ + host->embedded_sdio_data.cis = cis; + host->embedded_sdio_data.cccr = cccr; + host->embedded_sdio_data.funcs = funcs; + host->embedded_sdio_data.num_funcs = num_funcs; +} + +EXPORT_SYMBOL(mmc_set_embedded_sdio_data); +#endif + static int __init mmc_init(void) { int ret; diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index a811c52a165..eccd0f4e52c 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -33,6 +33,8 @@ void mmc_set_chip_select(struct mmc_host *host, int mode); void mmc_set_clock(struct mmc_host *host, unsigned int hz); void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); void mmc_set_bus_width(struct mmc_host *host, unsigned int width); +void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, + unsigned int ddr); u32 mmc_select_voltage(struct mmc_host *host, u32 ocr); void mmc_set_timing(struct mmc_host *host, unsigned int timing); diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index d80cfdc8edd..53351f29860 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -90,12 +90,15 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) host->pm_notify.notifier_call = mmc_pm_notify; #endif + snprintf(host->wakelock_name, sizeof(host->wakelock_name), + "mmc%d_delay_work", host->index); + wake_lock_init(&host->wakelock, WAKE_LOCK_SUSPEND, host->wakelock_name); + /* * By default, hosts do not support SGIO or large requests. * They have to set these according to their abilities. */ - host->max_hw_segs = 1; - host->max_phys_segs = 1; + host->max_segs = 1; host->max_seg_size = PAGE_CACHE_SIZE; host->max_req_size = PAGE_CACHE_SIZE; @@ -137,7 +140,8 @@ int mmc_add_host(struct mmc_host *host) #endif mmc_start_host(host); - register_pm_notifier(&host->pm_notify); + if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)) + register_pm_notifier(&host->pm_notify); return 0; } @@ -154,7 +158,9 @@ EXPORT_SYMBOL(mmc_add_host); */ void mmc_remove_host(struct mmc_host *host) { - unregister_pm_notifier(&host->pm_notify); + if (!(host->pm_flags & MMC_PM_IGNORE_PM_NOTIFY)) + unregister_pm_notifier(&host->pm_notify); + mmc_stop_host(host); #ifdef CONFIG_DEBUG_FS @@ -176,6 +182,7 @@ EXPORT_SYMBOL(mmc_remove_host); */ void mmc_free_host(struct mmc_host *host) { + wake_lock_destroy(&host->wakelock); spin_lock(&mmc_host_lock); idr_remove(&mmc_host_idr, host->index); spin_unlock(&mmc_host_lock); diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 89f7a25b7ac..eddba13ced0 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -114,17 +114,18 @@ static int mmc_decode_cid(struct mmc_card *card) static int mmc_decode_csd(struct mmc_card *card) { struct mmc_csd *csd = &card->csd; - unsigned int e, m, csd_struct; + unsigned int e, m; u32 *resp = card->raw_csd; /* * We only understand CSD structure v1.1 and v1.2. * v1.2 has extra information in bits 15, 11 and 10. + * We also support eMMC v4.4 & v4.41. */ - csd_struct = UNSTUFF_BITS(resp, 126, 2); - if (csd_struct != 1 && csd_struct != 2) { + csd->structure = UNSTUFF_BITS(resp, 126, 2); + if (csd->structure == 0) { printk(KERN_ERR "%s: unrecognised CSD structure version %d\n", - mmc_hostname(card->host), csd_struct); + mmc_hostname(card->host), csd->structure); return -EINVAL; } @@ -207,11 +208,22 @@ static int mmc_read_ext_csd(struct mmc_card *card) goto out; } + /* Version is coded in the CSD_STRUCTURE byte in the EXT_CSD register */ + if (card->csd.structure == 3) { + int ext_csd_struct = ext_csd[EXT_CSD_STRUCTURE]; + if (ext_csd_struct > 2) { + printk(KERN_ERR "%s: unrecognised EXT_CSD structure " + "version %d\n", mmc_hostname(card->host), + ext_csd_struct); + err = -EINVAL; + goto out; + } + } + card->ext_csd.rev = ext_csd[EXT_CSD_REV]; if (card->ext_csd.rev > 5) { - printk(KERN_ERR "%s: unrecognised EXT_CSD structure " - "version %d\n", mmc_hostname(card->host), - card->ext_csd.rev); + printk(KERN_ERR "%s: unrecognised EXT_CSD revision %d\n", + mmc_hostname(card->host), card->ext_csd.rev); err = -EINVAL; goto out; } @@ -222,11 +234,28 @@ static int mmc_read_ext_csd(struct mmc_card *card) ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | ext_csd[EXT_CSD_SEC_CNT + 2] << 16 | ext_csd[EXT_CSD_SEC_CNT + 3] << 24; - if (card->ext_csd.sectors) + + /* Cards with density > 2GiB are sector addressed */ + if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512) mmc_card_set_blockaddr(card); } switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) { + case EXT_CSD_CARD_TYPE_DDR_52 | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_52; + break; + case EXT_CSD_CARD_TYPE_DDR_1_2V | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_2V; + break; + case EXT_CSD_CARD_TYPE_DDR_1_8V | EXT_CSD_CARD_TYPE_52 | + EXT_CSD_CARD_TYPE_26: + card->ext_csd.hs_max_dtr = 52000000; + card->ext_csd.card_type = EXT_CSD_CARD_TYPE_DDR_1_8V; + break; case EXT_CSD_CARD_TYPE_52 | EXT_CSD_CARD_TYPE_26: card->ext_csd.hs_max_dtr = 52000000; break; @@ -303,7 +332,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, struct mmc_card *oldcard) { struct mmc_card *card; - int err; + int err, ddr = 0; u32 cid[4]; unsigned int max_dtr; @@ -444,17 +473,35 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, mmc_set_clock(host, max_dtr); /* - * Activate wide bus (if supported). + * Indicate DDR mode (if supported). + */ + if (mmc_card_highspeed(card)) { + if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) + && (host->caps & (MMC_CAP_1_8V_DDR))) + ddr = MMC_1_8V_DDR_MODE; + else if ((card->ext_csd.card_type & EXT_CSD_CARD_TYPE_DDR_1_2V) + && (host->caps & (MMC_CAP_1_2V_DDR))) + ddr = MMC_1_2V_DDR_MODE; + } + + /* + * Activate wide bus and DDR (if supported). */ if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { unsigned ext_csd_bit, bus_width; if (host->caps & MMC_CAP_8_BIT_DATA) { - ext_csd_bit = EXT_CSD_BUS_WIDTH_8; + if (ddr) + ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8; + else + ext_csd_bit = EXT_CSD_BUS_WIDTH_8; bus_width = MMC_BUS_WIDTH_8; } else { - ext_csd_bit = EXT_CSD_BUS_WIDTH_4; + if (ddr) + ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4; + else + ext_csd_bit = EXT_CSD_BUS_WIDTH_4; bus_width = MMC_BUS_WIDTH_4; } @@ -465,12 +512,17 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, goto free_card; if (err) { - printk(KERN_WARNING "%s: switch to bus width %d " + printk(KERN_WARNING "%s: switch to bus width %d ddr %d " "failed\n", mmc_hostname(card->host), - 1 << bus_width); + 1 << bus_width, ddr); err = 0; } else { - mmc_set_bus_width(card->host, bus_width); + if (ddr) + mmc_card_set_ddr_mode(card); + else + ddr = MMC_SDR_MODE; + + mmc_set_bus_width_ddr(card->host, bus_width, ddr); } } diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 326447c9ede..91ab05aa1d4 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -202,6 +202,7 @@ int mmc_set_relative_addr(struct mmc_card *card) { int err; struct mmc_command cmd; + u32 status; BUG_ON(!card); BUG_ON(!card->host); @@ -216,6 +217,28 @@ int mmc_set_relative_addr(struct mmc_card *card) if (err) return err; + /* Must check status to be sure of no errors */ + do { + err = mmc_send_status(card, &status); + if (err) + return err; + if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) + break; + if (mmc_host_is_spi(card->host)) + break; + } while (R1_CURRENT_STATE(status) == 7); + + if (mmc_host_is_spi(card->host)) { + if (status & R1_SPI_ILLEGAL_COMMAND) + return -EBADMSG; + } else { + if (status & 0xFDFFA000) + printk(KERN_WARNING "%s: unexpected status %#x after " + "switch", mmc_hostname(card->host), status); + if (status & R1_SWITCH_ERROR) + return -EBADMSG; + } + return 0; } diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 5eac21df480..f5e29edbec0 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -337,7 +337,9 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, int err; u32 cid[4]; unsigned int max_dtr; - +#ifdef CONFIG_MMC_PARANOID_SD_INIT + int retries; +#endif BUG_ON(!host); WARN_ON(!host->claimed); @@ -440,11 +442,29 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, err = mmc_decode_scr(card); if (err < 0) goto free_card; - /* * Fetch switch information from card. */ +#ifdef CONFIG_MMC_PARANOID_SD_INIT + for (retries = 1; retries <= 3; retries++) { + err = mmc_read_switch(card); + if (!err) { + if (retries > 1) { + printk(KERN_WARNING + "%s: recovered\n", + mmc_hostname(host)); + } + break; + } else { + printk(KERN_WARNING + "%s: read switch failed (attempt %d)\n", + mmc_hostname(host), retries); + } + } +#else err = mmc_read_switch(card); +#endif + if (err) goto free_card; } @@ -539,18 +559,36 @@ static void mmc_sd_remove(struct mmc_host *host) */ static void mmc_sd_detect(struct mmc_host *host) { - int err; + int err = 0; +#ifdef CONFIG_MMC_PARANOID_SD_INIT + int retries = 5; +#endif BUG_ON(!host); BUG_ON(!host->card); - + mmc_claim_host(host); /* * Just check if our card has been removed. */ +#ifdef CONFIG_MMC_PARANOID_SD_INIT + while(retries) { + err = mmc_send_status(host->card, NULL); + if (err) { + retries--; + udelay(5); + continue; + } + break; + } + if (!retries) { + printk(KERN_ERR "%s(%s): Unable to re-detect card (%d)\n", + __func__, mmc_hostname(host), err); + } +#else err = mmc_send_status(host->card, NULL); - +#endif mmc_release_host(host); if (err) { @@ -588,12 +626,31 @@ static int mmc_sd_suspend(struct mmc_host *host) static int mmc_sd_resume(struct mmc_host *host) { int err; +#ifdef CONFIG_MMC_PARANOID_SD_INIT + int retries; +#endif BUG_ON(!host); BUG_ON(!host->card); mmc_claim_host(host); +#ifdef CONFIG_MMC_PARANOID_SD_INIT + retries = 5; + while (retries) { + err = mmc_sd_init_card(host, host->ocr, host->card); + + if (err) { + printk(KERN_ERR "%s: Re-init card rc = %d (retries = %d)\n", + mmc_hostname(host), err, retries); + mdelay(5); + retries--; + continue; + } + break; + } +#else err = mmc_sd_init_card(host, host->ocr, host->card); +#endif mmc_release_host(host); return err; @@ -640,6 +697,9 @@ static void mmc_sd_attach_bus_ops(struct mmc_host *host) int mmc_attach_sd(struct mmc_host *host, u32 ocr) { int err; +#ifdef CONFIG_MMC_PARANOID_SD_INIT + int retries; +#endif BUG_ON(!host); WARN_ON(!host->claimed); @@ -688,9 +748,27 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr) /* * Detect and init the card. */ +#ifdef CONFIG_MMC_PARANOID_SD_INIT + retries = 5; + while (retries) { + err = mmc_sd_init_card(host, host->ocr, NULL); + if (err) { + retries--; + continue; + } + break; + } + + if (!retries) { + printk(KERN_ERR "%s: mmc_sd_init_card() failure (err = %d)\n", + mmc_hostname(host), err); + goto err; + } +#else err = mmc_sd_init_card(host, host->ocr, NULL); if (err) goto err; +#endif mmc_release_host(host); diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index b9dee28ee7d..04e68fe3bcc 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -24,6 +24,10 @@ #include "sdio_ops.h" #include "sdio_cis.h" +#ifdef CONFIG_MMC_EMBEDDED_SDIO +#include <linux/mmc/sdio_ids.h> +#endif + static int sdio_read_fbr(struct sdio_func *func) { int ret; @@ -309,6 +313,13 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, if (err) goto remove; + /* + * Update oldcard with the new RCA received from the + * SDIO device. + */ + if (oldcard) + oldcard->rca = card->rca; + mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); } @@ -321,19 +332,35 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, goto remove; } - /* - * Read the common registers. - */ - err = sdio_read_cccr(card); - if (err) - goto remove; +#ifdef CONFIG_MMC_EMBEDDED_SDIO + if (host->embedded_sdio_data.cccr) + memcpy(&card->cccr, host->embedded_sdio_data.cccr, sizeof(struct sdio_cccr)); + else { +#endif + /* + * Read the common registers. + */ + err = sdio_read_cccr(card); + if (err) + goto remove; +#ifdef CONFIG_MMC_EMBEDDED_SDIO + } +#endif - /* - * Read the common CIS tuples. - */ - err = sdio_read_common_cis(card); - if (err) - goto remove; +#ifdef CONFIG_MMC_EMBEDDED_SDIO + if (host->embedded_sdio_data.cis) + memcpy(&card->cis, host->embedded_sdio_data.cis, sizeof(struct sdio_cis)); + else { +#endif + /* + * Read the common CIS tuples. + */ + err = sdio_read_common_cis(card); + if (err) + goto remove; +#ifdef CONFIG_MMC_EMBEDDED_SDIO + } +#endif if (oldcard) { int same = (card->cis.vendor == oldcard->cis.vendor && @@ -344,7 +371,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, goto err; } card = oldcard; - return 0; } /* @@ -515,11 +541,26 @@ static int mmc_sdio_resume(struct mmc_host *host) return err; } +static void mmc_sdio_power_restore(struct mmc_host *host) +{ + int err; + BUG_ON(!host); + BUG_ON(!host->card); + + mmc_claim_host(host); + err = mmc_sdio_init_card(host, host->ocr, host->card, + (host->pm_flags & MMC_PM_KEEP_POWER)); + if (!err && host->sdio_irqs) + mmc_signal_sdio_irq(host); + mmc_release_host(host); +} + static const struct mmc_bus_ops mmc_sdio_ops = { .remove = mmc_sdio_remove, .detect = mmc_sdio_detect, .suspend = mmc_sdio_suspend, .resume = mmc_sdio_resume, + .power_restore = mmc_sdio_power_restore, }; @@ -573,6 +614,11 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) funcs = (ocr & 0x70000000) >> 28; card->sdio_funcs = 0; +#ifdef CONFIG_MMC_EMBEDDED_SDIO + if (host->embedded_sdio_data.funcs) + card->sdio_funcs = funcs = host->embedded_sdio_data.num_funcs; +#endif + /* * If needed, disconnect card detection pull-up resistor. */ @@ -584,9 +630,27 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) * Initialize (but don't add) all present functions. */ for (i = 0; i < funcs; i++, card->sdio_funcs++) { - err = sdio_init_func(host->card, i + 1); - if (err) - goto remove; +#ifdef CONFIG_MMC_EMBEDDED_SDIO + if (host->embedded_sdio_data.funcs) { + struct sdio_func *tmp; + + tmp = sdio_alloc_func(host->card); + if (IS_ERR(tmp)) + goto remove; + tmp->num = (i + 1); + card->sdio_func[i] = tmp; + tmp->class = host->embedded_sdio_data.funcs[i].f_class; + tmp->max_blksize = host->embedded_sdio_data.funcs[i].f_maxblksize; + tmp->vendor = card->cis.vendor; + tmp->device = card->cis.device; + } else { +#endif + err = sdio_init_func(host->card, i + 1); + if (err) + goto remove; +#ifdef CONFIG_MMC_EMBEDDED_SDIO + } +#endif } mmc_release_host(host); @@ -628,3 +692,82 @@ err: return err; } +int sdio_reset_comm(struct mmc_card *card) +{ + struct mmc_host *host = card->host; + u32 ocr; + int err; + + printk("%s():\n", __func__); + mmc_claim_host(host); + + mmc_go_idle(host); + + mmc_set_clock(host, host->f_min); + + err = mmc_send_io_op_cond(host, 0, &ocr); + if (err) + goto err; + + host->ocr = mmc_select_voltage(host, ocr); + if (!host->ocr) { + err = -EINVAL; + goto err; + } + + err = mmc_send_io_op_cond(host, host->ocr, &ocr); + if (err) + goto err; + + if (mmc_host_is_spi(host)) { + err = mmc_spi_set_crc(host, use_spi_crc); + if (err) + goto err; + } + + if (!mmc_host_is_spi(host)) { + err = mmc_send_relative_addr(host, &card->rca); + if (err) + goto err; + mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); + } + if (!mmc_host_is_spi(host)) { + err = mmc_select_card(card); + if (err) + goto err; + } + + /* + * Switch to high-speed (if supported). + */ + err = sdio_enable_hs(card); + if (err) + goto err; + + /* + * Change to the card's maximum speed. + */ + if (mmc_card_highspeed(card)) { + /* + * The SDIO specification doesn't mention how + * the CIS transfer speed register relates to + * high-speed, but it seems that 50 MHz is + * mandatory. + */ + mmc_set_clock(host, 50000000); + } else { + mmc_set_clock(host, card->cis.max_dtr); + } + + err = sdio_enable_wide(card); + if (err) + goto err; + mmc_release_host(host); + return 0; +err: + printk("%s: Error resetting SDIO communications (%d)\n", + mmc_hostname(host), err); + mmc_release_host(host); + return err; +} +EXPORT_SYMBOL(sdio_reset_comm); diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 4a890dcb95a..f59f9255448 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c @@ -21,6 +21,10 @@ #include "sdio_cis.h" #include "sdio_bus.h" +#ifdef CONFIG_MMC_EMBEDDED_SDIO +#include <linux/mmc/host.h> +#endif + /* show configuration fields */ #define sdio_config_attr(field, format_string) \ static ssize_t \ @@ -200,7 +204,14 @@ static void sdio_release_func(struct device *dev) { struct sdio_func *func = dev_to_sdio_func(dev); - sdio_free_func_cis(func); +#ifdef CONFIG_MMC_EMBEDDED_SDIO + /* + * If this device is embedded then we never allocated + * cis tables for this func + */ + if (!func->card->host->embedded_sdio_data.funcs) +#endif + sdio_free_func_cis(func); if (func->info) kfree(func->info); diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c index 0f687cdeb06..a2767401182 100644..100755 --- a/drivers/mmc/core/sdio_io.c +++ b/drivers/mmc/core/sdio_io.c @@ -338,6 +338,10 @@ static int sdio_io_rw_ext_helper(struct sdio_func *func, int write, while (remainder > 0) { size = min(remainder, sdio_max_byte_size(func)); + // Some of host controllers does not support non-power-of-two block sizes + if (func->card->host->caps & MMC_CAP_POWER_OF_TWO_BLKSIZE) + size = 1 << (fls(size) - 1); + ret = mmc_io_rw_extended(func->card, write, func->num, addr, incr_addr, buf, 1, size); if (ret) @@ -383,6 +387,39 @@ u8 sdio_readb(struct sdio_func *func, unsigned int addr, int *err_ret) EXPORT_SYMBOL_GPL(sdio_readb); /** + * sdio_readb_ext - read a single byte from a SDIO function + * @func: SDIO function to access + * @addr: address to read + * @err_ret: optional status value from transfer + * @in: value to add to argument + * + * Reads a single byte from the address space of a given SDIO + * function. If there is a problem reading the address, 0xff + * is returned and @err_ret will contain the error code. + */ +unsigned char sdio_readb_ext(struct sdio_func *func, unsigned int addr, + int *err_ret, unsigned in) +{ + int ret; + unsigned char val; + + BUG_ON(!func); + + if (err_ret) + *err_ret = 0; + + ret = mmc_io_rw_direct(func->card, 0, func->num, addr, (u8)in, &val); + if (ret) { + if (err_ret) + *err_ret = ret; + return 0xFF; + } + + return val; +} +EXPORT_SYMBOL_GPL(sdio_readb_ext); + +/** * sdio_writeb - write a single byte to a SDIO function * @func: SDIO function to access * @b: byte to write diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index bb192f90e8e..96f81237d75 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -27,11 +27,29 @@ #include "sdio_ops.h" +#define SDIO_IDLE_POLL_PERIOD 10 + static int process_sdio_pending_irqs(struct mmc_card *card) { int i, ret, count; unsigned char pending; + /* + * Optimization, if there is only 1 function registered + * and IRQ:s are supported and currently enabled, then + * we can assume that this actually is an IRQ and we can + * call the registered IRQ handler directly without + * checking the CCCR registers. + */ + if ((card->host->caps & MMC_CAP_SDIO_IRQ) && + card->host->sdio_irqs && (card->sdio_funcs == 1)) { + struct sdio_func *func = card->sdio_func[0]; + if (func && func->irq_handler) { + func->irq_handler(func); + return 1; + } + } + ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_INTx, 0, &pending); if (ret) { printk(KERN_DEBUG "%s: error %d reading SDIO_CCCR_INTx\n", @@ -65,89 +83,50 @@ static int process_sdio_pending_irqs(struct mmc_card *card) return ret; } -static int sdio_irq_thread(void *_host) +static void sdio_irq_work_func(struct work_struct *work) { - struct mmc_host *host = _host; - struct sched_param param = { .sched_priority = 1 }; - unsigned long period, idle_period; + struct mmc_host *host = (struct mmc_host *) + container_of(work, struct mmc_host, sdio_irq_work.work); int ret; - sched_setscheduler(current, SCHED_FIFO, ¶m); - /* - * We want to allow for SDIO cards to work even on non SDIO - * aware hosts. One thing that non SDIO host cannot do is - * asynchronous notification of pending SDIO card interrupts - * hence we poll for them in that case. + * We claim the host here on drivers behalf for a couple + * reasons: + * + * 1) it is already needed to retrieve the CCCR_INTx; + * 2) we want the driver(s) to clear the IRQ condition ASAP; + * 3) we need to control the abort condition locally. + * + * Just like traditional hard IRQ handlers, we expect SDIO + * IRQ handlers to be quick and to the point, so that the + * holding of the host lock does not cover too much work + * that doesn't require that lock to be held. */ - idle_period = msecs_to_jiffies(10); - period = (host->caps & MMC_CAP_SDIO_IRQ) ? - MAX_SCHEDULE_TIMEOUT : idle_period; + mmc_claim_host(host); - pr_debug("%s: IRQ thread started (poll period = %lu jiffies)\n", - mmc_hostname(host), period); + ret = process_sdio_pending_irqs(host->card); - do { - /* - * We claim the host here on drivers behalf for a couple - * reasons: - * - * 1) it is already needed to retrieve the CCCR_INTx; - * 2) we want the driver(s) to clear the IRQ condition ASAP; - * 3) we need to control the abort condition locally. - * - * Just like traditional hard IRQ handlers, we expect SDIO - * IRQ handlers to be quick and to the point, so that the - * holding of the host lock does not cover too much work - * that doesn't require that lock to be held. - */ - ret = __mmc_claim_host(host, &host->sdio_irq_thread_abort); - if (ret) - break; - ret = process_sdio_pending_irqs(host->card); - mmc_release_host(host); - - /* - * Give other threads a chance to run in the presence of - * errors. - */ - if (ret < 0) { - set_current_state(TASK_INTERRUPTIBLE); - if (!kthread_should_stop()) - schedule_timeout(HZ); - set_current_state(TASK_RUNNING); - } + mmc_release_host(host); + if (host->caps & MMC_CAP_SDIO_IRQ) + host->ops->enable_sdio_irq(host, true); + else { /* * Adaptive polling frequency based on the assumption * that an interrupt will be closely followed by more. * This has a substantial benefit for network devices. */ - if (!(host->caps & MMC_CAP_SDIO_IRQ)) { - if (ret > 0) - period /= 2; - else { - period++; - if (period > idle_period) - period = idle_period; - } + if (ret > 0) + host->sdio_poll_period /= 2; + else { + host->sdio_poll_period++; + if (host->sdio_poll_period > SDIO_IDLE_POLL_PERIOD) + host->sdio_poll_period = SDIO_IDLE_POLL_PERIOD; } - - set_current_state(TASK_INTERRUPTIBLE); - if (host->caps & MMC_CAP_SDIO_IRQ) - host->ops->enable_sdio_irq(host, 1); - if (!kthread_should_stop()) - schedule_timeout(period); - set_current_state(TASK_RUNNING); - } while (!kthread_should_stop()); - - if (host->caps & MMC_CAP_SDIO_IRQ) - host->ops->enable_sdio_irq(host, 0); - - pr_debug("%s: IRQ thread exiting with code %d\n", - mmc_hostname(host), ret); - - return ret; + queue_delayed_work(host->sdio_irq_workqueue, + &host->sdio_irq_work, + msecs_to_jiffies(host->sdio_poll_period)); + } } static int sdio_card_irq_get(struct mmc_card *card) @@ -157,14 +136,28 @@ static int sdio_card_irq_get(struct mmc_card *card) WARN_ON(!host->claimed); if (!host->sdio_irqs++) { - atomic_set(&host->sdio_irq_thread_abort, 0); - host->sdio_irq_thread = - kthread_run(sdio_irq_thread, host, "ksdioirqd/%s", - mmc_hostname(host)); - if (IS_ERR(host->sdio_irq_thread)) { - int err = PTR_ERR(host->sdio_irq_thread); + host->sdio_irq_workqueue = + create_singlethread_workqueue("sdio_irq_workqueue"); + if (host->sdio_irq_workqueue == NULL) { host->sdio_irqs--; - return err; + return -ENOMEM; + } + + INIT_DELAYED_WORK(&host->sdio_irq_work, sdio_irq_work_func); + + /* + * We want to allow for SDIO cards to work even on non SDIO + * aware hosts. One thing that non SDIO host cannot do is + * asynchronous notification of pending SDIO card interrupts + * hence we poll for them in that case. + */ + if (host->caps & MMC_CAP_SDIO_IRQ) + host->ops->enable_sdio_irq(host, true); + else { + host->sdio_poll_period = SDIO_IDLE_POLL_PERIOD; + queue_delayed_work(host->sdio_irq_workqueue, + &host->sdio_irq_work, + msecs_to_jiffies(host->sdio_poll_period)); } } @@ -179,8 +172,9 @@ static int sdio_card_irq_put(struct mmc_card *card) BUG_ON(host->sdio_irqs < 1); if (!--host->sdio_irqs) { - atomic_set(&host->sdio_irq_thread_abort, 1); - kthread_stop(host->sdio_irq_thread); + host->ops->enable_sdio_irq(host, false); + destroy_workqueue(host->sdio_irq_workqueue); + host->sdio_irq_workqueue = NULL; } return 0; diff --git a/drivers/mmc/core/sdio_ops.c b/drivers/mmc/core/sdio_ops.c index dea36d9c22e..4e3b3004013 100644 --- a/drivers/mmc/core/sdio_ops.c +++ b/drivers/mmc/core/sdio_ops.c @@ -152,10 +152,15 @@ int mmc_io_rw_extended(struct mmc_card *card, int write, unsigned fn, cmd.arg |= fn << 28; cmd.arg |= incr_addr ? 0x04000000 : 0x00000000; cmd.arg |= addr << 9; - if (blocks == 1 && blksz <= 512) - cmd.arg |= (blksz == 512) ? 0 : blksz; /* byte mode */ + + if (blocks == 1 && blksz < 512) + cmd.arg |= blksz; /* byte mode */ + else if (blocks == 1 && blksz == 512 && + !(card->host->caps & MMC_CAP_BROKEN_SDIO_CMD53)) + cmd.arg |= 0; /* byte mode, 0=512 */ else cmd.arg |= 0x08000000 | blocks; /* block mode */ + cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; data.blksz = blksz; diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 5f3a599ead0..80a95b49513 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c @@ -946,8 +946,7 @@ static int __init at91_mci_probe(struct platform_device *pdev) mmc->max_blk_size = MCI_MAXBLKSIZE; mmc->max_blk_count = MCI_BLKATONCE; mmc->max_req_size = MCI_BUFSIZE; - mmc->max_phys_segs = MCI_BLKATONCE; - mmc->max_hw_segs = MCI_BLKATONCE; + mmc->max_segs = MCI_BLKATONCE; mmc->max_seg_size = MCI_BUFSIZE; host = mmc_priv(mmc); diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 95ef864ad8f..ac7989f1240 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1618,8 +1618,7 @@ static int __init atmci_init_slot(struct atmel_mci *host, if (slot_data->bus_width >= 4) mmc->caps |= MMC_CAP_4_BIT_DATA; - mmc->max_hw_segs = 64; - mmc->max_phys_segs = 64; + mmc->max_segs = 64; mmc->max_req_size = 32768 * 512; mmc->max_blk_size = 32768; mmc->max_blk_count = 512; diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index c8da5d30a86..59b2265a41d 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c @@ -998,7 +998,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev) mmc->f_max = 24000000; mmc->max_seg_size = AU1XMMC_DESCRIPTOR_SIZE; - mmc->max_phys_segs = AU1XMMC_DESCRIPTOR_COUNT; + mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT; mmc->max_blk_size = 2048; mmc->max_blk_count = 512; diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index 4b0e677d729..bac7d62866b 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c @@ -469,7 +469,7 @@ static int __devinit sdh_probe(struct platform_device *pdev) } mmc->ops = &sdh_ops; - mmc->max_phys_segs = 32; + mmc->max_segs = 32; mmc->max_seg_size = 1 << 16; mmc->max_blk_size = 1 << 11; mmc->max_blk_count = 1 << 11; diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 33d9f1b0086..e15547cf701 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c @@ -138,7 +138,7 @@ /* * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units, * and we handle up to MAX_NR_SG segments. MMC_BLOCK_BOUNCE kicks in only - * for drivers with max_hw_segs == 1, making the segments bigger (64KB) + * for drivers with max_segs == 1, making the segments bigger (64KB) * than the page or two that's otherwise typical. nr_sg (passed from * platform data) == 16 gives at least the same throughput boost, using * EDMA transfer linkage instead of spending CPU time copying pages. @@ -1239,8 +1239,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) * Each hw_seg uses one EDMA parameter RAM slot, always one * channel and then usually some linked slots. */ - mmc->max_hw_segs = 1 + host->n_link; - mmc->max_phys_segs = mmc->max_hw_segs; + mmc->max_segs = 1 + host->n_link; /* EDMA limit per hw segment (one or two MBytes) */ mmc->max_seg_size = MAX_CCNT * rw_threshold; @@ -1250,8 +1249,7 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) mmc->max_blk_count = 65535; /* NBLK is 16 bits */ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; - dev_dbg(mmc_dev(host->mmc), "max_phys_segs=%d\n", mmc->max_phys_segs); - dev_dbg(mmc_dev(host->mmc), "max_hw_segs=%d\n", mmc->max_hw_segs); + dev_dbg(mmc_dev(host->mmc), "max_segs=%d\n", mmc->max_segs); dev_dbg(mmc_dev(host->mmc), "max_blk_size=%d\n", mmc->max_blk_size); dev_dbg(mmc_dev(host->mmc), "max_req_size=%d\n", mmc->max_req_size); dev_dbg(mmc_dev(host->mmc), "max_seg_size=%d\n", mmc->max_seg_size); diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index 9a68ff4353a..24f24c86b71 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c @@ -965,8 +965,7 @@ static int __init imxmci_probe(struct platform_device *pdev) mmc->caps = MMC_CAP_4_BIT_DATA; /* MMC core transfer sizes tunable parameters */ - mmc->max_hw_segs = 64; - mmc->max_phys_segs = 64; + mmc->max_segs = 64; mmc->max_seg_size = 64*512; /* default PAGE_CACHE_SIZE */ mmc->max_req_size = 64*512; /* default PAGE_CACHE_SIZE */ mmc->max_blk_size = 2048; diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index ad847a24a67..b49cf4727ae 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1382,8 +1382,7 @@ static int mmc_spi_probe(struct spi_device *spi) mmc->ops = &mmc_spi_ops; mmc->max_blk_size = MMC_SPI_BLOCKSIZE; - mmc->max_hw_segs = MMC_SPI_BLOCKSATONCE; - mmc->max_phys_segs = MMC_SPI_BLOCKSATONCE; + mmc->max_segs = MMC_SPI_BLOCKSATONCE; mmc->max_req_size = MMC_SPI_BLOCKSATONCE * MMC_SPI_BLOCKSIZE; mmc->max_blk_count = MMC_SPI_BLOCKSATONCE; diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 2ed435bd4b6..92a5f73854c 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -2,7 +2,7 @@ * linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver * * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. - * Copyright (C) 2010 ST-Ericsson AB. + * Copyright (C) 2010 ST-Ericsson SA * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -18,44 +18,249 @@ #include <linux/err.h> #include <linux/highmem.h> #include <linux/log2.h> +#include <linux/pm_runtime.h> #include <linux/mmc/host.h> +#include <linux/mmc/card.h> +#include <linux/mmc/pm.h> #include <linux/amba/bus.h> #include <linux/clk.h> #include <linux/scatterlist.h> #include <linux/gpio.h> -#include <linux/amba/mmci.h> #include <linux/regulator/consumer.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> +#include <linux/amba/mmci.h> -#include <asm/cacheflush.h> -#include <asm/div64.h> -#include <asm/io.h> +#include <linux/io.h> #include <asm/sizes.h> +#ifdef CONFIG_ARCH_U8500 +/* Temporary solution to find out if HW is db8500 v1 or v2. */ +#include <mach/hardware.h> +#endif + #include "mmci.h" #define DRIVER_NAME "mmci-pl18x" static unsigned int fmax = 515633; +static unsigned int dataread_delay_clks = 7500000; + +/** + * struct variant_data - MMCI variant-specific quirks + * @clkreg: default value for MCICLOCK register + * @clkreg_enable: enable value for MMCICLOCK register + * @dmareg_enable: enable value for MMCIDATACTRL register + * @datalength_bits: number of bits in the MMCIDATALENGTH register + * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY + * is asserted (likewise for RX) + * @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY + * is asserted (likewise for RX) + * @txsize_threshold: Sets DMA burst size to minimal if transfer size is + * less or equal to this threshold. This shall be specified in + * number of bytes. Set 0 for no burst compensation + * @broken_blockend: the MCI_DATABLOCKEND is broken on the hardware + * and will not work at all. + * @sdio: variant supports SDIO + * @st_clkdiv: true if using a ST-specific clock divider algorithm + * @pwrreg_powerup: power up value for MMCIPOWER register + * @signal_direction: input/out direction of bus signals can be indicated, + * this is usually used by e.g. voltage level translators. + * @non_power_of_2_blksize: variant supports block sizes that are not + * a power of two. + */ +struct variant_data { + unsigned int clkreg; + unsigned int clkreg_enable; + unsigned int dmareg_enable; + unsigned int datalength_bits; + unsigned int fifosize; + unsigned int fifohalfsize; + unsigned int txsize_threshold; + bool broken_blockend; + bool sdio; + bool st_clkdiv; + unsigned int pwrreg_powerup; + bool signal_direction; + bool non_power_of_2_blksize; +}; + +static struct variant_data variant_arm = { + .fifosize = 16 * 4, + .fifohalfsize = 8 * 4, + .datalength_bits = 16, + .pwrreg_powerup = MCI_PWR_UP, +}; + +static struct variant_data variant_u300 = { + .fifosize = 16 * 4, + .fifohalfsize = 8 * 4, + .clkreg_enable = 1 << 13, /* HWFCEN */ + .datalength_bits = 16, + .sdio = true, + .pwrreg_powerup = MCI_PWR_ON, + .signal_direction = true, +}; + +static struct variant_data variant_ux500 = { + .fifosize = 30 * 4, + .fifohalfsize = 8 * 4, + .txsize_threshold = 16, + .clkreg = MCI_CLK_ENABLE, + .clkreg_enable = 1 << 14, /* HWFCEN */ + .dmareg_enable = 1 << 12, /* DMAREQCTRL */ + .datalength_bits = 24, + .broken_blockend = true, + .sdio = true, + .st_clkdiv = true, + .pwrreg_powerup = MCI_PWR_ON, + .signal_direction = true, + .non_power_of_2_blksize = true, +}; +/* + * Debugfs + */ +#ifdef CONFIG_DEBUG_FS +#include <linux/debugfs.h> +#include <linux/seq_file.h> + +static int mmci_regs_show(struct seq_file *seq, void *v) +{ + struct mmci_host *host = seq->private; + unsigned long iflags; + u32 pwr, clk, arg, cmd, rspcmd, r0, r1, r2, r3; + u32 dtimer, dlength, dctrl, dcnt; + u32 sta, clear, mask0, mask1, fifocnt, fifo; + + mmc_host_enable(host->mmc); + spin_lock_irqsave(&host->lock, iflags); + + pwr = readl(host->base + MMCIPOWER); + clk = readl(host->base + MMCICLOCK); + arg = readl(host->base + MMCIARGUMENT); + cmd = readl(host->base + MMCICOMMAND); + rspcmd = readl(host->base + MMCIRESPCMD); + r0 = readl(host->base + MMCIRESPONSE0); + r1 = readl(host->base + MMCIRESPONSE1); + r2 = readl(host->base + MMCIRESPONSE2); + r3 = readl(host->base + MMCIRESPONSE3); + dtimer = readl(host->base + MMCIDATATIMER); + dlength = readl(host->base + MMCIDATALENGTH); + dctrl = readl(host->base + MMCIDATACTRL); + dcnt = readl(host->base + MMCIDATACNT); + sta = readl(host->base + MMCISTATUS); + clear = readl(host->base + MMCICLEAR); + mask0 = readl(host->base + MMCIMASK0); + mask1 = readl(host->base + MMCIMASK1); + fifocnt = readl(host->base + MMCIFIFOCNT); + fifo = readl(host->base + MMCIFIFO); + + spin_unlock_irqrestore(&host->lock, iflags); + mmc_host_disable(host->mmc); + + seq_printf(seq, "\033[1;34mMMCI registers\033[0m\n"); + seq_printf(seq, "%-20s:0x%x\n", "mmci_power", pwr); + seq_printf(seq, "%-20s:0x%x\n", "mmci_clock", clk); + seq_printf(seq, "%-20s:0x%x\n", "mmci_arg", arg); + seq_printf(seq, "%-20s:0x%x\n", "mmci_cmd", cmd); + seq_printf(seq, "%-20s:0x%x\n", "mmci_respcmd", rspcmd); + seq_printf(seq, "%-20s:0x%x\n", "mmci_resp0", r0); + seq_printf(seq, "%-20s:0x%x\n", "mmci_resp1", r1); + seq_printf(seq, "%-20s:0x%x\n", "mmci_resp2", r2); + seq_printf(seq, "%-20s:0x%x\n", "mmci_resp3", r3); + seq_printf(seq, "%-20s:0x%x\n", "mmci_datatimer", dtimer); + seq_printf(seq, "%-20s:0x%x\n", "mmci_datalen", dlength); + seq_printf(seq, "%-20s:0x%x\n", "mmci_datactrl", dctrl); + seq_printf(seq, "%-20s:0x%x\n", "mmci_datacnt", dcnt); + seq_printf(seq, "%-20s:0x%x\n", "mmci_status", sta); + seq_printf(seq, "%-20s:0x%x\n", "mmci_iclear", clear); + seq_printf(seq, "%-20s:0x%x\n", "mmci_imask0", mask0); + seq_printf(seq, "%-20s:0x%x\n", "mmci_imask1", mask1); + seq_printf(seq, "%-20s:0x%x\n", "mmci_fifocnt", fifocnt); + seq_printf(seq, "%-20s:0x%x\n", "mmci_fifo", fifo); + + return 0; +} + +static int mmci_regs_open(struct inode *inode, struct file *file) +{ + return single_open(file, mmci_regs_show, inode->i_private); +} + +static const struct file_operations mmci_fops_regs = { + .owner = THIS_MODULE, + .open = mmci_regs_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void mmci_debugfs_create(struct mmci_host *host) +{ + host->debug_regs = debugfs_create_file("regs", S_IRUGO, + host->mmc->debugfs_root, host, + &mmci_fops_regs); + + if (IS_ERR(host->debug_regs)) + dev_err(mmc_dev(host->mmc), + "failed to create debug regs file\n"); +} + +static void mmci_debugfs_remove(struct mmci_host *host) +{ + debugfs_remove(host->debug_regs); +} + +#else +static inline void mmci_debugfs_create(struct mmci_host *host) { } +static inline void mmci_debugfs_remove(struct mmci_host *host) { } +#endif + +/* + * Uggly hack! This must be removed soon!! + * + * u8500_sdio_detect_card() - Initiates card scan for sdio host. + * This is required to initiate card rescan from sdio client device driver. + * + * sdio_host_ptr - Host pointer to save SDIO host data structure + * (will only work when the SDIO device is probed as the last MMCI device). + */ +static struct mmci_host *sdio_host_ptr; +void u8500_sdio_detect_card(void) +{ + struct mmci_host *host = sdio_host_ptr; + if (sdio_host_ptr && host->mmc) + mmc_detect_change(host->mmc, msecs_to_jiffies(10)); + + return; +} +EXPORT_SYMBOL(u8500_sdio_detect_card); /* * This must be called with host->lock held */ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) { - u32 clk = 0; + struct variant_data *variant = host->variant; + u32 clk = variant->clkreg; if (desired) { if (desired >= host->mclk) { - clk = MCI_CLK_BYPASS; + clk = MCI_CLK_BYPASS | MCI_NEG_EDGE; host->cclk = host->mclk; + } else if (variant->st_clkdiv) { + clk = ((host->mclk + desired - 1) / desired) - 2; + if (clk >= 256) + clk = 255; + host->cclk = host->mclk / (clk + 2); } else { clk = host->mclk / (2 * desired) - 1; if (clk >= 256) clk = 255; host->cclk = host->mclk / (2 * (clk + 1)); } - if (host->hw_designer == AMBA_VENDOR_ST) - clk |= MCI_ST_FCEN; /* Bug fix in ST IP block */ + + clk |= variant->clkreg_enable; clk |= MCI_CLK_ENABLE; /* This hasn't proven to be worthwhile */ /* clk |= MCI_CLK_PWRSAVE; */ @@ -91,63 +296,62 @@ mmci_request_end(struct mmci_host *host, struct mmc_request *mrq) spin_lock(&host->lock); } -static void mmci_stop_data(struct mmci_host *host) -{ - writel(0, host->base + MMCIDATACTRL); - writel(0, host->base + MMCIMASK1); - host->data = NULL; -} - -static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) +static void mmci_set_mask1(struct mmci_host *host, unsigned int mask) { - unsigned int datactrl, timeout, irqmask; - unsigned long long clks; - void __iomem *base; - int blksz_bits; + void __iomem *base = host->base; - dev_dbg(mmc_dev(host->mmc), "blksz %04x blks %04x flags %08x\n", - data->blksz, data->blocks, data->flags); + if (host->singleirq) { + unsigned int mask0 = readl(base + MMCIMASK0); - host->data = data; - host->size = data->blksz; - host->data_xfered = 0; + mask0 &= ~MCI_IRQ1MASK; + mask0 |= mask; - mmci_init_sg(host, data); + writel(mask0, base + MMCIMASK0); + } - clks = (unsigned long long)data->timeout_ns * host->cclk; - do_div(clks, 1000000000UL); + writel(mask, base + MMCIMASK1); +} - timeout = data->timeout_clks + (unsigned int)clks; +static void mmci_stop_data(struct mmci_host *host) +{ + u32 clk; + unsigned int datactrl = 0; - base = host->base; - writel(timeout, base + MMCIDATATIMER); - writel(host->size, base + MMCIDATALENGTH); + /* + * The ST Micro variants has a special bit + * to enable SDIO mode. This bit must remain set even when not + * doing data transfers, otherwise no SDIO interrupts can be + * received. + */ + if (host->variant->sdio && + host->mmc->card && + mmc_card_sdio(host->mmc->card)) + datactrl |= MCI_ST_DPSM_SDIOEN; - blksz_bits = ffs(data->blksz) - 1; - BUG_ON(1 << blksz_bits != data->blksz); + writel(datactrl, host->base + MMCIDATACTRL); + mmci_set_mask1(host, 0); - datactrl = MCI_DPSM_ENABLE | blksz_bits << 4; - if (data->flags & MMC_DATA_READ) { - datactrl |= MCI_DPSM_DIRECTION; - irqmask = MCI_RXFIFOHALFFULLMASK; + /* Needed for DDR */ + if (host->mmc->card && mmc_card_ddr_mode(host->mmc->card)) { + clk = readl(host->base + MMCICLOCK); + clk &= ~(MCI_NEG_EDGE); - /* - * If we have less than a FIFOSIZE of bytes to transfer, - * trigger a PIO interrupt as soon as any data is available. - */ - if (host->size < MCI_FIFOSIZE) - irqmask |= MCI_RXDATAAVLBLMASK; - } else { - /* - * We don't actually need to include "FIFO empty" here - * since its implicit in "FIFO half empty". - */ - irqmask = MCI_TXFIFOHALFEMPTYMASK; + writel(clk, (host->base + MMCICLOCK)); } - writel(datactrl, base + MMCIDATACTRL); - writel(readl(base + MMCIMASK0) & ~MCI_DATAENDMASK, base + MMCIMASK0); - writel(irqmask, base + MMCIMASK1); + host->data = NULL; +} + +static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) +{ + unsigned int flags = SG_MITER_ATOMIC; + + if (data->flags & MMC_DATA_READ) + flags |= SG_MITER_TO_SG; + else + flags |= SG_MITER_FROM_SG; + + sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); } static void @@ -179,49 +383,499 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c) } static void -mmci_data_irq(struct mmci_host *host, struct mmc_data *data, - unsigned int status) +mmci_complete_data_xfer(struct mmci_host *host) { - if (status & MCI_DATABLOCKEND) { - host->data_xfered += data->blksz; -#ifdef CONFIG_ARCH_U300 + struct mmc_data *data = host->data; + + if ((host->size == 0) || data->error) { + + /* + * Variants with broken blockend flags and as well dma + * transfers handles the end of the entire transfer here. + */ + if (host->last_blockend && !data->error) + host->data_xfered = data->blksz * data->blocks; + + mmci_stop_data(host); + + if (!data->stop) + mmci_request_end(host, data->mrq); + else + mmci_start_command(host, data->stop, 0); + } +} + +/* + * All the DMA operation mode stuff goes inside this ifdef. + * This assumes that you have a generic DMA device interface, + * no custom DMA interfaces are supported. + */ +#ifdef CONFIG_DMA_ENGINE +static void __devinit mmci_setup_dma(struct mmci_host *host) +{ + struct mmci_platform_data *plat = host->plat; + dma_cap_mask_t mask; + + if (!plat || !plat->dma_filter) { + dev_err(mmc_dev(host->mmc), "no DMA platform data!\n"); + return; + } + + /* Try to acquire a generic DMA engine slave channel */ + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + /* + * If only an RX channel is specified, the driver will + * attempt to use it bidirectionally, however if it is + * is specified but cannot be located, DMA will be disabled. + */ + host->dma_rx_channel = dma_request_channel(mask, + plat->dma_filter, + plat->dma_rx_param); + /* E.g if no DMA hardware is present */ + if (!host->dma_rx_channel) { + dev_err(mmc_dev(host->mmc), "no RX DMA channel!\n"); + return; + } + if (plat->dma_tx_param) { + host->dma_tx_channel = dma_request_channel(mask, + plat->dma_filter, + plat->dma_tx_param); + if (!host->dma_tx_channel) { + dma_release_channel(host->dma_rx_channel); + host->dma_rx_channel = NULL; + return; + } + } else { + host->dma_tx_channel = host->dma_rx_channel; + } + host->dma_enable = true; + dev_info(mmc_dev(host->mmc), "use DMA channels DMA RX %s, DMA TX %s\n", + dma_chan_name(host->dma_rx_channel), + dma_chan_name(host->dma_tx_channel)); +} + +/* + * This is used in __devinit or __devexit so inline it + * so it can be discarded. + */ +static inline void mmci_disable_dma(struct mmci_host *host) +{ + if (host->dma_rx_channel) + dma_release_channel(host->dma_rx_channel); + if (host->dma_tx_channel) + dma_release_channel(host->dma_tx_channel); + host->dma_enable = false; +} + +static void mmci_dma_data_end(struct mmci_host *host) +{ + struct mmc_data *data = host->data; + + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + (data->flags & MMC_DATA_WRITE) + ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + host->dma_on_current_xfer = false; +} + +static void mmci_dma_terminate(struct mmci_host *host) +{ + struct mmc_data *data = host->data; + struct dma_chan *chan; + + dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n"); + if (data->flags & MMC_DATA_READ) + chan = host->dma_rx_channel; + else + chan = host->dma_tx_channel; + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + (data->flags & MMC_DATA_WRITE) + ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); + host->dma_on_current_xfer = false; +} + +static void mmci_dma_callback(void *arg) +{ + unsigned long flags; + struct mmci_host *host = arg; + + dev_vdbg(mmc_dev(host->mmc), "DMA transfer done!\n"); + + spin_lock_irqsave(&host->lock, flags); + + mmci_dma_data_end(host); + + /* Mark that the entire data is transferred for this dma transfer. */ + host->size = 0; + + /* + * Make sure MMCI has received MCI_DATAEND before + * completing the data transfer. + */ + if (host->dataend) + mmci_complete_data_xfer(host); + + spin_unlock_irqrestore(&host->lock, flags); +} + +static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl) +{ + struct variant_data *variant = host->variant; + struct dma_slave_config rx_conf = { + .src_addr = host->phybase + MMCIFIFO, + .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, + .direction = DMA_FROM_DEVICE, + .src_maxburst = variant->fifohalfsize >> 2, /* # of words */ + }; + struct dma_slave_config tx_conf = { + .dst_addr = host->phybase + MMCIFIFO, + .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, + .direction = DMA_TO_DEVICE, + .dst_maxburst = variant->fifohalfsize >> 2, /* # of words */ + }; + struct mmc_data *data = host->data; + enum dma_data_direction direction; + struct dma_chan *chan; + struct dma_async_tx_descriptor *desc; + struct scatterlist *sg; + dma_cookie_t cookie; + int i; + unsigned int irqmask0; + int sg_len; + + /* If less than or equal to the fifo size, don't bother with DMA */ + if (host->size <= variant->fifosize) + return -EINVAL; + + datactrl |= MCI_DPSM_DMAENABLE; + datactrl |= variant->dmareg_enable; + + if (data->flags & MMC_DATA_READ) { + if (host->size <= variant->txsize_threshold) + rx_conf.src_maxburst = 1; + + direction = DMA_FROM_DEVICE; + chan = host->dma_rx_channel; + chan->device->device_control(chan, DMA_SLAVE_CONFIG, + (unsigned long) &rx_conf); + } else { + if (host->size <= variant->txsize_threshold) + tx_conf.dst_maxburst = 1; + + direction = DMA_TO_DEVICE; + chan = host->dma_tx_channel; + chan->device->device_control(chan, DMA_SLAVE_CONFIG, + (unsigned long) &tx_conf); + } + + /* Check for weird stuff in the sg list */ + for_each_sg(data->sg, sg, data->sg_len, i) { + dev_vdbg(mmc_dev(host->mmc), + "MMCI SGlist %d dir %d: length: %08x\n", + i, direction, sg->length); + if (sg->offset & 3 || sg->length & 3) + return -EINVAL; + } + + sg_len = dma_map_sg(mmc_dev(host->mmc), data->sg, + data->sg_len, direction); + if (!sg_len) + goto map_err; + + desc = chan->device->device_prep_slave_sg(chan, + data->sg, sg_len, direction, + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + if (!desc) + goto unmap_exit; + + desc->callback = mmci_dma_callback; + desc->callback_param = host; + host->dma_desc = desc; + dev_vdbg(mmc_dev(host->mmc), "Submit MMCI DMA job, sglen %d " + "blksz %04x blks %04x flags %08x\n", + data->sg_len, data->blksz, data->blocks, data->flags); + cookie = desc->tx_submit(desc); + + /* Here overloaded DMA controllers may fail */ + if (dma_submit_error(cookie)) + goto unmap_exit; + + host->dma_on_current_xfer = true; + chan->device->device_issue_pending(chan); + + /* + * MMCI monitors both MCI_DATAEND and the DMA callback. + * Both events must occur before the transfer is considered + * to be completed. MCI_DATABLOCKEND is not used in DMA mode. + */ + host->last_blockend = true; + irqmask0 = readl(host->base + MMCIMASK0); + irqmask0 &= ~MCI_DATABLOCKENDMASK; + writel(irqmask0, host->base + MMCIMASK0); + + /* Trigger the DMA transfer */ + writel(datactrl, host->base + MMCIDATACTRL); + return 0; + +unmap_exit: + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, direction); +map_err: + chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); + return -ENOMEM; +} +#else +/* Blank functions if the DMA engine is not available */ +static inline void mmci_setup_dma(struct mmci_host *host) +{ +} + +static inline void mmci_disable_dma(struct mmci_host *host) +{ +} + +static inline void mmci_dma_data_end(struct mmci_host *host) +{ +} + +static inline void mmci_dma_terminate(struct mmci_host *host) +{ +} + +static inline int mmci_dma_start_data(struct mmci_host *host, + unsigned int datactrl) +{ + return -ENOSYS; +} +#endif + +static void mmci_start_data(struct mmci_host *host, struct mmc_data *data) +{ + struct variant_data *variant = host->variant; + unsigned int datactrl, timeout, irqmask0, irqmask1; + unsigned int clkcycle_ns; + void __iomem *base; + int blksz_bits; + u32 clk; + + dev_dbg(mmc_dev(host->mmc), "blksz %04x blks %04x flags %08x\n", + data->blksz, data->blocks, data->flags); + + host->data = data; + host->size = data->blksz * data->blocks; + host->data_xfered = 0; + host->last_blockend = false; + host->dataend = false; + host->cache_len = 0; + host->cache = 0; + + clkcycle_ns = 1000000000 / host->cclk; + timeout = data->timeout_ns / clkcycle_ns; + timeout += data->timeout_clks; + + if (data->flags & MMC_DATA_READ) { /* - * On the U300 some signal or other is - * badly routed so that a data write does - * not properly terminate with a MCI_DATAEND - * status flag. This quirk will make writes - * work again. + * Since the read command is sent after we have setup + * the data transfer we must increase the data timeout. + * Unfortunately this is not enough since some cards + * does not seem to stick to what is stated in their + * CSD for TAAC and NSAC. */ - if (data->flags & MMC_DATA_WRITE) - status |= MCI_DATAEND; + timeout += dataread_delay_clks; + } + + base = host->base; + writel(timeout, base + MMCIDATATIMER); + writel(host->size, base + MMCIDATALENGTH); + + blksz_bits = ffs(data->blksz) - 1; + +#ifdef CONFIG_ARCH_U8500 + /* Temporary solution for db8500v2. */ + if (cpu_is_u8500v20_or_later()) + datactrl = MCI_DPSM_ENABLE | (data->blksz << 16); + else #endif + datactrl = MCI_DPSM_ENABLE | blksz_bits << 4; + + if (data->flags & MMC_DATA_READ) + datactrl |= MCI_DPSM_DIRECTION; + + if (host->mmc->card && mmc_card_ddr_mode(host->mmc->card)) { + datactrl |= MCI_ST_DPSM_DDRMODE; + + /* Needed for DDR */ + clk = readl(base + MMCICLOCK); + clk |= MCI_NEG_EDGE; + + writel(clk, (base + MMCICLOCK)); + } + + if (variant->sdio && + host->mmc->card && + mmc_card_sdio(host->mmc->card)) { + /* + * The ST Micro variants has a special bit + * to enable SDIO mode. This bit is set the first time + * a SDIO data transfer is done and must remain set + * after the data transfer is completed. The reason is + * because of otherwise no SDIO interrupts can be + * received. + */ + datactrl |= MCI_ST_DPSM_SDIOEN; + + /* + * The ST Micro variant for SDIO transfer sizes + * less than or equal to 8 bytes needs to have clock + * H/W flow control disabled. Since flow control is + * not really needed for anything that fits in the + * FIFO, we can disable it for any write smaller + * than the FIFO size. + */ + if ((host->size <= variant->fifosize) && + (data->flags & MMC_DATA_WRITE)) + writel(readl(host->base + MMCICLOCK) & + ~variant->clkreg_enable, + host->base + MMCICLOCK); + else + writel(readl(host->base + MMCICLOCK) | + variant->clkreg_enable, + host->base + MMCICLOCK); + } + + if (host->dma_enable) { + int ret; + + /* + * Attempt to use DMA operation mode, if this + * should fail, fall back to PIO mode + */ + ret = mmci_dma_start_data(host, datactrl); + if (!ret) + return; + } + + /* IRQ mode, map the SG list for CPU reading/writing */ + mmci_init_sg(host, data); + + if (data->flags & MMC_DATA_READ) { + irqmask1 = MCI_RXFIFOHALFFULLMASK; + + /* + * If we have less than a FIFOSIZE of bytes to + * transfer, trigger a PIO interrupt as soon as any + * data is available. + */ + if (host->size < variant->fifosize) + irqmask1 |= MCI_RXDATAAVLBLMASK; + } else { + /* + * We don't actually need to include "FIFO empty" here + * since its implicit in "FIFO half empty". + */ + irqmask1 = MCI_TXFIFOHALFEMPTYMASK; + } + + /* Setup IRQ */ + irqmask0 = readl(base + MMCIMASK0); + if (variant->broken_blockend) { + host->last_blockend = true; + irqmask0 &= ~MCI_DATABLOCKENDMASK; + } else { + irqmask0 |= MCI_DATABLOCKENDMASK; } - if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) { - dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status); + writel(irqmask0, base + MMCIMASK0); + mmci_set_mask1(host, irqmask1); + + /* Start the data transfer */ + writel(datactrl, base + MMCIDATACTRL); +} + +static void +mmci_data_irq(struct mmci_host *host, struct mmc_data *data, + unsigned int status) +{ + struct variant_data *variant = host->variant; + + /* First check for errors */ + if (status & MCI_DATA_ERR) { + dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", + status); if (status & MCI_DATACRCFAIL) data->error = -EILSEQ; else if (status & MCI_DATATIMEOUT) data->error = -ETIMEDOUT; else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) data->error = -EIO; - status |= MCI_DATAEND; /* * We hit an error condition. Ensure that any data - * partially written to a page is properly coherent. + * partially written to a page is properly coherent, + * unless we're using DMA. */ - if (host->sg_len && data->flags & MMC_DATA_READ) - flush_dcache_page(sg_page(host->sg_ptr)); + if (host->dma_on_current_xfer) + mmci_dma_terminate(host); + else if (data->flags & MMC_DATA_READ) { + struct sg_mapping_iter *sg_miter = &host->sg_miter; + unsigned long flags; + + local_irq_save(flags); + if (sg_miter_next(sg_miter)) { + flush_dcache_page(sg_miter->page); + sg_miter_stop(sg_miter); + } + local_irq_restore(flags); + } } - if (status & MCI_DATAEND) { - mmci_stop_data(host); - if (!data->stop) { - mmci_request_end(host, data->mrq); - } else { - mmci_start_command(host, data->stop, 0); + /* + * On ARM variants in PIO mode, MCI_DATABLOCKEND + * is always sent first, and we increase the + * transfered number of bytes for that IRQ. Then + * MCI_DATAEND follows and we conclude the transaction. + * + * On the Ux500 single-IRQ variant MCI_DATABLOCKEND + * doesn't seem to immediately clear from the status, + * so we can't use it keep count when only one irq is + * used because the irq will hit for other reasons, and + * then the flag is still up. So we use the MCI_DATAEND + * IRQ at the end of the entire transfer because + * MCI_DATABLOCKEND is broken. + * + * In the U300, the IRQs can arrive out-of-order, + * e.g. MCI_DATABLOCKEND sometimes arrives after MCI_DATAEND, + * so for this case we use the flags "last_blockend" and + * "dataend" to make sure both IRQs have arrived before + * concluding the transaction. (This does not apply + * to the Ux500 which doesn't fire MCI_DATABLOCKEND + * at all.) In DMA mode it suffers from the same problem + * as the Ux500. + */ + if (status & MCI_DATABLOCKEND) { + /* + * Just being a little over-cautious, we do not + * use this progressive update if the hardware blockend + * flag is unreliable: since it can stay high between + * IRQs it will corrupt the transfer counter. + */ + if (!variant->broken_blockend && !host->dma_on_current_xfer) { + host->data_xfered += data->blksz; + + if (host->data_xfered == data->blksz * data->blocks) + host->last_blockend = true; } } + + if (status & MCI_DATAEND) + host->dataend = true; + + /* + * On variants with broken blockend we shall only wait for dataend, + * on others we must sync with the blockend signal since they can + * appear out-of-order. + */ + if ((host->dataend && host->last_blockend) || data->error) + mmci_complete_data_xfer(host); } static void @@ -237,22 +891,24 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd, cmd->resp[2] = readl(base + MMCIRESPONSE2); cmd->resp[3] = readl(base + MMCIRESPONSE3); - if (status & MCI_CMDTIMEOUT) { + if (status & MCI_CMDTIMEOUT) cmd->error = -ETIMEDOUT; - } else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) { + else if (status & MCI_CMDCRCFAIL && cmd->flags & MMC_RSP_CRC) cmd->error = -EILSEQ; - } if (!cmd->data || cmd->error) { - if (host->data) + if (host->data) { + if (host->dma_on_current_xfer) + mmci_dma_terminate(host); mmci_stop_data(host); + } mmci_request_end(host, cmd->mrq); - } else if (!(cmd->data->flags & MMC_DATA_READ)) { + } else if (!(cmd->data->flags & MMC_DATA_READ)) mmci_start_data(host, cmd->data); - } } -static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int remain) +static int mmci_pio_read(struct mmci_host *host, char *buffer, + unsigned int remain) { void __iomem *base = host->base; char *ptr = buffer; @@ -268,7 +924,24 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema if (count <= 0) break; - readsl(base + MMCIFIFO, ptr, count >> 2); + /* + * SDIO especially may want to receive something that is + * not divisible by 4 (as opposed to card sectors + * etc). Therefore make sure we always read the last bytes + * out of the FIFO. + */ + switch (count) { + case 1: + case 3: + readsb(base + MMCIFIFO, ptr, count); + break; + case 2: + readsw(base + MMCIFIFO, ptr, 1); + break; + default: + readsl(base + MMCIFIFO, ptr, count >> 2); + break; + } ptr += count; remain -= count; @@ -283,21 +956,96 @@ static int mmci_pio_read(struct mmci_host *host, char *buffer, unsigned int rema return ptr - buffer; } -static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int remain, u32 status) +static int mmci_pio_write(struct mmci_host *host, char *buffer, + unsigned int remain, u32 status) { + struct variant_data *variant = host->variant; void __iomem *base = host->base; char *ptr = buffer; + unsigned int data_left = host->size; + unsigned int count, maxcnt; + char *cache_ptr; + int i; + do { - unsigned int count, maxcnt; + maxcnt = status & MCI_TXFIFOEMPTY ? + variant->fifosize : variant->fifohalfsize; + + /* + * A write to the FIFO must always be done of 4 bytes aligned + * data. If the buffer is not 4 bytes aligned we must pad the + * data, but this must only be done for the final write for the + * entire data transfer, otherwise we will corrupt the data. + * Thus a buffer cache of four bytes is needed to temporary + * store data. + */ + + if (host->cache_len) { + cache_ptr = (char *)&host->cache; + cache_ptr = cache_ptr + host->cache_len; + data_left += host->cache_len; + + while ((host->cache_len < 4) && (remain > 0)) { + *cache_ptr = *ptr; + cache_ptr++; + ptr++; + host->cache_len++; + remain--; + } + + if ((host->cache_len == 4) || + (data_left == host->cache_len)) { + + writesl(base + MMCIFIFO, &host->cache, 1); + if (data_left == host->cache_len) + break; + + host->cache = 0; + host->cache_len = 0; + maxcnt -= 4; + data_left -= 4; + } + + if (remain == 0) + break; + } - maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : MCI_FIFOHALFSIZE; count = min(remain, maxcnt); - writesl(base + MMCIFIFO, ptr, count >> 2); + if (!(count % 4) || (data_left == count)) { + /* + * The data is either 4-bytes aligned or it is the + * last data to write. It is thus fine to potentially + * pad the data if needed. + */ + writesl(base + MMCIFIFO, ptr, (count + 3) >> 2); + ptr += count; + remain -= count; + data_left -= count; - ptr += count; - remain -= count; + } else { + + host->cache_len = count % 4; + count = (count >> 2) << 2; + + if (count) + writesl(base + MMCIFIFO, ptr, count >> 2); + + ptr += count; + remain -= count; + data_left -= count; + + i = 0; + cache_ptr = (char *)&host->cache; + while (i < host->cache_len) { + *cache_ptr = *ptr; + cache_ptr++; + ptr++; + remain--; + i++; + } + } if (remain == 0) break; @@ -314,15 +1062,19 @@ static int mmci_pio_write(struct mmci_host *host, char *buffer, unsigned int rem static irqreturn_t mmci_pio_irq(int irq, void *dev_id) { struct mmci_host *host = dev_id; + struct sg_mapping_iter *sg_miter = &host->sg_miter; + struct variant_data *variant = host->variant; void __iomem *base = host->base; + unsigned long flags; u32 status; status = readl(base + MMCISTATUS); dev_dbg(mmc_dev(host->mmc), "irq1 (pio) %08x\n", status); + local_irq_save(flags); + do { - unsigned long flags; unsigned int remain, len; char *buffer; @@ -336,11 +1088,11 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) if (!(status & (MCI_TXFIFOHALFEMPTY|MCI_RXDATAAVLBL))) break; - /* - * Map the current scatter buffer. - */ - buffer = mmci_kmap_atomic(host, &flags) + host->sg_off; - remain = host->sg_ptr->length - host->sg_off; + if (!sg_miter_next(sg_miter)) + break; + + buffer = sg_miter->addr; + remain = sg_miter->length; len = 0; if (status & MCI_RXACTIVE) @@ -348,47 +1100,42 @@ static irqreturn_t mmci_pio_irq(int irq, void *dev_id) if (status & MCI_TXACTIVE) len = mmci_pio_write(host, buffer, remain, status); - /* - * Unmap the buffer. - */ - mmci_kunmap_atomic(host, buffer, &flags); + sg_miter->consumed = len; - host->sg_off += len; host->size -= len; remain -= len; if (remain) break; - /* - * If we were reading, and we have completed this - * page, ensure that the data cache is coherent. - */ if (status & MCI_RXACTIVE) - flush_dcache_page(sg_page(host->sg_ptr)); - - if (!mmci_next_sg(host)) - break; + flush_dcache_page(sg_miter->page); status = readl(base + MMCISTATUS); } while (1); + sg_miter_stop(sg_miter); + + local_irq_restore(flags); + /* * If we're nearing the end of the read, switch to * "any data available" mode. */ - if (status & MCI_RXACTIVE && host->size < MCI_FIFOSIZE) - writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); + if (status & MCI_RXACTIVE && host->size < variant->fifosize) + mmci_set_mask1(host, MCI_RXDATAAVLBLMASK); - /* - * If we run out of data, disable the data IRQs; this - * prevents a race where the FIFO becomes empty before - * the chip itself has disabled the data path, and - * stops us racing with our data end IRQ. - */ + /* If we run out of data, disable the data IRQs. */ if (host->size == 0) { - writel(0, base + MMCIMASK1); - writel(readl(base + MMCIMASK0) | MCI_DATAENDMASK, base + MMCIMASK0); + mmci_set_mask1(host, 0); + + /* + * If we already received MCI_DATAEND and the last + * MCI_DATABLOCKEND, the entire data transfer shall + * be completed. + */ + if (host->dataend && host->last_blockend) + mmci_complete_data_xfer(host); } return IRQ_HANDLED; @@ -401,6 +1148,7 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) { struct mmci_host *host = dev_id; u32 status; + int sdio_irq = 0; int ret = 0; spin_lock(&host->lock); @@ -410,18 +1158,28 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) struct mmc_data *data; status = readl(host->base + MMCISTATUS); + + if (host->singleirq) { + if (status & readl(host->base + MMCIMASK1)) + mmci_pio_irq(irq, dev_id); + + status &= ~MCI_IRQ1MASK; + } + status &= readl(host->base + MMCIMASK0); writel(status, host->base + MMCICLEAR); dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); + if (status & MCI_SDIOIT) + sdio_irq = 1; + data = host->data; - if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN| - MCI_RXOVERRUN|MCI_DATAEND|MCI_DATABLOCKEND) && data) + if (status & MCI_DATA_IRQ && data) mmci_data_irq(host, data, status); cmd = host->cmd; - if (status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT|MCI_CMDSENT|MCI_CMDRESPEND) && cmd) + if (status & MCI_CMD_IRQ && cmd) mmci_cmd_irq(host, cmd, status); ret = 1; @@ -429,17 +1187,27 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) spin_unlock(&host->lock); + if (sdio_irq) + mmc_signal_sdio_irq(host->mmc); + return IRQ_RETVAL(ret); } static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct mmci_host *host = mmc_priv(mmc); + struct variant_data *variant = host->variant; unsigned long flags; WARN_ON(host->mrq != NULL); - if (mrq->data && !is_power_of_2(mrq->data->blksz)) { + if (mrq->data && + (!variant->non_power_of_2_blksize || +#ifdef CONFIG_ARCH_U8500 + !cpu_is_u8500v20_or_later() || +#endif + (mmc->card && mmc_card_ddr_mode(mmc->card))) && + !is_power_of_2(mrq->data->blksz)) { dev_err(mmc_dev(mmc), "unsupported block size (%d bytes)\n", mrq->data->blksz); mrq->cmd->error = -EINVAL; @@ -462,41 +1230,81 @@ static void mmci_request(struct mmc_host *mmc, struct mmc_request *mrq) static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct mmci_host *host = mmc_priv(mmc); + struct variant_data *variant = host->variant; u32 pwr = 0; unsigned long flags; + int ret; + + if (host->plat->vdd_handler) + host->plat->vdd_handler(mmc_dev(mmc), ios->vdd, + ios->power_mode); switch (ios->power_mode) { case MMC_POWER_OFF: - if(host->vcc && - regulator_is_enabled(host->vcc)) - regulator_disable(host->vcc); + if (host->vcard) + ret = mmc_regulator_set_ocr(mmc, host->vcard, 0); break; case MMC_POWER_UP: -#ifdef CONFIG_REGULATOR - if (host->vcc) - /* This implicitly enables the regulator */ - mmc_regulator_set_ocr(host->vcc, ios->vdd); -#endif + if (host->vcard) { + ret = mmc_regulator_set_ocr(mmc, host->vcard, ios->vdd); + if (ret) { + dev_err(mmc_dev(mmc), "unable to set OCR\n"); + /* + * The .set_ios() function in the mmc_host_ops + * struct return void, and failing to set the + * power should be rare so we print an error + * and return here. + */ + return; + } + } + /* - * The translate_vdd function is not used if you have - * an external regulator, or your design is really weird. - * Using it would mean sending in power control BOTH using - * a regulator AND the 4 MMCIPWR bits. If we don't have - * a regulator, we might have some other platform specific - * power control behind this translate function. + * The ST Micro variant doesn't have the PL180s MCI_PWR_UP + * and instead uses MCI_PWR_ON so apply whatever value is + * configured in the variant data. */ - if (!host->vcc && host->plat->translate_vdd) - pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd); - /* The ST version does not have this, fall through to POWER_ON */ - if (host->hw_designer != AMBA_VENDOR_ST) { - pwr |= MCI_PWR_UP; - break; - } + pwr |= variant->pwrreg_powerup; + + break; case MMC_POWER_ON: pwr |= MCI_PWR_ON; break; } + if (variant->signal_direction && ios->power_mode != MMC_POWER_OFF) { + /* + * The ST Micro variant has some additional bits + * indicating signal direction for the signals in + * the SD/MMC bus and feedback-clock usage. The + * fall-throughs in the code below are intentional. + */ + + if (host->plat->sigdir & MMCI_ST_DIRFBCLK) + pwr |= MCI_ST_FBCLKEN; + if (host->plat->sigdir & MMCI_ST_DIRCMD) + pwr |= MCI_ST_CMDDIREN; + + switch (ios->bus_width) { + case MMC_BUS_WIDTH_8: + if (host->plat->sigdir & MMCI_ST_DIRDAT74) + pwr |= MCI_ST_DATA74DIREN; + case MMC_BUS_WIDTH_4: + if (host->plat->sigdir & MMCI_ST_DIRDAT31) + pwr |= MCI_ST_DATA31DIREN; + if (host->plat->sigdir & MMCI_ST_DIRDAT2) + pwr |= MCI_ST_DATA2DIREN; + case MMC_BUS_WIDTH_1: + if (host->plat->sigdir & MMCI_ST_DIRDAT0) + pwr |= MCI_ST_DATA0DIREN; + break; + default: + dev_err(mmc_dev(mmc), "unsupported MMC bus width %d\n", + ios->bus_width); + break; + } + } + if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) { if (host->hw_designer != AMBA_VENDOR_ST) pwr |= MCI_ROD; @@ -505,7 +1313,8 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) * The ST Micro variant use the ROD bit for something * else and only has OD (Open Drain). */ - pwr |= MCI_OD; + if (mmc->card && (mmc->card->type == MMC_TYPE_MMC)) + pwr |= MCI_OD; } } @@ -528,18 +1337,23 @@ static int mmci_get_ro(struct mmc_host *mmc) if (host->gpio_wp == -ENOSYS) return -ENOSYS; - return gpio_get_value(host->gpio_wp); + return gpio_get_value_cansleep(host->gpio_wp); } static int mmci_get_cd(struct mmc_host *mmc) { struct mmci_host *host = mmc_priv(mmc); + struct mmci_platform_data *plat = host->plat; unsigned int status; - if (host->gpio_cd == -ENOSYS) - status = host->plat->status(mmc_dev(host->mmc)); - else - status = !gpio_get_value(host->gpio_cd); + if (host->gpio_cd == -ENOSYS) { + if (!plat->status) + return 1; /* Assume always present */ + + status = plat->status(mmc_dev(host->mmc)); + } else + status = !!gpio_get_value_cansleep(host->gpio_cd) + ^ plat->cd_invert; /* * Use positive logic throughout - status is zero for no card, @@ -548,28 +1362,156 @@ static int mmci_get_cd(struct mmc_host *mmc) return status; } +#ifdef CONFIG_PM +static int mmci_enable(struct mmc_host *mmc) +{ + unsigned long flags; + struct mmci_host *host = mmc_priv(mmc); + int ret = 0; + + clk_enable(host->clk); + if (host->vcc) { + ret = regulator_enable(host->vcc); + if (ret) { + dev_err(mmc_dev(host->mmc), + "failed to enable regulator %s\n", + host->plat->vcc); + return ret; + } + } + + if (pm_runtime_get_sync(mmc->parent) < 0) + dev_err(mmc_dev(mmc), "failed pm_runtime_get_sync\n"); + + spin_lock_irqsave(&host->lock, flags); + + /* Restore registers for POWER, CLOCK and IRQMASK0 */ + writel(host->clk_reg, host->base + MMCICLOCK); + writel(host->pwr_reg, host->base + MMCIPOWER); + writel(host->irqmask0_reg, host->base + MMCIMASK0); + + if (host->variant->sdio && + host->mmc->card && + mmc_card_sdio(host->mmc->card)) { + /* + * The ST Micro variants has a special bit in the DATACTRL + * register to enable SDIO mode. This bit must be set otherwise + * no SDIO interrupts can be received. + */ + writel(MCI_ST_DPSM_SDIOEN, host->base + MMCIDATACTRL); + } + + spin_unlock_irqrestore(&host->lock, flags); + + /* Restore settings done by the vdd_handler. */ + if (host->plat->vdd_handler) + host->plat->vdd_handler(mmc_dev(mmc), + mmc->ios.vdd, + mmc->ios.power_mode); + + /* + * To be able to handle specific wake up scenarios for each host, + * the following function shall be implemented. + */ + if (host->plat->wakeup_handler) + host->plat->wakeup_handler(host->mmc, true); + + return ret; +} + +static int mmci_disable(struct mmc_host *mmc, int lazy) +{ + unsigned long flags; + struct mmci_host *host = mmc_priv(mmc); + + /* + * To be able to handle specific shutdown scenarios for each host, + * the following function shall be implemented. + */ + if (host->plat->wakeup_handler) + host->plat->wakeup_handler(host->mmc, false); + + /* + * Let the vdd_handler act on a POWER_OFF to potentially do some + * power save actions. + */ + if (host->plat->vdd_handler) + host->plat->vdd_handler(mmc_dev(mmc), 0, MMC_POWER_OFF); + + spin_lock_irqsave(&host->lock, flags); + + /* Save registers for POWER, CLOCK and IRQMASK0 */ + host->irqmask0_reg = readl(host->base + MMCIMASK0); + host->pwr_reg = readl(host->base + MMCIPOWER); + host->clk_reg = readl(host->base + MMCICLOCK); + + /* + * Make sure we do not get any interrupts when we disabled the + * clock and the regulator and as well make sure to clear the + * registers for clock and power. + */ + writel(0, host->base + MMCIMASK0); + writel(0, host->base + MMCIPOWER); + writel(0, host->base + MMCICLOCK); + + spin_unlock_irqrestore(&host->lock, flags); + + if (pm_runtime_put_sync(mmc->parent) < 0) + dev_err(mmc_dev(mmc), "failed pm_runtime_put_sync\n"); + + clk_disable(host->clk); + if (host->vcc) { + regulator_disable(host->vcc); + } + + return 0; +} +#else +#define mmci_enable NULL +#define mmci_disable NULL +#endif + +static irqreturn_t mmci_cd_irq(int irq, void *dev_id) +{ + struct mmci_host *host = dev_id; + + mmc_detect_change(host->mmc, msecs_to_jiffies(500)); + + return IRQ_HANDLED; +} + +static void mmci_enable_sdio_irq(struct mmc_host *mmc, int enable) +{ + unsigned long flags; + unsigned int mask0; + struct mmci_host *host = mmc_priv(mmc); + + spin_lock_irqsave(&host->lock, flags); + + mask0 = readl(host->base + MMCIMASK0); + if (enable) + mask0 |= MCI_SDIOIT; + else + mask0 &= ~MCI_SDIOIT; + writel(mask0, host->base + MMCIMASK0); + + spin_unlock_irqrestore(&host->lock, flags); +} + static const struct mmc_host_ops mmci_ops = { .request = mmci_request, .set_ios = mmci_set_ios, .get_ro = mmci_get_ro, .get_cd = mmci_get_cd, + .enable = mmci_enable, + .disable = mmci_disable, + .enable_sdio_irq = mmci_enable_sdio_irq, }; -static void mmci_check_status(unsigned long data) -{ - struct mmci_host *host = (struct mmci_host *)data; - unsigned int status = mmci_get_cd(host->mmc); - - if (status ^ host->oldstat) - mmc_detect_change(host->mmc, 0); - - host->oldstat = status; - mod_timer(&host->timer, jiffies + HZ); -} - static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) { struct mmci_platform_data *plat = dev->dev.platform_data; + struct variant_data *variant = id->data; struct mmci_host *host; struct mmc_host *mmc; int ret; @@ -592,9 +1534,16 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) host = mmc_priv(mmc); host->mmc = mmc; + host->plat = plat; + host->variant = variant; host->gpio_wp = -ENOSYS; host->gpio_cd = -ENOSYS; + host->gpio_cd_irq = -1; + + host->irqmask0_reg = 0; + host->pwr_reg = 0; + host->clk_reg = 0; host->hw_designer = amba_manf(dev); host->hw_revision = amba_rev(dev); @@ -608,11 +1557,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) goto host_free; } - ret = clk_enable(host->clk); - if (ret) - goto clk_free; - - host->plat = plat; host->mclk = clk_get_rate(host->clk); /* * According to the spec, mclk is max 100 MHz, @@ -622,15 +1566,16 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) if (host->mclk > 100000000) { ret = clk_set_rate(host->clk, 100000000); if (ret < 0) - goto clk_disable; + goto clk_free; host->mclk = clk_get_rate(host->clk); dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n", host->mclk); } + host->phybase = dev->res.start; host->base = ioremap(dev->res.start, resource_size(&dev->res)); if (!host->base) { ret = -ENOMEM; - goto clk_disable; + goto clk_free; } mmc->ops = &mmci_ops; @@ -649,14 +1594,31 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) mmc->f_max = min(host->mclk, fmax); dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); -#ifdef CONFIG_REGULATOR - /* If we're using the regulator framework, try to fetch a regulator */ - host->vcc = regulator_get(&dev->dev, "vmmc"); - if (IS_ERR(host->vcc)) - host->vcc = NULL; - else { - int mask = mmc_regulator_get_ocrmask(host->vcc); + /* Host regulator */ + if (plat->vcc) { + host->vcc = regulator_get(&dev->dev, plat->vcc); + ret = IS_ERR(host->vcc); + if (ret) { + host->vcc = NULL; + goto clk_free; + } + dev_dbg(mmc_dev(host->mmc), "fetched regulator %s\n", + plat->vcc); + } + /* Card regulator (could be a level shifter) */ + if (plat->vcard) { + int mask; + host->vcard = regulator_get(&dev->dev, plat->vcard); + ret = IS_ERR(host->vcard); + if (ret) { + host->vcard = NULL; + goto vcc_free; + } + dev_dbg(mmc_dev(host->mmc), "fetched regulator %s\n", + plat->vcard); + + mask = mmc_regulator_get_ocrmask(host->vcard); if (mask < 0) dev_err(&dev->dev, "error getting OCR mask (%d)\n", mask); @@ -667,30 +1629,42 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) "Provided ocr_mask/setpower will not be used " "(using regulator instead)\n"); } - } -#endif - /* Fall back to platform data if no regulator is found */ - if (host->vcc == NULL) + + } else { + /* Use platform data if no regulator for vcard is used */ mmc->ocr_avail = plat->ocr_mask; + } + + /* Use platform capabilities */ mmc->caps = plat->capabilities; + /* Set disable timeout if supported */ + if (mmc->caps & MMC_CAP_DISABLE) + mmc_set_disable_delay(mmc, plat->disable); + + /* We support these PM capabilities. */ + mmc->pm_caps = MMC_PM_KEEP_POWER; + /* * We can do SGIO */ - mmc->max_hw_segs = 16; - mmc->max_phys_segs = NR_SG; + mmc->max_segs = NR_SG; /* - * Since we only have a 16-bit data length register, we must - * ensure that we don't exceed 2^16-1 bytes in a single request. + * Since only a certain number of bits are valid in the data length + * register, we must ensure that we don't exceed 2^num-1 bytes in a + * single request. */ - mmc->max_req_size = 65535; + mmc->max_req_size = (1 << variant->datalength_bits) - 1; /* - * Set the maximum segment size. Since we aren't doing DMA - * (yet) we are only limited by the data length register. + * Set the maximum segment size. Right now DMA sets the + * limit and not the data length register. Thus until the DMA + * driver not handles this, the segment size is limited by DMA. + * DMA limit: src_addr_width x (64 KB -1). src_addr_width + * can be 1. */ - mmc->max_seg_size = mmc->max_req_size; + mmc->max_seg_size = 65535; /* * Block size can be up to 2048 bytes, but must be a power of two. @@ -704,10 +1678,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) spin_lock_init(&host->lock); - writel(0, host->base + MMCIMASK0); - writel(0, host->base + MMCIMASK1); - writel(0xfff, host->base + MMCICLEAR); - if (gpio_is_valid(plat->gpio_cd)) { ret = gpio_request(plat->gpio_cd, DRIVER_NAME " (cd)"); if (ret == 0) @@ -716,6 +1686,13 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) host->gpio_cd = plat->gpio_cd; else if (ret != -ENOSYS) goto err_gpio_cd; + + ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd), + mmci_cd_irq, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + DRIVER_NAME " (cd)", host); + if (ret >= 0) + host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd); } if (gpio_is_valid(plat->gpio_wp)) { ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)"); @@ -727,45 +1704,70 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) goto err_gpio_wp; } - ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host); + if ((host->plat->status || host->gpio_cd != -ENOSYS) + && host->gpio_cd_irq < 0) + mmc->caps |= MMC_CAP_NEEDS_POLL; + + mmci_setup_dma(host); + + ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, + DRIVER_NAME " (cmd)", host); if (ret) goto unmap; - ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, DRIVER_NAME " (pio)", host); - if (ret) - goto irq0_free; + if (dev->irq[1] == NO_IRQ) + host->singleirq = true; + else { + ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED, + DRIVER_NAME " (pio)", host); + if (ret) + goto irq0_free; + } - writel(MCI_IRQENABLE, host->base + MMCIMASK0); + /* Prepare IRQMASK0 */ + host->irqmask0_reg = MCI_IRQENABLE; + if (host->variant->broken_blockend) + host->irqmask0_reg &= ~MCI_DATABLOCKEND; amba_set_drvdata(dev, mmc); - host->oldstat = mmci_get_cd(host->mmc); + + pm_runtime_enable(mmc->parent); + if (pm_runtime_get_sync(mmc->parent) < 0) + dev_err(mmc_dev(mmc), "failed pm_runtime_get_sync\n"); + if (pm_runtime_put_sync(mmc->parent) < 0) + dev_err(mmc_dev(mmc), "failed pm_runtime_put_sync\n"); mmc_add_host(mmc); - dev_info(&dev->dev, "%s: MMCI rev %x cfg %02x at 0x%016llx irq %d,%d\n", - mmc_hostname(mmc), amba_rev(dev), amba_config(dev), - (unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]); + dev_info(&dev->dev, + "%s: MMCI/PL180 manf %x rev %x cfg %02x at 0x%016llx\n", + mmc_hostname(mmc), amba_manf(dev), amba_rev(dev), + amba_config(dev), (unsigned long long)dev->res.start); + dev_info(&dev->dev, "IRQ %d, %d (pio)\n", dev->irq[0], dev->irq[1]); - init_timer(&host->timer); - host->timer.data = (unsigned long)host; - host->timer.function = mmci_check_status; - host->timer.expires = jiffies + HZ; - add_timer(&host->timer); + /* Ugly hack for u8500_sdio_detect_card, to be removed soon. */ + sdio_host_ptr = host; + + mmci_debugfs_create(host); return 0; irq0_free: free_irq(dev->irq[0], host); unmap: + mmci_disable_dma(host); if (host->gpio_wp != -ENOSYS) gpio_free(host->gpio_wp); err_gpio_wp: + if (host->gpio_cd_irq >= 0) + free_irq(host->gpio_cd_irq, host); if (host->gpio_cd != -ENOSYS) gpio_free(host->gpio_cd); err_gpio_cd: iounmap(host->base); - clk_disable: - clk_disable(host->clk); + vcc_free: + if (host->vcc) + regulator_put(host->vcc); clk_free: clk_put(host->clk); host_free: @@ -785,8 +1787,12 @@ static int __devexit mmci_remove(struct amba_device *dev) if (mmc) { struct mmci_host *host = mmc_priv(mmc); - del_timer_sync(&host->timer); + pm_runtime_disable(mmc->parent); + if (host->vcc) + regulator_enable(host->vcc); + + mmci_debugfs_remove(host); mmc_remove_host(mmc); writel(0, host->base + MMCIMASK0); @@ -795,11 +1801,15 @@ static int __devexit mmci_remove(struct amba_device *dev) writel(0, host->base + MMCICOMMAND); writel(0, host->base + MMCIDATACTRL); + mmci_disable_dma(host); free_irq(dev->irq[0], host); - free_irq(dev->irq[1], host); + if (!host->singleirq) + free_irq(dev->irq[1], host); if (host->gpio_wp != -ENOSYS) gpio_free(host->gpio_wp); + if (host->gpio_cd_irq >= 0) + free_irq(host->gpio_cd_irq, host); if (host->gpio_cd != -ENOSYS) gpio_free(host->gpio_cd); @@ -807,9 +1817,15 @@ static int __devexit mmci_remove(struct amba_device *dev) clk_disable(host->clk); clk_put(host->clk); - if (regulator_is_enabled(host->vcc)) + if (host->vcc) { regulator_disable(host->vcc); - regulator_put(host->vcc); + regulator_put(host->vcc); + } + + if (host->vcard) { + mmc_regulator_set_ocr(mmc, host->vcard, 0); + regulator_put(host->vcard); + } mmc_free_host(mmc); @@ -826,11 +1842,38 @@ static int mmci_suspend(struct amba_device *dev, pm_message_t state) int ret = 0; if (mmc) { - struct mmci_host *host = mmc_priv(mmc); + /* + * The host must be claimed to prevent request handling etc. + * Also make sure to not sleep, since we must return with a + * response quite quickly. + */ + if (mmc_try_claim_host(mmc)) { + struct mmci_host *host = mmc_priv(mmc); + + if (mmc->enabled) { + /* + * Do not suspend if the host has not been + * disabled. + */ + mmc_do_release_host(mmc); + ret = -EBUSY; + } else if ((!(host->plat->pm_flags & MMC_PM_KEEP_POWER)) + && (!(mmc->pm_flags & MMC_PM_KEEP_POWER))) { + /* Cut the power to the card to save current. */ + mmc_host_enable(mmc); + mmc_power_save_host(mmc); + mmc_host_disable(mmc); + host->pwr_reg = 0; + host->clk_reg = 0; + } - ret = mmc_suspend_host(mmc); - if (ret == 0) - writel(0, host->base + MMCIMASK0); + } else { + /* + * We did not manage to claim the host, thus someone + * is still using it. Do not suspend. + */ + ret = -EBUSY; + } } return ret; @@ -839,17 +1882,26 @@ static int mmci_suspend(struct amba_device *dev, pm_message_t state) static int mmci_resume(struct amba_device *dev) { struct mmc_host *mmc = amba_get_drvdata(dev); - int ret = 0; if (mmc) { struct mmci_host *host = mmc_priv(mmc); - writel(MCI_IRQENABLE, host->base + MMCIMASK0); + /* We expect the host to be claimed. */ + WARN_ON(!mmc->claimed); - ret = mmc_resume_host(mmc); + /* Restore power and re-initialize the card. */ + if ((!(host->plat->pm_flags & MMC_PM_KEEP_POWER)) && + (!(mmc->pm_flags & MMC_PM_KEEP_POWER))) { + mmc_host_enable(mmc); + mmc_power_restore_host(mmc); + mmc_host_disable(mmc); + } + + /* Release the host to provide access to it again. */ + mmc_do_release_host(mmc); } - return ret; + return 0; } #else #define mmci_suspend NULL @@ -860,19 +1912,28 @@ static struct amba_id mmci_ids[] = { { .id = 0x00041180, .mask = 0x000fffff, + .data = &variant_arm, }, { .id = 0x00041181, .mask = 0x000fffff, + .data = &variant_arm, }, /* ST Micro variants */ { .id = 0x00180180, .mask = 0x00ffffff, + .data = &variant_u300, }, { .id = 0x00280180, .mask = 0x00ffffff, + .data = &variant_u300, + }, + { + .id = 0x00480180, + .mask = 0x00ffffff, + .data = &variant_ux500, }, { 0, 0 }, }; diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index d77062e5e3a..87d35cc1fea 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h @@ -11,15 +11,15 @@ #define MCI_PWR_OFF 0x00 #define MCI_PWR_UP 0x02 #define MCI_PWR_ON 0x03 -#define MCI_DATA2DIREN (1 << 2) -#define MCI_CMDDIREN (1 << 3) -#define MCI_DATA0DIREN (1 << 4) -#define MCI_DATA31DIREN (1 << 5) +#define MCI_ST_DATA2DIREN (1 << 2) +#define MCI_ST_CMDDIREN (1 << 3) +#define MCI_ST_DATA0DIREN (1 << 4) +#define MCI_ST_DATA31DIREN (1 << 5) #define MCI_OD (1 << 6) #define MCI_ROD (1 << 7) /* The ST Micro version does not have ROD */ -#define MCI_FBCLKEN (1 << 7) -#define MCI_DATA74DIREN (1 << 8) +#define MCI_ST_FBCLKEN (1 << 7) +#define MCI_ST_DATA74DIREN (1 << 8) #define MMCICLOCK 0x004 #define MCI_CLK_ENABLE (1 << 8) @@ -28,8 +28,8 @@ #define MCI_4BIT_BUS (1 << 11) /* 8bit wide buses supported in ST Micro versions */ #define MCI_ST_8BIT_BUS (1 << 12) -/* HW flow control on the ST Micro version */ -#define MCI_ST_FCEN (1 << 13) +#define MCI_NEG_EDGE (1 << 13) +#define MCI_CLK_INV (1 << 15) #define MMCIARGUMENT 0x008 #define MMCICOMMAND 0x00c @@ -56,10 +56,16 @@ #define MCI_DPSM_MODE (1 << 2) #define MCI_DPSM_DMAENABLE (1 << 3) #define MCI_DPSM_BLOCKSIZE (1 << 4) -#define MCI_DPSM_RWSTART (1 << 8) -#define MCI_DPSM_RWSTOP (1 << 9) -#define MCI_DPSM_RWMOD (1 << 10) -#define MCI_DPSM_SDIOEN (1 << 11) +/* Control register extensions in the ST Micro U300 and Ux500 versions */ +#define MCI_ST_DPSM_RWSTART (1 << 8) +#define MCI_ST_DPSM_RWSTOP (1 << 9) +#define MCI_ST_DPSM_RWMOD (1 << 10) +#define MCI_ST_DPSM_SDIOEN (1 << 11) +/* Control register extensions in the ST Micro Ux500 versions */ +#define MCI_ST_DPSM_DMAREQCTL (1 << 12) +#define MCI_ST_DPSM_DBOOTMODEEN (1 << 13) +#define MCI_ST_DPSM_BUSYMODE (1 << 14) +#define MCI_ST_DPSM_DDRMODE (1 << 15) #define MMCIDATACNT 0x030 #define MMCISTATUS 0x034 @@ -133,20 +139,28 @@ #define MCI_IRQENABLE \ (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ - MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK) + MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK) -/* - * The size of the FIFO in bytes. - */ -#define MCI_FIFOSIZE (16*4) - -#define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2) +#define MCI_DATA_ERR \ + (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN) +#define MCI_DATA_IRQ (MCI_DATA_ERR|MCI_DATAEND|MCI_DATABLOCKEND) +#define MCI_CMD_ERR (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT) +#define MCI_CMD_IRQ (MCI_CMD_ERR|MCI_CMDRESPEND|MCI_CMDSENT) + +/* These interrupts are directed to IRQ1 when two IRQ lines are available */ +#define MCI_IRQ1MASK \ + (MCI_RXFIFOHALFFULLMASK | MCI_RXDATAAVLBLMASK | \ + MCI_TXFIFOHALFEMPTYMASK) -#define NR_SG 16 +#define NR_SG 128 struct clk; +struct variant_data; +struct dma_chan; +struct dma_async_tx_descriptor; struct mmci_host { + phys_addr_t phybase; void __iomem *base; struct mmc_request *mrq; struct mmc_command *cmd; @@ -155,6 +169,8 @@ struct mmci_host { struct clk *clk; int gpio_cd; int gpio_wp; + int gpio_cd_irq; + bool singleirq; unsigned int data_xfered; @@ -164,6 +180,7 @@ struct mmci_host { unsigned int cclk; u32 pwr; struct mmci_platform_data *plat; + struct variant_data *variant; u8 hw_designer; u8 hw_revision:4; @@ -171,42 +188,34 @@ struct mmci_host { struct timer_list timer; unsigned int oldstat; - unsigned int sg_len; + bool last_blockend; + bool dataend; + + /* register cache */ + unsigned int irqmask0_reg; + unsigned int pwr_reg; + unsigned int clk_reg; /* pio stuff */ - struct scatterlist *sg_ptr; - unsigned int sg_off; + struct sg_mapping_iter sg_miter; unsigned int size; + unsigned int cache; + unsigned int cache_len; + struct regulator *vcc; + struct regulator *vcard; + + /* DMA stuff */ + bool dma_enable; + bool dma_on_current_xfer; +#ifdef CONFIG_DMA_ENGINE + struct dma_chan *dma_rx_channel; + struct dma_chan *dma_tx_channel; + struct dma_async_tx_descriptor *dma_desc; +#endif + +#ifdef CONFIG_DEBUG_FS + struct dentry *debug_regs; +#endif }; -static inline void mmci_init_sg(struct mmci_host *host, struct mmc_data *data) -{ - /* - * Ideally, we want the higher levels to pass us a scatter list. - */ - host->sg_len = data->sg_len; - host->sg_ptr = data->sg; - host->sg_off = 0; -} - -static inline int mmci_next_sg(struct mmci_host *host) -{ - host->sg_ptr++; - host->sg_off = 0; - return --host->sg_len; -} - -static inline char *mmci_kmap_atomic(struct mmci_host *host, unsigned long *flags) -{ - struct scatterlist *sg = host->sg_ptr; - - local_irq_save(*flags); - return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; -} - -static inline void mmci_kunmap_atomic(struct mmci_host *host, void *buffer, unsigned long *flags) -{ - kunmap_atomic(buffer, KM_BIO_SRC_IRQ); - local_irq_restore(*flags); -} diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index 24e09454e52..dee02020489 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c @@ -1200,8 +1200,7 @@ msmsdcc_probe(struct platform_device *pdev) mmc->caps |= MMC_CAP_SDIO_IRQ; mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; - mmc->max_phys_segs = NR_SG; - mmc->max_hw_segs = NR_SG; + mmc->max_segs = NR_SG; mmc->max_blk_size = 4096; /* MCI_DATA_CTL BLOCKSIZE up to 4096 */ mmc->max_blk_count = 65536; diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 366eefa77c5..a5bf60e01af 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -742,8 +742,7 @@ static int __init mvsd_probe(struct platform_device *pdev) mmc->max_blk_size = 2048; mmc->max_blk_count = 65535; - mmc->max_hw_segs = 1; - mmc->max_phys_segs = 1; + mmc->max_segs = 1; mmc->max_seg_size = mmc->max_blk_size * mmc->max_blk_count; mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index d9d4a72e0ec..6feec7f5172 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c @@ -786,8 +786,7 @@ static int mxcmci_probe(struct platform_device *pdev) mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; /* MMC core transfer sizes tunable parameters */ - mmc->max_hw_segs = 64; - mmc->max_phys_segs = 64; + mmc->max_segs = 64; mmc->max_blk_size = 2048; mmc->max_blk_count = 65535; mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index d98ddcfac5e..0c7e37f496e 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c @@ -1335,8 +1335,7 @@ static int __init mmc_omap_new_slot(struct mmc_omap_host *host, int id) * NOTE max_seg_size assumption that small blocks aren't * normally used (except e.g. for reading SD registers). */ - mmc->max_phys_segs = 32; - mmc->max_hw_segs = 32; + mmc->max_segs = 32; mmc->max_blk_size = 2048; /* BLEN is 11 bits (+1) */ mmc->max_blk_count = 2048; /* NBLK is 11 bits (+1) */ mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index b032828c612..674269f820c 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -248,9 +248,9 @@ static int omap_hsmmc_1_set_power(struct device *dev, int slot, int power_on, mmc_slot(host).before_set_reg(dev, slot, power_on, vdd); if (power_on) - ret = mmc_regulator_set_ocr(host->vcc, vdd); + ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); else - ret = mmc_regulator_set_ocr(host->vcc, 0); + ret = mmc_regulator_set_ocr(host->mmc, host->vcc, 0); if (mmc_slot(host).after_set_reg) mmc_slot(host).after_set_reg(dev, slot, power_on, vdd); @@ -289,18 +289,23 @@ static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on, * chips/cards need an interface voltage rail too. */ if (power_on) { - ret = mmc_regulator_set_ocr(host->vcc, vdd); + ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); /* Enable interface voltage rail, if needed */ if (ret == 0 && host->vcc_aux) { ret = regulator_enable(host->vcc_aux); if (ret < 0) - ret = mmc_regulator_set_ocr(host->vcc, 0); + ret = mmc_regulator_set_ocr(host->mmc, + host->vcc, 0); } } else { + /* Shut down the rail */ if (host->vcc_aux) ret = regulator_disable(host->vcc_aux); - if (ret == 0) - ret = mmc_regulator_set_ocr(host->vcc, 0); + if (!ret) { + /* Then proceed to shut down the local regulator */ + ret = mmc_regulator_set_ocr(host->mmc, + host->vcc, 0); + } } if (mmc_slot(host).after_set_reg) @@ -341,9 +346,9 @@ static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep, if (cardsleep) { /* VCC can be turned off if card is asleep */ if (sleep) - err = mmc_regulator_set_ocr(host->vcc, 0); + err = mmc_regulator_set_ocr(host->mmc, host->vcc, 0); else - err = mmc_regulator_set_ocr(host->vcc, vdd); + err = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); } else err = regulator_set_mode(host->vcc, mode); if (err) @@ -2085,8 +2090,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) /* Since we do only SG emulation, we can have as many segs * as we want. */ - mmc->max_phys_segs = 1024; - mmc->max_hw_segs = 1024; + mmc->max_segs = 1024; mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 0a4e43f3714..7257738fd7d 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -99,14 +99,25 @@ static inline void pxamci_init_ocr(struct pxamci_host *host) } } -static inline void pxamci_set_power(struct pxamci_host *host, unsigned int vdd) +static inline int pxamci_set_power(struct pxamci_host *host, + unsigned char power_mode, + unsigned int vdd) { int on; -#ifdef CONFIG_REGULATOR - if (host->vcc) - mmc_regulator_set_ocr(host->vcc, vdd); -#endif + if (host->vcc) { + int ret; + + if (power_mode == MMC_POWER_UP) { + ret = mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); + if (ret) + return ret; + } else if (power_mode == MMC_POWER_OFF) { + ret = mmc_regulator_set_ocr(host->mmc, host->vcc, 0); + if (ret) + return ret; + } + } if (!host->vcc && host->pdata && gpio_is_valid(host->pdata->gpio_power)) { on = ((1 << vdd) & host->pdata->ocr_mask); @@ -115,6 +126,8 @@ static inline void pxamci_set_power(struct pxamci_host *host, unsigned int vdd) } if (!host->vcc && host->pdata && host->pdata->setpower) host->pdata->setpower(mmc_dev(host->mmc), vdd); + + return 0; } static void pxamci_stop_clock(struct pxamci_host *host) @@ -490,9 +503,21 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) } if (host->power_mode != ios->power_mode) { + int ret; + host->power_mode = ios->power_mode; - pxamci_set_power(host, ios->vdd); + ret = pxamci_set_power(host, ios->power_mode, ios->vdd); + if (ret) { + dev_err(mmc_dev(mmc), "unable to set power\n"); + /* + * The .set_ios() function in the mmc_host_ops + * struct return void, and failing to set the + * power should be rare so we print an error and + * return here. + */ + return; + } if (ios->power_mode == MMC_POWER_ON) host->cmdat |= CMDAT_INIT; @@ -503,8 +528,8 @@ static void pxamci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) else host->cmdat &= ~CMDAT_SD_4DAT; - pr_debug("PXAMCI: clkrt = %x cmdat = %x\n", - host->clkrt, host->cmdat); + dev_dbg(mmc_dev(mmc), "PXAMCI: clkrt = %x cmdat = %x\n", + host->clkrt, host->cmdat); } static void pxamci_enable_sdio_irq(struct mmc_host *host, int enable) @@ -576,7 +601,7 @@ static int pxamci_probe(struct platform_device *pdev) * We can do SG-DMA, but we don't because we never know how much * data we successfully wrote to the card. */ - mmc->max_phys_segs = NR_SG; + mmc->max_segs = NR_SG; /* * Our hardware DMA can handle a maximum of one page per SG entry. diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 2e16e0a90a5..262b3882cfc 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -1736,8 +1736,7 @@ static int __devinit s3cmci_probe(struct platform_device *pdev) mmc->max_req_size = 4095 * 512; mmc->max_seg_size = mmc->max_req_size; - mmc->max_phys_segs = 128; - mmc->max_hw_segs = 128; + mmc->max_segs = 128; dbg(host, dbg_debug, "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n", diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index c6d1bd8d4ac..0f77a6d27bd 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1823,12 +1823,11 @@ int sdhci_add_host(struct sdhci_host *host) * can do scatter/gather or not. */ if (host->flags & SDHCI_USE_ADMA) - mmc->max_hw_segs = 128; + mmc->max_segs = 128; else if (host->flags & SDHCI_USE_SDMA) - mmc->max_hw_segs = 1; + mmc->max_segs = 1; else /* PIO */ - mmc->max_hw_segs = 128; - mmc->max_phys_segs = 128; + mmc->max_segs = 128; /* * Maximum number of sectors in one transfer. Limited by DMA boundary diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 5d3f824bb5a..0f06b800281 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -846,8 +846,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) mmc->caps = MMC_CAP_MMC_HIGHSPEED; if (pd->caps) mmc->caps |= pd->caps; - mmc->max_phys_segs = 128; - mmc->max_hw_segs = 128; + mmc->max_segs = 128; mmc->max_blk_size = 512; mmc->max_blk_count = 65535; mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index cec99958b65..457c26ea09d 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c @@ -978,11 +978,10 @@ static int tifm_sd_probe(struct tifm_dev *sock) mmc->f_max = 24000000; mmc->max_blk_count = 2048; - mmc->max_hw_segs = mmc->max_blk_count; + mmc->max_segs = mmc->max_blk_count; mmc->max_blk_size = min(TIFM_MMCSD_MAX_BLOCK_SIZE, PAGE_SIZE); mmc->max_seg_size = mmc->max_blk_count * mmc->max_blk_size; mmc->max_req_size = mmc->max_seg_size; - mmc->max_phys_segs = mmc->max_hw_segs; sock->card_event = tifm_sd_card_event; sock->data_event = tifm_sd_data_event; diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 19f2d72dbca..9ed84ddb478 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -1050,8 +1050,7 @@ static void via_init_mmc_host(struct via_crdr_mmc_host *host) mmc->ops = &via_sdc_ops; /*Hardware cannot do scatter lists*/ - mmc->max_hw_segs = 1; - mmc->max_phys_segs = 1; + mmc->max_segs = 1; mmc->max_blk_size = VIA_CRDR_MAX_BLOCK_LENGTH; mmc->max_blk_count = VIA_CRDR_MAX_BLOCK_COUNT; diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index 0012f5d13d2..7fca0a386ba 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -1235,8 +1235,7 @@ static int __devinit wbsd_alloc_mmc(struct device *dev) * Maximum number of segments. Worst case is one sector per segment * so this will be 64kB/512. */ - mmc->max_hw_segs = 128; - mmc->max_phys_segs = 128; + mmc->max_segs = 128; /* * Maximum request size. Also limited by 64KiB buffer. |