Skip to content

Commit

Permalink
Merge tag 'mmc-updates-for-3.8-rc1' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/cjb/mmc

Pull MMC updates from Chris Ball:
 "MMC highlights for 3.8:

  Core:
   - Expose access to the eMMC RPMB ("Replay Protected Memory Block")
     area by extending the existing mmc_block ioctl.
   - Add SDIO powered-suspend DT properties to the core MMC DT binding.
   - Add no-1-8-v DT flag for boards where the SD controller reports
     that it supports 1.8V but the board itself has no way to switch to
     1.8V.
   - More work on switching to 1.8V UHS support using a vqmmc regulator.
   - Fix up a case where the slot-gpio helper may fail to reset the host
     controller properly if a card was removed during a transfer.
   - Fix several cases where a broken device could cause an infinite
     loop while we wait for a register to update.

  Drivers:
   - at91-mci: Remove obsolete driver, atmel-mci handles these devices
     now.
   - sdhci-dove: Allow using GPIOs for card-detect notifications.
   - sdhci-esdhc: Fix for recovering from ADMA errors on broken silicon.
   - sdhci-s3c: Add pinctrl support.
   - wmt-sdmmc: New driver for WonderMedia SD/MMC controllers."

* tag 'mmc-updates-for-3.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (65 commits)
  mmc: sdhci: implement the .card_event() method
  mmc: extend the slot-gpio card-detection to use host's .card_event() method
  mmc: add a card-event host operation
  mmc: sdhci-s3c: Fix compilation warning
  mmc: sdhci-pci: Enable SDHCI_CAN_DO_HISPD for Ricoh SDHCI controller
  mmc: sdhci-dove: allow GPIOs to be used for card detection on Dove
  mmc: sdhci-dove: use two-stage initialization for sdhci-pltfm
  mmc: sdhci-dove: use devm_clk_get()
  mmc: eSDHC: Recover from ADMA errors
  mmc: dw_mmc: remove duplicated buswidth code
  mmc: dw_mmc: relocate where dw_mci_setup_bus() is called from
  mmc: Limit MMC speed to 52MHz if not HS200
  mmc: dw_mmc: use devres functions in dw_mmc
  mmc: sh_mmcif: remove unneeded clock connection ID
  mmc: sh_mobile_sdhi: remove unneeded clock connection ID
  mmc: sh_mobile_sdhi: fix clock frequency printing
  mmc: Remove redundant null check before kfree in bus.c
  mmc: Remove redundant null check before kfree in sdio_bus.c
  mmc: sdhci-imx-esdhc: use more devm_* functions
  mmc: dt: add no-1-8-v device tree flag
  ...
  • Loading branch information
Linus Torvalds committed Dec 11, 2012
2 parents 2959440 + 71e6921 commit 11b84c5
Show file tree
Hide file tree
Showing 52 changed files with 1,781 additions and 1,722 deletions.
8 changes: 8 additions & 0 deletions Documentation/devicetree/bindings/mmc/mmc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ Optional properties:
- cd-inverted: when present, polarity on the cd gpio line is inverted
- wp-inverted: when present, polarity on the wp gpio line is inverted
- max-frequency: maximum operating clock frequency
- no-1-8-v: when present, denotes that 1.8v card voltage is not supported on
this system, even if the controller claims it is.

Optional SDIO properties:
- keep-power-in-suspend: Preserves card power during a suspend/resume cycle
- enable-sdio-wakeup: Enables wake up of host system on SDIO IRQ assertion

Example:

Expand All @@ -33,4 +39,6 @@ sdhci@ab000000 {
cd-inverted;
wp-gpios = <&gpio 70 0>;
max-frequency = <50000000>;
keep-power-in-suspend;
enable-sdio-wakeup;
}
20 changes: 13 additions & 7 deletions Documentation/devicetree/bindings/mmc/samsung-sdhci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ is used. The Samsung's SDHCI controller bindings extends this as listed below.
[A] The property "samsung,cd-pinmux-gpio" can be used as stated in the
"Optional Board Specific Properties" section below.

