Skip to content

Commit

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

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

  Core:
   - Add support for eMMC 5.1 devices
   - Add MMC_CAP_AGGRESSIVE_PM capability for aggressive power
     management of eMMC/SD between requests, using runtime PM
   - Add an ioctl to perform the eMMC 4.5 Sanitize command.  Sample code
     at:

       git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc-utils.git

  Drivers:
   - dw_mmc: Add support for Rockchip's Cortex-A9 SoCs
   - dw_mmc: Add support for Altera SoCFPGAs
   - sdhci-esdhc-imx: Add support for 8-bit bus width, non-removable
     cards
   - sdhci-bcm-kona: New driver for Broadcom Kona (281xx) SoCs
   - sdhi/tmio: Add DT DMA support"

* tag 'mmc-updates-for-3.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/cjb/mmc: (87 commits)
  mmc: bcm281xx SDHCI driver
  mmc: sdhci: add card_event callback to sdhci
  mmc: core: Fixup Oops for SDIO shutdown
  mmc: sdhci-pci: add another device id
  mmc: esdhc: Fix bug when writing to SDHCI_HOST_CONTROL register
  mmc: esdhc: Add support for 8-bit bus width and non-removable card
  mmc: core: production year for eMMC 4.41 and later
  mmc: omap: remove unnecessary #if 0's
  mmc: sdhci: fix ctrl_2 on super-speed selection
  mmc: dw_mmc-pltfm: add Rockchip variant
  mmc: dw_mmc-pltfm: move probe and remove below dt match table
  mmc: dw_mmc-pltfm: remove static from dw_mci_pltfm_remove
  mmc: sdhci-acpi: add support for eMMC hardware reset for HID 80860F14
  mmc: sdhci-pci: add support for eMMC hardware reset for BYT eMMC.
  mmc: dw_mmc: Add support DW SD/MMC driver on SOCFPGA
  mmc: sdhci: fix caps2 for HS200
  sdhci-pxav3: Fix runtime PM initialization
  mmc: core: Add DT-bindings for MMC_CAP2_FULL_PWR_CYCLE
  mmc: core: Invent MMC_CAP2_FULL_PWR_CYCLE
  mmc: core: Enable power_off_notify for eMMC shutdown sequence
  ...
  • Loading branch information
torvalds committed Jul 10, 2013
2 parents 34ae0a6 + 01ebea1 commit bfffbea
Show file tree
Hide file tree
Showing 73 changed files with 1,807 additions and 790 deletions.
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/mmc/mmc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ Optional properties:
- cap-mmc-highspeed: MMC high-speed timing is supported
- cap-power-off-card: powering off the card is safe
- cap-sdio-irq: enable SDIO IRQ signalling on this interface
- full-pwr-cycle: full power cycle of the card is supported

*NOTE* on CD and WP polarity. To use common for all SD/MMC host controllers line
polarity properties, we have to fix the meaning of the "normal" and "inverted"
Expand Down
23 changes: 23 additions & 0 deletions Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
* Rockchip specific extensions to the Synopsis Designware Mobile
Storage Host Controller

The Synopsis designware mobile storage host controller is used to interface
a SoC with storage medium such as eMMC or SD/MMC cards. This file documents
differences between the core Synopsis dw mshc controller properties described
by synopsis-dw-mshc.txt and the properties used by the Rockchip specific
extensions to the Synopsis Designware Mobile Storage Host Controller.

Required Properties:

* compatible: should be
- "rockchip,rk2928-dw-mshc": for Rockchip RK2928 and following

Example:

rkdwmmc0@12200000 {
compatible = "rockchip,rk2928-dw-mshc";
reg = <0x12200000 0x1000>;
interrupts = <0 75 0>;
#address-cells = <1>;
#size-cells = <0>;
};
20 changes: 20 additions & 0 deletions Documentation/devicetree/bindings/mmc/synopsis-dw-mshc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ Required Properties:

Optional properties:

