Skip to content

Commit

Permalink
Merge tag 'mmc-merge-for-3.5-rc1' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/cjb/mmc

Pull MMC changes from Chris Ball
 - at91-mci: This driver will be replaced by atmel-mci in 3.7.
 - atmel-mci: Add support for old at91-mci hardware.
 - dw_mmc: Allow multiple controllers; this previously caused
   corruption.
 - imxmmc: Remove this driver, replaced by mxcmmc.
 - mmci: Add device tree support.
 - omap: Allow multiple controllers.
 - omap_hsmmc: Auto CMD12, DDR support.
 - tegra: Support SD 3.0 spec.

Fix up the usual trivial conflicts in feature-removal-schedule.txt

* tag 'mmc-merge-for-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (38 commits)
  mmc: at91-mci: this driver is now deprecated
  mmc: omap_hsmmc: pass IRQF_ONESHOT to request_threaded_irq
  mmc: block: Allow disabling 512B sector size emulation
  mmc: atmel-mci: add debug logs
  mmc: atmel-mci: add support for version lower than v2xx
  mmc: atmel-mci: change the state machine for compatibility with old IP
  mmc: atmel-mci: the r/w proof capability lack was not well managed
  mmc: dw_mmc: Fixed sdio interrupt mask bit setting bug
  mmc: omap: convert to module_platform_driver
  mmc: omap: make it behave well as a module
  mmc: omap: convert to per instance workqueue
  mmc: core: Remove dead code
  mmc: card: Avoid null pointer dereference
  mmc: core: Prevent eMMC VCC supply to be cut from late init
  mmc: dw_mmc: make multiple instances of dw_mci_card_workqueue
  mmc: queue: remove redundant memsets
  mmc: queue: rename mmc_request function
  mmc: core: skip card initialization if power class selection fails
  mmc: core: fix the signaling 1.8V for HS200
  mmc: core: fix the decision of HS200/DDR card-type
  ...
  • Loading branch information
torvalds committed May 25, 2012
2 parents 603d663 + 0caaa95 commit 92bf3d0
Show file tree
Hide file tree
Showing 27 changed files with 667 additions and 1,661 deletions.
19 changes: 19 additions & 0 deletions Documentation/devicetree/bindings/mmc/mmci.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
* ARM PrimeCell MultiMedia Card Interface (MMCI) PL180/1

The ARM PrimeCell MMCI PL180 and PL181 provides and interface for
reading and writing to MultiMedia and SD cards alike.

Required properties:
- compatible : contains "arm,pl18x", "arm,primecell".
- reg : contains pl18x registers and length.
- interrupts : contains the device IRQ(s).
- arm,primecell-periphid : contains the PrimeCell Peripheral ID.

Optional properties:
- wp-gpios : contains any write protect (ro) gpios
- cd-gpios : contains any card detection gpios
- cd-inverted : indicates whether the cd gpio is inverted
- max-frequency : contains the maximum operating frequency
- bus-width : number of data lines, can be <1>, <4>, or <8>
- mmc-cap-mmc-highspeed : indicates whether MMC is high speed capable
- mmc-cap-sd-highspeed : indicates whether SD is high speed capable
11 changes: 11 additions & 0 deletions Documentation/feature-removal-schedule.txt
Original file line number Diff line number Diff line change
Expand Up @@ -595,3 +595,14 @@ Why: KVM tracepoints provide mostly equivalent information in a much more
flexible fashion.

----------------------------

What: at91-mci driver ("CONFIG_MMC_AT91")
When: 3.7
Why: There are two mci drivers: at91-mci and atmel-mci. The PDC support
was added to atmel-mci as a first step to support more chips.
Then at91-mci was kept only for old IP versions (on at91rm9200 and
at91sam9261). The support of these IP versions has just been added
to atmel-mci, so atmel-mci can be used for all chips.
Who: Ludovic Desroches <ludovic.desroches@atmel.com>

----------------------------
22 changes: 19 additions & 3 deletions drivers/mmc/card/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
md = mmc_blk_get(bdev->bd_disk);
if (!md) {
err = -EINVAL;
goto cmd_done;
goto cmd_err;
}

