diff options
59 files changed, 1010 insertions, 642 deletions
diff --git a/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml new file mode 100644 index 000000000000..6f569fbfa134 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/brcm,iproc-sdhci.yaml @@ -0,0 +1,63 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/brcm,iproc-sdhci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Broadcom IPROC SDHCI controller + +maintainers: + - Ray Jui <ray.jui@broadcom.com> + - Scott Branden <scott.branden@broadcom.com> + - Nicolas Saenz Julienne <nsaenz@kernel.org> + +allOf: + - $ref: mmc-controller.yaml# + +properties: + compatible: + enum: + - brcm,bcm2835-sdhci + - brcm,bcm2711-emmc2 + - brcm,sdhci-iproc-cygnus + - brcm,sdhci-iproc + + reg: + minItems: 1 + + interrupts: + maxItems: 1 + + clocks: + maxItems: 1 + description: + Handle to core clock for the sdhci controller. + + sdhci,auto-cmd12: + type: boolean + description: Specifies that controller should use auto CMD12 + +required: + - compatible + - reg + - interrupts + - clocks + +unevaluatedProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/irq.h> + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/clock/bcm-cygnus.h> + + mmc@18041000 { + compatible = "brcm,sdhci-iproc-cygnus"; + reg = <0x18041000 0x100>; + interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&lcpll0_clks BCM_CYGNUS_LCPLL0_SDIO_CLK>; + bus-width = <4>; + sdhci,auto-cmd12; + no-1-8-v; + }; +... diff --git a/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt b/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt deleted file mode 100644 index 09d87cc1182a..000000000000 --- a/Documentation/devicetree/bindings/mmc/brcm,sdhci-iproc.txt +++ /dev/null @@ -1,37 +0,0 @@ -Broadcom IPROC SDHCI controller - -This file documents differences between the core properties described -by mmc.txt and the properties that represent the IPROC SDHCI controller. - -Required properties: -- compatible : Should be one of the following - "brcm,bcm2835-sdhci" - "brcm,bcm2711-emmc2" - "brcm,sdhci-iproc-cygnus" - "brcm,sdhci-iproc" - -Use brcm2835-sdhci for the eMMC controller on the BCM2835 (Raspberry Pi) and -bcm2711-emmc2 for the additional eMMC2 controller on BCM2711. - -Use sdhci-iproc-cygnus for Broadcom SDHCI Controllers -restricted to 32bit host accesses to SDHCI registers. - -Use sdhci-iproc for Broadcom SDHCI Controllers that allow standard -8, 16, 32-bit host access to SDHCI register. - -- clocks : The clock feeding the SDHCI controller. - -Optional properties: - - sdhci,auto-cmd12: specifies that controller should use auto CMD12. - -Example: - -sdhci0: sdhci@18041000 { - compatible = "brcm,sdhci-iproc-cygnus"; - reg = <0x18041000 0x100>; - interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&lcpll0_clks BCM_CYGNUS_LCPLL0_SDIO_CLK>; - bus-width = <4>; - sdhci,auto-cmd12; - no-1-8-v; -}; diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml index 802c9df23752..369471814496 100644 --- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml +++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml @@ -103,6 +103,26 @@ properties: Only eMMC HS400 mode need to take care of this property. default: 0 + clocks: + maxItems: 3 + description: + Handle clocks for the sdhc controller. + + clock-names: + items: + - const: ipg + - const: ahb + - const: per + + pinctrl-names: + minItems: 1 + maxItems: 4 + items: + - const: default + - const: state_100mhz + - const: state_200mhz + - const: sleep + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt index 75486cca8054..5e74db69f581 100644 --- a/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt +++ b/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt @@ -5,11 +5,11 @@ by mmc.txt and the properties used by the mmc_spi driver. Required properties: - spi-max-frequency : maximum frequency for this device (Hz). -- voltage-ranges : two cells are required, first cell specifies minimum - slot voltage (mV), second cell specifies maximum slot voltage (mV). - Several ranges could be specified. Optional properties: +- voltage-ranges : two cells are required, first cell specifies minimum + slot voltage (mV), second cell specifies maximum slot voltage (mV). + Several ranges could be specified. If not provided, 3.2v..3.4v is assumed. - gpios : may specify GPIOs in this order: Card-Detect GPIO, Write-Protect GPIO. Note that this does not follow the binding from mmc.txt, for historical reasons. diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml index 01630b0ecea7..8648d48dbbfd 100644 --- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml +++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml @@ -31,6 +31,7 @@ properties: - const: mediatek,mt2701-mmc - items: - const: mediatek,mt8192-mmc + - const: mediatek,mt8195-mmc - const: mediatek,mt8183-mmc clocks: diff --git a/Documentation/devicetree/bindings/mmc/sdhci-of-dwcmshc.txt b/Documentation/devicetree/bindings/mmc/sdhci-of-dwcmshc.txt deleted file mode 100644 index ee4253b33be2..000000000000 --- a/Documentation/devicetree/bindings/mmc/sdhci-of-dwcmshc.txt +++ /dev/null @@ -1,20 +0,0 @@ -* Synopsys DesignWare Cores Mobile Storage Host Controller - -Required properties: -- compatible: should be one of the following: - "snps,dwcmshc-sdhci" -- reg: offset and length of the register set for the device. -- interrupts: a single interrupt specifier. -- clocks: Array of clocks required for SDHCI; requires at least one for - core clock. -- clock-names: Array of names corresponding to clocks property; shall be - "core" for core clock and "bus" for optional bus clock. - -Example: - sdhci2: sdhci@aa0000 { - compatible = "snps,dwcmshc-sdhci"; - reg = <0xaa0000 0x1000>; - interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&emmcclk>; - bus-width = <8>; - } diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml new file mode 100644 index 000000000000..e6c9a2f77cc7 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: GPL-2.0-only +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/snps,dwcmshc-sdhci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Synopsys Designware Mobile Storage Host Controller Binding + +maintainers: + - Ulf Hansson <ulf.hansson@linaro.org> + - Jisheng Zhang <Jisheng.Zhang@synaptics.com> + +allOf: + - $ref: mmc-controller.yaml# + +properties: + compatible: + enum: + - rockchip,rk3568-dwcmshc + - snps,dwcmshc-sdhci + + reg: + minItems: 1 + items: + - description: Offset and length of the register set for the device + + interrupts: + maxItems: 1 + + clocks: + minItems: 1 + items: + - description: core clock + - description: bus clock for optional + - description: axi clock for rockchip specified + - description: block clock for rockchip specified + - description: timer clock for rockchip specified + + + clock-names: + minItems: 1 + items: + - const: core + - const: bus + - const: axi + - const: block + - const: timer + + rockchip,txclk-tapnum: + description: Specify the number of delay for tx sampling. + $ref: /schemas/types.yaml#/definitions/uint8 + + +required: + - compatible + - reg + - interrupts + - clocks + - clock-names + +unevaluatedProperties: false + +examples: + - | + mmc@fe310000 { + compatible = "rockchip,rk3568-dwcmshc"; + reg = <0xfe310000 0x10000>; + interrupts = <0 25 0x4>; + clocks = <&cru 17>, <&cru 18>, <&cru 19>, <&cru 20>, <&cru 21>; + clock-names = "core", "bus", "axi", "block", "timer"; + bus-width = <8>; + #address-cells = <1>; + #size-cells = <0>; + }; + - | + mmc@aa0000 { + compatible = "snps,dwcmshc-sdhci"; + reg = <0xaa000 0x1000>; + interrupts = <0 25 0x4>; + clocks = <&cru 17>, <&cru 18>; + clock-names = "core", "bus"; + bus-width = <8>; + #address-cells = <1>; + #size-cells = <0>; + }; + +... diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c index 12bc3f5a6cbb..bb1065990aeb 100644 --- a/drivers/memstick/core/memstick.c +++ b/drivers/memstick/core/memstick.c @@ -331,18 +331,17 @@ static int h_memstick_read_dev_id(struct memstick_dev *card, sizeof(struct ms_id_register)); *mrq = &card->current_mrq; return 0; - } else { - if (!(*mrq)->error) { - memcpy(&id_reg, (*mrq)->data, sizeof(id_reg)); - card->id.match_flags = MEMSTICK_MATCH_ALL; - card->id.type = id_reg.type; - card->id.category = id_reg.category; - card->id.class = id_reg.class; - dev_dbg(&card->dev, "if_mode = %02x\n", id_reg.if_mode); - } - complete(&card->mrq_complete); - return -EAGAIN; } + if (!(*mrq)->error) { + memcpy(&id_reg, (*mrq)->data, sizeof(id_reg)); + card->id.match_flags = MEMSTICK_MATCH_ALL; + card->id.type = id_reg.type; + card->id.category = id_reg.category; + card->id.class = id_reg.class; + dev_dbg(&card->dev, "if_mode = %02x\n", id_reg.if_mode); + } + complete(&card->mrq_complete); + return -EAGAIN; } static int h_memstick_set_rw_addr(struct memstick_dev *card, diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index afb892e7ffc6..cf7fe0d58ee7 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c @@ -1382,7 +1382,8 @@ static int mspro_block_resume(struct memstick_dev *card) new_msb->card = card; memstick_set_drvdata(card, new_msb); - if (mspro_block_init_card(card)) + rc = mspro_block_init_card(card); + if (rc) goto out_free; for (cnt = 0; new_msb->attr_group.attrs[cnt] diff --git a/drivers/memstick/host/r592.c b/drivers/memstick/host/r592.c index d2ef46337191..615a83782e55 100644 --- a/drivers/memstick/host/r592.c +++ b/drivers/memstick/host/r592.c @@ -359,13 +359,15 @@ static void r592_write_fifo_pio(struct r592_device *dev, /* Flushes the temporary FIFO used to make aligned DWORD writes */ static void r592_flush_fifo_write(struct r592_device *dev) { + int ret; u8 buffer[4] = { 0 }; - int len; if (kfifo_is_empty(&dev->pio_fifo)) return; - len = kfifo_out(&dev->pio_fifo, buffer, 4); + ret = kfifo_out(&dev->pio_fifo, buffer, 4); + /* intentionally ignore __must_check return code */ + (void)ret; r592_write_reg_raw_be(dev, R592_FIFO_PIO, *(u32 *)buffer); } diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index d666e24fbe0e..689eb9afeeed 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -539,7 +539,7 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_SANITIZE_START) && (cmd.opcode == MMC_SWITCH)) - return mmc_sanitize(card); + return mmc_sanitize(card, idata->ic.cmd_timeout_ms); mmc_wait_for_req(card->host, &mrq); @@ -573,6 +573,18 @@ static int __mmc_blk_ioctl_cmd(struct mmc_card *card, struct mmc_blk_data *md, } /* + * Make sure to update CACHE_CTRL in case it was changed. The cache + * will get turned back on if the card is re-initialized, e.g. + * suspend/resume or hw reset in recovery. + */ + if ((MMC_EXTRACT_INDEX_FROM_ARG(cmd.arg) == EXT_CSD_CACHE_CTRL) && + (cmd.opcode == MMC_SWITCH)) { + u8 value = MMC_EXTRACT_VALUE_FROM_ARG(cmd.arg) & 1; + + card->ext_csd.cache_ctrl = value; + } + + /* * According to the SD specs, some commands require a delay after * issuing the command. */ @@ -947,7 +959,7 @@ static int mmc_blk_reset(struct mmc_blk_data *md, struct mmc_host *host, md->reset_done |= type; err = mmc_hw_reset(host); /* Ensure we switch back to the correct partition */ - if (err != -EOPNOTSUPP) { + if (err) { struct mmc_blk_data *main_md = dev_get_drvdata(&host->card->dev); int part_err; @@ -1933,8 +1945,9 @@ static void mmc_blk_hsq_req_done(struct mmc_request *mrq) void mmc_blk_mq_complete(struct request *req) { struct mmc_queue *mq = req->q->queuedata; + struct mmc_host *host = mq->card->host; - if (mq->use_cqe) + if (host->cqe_enabled) mmc_blk_cqe_complete_rq(mq, req); else if (likely(!blk_should_fake_timeout(req->q))) mmc_blk_mq_complete_rq(mq, req); @@ -2179,7 +2192,7 @@ out_post_req: static int mmc_blk_wait_for_idle(struct mmc_queue *mq, struct mmc_host *host) { - if (mq->use_cqe) + if (host->cqe_enabled) return host->cqe_ops->cqe_wait_for_idle(host); return mmc_blk_rw_wait(mq, NULL); @@ -2224,11 +2237,15 @@ enum mmc_issued mmc_blk_mq_issue_rq(struct mmc_queue *mq, struct request *req) case MMC_ISSUE_ASYNC: switch (req_op(req)) { case REQ_OP_FLUSH: + if (!mmc_cache_enabled(host)) { + blk_mq_end_request(req, BLK_STS_OK); + return MMC_REQ_FINISHED; + } ret = mmc_blk_cqe_issue_flush(mq, req); break; case REQ_OP_READ: case REQ_OP_WRITE: - if (mq->use_cqe) + if (host->cqe_enabled) ret = mmc_blk_cqe_issue_rw_rq(mq, req); else ret = mmc_blk_mq_issue_rw_rq(mq, req); @@ -2261,6 +2278,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, { struct mmc_blk_data *md; int devidx, ret; + char cap_str[10]; devidx = ida_simple_get(&mmc_blk_ida, 0, max_devices, GFP_KERNEL); if (devidx < 0) { @@ -2365,6 +2383,12 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card, blk_queue_write_cache(md->queue.queue, true, true); } + string_get_size((u64)size, 512, STRING_UNITS_2, + cap_str, sizeof(cap_str)); + pr_info("%s: %s %s %s %s\n", + md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), + cap_str, md->read_only ? "(ro)" : ""); + return md; err_putdisk: @@ -2407,7 +2431,6 @@ static int mmc_blk_alloc_part(struct mmc_card *card, const char *subname, int area_type) { - char cap_str[10]; struct mmc_blk_data *part_md; part_md = mmc_blk_alloc_req(card, disk_to_dev(md->disk), size, default_ro, @@ -2417,11 +2440,6 @@ static int mmc_blk_alloc_part(struct mmc_card *card, part_md->part_type = part_type; list_add(&part_md->part, &md->part); - string_get_size((u64)get_capacity(part_md->disk), 512, STRING_UNITS_2, - cap_str, sizeof(cap_str)); - pr_info("%s: %s %s partition %u %s\n", - part_md->disk->disk_name, mmc_card_id(card), - mmc_card_name(card), part_md->part_type, cap_str); return 0; } @@ -2558,9 +2576,8 @@ static int mmc_blk_alloc_rpmb_part(struct mmc_card *card, string_get_size((u64)size, 512, STRING_UNITS_2, cap_str, sizeof(cap_str)); - pr_info("%s: %s %s partition %u %s, chardev (%d:%d)\n", - rpmb_name, mmc_card_id(card), - mmc_card_name(card), EXT_CSD_PART_CONFIG_ACC_RPMB, cap_str, + pr_info("%s: %s %s %s, chardev (%d:%d)\n", + rpmb_name, mmc_card_id(card), mmc_card_name(card), cap_str, MAJOR(mmc_rpmb_devt), rpmb->id); return 0; @@ -2876,7 +2893,7 @@ static void mmc_blk_remove_debugfs(struct mmc_card *card, static int mmc_blk_probe(struct mmc_card *card) { struct mmc_blk_data *md, *part_md; - char cap_str[10]; + int ret = 0; /* * Check that the card supports the command class(es) we need. @@ -2888,31 +2905,30 @@ static int mmc_blk_probe(struct mmc_card *card) card->complete_wq = alloc_workqueue("mmc_complete", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0); - if (unlikely(!card->complete_wq)) { + if (!card->complete_wq) { pr_err("Failed to create mmc completion workqueue"); return -ENOMEM; } md = mmc_blk_alloc(card); - if (IS_ERR(md)) - return PTR_ERR(md); - - string_get_size((u64)get_capacity(md->disk), 512, STRING_UNITS_2, - cap_str, sizeof(cap_str)); - pr_info("%s: %s %s %s %s\n", - md->disk->disk_name, mmc_card_id(card), mmc_card_name(card), - cap_str, md->read_only ? "(ro)" : ""); + if (IS_ERR(md)) { + ret = PTR_ERR(md); + goto out_free; + } - if (mmc_blk_alloc_parts(card, md)) + ret = mmc_blk_alloc_parts(card, md); + if (ret) goto out; dev_set_drvdata(&card->dev, md); - if (mmc_add_disk(md)) + ret = mmc_add_disk(md); + if (ret) goto out; list_for_each_entry(part_md, &md->part, part) { - if (mmc_add_disk(part_md)) + ret = mmc_add_disk(part_md); + if (ret) goto out; } @@ -2933,10 +2949,12 @@ static int mmc_blk_probe(struct mmc_card *card) return 0; - out: +out: mmc_blk_remove_parts(card, md); mmc_blk_remove_req(md); - return 0; +out_free: + destroy_workqueue(card->complete_wq); + return ret; } static void mmc_blk_remove(struct mmc_card *card) diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 1136b859ddd8..f194940c5974 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -1207,7 +1207,7 @@ int mmc_set_uhs_voltage(struct mmc_host *host, u32 ocr) err = mmc_wait_for_cmd(host, &cmd, 0); if (err) - return err; + goto power_cycle; if (!mmc_host_is_spi(host) && (cmd.resp[0] & R1_ERROR)) return -EIO; @@ -1378,62 +1378,12 @@ void mmc_power_cycle(struct mmc_host *host, u32 ocr) } /* - * Cleanup when the last reference to the bus operator is dropped. - */ -static void __mmc_release_bus(struct mmc_host *host) -{ - WARN_ON(!host->bus_dead); - - host->bus_ops = NULL; -} - -/* - * Increase reference count of bus operator - */ -static inline void mmc_bus_get(struct mmc_host *host) -{ - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - host->bus_refs++; - spin_unlock_irqrestore(&host->lock, flags); -} - -/* - * Decrease reference count of bus operator and free it if - * it is the last reference. - */ -static inline void mmc_bus_put(struct mmc_host *host) -{ - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - host->bus_refs--; - if ((host->bus_refs == 0) && host->bus_ops) - __mmc_release_bus(host); - spin_unlock_irqrestore(&host->lock, flags); -} - -/* * Assign a mmc bus handler to a host. Only one bus handler may control a * host at any given time. */ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops) { - unsigned long flags; - - WARN_ON(!host->claimed); - - spin_lock_irqsave(&host->lock, flags); - - WARN_ON(host->bus_ops); - WARN_ON(host->bus_refs); - host->bus_ops = |