* clocks: from common clock binding: handle to biu and ciu clocks for the
bus interface unit clock and the card interface unit clock.

* clock-names: from common clock binding: Shall be "biu" and "ciu".
If the biu clock is missing we'll simply skip enabling it. If the
ciu clock is missing we'll just assume that the clock is running at
clock-frequency. It is an error to omit both the ciu clock and the
clock-frequency.

* clock-frequency: should be the frequency (in Hz) of the ciu clock. If this
is specified and the ciu clock is specified then we'll try to set the ciu
clock to this at probe time.

* num-slots: specifies the number of slots supported by the controller.
The number of physical slots actually used could be equal or less than the
value specified by num-slots. If this property is not specified, the value
Expand All @@ -55,6 +68,9 @@ Optional properties:

* broken-cd: as documented in mmc core bindings.

* vmmc-supply: The phandle to the regulator to use for vmmc. If this is
specified we'll defer probe until we can find this regulator.

Aliases:

- All the MSHC controller nodes should be represented in the aliases node using
Expand All @@ -67,18 +83,22 @@ board specific portions as listed below.

dwmmc0@12200000 {
compatible = "snps,dw-mshc";
clocks = <&clock 351>, <&clock 132>;
clock-names = "biu", "ciu";
reg = <0x12200000 0x1000>;
interrupts = <0 75 0>;
#address-cells = <1>;
#size-cells = <0>;
};