[B] If core card-detect bindings and "samsung,cd-pinmux-gpio" property
is not specified, it is assumed that there is no card detection
mechanism used.

Required SoC Specific Properties:
- compatible: should be one of the following
- "samsung,s3c6410-sdhci": For controllers compatible with s3c6410 sdhci
Expand All @@ -24,14 +20,18 @@ Required SoC Specific Properties:
controller.

Required Board Specific Properties:
- gpios: Should specify the gpios used for clock, command and data lines. The
gpio specifier format depends on the gpio controller.
- Samsung GPIO variant (will be completely replaced by pinctrl):
- gpios: Should specify the gpios used for clock, command and data lines. The
gpio specifier format depends on the gpio controller.
- Pinctrl variant (preferred if available):
- pinctrl-0: Should specify pin control groups used for this controller.
- pinctrl-names: Should contain only one value - "default".

Optional Board Specific Properties:
- samsung,cd-pinmux-gpio: Specifies the card detect line that is routed
through a pinmux to the card-detect pin of the card slot. This property
should be used only if none of the mmc core card-detect properties are
used.
used. Only for Samsung GPIO variant.

Example:
sdhci@12530000 {
Expand All @@ -40,12 +40,18 @@ Example:
interrupts = <0 75 0>;
bus-width = <4>;
cd-gpios = <&gpk2 2 2 3 3>;

/* Samsung GPIO variant */
gpios = <&gpk2 0 2 0 3>, /* clock line */
<&gpk2 1 2 0 3>, /* command line */
<&gpk2 3 2 3 3>, /* data line 0 */
<&gpk2 4 2 3 3>, /* data line 1 */
<&gpk2 5 2 3 3>, /* data line 2 */
<&gpk2 6 2 3 3>; /* data line 3 */

/* Pinctrl variant */
pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_bus4>;
pinctrl-names = "default";
};

Note: This example shows both SoC specific and board specific properties
Expand Down
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ ti,dual-volt: boolean, supports dual voltage cards
"supply-name" examples are "vmmc", "vmmc_aux" etc
ti,non-removable: non-removable slot (like eMMC)
ti,needs-special-reset: Requires a special softreset sequence
ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed

Example:
mmc1: mmc@0x4809c000 {
Expand Down
23 changes: 23 additions & 0 deletions Documentation/devicetree/bindings/mmc/vt8500-sdmmc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
* Wondermedia WM8505/WM8650 SD/MMC Host Controller

This file documents differences between the core properties described
by mmc.txt and the properties used by the wmt-sdmmc driver.

Required properties:
- compatible: Should be "wm,wm8505-sdhc".
- interrupts: Two interrupts are required - regular irq and dma irq.

Optional properties:
- sdon-inverted: SD_ON bit is inverted on the controller

Examples:

sdhc@d800a000 {
compatible = "wm,wm8505-sdhc";
reg = <0xd800a000 0x1000>;
interrupts = <20 21>;
clocks = <&sdhc>;
bus-width = <4>;
sdon-inverted;
};

7 changes: 7 additions & 0 deletions Documentation/mmc/mmc-dev-attrs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ All attributes are read-only.
serial Product Serial Number (from CID Register)
erase_size Erase group size
preferred_erase_size Preferred erase size
raw_rpmb_size_mult RPMB partition size
rel_sectors Reliable write sector count

Note on Erase Size and Preferred Erase Size:

Expand Down Expand Up @@ -65,6 +67,11 @@ Note on Erase Size and Preferred Erase Size:

"preferred_erase_size" is in bytes.

Note on raw_rpmb_size_mult:
"raw_rpmb_size_mult" is a mutliple of 128kB block.
RPMB size in byte is calculated by using the following equation:
RPMB partition size = 128kB x raw_rpmb_size_mult

SD/MMC/SDIO Clock Gating Attribute
==================================

Expand Down
9 changes: 1 addition & 8 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,7 @@ F: drivers/video/wm8505fb*
F: drivers/video/wmt_ge_rops.*
F: drivers/tty/serial/vt8500_serial.c
F: drivers/rtc/rtc-vt8500-c
F: drivers/mmc/host/wmt-sdmmc.c

ARM/ZIPIT Z2 SUPPORT
M: Marek Vasut <marek.vasut@gmail.com>
Expand Down Expand Up @@ -1368,14 +1369,6 @@ S: Maintained
F: drivers/atm/
F: include/linux/atm*

ATMEL AT91 MCI DRIVER
M: Ludovic Desroches <ludovic.desroches@atmel.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://www.atmel.com/products/AT91/
W: http://www.at91.com/
S: Maintained
F: drivers/mmc/host/at91_mci.c

ATMEL AT91 / AT32 MCI DRIVER
M: Ludovic Desroches <ludovic.desroches@atmel.com>
S: Maintained
Expand Down
10 changes: 0 additions & 10 deletions arch/arm/mach-at91/include/mach/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,6 @@ struct at91_cf_data {
extern void __init at91_add_device_cf(struct at91_cf_data *data);

/* MMC / SD */
/* at91_mci platform config */
struct at91_mmc_data {
int det_pin; /* card detect IRQ */
unsigned slot_b:1; /* uses Slot B */
unsigned wire4:1; /* (SD) supports DAT0..DAT3 */
int wp_pin; /* (SD) writeprotect detect */
int vcc_pin; /* power switching (high == on) */
};
extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data);

/* atmel-mci platform config */
extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data);

