diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-06-28 10:44:54 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-06-28 10:44:54 -0700 |
commit | ef60eb0eb6e0aaf0aae302cb6362a81b2491e997 (patch) | |
tree | c7898a560884827f335dd2055a60a396d9349937 | |
parent | 43bd8a67cd10e9526656e2bc160e52920bd9e43c (diff) | |
parent | 98b5ce4c08ca85727888fdbd362d574bcfa18e3c (diff) |
Merge tag 'mmc-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC and MEMSTICK updates from Ulf Hansson:
"MMC core:
- Add support for Cache Ctrl for SD cards
- Add support for Power Off Notification for SD cards
- Add support for read/write of the SD function extension registers
- Allow broken eMMC HS400 mode to be disabled via DT
- Allow UHS-I voltage switch for SDSC cards if supported
- Disable command queueing in the ioctl path
- Enable eMMC sleep commands to use HW busy polling to minimize delay
- Extend re-use of the common polling loop to standardize behaviour
- Take into account MMC_CAP_NEED_RSP_BUSY for eMMC HPI commands
MMC host:
- jz4740: Add support for the JZ4775 variant
- sdhci-acpi: Disable write protect detection on Toshiba Encore 2 WT8-B
- sdhci-esdhc-imx: Advertise HS400 support through MMC caps
- sdhci-esdhc-imx: Enable support for system wakeup for SDIO
- sdhci-iproc: Add support for the legacy sdhci controller on the BCM7211
- vub3000: Fix control-request direction
MEMSTICK:
- A couple of fixes/cleanups"
* tag 'mmc-v5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (54 commits)
mmc: sdhci-iproc: Add support for the legacy sdhci controller on the BCM7211
dt-bindings: mmc: sdhci-iproc: Add brcm,bcm7211a0-sdhci
mmc: JZ4740: Add support for JZ4775
dt-bindings: mmc: JZ4740: Add bindings for JZ4775
mmc: sdhci-esdhc-imx: Enable support for system wakeup for SDIO
mmc: Improve function name when aborting a tuning cmd
mmc: sdhci-of-aspeed: Turn down a phase correction warning
mmc: debugfs: add description for module parameter
mmc: via-sdmmc: add a check against NULL pointer dereference
mmc: sdhci-sprd: use sdhci_sprd_writew
mmc: sdhci-esdhc-imx: remove unused is_imx6q_usdhc
mmc: core: Allow UHS-I voltage switch for SDSC cards if supported
mmc: mmc_spi: Imply container_of() to be no-op
mmc: mmc_spi: Drop duplicate 'mmc_spi' in the debug messages
mmc: dw_mmc-pltfm: Remove unused <linux/clk.h>
mmc: sdhci-of-aspeed: Configure the SDHCIs as specified by the devicetree.
mmc: core: Add a missing SPDX license header
mmc: vub3000: fix control-request direction
mmc: sdhci-omap: Use pm_runtime_resume_and_get() to replace open coding
mmc: sdhci_am654: Use pm_runtime_resume_and_get() to replace open coding
...
45 files changed, 987 insertions, 342 deletions
diff --git a/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml index 6f569fbfa134..2f63f2cdeb71 100644 --- a/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml +++ b/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml @@ -21,6 +21,7 @@ properties: - brcm,bcm2711-emmc2 - brcm,sdhci-iproc-cygnus - brcm,sdhci-iproc + - brcm,bcm7211a0-sdhci reg: minItems: 1 diff --git a/Documentation/devicetree/bindings/mmc/ingenic,mmc.yaml b/Documentation/devicetree/bindings/mmc/ingenic,mmc.yaml index 04ba8b7fc054..546480f41141 100644 --- a/Documentation/devicetree/bindings/mmc/ingenic,mmc.yaml +++ b/Documentation/devicetree/bindings/mmc/ingenic,mmc.yaml @@ -19,6 +19,7 @@ properties: - ingenic,jz4740-mmc - ingenic,jz4725b-mmc - ingenic,jz4760-mmc + - ingenic,jz4775-mmc - ingenic,jz4780-mmc - ingenic,x1000-mmc - items: diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml index e141330c1114..25ac8e200970 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml +++ b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml @@ -220,6 +220,11 @@ properties: description: eMMC HS400 enhanced strobe mode is supported + no-mmc-hs400: + $ref: /schemas/types.yaml#/definitions/flag + description: + All eMMC HS400 modes are not supported. + dsr: description: Value the card Driver Stage Register (DSR) should be programmed @@ -358,22 +363,6 @@ additionalProperties: true examples: - | - mmc@ab000000 { - compatible = "sdhci"; - reg = <0xab000000 0x200>; - interrupts = <23>; - bus-width = <4>; - cd-gpios = <&gpio 69 0>; - cd-inverted; - wp-gpios = <&gpio 70 0>; - max-frequency = <50000000>; - keep-power-in-suspend; - wakeup-source; - mmc-pwrseq = <&sdhci0_pwrseq>; - clk-phase-sd-hs = <63>, <72>; - }; - - - | mmc3: mmc@1c12000 { #address-cells = <1>; #size-cells = <0>; @@ -385,9 +374,9 @@ examples: non-removable; mmc-pwrseq = <&sdhci0_pwrseq>; - brcmf: bcrmf@1 { + brcmf: wifi@1 { reg = <1>; - compatible = "brcm,bcm43xx-fmac"; + compatible = "brcm,bcm4329-fmac"; interrupt-parent = <&pio>; interrupts = <10 8>; interrupt-names = "host-wake"; diff --git a/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt b/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt deleted file mode 100644 index 291532ac0446..000000000000 --- a/Documentation/devicetree/bindings/mmc/renesas,mmcif.txt +++ /dev/null @@ -1,53 +0,0 @@ -* Renesas Multi Media Card Interface (MMCIF) Controller - -This file documents differences between the core properties in mmc.txt -and the properties used by the MMCIF device. - - -Required properties: - -- compatible: should be "renesas,mmcif-<soctype>", "renesas,sh-mmcif" as a - fallback. Examples with <soctype> are: - - "renesas,mmcif-r7s72100" for the MMCIF found in r7s72100 SoCs - - "renesas,mmcif-r8a73a4" for the MMCIF found in r8a73a4 SoCs - - "renesas,mmcif-r8a7740" for the MMCIF found in r8a7740 SoCs - - "renesas,mmcif-r8a7742" for the MMCIF found in r8a7742 SoCs - - "renesas,mmcif-r8a7743" for the MMCIF found in r8a7743 SoCs - - "renesas,mmcif-r8a7744" for the MMCIF found in r8a7744 SoCs - - "renesas,mmcif-r8a7745" for the MMCIF found in r8a7745 SoCs - - "renesas,mmcif-r8a7778" for the MMCIF found in r8a7778 SoCs - - "renesas,mmcif-r8a7790" for the MMCIF found in r8a7790 SoCs - - "renesas,mmcif-r8a7791" for the MMCIF found in r8a7791 SoCs - - "renesas,mmcif-r8a7793" for the MMCIF found in r8a7793 SoCs - - "renesas,mmcif-r8a7794" for the MMCIF found in r8a7794 SoCs - - "renesas,mmcif-sh73a0" for the MMCIF found in sh73a0 SoCs - -- interrupts: Some SoCs have only 1 shared interrupt, while others have either - 2 or 3 individual interrupts (error, int, card detect). Below is the number - of interrupts for each SoC: - 1: r8a73a4, r8a7742, r8a7743, r8a7744, r8a7745, r8a7778, r8a7790, r8a7791, - r8a7793, r8a7794 - 2: r8a7740, sh73a0 - 3: r7s72100 - -- clocks: reference to the functional clock - -- dmas: reference to the DMA channels, one per channel name listed in the - dma-names property. -- dma-names: must contain "tx" for the transmit DMA channel and "rx" for the - receive DMA channel. -- max-frequency: Maximum operating clock frequency, driver uses default clock - frequency if it is not set. - - -Example: R8A7790 (R-Car H2) MMCIF0 - - mmcif0: mmc@ee200000 { - compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif"; - reg = <0 0xee200000 0 0x80>; - interrupts = <0 169 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&mstp3_clks R8A7790_CLK_MMCIF0>; - dmas = <&dmac0 0xd1>, <&dmac0 0xd2>; - dma-names = "tx", "rx"; - max-frequency = <97500000>; - }; diff --git a/Documentation/devicetree/bindings/mmc/renesas,mmcif.yaml b/Documentation/devicetree/bindings/mmc/renesas,mmcif.yaml new file mode 100644 index 000000000000..c36ba561c387 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/renesas,mmcif.yaml @@ -0,0 +1,135 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/renesas,mmcif.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Renesas Multi Media Card Interface (MMCIF) Controller + +maintainers: + - Wolfram Sang <wsa+renesas@sang-engineering.com> + +allOf: + - $ref: "mmc-controller.yaml" + +properties: + compatible: + items: + - enum: + - renesas,mmcif-r7s72100 # RZ/A1H + - renesas,mmcif-r8a73a4 # R-Mobile APE6 + - renesas,mmcif-r8a7740 # R-Mobile A1 + - renesas,mmcif-r8a7742 # RZ/G1H + - renesas,mmcif-r8a7743 # RZ/G1M + - renesas,mmcif-r8a7744 # RZ/G1N + - renesas,mmcif-r8a7745 # RZ/G1E + - renesas,mmcif-r8a7778 # R-Car M1A + - renesas,mmcif-r8a7790 # R-Car H2 + - renesas,mmcif-r8a7791 # R-Car M2-W + - renesas,mmcif-r8a7793 # R-Car M2-N + - renesas,mmcif-r8a7794 # R-Car E2 + - renesas,mmcif-sh73a0 # SH-Mobile AG5 + - const: renesas,sh-mmcif + + reg: + maxItems: 1 + + interrupts: true + + clocks: + maxItems: 1 + + power-domains: + maxItems: 1 + + resets: + maxItems: 1 + + dmas: + minItems: 2 + maxItems: 4 + description: + Must contain a list of pairs of references to DMA specifiers, one for + transmission, and one for reception. + + dma-names: + minItems: 2 + maxItems: 4 + items: + enum: + - tx + - rx + + max-frequency: true + +required: + - compatible + - reg + - interrupts + - clocks + - power-domains + +if: + properties: + compatible: + contains: + const: renesas,mmcif-r7s72100 +then: + properties: + interrupts: + items: + - description: Error interrupt + - description: Normal operation interrupt + - description: Card detection interrupt +else: + if: + properties: + compatible: + contains: + enum: + - renesas,mmcif-r8a7740 + - renesas,mmcif-sh73a0 + then: + properties: + interrupts: + items: + - description: Error interrupt + - description: Normal operation interrupt + else: + if: + properties: + compatible: + contains: + enum: + - renesas,mmcif-r8a73a4 + - renesas,mmcif-r8a7778 + then: + properties: + interrupts: + maxItems: 1 + else: + properties: + interrupts: + maxItems: 1 + required: + - resets + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/clock/r8a7790-cpg-mssr.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/power/r8a7790-sysc.h> + + mmcif0: mmc@ee200000 { + compatible = "renesas,mmcif-r8a7790", "renesas,sh-mmcif"; + reg = <0xee200000 0x80>; + interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cpg CPG_MOD 315>; + power-domains = <&sysc R8A7790_PD_ALWAYS_ON>; + resets = <&cpg 315>; + dmas = <&dmac0 0xd1>, <&dmac0 0xd2>, <&dmac1 0xd1>, <&dmac1 0xd2>; + dma-names = "tx", "rx", "tx", "rx"; + max-frequency = <97500000>; + }; diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml index 3762f1c8de96..54fb59820d2b 100644 --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml @@ -29,21 +29,15 @@ properties: - const: rockchip,rk3288-dw-mshc - items: - enum: - # for Rockchip PX30 - rockchip,px30-dw-mshc - # for Rockchip RK3036 + - rockchip,rk1808-dw-mshc - rockchip,rk3036-dw-mshc - # for Rockchip RK322x - rockchip,rk3228-dw-mshc - # for Rockchip RK3308 - rockchip,rk3308-dw-mshc - # for Rockchip RK3328 - rockchip,rk3328-dw-mshc - # for Rockchip RK3368 - rockchip,rk3368-dw-mshc - # for Rockchip RK3399 - rockchip,rk3399-dw-mshc - # for Rockchip RV1108 + - rockchip,rk3568-dw-mshc - rockchip,rv1108-dw-mshc - const: rockchip,rk3288-dw-mshc diff --git a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml index 3a79e39253d2..29399e88ac53 100644 --- a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml +++ b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml @@ -19,7 +19,6 @@ properties: - const: ti,am654-sdhci-5.1 - const: ti,j721e-sdhci-8bit - const: ti,j721e-sdhci-4bit - - const: ti,j721e-sdhci-4bit - const: ti,am64-sdhci-8bit - const: ti,am64-sdhci-4bit - items: diff --git a/drivers/memstick/core/ms_block.c b/drivers/memstick/core/ms_block.c index 8004dd64d09a..d971acd98236 100644 --- a/drivers/memstick/core/ms_block.c +++ b/drivers/memstick/core/ms_block.c @@ -129,7 +129,7 @@ static int msb_sg_compare_to_buffer(struct scatterlist *sg, * Each zone consists of 512 eraseblocks, out of which in first * zone 494 are used and 496 are for all following zones. * Therefore zone #0 hosts blocks 0-493, zone #1 blocks 494-988, etc... -*/ + */ static int msb_get_zone_from_lba(int lba) { if (lba < 494) @@ -348,8 +348,9 @@ again: switch (msb->state) { case MSB_RP_SEND_BLOCK_ADDRESS: /* msb_write_regs sometimes "fails" because it needs to update - the reg window, and thus it returns request for that. - Then we stay in this state and retry */ + * the reg window, and thus it returns request for that. + * Then we stay in this state and retry + */ if (!msb_write_regs(msb, offsetof(struct ms_register, param), sizeof(struct ms_param_register), @@ -368,7 +369,8 @@ again: case MSB_RP_SEND_INT_REQ: msb->state = MSB_RP_RECEIVE_INT_REQ_RESULT; /* If dont actually need to send the int read request (only in - serial mode), then just fall through */ + * serial mode), then just fall through + */ if (msb_read_int_reg(msb, -1)) return 0; fallthrough; @@ -702,7 +704,8 @@ static int h_msb_parallel_switch(struct memstick_dev *card, case MSB_PS_SWICH_HOST: /* Set parallel interface on our side + send a dummy request - to see if card responds */ + * to see if card responds + */ host->set_param(host, MEMSTICK_INTERFACE, MEMSTICK_PAR4); memstick_init_req(mrq, MS_TPC_GET_INT, NULL, 1); msb->state = MSB_PS_CONFIRM; @@ -821,6 +824,7 @@ static int msb_mark_page_bad(struct msb_data *msb, int pba, int page) static int msb_erase_block(struct msb_data *msb, u16 pba) { int error, try; + if (msb->read_only) return -EROFS; @@ -997,6 +1001,7 @@ static int msb_write_block(struct msb_data *msb, u16 pba, u32 lba, struct scatterlist *sg, int offset) { int error, current_try = 1; + BUG_ON(sg->length < msb->page_size); if (msb->read_only) @@ -1045,11 +1050,12 @@ static int msb_write_block(struct msb_data *msb, error = msb_run_state_machine(msb, h_msb_write_block); /* Sector we just wrote to is assumed erased since its pba - was erased. If it wasn't erased, write will succeed - and will just clear the bits that were set in the block - thus test that what we have written, - matches what we expect. - We do trust the blocks that we erased */ + * was erased. If it wasn't erased, write will succeed + * and will just clear the bits that were set in the block + * thus test that what we have written, + * matches what we expect. + * We do trust the blocks that we erased + */ if (!error && (verify_writes || !test_bit(pba, msb->erased_blocks_bitmap))) error = msb_verify_block(msb, pba, sg, offset); @@ -1493,6 +1499,7 @@ static int msb_ftl_scan(struct msb_data *msb) static void msb_cache_flush_timer(struct timer_list *t) { struct msb_data *msb = from_timer(msb, t, cache_flush_timer); + msb->need_flush_cache = true; queue_work(msb->io_queue, &msb->io_work); } @@ -1673,7 +1680,8 @@ static int msb_cache_read(struct msb_data *msb, int lba, * This table content isn't that importaint, * One could put here different values, providing that they still * cover whole disk. - * 64 MB entry is what windows reports for my 64M memstick */ + * 64 MB entry is what windows reports for my 64M memstick + */ static const struct chs_entry chs_table[] = { /* size sectors cylynders heads */ @@ -1706,8 +1714,9 @@ static int msb_init_card(struct memstick_dev *card) return error; /* Due to a bug in Jmicron driver written by Alex Dubov, - its serial mode barely works, - so we switch to parallel mode right away */ + * its serial mode barely works, + * so we switch to parallel mode right away + */ if (host->caps & MEMSTICK_CAP_PAR4) msb_switch_to_parallel(msb); @@ -2033,6 +2042,7 @@ static blk_status_t msb_queue_rq(struct blk_mq_hw_ctx *hctx, static int msb_check_card(struct memstick_dev *card) { struct msb_data *msb = memstick_get_drvdata(card); + return (msb->card_dead == 0); } @@ -2333,6 +2343,7 @@ static struct memstick_driver msb_driver = { static int __init msb_init(void) { int rc = memstick_register_driver(&msb_driver); + if (rc) pr_err("failed to register memstick driver (error %d)\n", rc); diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c index 102dbb8080da..29271ad4728a 100644 --- a/drivers/memstick/host/rtsx_usb_ms.c +++ b/drivers/memstick/host/rtsx_usb_ms.c @@ -799,9 +799,9 @@ static int rtsx_usb_ms_drv_probe(struct platform_device *pdev) return 0; err_out: - memstick_free_host(msh); pm_runtime_disable(ms_dev(host)); pm_runtime_put_noidle(ms_dev(host)); + memstick_free_host(msh); return err; } @@ -828,9 +828,6 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev) } mutex_unlock(&host->host_mutex); - memstick_remove_host(msh); - memstick_free_host(msh); - /* Balance possible unbalanced usage count * e.g. unconditional module removal */ @@ -838,10 +835,11 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev) pm_runtime_put(ms_dev(host)); pm_runtime_disable(ms_dev(host)); - platform_set_drvdata(pdev, NULL); - + memstick_remove_host(msh); dev_dbg(ms_dev(host), ": Realtek USB Memstick controller has been removed\n"); + memstick_free_host(msh); + platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 689eb9afeeed..88f4c215caa6 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Block driver for media (i.e., flash cards) * @@ -1004,6 +1005,12 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req) switch (mq_rq->drv_op) { case MMC_DRV_OP_IOCTL: + if (card->ext_csd.cmdq_en) { + ret = mmc_cmdq_disable(card); + if (ret) + break; + } + fallthrough; case MMC_DRV_OP_IOCTL_RPMB: idata = mq_rq->drv_op_data; for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) { @@ -1014,6 +1021,8 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req) /* Always switch back to main area after RPMB access */ if (rpmb_ioctl) mmc_blk_part_switch(card, 0); + else if (card->reenable_cmdq && !card->ext_csd.cmdq_en) + mmc_cmdq_enable(card); break; case MMC_DRV_OP_BOOT_WP: ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, @@ -1159,7 +1168,7 @@ static void mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req) struct mmc_card *card = md->queue.card; int ret = 0; - ret = mmc_flush_cache(card); + ret = mmc_flush_cache(card->host); blk_mq_end_request(req, ret ? BLK_STS_IOERR : BLK_STS_OK); } diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index f194940c5974..b039dcff17f8 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1582,7 +1582,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, { struct mmc_command cmd = {}; unsigned int qty = 0, busy_timeout = 0; - bool use_r1b_resp = false; + bool use_r1b_resp; int err; mmc_retune_hold(card->host); @@ -1650,23 +1650,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, cmd.opcode = MMC_ERASE; cmd.arg = arg; busy_timeout = mmc_erase_timeout(card, arg, qty); - /* - * If the host controller supports busy signalling and the timeout for - * the erase operation does not exceed the max_busy_timeout, we should - * use R1B response. Or we need to prevent the host from doing hw busy - * detection, which is done by converting to a R1 response instead. - * Note, some hosts requires R1B, which also means they are on their own - * when it comes to deal with the busy timeout. - */ - if (!(card->host->caps & MMC_CAP_NEED_RSP_BUSY) && - card->host->max_busy_timeout && - busy_timeout > card->host->max_busy_timeout) { - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; - } else { - cmd.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; - cmd.busy_timeout = busy_timeout; - use_r1b_resp = true; - } + use_r1b_resp = mmc_prepare_busy_cmd(card->host, &cmd, busy_timeout); err = mmc_wait_for_cmd(card->host, &cmd, 0); if (err) { @@ -1687,7 +1671,7 @@ static int mmc_do_erase(struct mmc_card *card, unsigned int from, goto out; /* Let's poll to find out when the erase operation completes. */ - err = mmc_poll_for_busy(card, busy_timeout, MMC_BUSY_ERASE); + err = mmc_poll_for_busy(card, busy_timeout, false, MMC_BUSY_ERASE); out: mmc_retune_release(card->host); diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index db3c9c68875d..0c4de2030b3f 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -30,6 +30,7 @@ struct mmc_bus_ops { int (*hw_reset)(struct mmc_host *); int (*sw_reset)(struct mmc_host *); bool (*cache_enabled)(struct mmc_host *); + int (*flush_cache)(struct mmc_host *); }; void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); @@ -172,4 +173,12 @@ static inline bool mmc_cache_enabled(struct mmc_host *host) return false; } +static inline int mmc_flush_cache(struct mmc_host *host) +{ + if (host->bus_ops->flush_cache) + return host->bus_ops->flush_cache(host); + + return 0; +} + #endif diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index 9ec84c86c46a..3fdbc801e64a 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c @@ -26,6 +26,7 @@ static DECLARE_FAULT_ATTR(fail_default_attr); static char *fail_request; module_param(fail_request, charp, 0); +MODULE_PARM_DESC(fail_request, "default fault injection attributes"); #endif /* CONFIG_FAIL_MMC_REQUEST */ diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 0b0577990ddc..eda4a1892c33 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -388,6 +388,9 @@ int mmc_of_parse(struct mmc_host *host) host->caps2 |= MMC_CAP2_NO_SD; if (device_property_read_bool(dev, "no-mmc")) host->caps2 |= MMC_CAP2_NO_MMC; + if (device_property_read_bool(dev, "no-mmc-hs400")) + host->caps2 &= ~(MMC_CAP2_HS400_1_8V | MMC_CAP2_HS400_1_2V | + MMC_CAP2_HS400_ES); /* Must be after "non-removable" check */ if (device_property_read_u32(dev, "fixed-emmc-driver-type", &drv_type) == 0) { diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 8674c3e0c02c..838726b68ff3 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -28,6 +28,7 @@ #define DEFAULT_CMD6_TIMEOUT_MS 500 #define MIN_CACHE_EN_TIMEOUT_MS 1600 +#define CACHE_FLUSH_TIMEOUT_MS 30000 /* 30s */ static const unsigned int tran_exp[] = { 10000, 100000, 1000000, 10000000, @@ -1905,11 +1906,20 @@ static int mmc_can_sleep(struct mmc_card *card) return card->ext_csd.rev >= 3; } +static int mmc_sleep_busy_cb(void *cb_data, bool *busy) +{ + struct mmc_host *host = cb_data; + + *busy = host->ops->card_busy(host); + return 0; +} + static int mmc_sleep(struct mmc_host *host) { struct mmc_command cmd = {}; struct mmc_card *card = host->card; unsigned int timeout_ms = DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000); + bool use_r1b_resp; int err; /* Re-tuning can't be done once the card is deselected */ @@ -1922,35 +1932,27 @@ static int mmc_sleep(struct mmc_host *host) cmd.opcode = MMC_SLEEP_AWAKE; cmd.arg = card->rca << 16; cmd.arg |= 1 << 15; - - /* - * If the max_busy_timeout of the host is specified, validate it against - * the sleep cmd timeout. A failure means we need to prevent the host - * from doing hw busy detection, which is done by converting to a R1 - * response instead of a R1B. Note, some hosts requires R1B, which also - * means they are on their own when it comes to deal with the busy - * timeout. - */ - if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout && - (timeout_ms > host->max_busy_timeout)) { - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - } else { - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - cmd.busy_timeout = timeout_ms; - } + use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, timeout_ms); err = mmc_wait_for_cmd(host, &cmd, 0); if (err) goto out_release; /* - * If the host does not wait while the card signals busy, then we will - * will have to wait the sleep/awake timeout. Note, we cannot use the - * SEND_STATUS command to poll the status because that command (and most - * others) is invalid while the card sleeps. + * If the host does not wait while the card signals busy, then we can + * try to poll, but only if the host supports HW polling, as the + * SEND_STATUS cmd is not allowed. If we can't poll, then we simply need + * to wait the sleep/awake timeout. */ - if (!cmd.busy_timeout || !(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) + if (host->caps & MMC_CAP_WAIT_WHILE_BUSY && use_r1b_resp) + goto out_release; + + if (!host->ops->card_busy) { mmc_delay(timeout_ms); + goto out_release; + } + + err = __mmc_poll_for_busy(card, timeout_ms, &mmc_sleep_busy_cb, host); out_release: mmc_retune_release(host); @@ -2035,6 +2037,25 @@ static bool _mmc_cache_enabled(struct mmc_host *host) host->card->ext_csd.cache_ctrl & 1; } +/* + * Flush the internal cache of the eMMC to non-volatile storage. + */ +static int _mmc_flush_cache(struct mmc_host *host) +{ + int err = 0; + + if (_mmc_cache_enabled(host)) { + err = mmc_switch(host->card, EXT_CSD_CMD_SET_NORMAL, + EXT_CSD_FLUSH_CACHE, 1, + CACHE_FLUSH_TIMEOUT_MS); + if (err) + pr_err("%s: cache flush error %d\n", + mmc_hostname(host), err); + } + + return err; +} + static int _mmc_suspend(struct mmc_host *host, bool is_suspend) { int err = 0; @@ -2046,7 +2067,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) if (mmc_card_suspended(host->card)) goto out; - err = mmc_flush_cache(host->card); + err = _mmc_flush_cache(host); if (err) goto out; @@ -2187,7 +2208,7 @@ static int _mmc_hw_reset(struct mmc_host *host) * In the case of recovery, we can't expect flushing the cache to work * always, but we have a go and ignore errors. */ - mmc_flush_cache(host->card); + _mmc_flush_cache(host); if ((host->caps & MMC_CAP_HW_RESET) && host->ops->hw_reset && mmc_can_reset(card)) { @@ -2215,6 +2236,7 @@ static const struct mmc_bus_ops mmc_ops = { .shutdown = mmc_shutdown, .hw_reset = _mmc_hw_reset, .cache_enabled = _mmc_cache_enabled, + .flush_cache = _mmc_flush_cache, }; /* diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 5756781fef37..973756ed4016 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -20,7 +20,6 @@ #include "mmc_ops.h" #define MMC_BKOPS_TIMEOUT_MS (120 * 1000) /* 120s */ -#define MMC_CACHE_FLUSH_TIMEOUT_MS (30 * 1000) /* 30s */ #define MMC_SANITIZE_TIMEOUT_MS (240 * 1000) /* 240s */ static const u8 tuning_blk_pattern_4bit[] = { @@ -53,6 +52,12 @@ static const u8 tuning_blk_pattern_8bit[] = { 0xff, 0x77, 0x77, 0xff, 0x77, 0xbb, 0xdd, 0xee, }; +struct mmc_busy_data { + struct mmc_card *card; + bool retry_crc_err; + enum mmc_busy_cmd busy_cmd; +}; + int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries) { int err; @@ -246,9 +251,8 @@ mmc_send_cxd_native(struct mmc_host *host, u32 arg, u32 *cxd, int opcode) * NOTE: void *buf, caller for the buf is required to use DMA-capable * buffer or on-stack buffer (with some overhead in callee). */ -static int -mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, - u32 opcode, void *buf, unsigned len) +int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode, + u32 args, void *buf, unsigned len) { struct mmc_request mrq = {}; struct mmc_command cmd = {}; @@ -259,7 +263,7 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, mrq.data = &data; cmd.opcode = opcode; - cmd.arg = 0; + cmd.arg = args; /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we * rely on callers to never use this with "native" calls for reading @@ -305,7 +309,7 @@ static int mmc_spi_send_cxd(struct mmc_host *host, u32 *cxd, u32 opcode) if (!cxd_tmp) return -ENOMEM; - ret = mmc_send_cxd_data(NULL, host, opcode, cxd_tmp, 16); + ret = mmc_send_adtc_data(NULL, host, opcode, 0, cxd_tmp, 16); if (ret) goto err; @@ -353,7 +357,7 @@ int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd) if (!ext_csd) return -ENOMEM; - err = mmc_send_cxd_data(card, card->host, MMC_SEND_EXT_CSD, ext_csd, + err = mmc_send_adtc_data(card, card->host, MMC_SEND_EXT_CSD, 0, ext_csd, 512); if (err) kfree(ext_csd); @@ -424,10 +428,10 @@ int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal) return mmc_switch_status_error(card->host, status); } -static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, - enum mmc_busy_cmd busy_cmd, bool *busy) +static int mmc_busy_cb(void *cb_data, bool *busy) { - struct mmc_host *host = card->host; + struct mmc_busy_data *data = cb_data; + struct mmc_host *host = data->card->host; u32 status = 0; int err; @@ -436,22 +440,23 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, return 0; } - err = mmc_send_status(card, &status); - if (retry_crc_err && err == -EILSEQ) { + err = mmc_send_status(data->card, &status); + if (data->retry_crc_err && err == -EILSEQ) { *busy = true; return 0; } if (err) return err; - switch (busy_cmd) { + switch (data->busy_cmd) { case MMC_BUSY_CMD6: - err = mmc_switch_status_error(card->host, status); + err = mmc_switch_status_error(host, status); break; case MMC_BUSY_ERASE: err = R1_STATUS(status) ? -EIO : 0; break; case MMC_BUSY_HPI: + case MMC_BUSY_EXTR_SINGLE: break; default: err = -EINVAL; @@ -464,9 +469,9 @@ static int mmc_busy_status(struct mmc_card *card, bool retry_crc_err, return 0; } -static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, - bool send_status, bool retry_crc_err, - enum mmc_busy_cmd busy_cmd) +int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + int (*busy_cb)(void *cb_data, bool *busy), + void *cb_data) { struct mmc_host *host = card->host; int err; @@ -475,16 +480,6 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, bool expired = false; bool busy = false; - /* - * In cases when not allowed to poll by using CMD13 or because we aren't - * capable of polling by using ->card_busy(), then rely on waiting the - * stated timeout to be sufficient. - */ - if (!send_status && !host->ops->card_busy) { - mmc_delay(timeout_ms); - return 0; - } - timeout = jiffies + msecs_to_jiffies(timeout_ms) + 1; do { /* @@ -493,7 +488,7 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, */ expired = time_after(jiffies, timeout); - err = mmc_busy_status(card, retry_crc_err, busy_cmd, &busy); + err = (*busy_cb)(cb_data, &busy); if (err) return err; @@ -516,9 +511,36 @@ static int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, } int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, - enum mmc_busy_cmd busy_cmd) + bool retry_crc_err, enum mmc_busy_cmd busy_cmd) +{ + struct mmc_busy_data cb_data; + + cb_data.card = card; + cb_data.retry_crc_err = retry_crc_err; + cb_data.busy_cmd = busy_cmd; + + return __mmc_poll_for_busy(card, timeout_ms, &mmc_busy_cb, &cb_data); +} + +bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, + unsigned int timeout_ms) { - return __mmc_poll_for_busy(card, timeout_ms, true, false, busy_cmd); + /* + * If the max_busy_timeout of the host is specified, make sure it's + * enough to fit the used timeout_ms. In case it's not, let's instruct + * the host to avoid HW busy detection, by converting to a R1 response + * instead of a R1B. Note, some hosts requires R1B, which also means + * they are on their own when it comes to deal with the busy timeout. + */ + if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout && + (timeout_ms > host->max_busy_timeout)) { + cmd->flags = MMC_CMD_AC | MMC_RSP_SPI_R1 | MMC_RSP_R1; + return false; + } + + cmd->flags = MMC_CMD_AC | MMC_RSP_SPI_R1B | MMC_RSP_R1B; + cmd->busy_timeout = timeout_ms; + return true; } /** @@ -543,7 +565,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, struct mmc_host *host = card->host; int err; struct mmc_command cmd = {}; - bool use_r1b_resp = true; + bool use_r1b_resp; unsigned char old_timing = host->ios.timing; mmc_retune_hold(host); @@ -554,29 +576,12 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, timeout_ms = card->ext_csd.generic_cmd6_time; } - /* - * If the max_busy_timeout of the host is specified, make sure it's - * enough to fit the used timeout_ms. In case it's not, let's instruct - * the host to avoid HW busy detection, by converting to a R1 response - * instead of a R1B. Note, some hosts requires R1B, which also means - * they are on their own when it comes to deal with the busy timeout. - */ - if (!(host->caps & MMC_CAP_NEED_RSP_BUSY) && host->max_busy_timeout && - (timeout_ms > host->max_busy_timeout)) - use_r1b_resp = false; - cmd.opcode = MMC_SWITCH; cmd.arg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | (index << 16) | (value << 8) | set; - cmd.flags = MMC_CMD_AC; - if (use_r1b_resp) { - cmd.flags |= MMC_RSP_SPI_R1B | MMC_RSP_R1B; - cmd.busy_timeout = timeout_ms; - } else { - cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; - } + use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, timeout_ms); err = mmc_wait_for_cmd(host, &cmd, retries); if (err) @@ -587,9 +592,18 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, mmc_host_is_spi(host)) goto out_tim; + /* + * If the host doesn't support HW polling via the ->card_busy() ops and + * when it's not allowed to poll by using CMD13, then we need to rely on + * waiting the stated timeout to be sufficient. + */ + if (!send_status && !host->ops->card_busy) { + mmc_delay(timeout_ms); + goto out_tim; + } + /* Let's try to poll to find out when the command is completed. */ - err = __mmc_poll_for_busy(card, timeout_ms, send_status, retry_crc_err, - MMC_BUSY_CMD6); + err = mmc_poll_for_busy(card, timeout_ms, retry_crc_err, MMC_BUSY_CMD6); if (err) goto out; @@ -686,7 +700,7 @@ out: } EXPORT_SYMBOL_GPL(mmc_send_tuning); -int mmc_abort_tuning(struct mmc_host *host, u32 opcode) +int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode) { struct mmc_command cmd = {}; @@ -709,7 +723,7 @@ int mmc_abort_tuning(struct mmc_host *host, u32 opcode) return mmc_wait_for_cmd(host, &cmd, 0); } -EXPORT_SYMBOL_GPL(mmc_abort_tuning); +EXPORT_SYMBOL_GPL(mmc_send_abort_tuning); static int mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, @@ -813,28 +827,17 @@ static int mmc_send_hpi_cmd(struct mmc_card *card) { unsigned int busy_timeout_ms = card->ext_csd.out_of_int_time; struct mmc_host *host = card->host; - bool use_r1b_resp = true; + bool use_r1b_resp = false; struct mmc_command cmd = {}; int err; cmd.opcode = card->ext_csd.hpi_cmd; cmd.arg = card->rca << 16 | 1; + cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - /* - * Make sure the host's max_busy_timeout fit the needed timeout for HPI. - * In case it doesn't, let's instruct the host to avoid HW busy - * detection, by using a R1 response instead of R1B. - */ - if (host->max_busy_timeout && busy_timeout_ms > host->max_busy_timeout) - use_r1b_resp = false; - - if (cmd.opcode == MMC_STOP_TRANSMISSION && use_r1b_resp) { - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - cmd.busy_timeout = busy_timeout_ms; - } else { - cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; - use_r1b_resp = false; - } + if (cmd.opcode == MMC_STOP_TRANSMISSION) + use_r1b_resp = mmc_prepare_busy_cmd(host, &cmd, + busy_timeout_ms); err = mmc_wait_for_cmd(host, &cmd, 0); if (err) { @@ -848,7 +851,7 @@ static int mmc_send_hpi_cmd(struct mmc_card *card) return 0; /* Let's poll to find out when the HPI request completes. */ - return mmc_poll_for_busy(card, busy_timeout_ms, MMC_BUSY_HPI); + return mmc_poll_for_busy(card, busy_timeout_ms, false, MMC_BUSY_HPI); } /** @@ -961,26 +964,6 @@ void mmc_run_bkops(struct mmc_card *card) } EXPORT_SYMBOL(mmc_run_bkops); -/* - * Flush the cache to the non-volatile storage. - */ -int mmc_flush_cache(struct mmc_card *card) -{ - int err = 0; - - if (mmc_cache_enabled(card->host)) { - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_FLUSH_CACHE, 1, - MMC_CACHE_FLUSH_TIMEOUT_MS); - if (err) - pr_err("%s: cache flush error %d\n", - mmc_hostname(card->host), err); - } - - return err; -} -EXPORT_SYMBOL(mmc_flush_cache); - static int mmc_cmdq_switch(struct mmc_card *card, bool enable) { u8 val = enable ? EXT_CSD_CMDQ_MODE_ENABLED : 0; diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 7bc1cfb0654c..41ab4f573a31 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -14,10 +14,12 @@ enum mmc_busy_cmd { MMC_BUSY_CMD6, MMC_BUSY_ERASE, MMC_BUSY_HPI, + MMC_BUSY_EXTR_SINGLE, }; struct mmc_host; struct mmc_card; +struct mmc_command; int mmc_select_card(struct mmc_card *card); int mmc_deselect_cards(struct mmc_host *host); @@ -25,6 +27,8 @@ int mmc_set_dsr(struct mmc_host *host); int mmc_go_idle(struct mmc_host *host); int mmc_send_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr); int mmc_set_relative_addr(struct mmc_card *card); +int mmc_send_adtc_data(struct mmc_card *card, struct mmc_host *host, u32 opcode, + u32 args, void *buf, unsigned len); int mmc_send_csd(struct mmc_card *card, u32 *csd); int __mmc_send_status(struct mmc_card *card, u32 *status, unsigned int retries); int mmc_send_status(struct mmc_card *card, u32 *status); @@ -35,15 +39,19 @@ int mmc_bus_test(struct mmc_card *card, u8 bus_width); int mmc_can_ext_csd(struct mmc_card *card); int mmc_get_ext_csd(struct mmc_card *card, u8 **new_ext_csd); int mmc_switch_status(struct mmc_card *card, bool crc_err_fatal); +bool mmc_prepare_busy_cmd(struct mmc_host *host, struct mmc_command *cmd, + unsigned int timeout_ms); +int __mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, + int (*busy_cb)(void *cb_data, bool *busy), + void *cb_data); int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, - enum mmc_busy_cmd busy_cmd); + bool retry_crc_err, enum mmc_busy_cmd busy_cmd); int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms, unsigned char timing, bool send_status, bool retry_crc_err, unsigned int retries); int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms); void mmc_run_bkops(struct mmc_card *card); -int mmc_flush_cache(struct mmc_card *card); int mmc_cmdq_enable(struct mmc_card *card); int mmc_cmdq_disable(struct mmc_card *card); int mmc_sanitize(struct mmc_card *card, unsigned int timeout_ms); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 2c48d6504101..4646b7a03db6 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -66,6 +66,14 @@ static const unsigned int sd_au_size[] = { __res & __mask; \ }) +#define SD_POWEROFF_NOTIFY_TIMEOUT_MS 2000 +#define SD_WRITE_EXTR_SINGLE_TIMEOUT_MS 1000 + +struct sd_busy_data { + struct mmc_card *card; + u8 *reg_buf; +}; + /* * Given the decoded CSD structure, decode the raw CID to our CID structure. */ @@ -222,7 +230,9 @@ static int mmc_decode_scr(struct mmc_card *card) else card->erased_byte = 0x0; - if (scr->sda_spec3) + if (scr->sda_spec4) + scr->cmds = UNSTUFF_BITS(resp, 32, 4); + else if (scr->sda_spec3) scr->cmds = UNSTUFF_BITS(resp, 32, 2); /* SD Spec says: any SD Card shall set at least bits 0 and 2 */ @@ -847,11 +857,13 @@ try_again: return err; /* - * In case CCS and S18A in the response is set, start Signal Voltage - * Switch procedure. SPI mode doesn't support CMD11. + * In case the S18A bit is set in the response, let's start the signal + * voltage switch procedure. SPI mode doesn't support CMD11. + * Note that, according to the spec, the S18A bit is not valid unless + * the CCS bit is set as well. We deliberately deviate from the spec in + * regards to this, which allows UHS-I to be supported for SDSC cards. */ - if (!mmc_host_is_spi(host) && rocr && - ((*rocr & 0x41000000) == 0x41000000)) { + if (!mmc_host_is_spi(host) && rocr && (*rocr & 0x01000000)) { err = mmc_set_uhs_voltage(host, pocr); if (err == -EAGAIN) { retries--; @@ -994,6 +1006,380 @@ static bool mmc_sd_card_using_v18(struct mmc_card *card) (SD_MODE_UHS_SDR50 | SD_MODE_UHS_SDR104 | SD_MODE_UHS_DDR50); } +static int sd_write_ext_reg(struct mmc_card *card, u8 fno, u8 page, u16 offset, + u8 reg_data) +{ + struct mmc_host *host = card->host; + struct mmc_request mrq = {}; + struct mmc_command cmd = {}; + struct mmc_data data = {}; + struct scatterlist sg; + u8 *reg_buf; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + mrq.cmd = &cmd; + mrq.data = &data; + + /* + * Arguments of CMD49: + * [31:31] MIO (0 = memory). + * [30:27] FNO (function number). + * [26:26] MW - mask write mode (0 = disable). + * [25:18] page number. + * [17:9] offset address. + * [8:0] length (0 = 1 byte). + */ + cmd.arg = fno << 27 | page << 18 | offset << 9; + + /* The first byte in the buffer is the data to be written. */ + reg_buf[0] = reg_data; + + data.flags = MMC_DATA_WRITE; + data.blksz = 512; + data.blocks = 1; + data.sg = &sg; + data.sg_len = 1; + sg_init_one(&sg, reg_buf, 512); + + cmd.opcode = SD_WRITE_EXTR_SINGLE; + cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; + + mmc_set_data_timeout(&data, card); + mmc_wait_for_req(host, &mrq); + + kfree(reg_buf); + + /* + * Note that, the SD card is allowed to signal busy on DAT0 up to 1s + * after the CMD49. Although, let's leave this to be managed by the + * caller. + */ + + if (cmd.error) + return cmd.error; + if (data.error) + return data.error; + + return 0; +} + +static int sd_read_ext_reg(struct mmc_card *card, u8 fno, u8 page, + u16 offset, u16 len, u8 *reg_buf) +{ + u32 cmd_args; + + /* + * Command arguments of CMD48: + * [31:31] MIO (0 = memory). + * [30:27] FNO (function number). + * [26:26] reserved (0). + * [25:18] page number. + * [17:9] offset address. + * [8:0] length (0 = 1 byte, 1ff = 512 bytes). + */ + cmd_args = fno << 27 | page << 18 | offset << 9 | (len -1); + + return mmc_send_adtc_data(card, card->host, SD_READ_EXTR_SINGLE, + cmd_args, reg_buf, 512); +} + +static int sd_parse_ext_reg_power(struct mmc_card *card, u8 fno, u8 page, + u16 offset) +{ + int err; + u8 *reg_buf; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* Read the extension register for power management function. */ + err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf); + if (err) { + pr_warn("%s: error %d reading PM func of ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + + /* PM revision consists of 4 bits. */ + card->ext_power.rev = reg_buf[0] & 0xf; + + /* Power Off Notification support at bit 4. */ + if (reg_buf[1] & BIT(4)) + card->ext_power.feature_support |= SD_EXT_POWER_OFF_NOTIFY; + + /* Power Sustenance support at bit 5. */ + if (reg_buf[1] & BIT(5)) + card->ext_power.feature_support |= SD_EXT_POWER_SUSTENANCE; + + /* Power Down Mode support at bit 6. */ + if (reg_buf[1] & BIT(6)) + card->ext_power.feature_support |= SD_EXT_POWER_DOWN_MODE; + + card->ext_power.fno = fno; + card->ext_power.page = page; + card->ext_power.offset = offset; + +out: + kfree(reg_buf); + return err; +} + +static int sd_parse_ext_reg_perf(struct mmc_card *card, u8 fno, u8 page, + u16 offset) +{ + int err; + u8 *reg_buf; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + err = sd_read_ext_reg(card, fno, page, offset, 512, reg_buf); + if (err) { + pr_warn("%s: error %d reading PERF func of ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + + /* PERF revision. */ + card->ext_perf.rev = reg_buf[0]; + + /* FX_EVENT support at bit 0. */ + if (reg_buf[1] & BIT(0)) + card->ext_perf.feature_support |= SD_EXT_PERF_FX_EVENT; + + /* Card initiated self-maintenance support at bit 0. */ + if (reg_buf[2] & BIT(0)) + card->ext_perf.feature_support |= SD_EXT_PERF_CARD_MAINT; + + /* Host initiated self-maintenance support at bit 1. */ + if (reg_buf[2] & BIT(1)) + card->ext_perf.feature_support |= SD_EXT_PERF_HOST_MAINT; + + /* Cache support at bit 0. */ + if (reg_buf[4] & BIT(0)) + card->ext_perf.feature_support |= SD_EXT_PERF_CACHE; + + /* Command queue support indicated via queue depth bits (0 to 4). */ + if (reg_buf[6] & 0x1f) + card->ext_perf.feature_support |= SD_EXT_PERF_CMD_QUEUE; + + card->ext_perf.fno = fno; + card->ext_perf.page = page; + card->ext_perf.offset = offset; + +out: + kfree(reg_buf); + return err; +} + +static int sd_parse_ext_reg(struct mmc_card *card, u8 *gen_info_buf, + u16 *next_ext_addr) +{ + u8 num_regs, fno, page; + u16 sfc, offset, ext = *next_ext_addr; + u32 reg_addr; + + /* + * Parse only one register set per extension, as that is sufficient to + * support the standard functions. This means another 48 bytes in the + * buffer must be available. + */ + if (ext + 48 > 512) + return -EFAULT; + + /* Standard Function Code */ + memcpy(&sfc, &gen_info_buf[ext], 2); + + /* Address to the next extension. */ + memcpy(next_ext_addr, &gen_info_buf[ext + 40], 2); + + /* Number of registers for this extension. */ + num_regs = gen_info_buf[ext + 42]; + + /* We support only one register per extension. */ + if (num_regs != 1) + return 0; + + /* Extension register address. */ + memcpy(®_addr, &gen_info_buf[ext + 44], 4); + + /* 9 bits (0 to 8) contains the offset address. */ + offset = reg_addr & 0x1ff; + + /* 8 bits (9 to 16) contains the page number. */ + page = reg_addr >> 9 & 0xff ; + + /* 4 bits (18 to 21) contains the function number. */ + fno = reg_addr >> 18 & 0xf; + + /* Standard Function Code for power management. */ + if (sfc == 0x1) + return sd_parse_ext_reg_power(card, fno, page, offset); + + /* Standard Function Code for performance enhancement. */ + if (sfc == 0x2) + return sd_parse_ext_reg_perf(card, fno, page, offset); + + return 0; +} + +static int sd_read_ext_regs(struct mmc_card *card) +{ + int err, i; + u8 num_ext, *gen_info_buf; + u16 rev, len, next_ext_addr; + + if (mmc_host_is_spi(card->host)) + return 0; + + if (!(card->scr.cmds & SD_SCR_CMD48_SUPPORT)) + return 0; + + gen_info_buf = kzalloc(512, GFP_KERNEL); + if (!gen_info_buf) + return -ENOMEM; + + /* + * Read 512 bytes of general info, which is found at function number 0, + * at page 0 and with no offset. + */ + err = sd_read_ext_reg(card, 0, 0, 0, 512, gen_info_buf); + if (err) { + pr_warn("%s: error %d reading general info of SD ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + + /* General info structure revision. */ + memcpy(&rev, &gen_info_buf[0], 2); + + /* Length of general info in bytes. */ + memcpy(&len, &gen_info_buf[2], 2); + + /* Number of extensions to be find. */ + num_ext = gen_info_buf[4]; + + /* We support revision 0, but limit it to 512 bytes for simplicity. */ + if (rev != 0 || len > 512) { + pr_warn("%s: non-supported SD ext reg layout\n", + mmc_hostname(card->host)); + goto out; + } + + /* + * Parse the extension registers. The first extension should start + * immediately after the general info header (16 bytes). + */ + next_ext_addr = 16; + for (i = 0; i < num_ext; i++) { + err = sd_parse_ext_reg(card, gen_info_buf, &next_ext_addr); + if (err) { + pr_warn("%s: error %d parsing SD ext reg\n", + mmc_hostname(card->host), err); + goto out; + } + } + +out: + kfree(gen_info_buf); + return err; +} + +static bool sd_cache_enabled(struct mmc_host *host) +{ + return host->card->ext_perf.feature_enabled & SD_EXT_PERF_CACHE; +} + +static int sd_flush_cache(struct mmc_host *host) +{ + struct mmc_card *card = host->card; + u8 *reg_buf, fno, page; + u16 offset; + int err; + + if (!sd_cache_enabled(host)) + return 0; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* + * Set Flush Cache at bit 0 in the performance enhancement register at + * 261 bytes offset. + */ + fno = card->ext_perf.fno; + page = card->ext_perf.page; + offset = card->ext_perf.offset + 261; + + err = sd_write_ext_reg(card, fno, page, offset, BIT(0)); + if (err) { + pr_warn("%s: error %d writing Cache Flush bit\n", + mmc_hostname(host), err); + goto out; + } + + err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, + MMC_BUSY_EXTR_SINGLE); + if (err) + goto out; + + /* + * Read the Flush Cache bit. The card shall reset it, to confirm that + * it's has completed the flushing of the cache. + */ + err = sd_read_ext_reg(card, fno, page, offset, 1, reg_buf); + if (err) { + pr_warn("%s: error %d reading Cache Flush bit\n", + mmc_hostname(host), err); + goto out; + } + + if (reg_buf[0] & BIT(0)) + err = -ETIMEDOUT; +out: + kfree(reg_buf); + return err; +} + +static int sd_enable_cache(struct mmc_card *card) +{ + u8 *reg_buf; + int err; + + card->ext_perf.feature_enabled &= ~SD_EXT_PERF_CACHE; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* + * Set Cache Enable at bit 0 in the performance enhancement register at + * 260 bytes offset. + */ + err = sd_write_ext_reg(card, card->ext_perf.fno, card->ext_perf.page, + card->ext_perf.offset + 260, BIT(0)); + if (err) { + pr_warn("%s: error %d writing Cache Enable bit\n", + mmc_hostname(card->host), err); + goto out; + } + + err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, + MMC_BUSY_EXTR_SINGLE); + if (!err) + card->ext_perf.feature_enabled |= SD_EXT_PERF_CACHE; + +out: + kfree(reg_buf); + return err; +} + /* * Handle the detection and initialisation of a card. * @@ -1142,6 +1528,20 @@ retry: } } + if (!oldcard) { + /* Read/parse the extension registers. */ + err = sd_read_ext_regs(card); + if (err) + goto free_card; + } + + /* Enable internal SD cache if supported. */ + if (card->ext_perf.feature_support & SD_EXT_PERF_CACHE) { + err = sd_enable_cache(card); + if (err) + goto free_card; + } + if (host->cqe_ops && !host->cqe_enabled) { err = host->cqe_ops->cqe_enable(host, card); if (!err) { @@ -1213,21 +1613,84 @@ static void mmc_sd_detect(struct mmc_host *host) } } +static int sd_can_poweroff_notify(struct mmc_card *card) +{ + return card->ext_power.feature_support & SD_EXT_POWER_OFF_NOTIFY; +} + +static int sd_busy_poweroff_notify_cb(void *cb_data, bool *busy) +{ + struct sd_busy_data *data = cb_data; + struct mmc_card *card = data->card; + int err; + + /* + * Read the status register for the power management function. It's at + * one byte offset and is one byte long. The Power Off Notification + * Ready is bit 0. + */ + err = sd_read_ext_reg(card, card->ext_power.fno, card->ext_power.page, + card->ext_power.offset + 1, 1, data->reg_buf); + if (err) { + pr_warn("%s: error %d reading status reg of PM func\n", + mmc_hostname(card->host), err); + return err; + } + + *busy = !(data->reg_buf[0] & BIT(0)); + return 0; +} + +static int sd_poweroff_notify(struct mmc_card *card) +{ + struct sd_busy_data cb_data; + u8 *reg_buf; + int err; + + reg_buf = kzalloc(512, GFP_KERNEL); + if (!reg_buf) + return -ENOMEM; + + /* + * Set the Power Off Notification bit in the power management settings + * register at 2 bytes offset. + */ + err = sd_write_ext_reg(card, card->ext_power.fno, card->ext_power.page, + card->ext_power.offset + 2, BIT(0)); + if (err) { + pr_warn("%s: error %d writing Power Off Notify bit\n", + mmc_hostname(card->host), err); + goto out; + } + + cb_data.card = card; + cb_data.reg_buf = reg_buf; + err = __mmc_poll_for_busy(card, SD_POWEROFF_NOTIFY_TIMEOUT_MS, + &sd_busy_poweroff_notify_cb, &cb_data); + +out: + kfree(reg_buf); + return err; +} + static int _mmc_sd_suspend(struct mmc_host *host) { + struct mmc_card *card = host->card; int err = 0; mmc_claim_host(host); - if (mmc_card_suspended(host->card)) + if (mmc_card_suspended(card)) goto out; - if (!mmc_host_is_spi(host)) + if (sd_can_poweroff_notify(card)) + err = sd_poweroff_notify(card); + else if (!mmc_host_is_spi(host)) err = mmc_deselect_cards(host); if (!err) { mmc_power_off(host); - mmc_card_set_suspended(host->card); + mmc_card_set_suspended(card); } out: @@ -1331,6 +1794,8 @@ static const struct mmc_bus_ops mmc_sd_ops = { .alive = mmc_sd_alive, .shutdown = mmc_sd_suspend, .hw_reset = mmc_sd_hw_reset, + .cache_enabled = sd_cache_enabled, + .flush_cache = sd_flush_cache, }; /* diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index d61ff811218c..ef8d1dce5af1 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c @@ -17,6 +17,7 @@ #include "core.h" #include "sd_ops.h" +#include "mmc_ops.h" int mmc_app_cmd(struct mmc_host *host, struct mmc_card *card) { @@ -309,43 +310,18 @@ int mmc_app_send_scr(struct mmc_card *card) int mmc_sd_switch(struct mmc_card *card, int mode, int group, u8 value, u8 *resp) { - struct mmc_request mrq = {}; - struct mmc_command cmd = {}; - struct mmc_data data = {}; - struct scatterlist sg; + u32 cmd_args; /* NOTE: caller guarantees resp is heap-allocated */ mode = !!mode; value &= 0xF; + cmd_args = mode << 31 | 0x00FFFFFF; + cmd_args &= ~(0xF << (group * 4)); + cmd_args |= value << (group * 4); - mrq.cmd = &cmd; - mrq.data = &data; - - cmd.opcode = SD_SWITCH; - cmd.arg = mode << 31 | 0x00FFFFFF; - cmd.arg &= ~(0xF << (group * 4)); - cmd.arg |= value << (group * 4); - cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; - - data.blksz = 64; - data.blocks = 1; - data.flags = MMC_DATA_READ; - data.sg = &sg; - data.sg_len = 1; - - sg_init_one(&sg, resp, 64); - - mmc_set_data_timeout(&data, card); - - mmc_wait_for_req(card->host, &mrq); - - if (cmd.error) - return cmd.error; - if (data.error) - return data.error; - - return 0; + return mmc_send_adtc_data(card, card->host, SD_SWITCH, cmd_args, resp, + 64); } int mmc_app_sd_status(struct mmc_card *card, void *ssr) diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 3eb94ac2712e..68edf7a615be 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -937,11 +937,9 @@ static void mmc_sdio_detect(struct mmc_host *host) /* Make sure card is powered before detecting it */ if (host->caps & MMC_CAP_POWER_OFF_CARD) { - err = pm_runtime_get_sync(&host->card->dev); - if (err < 0) { - pm_runtime_put_noidle(&host->card->dev); + err = pm_runtime_resume_and_get(&host->card->dev); + if (err < 0) goto out; - } } mmc_claim_host(host); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index a4d4c757eea0..561184fa7eb9 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -412,7 +412,7 @@ config MMC_SDHCI_MILBEAUT config MMC_SDHCI_IPROC tristate "SDHCI support for the BCM2835 & iProc SD/MMC Controller" - depends on ARCH_BCM2835 || ARCH_BCM_IPROC || COMPILE_TEST + depends on ARCH_BCM2835 || ARCH_BCM_IPROC || ARCH_BRCMSTB || COMPILE_TEST depends on MMC_SDHCI_PLTFM depends on OF || ACPI default ARCH_BCM_IPROC diff --git a/drivers/mmc/host/cqhci-core.c b/drivers/mmc/host/cqhci-core.c index 93b0432bb601..38559a956330 100644 --- a/drivers/mmc/host/cqhci-core.c +++ b/drivers/mmc/host/cqhci-core.c @@ -45,17 +45,23 @@ static inline u8 *get_link_desc(struct cqhci_host *cq_host, u8 tag) return desc + cq_host->task_desc_len; } +static inline size_t get_trans_desc_offset(struct cqhci_host *cq_host, u8 tag) +{ + return cq_host->trans_desc_len * cq_host->mmc->max_segs * tag; +} + static inline dma_addr_t get_trans_desc_dma(struct cqhci_host *cq_host, u8 tag) { - return cq_host->trans_desc_dma_base + - (cq_host->mmc->max_segs * tag * - cq_host->trans_desc_len); + size_t offset = get_trans_desc_offset(cq_host, tag); + + return cq_host->trans_desc_dma_base + offset; } static inline u8 *get_trans_desc(struct cqhci_host *cq_host, u8 tag) { - return cq_host->trans_desc_base + - (cq_host->trans_desc_len * cq_host->mmc->max_segs * tag); + size_t offset = get_trans_desc_offset(cq_host, tag); + + return cq_host->trans_desc_base + offset; } static void setup_trans_desc(struct cqhci_host *cq_host, u8 tag) @@ -146,7 +152,7 @@ static void cqhci_dumpregs(struct cqhci_host *cq_host) } /* - * The allocated descriptor table for task, link & transfer descritors + * The allocated descriptor table for task, link & transfer descriptors * looks like: * |----------| * |task desc | |->|----------| @@ -194,8 +200,7 @@ static int cqhci_host_alloc_tdl(struct cqhci_host *cq_host) cq_host->desc_size = cq_host->slot_sz * cq_host->num_slots; - cq_host->data_size = cq_host->trans_desc_len * cq_host->mmc->max_segs * - cq_host->mmc->cqe_qdepth; + cq_host->data_size = get_trans_desc_offset(cq_host, cq_host->mmc->cqe_qdepth); pr_debug("%s: cqhci: desc_size: %zu data_sz: %zu slot-sz: %d\n", mmc_hostname(cq_host->mmc), cq_host->desc_size, cq_host->data_size, diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index 73731cd3ba23..9901208be797 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -17,7 +17,6 @@ #include <linux/mmc/host.h> #include <linux/mmc/mmc.h> #include <linux/of.h> -#include <linux/clk.h> #include "dw_mmc.h" #include "dw_mmc-pltfm.h" diff --git a/drivers/mmc/host/jz4740_mmc.c b/drivers/mmc/host/jz4740_mmc.c index b3c636edbb46..0db17bcc9c16 100644 --- a/drivers/mmc/host/jz4740_mmc.c +++ b/drivers/mmc/host/jz4740_mmc.c @@ -674,7 +674,7 @@ static void jz4740_mmc_send_command(struct jz4740_mmc_host *host, cmdat |= JZ_MMC_CMDAT_WRITE; if (host->use_dma) { /* - * The 4780's MMC controller has integrated DMA ability + * The JZ4780's MMC controller has integrated DMA ability * in addition to being able to use the external DMA * controller. It moves DMA control bits to a separate * register. The DMA_SEL bit chooses the external @@ -866,7 +866,7 @@ static int jz4740_mmc_set_clock_rate(struct jz4740_mmc_host *host, int rate) writew(div, host->base + JZ_REG_MMC_CLKRT); if (real_rate > 25000000) { - if (host->version >= JZ_MMC_X1000) { + if (host->version >= JZ_MMC_JZ4780) { writel(JZ_MMC_LPM_DRV_RISING_QTR_PHASE_DLY | JZ_MMC_LPM_SMP_RISING_QTR_OR_HALF_PHASE_DLY | JZ_MMC_LPM_LOW_POWER_MODE_EN, @@ -959,6 +959,7 @@ static const struct of_device_id jz4740_mmc_of_match[] = { { .compatible = "ingenic,jz4740-mmc", .data = (void *) JZ_MMC_JZ4740 }, { .compatible = "ingenic,jz4725b-mmc", .data = (void *)JZ_MMC_JZ4725B }, { .compatible = "ingenic,jz4760-mmc", .data = (void *) JZ_MMC_JZ4760 }, + { .compatible = "ingenic,jz4775-mmc", .data = (void *) JZ_MMC_JZ4780 }, { .compatible = "ingenic,jz4780-mmc", .data = (void *) JZ_MMC_JZ4780 }, { .compatible = "ingenic,x1000-mmc", .data = (void *) JZ_MMC_X1000 }, {}, @@ -1013,7 +1014,6 @@ static int jz4740_mmc_probe(struct platform_device* pdev) host->base = devm_ioremap_resource(&pdev->dev, host->mem_res); if (IS_ERR(host->base)) { ret = PTR_ERR(host->base); - dev_err(&pdev->dev, "Failed to ioremap base memory\n"); goto err_free_host; } diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 9776a03a10f5..65c65bb5737f 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -504,7 +504,7 @@ mmc_spi_command_send(struct mmc_spi_host *host, /* else: R1 (most commands) */ } - dev_dbg(&host->spi->dev, " mmc_spi: CMD%d, resp %s\n", + dev_dbg(&host->spi->dev, " CMD%d, resp %s\n", cmd->opcode, maptype(cmd)); /* send command, leaving chipselect active */ @@ -928,8 +928,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, while (length) { t->len = min(length, blk_size); - dev_dbg(&host->spi->dev, - " mmc_spi: %s block, %d bytes\n", + dev_dbg(&host->spi->dev, " %s block, %d bytes\n", (direction == DMA_TO_DEVICE) ? "write" : "read", t->len); @@ -974,7 +973,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, int tmp; const unsigned statlen = sizeof(scratch->status); - dev_dbg(&spi->dev, " mmc_spi: STOP_TRAN\n"); + dev_dbg(&spi->dev, " STOP_TRAN\n"); /* Tweak the per-block message we set up earlier by morphing * it to hold single buffer with the token followed by some @@ -1175,7 +1174,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) canpower = host->pdata && host->pdata->setpower; - dev_dbg(&host->spi->dev, "mmc_spi: power %s (%d)%s\n", + dev_dbg(&host->spi->dev, "power %s (%d)%s\n", mmc_powerstring(ios->power_mode), ios->vdd, canpower ? ", can switch" : ""); @@ -1248,8 +1247,7 @@ static void mmc_spi_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->spi->max_speed_hz = ios->clock; status = spi_setup(host->spi); - dev_dbg(&host->spi->dev, - "mmc_spi: clock to %d Hz, %d\n", + dev_dbg(&host->spi->dev, " clock to %d Hz, %d\n", host->spi->max_speed_hz, status); } } diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index 898ed1b023df..4dfc246c5f95 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -724,10 +724,8 @@ static inline void msdc_dma_setup(struct msdc_host *host, struct msdc_dma *dma, writel(lower_32_bits(dma->gpd_addr), host->base + MSDC_DMA_SA); } -static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq) +static void msdc_prepare_data(struct msdc_host *host, struct mmc_data *data) { - struct mmc_data *data = mrq->data; - if (!(data->host_cookie & MSDC_PREPARE_FLAG)) { data->host_cookie |= MSDC_PREPARE_FLAG; data->sg_count = dma_map_sg(host->dev, data->sg, data->sg_len, @@ -735,10 +733,8 @@ static void msdc_prepare_data(struct msdc_host *host, struct mmc_request *mrq) } } -static void msdc_unprepare_data(struct msdc_host *host, struct mmc_request *mrq) +static void msdc_unprepare_data(struct msdc_host *host, struct mmc_data *data) { - struct mmc_data *data = mrq->data; - if (data->host_cookie & MSDC_ASYNC_FLAG) return; @@ -1140,7 +1136,7 @@ static void msdc_request_done(struct msdc_host *host, struct mmc_request *mrq) msdc_track_cmd_data(host, mrq->cmd, mrq->data); if (mrq->data) - msdc_unprepare_data(host, mrq); + msdc_unprepare_data(host, mrq->data); if (host->error) msdc_reset_hw(host); mmc_request_done(mmc_from_priv(host), mrq); @@ -1311,7 +1307,7 @@ static void msdc_ops_request(struct mmc_host *mmc, struct mmc_request *mrq) host->mrq = mrq; if (mrq->data) - msdc_prepare_data(host, mrq); + msdc_prepare_data(host, mrq->data); /* if SBC is required, we have HW option and SW option. * if HW option is enabled, and SBC does not have "special" flags, @@ -1332,7 +1328,7 @@ static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq) if (!data) return; - msdc_prepare_data(host, mrq); + msdc_prepare_data(host, data); data->host_cookie |= MSDC_ASYNC_FLAG; } @@ -1340,19 +1336,18 @@ static void msdc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, int err) { struct msdc_host *host = mmc_priv(mmc); - struct mmc_data *data; + struct mmc_data *data = mrq->data; - data = mrq->data; if (!data) return; + if (data->host_cookie) { data->host_cookie &= ~MSDC_ASYNC_FLAG; - msdc_unprepare_data(host, mrq); + msdc_unprepare_data(host, data); } } -static void msdc_data_xfer_next(struct msdc_host *host, - struct mmc_request *mrq, struct mmc_data *data) +static void msdc_data_xfer_next(struct msdc_host *host, struct mmc_request *mrq) { if (mmc_op_multi(mrq->cmd->opcode) && mrq->stop && !mrq->stop->error && !mrq->sbc) @@ -1411,7 +1406,7 @@ static bool msdc_data_xfer_done(struct msdc_host *host, u32 events, (int)data->error, data->bytes_xfered); } - msdc_data_xfer_next(host, mrq, data); + msdc_data_xfer_next(host, mrq); done = true; } return done; diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index 9d480a05f655..3629550528b6 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c @@ -22,8 +22,8 @@ MODULE_LICENSE("GPL"); struct of_mmc_spi { - int detect_irq; struct mmc_spi_platform_data pdata; + int detect_irq; }; static struct of_mmc_spi *to_of_mmc_spi(struct device *dev) diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index baab4c2e1b53..e49ca0f7fe9a 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -704,7 +704,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode) set_bit(i, priv->smpcmp); if (cmd_error) - mmc_abort_tuning(mmc, opcode); + mmc_send_abort_tuning(mmc, opcode); } ret = renesas_sdhi_select_tuning(host); diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 0ca6f6d30b75..8d5929a32d34 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -1578,17 +1578,12 @@ static int s3cmci_probe(struct platform_device *pdev) goto probe_iounmap; } - if (request_irq(host->irq, s3cmci_irq, 0, DRIVER_NAME, host)) { + if (request_irq(host->irq, s3cmci_irq, IRQF_NO_AUTOEN, DRIVER_NAME, host)) { dev_err(&pdev->dev, "failed to request mci interrupt.\n"); ret = -ENOENT; goto probe_iounmap; } - /* We get spurious interrupts even when we have set the IMSK - * register to ignore everything, so use disable_irq() to make - * ensure we don't lock the system with un-serviceable requests. */ - - disable_irq(host->irq); host->irq_state = false; /* Depending on the dma state, get a DMA channel to use. */ diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index c3fbf8c825c4..8fe65f172a61 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -822,6 +822,17 @@ static const struct dmi_system_id sdhci_acpi_quirks[] = { }, .driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT, }, + { + /* + * The Toshiba WT8-B's microSD slot always reports the card being + * write-protected. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TOSHIBA ENCORE 2 WT8-B"), + }, + .driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT, + }, {} /* Terminating entry */ }; diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index b991cf0e60c5..72c0bf0c1887 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -324,11 +324,6 @@ static inline int is_imx53_esdhc(struct pltfm_imx_data *data) return data->socdata == &esdhc_imx53_data; } -static inline int is_imx6q_usdhc(struct pltfm_imx_data *data) -{ - return data->socdata == &usdhc_imx6q_data; -} - static inline int esdhc_is_usdhc(struct pltfm_imx_data *data) { return !!(data->socdata->flags & ESDHC_FLAG_USDHC); @@ -427,9 +422,6 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) | FIELD_PREP(SDHCI_RETUNING_MODE_MASK, SDHCI_TUNING_MODE_3); - if (imx_data->socdata->flags & ESDHC_FLAG_HS400) - val |= SDHCI_SUPPORT_HS400; - /* * Do not advertise faster UHS modes if there are no * pinctrl states for 100MHz/200MHz. @@ -1591,7 +1583,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; if (imx_data->socdata->flags & ESDHC_FLAG_HS400) - host->quirks2 |= SDHCI_QUIRK2_CAPS_BIT63_FOR_HS400; + host->mmc->caps2 |= MMC_CAP2_HS400; if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23) host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN; @@ -1628,6 +1620,14 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (err) goto disable_ahb_clk; + /* + * Setup the wakeup capability here, let user to decide + * whether need to enable this wakeup through sysfs interface. + */ + if ((host->mmc->pm_caps & MMC_PM_KEEP_POWER) && + (host->mmc->pm_caps & MMC_PM_WAKE_SDIO_IRQ)) + device_set_wakeup_capable(&pdev->dev, true); + pm_runtime_set_active(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, 50); pm_runtime_use_autosuspend(&pdev->dev); diff --git a/drivers/mmc/host/sdhci-iproc.c b/drivers/mmc/host/sdhci-iproc.c index ddeaf8e1f72f..cce390fe9cf3 100644 --- a/drivers/mmc/host/sdhci-iproc.c +++ b/drivers/mmc/host/sdhci-iproc.c @@ -286,11 +286,35 @@ static const struct sdhci_iproc_data bcm2711_data = { .mmc_caps = MMC_CAP_3_3V_DDR, }; +static const struct sdhci_pltfm_data sdhci_bcm7211a0_pltfm_data = { + .quirks = SDHCI_QUIRK_MISSING_CAPS | + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | + SDHCI_QUIRK_BROKEN_DMA | + SDHCI_QUIRK_BROKEN_ADMA, + .ops = &sdhci_iproc_ops, +}; + +#define BCM7211A0_BASE_CLK_MHZ 100 +static const struct sdhci_iproc_data bcm7211a0_data = { + .pdata = &sdhci_bcm7211a0_pltfm_data, + .caps = ((BCM7211A0_BASE_CLK_MHZ / 2) << SDHCI_TIMEOUT_CLK_SHIFT) | + (BCM7211A0_BASE_CLK_MHZ << SDHCI_CLOCK_BASE_SHIFT) | + ((0x2 << SDHCI_MAX_BLOCK_SHIFT) + & SDHCI_MAX_BLOCK_MASK) | + SDHCI_CAN_VDD_330 | + SDHCI_CAN_VDD_180 | + SDHCI_CAN_DO_SUSPEND | + SDHCI_CAN_DO_HISPD, + .caps1 = SDHCI_DRIVER_TYPE_C | + SDHCI_DRIVER_TYPE_D, +}; + static const struct of_device_id sdhci_iproc_of_match[] = { { .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data }, { .compatible = "brcm,bcm2711-emmc2", .data = &bcm2711_data }, { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data}, { .compatible = "brcm,sdhci-iproc", .data = &iproc_data }, + { .compatible = "brcm,bcm7211a0-sdhci", .data = &bcm7211a0_data }, { } }; MODULE_DEVICE_TABLE(of, sdhci_iproc_of_match); @@ -384,6 +408,11 @@ err: return ret; } +static void sdhci_iproc_shutdown(struct platform_device *pdev) +{ + sdhci_pltfm_suspend(&pdev->dev); +} + static struct platform_driver sdhci_iproc_driver = { .driver = { .name = "sdhci-iproc", @@ -394,6 +423,7 @@ static struct platform_driver sdhci_iproc_driver = { }, .probe = sdhci_iproc_probe, .remove = sdhci_pltfm_unregister, + .shutdown = sdhci_iproc_shutdown, }; module_platform_driver(sdhci_iproc_driver); diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c index d001c51074a0..6e4e132903a6 100644 --- a/drivers/mmc/host/sdhci-of-aspeed.c +++ b/drivers/mmc/host/sdhci-of-aspeed.c @@ -31,6 +31,11 @@ #define ASPEED_SDC_S0_PHASE_OUT_EN GENMASK(1, 0) #define ASPEED_SDC_PHASE_MAX 31 +/* SDIO{10,20} */ +#define ASPEED_SDC_CAP1_1_8V (0 * 32 + 26) +/* SDIO{14,24} */ +#define ASPEED_SDC_CAP2_SDR104 (1 * 32 + 1) + struct aspeed_sdc { struct clk *clk; struct resource *res; @@ -72,6 +77,37 @@ struct aspeed_sdhci { const struct aspeed_sdhci_phase_desc *phase_desc; }; +/* + * The function sets the mirror register for updating + * capbilities of the current slot. + * + * slot | capability | caps_reg | mirror_reg + * -----|-------------|----------|------------ + * 0 | CAP1_1_8V | SDIO140 | SDIO10 + * 0 | CAP2_SDR104 | SDIO144 | SDIO14 + * 1 | CAP1_1_8V | SDIO240 | SDIO20 + * 1 | CAP2_SDR104 | SDIO244 | SDIO24 + */ +static void aspeed_sdc_set_slot_capability(struct sdhci_host *host, struct aspeed_sdc *sdc, + int capability, bool enable, u8 slot) +{ + u32 mirror_reg_offset; + u32 cap_val; + u8 cap_reg; + + if (slot > 1) + return; + + cap_reg = capability / 32; + cap_val = sdhci_readl(host, 0x40 + (cap_reg * 4)); + if (enable) + cap_val |= BIT(capability % 32); + else + cap_val &= ~BIT(capability % 32); + mirror_reg_offset = ((slot + 1) * 0x10) + (cap_reg * 4); + writel(cap_val, sdc->regs + mirror_reg_offset); +} + static void aspeed_sdc_configure_8bit_mode(struct aspeed_sdc *sdc, struct aspeed_sdhci *sdhci, bool bus8) @@ -150,7 +186,7 @@ static int aspeed_sdhci_phase_to_tap(struct device *dev, unsigned long rate_hz, tap = div_u64(phase_period_ps, prop_delay_ps); if (tap > ASPEED_SDHCI_NR_TAPS) { - dev_warn(dev, + dev_dbg(dev, "Requested out of range phase tap %d for %d degrees of phase compensation at %luHz, clamping to tap %d\n", tap, phase_deg, rate_hz, ASPEED_SDHCI_NR_TAPS); tap = ASPEED_SDHCI_NR_TAPS; @@ -328,6 +364,7 @@ static inline int aspeed_sdhci_calculate_slot(struct aspeed_sdhci *dev, static int aspeed_sdhci_probe(struct platform_device *pdev) { const struct aspeed_sdhci_pdata *aspeed_pdata; + struct device_node *np = pdev->dev.of_node; struct sdhci_pltfm_host *pltfm_host; struct aspeed_sdhci *dev; struct sdhci_host *host; @@ -372,6 +409,17 @@ static int aspeed_sdhci_probe(struct platform_device *pdev) sdhci_get_of_property(pdev); + if (of_property_read_bool(np, "mmc-hs200-1_8v") || + of_property_read_bool(np, "sd-uhs-sdr104")) { + aspeed_sdc_set_slot_capability(host, dev->parent, ASPEED_SDC_CAP1_1_8V, + true, slot); + } + + if (of_property_read_bool(np, "sd-uhs-sdr104")) { + aspeed_sdc_set_slot_capability(host, dev->parent, ASPEED_SDC_CAP2_SDR104, + true, slot); + } + pltfm_host->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(pltfm_host->clk)) return PTR_ERR(pltfm_host->clk); diff --git a/drivers/mmc/host/sdhci-omap.c b/drivers/mmc/host/sdhci-omap.c index 7893fd3599b6..8f4d1f003f65 100644 --- a/drivers/mmc/host/sdhci-omap.c +++ b/drivers/mmc/host/sdhci-omap.c @@ -1173,10 +1173,9 @@ static int sdhci_omap_probe(struct platform_device *pdev) * as part of pm_runtime_get_sync. */ pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); - if (ret < 0) { + ret = pm_runtime_resume_and_get(dev); + if (ret) { dev_err(dev, "pm_runtime_get_sync failed\n"); - pm_runtime_put_noidle(dev); goto err_rpm_disable; } diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index 061618aa247f..4fd99c1e82ba 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -94,7 +94,7 @@ #define PCIE_GLI_9763E_CFG2 0x8A4 #define GLI_9763E_CFG2_L1DLY GENMASK(28, 19) -#define GLI_9763E_CFG2_L1DLY_MID 0x50 +#define GLI_9763E_CFG2_L1DLY_MID 0x54 #define PCIE_GLI_9763E_MMC_CTRL 0x960 #define GLI_9763E_HS400_SLOW BIT(3) @@ -847,7 +847,7 @@ static void gli_set_gl9763e(struct sdhci_pci_slot *slot) pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG2, &value); value &= ~GLI_9763E_CFG2_L1DLY; - /* set ASPM L1 entry delay to 20us */ + /* set ASPM L1 entry delay to 21us */ value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MID); pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG2, value); diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 5dc36efff47f..11e375579cfb 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -393,6 +393,7 @@ static void sdhci_sprd_request_done(struct sdhci_host *host, static struct sdhci_ops sdhci_sprd_ops = { .read_l = sdhci_sprd_readl, .write_l = sdhci_sprd_writel, + .write_w = sdhci_sprd_writew, .write_b = sdhci_sprd_writeb, .set_clock = sdhci_sprd_set_clock, .get_max_clock = sdhci_sprd_get_max_clock, diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index bf238ade1602..6aaf5c3ce34c 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -2680,7 +2680,7 @@ void sdhci_abort_tuning(struct sdhci_host *host, u32 opcode) sdhci_end_tuning(host); - mmc_abort_tuning(host->mmc, opcode); + mmc_send_abort_tuning(host->mmc, opcode); } EXPORT_SYMBOL_GPL(sdhci_abort_tuning); diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 0770c036e2ff..c35ed4be75b7 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -201,8 +201,10 @@ #define SDHCI_CAPABILITIES 0x40 #define SDHCI_TIMEOUT_CLK_MASK GENMASK(5, 0) +#define SDHCI_TIMEOUT_CLK_SHIFT 0 #define SDHCI_TIMEOUT_CLK_UNIT 0x00000080 #define SDHCI_CLOCK_BASE_MASK GENMASK(13, 8) +#define SDHCI_CLOCK_BASE_SHIFT 8 #define SDHCI_CLOCK_V3_BASE_MASK GENMASK(15, 8) #define SDHCI_MAX_BLOCK_MASK 0x00030000 #define SDHCI_MAX_BLOCK_SHIFT 16 diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 1fad6e442688..f654afbe8e83 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -809,11 +809,9 @@ static int sdhci_am654_probe(struct platform_device *pdev) /* Clocks are enabled using pm_runtime */ pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put_noidle(dev); + ret = pm_runtime_resume_and_get(dev); + if (ret) goto pm_runtime_disable; - } base = devm_platform_ioremap_resource(pdev, 1); if (IS_ERR(base)) { diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index 615f3d008af1..b9b79b1089a0 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1801,6 +1801,7 @@ static int usdhi6_probe(struct platform_device *pdev) version = usdhi6_read(host, USDHI6_VERSION); if ((version & 0xfff) != 0xa0d) { + ret = -EPERM; dev_err(dev, "Version not recognized %x\n", version); goto e_clk_off; } diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index a1d098560099..c32df5530b94 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -857,6 +857,9 @@ static void via_sdc_data_isr(struct via_crdr_mmc_host *host, u16 intmask) { BUG_ON(intmask == 0); + if (!host->data) + return; + if (intmask & VIA_CRDR_SDSTS_DT) host->data->error = -ETIMEDOUT; else if (intmask & (VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC)) diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index 739cf63ef6e2..4950d10d3a19 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c @@ -2279,7 +2279,7 @@ static int vub300_probe(struct usb_interface *interface, if (retval < 0) goto error5; retval = - usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0), + usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0), SET_ROM_WAIT_STATES, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, firmware_rom_wait_states, 0x0000, NULL, 0, HZ); diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index f9ad35dd6012..74e6c0624d27 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -139,6 +139,8 @@ struct sd_scr { unsigned char cmds; #define SD_SCR_CMD20_SUPPORT (1<<0) #define SD_SCR_CMD23_SUPPORT (1<<1) +#define SD_SCR_CMD48_SUPPORT (1<<2) +#define SD_SCR_CMD58_SUPPORT (1<<3) }; struct sd_ssr { @@ -189,6 +191,25 @@ struct sd_switch_caps { #define SD_MAX_CURRENT_800 (1 << SD_SET_CURRENT_LIMIT_800) }; +struct sd_ext_reg { + u8 fno; + u8 page; + u16 offset; + u8 rev; + u8 feature_enabled; + u8 feature_support; +/* Power Management Function. */ +#define SD_EXT_POWER_OFF_NOTIFY (1<<0) +#define SD_EXT_POWER_SUSTENANCE (1<<1) +#define SD_EXT_POWER_DOWN_MODE (1<<2) +/* Performance Enhancement Function. */ +#define SD_EXT_PERF_FX_EVENT (1<<0) +#define SD_EXT_PERF_CARD_MAINT (1<<1) +#define SD_EXT_PERF_HOST_MAINT (1<<2) +#define SD_EXT_PERF_CACHE (1<<3) +#define SD_EXT_PERF_CMD_QUEUE (1<<4) +}; + struct sdio_cccr { unsigned int sdio_vsn; unsigned int sd_vsn; @@ -290,6 +311,8 @@ struct mmc_card { struct sd_scr scr; /* extra SD information */ struct sd_ssr ssr; /* yet more SD information */ struct sd_switch_caps sw_caps; /* switch (CMD6) caps */ + struct sd_ext_reg ext_power; /* SD extension reg for PM */ + struct sd_ext_reg ext_perf; /* SD extension reg for PERF */ unsigned int sdio_funcs; /* number of SDIO functions */ atomic_t sdio_funcs_probed; /* number of probed SDIO funcs */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index c7e7b43600e9..0abd47e9ef9b 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -632,6 +632,6 @@ static inline enum dma_data_direction mmc_get_dma_dir(struct mmc_data *data) } int mmc_send_tuning(struct mmc_host *host, u32 opcode, int *cmd_error); -int mmc_abort_tuning(struct mmc_host *host, u32 opcode); +int mmc_send_abort_tuning(struct mmc_host *host, u32 opcode); #endif /* LINUX_MMC_HOST_H */ diff --git a/include/linux/mmc/sd.h b/include/linux/mmc/sd.h index 2236aa540faa..6727576a8755 100644 --- a/include/linux/mmc/sd.h +++ b/include/linux/mmc/sd.h @@ -29,6 +29,10 @@ #define SD_APP_OP_COND 41 /* bcr [31:0] OCR R3 */ #define SD_APP_SEND_SCR 51 /* adtc R1 */ + /* class 11 */ +#define SD_READ_EXTR_SINGLE 48 /* adtc [31:0] R1 */ +#define SD_WRITE_EXTR_SINGLE 49 /* adtc [31:0] R1 */ + /* OCR bit definitions */ #define SD_OCR_S18R (1 << 24) /* 1.8V switching request */ #define SD_ROCR_S18A SD_OCR_S18R /* 1.8V switching accepted by card */ |