dwmmc0@12200000 {
clock-frequency = <400000000>;
num-slots = <1>;
supports-highspeed;
broken-cd;
fifo-depth = <0x80>;
card-detect-delay = <200>;
vmmc-supply = <&buck8>;

slot@0 {
reg = <0>;
Expand Down
7 changes: 7 additions & 0 deletions arch/arm/configs/bcm_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_LCD_CLASS_DEVICE=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_USB_SUPPORT is not set
CONFIG_MMC=y
CONFIG_MMC_UNSAFE_RESUME=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_TEST=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_BCM_KONA=y
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_TRIGGERS=y
Expand Down
130 changes: 95 additions & 35 deletions drivers/mmc/card/block.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <linux/delay.h>
#include <linux/capability.h>
#include <linux/compat.h>
#include <linux/pm_runtime.h>

#include <linux/mmc/ioctl.h>
#include <linux/mmc/card.h>
Expand All @@ -58,6 +59,8 @@ MODULE_ALIAS("mmc:block");
#define INAND_CMD38_ARG_SECTRIM1 0x81
#define INAND_CMD38_ARG_SECTRIM2 0x88
#define MMC_BLK_TIMEOUT_MS (10 * 60 * 1000) /* 10 minute timeout */
#define MMC_SANITIZE_REQ_TIMEOUT 240000
#define MMC_EXTRACT_INDEX_FROM_ARG(x) ((x & 0x00FF0000) >> 16)

#define mmc_req_rel_wr(req) (((req->cmd_flags & REQ_FUA) || \
(req->cmd_flags & REQ_META)) && \
Expand Down Expand Up @@ -222,7 +225,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
md = mmc_blk_get(dev_to_disk(dev));
card = md->queue.card;

mmc_claim_host(card->host);
mmc_get_card(card);

ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP,
card->ext_csd.boot_ro_lock |
Expand All @@ -233,7 +236,7 @@ static ssize_t power_ro_lock_store(struct device *dev,
else
card->ext_csd.boot_ro_lock |= EXT_CSD_BOOT_WP_B_PWR_WP_EN;

mmc_release_host(card->host);
mmc_put_card(card);

if (!ret) {
pr_info("%s: Locking boot partition ro until next power on\n",
Expand Down Expand Up @@ -408,6 +411,35 @@ static int ioctl_rpmb_card_status_poll(struct mmc_card *card, u32 *status,
return err;
}

static int ioctl_do_sanitize(struct mmc_card *card)
{
int err;

if (!(mmc_can_sanitize(card) &&
(card->host->caps2 & MMC_CAP2_SANITIZE))) {
pr_warn("%s: %s - SANITIZE is not supported\n",
mmc_hostname(card->host), __func__);
err = -EOPNOTSUPP;
goto out;
}

pr_debug("%s: %s - SANITIZE IN PROGRESS...\n",
mmc_hostname(card->host), __func__);

err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_SANITIZE_START, 1,
MMC_SANITIZE_REQ_TIMEOUT);

if (err)
pr_err("%s: %s - EXT_CSD_SANITIZE_START failed. err=%d\n",
mmc_hostname(card->host), __func__, err);

pr_debug("%s: %s - SANITIZE COMPLETED\n", mmc_hostname(card->host),
__func__);
out:
return err;
}

static int mmc_blk_ioctl_cmd(struct block_device *bdev,
struct mmc_ioc_cmd __user *ic_ptr)
{
Expand Down Expand Up @@ -491,7 +523,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,

mrq.cmd = &cmd;

mmc_claim_host(card->host);
mmc_get_card(card);

err = mmc_blk_part_switch(card, md);
if (err)
Expand All @@ -510,6 +542,17 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
goto cmd_rel_host;
}

if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) &&
(cmd.opcode == MMC_SWITCH)) {
err = ioctl_do_sanitize(card);

if (err)
pr_err("%s: ioctl_do_sanitize() failed. err = %d",
__func__, err);

goto cmd_rel_host;
}

mmc_wait_for_req(card->host, &mrq);

if (cmd.error) {
Expand Down Expand Up @@ -558,7 +601,7 @@ static int mmc_blk_ioctl_cmd(struct block_device *bdev,
}

cmd_rel_host:
mmc_release_host(card->host);
mmc_put_card(card);

cmd_done:
mmc_blk_put(md);
Expand Down Expand Up @@ -939,34 +982,22 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
{
struct mmc_blk_data *md = mq->data;
struct mmc_card *card = md->queue.card;
unsigned int from, nr, arg, trim_arg, erase_arg;
unsigned int from, nr, arg;
int err = 0, type = MMC_BLK_SECDISCARD;

if (!(mmc_can_secure_erase_trim(card) || mmc_can_sanitize(card))) {
if (!(mmc_can_secure_erase_trim(card))) {
err = -EOPNOTSUPP;
goto out;
}

from = blk_rq_pos(req);
nr = blk_rq_sectors(req);

/* The sanitize operation is supported at v4.5 only */
if (mmc_can_sanitize(card)) {
erase_arg = MMC_ERASE_ARG;
trim_arg = MMC_TRIM_ARG;
} else {
erase_arg = MMC_SECURE_ERASE_ARG;
trim_arg = MMC_SECURE_TRIM1_ARG;
}
if (mmc_can_trim(card) && !mmc_erase_group_aligned(card, from, nr))
arg = MMC_SECURE_TRIM1_ARG;
else
arg = MMC_SECURE_ERASE_ARG;

if (mmc_erase_group_aligned(card, from, nr))
arg = erase_arg;
else if (mmc_can_trim(card))
arg = trim_arg;
else {
err = -EINVAL;
goto out;
}
retry:
if (card->quirks & MMC_QUIRK_INAND_CMD38) {
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
Expand Down Expand Up @@ -1002,9 +1033,6 @@ static int mmc_blk_issue_secdiscard_rq(struct mmc_queue *mq,
goto out;
}

if (mmc_can_sanitize(card))
err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
EXT_CSD_SANITIZE_START, 1, 0);
out_retry:
if (err && !mmc_blk_reset(md, card->host, type))
goto retry;
Expand Down Expand Up @@ -1895,7 +1923,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)

if (req && !mq->mqrq_prev->req)
/* claim host only for the first request */
mmc_claim_host(card->host);
mmc_get_card(card);

ret = mmc_blk_part_switch(card, md);
if (ret) {
Expand Down Expand Up @@ -1939,7 +1967,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
* In case sepecial request, there is no reentry to
* the 'mmc_blk_issue_rq' with 'mqrq_prev->req'.
*/
mmc_release_host(card->host);
mmc_put_card(card);
return ret;
}

Expand Down Expand Up @@ -2158,6 +2186,14 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
struct mmc_card *card;

if (md) {
/*
* Flush remaining requests and free queues. It
* is freeing the queue that stops new requests
* from being accepted.
*/
mmc_cleanup_queue(&md->queue);
if (md->flags & MMC_BLK_PACKED_CMD)
mmc_packed_clean(&md->queue);
card = md->queue.card;
if (md->disk->flags & GENHD_FL_UP) {
device_remove_file(disk_to_dev(md->disk), &md->force_ro);
Expand All @@ -2166,14 +2202,8 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md)
device_remove_file(disk_to_dev(md->disk),
&md->power_ro_lock);

/* Stop new requests from getting into the queue */
del_gendisk(md->disk);
}

/* Then flush out any already in there */
mmc_cleanup_queue(&md->queue);
if (md->flags & MMC_BLK_PACKED_CMD)
mmc_packed_clean(&md->queue);
mmc_blk_put(md);
}
}
Expand Down Expand Up @@ -2336,6 +2366,19 @@ static int mmc_blk_probe(struct mmc_card *card)
if (mmc_add_disk(part_md))
goto out;
}