card = md->queue.card;
Expand Down Expand Up @@ -483,6 +483,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,

cmd_done:
mmc_blk_put(md);
cmd_err:
kfree(idata->buf);
kfree(idata);
return err;
Expand Down Expand Up @@ -1283,14 +1284,24 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
int ret = 1, disable_multi = 0, retry = 0, type;
enum mmc_blk_status status;
struct mmc_queue_req *mq_rq;
struct request *req;
struct request *req = rqc;
struct mmc_async_req *areq;

if (!rqc && !mq->mqrq_prev->req)
return 0;

do {
if (rqc) {
/*
* When 4KB native sector is enabled, only 8 blocks
* multiple read or write is allowed
*/
if ((brq->data.blocks & 0x07) &&
(card->ext_csd.data_sector_size == 4096)) {
pr_err("%s: Transfer size is not 4KB sector size aligned\n",
req->rq_disk->disk_name);
goto cmd_abort;
}
mmc_blk_rw_rq_prep(mq->mqrq_cur, card, 0, mq);
areq = &mq->mqrq_cur->mmc_active;
} else
Expand Down Expand Up @@ -1538,7 +1549,12 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
snprintf(md->disk->disk_name, sizeof(md->disk->disk_name),
"mmcblk%d%s", md->name_idx, subname ? subname : "");

blk_queue_logical_block_size(md->queue.queue, 512);
if (mmc_card_mmc(card))
blk_queue_logical_block_size(md->queue.queue,
card->ext_csd.data_sector_size);
else
blk_queue_logical_block_size(md->queue.queue, 512);

set_capacity(md->disk, size);

if (mmc_host_cmd23(card->host)) {
Expand Down
6 changes: 2 additions & 4 deletions drivers/mmc/card/queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ static int mmc_queue_thread(void *d)
* on any queue on this host, and attempt to issue it. This may
* not be the queue we were asked to process.
*/
static void mmc_request(struct request_queue *q)
static void mmc_request_fn(struct request_queue *q)
{
struct mmc_queue *mq = q->queuedata;
struct request *req;
Expand Down Expand Up @@ -171,12 +171,10 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
limit = *mmc_dev(host)->dma_mask;

mq->card = card;
mq->queue = blk_init_queue(mmc_request, lock);
mq->queue = blk_init_queue(mmc_request_fn, lock);
if (!mq->queue)
return -ENOMEM;

memset(&mq->mqrq_cur, 0, sizeof(mq->mqrq_cur));
memset(&mq->mqrq_prev, 0, sizeof(mq->mqrq_prev));
mq->mqrq_cur = mqrq_cur;
mq->mqrq_prev = mqrq_prev;
mq->queue->queuedata = mq;
Expand Down
2 changes: 2 additions & 0 deletions drivers/mmc/core/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ static int mmc_bus_remove(struct device *dev)
return 0;
}

#ifdef CONFIG_PM_SLEEP
static int mmc_bus_suspend(struct device *dev)
{
struct mmc_driver *drv = to_mmc_driver(dev->driver);
Expand All @@ -143,6 +144,7 @@ static int mmc_bus_resume(struct device *dev)
ret = drv->resume(card);
return ret;
}
#endif

#ifdef CONFIG_PM_RUNTIME

Expand Down
3 changes: 3 additions & 0 deletions drivers/mmc/core/cd-gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ void mmc_cd_gpio_free(struct mmc_host *host)
{
struct mmc_cd_gpio *cd = host->hotplug.handler_priv;

if (!cd)
return;

free_irq(host->hotplug.irq, host);
gpio_free(cd->gpio);
kfree(cd);
Expand Down
18 changes: 15 additions & 3 deletions drivers/mmc/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include "sdio_ops.h"

static struct workqueue_struct *workqueue;
static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };

/*
* Enabling software CRCs on the data blocks can be a significant (30%)
Expand Down Expand Up @@ -1157,6 +1158,9 @@ static void mmc_power_up(struct mmc_host *host)
{
int bit;

if (host->ios.power_mode == MMC_POWER_ON)
return;

mmc_host_clk_hold(host);

/* If ocr is set, we use it */
Expand Down Expand Up @@ -1199,6 +1203,10 @@ static void mmc_power_up(struct mmc_host *host)
void mmc_power_off(struct mmc_host *host)
{
int err = 0;

if (host->ios.power_mode == MMC_POWER_OFF)
return;

mmc_host_clk_hold(host);

host->ios.clock = 0;
Expand Down Expand Up @@ -2005,7 +2013,6 @@ EXPORT_SYMBOL(mmc_detect_card_removed);

void mmc_rescan(struct work_struct *work)
{
static const unsigned freqs[] = { 400000, 300000, 200000, 100000 };
struct mmc_host *host =
container_of(work, struct mmc_host, detect.work);
int i;
Expand Down Expand Up @@ -2044,8 +2051,12 @@ void mmc_rescan(struct work_struct *work)
*/
mmc_bus_put(host);

if (host->ops->get_cd && host->ops->get_cd(host) == 0)
if (host->ops->get_cd && host->ops->get_cd(host) == 0) {
mmc_claim_host(host);
mmc_power_off(host);
mmc_release_host(host);
goto out;
}

mmc_claim_host(host);
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
Expand All @@ -2063,7 +2074,8 @@ void mmc_rescan(struct work_struct *work)

void mmc_start_host(struct mmc_host *host)
{
mmc_power_off(host);
host->f_init = max(freqs[0], host->f_min);
mmc_power_up(host);
mmc_detect_change(host, 0);
}

Expand Down
119 changes: 49 additions & 70 deletions drivers/mmc/core/mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,36 @@ static int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd)
return err;
}

static void mmc_select_card_type(struct mmc_card *card)
{
struct mmc_host *host = card->host;
u8 card_type = card->ext_csd.raw_card_type & EXT_CSD_CARD_TYPE_MASK;
unsigned int caps = host->caps, caps2 = host->caps2;
unsigned int hs_max_dtr = 0;

if (card_type & EXT_CSD_CARD_TYPE_26)
hs_max_dtr = MMC_HIGH_26_MAX_DTR;

if (caps & MMC_CAP_MMC_HIGHSPEED &&
card_type & EXT_CSD_CARD_TYPE_52)
hs_max_dtr = MMC_HIGH_52_MAX_DTR;

if ((caps & MMC_CAP_1_8V_DDR &&
card_type & EXT_CSD_CARD_TYPE_DDR_1_8V) ||
(caps & MMC_CAP_1_2V_DDR &&
card_type & EXT_CSD_CARD_TYPE_DDR_1_2V))
hs_max_dtr = MMC_HIGH_DDR_MAX_DTR;

if ((caps2 & MMC_CAP2_HS200_1_8V_SDR &&
card_type & EXT_CSD_CARD_TYPE_SDR_1_8V) ||
(caps2 & MMC_CAP2_HS200_1_2V_SDR &&
card_type & EXT_CSD_CARD_TYPE_SDR_1_2V))
hs_max_dtr = MMC_HS200_MAX_DTR;

card->ext_csd.hs_max_dtr = hs_max_dtr;
card->ext_csd.card_type = card_type;
}

/*
* Decode extended CSD.
*/
Expand Down Expand Up @@ -284,56 +314,9 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
if (card->ext_csd.sectors > (2u * 1024 * 1024 * 1024) / 512)
mmc_card_set_blockaddr(card);
}

card->ext_csd.raw_card_type = ext_csd[EXT_CSD_CARD_TYPE];
switch (ext_csd[EXT_CSD_CARD_TYPE] & EXT_CSD_CARD_TYPE_MASK) {
case EXT_CSD_CARD_TYPE_SDR_ALL:
case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_8V:
case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_1_2V:
case EXT_CSD_CARD_TYPE_SDR_ALL_DDR_52:
card->ext_csd.hs_max_dtr = 200000000;
card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_200;
break;
case EXT_CSD_CARD_TYPE_SDR_1_2V_ALL:
case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_8V:
case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_1_2V:
case EXT_CSD_CARD_TYPE_SDR_1_2V_DDR_52:
card->ext_csd.hs_max_dtr = 200000000;
card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_2V;
break;
case EXT_CSD_CARD_TYPE_SDR_1_8V_ALL:
case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_8V:
case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_1_2V:
case EXT_CSD_CARD_TYPE_SDR_1_8V_DDR_52:
card->ext_csd.hs_max_dtr = 200000000;
card->ext_csd.card_type = EXT_CSD_CARD_TYPE_SDR_1_8V;
break;
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;
case EXT_CSD_CARD_TYPE_26:
card->ext_csd.hs_max_dtr = 26000000;
break;
default:
/* MMC v4 spec says this cannot happen */
pr_warning("%s: card is mmc v4 but doesn't "
"support any high-speed modes.\n",
mmc_hostname(card->host));
}
mmc_select_card_type(card);

card->ext_csd.raw_s_a_timeout = ext_csd[EXT_CSD_S_A_TIMEOUT];
card->ext_csd.raw_erase_timeout_mult =
Expand Down Expand Up @@ -533,6 +516,8 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd)
} else {
card->ext_csd.data_tag_unit_size = 0;
}
} else {
card->ext_csd.data_sector_size = 512;
}

