diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2021-04-28 15:56:51 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-04-28 15:56:51 -0700 |
commit | be18cd1fcae2ed7db58d92d20733dfa8aa0a5173 (patch) | |
tree | 537192d3bf7f463baa3a06c6f2ed74c2ebf339a2 | |
parent | 6fa09d313921cd960ebb7f87132e49deb034b5f1 (diff) | |
parent | 97fce126e279690105ee15be652b465fd96f9997 (diff) |
Merge tag 'mmc-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
Pull MMC and MEMSTICK updates from Ulf Hansson:
"MMC core:
- Fix hanging on I/O during system suspend for removable cards
- Set read only for SD cards with permanent write protect bit
- Power cycle the SD/SDIO card if CMD11 fails for UHS voltage
- Issue a cache flush for eMMC only when it's enabled
- Adopt to updated cache ctrl settings for eMMC from MMC ioctls
- Use use device property API when parsing voltages
- Don't retry eMMC sanitize cmds
- Use the timeout from the MMC ioctl for eMMC santize cmds
MMC host:
- mmc_spi: Make of_mmc_spi.c resource provider agnostic
- mmc_spi: Use polling for card detect even without voltage-ranges
- sdhci: Check for reset prior to DMA address unmap
- sdhci-acpi: Add support for the AMDI0041 eMMC controller variant
- sdhci-esdhc-imx: Depending on OF Kconfig and cleanup code
- sdhci-pci: Add PCI IDs for Intel LKF
- sdhci-pci: Fix initialization of some SD cards for Intel BYT
- sdhci-pci-gli: Various improvements for GL97xx variants
- sdhci-of-dwcmshc: Enable support for MMC_CAP_WAIT_WHILE_BUSY
- sdhci-of-dwcmshc: Add ACPI support for BlueField-3 SoC
- sdhci-of-dwcmshc: Add Rockchip platform support
- tmio/renesas_sdhi: Extend support for reset and use a reset controller
- tmio/renesas_sdhi: Enable support for MMC_CAP_WAIT_WHILE_BUSY
- tmio/renesas_sdhi: Various improvements
MEMSTICK:
- Minor improvements/cleanups"
* tag 'mmc-v5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc: (79 commits)
mmc: block: Issue a cache flush only when it's enabled
memstick: r592: ignore kfifo_out() return code again
mmc: block: Update ext_csd.cache_ctrl if it was written
mmc: mmc_spi: Make of_mmc_spi.c resource provider agnostic
mmc: mmc_spi: Use already parsed IRQ
mmc: mmc_spi: Drop unused NO_IRQ definition
mmc: mmc_spi: Set up polling even if voltage-ranges is not present
mmc: core: Convert mmc_of_parse_voltage() to use device property API
mmc: core: Correct descriptions in mmc_of_parse()
mmc: dw_mmc-rockchip: Just set default sample value for legacy mode
mmc: sdhci-s3c: constify uses of driver/match data
mmc: sdhci-s3c: correct kerneldoc of sdhci_s3c_drv_data
mmc: sdhci-s3c: simplify getting of_device_id match data
mmc: tmio: always restore irq register
mmc: sdhci-pci-gli: Enlarge ASPM L1 entry delay of GL975x
mmc: core: Let eMMC sanitize not retry in case of timeout/failure
mmc: core: Add a retries parameter to __mmc_switch function
memstick: r592: remove unused variable
mmc: sdhci-st: Remove unnecessary error log
mmc: sdhci-msm: Remove unnecessary error log
...
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 = ops; - host->bus_refs = 1; - host->bus_dead = 0; - - spin_unlock_irqrestore(&host->lock, flags); } /* @@ -1441,18 +1391,7 @@ void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops) */ void mmc_detach_bus(struct mmc_host *host) { - unsigned long flags; - - WARN_ON(!host->claimed); - WARN_ON(!host->bus_ops); - - spin_lock_irqsave(&host->lock, flags); - - host->bus_dead = 1; - - spin_unlock_irqrestore(&host->lock, flags); - - mmc_bus_put(host); + host->bus_ops = NULL; } void _mmc_detect_change(struct mmc_host *host, unsigned long delay, bool cd_irq) @@ -2080,18 +2019,7 @@ int mmc_hw_reset(struct mmc_host *host) { int ret; - if (!host->card) - return -EINVAL; - - mmc_bus_get(host); - if (!host->bus_ops || host->bus_dead || !host->bus_ops->hw_reset) { - mmc_bus_put(host); - return -EOPNOTSUPP; - } - ret = host->bus_ops->hw_reset(host); - mmc_bus_put(host); - if (ret < 0) pr_warn("%s: tried to HW reset card, got error %d\n", mmc_hostname(host), ret); @@ -2104,18 +2032,10 @@ int mmc_sw_reset(struct mmc_host *host) { int ret; - if (!host->card) - return -EINVAL; - - mmc_bus_get(host); - if (!host->bus_ops || host->bus_dead || !host->bus_ops->sw_reset) { - mmc_bus_put(host); + if (!host->bus_ops->sw_reset) return -EOPNOTSUPP; - } ret = host->bus_ops->sw_reset(host); - mmc_bus_put(host); - if (ret) pr_warn("%s: tried to SW reset card, got error %d\n", mmc_hostname(host), ret); @@ -2263,32 +2183,15 @@ void mmc_rescan(struct work_struct *work) host->trigger_card_event = false; } - mmc_bus_get(host); - /* Verify a registered card to be functional, else remove it. */ - if (host->bus_ops && !host->bus_dead) + if (host->bus_ops) host->bus_ops->detect(host); host->detect_change = 0; - /* - * Let mmc_bus_put() free the bus/bus_ops if we've found that - * the card is no longer present. - */ - mmc_bus_put(host); - mmc_bus_get(host); - /* if there still is a card present, stop here */ - if (host->bus_ops != NULL) { - mmc_bus_put(host); + if (host->bus_ops != NULL) goto out; - } - - /* - * Only we can add a new handler, so it's safe to - * release the lock here. - */ - mmc_bus_put(host); mmc_claim_host(host); if (mmc_card_is_removable(host) && host->ops->get_cd && @@ -2351,98 +2254,21 @@ void mmc_stop_host(struct mmc_host *host) /* clear pm flags now and let card drivers set them as needed */ host->pm_flags = 0; - mmc_bus_get(host); - if (host->bus_ops && !host->bus_dead) { + if (host->bus_ops) { /* Calling bus_ops->remove() with a claimed host can deadlock */ host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_power_off(host); mmc_release_host(host); - mmc_bus_put(host); return; } - mmc_bus_put(host); mmc_claim_host(host); mmc_power_off(host); mmc_release_host(host); } -#ifdef CONFIG_PM_SLEEP -/* Do the card removal on suspend if card is assumed removeable - * Do that in pm notifier while userspace isn't yet frozen, so we will be able - to sync the card. -*/ -static int mmc_pm_notify(struct notifier_block *notify_block, - unsigned long mode, void *unused) -{ - struct mmc_host *host = container_of( - notify_block, struct mmc_host, pm_notify); - unsigned long flags; - int err = 0; - - switch (mode) { - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: - case PM_RESTORE_PREPARE: - spin_lock_irqsave(&host->lock, flags); - host->rescan_disable = 1; - spin_unlock_irqrestore(&host->lock, flags); - cancel_delayed_work_sync(&host->detect); - - if (!host->bus_ops) - break; - - /* Validate prerequisites for suspend */ - if (host->bus_ops->pre_suspend) - err = host->bus_ops->pre_suspend(host); - if (!err) - break; - - if (!mmc_card_is_removable(host)) { - dev_warn(mmc_dev(host), - "pre_suspend failed for non-removable host: " - "%d\n", err); - /* Avoid removing non-removable hosts */ - break; - } - - /* Calling bus_ops->remove() with a claimed host can deadlock */ - host->bus_ops->remove(host); - mmc_claim_host(host); - mmc_detach_bus(host); - mmc_power_off(host); - mmc_release_host(host); - host->pm_flags = 0; - break; - - case PM_POST_SUSPEND: - case PM_POST_HIBERNATION: - case PM_POST_RESTORE: - - spin_lock_irqsave(&host->lock, flags); - host->rescan_disable = 0; - spin_unlock_irqrestore(&host->lock, flags); - _mmc_detect_change(host, 0, false); - - } - - return 0; -} - -void mmc_register_pm_notifier(struct mmc_host *host) -{ - host->pm_notify.notifier_call = mmc_pm_notify; - register_pm_notifier(&host->pm_notify); -} - -void mmc_unregister_pm_notifier(struct mmc_host *host) -{ - unregister_pm_notifier(&host->pm_notify); -} -#endif - static int __init mmc_init(void) { int ret; diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 575ac0257af2..db3c9c68875d 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h @@ -29,6 +29,7 @@ struct mmc_bus_ops { int (*shutdown)(struct mmc_host *); int (*hw_reset)(struct mmc_host *); int (*sw_reset)(struct mmc_host *); + bool (*cache_enabled)(struct mmc_host *); }; void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); @@ -93,14 +94,6 @@ int mmc_execute_tuning(struct mmc_card *card); int mmc_hs200_to_hs400(struct mmc_card *card); int mmc_hs400_to_hs200(struct mmc_card *card); -#ifdef CONFIG_PM_SLEEP -void mmc_register_pm_notifier(struct mmc_host *host); -void mmc_unregister_pm_notifier(struct mmc_host *host); -#else -static inline void mmc_register_pm_notifier(struct mmc_host *host) { } -static inline void mmc_unregister_pm_notifier(struct mmc_host *host) { } -#endif - void mmc_wait_for_req_done(struct mmc_host *host, struct mmc_request *mrq); bool mmc_is_req_done(struct mmc_host *host, struct mmc_request *mrq); @@ -171,4 +164,12 @@ static inline void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, host->ops->post_req(host, mrq, err); } +static inline bool mmc_cache_enabled(struct mmc_host *host) +{ + if (host->bus_ops->cache_enabled) + return host->bus_ops->cache_enabled(host); + + return false; +} + #endif diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 9b89a91b6b47..0b0577990ddc 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -35,6 +35,42 @@ static DEFINE_IDA(mmc_host_ida); +#ifdef CONFIG_PM_SLEEP +static int mmc_host_class_prepare(struct device *dev) +{ + struct mmc_host *host = cls_dev_to_mmc_host(dev); + + /* + * It's safe to access the bus_ops pointer, as both userspace and the + * workqueue for detecting cards are frozen at this point. + */ + if (!host->bus_ops) + return 0; + + /* Validate conditions for system suspend. */ + if (host->bus_ops->pre_suspend) + return host->bus_ops->pre_suspend(host); + + return 0; +} + +static void mmc_host_class_complete(struct device *dev) +{ + struct mmc_host *host = cls_dev_to_mmc_host(dev); + + _mmc_detect_change(host, 0, false); +} + +static const struct dev_pm_ops mmc_host_class_dev_pm_ops = { + .prepare = mmc_host_class_prepare, + .complete = mmc_host_class_complete, +}; + +#define MMC_HOST_CLASS_DEV_PM_OPS (&mmc_host_class_dev_pm_ops) +#else +#define MMC_HOST_CLASS_DEV_PM_OPS NULL +#endif + static void mmc_host_classdev_release(struct device *dev) { struct mmc_host *host = cls_dev_to_mmc_host(dev); @@ -46,6 +82,7 @@ static void mmc_host_classdev_release(struct device *dev) static struct class mmc_host_class = { .name = "mmc_host", .dev_release = mmc_host_classdev_release, + .pm = MMC_HOST_CLASS_DEV_PM_OPS, }; int mmc_register_host_class(void) @@ -209,8 +246,8 @@ mmc_of_parse_clk_phase(struct mmc_host *host, struct mmc_clk_phase_map *map) EXPORT_SYMBOL(mmc_of_parse_clk_phase); /** - * mmc_of_parse() - parse host's device-tree node - * @host: host whose node should be parsed. + * mmc_of_parse() - parse host's device properties + * @host: host whose properties should be parsed. * * To keep the rest of the MMC subsystem unaware of whether DT has been * used to to instantiate and configure this host instance or not, we @@ -379,44 +416,62 @@ EXPORT_SYMBOL(mmc_of_parse); /** * mmc_of_parse_voltage - return mask of supported voltages - * @np: The device node need to be parsed. + * @host: host whose properties should be parsed. * @mask: mask of voltages available for MMC/SD/SDIO * - * Parse the "voltage-ranges" DT property, returning zero if it is not + * Parse the "voltage-ranges" property, returning zero if it is not * found, negative errno if the voltage-range specification is invalid, * or one if the voltage-range is specified and successfully parsed. */ -int mmc_of_parse_voltage(struct device_node *np, u32 *mask) +int mmc_of_parse_voltage(struct mmc_host *host, u32 *mask) { - const u32 *voltage_ranges; + const char *prop = "voltage-ranges"; + struct device *dev = host->parent; + u32 *voltage_ranges; int num_ranges, i; + int ret; - voltage_ranges = of_get_property(np, "voltage-ranges", &num_ranges); - if (!voltage_ranges) { - pr_debug("%pOF: voltage-ranges unspecified\n", np); + if (!device_property_present(dev, prop)) { + dev_dbg(dev, "%s unspecified\n", prop); return 0; } - num_ranges = num_ranges / sizeof(*voltage_ranges) / 2; + + ret = device_property_count_u32(dev, prop); + if (ret < 0) + return ret; + + num_ranges = ret / 2; if (!num_ranges) { - pr_err("%pOF: voltage-ranges empty\n", np); + dev_err(dev, "%s empty\n", prop); return -EINVAL; } + voltage_ranges = kcalloc(2 * num_ranges, sizeof(*voltage_ranges), GFP_KERNEL); + if (!voltage_ranges) + return -ENOMEM; + + ret = device_property_read_u32_array(dev, prop, voltage_ranges, 2 * num_ranges); + if (ret) { + kfree(voltage_ranges); + return ret; + } + for (i = 0; i < num_ranges; i++) { const int j = i * 2; u32 ocr_mask; - ocr_mask = mmc_vddrange_to_ocrmask( - be32_to_cpu(voltage_ranges[j]), - be32_to_cpu(voltage_ranges[j + 1])); + ocr_mask = mmc_vddrange_to_ocrmask(voltage_ranges[j + 0], + voltage_ranges[j + 1]); if (!ocr_mask) { - pr_err("%pOF: voltage-range #%d is invalid\n", - np, i); + dev_err(dev, "range #%d in %s is invalid\n", i, prop); + kfree(voltage_ranges); return -EINVAL; } *mask |= ocr_mask; } + kfree(voltage_ranges); + return 1; } EXPORT_SYMBOL(mmc_of_parse_voltage); @@ -538,8 +593,6 @@ int mmc_add_host(struct mmc_host *host) #endif mmc_start_host(host); - mmc_register_pm_notifier(host); - return 0; } @@ -555,7 +608,6 @@ EXPORT_SYMBOL(mmc_add_host); */ void mmc_remove_host(struct mmc_host *host) { - mmc_unregister_pm_notifier(host); mmc_stop_host(host); #ifdef CONFIG_DEBUG_FS diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 8741271d3971..8674c3e0c02c 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1068,7 +1068,7 @@ static int mmc_select_hs(struct mmc_card *card) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, card->ext_csd.generic_cmd6_time, MMC_TIMING_MMC_HS, - true, true); + true, true, MMC_CMD_RETRIES); if (err) pr_warn("%s: switch to high-speed failed, err:%d\n", mmc_hostname(card->host), err); @@ -1100,7 +1100,7 @@ static int mmc_select_hs_ddr(struct mmc_card *card) ext_csd_bits, card->ext_csd.generic_cmd6_time, MMC_TIMING_MMC_DDR52, - true, true); + true, true, MMC_CMD_RETRIES); if (err) { pr_err("%s: switch to bus width %d ddr failed\n", mmc_hostname(host), 1 << bus_width); @@ -1168,7 +1168,7 @@ static int mmc_select_hs400(struct mmc_card *card) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - false, true); + false, true, MMC_CMD_RETRIES); if (err) { pr_err("%s: switch to high-speed from hs200 failed, err:%d\n", mmc_hostname(host), err); @@ -1210,7 +1210,7 @@ static int mmc_select_hs400(struct mmc_card *card) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - false, true); + false, true, MMC_CMD_RETRIES); if (err) { pr_err("%s: switch to hs400 failed, err:%d\n", mmc_hostname(host), err); @@ -1256,7 +1256,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card) val = EXT_CSD_TIMING_HS; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - false, true); + false, true, MMC_CMD_RETRIES); if (err) goto out_err; @@ -1272,7 +1272,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card) /* Switch HS DDR to HS */ err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, EXT_CSD_BUS_WIDTH_8, card->ext_csd.generic_cmd6_time, - 0, false, true); + 0, false, true, MMC_CMD_RETRIES); if (err) goto out_err; @@ -1287,7 +1287,7 @@ int mmc_hs400_to_hs200(struct mmc_card *card) card->drive_strength << EXT_CSD_DRV_STR_SHIFT; err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - false, true); + false, true, MMC_CMD_RETRIES); if (err) goto out_err; @@ -1371,7 +1371,7 @@ static int mmc_select_hs400es(struct mmc_card *card) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, EXT_CSD_TIMING_HS, card->ext_csd.generic_cmd6_time, 0, - false, true); + false, true, MMC_CMD_RETRIES); if (err) { pr_err("%s: switch to hs for hs400es failed, err:%d\n", mmc_hostname(host), err); @@ -1405,7 +1405,7 @@ static int mmc_select_hs400es(struct mmc_card *card) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - false, true); + false, true, MMC_CMD_RETRIES); if (err) { pr_err("%s: switch to hs400es failed, err:%d\n", mmc_hostname(host), err); @@ -1470,7 +1470,7 @@ static int mmc_select_hs200(struct mmc_card *card) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, val, card->ext_csd.generic_cmd6_time, 0, - false, true); + false, true, MMC_CMD_RETRIES); if (err) goto err; old_timing = host->ios.timing; @@ -1975,7 +1975,7 @@ static int mmc_poweroff_notify(struct mmc_card *card, unsigned int notify_type) err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_POWER_OFF_NOTIFICATION, - notify_type, timeout, 0, false, false); + notify_type, timeout, 0, false, false, MMC_CMD_RETRIES); if (err) pr_err("%s: Power Off Notification timed out, %u\n", mmc_hostname(card->host), timeout); @@ -2029,6 +2029,12 @@ static void mmc_detect(struct mmc_host *host) } } +static bool _mmc_cache_enabled(struct mmc_host *host) +{ + return host->card->ext_csd.cache_size > 0 && + host->card->ext_csd.cache_ctrl & 1; +} + static int _mmc_suspend(struct mmc_host *host, bool is_suspend) { int err = 0; @@ -2208,6 +2214,7 @@ static const struct mmc_bus_ops mmc_ops = { .alive = mmc_alive, .shutdown = mmc_shutdown, .hw_reset = _mmc_hw_reset, + .cache_enabled = _mmc_cache_enabled, }; /* diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 265d95ec82ce..5756781fef37 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -296,61 +296,40 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, return 0; } -static int mmc_spi_send_csd(struct mmc_host *host, u32 *csd) +static int mmc_spi_send_cxd(struct mmc_host *host, u32 *cxd, u32 opcode) { int ret, i; - __be32 *csd_tmp; + __be32 *cxd_tmp; - csd_tmp = kzalloc(16, GFP_KERNEL); - if (!csd_tmp) + cxd_tmp = kzalloc(16, GFP_KERNEL); + if (!cxd_tmp) return -ENOMEM; - ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CSD, csd_tmp, 16); + ret = mmc_send_cxd_data(NULL, host, opcode, cxd_tmp, 16); if (ret) goto err; for (i = 0; i < 4; i++) - csd[i] = be32_to_cpu(csd_tmp[i]); + cxd[i] = be32_to_cpu(cxd_tmp[i]); err: - kfree(csd_tmp); + kfree(cxd_tmp); return ret; } int mmc_send_csd(struct mmc_card *card, u32 *csd) { if (mmc_host_is_spi(card->host)) - return mmc_spi_send_csd(card->host, csd); + return mmc_spi_send_cxd(card->host, csd, MMC_SEND_CSD); return mmc_send_cxd_native(card->host, card->rca << 16, csd, MMC_SEND_CSD); } -static int mmc_spi_send_cid(struct mmc_host *host, u32 *cid) -{ - int ret, i; - __be32 *cid_tmp; - - cid_tmp = kzalloc(16, GFP_KERNEL); - if (!cid_tmp) - return -ENOMEM; - - ret = mmc_send_cxd_data(NULL, host, MMC_SEND_CID, cid_tmp, 16); - if (ret) - goto err; - - for (i = 0; i < 4; i++) - cid[i] = be32_to_cpu(cid_tmp[i]); - -err: - kfree(cid_tmp); - return ret; -} - int mmc_send_cid(struct mmc_host *host, u32 *cid) { if (mmc_host_is_spi(host)) - return mmc_spi_send_cid(host, cid); + return mmc_spi_send_cxd(host, cid, MMC_SEND_CID); return mmc_send_cxd_native(host, 0, cid, MMC_ALL_SEND_CID); } @@ -553,12 +532,13 @@ int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, * @timing: new timing to change to * @send_status: send status cmd to poll for busy * @retry_crc_err: retry when CRC errors when polling with CMD13 for busy + * @retries: number of retries * * Modifies the EXT_CSD register for selected card. */ 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) + bool send_status, bool retry_crc_err, unsigned int retries) { struct mmc_host *host = card->host; int err; @@ -598,7 +578,7 @@ int __mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, cmd.flags |= MMC_RSP_SPI_R1 | MMC_RSP_R1; } - err = mmc_wait_for_cmd(host, &cmd, MMC_CMD_RETRIES); + err = mmc_wait_for_cmd(host, &cmd, retries); if (err) goto out; @@ -633,7 +613,7 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value, unsigned int timeout_ms) { return __mmc_switch(card, set, index, value, timeout_ms, 0, - true, false); + true, false, MMC_CMD_RETRIES); } EXPORT_SYMBOL_GPL(mmc_switch); @@ -988,9 +968,7 @@ int mmc_flush_cache(struct mmc_card *card) { int err = 0; - if (mmc_card_mmc(card) && - (card->ext_csd.cache_size > 0) && - (card->ext_csd.cache_ctrl & 1)) { + 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); @@ -1031,7 +1009,7 @@ int mmc_cmdq_disable(struct mmc_card *card) } EXPORT_SYMBOL_GPL(mmc_cmdq_disable); -int mmc_sanitize(struct mmc_card *card) +int mmc_sanitize(struct mmc_card *card, unsigned int timeout_ms) { struct mmc_host *host = card->host; int err; @@ -1041,12 +1019,15 @@ int mmc_sanitize(struct mmc_card *card) return -EOPNOTSUPP; } + if (!timeout_ms) + timeout_ms = MMC_SANITIZE_TIMEOUT_MS; + pr_debug("%s: Sanitize in progress...\n", mmc_hostname(host)); mmc_retune_hold(host); - err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_SANITIZE_START, - 1, MMC_SANITIZE_TIMEOUT_MS); + err = __mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_SANITIZE_START, + 1, timeout_ms, 0, true, false, 0); if (err) pr_err("%s: Sanitize failed err=%d\n", mmc_hostname(host), err); diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 632009260e51..7bc1cfb0654c 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h @@ -39,14 +39,14 @@ int mmc_poll_for_busy(struct mmc_card *card, unsigned int timeout_ms, 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); + 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); +int mmc_sanitize(struct mmc_card *card, unsigned int timeout_ms); #endif diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 27d2b8ed9484..d600e0a4a460 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -60,7 +60,7 @@ enum mmc_issue_type mmc_issue_type(struct mmc_queue *mq, struct request *req) { struct mmc_host *host = mq->card->host; - if (mq->use_cqe && !host->hsq_enabled) + if (host->cqe_enabled && !host->hsq_enabled) return mmc_cqe_issue_type(host, req); if (req_op(req) == REQ_OP_READ || req_op(req) == REQ_OP_WRITE) @@ -127,7 +127,7 @@ static enum blk_eh_timer_return mmc_mq_timed_out(struct request *req, bool ignore_tout; spin_lock_irqsave(&mq->lock, flags); - ignore_tout = mq->recovery_needed || !mq->use_cqe || host->hsq_enabled; + ignore_tout = mq->recovery_needed || !host->cqe_enabled || host->hsq_enabled; spin_unlock_irqrestore(&mq->lock, flags); return ignore_tout ? BLK_EH_RESET_TIMER : mmc_cqe_timed_out(req); @@ -144,7 +144,7 @@ static void mmc_mq_recovery_handler(struct work_struct *work) mq->in_recovery = true; - if (mq->use_cqe && !host->hsq_enabled) + if (host->cqe_enabled && !host->hsq_enabled) mmc_blk_cqe_recovery(mq); else mmc_blk_mq_recovery(mq); @@ -315,7 +315,7 @@ static blk_status_t mmc_mq_queue_rq(struct blk_mq_hw_ctx *hctx, if (get_card) mmc_get_card(card, &mq->ctx); - if (mq->use_cqe) { + if (host->cqe_enabled) { host->retune_now = host->need_retune && cqe_retune_ok && !host->hold_retune; } @@ -430,7 +430,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card) int ret; mq->card = card; - mq->use_cqe = host->cqe_enabled; spin_lock_init(&mq->lock); @@ -440,7 +439,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card) * The queue depth for CQE must match the hardware because the request * tag is used to index the hardware queue. */ - if (mq->use_cqe && !host->hsq_enabled) + if (host->cqe_enabled && !host->hsq_enabled) mq->tag_set.queue_depth = min_t(int, card->ext_csd.cmdq_depth, host->cqe_qdepth); else diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h index 57c59b6cb1b9..3319d8ab57d0 100644 --- a/drivers/mmc/core/queue.h +++ b/drivers/mmc/core/queue.h @@ -82,7 +82,6 @@ struct mmc_queue { unsigned int cqe_busy; #define MMC_CQE_DCMD_BUSY BIT(0) bool busy; - bool use_cqe; bool recovery_needed; bool in_recovery; bool rw_wait; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 6fa51a6ed058..2c48d6504101 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -135,6 +135,9 @@ static int mmc_decode_csd(struct mmc_card *card) csd->erase_size = UNSTUFF_BITS(resp, 39, 7) + 1; csd->erase_size <<= csd->write_blkbits - 9; } + + if (UNSTUFF_BITS(resp, 13, 1)) + mmc_card_set_readonly(card); break; case 1: /* @@ -169,6 +172,9 @@ static int mmc_decode_csd(struct mmc_card *card) csd->write_blkbits = 9; csd->write_partial = 0; csd->erase_size = 1; + + if (UNSTUFF_BITS(resp, 13, 1)) + mmc_card_set_readonly(card); break; default: pr_err("%s: unrecognised CSD structure version %d\n", diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 0fda7784cab2..3eb94ac2712e 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -985,21 +985,37 @@ out: */ static int mmc_sdio_pre_suspend(struct mmc_host *host) { - int i, err = 0; + int i; for (i = 0; i < host->card->sdio_funcs; i++) { struct sdio_func *func = host->card->sdio_func[i]; if (func && sdio_func_present(func) && func->dev.driver) { const struct dev_pm_ops *pmops = func->dev.driver->pm; - if (!pmops || !pmops->suspend || !pmops->resume) { + if (!pmops || !pmops->suspend || !pmops->resume) /* force removal of entire card in that case */ - err = -ENOSYS; - break; - } + goto remove; } } - return err; + return 0; + +remove: + if (!mmc_card_is_removable(host)) { + dev_warn(mmc_dev(host), + "missing suspend/resume ops for non-removable SDIO card\n"); + /* Don't remove a non-removable card - we can't re-detect it. */ + return 0; + } + + /* Remove the SDIO card and let it be re-detected later on. */ + mmc_sdio_remove(host); + mmc_claim_host(host); + mmc_detach_bus(host); + mmc_power_off(host); + mmc_release_host(host); + host->pm_flags = 0; + + return 0; } /* diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index b236dfe2e879..a4d4c757eea0 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -278,6 +278,7 @@ config MMC_SDHCI_ESDHC_IMX tristate "SDHCI support for the Freescale eSDHC/uSDHC i.MX controller" depends on ARCH_MXC || COMPILE_TEST depends on MMC_SDHCI_PLTFM + depends on OF select MMC_SDHCI_IO_ACCESSORS select MMC_CQHCI help @@ -707,6 +708,7 @@ config MMC_SDHI tristate "Renesas SDHI SD/SDIO controller support" depends on SUPERH || ARCH_RENESAS || COMPILE_TEST select MMC_TMIO_CORE + select RESET_CONTROLLER if ARCH_RENESAS help This provides support for the SDHI SD/SDIO controller found in Renesas SuperH, ARM and ARM64 based SoCs diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 6df5c4774260..14004cc09aaa 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile @@ -34,9 +34,7 @@ obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o obj-$(CONFIG_MMC_MVSDIO) += mvsdio.o obj-$(CONFIG_MMC_DAVINCI) += davinci_mmc.o obj-$(CONFIG_MMC_SPI) += mmc_spi.o -ifeq ($(CONFIG_OF),y) obj-$(CONFIG_MMC_SPI) += of_mmc_spi.o -endif obj-$(CONFIG_MMC_S3C) += s3cmci.o obj-$(CONFIG_MMC_SDRICOH_CS) += sdricoh_cs.o obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c index 4bb8f2800a2b..95a41983c6c0 100644 --- a/drivers/mmc/host/cavium.c +++ b/drivers/mmc/host/cavium.c @@ -656,8 +656,7 @@ static void cvm_mmc_dma_request(struct mmc_host *mmc, if (!mrq->data || !mrq->data->sg || !mrq->data->sg_len || !mrq->stop || mrq->stop->opcode != MMC_STOP_TRANSMISSION) { - dev_err(&mmc->card->dev, - "Error: cmv_mmc_dma_request no data\n"); + dev_err(&mmc->card->dev, "Error: %s no data\n", __func__); goto error; } diff --git a/drivers/mmc/host/dw_mmc-k3.c b/drivers/mmc/host/dw_mmc-k3.c index 29d2494eb27a..0311a37dd4ab 100644 --- a/drivers/mmc/host/dw_mmc-k3.c +++ b/drivers/mmc/host/dw_mmc-k3.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2013 Linaro Ltd. - * Copyright (c) 2013 Hisilicon Limited. + * Copyright (c) 2013 HiSilicon Limited. */ #include <linux/bitops.h> diff --git a/drivers/mmc/host/dw_mmc-rockchip.c b/drivers/mmc/host/dw_mmc-rockchip.c index 753502ce3c85..d36991acd6df 100644 --- a/drivers/mmc/host/dw_mmc-rockchip.c +++ b/drivers/mmc/host/dw_mmc-rockchip.c @@ -61,7 +61,7 @@ static void dw_mci_rk3288_set_ios(struct dw_mci *host, struct mmc_ios *ios) } /* Make sure we use phases which we can enumerate with */ - if (!IS_ERR(priv->sample_clk)) + if (!IS_ERR(priv->sample_clk) && ios->timing <= MMC_TIMING_SD_HS) clk_set_phase(priv->sample_clk, priv->default_sample_phase); /* diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 2f4de30f650b..d333130d1531 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2606,8 +2606,6 @@ static void dw_mci_handle_cd(struct dw_mci *host) { struct dw_mci_slot *slot = host->slot; - if (slot->mmc->ops->card_event) - slot->mmc->ops->card_event(slot->mmc); mmc_detect_change(slot->mmc, msecs_to_jiffies(host->pdata->detect_delay_ms)); } @@ -3095,10 +3093,8 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host) /* find reset controller when exist */ pdata->rstc = devm_reset_control_get_optional_exclusive(dev, "reset"); - if (IS_ERR(pdata->rstc)) { - if (PTR_ERR(pdata->rstc) == -EPROBE_DEFER) - return ERR_PTR(-EPROBE_DEFER); - } + if (IS_ERR(pdata->rstc)) + return ERR_CAST(pdata->rstc); if (device_property_read_u32(dev, "fifo-depth", &pdata->fifo_depth)) dev_info(dev, @@ -3204,7 +3200,7 @@ int dw_mci_probe(struct dw_mci *host) goto err_clk_ciu; } - if (!IS_ERR(host->pdata->rstc)) { + if (host->pdata->rstc) { reset_control_assert(host->pdata->rstc); usleep_range(10, 50); reset_control_deassert(host->pdata->rstc); @@ -3344,8 +3340,7 @@ err_dmaunmap: if (host->use_dma && host->dma_ops->exit) host->dma_ops->exit(host); - if (!IS_ERR(host->pdata->rstc)) - reset_control_assert(host->pdata->rstc); + reset_control_assert(host->pdata->rstc); err_clk_ciu: clk_disable_unprepare(host->ciu_clk); @@ -3373,8 +3368,7 @@ void dw_mci_remove(struct dw_mci *host) if (host->use_dma && host->dma_ops->exit) host->dma_ops->exit(host); - if (!IS_ERR(host->pdata->rstc)) - reset_control_assert(host->pdata->rstc); + reset_control_assert(host->pdata->rstc); clk_disable_unprepare(host->ciu_clk); clk_disable_unprepare(host->biu_clk); diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 02f4fd26e76a..9776a03a10f5 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -1397,6 +1397,8 @@ static int mmc_spi_probe(struct spi_device *spi) host->ones = ones; + dev_set_drvdata(&spi->dev, mmc); + /* Platform data is used to hook up things like card sensing * and power switching gpios. */ @@ -1413,8 +1415,6 @@ static int mmc_spi_probe(struct spi_device *spi) host->powerup_msecs = 250; } - dev_set_drvdata(&spi->dev, mmc); - /* preallocate dma buffers */ host->data = kmalloc(sizeof(*host->data), GFP_KERNEL); if (!host->data) @@ -1494,8 +1494,8 @@ fail_glue_init: fail_dma: kfree(host->data); fail_nobuf1: - mmc_free_host(mmc); mmc_spi_put_pdata(spi); + mmc_free_host(mmc); nomem: kfree(ones); return status; @@ -1518,8 +1518,8 @@ static int mmc_spi_remove(struct spi_device *spi) kfree(host->ones); spi->max_speed_hz = mmc->f_max; - mmc_free_host(mmc); mmc_spi_put_pdata(spi); + mmc_free_host(mmc); return 0; } diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index 89bff4e8ec10..bde298887579 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c @@ -257,7 +257,6 @@ static void moxart_dma_complete(void *param) static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host) { u32 len, dir_slave; - long dma_time; struct dma_async_tx_descriptor *desc = NULL; struct dma_chan *dma_chan; @@ -294,8 +293,8 @@ static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host) data->bytes_xfered += host->data_remain; - dma_time = wait_for_completion_interruptible_timeout( - &host->dma_complete, host->timeout); + wait_for_completion_interruptible_timeout(&host->dma_complete, + host->timeout); dma_unmap_sg(dma_chan->device->dev, data->sg, data->sg_len, @@ -395,7 +394,6 @@ static void moxart_prepare_data(struct moxart_host *host) static void moxart_request(struct mmc_host *mmc, struct mmc_request *mrq) { struct moxart_host *host = mmc_priv(mmc); - long pio_time; unsigned long flags; u32 status; @@ -431,8 +429,8 @@ static void moxart_request(struct mmc_host *mmc, struct mmc_request *mrq) spin_unlock_irqrestore(&host->lock, flags); /* PIO transfers start from interrupt. */ - pio_time = wait_for_completion_interruptible_timeout( - &host->pio_complete, host->timeout); + wait_for_completion_interruptible_timeout(&host->pio_complete, + host->timeout); spin_lock_irqsave(&host->lock, flags); } diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index 3c4d950a4755..9d480a05f655 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c @@ -19,11 +19,6 @@ #include <linux/mmc/core.h> #include <linux/mmc/host.h> -/* For archs that don't support NO_IRQ (such as mips), provide a dummy value */ -#ifndef NO_IRQ -#define NO_IRQ 0 -#endif - MODULE_LICENSE("GPL"); struct of_mmc_spi { @@ -54,22 +49,22 @@ static void of_mmc_spi_exit(struct device *dev, void *mmc) struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) { + struct mmc_host *mmc = dev_get_drvdata(&spi->dev); struct device *dev = &spi->dev; - struct device_node *np = dev->of_node; struct of_mmc_spi *oms; - if (dev->platform_data || !np) + if (dev->platform_data || !dev_fwnode(dev)) return dev->platform_data; oms = kzalloc(sizeof(*oms), GFP_KERNEL); if (!oms) return NULL; - if (mmc_of_parse_voltage(np, &oms->pdata.ocr_mask) <= 0) + if (mmc_of_parse_voltage(mmc, &oms->pdata.ocr_mask) < 0) goto err_ocr; - oms->detect_irq = irq_of_parse_and_map(np, 0); - if (oms->detect_irq != 0) { + oms->detect_irq = spi->irq; + if (oms->detect_irq > 0) { oms->pdata.init = of_mmc_spi_init; oms->pdata.exit = of_mmc_spi_exit; } else { @@ -87,10 +82,9 @@ EXPORT_SYMBOL(mmc_spi_get_pdata); void mmc_spi_put_pdata(struct spi_device *spi) { struct device *dev = &spi->dev; - struct device_node *np = dev->of_node; struct of_mmc_spi *oms = to_of_mmc_spi(dev); - if (!dev->platform_data || !np) + if (!dev->platform_data || !dev_fwnode(dev)) return; kfree(oms); diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index 5490962dc8e5..3dc143b03939 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -581,7 +581,6 @@ static int owl_mmc_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); owl_host->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(owl_host->base)) { - dev_err(&pdev->dev, "Failed to remap registers\n"); ret = PTR_ERR(owl_host->base); goto err_free_host; } diff --git a/drivers/mmc/host/renesas_sdhi.h b/drivers/mmc/host/renesas_sdhi.h index cb962c7883dc..53eded81a53e 100644 --- a/drivers/mmc/host/renesas_sdhi.h +++ b/drivers/mmc/host/renesas_sdhi.h @@ -70,6 +70,8 @@ struct renesas_sdhi { DECLARE_BITMAP(smpcmp, BITS_PER_LONG); unsigned int tap_num; unsigned int tap_set; + + struct reset_control *rstc; }; #define host_to_priv(host) \ diff --git a/drivers/mmc/host/renesas_sdhi_core.c b/drivers/mmc/host/renesas_sdhi_core.c index 158c21e5a942..635bf31a6735 100644 --- a/drivers/mmc/host/renesas_sdhi_core.c +++ b/drivers/mmc/host/renesas_sdhi_core.c @@ -20,6 +20,7 @@ #include <linux/clk.h> #include <linux/delay.h> +#include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/mfd/tmio.h> #include <linux/mmc/host.h> @@ -32,6 +33,7 @@ #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/regulator/consumer.h> +#include <linux/reset.h> #include <linux/sh_dma.h> #include <linux/slab.h> #include <linux/sys_soc.h> @@ -557,24 +559,35 @@ static int renesas_sdhi_prepare_hs400_tuning(struct mmc_host *mmc, struct mmc_io return 0; } +static void renesas_sdhi_scc_reset(struct tmio_mmc_host *host, struct renesas_sdhi *priv) +{ + renesas_sdhi_disable_scc(host->mmc); + renesas_sdhi_reset_hs400_mode(host, priv); + priv->needs_adjust_hs400 = false; + + sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, + ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & + sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); +} + /* only populated for TMIO_MMC_MIN_RCAR2 */ static void renesas_sdhi_reset(struct tmio_mmc_host *host) { struct renesas_sdhi *priv = host_to_priv(host); + int ret; u16 val; - if (priv->scc_ctl) { - renesas_sdhi_disable_scc(host->mmc); - renesas_sdhi_reset_hs400_mode(host, priv); + if (priv->rstc) { + reset_control_reset(priv->rstc); + /* Unknown why but without polling reset status, it will hang */ + read_poll_timeout(reset_control_status, ret, ret == 0, 1, 100, + false, priv->rstc); priv->needs_adjust_hs400 = false; - - sd_scc_write32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL, - ~SH_MOBILE_SDHI_SCC_RVSCNTL_RVSEN & - sd_scc_read32(host, priv, SH_MOBILE_SDHI_SCC_RVSCNTL)); + renesas_sdhi_set_clock(host, host->clk_cache); + } else if (priv->scc_ctl) { + renesas_sdhi_scc_reset(host, priv); } - sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, TMIO_MASK_INIT_RCAR2); - if (sd_ctrl_read16(host, CTL_VERSION) >= SDHI_VER_GEN3_SD) { val = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT); val |= CARD_OPT_EXTOP; @@ -691,7 +704,7 @@ static int renesas_sdhi_execute_tuning(struct mmc_host *mmc, u32 opcode) ret = renesas_sdhi_select_tuning(host); if (ret < 0) - renesas_sdhi_reset(host); + renesas_sdhi_scc_reset(host, priv); return ret; } @@ -1034,6 +1047,7 @@ int renesas_sdhi_probe(struct platform_device *pdev, host->ops.start_signal_voltage_switch = renesas_sdhi_start_signal_voltage_switch; host->sdcard_irq_setbit_mask = TMIO_STAT_ALWAYS_SET_27; + host->sdcard_irq_mask_all = TMIO_MASK_ALL_RCAR2; host->reset = renesas_sdhi_reset; } @@ -1076,6 +1090,10 @@ int renesas_sdhi_probe(struct platform_device *pdev, if (ret) goto efree; + priv->rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); + if (IS_ERR(priv->rstc)) + return PTR_ERR(priv->rstc); + ver = sd_ctrl_read16(host, CTL_VERSION); /* GEN2_SDR104 is first known SDHI to use 32bit block count */ if (ver < SDHI_VER_GEN2_SDR104 && mmc_data->max_blk_count > U16_MAX) diff --git a/drivers/mmc/host/renesas_sdhi_internal_dmac.c b/drivers/mmc/host/renesas_sdhi_internal_dmac.c index ff97f15e317c..e8f4863d8f1a 100644 --- a/drivers/mmc/host/renesas_sdhi_internal_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_internal_dmac.c @@ -97,7 +97,7 @@ static const struct renesas_sdhi_of_data of_rza2_compatible = { TMIO_MMC_HAVE_CBSY, .tmio_ocr_mask = MMC_VDD_32_33, .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | - MMC_CAP_CMD23, + MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY, .bus_shift = 2, .scc_offset = 0 - 0x1000, .taps = rcar_gen3_scc_taps, @@ -111,7 +111,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen3_compatible = { .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL | TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2, .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | - MMC_CAP_CMD23, + MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY, .capabilities2 = MMC_CAP2_NO_WRITE_PROTECT | MMC_CAP2_MERGE_CAPABLE, .bus_shift = 2, .scc_offset = 0x1000, diff --git a/drivers/mmc/host/renesas_sdhi_sys_dmac.c b/drivers/mmc/host/renesas_sdhi_sys_dmac.c index c5f789675302..ffa64211f4de 100644 --- a/drivers/mmc/host/renesas_sdhi_sys_dmac.c +++ b/drivers/mmc/host/renesas_sdhi_sys_dmac.c @@ -33,12 +33,14 @@ static const struct renesas_sdhi_of_data of_rz_compatible = { .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_32BIT_DATA_PORT | TMIO_MMC_HAVE_CBSY, .tmio_ocr_mask = MMC_VDD_32_33, - .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, + .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | + MMC_CAP_WAIT_WHILE_BUSY, }; static const struct renesas_sdhi_of_data of_rcar_gen1_compatible = { .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL, - .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ, + .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | + MMC_CAP_WAIT_WHILE_BUSY, .capabilities2 = MMC_CAP2_NO_WRITE_PROTECT, }; @@ -58,7 +60,7 @@ static const struct renesas_sdhi_of_data of_rcar_gen2_compatible = { .tmio_flags = TMIO_MMC_HAS_IDLE_WAIT | TMIO_MMC_CLK_ACTUAL | TMIO_MMC_HAVE_CBSY | TMIO_MMC_MIN_RCAR2, .capabilities = MMC_CAP_SD_HIGHSPEED | MMC_CAP_SDIO_IRQ | - MMC_CAP_CMD23, + MMC_CAP_CMD23 | MMC_CAP_WAIT_WHILE_BUSY, .capabilities2 = MMC_CAP2_NO_WRITE_PROTECT, .dma_buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES, .dma_rx_offset = 0x2000, diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index b6574e7fd26b..c3fbf8c825c4 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -772,6 +772,7 @@ static const struct sdhci_acpi_uid_slot sdhci_acpi_uids[] = { { "QCOM8051", NULL, &sdhci_acpi_slot_qcom_sd_3v }, { "QCOM8052", NULL, &sdhci_acpi_slot_qcom_sd }, { "AMDI0040", NULL, &sdhci_acpi_slot_amd_emmc }, + { "AMDI0041", NULL, &sdhci_acpi_slot_amd_emmc }, { }, }; @@ -789,6 +790,7 @@ static const struct acpi_device_id sdhci_acpi_ids[] = { { "QCOM8051" }, { "QCOM8052" }, { "AMDI0040" }, + { "AMDI0041" }, { }, }; MODULE_DEVICE_TABLE(acpi, sdhci_acpi_ids); diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index f9780c65ebe9..f24623aac2db 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -199,7 +199,6 @@ static int sdhci_brcmstb_add_host(struct sdhci_host *host, if (dma64) { dev_dbg(mmc_dev(host->mmc), "Using 64 bit DMA\n"); cq_host->caps |= CQHCI_TASK_DESC_SZ_128; - cq_host->quirks |= CQHCI_QUIRK_SHORT_TXFR_DESC_SZ; } ret = cqhci_init(cq_host, host->mmc, dma64); diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index a20459744d21..b991cf0e60c5 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -434,10 +434,10 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg) * Do not advertise faster UHS modes if there are no * pinctrl states for 100MHz/200MHz. */ - if (IS_ERR_OR_NULL(imx_data->pins_100mhz) || - IS_ERR_OR_NULL(imx_data->pins_200mhz)) - val &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50 - | SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_HS400); + if (IS_ERR_OR_NULL(imx_data->pins_100mhz)) + val &= ~(SDHCI_SUPPORT_SDR50 | SDHCI_SUPPORT_DDR50); + if (IS_ERR_OR_NULL(imx_data->pins_200mhz)) + val &= ~(SDHCI_SUPPORT_SDR104 | SDHCI_SUPPORT_HS400); } } @@ -1453,7 +1453,6 @@ static const struct cqhci_host_ops esdhc_cqhci_ops = { .dumpregs = esdhc_sdhci_dumpregs, }; -#ifdef CONFIG_OF static int sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, struct sdhci_host *host, @@ -1486,9 +1485,9 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, if (of_property_read_u32(np, "fsl,delay-line", &boarddata->delay_line)) boarddata->delay_line = 0; - mmc_of_parse_voltage(np, &host->ocr_mask); + mmc_of_parse_voltage(host->mmc, &host->ocr_mask); - if (esdhc_is_usdhc(imx_data)) { + if (esdhc_is_usdhc(imx_data) && !IS_ERR(imx_data->pinctrl)) { imx_data->pins_100mhz = pinctrl_lookup_state(imx_data->pinctrl, ESDHC_PINCTRL_STATE_100MHZ); imx_data->pins_200mhz = pinctrl_lookup_state(imx_data->pinctrl, @@ -1505,20 +1504,9 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, return 0; } -#else -static inline int -sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, - struct sdhci_host *host, - struct pltfm_imx_data *imx_data) -{ - return -ENODEV; -} -#endif static int sdhci_esdhc_imx_probe(struct platform_device *pdev) { - const struct of_device_id *of_id = - of_match_device(imx_esdhc_dt_ids, &pdev->dev); struct sdhci_pltfm_host *pltfm_host; struct sdhci_host *host; struct cqhci_host *cq_host; @@ -1534,7 +1522,7 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) imx_data = sdhci_pltfm_priv(pltfm_host); - imx_data->socdata = of_id->data; + imx_data->socdata = device_get_match_data(&pdev->dev); if (imx_data->socdata->flags & ESDHC_FLAG_PMQOS) cpu_latency_qos_add_request(&imx_data->pm_qos_req, 0); diff --git a/drivers/mmc/host/sdhci-esdhc-mcf.c b/drivers/mmc/host/sdhci-esdhc-mcf.c index ca7a1690b2a8..05926bf5ecf9 100644 --- a/drivers/mmc/host/sdhci-esdhc-mcf.c +++ b/drivers/mmc/host/sdhci-esdhc-mcf.c @@ -367,14 +367,14 @@ static int esdhc_mcf_plat_init(struct sdhci_host *host, struct pltfm_mcf_data *mcf_data) { struct mcf_esdhc_platform_data *plat_data; + struct device *dev = mmc_dev(host->mmc); - if (!host->mmc->parent->platform_data) { - dev_err(mmc_dev(host->mmc), "no platform data!\n"); + if (!dev->platform_data) { + dev_err(dev, "no platform data!\n"); return -EINVAL; } - plat_data = (struct mcf_esdhc_platform_data *) - host->mmc->parent->platform_data; + plat_data = (struct mcf_esdhc_platform_data *)dev->platform_data; /* Card_detect */ switch (plat_data->cd_type) { diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index d170c919e6e4..e44b7a66b73c 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1863,7 +1863,6 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, struct mmc_host *mmc = msm_host->mmc; struct device *dev = mmc_dev(mmc); struct resource *res; - int err; if (!(cqhci_readl(cq_host, CQHCI_CAP) & CQHCI_CAP_CS)) return 0; @@ -1881,11 +1880,8 @@ static int sdhci_msm_ice_init(struct sdhci_msm_host *msm_host, } msm_host->ice_mem = devm_ioremap_resource(dev, res); - if (IS_ERR(msm_host->ice_mem)) { - err = PTR_ERR(msm_host->ice_mem); - dev_err(dev, "Failed to map ICE registers; err=%d\n", err); - return err; - } + if (IS_ERR(msm_host->ice_mem)) + return PTR_ERR(msm_host->ice_mem); if (!sdhci_msm_ice_supported(msm_host)) goto disable; diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c index 7d8692e90996..d001c51074a0 100644 --- a/drivers/mmc/host/sdhci-of-aspeed.c +++ b/drivers/mmc/host/sdhci-of-aspeed.c @@ -181,7 +181,7 @@ aspeed_sdhci_configure_phase(struct sdhci_host *host, unsigned long rate) struct aspeed_sdhci *sdhci; struct device *dev; - dev = host->mmc->parent; + dev = mmc_dev(host->mmc); sdhci = sdhci_pltfm_priv(sdhci_priv(host)); if (!sdhci->phase_desc) diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index 59d8d96ce206..bac874ab0b33 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -7,11 +7,14 @@ * Author: Jisheng Zhang <jszhang@kernel.org> */ +#include <linux/acpi.h> #include <linux/clk.h> #include <linux/dma-mapping.h> +#include <linux/iopoll.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/sizes.h> #include "sdhci-pltfm.h" @@ -21,11 +24,52 @@ /* DWCMSHC specific Mode Select value */ #define DWCMSHC_CTRL_HS400 0x7 +/* DWC IP vendor area 1 pointer */ +#define DWCMSHC_P_VENDOR_AREA1 0xe8 +#define DWCMSHC_AREA1_MASK GENMASK(11, 0) +/* Offset inside the vendor area 1 */ +#define DWCMSHC_HOST_CTRL3 0x8 +#define DWCMSHC_EMMC_CONTROL 0x2c +#define DWCMSHC_ENHANCED_STROBE BIT(8) +#define DWCMSHC_EMMC_ATCTRL 0x40 + +/* Rockchip specific Registers */ +#define DWCMSHC_EMMC_DLL_CTRL 0x800 +#define DWCMSHC_EMMC_DLL_RXCLK 0x804 +#define DWCMSHC_EMMC_DLL_TXCLK 0x808 +#define DWCMSHC_EMMC_DLL_STRBIN 0x80c +#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24) +#define DWCMSHC_EMMC_DLL_STATUS0 0x840 +#define DWCMSHC_EMMC_DLL_START BIT(0) +#define DWCMSHC_EMMC_DLL_LOCKED BIT(8) +#define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9) +#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29 +#define DWCMSHC_EMMC_DLL_START_POINT 16 +#define DWCMSHC_EMMC_DLL_INC 8 +#define DWCMSHC_EMMC_DLL_DLYENA BIT(27) +#define DLL_TXCLK_TAPNUM_DEFAULT 0x8 +#define DLL_STRBIN_TAPNUM_DEFAULT 0x8 +#define DLL_TXCLK_TAPNUM_FROM_SW BIT(24) +#define DLL_RXCLK_NO_INVERTER 1 +#define DLL_RXCLK_INVERTER 0 +#define DLL_LOCK_WO_TMOUT(x) \ + ((((x) & DWCMSHC_EMMC_DLL_LOCKED) == DWCMSHC_EMMC_DLL_LOCKED) && \ + (((x) & DWCMSHC_EMMC_DLL_TIMEOUT) == 0)) +#define RK3568_MAX_CLKS 3 + #define BOUNDARY_OK(addr, len) \ ((addr | (SZ_128M - 1)) == ((addr + len - 1) | (SZ_128M - 1))) +struct rk3568_priv { + /* Rockchip specified optional clocks */ + struct clk_bulk_data rockchip_clks[RK3568_MAX_CLKS]; + u8 txclk_tapnum; +}; + struct dwcmshc_priv { struct clk *bus_clk; + int vendor_specific_area1; /* P_VENDOR_SPECIFIC_AREA reg */ + void *priv; /* pointer to SoC private stuff */ }; /* @@ -51,6 +95,16 @@ static void dwcmshc_adma_write_desc(struct sdhci_host *host, void **desc, sdhci_adma_write_desc(host, desc, addr, len, cmd); } +static unsigned int dwcmshc_get_max_clock(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + if (pltfm_host->clk) + return sdhci_pltfm_clk_get_max_clock(host); + else + return pltfm_host->clock; +} + static void dwcmshc_check_auto_cmd23(struct mmc_host *mmc, struct mmc_request *mrq) { @@ -100,10 +154,120 @@ static void dwcmshc_set_uhs_signaling(struct sdhci_host *host, sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); } +static void dwcmshc_hs400_enhanced_strobe(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + u32 vendor; + struct sdhci_host *host = mmc_priv(mmc); + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); + int reg = priv->vendor_specific_area1 + DWCMSHC_EMMC_CONTROL; + + vendor = sdhci_readl(host, reg); + if (ios->enhanced_strobe) + vendor |= DWCMSHC_ENHANCED_STROBE; + else + vendor &= ~DWCMSHC_ENHANCED_STROBE; + + sdhci_writel(host, vendor, reg); +} + +static void dwcmshc_rk3568_set_clock(struct sdhci_host *host, unsigned int clock) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct dwcmshc_priv *dwc_priv = sdhci_pltfm_priv(pltfm_host); + struct rk3568_priv *priv = dwc_priv->priv; + u8 txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT; + u32 extra, reg; + int err; + + host->mmc->actual_clock = 0; + + /* + * DO NOT TOUCH THIS SETTING. RX clk inverter unit is enabled + * by default, but it shouldn't be enabled. We should anyway + * disable it before issuing any cmds. + */ + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK); + + if (clock == 0) + return; + + /* Rockchip platform only support 375KHz for identify mode */ + if (clock <= 400000) + clock = 375000; + + err = clk_set_rate(pltfm_host->clk, clock); + if (err) + dev_err(mmc_dev(host->mmc), "fail to set clock %d", clock); + + sdhci_set_clock(host, clock); + + /* Disable cmd conflict check */ + reg = dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3; + extra = sdhci_readl(host, reg); + extra &= ~BIT(0); + sdhci_writel(host, extra, reg); + + if (clock <= 400000) { + /* Disable DLL to reset sample clock */ + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL); + return; + } + + /* Reset DLL */ + sdhci_writel(host, BIT(1), DWCMSHC_EMMC_DLL_CTRL); + udelay(1); + sdhci_writel(host, 0x0, DWCMSHC_EMMC_DLL_CTRL); + + /* Init DLL settings */ + extra = 0x5 << DWCMSHC_EMMC_DLL_START_POINT | + 0x2 << DWCMSHC_EMMC_DLL_INC | + DWCMSHC_EMMC_DLL_START; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL); + err = readl_poll_timeout(host->ioaddr + DWCMSHC_EMMC_DLL_STATUS0, + extra, DLL_LOCK_WO_TMOUT(extra), 1, + 500 * USEC_PER_MSEC); + if (err) { + dev_err(mmc_dev(host->mmc), "DLL lock timeout!\n"); + return; + } + + extra = 0x1 << 16 | /* tune clock stop en */ + 0x2 << 17 | /* pre-change delay */ + 0x3 << 19; /* post-change delay */ + sdhci_writel(host, extra, dwc_priv->vendor_specific_area1 + DWCMSHC_EMMC_ATCTRL); + + if (host->mmc->ios.timing == MMC_TIMING_MMC_HS200 || + host->mmc->ios.timing == MMC_TIMING_MMC_HS400) + txclk_tapnum = priv->txclk_tapnum; + + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_TXCLK_TAPNUM_FROM_SW | + txclk_tapnum; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK); + + extra = DWCMSHC_EMMC_DLL_DLYENA | + DLL_STRBIN_TAPNUM_DEFAULT | + DLL_STRBIN_TAPNUM_FROM_SW; + sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN); +} + static const struct sdhci_ops sdhci_dwcmshc_ops = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, .set_uhs_signaling = dwcmshc_set_uhs_signaling, + .get_max_clock = dwcmshc_get_max_clock, + .reset = sdhci_reset, + .adma_write_desc = dwcmshc_adma_write_desc, +}; + +static const struct sdhci_ops sdhci_dwcmshc_rk3568_ops = { + .set_clock = dwcmshc_rk3568_set_clock, + .set_bus_width = sdhci_set_bus_width, + .set_uhs_signaling = dwcmshc_set_uhs_signaling, .get_max_clock = sdhci_pltfm_clk_get_max_clock, .reset = sdhci_reset, .adma_write_desc = dwcmshc_adma_write_desc, @@ -115,15 +279,86 @@ static const struct sdhci_pltfm_data sdhci_dwcmshc_pdata = { .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, }; +static const struct sdhci_pltfm_data sdhci_dwcmshc_rk3568_pdata = { + .ops = &sdhci_dwcmshc_rk3568_ops, + .quirks = SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN | + SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | + SDHCI_QUIRK2_CLOCK_DIV_ZERO_BROKEN, +}; + +static int dwcmshc_rk3568_init(struct sdhci_host *host, struct dwcmshc_priv *dwc_priv) +{ + int err; + struct rk3568_priv *priv = dwc_priv->priv; + + priv->rockchip_clks[0].id = "axi"; + priv->rockchip_clks[1].id = "block"; + priv->rockchip_clks[2].id = "timer"; + err = devm_clk_bulk_get_optional(mmc_dev(host->mmc), RK3568_MAX_CLKS, + priv->rockchip_clks); + if (err) { + dev_err(mmc_dev(host->mmc), "failed to get clocks %d\n", err); + return err; + } + + err = clk_bulk_prepare_enable(RK3568_MAX_CLKS, priv->rockchip_clks); + if (err) { + dev_err(mmc_dev(host->mmc), "failed to enable clocks %d\n", err); + return err; + } + + if (of_property_read_u8(mmc_dev(host->mmc)->of_node, "rockchip,txclk-tapnum", + &priv->txclk_tapnum)) + priv->txclk_tapnum = DLL_TXCLK_TAPNUM_DEFAULT; + + /* Disable cmd conflict check */ + sdhci_writel(host, 0x0, dwc_priv->vendor_specific_area1 + DWCMSHC_HOST_CTRL3); + /* Reset previous settings */ + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK); + sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN); + + return 0; +} + +static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { + { + .compatible = "rockchip,rk3568-dwcmshc", + .data = &sdhci_dwcmshc_rk3568_pdata, + }, + { + .compatible = "snps,dwcmshc-sdhci", + .data = &sdhci_dwcmshc_pdata, + }, + {}, +}; +MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids); + +#ifdef CONFIG_ACPI +static const struct acpi_device_id sdhci_dwcmshc_acpi_ids[] = { + { .id = "MLNXBF30" }, + {} +}; +#endif + static int dwcmshc_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; struct sdhci_pltfm_host *pltfm_host; struct sdhci_host *host; struct dwcmshc_priv *priv; + struct rk3568_priv *rk_priv = NULL; + const struct sdhci_pltfm_data *pltfm_data; int err; u32 extra; - host = sdhci_pltfm_init(pdev, &sdhci_dwcmshc_pdata, + pltfm_data = of_device_get_match_data(&pdev->dev); + if (!pltfm_data) { + dev_err(&pdev->dev, "Error: No device match data found\n"); + return -ENODEV; + } + + host = sdhci_pltfm_init(pdev, pltfm_data, sizeof(struct dwcmshc_priv)); if (IS_ERR(host)) return PTR_ERR(host); @@ -131,7 +366,7 @@ static int dwcmshc_probe(struct platform_device *pdev) /* * extra adma table cnt for cross 128M boundary handling. */ - extra = DIV_ROUND_UP_ULL(dma_get_required_mask(&pdev->dev), SZ_128M); + extra = DIV_ROUND_UP_ULL(dma_get_required_mask(dev), SZ_128M); if (extra > SDHCI_MAX_SEGS) extra = SDHCI_MAX_SEGS; host->adma_table_cnt += extra; @@ -139,19 +374,21 @@ static int dwcmshc_probe(struct platform_device *pdev) pltfm_host = sdhci_priv(host); priv = sdhci_pltfm_priv(pltfm_host); - pltfm_host->clk = devm_clk_get(&pdev->dev, "core"); - if (IS_ERR(pltfm_host->clk)) { - err = PTR_ERR(pltfm_host->clk); - dev_err(&pdev->dev, "failed to get core clk: %d\n", err); - goto free_pltfm; + if (dev->of_node) { + pltfm_host->clk = devm_clk_get(dev, "core"); + if (IS_ERR(pltfm_host->clk)) { + err = PTR_ERR(pltfm_host->clk); + dev_err(dev, "failed to get core clk: %d\n", err); + goto free_pltfm; + } + err = clk_prepare_enable(pltfm_host->clk); + if (err) + goto free_pltfm; + + priv->bus_clk = devm_clk_get(dev, "bus"); + if (!IS_ERR(priv->bus_clk)) + clk_prepare_enable(priv->bus_clk); } - err = clk_prepare_enable(pltfm_host->clk); - if (err) - goto free_pltfm; - - priv->bus_clk = devm_clk_get(&pdev->dev, "bus"); - if (!IS_ERR(priv->bus_clk)) - clk_prepare_enable(priv->bus_clk); err = mmc_of_parse(host->mmc); if (err) @@ -159,7 +396,27 @@ static int dwcmshc_probe(struct platform_device *pdev) sdhci_get_of_property(pdev); + priv->vendor_specific_area1 = + sdhci_readl(host, DWCMSHC_P_VENDOR_AREA1) & DWCMSHC_AREA1_MASK; + host->mmc_host_ops.request = dwcmshc_request; + host->mmc_host_ops.hs400_enhanced_strobe = dwcmshc_hs400_enhanced_strobe; + + if (pltfm_data == &sdhci_dwcmshc_rk3568_pdata) { + rk_priv = devm_kzalloc(&pdev->dev, sizeof(struct rk3568_priv), GFP_KERNEL); + if (!rk_priv) { + err = -ENOMEM; + goto err_clk; + } + + priv->priv = rk_priv; + + err = dwcmshc_rk3568_init(host, priv); + if (err) + goto err_clk; + } + + host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY; err = sdhci_add_host(host); if (err) @@ -170,6 +427,9 @@ static int dwcmshc_probe(struct platform_device *pdev) err_clk: clk_disable_unprepare(pltfm_host->clk); clk_disable_unprepare(priv->bus_clk); + if (rk_priv) + clk_bulk_disable_unprepare(RK3568_MAX_CLKS, + rk_priv->rockchip_clks); free_pltfm: sdhci_pltfm_free(pdev); return err; @@ -180,12 +440,15 @@ static int dwcmshc_remove(struct platform_device *pdev) struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); + struct rk3568_priv *rk_priv = priv->priv; sdhci_remove_host(host, 0); clk_disable_unprepare(pltfm_host->clk); clk_disable_unprepare(priv->bus_clk); - + if (rk_priv) + clk_bulk_disable_unprepare(RK3568_MAX_CLKS, + rk_priv->rockchip_clks); sdhci_pltfm_free(pdev); return 0; @@ -197,6 +460,7 @@ static int dwcmshc_suspend(struct device *dev) struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); + struct rk3568_priv *rk_priv = priv->priv; int ret; ret = sdhci_suspend_host(host); @@ -207,6 +471,10 @@ static int dwcmshc_suspend(struct device *dev) if (!IS_ERR(priv->bus_clk)) clk_disable_unprepare(priv->bus_clk); + if (rk_priv) + clk_bulk_disable_unprepare(RK3568_MAX_CLKS, + rk_priv->rockchip_clks); + return ret; } @@ -215,6 +483,7 @@ static int dwcmshc_resume(struct device *dev) struct sdhci_host *host = dev_get_drvdata(dev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct dwcmshc_priv *priv = sdhci_pltfm_priv(pltfm_host); + struct rk3568_priv *rk_priv = priv->priv; int ret; ret = clk_prepare_enable(pltfm_host->clk); @@ -227,23 +496,25 @@ static int dwcmshc_resume(struct device *dev) return ret; } + if (rk_priv) { + ret = clk_bulk_prepare_enable(RK3568_MAX_CLKS, + rk_priv->rockchip_clks); + if (ret) + return ret; + } + return sdhci_resume_host(host); } #endif static SIMPLE_DEV_PM_OPS(dwcmshc_pmops, dwcmshc_suspend, dwcmshc_resume); -static const struct of_device_id sdhci_dwcmshc_dt_ids[] = { - { .compatible = "snps,dwcmshc-sdhci" }, - {} -}; -MODULE_DEVICE_TABLE(of, sdhci_dwcmshc_dt_ids); - static struct platform_driver sdhci_dwcmshc_driver = { .driver = { .name = "sdhci-dwcmshc", .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_dwcmshc_dt_ids, + .acpi_match_table = ACPI_PTR(sdhci_dwcmshc_acpi_ids), .pm = &dwcmshc_pmops, }, .probe = dwcmshc_probe, diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index ab5ab969f711..a593b1fbd69e 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -1489,7 +1489,7 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) if (ret) goto err; - mmc_of_parse_voltage(np, &host->ocr_mask); + mmc_of_parse_voltage(host->mmc, &host->ocr_mask); ret = sdhci_add_host(host); if (ret) diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 9552708846ca..be19785227fe 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -516,6 +516,7 @@ struct intel_host { int drv_strength; bool d3_retune; bool rpm_retune_ok; + bool needs_pwr_off; u32 glk_rx_ctrl1; u32 glk_tun_val; u32 active_ltr; @@ -643,9 +644,25 @@ out: static void sdhci_intel_set_power(struct sdhci_host *host, unsigned char mode, unsigned short vdd) { + struct sdhci_pci_slot *slot = sdhci_priv(host); + struct intel_host *intel_host = sdhci_pci_priv(slot); int cntr; u8 reg; + /* + * Bus power may control card power, but a full reset still may not + * reset the power, whereas a direct write to SDHCI_POWER_CONTROL can. + * That might be needed to initialize correctly, if the card was left + * powered on previously. + */ + if (intel_host->needs_pwr_off) { + intel_host->needs_pwr_off = false; + if (mode != MMC_POWER_OFF) { + sdhci_writeb(host, 0, SDHCI_POWER_CONTROL); + usleep_range(10000, 12500); + } + } + sdhci_set_power(host, mode, vdd); if (mode == MMC_POWER_OFF) @@ -958,7 +975,7 @@ static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot) slot->host->mmc->caps2 |= MMC_CAP2_CQE; if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) { - slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES, + slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES; slot->host->mmc_host_ops.hs400_enhanced_strobe = intel_hs400_enhanced_strobe; slot->host->mmc->caps2 |= MMC_CAP2_CQE_DCMD; @@ -1135,6 +1152,14 @@ static int byt_sdio_probe_slot(struct sdhci_pci_slot *slot) return 0; } +static void byt_needs_pwr_off(struct sdhci_pci_slot *slot) +{ + struct intel_host *intel_host = sdhci_pci_priv(slot); + u8 reg = sdhci_readb(slot->host, SDHCI_POWER_CONTROL); + + intel_host->needs_pwr_off = reg & SDHCI_POWER_ON; +} + static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) { byt_probe_slot(slot); @@ -1152,6 +1177,8 @@ static int byt_sd_probe_slot(struct sdhci_pci_slot *slot) slot->chip->pdev->subsystem_device == PCI_SUBDEVICE_ID_NI_78E3) slot->host->mmc->caps2 |= MMC_CAP2_AVOID_3_3V; + byt_needs_pwr_off(slot); + return 0; } @@ -1903,6 +1930,8 @@ static const struct pci_device_id pci_ids[] = { SDHCI_PCI_DEVICE(INTEL, CMLH_SD, intel_byt_sd), SDHCI_PCI_DEVICE(INTEL, JSL_EMMC, intel_glk_emmc), SDHCI_PCI_DEVICE(INTEL, JSL_SD, intel_byt_sd), + SDHCI_PCI_DEVICE(INTEL, LKF_EMMC, intel_glk_emmc), + SDHCI_PCI_DEVICE(INTEL, LKF_SD, intel_byt_sd), SDHCI_PCI_DEVICE(O2, 8120, o2), SDHCI_PCI_DEVICE(O2, 8220, o2), SDHCI_PCI_DEVICE(O2, 8221, o2), diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index 4a0f69b97a78..592d79082f58 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -22,6 +22,10 @@ #define GLI_9750_WT_EN_ON 0x1 #define GLI_9750_WT_EN_OFF 0x0 +#define SDHCI_GLI_9750_CFG2 0x848 +#define SDHCI_GLI_9750_CFG2_L1DLY GENMASK(28, 24) +#define GLI_9750_CFG2_L1DLY_VALUE 0x1F + #define SDHCI_GLI_9750_DRIVING 0x860 #define SDHCI_GLI_9750_DRIVING_1 GENMASK(11, 0) #define SDHCI_GLI_9750_DRIVING_2 GENMASK(27, 26) @@ -90,7 +94,7 @@ #define PCIE_GLI_9763E_CFG2 0x8A4 #define GLI_9763E_CFG2_L1DLY GENMASK(28, 19) -#define GLI_9763E_CFG2_L1DLY_MAX 0x3FF +#define GLI_9763E_CFG2_L1DLY_MID 0x50 #define PCIE_GLI_9763E_MMC_CTRL 0x960 #define GLI_9763E_HS400_SLOW BIT(3) @@ -113,6 +117,10 @@ #define PCI_GLI_9755_LFCLK GENMASK(14, 12) #define PCI_GLI_9755_DMACLK BIT(29) +#define PCI_GLI_9755_CFG2 0x48 +#define PCI_GLI_9755_CFG2_L1DLY GENMASK(28, 24) +#define GLI_9755_CFG2_L1DLY_VALUE 0x1F + #define PCI_GLI_9755_PLL 0x64 #define PCI_GLI_9755_PLL_LDIV GENMASK(9, 0) #define PCI_GLI_9755_PLL_PDIV GENMASK(14, 12) @@ -123,6 +131,9 @@ #define PCI_GLI_9755_PLLSSC 0x68 #define PCI_GLI_9755_PLLSSC_PPM GENMASK(15, 0) +#define PCI_GLI_9755_SerDes 0x70 +#define PCI_GLI_9755_SCP_DIS BIT(19) + #define GLI_MAX_TUNING_LOOP 40 /* Genesys Logic chipset */ @@ -405,6 +416,22 @@ static void sdhci_gl9750_set_clock(struct sdhci_host *host, unsigned int clock) sdhci_enable_clk(host, clk); } +static void gl9750_hw_setting(struct sdhci_host *host) +{ + u32 value; + + gl9750_wt_on(host); + + value = sdhci_readl(host, SDHCI_GLI_9750_CFG2); + value &= ~SDHCI_GLI_9750_CFG2_L1DLY; + /* set ASPM L1 entry delay to 7.9us */ + value |= FIELD_PREP(SDHCI_GLI_9750_CFG2_L1DLY, + GLI_9750_CFG2_L1DLY_VALUE); + sdhci_writel(host, value, SDHCI_GLI_9750_CFG2); + + gl9750_wt_off(host); +} + static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot) { int ret; @@ -547,6 +574,18 @@ static void gl9755_hw_setting(struct sdhci_pci_slot *slot) value &= ~PCI_GLI_9755_DMACLK; pci_write_config_dword(pdev, PCI_GLI_9755_PECONF, value); + /* enable short circuit protection */ + pci_read_config_dword(pdev, PCI_GLI_9755_SerDes, &value); + value &= ~PCI_GLI_9755_SCP_DIS; + pci_write_config_dword(pdev, PCI_GLI_9755_SerDes, value); + + pci_read_config_dword(pdev, PCI_GLI_9755_CFG2, &value); + value &= ~PCI_GLI_9755_CFG2_L1DLY; + /* set ASPM L1 entry delay to 7.9us */ + value |= FIELD_PREP(PCI_GLI_9755_CFG2_L1DLY, + GLI_9755_CFG2_L1DLY_VALUE); + pci_write_config_dword(pdev, PCI_GLI_9755_CFG2, value); + gl9755_wt_off(pdev); } @@ -554,6 +593,7 @@ static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot) { struct sdhci_host *host = slot->host; + gl9750_hw_setting(host); gli_pcie_enable_msi(slot); slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; sdhci_enable_v4_mode(host); @@ -802,8 +842,8 @@ 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 260us */ - value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MAX); + /* set ASPM L1 entry delay to 20us */ + value |= FIELD_PREP(GLI_9763E_CFG2_L1DLY, GLI_9763E_CFG2_L1DLY_MID); pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG2, value); pci_read_config_dword(pdev, PCIE_GLI_9763E_CLKRXDLY, &value); diff --git a/drivers/mmc/host/sdhci-pci-o2micro.c b/drivers/mmc/host/sdhci-pci-o2micro.c index 94e3f72f6405..51d55a87aebe 100644 --- a/drivers/mmc/host/sdhci-pci-o2micro.c +++ b/drivers/mmc/host/sdhci-pci-o2micro.c @@ -706,6 +706,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) ret = pci_read_config_dword(chip->pdev, O2_SD_FUNC_REG0, &scratch_32); + if (ret) + return ret; scratch_32 = ((scratch_32 & 0xFF000000) >> 24); /* Check Whether subId is 0x11 or 0x12 */ @@ -716,6 +718,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) ret = pci_read_config_dword(chip->pdev, O2_SD_FUNC_REG4, &scratch_32); + if (ret) + return ret; /* Enable Base Clk setting change */ scratch_32 |= O2_SD_FREG4_ENABLE_CLK_SET; @@ -795,6 +799,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) ret = pci_read_config_dword(chip->pdev, O2_SD_PLL_SETTING, &scratch_32); + if (ret) + return ret; if ((scratch_32 & 0xff000000) == 0x01000000) { scratch_32 &= 0x0000FFFF; @@ -812,6 +818,8 @@ static int sdhci_pci_o2_probe(struct sdhci_pci_chip *chip) ret = pci_read_config_dword(chip->pdev, O2_SD_FUNC_REG4, &scratch_32); + if (ret) + return ret; scratch_32 |= (1 << 22); pci_write_config_dword(chip->pdev, O2_SD_FUNC_REG4, scratch_32); diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index d0ed232af0eb..8f90c4163bb5 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -57,6 +57,8 @@ #define PCI_DEVICE_ID_INTEL_CMLH_SD 0x06f5 #define PCI_DEVICE_ID_INTEL_JSL_EMMC 0x4dc4 #define PCI_DEVICE_ID_INTEL_JSL_SD 0x4df8 +#define PCI_DEVICE_ID_INTEL_LKF_EMMC 0x98c4 +#define PCI_DEVICE_ID_INTEL_LKF_SD 0x98f8 #define PCI_DEVICE_ID_SYSKONNECT_8000 0x8000 #define PCI_DEVICE_ID_VIA_95D0 0x95d0 diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index f48a788a9d3d..862f033d235d 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -20,6 +20,7 @@ #include <linux/gpio.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_device.h> #include <linux/of_gpio.h> #include <linux/pm.h> #include <linux/pm_runtime.h> @@ -129,7 +130,7 @@ struct sdhci_s3c { }; /** - * struct sdhci_s3c_driver_data - S3C SDHCI platform specific driver data + * struct sdhci_s3c_drv_data - S3C SDHCI platform specific driver data * @sdhci_quirks: sdhci host specific quirks. * @no_divider: no or non-standard internal clock divider. * @@ -461,28 +462,21 @@ static int sdhci_s3c_parse_dt(struct device *dev, } #endif -#ifdef CONFIG_OF -static const struct of_device_id sdhci_s3c_dt_match[]; -#endif - -static inline struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( +static inline const struct sdhci_s3c_drv_data *sdhci_s3c_get_driver_data( struct platform_device *pdev) { #ifdef CONFIG_OF - if (pdev->dev.of_node) { - const struct of_device_id *match; - match = of_match_node(sdhci_s3c_dt_match, pdev->dev.of_node); - return (struct sdhci_s3c_drv_data *)match->data; - } + if (pdev->dev.of_node) + return of_device_get_match_data(&pdev->dev); #endif - return (struct sdhci_s3c_drv_data *) + return (const struct sdhci_s3c_drv_data *) platform_get_device_id(pdev)->driver_data; } static int sdhci_s3c_probe(struct platform_device *pdev) { struct s3c_sdhci_platdata *pdata; - struct sdhci_s3c_drv_data *drv_data; + const struct sdhci_s3c_drv_data *drv_data; struct device *dev = &pdev->dev; struct sdhci_host *host; struct sdhci_s3c *sc; @@ -767,7 +761,7 @@ static const struct platform_device_id sdhci_s3c_driver_ids[] = { MODULE_DEVICE_TABLE(platform, sdhci_s3c_driver_ids); #ifdef CONFIG_OF -static struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = { +static const struct sdhci_s3c_drv_data exynos4_sdhci_drv_data = { .no_divider = true, }; diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c index 962872aec164..d41582c21aa3 100644 --- a/drivers/mmc/host/sdhci-st.c +++ b/drivers/mmc/host/sdhci-st.c @@ -362,11 +362,10 @@ static int sdhci_st_probe(struct platform_device *pdev) if (IS_ERR(icnclk)) icnclk = NULL; - rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); + rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); if (IS_ERR(rstc)) - rstc = NULL; - else - reset_control_deassert(rstc); + return PTR_ERR(rstc); + reset_control_deassert(rstc); host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, sizeof(*pdata)); if (IS_ERR(host)) { @@ -401,10 +400,8 @@ static int sdhci_st_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "top-mmc-delay"); pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(pdata->top_ioaddr)) { - dev_warn(&pdev->dev, "FlashSS Top Dly registers not available"); + if (IS_ERR(pdata->top_ioaddr)) pdata->top_ioaddr = NULL; - } pltfm_host->clk = clk; pdata->icnclk = icnclk; @@ -432,8 +429,7 @@ err_icnclk: err_of: sdhci_pltfm_free(pdev); err_pltfm_init: - if (rstc) - reset_control_assert(rstc); + reset_control_assert(rstc); return ret; } @@ -450,8 +446,7 @@ static int sdhci_st_remove(struct platform_device *pdev) clk_disable_unprepare(pdata->icnclk); - if (rstc) - reset_control_assert(rstc); + reset_control_assert(rstc); return ret; } @@ -471,8 +466,7 @@ static int sdhci_st_suspend(struct device *dev) if (ret) goto out; - if (pdata->rstc) - reset_control_assert(pdata->rstc); + reset_control_assert(pdata->rstc); clk_disable_unprepare(pdata->icnclk); clk_disable_unprepare(pltfm_host->clk); @@ -498,8 +492,7 @@ static int sdhci_st_resume(struct device *dev) return ret; } - if (pdata->rstc) - reset_control_deassert(pdata->rstc); + reset_control_deassert(pdata->rstc); st_mmcss_cconfig(np, host); diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 41d193fa77bb..387ce9cdbd7c 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -119,6 +119,10 @@ /* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */ #define SDHCI_TEGRA_CQE_BASE_ADDR 0xF000 +#define SDHCI_TEGRA_CQE_TRNS_MODE (SDHCI_TRNS_MULTI | \ + SDHCI_TRNS_BLK_CNT_EN | \ + SDHCI_TRNS_DMA) + struct sdhci_tegra_soc_data { const struct sdhci_pltfm_data *pdata; u64 dma_mask; @@ -596,49 +600,49 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host) &tegra_host->autocal_offsets; int err; - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-up-offset-3v3", &autocal->pull_up_3v3); if (err) autocal->pull_up_3v3 = 0; - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-down-offset-3v3", &autocal->pull_down_3v3); if (err) autocal->pull_down_3v3 = 0; - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-up-offset-1v8", &autocal->pull_up_1v8); if (err) autocal->pull_up_1v8 = 0; - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-down-offset-1v8", &autocal->pull_down_1v8); if (err) autocal->pull_down_1v8 = 0; - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-up-offset-sdr104", &autocal->pull_up_sdr104); if (err) autocal->pull_up_sdr104 = autocal->pull_up_1v8; - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-down-offset-sdr104", &autocal->pull_down_sdr104); if (err) autocal->pull_down_sdr104 = autocal->pull_down_1v8; - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-up-offset-hs400", &autocal->pull_up_hs400); if (err) autocal->pull_up_hs400 = autocal->pull_up_1v8; - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-down-offset-hs400", &autocal->pull_down_hs400); if (err) @@ -653,7 +657,7 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host) if (!(tegra_host->soc_data->nvquirks & NVQUIRK_NEEDS_PAD_CONTROL)) return; - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-up-offset-3v3-timeout", &autocal->pull_up_3v3_timeout); if (err) { @@ -664,7 +668,7 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host) autocal->pull_up_3v3_timeout = 0; } - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-down-offset-3v3-timeout", &autocal->pull_down_3v3_timeout); if (err) { @@ -675,7 +679,7 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host) autocal->pull_down_3v3_timeout = 0; } - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-up-offset-1v8-timeout", &autocal->pull_up_1v8_timeout); if (err) { @@ -686,7 +690,7 @@ static void tegra_sdhci_parse_pad_autocal_dt(struct sdhci_host *host) autocal->pull_up_1v8_timeout = 0; } - err = device_property_read_u32(host->mmc->parent, + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,pad-autocal-pull-down-offset-1v8-timeout", &autocal->pull_down_1v8_timeout); if (err) { @@ -720,17 +724,17 @@ static void tegra_sdhci_parse_tap_and_trim(struct sdhci_host *host) struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); int err; - err = device_property_read_u32(host->mmc->parent, "nvidia,default-tap", + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,default-tap", &tegra_host->default_tap); if (err) tegra_host->default_tap = 0; - err = device_property_read_u32(host->mmc->parent, "nvidia,default-trim", + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,default-trim", &tegra_host->default_trim); if (err) tegra_host->default_trim = 0; - err = device_property_read_u32(host->mmc->parent, "nvidia,dqs-trim", + err = device_property_read_u32(mmc_dev(host->mmc), "nvidia,dqs-trim", &tegra_host->dqs_trim); if (err) tegra_host->dqs_trim = 0x11; @@ -741,7 +745,7 @@ static void tegra_sdhci_parse_dt(struct sdhci_host *host) struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host); - if (device_property_read_bool(host->mmc->parent, "supports-cqe")) + if (device_property_read_bool(mmc_dev(host->mmc), "supports-cqe")) tegra_host->enable_hwcq = true; else tegra_host->enable_hwcq = false; @@ -1156,6 +1160,7 @@ static void tegra_sdhci_voltage_switch(struct sdhci_host *host) static void tegra_cqhci_writel(struct cqhci_host *cq_host, u32 val, int reg) { struct mmc_host *mmc = cq_host->mmc; + struct sdhci_host *host = mmc_priv(mmc); u8 ctrl; ktime_t timeout; bool timed_out; @@ -1170,6 +1175,7 @@ static void tegra_cqhci_writel(struct cqhci_host *cq_host, u32 val, int reg) */ if (reg == CQHCI_CTL && !(val & CQHCI_HALT) && cqhci_readl(cq_host, CQHCI_CTL) & CQHCI_HALT) { + sdhci_writew(host, SDHCI_TEGRA_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE); sdhci_cqe_enable(mmc); writel(val, cq_host->mmio + reg); timeout = ktime_add_us(ktime_get(), 50); @@ -1205,6 +1211,7 @@ static void sdhci_tegra_update_dcmd_desc(struct mmc_host *mmc, static void sdhci_tegra_cqe_enable(struct mmc_host *mmc) { struct cqhci_host *cq_host = mmc->cqe_private; + struct sdhci_host *host = mmc_priv(mmc); u32 val; /* @@ -1218,6 +1225,7 @@ static void sdhci_tegra_cqe_enable(struct mmc_host *mmc) if (val & CQHCI_ENABLE) cqhci_writel(cq_host, (val & ~CQHCI_ENABLE), CQHCI_CFG); + sdhci_writew(host, SDHCI_TEGRA_CQE_TRNS_MODE, SDHCI_TRANSFER_MODE); sdhci_cqe_enable(mmc); if (val & CQHCI_ENABLE) cqhci_writel(cq_host, val, CQHCI_CFG); @@ -1281,12 +1289,36 @@ static void tegra_sdhci_set_timeout(struct sdhci_host *host, __sdhci_set_timeout(host, cmd); } +static void sdhci_tegra_cqe_pre_enable(struct mmc_host *mmc) +{ + struct cqhci_host *cq_host = mmc->cqe_private; + u32 reg; + + reg = cqhci_readl(cq_host, CQHCI_CFG); + reg |= CQHCI_ENABLE; + cqhci_writel(cq_host, reg, CQHCI_CFG); +} + +static void sdhci_tegra_cqe_post_disable(struct mmc_host *mmc) +{ + struct cqhci_host *cq_host = mmc->cqe_private; + struct sdhci_host *host = mmc_priv(mmc); + u32 reg; + + reg = cqhci_readl(cq_host, CQHCI_CFG); + reg &= ~CQHCI_ENABLE; + cqhci_writel(cq_host, reg, CQHCI_CFG); + sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE); +} + static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = { .write_l = tegra_cqhci_writel, .enable = sdhci_tegra_cqe_enable, .disable = sdhci_cqe_disable, .dumpregs = sdhci_tegra_dumpregs, .update_dcmd_desc = sdhci_tegra_update_dcmd_desc, + .pre_enable = sdhci_tegra_cqe_pre_enable, + .post_disable = sdhci_tegra_cqe_post_disable, }; static int tegra_sdhci_set_dma_mask(struct sdhci_host *host) @@ -1529,7 +1561,7 @@ static int sdhci_tegra_add_host(struct sdhci_host *host) host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD; - cq_host = devm_kzalloc(host->mmc->parent, + cq_host = devm_kzalloc(mmc_dev(host->mmc), sizeof(*cq_host), GFP_KERNEL); if (!cq_host) { ret = -ENOMEM; diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2d73407ee52e..bf238ade1602 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -188,7 +188,7 @@ static void sdhci_runtime_pm_bus_on(struct sdhci_host *host) if (host->bus_on) return; host->bus_on = true; - pm_runtime_get_noresume(host->mmc->parent); + pm_runtime_get_noresume(mmc_dev(host->mmc)); } static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) @@ -196,7 +196,7 @@ static void sdhci_runtime_pm_bus_off(struct sdhci_host *host) if (!host->bus_on) return; host->bus_on = false; - pm_runtime_put_noidle(host->mmc->parent); + pm_runtime_put_noidle(mmc_dev(host->mmc)); } void sdhci_reset(struct sdhci_host *host, u8 mask) @@ -648,7 +648,7 @@ static int sdhci_pre_dma_transfer(struct sdhci_host *host, } } /* Switch ownership to the DMA */ - dma_sync_single_for_device(host->mmc->parent, + dma_sync_single_for_device(mmc_dev(host->mmc), host->bounce_addr, host->bounce_buffer_size, mmc_get_dma_dir(data)); @@ -907,7 +907,7 @@ static void sdhci_calc_sw_timeout(struct sdhci_host *host, if (data) { blksz = data->blksz; - freq = host->mmc->actual_clock ? : host->clock; + freq = mmc->actual_clock ? : host->clock; transfer_time = (u64)blksz * NSEC_PER_SEC * (8 / bus_width); do_div(transfer_time, freq); /* multiply by '2' to account for any unknowns */ @@ -1176,7 +1176,7 @@ static int sdhci_external_dma_init(struct sdhci_host *host) int ret = 0; struct mmc_host *mmc = host->mmc; - host->tx_chan = dma_request_chan(mmc->parent, "tx"); + host->tx_chan = dma_request_chan(mmc_dev(mmc), "tx"); if (IS_ERR(host->tx_chan)) { ret = PTR_ERR(host->tx_chan); if (ret != -EPROBE_DEFER) @@ -1185,7 +1185,7 @@ static int sdhci_external_dma_init(struct sdhci_host *host) return ret; } - host->rx_chan = dma_request_chan(mmc->parent, "rx"); + host->rx_chan = dma_request_chan(mmc_dev(mmc), "rx"); if (IS_ERR(host->rx_chan)) { if (host->tx_chan) { dma_release_channel(host->tx_chan); @@ -2269,14 +2269,14 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK && host->clock) { - host->timeout_clk = host->mmc->actual_clock ? - host->mmc->actual_clock / 1000 : + host->timeout_clk = mmc->actual_clock ? + mmc->actual_clock / 1000 : host->clock / 1000; - host->mmc->max_busy_timeout = + mmc->max_busy_timeout = host->ops->get_max_timeout_count ? host->ops->get_max_timeout_count(host) : 1 << 27; - host->mmc->max_busy_timeout /= host->timeout_clk; + mmc->max_busy_timeout /= host->timeout_clk; } } @@ -2399,7 +2399,7 @@ static int sdhci_get_cd(struct mmc_host *mmc) return 0; /* If nonremovable, assume that the card is always present. */ - if (!mmc_card_is_removable(host->mmc)) + if (!mmc_card_is_removable(mmc)) return 1; /* @@ -2489,14 +2489,14 @@ void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable) unsigned long flags; if (enable) - pm_runtime_get_noresume(host->mmc->parent); + pm_runtime_get_noresume(mmc_dev(mmc)); spin_lock_irqsave(&host->lock, flags); sdhci_enable_sdio_irq_nolock(host, enable); spin_unlock_irqrestore(&host->lock, flags); if (!enable) - pm_runtime_put_noidle(host->mmc->parent); + pm_runtime_put_noidle(mmc_dev(mmc)); } EXPORT_SYMBOL_GPL(sdhci_enable_sdio_irq); @@ -2837,7 +2837,7 @@ int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) goto out; } - host->mmc->retune_period = tuning_count; + mmc->retune_period = tuning_count; if (host->tuning_delay < 0) host->tuning_delay = opcode == MMC_SEND_TUNING_BLOCK; @@ -2886,11 +2886,10 @@ static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable) static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq, int err) { - struct sdhci_host *host = mmc_priv(mmc); struct mmc_data *data = mrq->data; if (data->host_cookie != COOKIE_UNMAPPED) - dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + dma_unmap_sg(mmc_dev(mmc), data->sg, data->sg_len, mmc_get_dma_dir(data)); data->host_cookie = COOKIE_UNMAPPED; @@ -2941,9 +2940,9 @@ static void sdhci_card_event(struct mmc_host *mmc) /* Check sdhci_has_requests() first in case we are runtime suspended */ if (sdhci_has_requests(host) && !present) { pr_err("%s: Card removed during transfer!\n", - mmc_hostname(host->mmc)); + mmc_hostname(mmc)); pr_err("%s: Resetting controller.\n", - mmc_hostname(host->mmc)); + mmc_hostname(mmc)); sdhci_do_reset(host, SDHCI_RESET_CMD); sdhci_do_reset(host, SDHCI_RESET_DATA); @@ -2997,6 +2996,37 @@ static bool sdhci_request_done(struct sdhci_host *host) } /* + * The controller needs a reset of internal state machines + * upon error conditions. + */ + if (sdhci_needs_reset(host, mrq)) { + /* + * Do not finish until command and data lines are available for + * reset. Note there can only be one other mrq, so it cannot + * also be in mrqs_done, otherwise host->cmd and host->data_cmd + * would both be null. + */ + if (host->cmd || host->data_cmd) { + spin_unlock_irqrestore(&host->lock, flags); + return true; + } + + /* Some controllers need this kick or reset won't work here */ + if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) + /* This is to force an update */ + host->ops->set_clock(host, host->clock); + + /* + * Spec says we should do both at the same time, but Ricoh + * controllers do not like that. + */ + sdhci_do_reset(host, SDHCI_RESET_CMD); + sdhci_do_reset(host, SDHCI_RESET_DATA); + + host->pending_reset = false; + } + + /* * Always unmap the data buffers if they were mapped by * sdhci_prepare_data() whenever we finish with a request. * This avoids leaking DMA mappings on error. @@ -3033,7 +3063,7 @@ static bool sdhci_request_done(struct sdhci_host *host) length = host->bounce_buffer_size; } dma_sync_single_for_cpu( - host->mmc->parent, + mmc_dev(host->mmc), host->bounce_addr, host->bounce_buffer_size, DMA_FROM_DEVICE); @@ -3044,7 +3074,7 @@ static bool sdhci_request_done(struct sdhci_host *host) } else { /* No copying, just switch ownership */ dma_sync_single_for_cpu( - host->mmc->parent, + mmc_dev(host->mmc), host->bounce_addr, host->bounce_buffer_size, mmc_get_dma_dir(data)); @@ -3059,35 +3089,6 @@ static bool sdhci_request_done(struct sdhci_host *host) } } - /* - * The controller needs a reset of internal state machines - * upon error conditions. - */ - if (sdhci_needs_reset(host, mrq)) { - /* - * Do not finish until command and data lines are available for - * reset. Note there can only be one other mrq, so it cannot - * also be in mrqs_done, otherwise host->cmd and host->data_cmd - * would both be null. - */ - if (host->cmd || host->data_cmd) { - spin_unlock_irqrestore(&host->lock, flags); - return true; - } - - /* Some controllers need this kick or reset won't work here */ - if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) - /* This is to force an update */ - host->ops->set_clock(host, host->clock); - - /* Spec says we should do both at the same time, but Ricoh - controllers do not like that. */ - sdhci_do_reset(host, SDHCI_RESET_CMD); - sdhci_do_reset(host, SDHCI_RESET_DATA); - - host->pending_reset = false; - } - host->mrqs_done[i] = NULL; spin_unlock_irqrestore(&host->lock, flags); @@ -3675,7 +3676,7 @@ int sdhci_resume_host(struct sdhci_host *host) host->ops->enable_dma(host); } - if ((host->mmc->pm_flags & MMC_PM_KEEP_POWER) && + if ((mmc->pm_flags & MMC_PM_KEEP_POWER) && (host->quirks2 & SDHCI_QUIRK2_HOST_OFF_CARD_ON)) { /* Card keeps power but host controller does not */ sdhci_init(host, 0); @@ -3683,7 +3684,7 @@ int sdhci_resume_host(struct sdhci_host *host) host->clock = 0; mmc->ops->set_ios(mmc, &mmc->ios); } else { - sdhci_init(host, (host->mmc->pm_flags & MMC_PM_KEEP_POWER)); + sdhci_init(host, (mmc->pm_flags & MMC_PM_KEEP_POWER)); } if (host->irq_wake_enabled) { @@ -3691,7 +3692,7 @@ int sdhci_resume_host(struct sdhci_host *host) } else { ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq, IRQF_SHARED, - mmc_hostname(host->mmc), host); + mmc_hostname(mmc), host); if (ret) return ret; } @@ -4052,7 +4053,7 @@ static void sdhci_allocate_bounce_buffer(struct sdhci_host *host) * speedups by the help of a bounce buffer to group scattered * reads/writes together. */ - host->bounce_buffer = devm_kmalloc(mmc->parent, + host->bounce_buffer = devm_kmalloc(mmc_dev(mmc), bounce_size, GFP_KERNEL); if (!host->bounce_buffer) { @@ -4066,11 +4067,11 @@ static void sdhci_allocate_bounce_buffer(struct sdhci_host *host) return; } - host->bounce_addr = dma_map_single(mmc->parent, + host->bounce_addr = dma_map_single(mmc_dev(mmc), host->bounce_buffer, bounce_size, DMA_BIDIRECTIONAL); - ret = dma_mapping_error(mmc->parent, host->bounce_addr); + ret = dma_mapping_error(mmc_dev(mmc), host->bounce_addr); if (ret) /* Again fall back to max_segs == 1 */ return; @@ -4378,7 +4379,7 @@ int sdhci_setup_host(struct sdhci_host *host) if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) && mmc_card_is_removable(mmc) && - mmc_gpio_get_cd(host->mmc) < 0) + mmc_gpio_get_cd(mmc) < 0) mmc->caps |= MMC_CAP_NEEDS_POLL; if (!IS_ERR(mmc->supply.vqmmc)) { diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index 7a34649b0754..1fad6e442688 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -558,7 +558,7 @@ static int sdhci_am654_cqe_add_host(struct sdhci_host *host) struct cqhci_host *cq_host; int ret; - cq_host = devm_kzalloc(host->mmc->parent, sizeof(struct cqhci_host), + cq_host = devm_kzalloc(mmc_dev(host->mmc), sizeof(struct cqhci_host), GFP_KERNEL); if (!cq_host) return -ENOMEM; diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index 2d1db9396d4a..f936aad945ce 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -100,8 +100,8 @@ /* Define some IRQ masks */ /* This is the mask used at reset by the chip */ -#define TMIO_MASK_INIT_RCAR2 0x8b7f031d /* Initial value for R-Car Gen2+ */ #define TMIO_MASK_ALL 0x837f031d +#define TMIO_MASK_ALL_RCAR2 0x8b7f031d #define TMIO_MASK_READOP (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND) #define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND) #define TMIO_MASK_CMD (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \ @@ -164,6 +164,7 @@ struct tmio_mmc_host { u32 sdio_irq_mask; unsigned int clk_cache; u32 sdcard_irq_setbit_mask; + u32 sdcard_irq_mask_all; spinlock_t lock; /* protect host private data */ unsigned long last_req_ts; diff --git a/drivers/mmc/host/tmio_mmc_core.c b/drivers/mmc/host/tmio_mmc_core.c index 49c2d406c48e..7dfc26f48c18 100644 --- a/drivers/mmc/host/tmio_mmc_core.c +++ b/drivers/mmc/host/tmio_mmc_core.c @@ -164,6 +164,21 @@ static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) } } +static void tmio_mmc_set_bus_width(struct tmio_mmc_host *host, + unsigned char bus_width) +{ + u16 reg = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT) + & ~(CARD_OPT_WIDTH | CARD_OPT_WIDTH8); + + /* reg now applies to MMC_BUS_WIDTH_4 */ + if (bus_width == MMC_BUS_WIDTH_1) + reg |= CARD_OPT_WIDTH; + else if (bus_width == MMC_BUS_WIDTH_8) + reg |= CARD_OPT_WIDTH8; + + sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, reg); +} + static void tmio_mmc_reset(struct tmio_mmc_host *host) { /* FIXME - should we set stop clock reg here */ @@ -172,15 +187,23 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host) sd_ctrl_write16(host, CTL_RESET_SD, 0x0001); usleep_range(10000, 11000); + tmio_mmc_abort_dma(host); + if (host->reset) host->reset(host); - tmio_mmc_abort_dma(host); + sd_ctrl_write32_as_16_and_16(host, CTL_IRQ_MASK, host->sdcard_irq_mask_all); + host->sdcard_irq_mask = host->sdcard_irq_mask_all; + + tmio_mmc_set_bus_width(host, host->mmc->ios.bus_width); if (host->pdata->flags & TMIO_MMC_SDIO_IRQ) { sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, host->sdio_irq_mask); sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001); } + + if (host->mmc->card) + mmc_retune_needed(host->mmc); } static void tmio_mmc_reset_work(struct work_struct *work) @@ -874,21 +897,6 @@ static void tmio_mmc_power_off(struct tmio_mmc_host *host) host->set_pwr(host->pdev, 0); } -static void tmio_mmc_set_bus_width(struct tmio_mmc_host *host, - unsigned char bus_width) -{ - u16 reg = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT) - & ~(CARD_OPT_WIDTH | CARD_OPT_WIDTH8); - - /* reg now applies to MMC_BUS_WIDTH_4 */ - if (bus_width == MMC_BUS_WIDTH_1) - reg |= CARD_OPT_WIDTH; - else if (bus_width == MMC_BUS_WIDTH_8) - reg |= CARD_OPT_WIDTH8; - - sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, reg); -} - static unsigned int tmio_mmc_get_timeout_cycles(struct tmio_mmc_host *host) { u16 val = sd_ctrl_read16(host, CTL_SD_MEM_CARD_OPT); @@ -1161,15 +1169,6 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) !mmc_card_is_removable(mmc)); /* - * On Gen2+, eMMC with NONREMOVABLE currently fails because native - * hotplug gets disabled. It seems RuntimePM related yet we need further - * research. Since we are planning a PM overhaul anyway, let's enforce - * for now the device being active by enabling native hotplug always. - */ - if (pdata->flags & TMIO_MMC_MIN_RCAR2) - _host->native_hotplug = true; - - /* * While using internal tmio hardware logic for card detection, we need * to ensure it stays powered for it to work. */ @@ -1180,12 +1179,12 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host) if (pdata->flags & TMIO_MMC_SDIO_IRQ) _host->sdio_irq_mask = TMIO_SDIO_MASK_ALL; + if (!_host->sdcard_irq_mask_all) + _host->sdcard_irq_mask_all = TMIO_MASK_ALL; + _host->set_clock(_host, 0); tmio_mmc_reset(_host); - _host->sdcard_irq_mask = sd_ctrl_read16_and_16_as_32(_host, CTL_IRQ_MASK); - tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL); - if (_host->native_hotplug) tmio_mmc_enable_mmc_irqs(_host, TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT); @@ -1238,7 +1237,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host) cancel_work_sync(&host->done); cancel_delayed_work_sync(&host->delayed_reset_work); tmio_mmc_release_dma(host); - tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL); + tmio_mmc_disable_mmc_irqs(host, host->sdcard_irq_mask_all); if (host->native_hotplug) pm_runtime_put_noidle(&pdev->dev); @@ -1268,7 +1267,7 @@ int tmio_mmc_host_runtime_suspend(struct device *dev) { struct tmio_mmc_host *host = dev_get_drvdata(dev); - tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_ALL); + tmio_mmc_disable_mmc_irqs(host, host->sdcard_irq_mask_all); if (host->clk_cache) host->set_clock(host, 0); @@ -1295,8 +1294,6 @@ int tmio_mmc_host_runtime_resume(struct device *dev) tmio_mmc_enable_dma(host, true); - mmc_retune_needed(host->mmc); - return 0; } EXPORT_SYMBOL_GPL(tmio_mmc_host_runtime_resume); diff --git a/drivers/mmc/host/uniphier-sd.c b/drivers/mmc/host/uniphier-sd.c index 2413b6750cec..ccbf9885a52b 100644 --- a/drivers/mmc/host/uniphier-sd.c +++ b/drivers/mmc/host/uniphier-sd.c @@ -635,7 +635,7 @@ static int uniphier_sd_probe(struct platform_device *pdev) ret = tmio_mmc_host_probe(host); if (ret) - goto free_host; + goto disable_clk; ret = devm_request_irq(dev, irq, tmio_mmc_irq, IRQF_SHARED, dev_name(dev), host); @@ -646,6 +646,8 @@ static int uniphier_sd_probe(struct platform_device *pdev) remove_host: tmio_mmc_host_remove(host); +disable_clk: + uniphier_sd_clk_disable(host); free_host: tmio_mmc_host_free(host); @@ -658,6 +660,7 @@ static int uniphier_sd_remove(struct platform_device *pdev) tmio_mmc_host_remove(host); uniphier_sd_clk_disable(host); + tmio_mmc_host_free(host); return 0; } diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 4f4c0813f9fd..a1d098560099 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -1271,7 +1271,6 @@ static int __maybe_unused via_sd_suspend(struct device *dev) static int __maybe_unused via_sd_resume(struct device *dev) { struct via_crdr_mmc_host *sdhost; - int ret = 0; u8 gatt; sdhost = dev_get_drvdata(dev); @@ -1292,7 +1291,7 @@ static int __maybe_unused via_sd_resume(struct device *dev) via_restore_pcictrlreg(sdhost); via_init_sdc_pm(sdhost); - return ret; + return 0; } static SIMPLE_DEV_PM_OPS(via_sd_pm_ops, via_sd_suspend, via_sd_resume); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 26a3c7bc29ae..c7e7b43600e9 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -302,9 +302,6 @@ struct mmc_host { u32 ocr_avail_sdio; /* SDIO-specific OCR */ u32 ocr_avail_sd; /* SD-specific OCR */ u32 ocr_avail_mmc; /* MMC-specific OCR */ -#ifdef CONFIG_PM_SLEEP - struct notifier_block pm_notify; -#endif struct wakeup_source *ws; /* Enable consume of uevents */ u32 max_current_330; u32 max_current_300; @@ -423,7 +420,6 @@ struct mmc_host { /* group bitfields together to minimize padding */ unsigned int use_spi_crc:1; unsigned int claimed:1; /* host exclusively claimed */ - unsigned int bus_dead:1; /* bus has been released */ unsigned int doing_init_tune:1; /* initial tuning in progress */ unsigned int can_retune:1; /* re-tuning can be used */ unsigned int doing_retune:1; /* re-tuning in progress */ @@ -454,7 +450,6 @@ struct mmc_host { struct mmc_slot slot; const struct mmc_bus_ops *bus_ops; /* current bus driver */ - unsigned int bus_refs; /* reference counter */ unsigned int sdio_irqs; struct task_struct *sdio_irq_thread; @@ -514,7 +509,7 @@ void mmc_free_host(struct mmc_host *); void mmc_of_parse_clk_phase(struct mmc_host *host, struct mmc_clk_phase_map *map); int mmc_of_parse(struct mmc_host *host); -int mmc_of_parse_voltage(struct device_node *np, u32 *mask); +int mmc_of_parse_voltage(struct mmc_host *host, u32 *mask); static inline void *mmc_priv(struct mmc_host *host) { diff --git a/include/linux/mmc/sdio.h b/include/linux/mmc/sdio.h index e28769991e82..2a05d1ac4f0e 100644 --- a/include/linux/mmc/sdio.h +++ b/include/linux/mmc/sdio.h @@ -82,7 +82,7 @@ #define SDIO_SD_REV_1_01 0 /* SD Physical Spec Version 1.01 */ #define SDIO_SD_REV_1_10 1 /* SD Physical Spec Version 1.10 */ #define SDIO_SD_REV_2_00 2 /* SD Physical Spec Version 2.00 */ -#define SDIO_SD_REV_3_00 3 /* SD Physical Spev Version 3.00 */ +#define SDIO_SD_REV_3_00 3 /* SD Physical Spec Version 3.00 */ #define SDIO_CCCR_IOEx 0x02 #define SDIO_CCCR_IORx 0x03 diff --git a/include/linux/spi/mmc_spi.h b/include/linux/spi/mmc_spi.h index 778ae8eb1f3e..9ad9a06e488d 100644 --- a/include/linux/spi/mmc_spi.h +++ b/include/linux/spi/mmc_spi.h @@ -35,16 +35,7 @@ struct mmc_spi_platform_data { void (*setpower)(struct device *, unsigned int maskval); }; -#ifdef CONFIG_OF extern struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi); extern void mmc_spi_put_pdata(struct spi_device *spi); -#else -static inline struct mmc_spi_platform_data * -mmc_spi_get_pdata(struct spi_device *spi) -{ - return spi->dev.platform_data; -} -static inline void mmc_spi_put_pdata(struct spi_device *spi) {} -#endif /* CONFIG_OF */ #endif /* __LINUX_SPI_MMC_SPI_H */ |