pm_runtime_set_autosuspend_delay(&card->dev, 3000);
pm_runtime_use_autosuspend(&card->dev);

/*
* Don't enable runtime PM for SD-combo cards here. Leave that
* decision to be taken during the SDIO init sequence instead.
*/
if (card->type != MMC_TYPE_SD_COMBO) {
pm_runtime_set_active(&card->dev);
pm_runtime_enable(&card->dev);
}

return 0;

out:
Expand All @@ -2349,20 +2392,24 @@ static void mmc_blk_remove(struct mmc_card *card)
struct mmc_blk_data *md = mmc_get_drvdata(card);

mmc_blk_remove_parts(card, md);
pm_runtime_get_sync(&card->dev);
mmc_claim_host(card->host);
mmc_blk_part_switch(card, md);
mmc_release_host(card->host);
if (card->type != MMC_TYPE_SD_COMBO)
pm_runtime_disable(&card->dev);
pm_runtime_put_noidle(&card->dev);
mmc_blk_remove_req(md);
mmc_set_drvdata(card, NULL);
}

#ifdef CONFIG_PM
static int mmc_blk_suspend(struct mmc_card *card)
static int _mmc_blk_suspend(struct mmc_card *card)
{
struct mmc_blk_data *part_md;
struct mmc_blk_data *md = mmc_get_drvdata(card);

if (md) {
pm_runtime_get_sync(&card->dev);
mmc_queue_suspend(&md->queue);
list_for_each_entry(part_md, &md->part, part) {
mmc_queue_suspend(&part_md->queue);
Expand All @@ -2371,6 +2418,17 @@ static int mmc_blk_suspend(struct mmc_card *card)
return 0;
}

static void mmc_blk_shutdown(struct mmc_card *card)
{
_mmc_blk_suspend(card);
}

#ifdef CONFIG_PM
static int mmc_blk_suspend(struct mmc_card *card)
{
return _mmc_blk_suspend(card);
}

static int mmc_blk_resume(struct mmc_card *card)
{
struct mmc_blk_data *part_md;
Expand All @@ -2386,6 +2444,7 @@ static int mmc_blk_resume(struct mmc_card *card)
list_for_each_entry(part_md, &md->part, part) {
mmc_queue_resume(&part_md->queue);
}
pm_runtime_put(&card->dev);
}
return 0;
}
Expand All @@ -2402,6 +2461,7 @@ static struct mmc_driver mmc_driver = {
.remove = mmc_blk_remove,
.suspend = mmc_blk_suspend,
.resume = mmc_blk_resume,
.shutdown = mmc_blk_shutdown,
};

static int __init mmc_blk_init(void)
Expand Down
Loading

0 comments on commit bfffbea

Please sign in to comment.