Expand Down
1 change: 1 addition & 0 deletions arch/arm/plat-omap/include/plat/mmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ struct omap_mmc_platform_data {
/* we can put the features above into this variable */
#define HSMMC_HAS_PBIAS (1 << 0)
#define HSMMC_HAS_UPDATED_RESET (1 << 1)
#define HSMMC_HAS_HSPE_SUPPORT (1 << 2)
unsigned features;

int switch_pin; /* gpio (card detect) */
Expand Down
81 changes: 81 additions & 0 deletions drivers/mmc/card/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ MODULE_ALIAS("mmc:block");
#define INAND_CMD38_ARG_SECERASE 0x80
#define INAND_CMD38_ARG_SECTRIM1 0x81
#define INAND_CMD38_ARG_SECTRIM2 0x88
#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */

static DEFINE_MUTEX(block_mutex);

Expand Down Expand Up @@ -126,6 +127,10 @@ enum mmc_blk_status {
module_param(perdev_minors, int, 0444);
MODULE_PARM_DESC(perdev_minors, "Minors numbers to allocate per device");

static inline int mmc_blk_part_switch(struct mmc_card *card,
struct mmc_blk_data *md);
static int get_card_status(struct mmc_card *card, u32 *status, int retries);

static struct mmc_blk_data *mmc_blk_get(struct gendisk *disk)
{
struct mmc_blk_data *md;
Expand Down Expand Up @@ -357,6 +362,38 @@ static struct mmc_blk_ioc_data *mmc_blk_ioctl_copy_from_user(
return ERR_PTR(err);
}

static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
u32 retries_max)
{
int err;
u32 retry_count = 0;

if (!status || !retries_max)
return -EINVAL;

do {
err = get_card_status(card, status, 5);
if (err)
break;

if (!R1_STATUS(*status) &&
(R1_CURRENT_STATE(*status) != R1_STATE_PRG))
break; /* RPMB programming operation complete */

/*
* Rechedule to give the MMC device a chance to continue
* processing the previous command without being polled too
* frequently.
*/
usleep_range(1000, 5000);
} while (++retry_count < retries_max);

if (retry_count == retries_max)
err = -EPERM;

return err;
}

static int mmc_blk_ioctl_cmd(struct block_device *bdev,
struct mmc_ioc_cmd __user *ic_ptr)
{
Expand All @@ -368,6 +405,8 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
struct mmc_request mrq = {NULL};
struct scatterlist sg;
int err;
int is_rpmb = false;
u32 status = 0;

/*
* The caller must have CAP_SYS_RAWIO, and must be calling this on the
Expand All @@ -387,6 +426,9 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
goto cmd_err;
}

if (md->area_type & MMC_BLK_DATA_AREA_RPMB)
is_rpmb = true;

card = md->queue.card;
if (IS_ERR(card)) {
err = PTR_ERR(card);
Expand Down Expand Up @@ -437,12 +479,23 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,

mmc_claim_host(card->host);

err = mmc_blk_part_switch(card, md);
if (err)
goto cmd_rel_host;

if (idata->ic.is_acmd) {
err = mmc_app_cmd(card->host, card);
if (err)
goto cmd_rel_host;
}

if (is_rpmb) {
err = mmc_set_blockcount(card, data.blocks,
idata->ic.write_flag & (1 << 31));
if (err)
goto cmd_rel_host;
}

mmc_wait_for_req(card->host, &mrq);

if (cmd.error) {
Expand Down Expand Up @@ -478,6 +531,18 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
}
}

if (is_rpmb) {
/*
* Ensure RPMB command has completed by polling CMD13
* "Send Status".
*/
err = ioctl_rpmb_card_status_poll(card, &status, 5);
if (err)
dev_err(mmc_dev(card->host),
"%s: Card Status=0x%08X, error %d\n",
__func__, status, err);
}

cmd_rel_host:
mmc_release_host(card->host);

Expand Down Expand Up @@ -1034,13 +1099,27 @@ static int mmc_blk_err_check(struct mmc_card *card,
*/
if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) {
u32 status;
unsigned long timeout;

timeout = jiffies + msecs_to_jiffies(MMC_BLK_TIMEOUT_MS);
do {
int err = get_card_status(card, &status, 5);
if (err) {
pr_err("%s: error %d requesting status\n",
req->rq_disk->disk_name, err);
return MMC_BLK_CMD_ERR;
}

/* Timeout if the device never becomes ready for data
* and never leaves the program state.
*/
if (time_after(jiffies, timeout)) {
pr_err("%s: Card stuck in programming state!"\
" %s %s\n", mmc_hostname(card->host),
req->rq_disk->disk_name, __func__);

return MMC_BLK_CMD_ERR;
}
/*
* Some cards mishandle the status bits,
* so make sure to check both the busy
Expand Down Expand Up @@ -1504,6 +1583,8 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
md->disk->queue = md->queue.queue;
md->disk->driverfs_dev = parent;
set_disk_ro(md->disk, md->read_only || default_ro);
if (area_type & MMC_BLK_DATA_AREA_RPMB)
md->disk->flags |= GENHD_FL_NO_PART_SCAN;

/*
* As discussed on lkml, GENHD_FL_REMOVABLE should:
Expand Down
17 changes: 10 additions & 7 deletions drivers/mmc/card/queue.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ static int mmc_queue_thread(void *d)
if (req || mq->mqrq_prev->req) {
set_current_state(TASK_RUNNING);
mq->issue_fn(mq, req);

/*
* Current request becomes previous request
* and vice versa.
*/
mq->mqrq_prev->brq.mrq.data = NULL;
mq->mqrq_prev->req = NULL;
tmp = mq->mqrq_prev;
mq->mqrq_prev = mq->mqrq_cur;
mq->mqrq_cur = tmp;
} else {
if (kthread_should_stop()) {
set_current_state(TASK_RUNNING);
Expand All @@ -77,13 +87,6 @@ static int mmc_queue_thread(void *d)
schedule();
down(&mq->thread_sem);
}

/* Current request becomes previous request and vice versa. */
mq->mqrq_prev->brq.mrq.data = NULL;
mq->mqrq_prev->req = NULL;
tmp = mq->mqrq_prev;
mq->mqrq_prev = mq->mqrq_cur;
mq->mqrq_cur = tmp;
} while (1);
up(&mq->thread_sem);

Expand Down
3 changes: 1 addition & 2 deletions drivers/mmc/core/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,7 @@ static void mmc_release_card(struct device *dev)

sdio_free_common_cis(card);

if (card->info)
kfree(card->info);
kfree(card->info);

kfree(card);
}
Expand Down
Loading

0 comments on commit 11b84c5

Please sign in to comment.