out:
Expand All @@ -556,14 +541,10 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width)
err = mmc_get_ext_csd(card, &bw_ext_csd);

if (err || bw_ext_csd == NULL) {
if (bus_width != MMC_BUS_WIDTH_1)
err = -EINVAL;
err = -EINVAL;
goto out;
}

if (bus_width == MMC_BUS_WIDTH_1)
goto out;

/* only compare read only fields */
err = !((card->ext_csd.raw_partition_support ==
bw_ext_csd[EXT_CSD_PARTITION_SUPPORT]) &&
Expand Down Expand Up @@ -736,6 +717,10 @@ static int mmc_select_powerclass(struct mmc_card *card,
card->ext_csd.generic_cmd6_time);
}

if (err)
pr_err("%s: power class selection for ext_csd_bus_width %d"
" failed\n", mmc_hostname(card->host), bus_width);

return err;
}

Expand All @@ -745,7 +730,7 @@ static int mmc_select_powerclass(struct mmc_card *card,
*/
static int mmc_select_hs200(struct mmc_card *card)
{
int idx, err = 0;
int idx, err = -EINVAL;
struct mmc_host *host;
static unsigned ext_csd_bits[] = {
EXT_CSD_BUS_WIDTH_4,
Expand All @@ -761,10 +746,12 @@ static int mmc_select_hs200(struct mmc_card *card)
host = card->host;

if (card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_2V &&
host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
if (mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120, 0))
err = mmc_set_signal_voltage(host,
MMC_SIGNAL_VOLTAGE_180, 0);
host->caps2 & MMC_CAP2_HS200_1_2V_SDR)
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_120, 0);

if (err && card->ext_csd.card_type & EXT_CSD_CARD_TYPE_SDR_1_8V &&
host->caps2 & MMC_CAP2_HS200_1_8V_SDR)
err = mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_180, 0);

/* If fails try again during next card power cycle */
if (err)
Expand Down Expand Up @@ -1117,9 +1104,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
EXT_CSD_BUS_WIDTH_8 : EXT_CSD_BUS_WIDTH_4;
err = mmc_select_powerclass(card, ext_csd_bits, ext_csd);
if (err)
pr_warning("%s: power class selection to bus width %d"
" failed\n", mmc_hostname(card->host),
1 << bus_width);
goto err;
}

/*
Expand Down Expand Up @@ -1151,10 +1136,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
err = mmc_select_powerclass(card, ext_csd_bits[idx][0],
ext_csd);
if (err)
pr_warning("%s: power class selection to "
"bus width %d failed\n",
mmc_hostname(card->host),
1 << bus_width);
goto err;

err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
Expand Down Expand Up @@ -1182,10 +1164,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
err = mmc_select_powerclass(card, ext_csd_bits[idx][1],
ext_csd);
if (err)
pr_warning("%s: power class selection to "
"bus width %d ddr %d failed\n",
mmc_hostname(card->host),
1 << bus_width, ddr);
goto err;

err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_BUS_WIDTH,
Expand Down
Loading

0 comments on commit 92bf3d0

Please sign in to comment.