diff --git a/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml index bd558a11b792..b3fcc1673c10 100644 --- a/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml +++ b/Documentation/devicetree/bindings/mmc/qcom,sdhci-msm.yaml @@ -145,6 +145,11 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 description: platform specific settings for DLL_CONFIG reg. + qcom,ice: + $ref: /schemas/types.yaml#/definitions/phandle + description: + phandle to the Inline Crypto Engine (ICE) hardware block for this controller. + iommus: minItems: 1 maxItems: 8 @@ -198,35 +203,69 @@ allOf: enum: - qcom,sdhci-msm-v4 then: - properties: - reg: - minItems: 2 - items: - - description: Host controller register map - - description: SD Core register map - - description: CQE register map - - description: Inline Crypto Engine register map - reg-names: - minItems: 2 - items: - - const: hc - - const: core - - const: cqhci - - const: ice + if: + required: + - qcom,ice + then: + properties: + reg: + minItems: 2 + items: + - description: Host controller register map + - description: SD Core register map + - description: CQE register map + reg-names: + minItems: 2 + items: + - const: hc + - const: core + - const: cqhci + else: + properties: + reg: + minItems: 2 + items: + - description: Host controller register map + - description: SD Core register map + - description: CQE register map + - description: Inline Crypto Engine register map + reg-names: + minItems: 2 + items: + - const: hc + - const: core + - const: cqhci + - const: ice else: - properties: - reg: - minItems: 1 - items: - - description: Host controller register map - - description: CQE register map - - description: Inline Crypto Engine register map - reg-names: - minItems: 1 - items: - - const: hc - - const: cqhci - - const: ice + if: + required: + - qcom,ice + then: + properties: + reg: + minItems: 1 + items: + - description: Host controller register map + - description: CQE register map + reg-names: + minItems: 1 + items: + - const: hc + - const: cqhci + else: + properties: + reg: + minItems: 1 + items: + - description: Host controller register map + - description: CQE register map + - description: Inline Crypto Engine register map + reg-names: + minItems: 1 + items: + - const: hc + - const: cqhci + - const: ice unevaluatedProperties: false diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml index 4965bb518c54..21ecfaa454f4 100644 --- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml +++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml @@ -43,6 +43,7 @@ properties: - rockchip,rk3562-dw-mshc - rockchip,rk3568-dw-mshc - rockchip,rk3588-dw-mshc + - rockchip,rv1106-dw-mshc - rockchip,rv1108-dw-mshc - rockchip,rv1126-dw-mshc - const: rockchip,rk3288-dw-mshc diff --git a/Documentation/devicetree/bindings/mmc/sdhci-st.txt b/Documentation/devicetree/bindings/mmc/sdhci-st.txt deleted file mode 100644 index ccf82b4ee838..000000000000 --- a/Documentation/devicetree/bindings/mmc/sdhci-st.txt +++ /dev/null @@ -1,110 +0,0 @@ -* STMicroelectronics sdhci-st MMC/SD controller - -This file documents the differences between the core properties in -Documentation/devicetree/bindings/mmc/mmc.txt and the properties -used by the sdhci-st driver. - -Required properties: -- compatible: Must be "st,sdhci" and it can be compatible to "st,sdhci-stih407" - to set the internal glue logic used for configuring the MMC - subsystem (mmcss) inside the FlashSS (available in STiH407 SoC - family). - -- clock-names: Should be "mmc" and "icn". (NB: The latter is not compulsory) - See: Documentation/devicetree/bindings/resource-names.txt -- clocks: Phandle to the clock. - See: Documentation/devicetree/bindings/clock/clock-bindings.txt - -- interrupts: One mmc interrupt should be described here. -- interrupt-names: Should be "mmcirq". - -- pinctrl-names: A pinctrl state names "default" must be defined. -- pinctrl-0: Phandle referencing pin configuration of the sd/emmc controller. - See: Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt - -- reg: This must provide the host controller base address and it can also - contain the FlashSS Top register for TX/RX delay used by the driver - to configure DLL inside the flashSS, if so reg-names must also be - specified. - -Optional properties: -- reg-names: Should be "mmc" and "top-mmc-delay". "top-mmc-delay" is optional - for eMMC on stih407 family silicon to configure DLL inside FlashSS. - -- non-removable: Non-removable slot. Also used for configuring mmcss in STiH407 SoC - family. - See: Documentation/devicetree/bindings/mmc/mmc.txt. - -- bus-width: Number of data lines. - See: Documentation/devicetree/bindings/mmc/mmc.txt. - -- max-frequency: Can be 200MHz, 100MHz or 50MHz (default) and used for - configuring the CCONFIG3 in the mmcss. - See: Documentation/devicetree/bindings/mmc/mmc.txt. - -- resets: Phandle and reset specifier pair to softreset line of HC IP. - See: Documentation/devicetree/bindings/reset/reset.txt - -- vqmmc-supply: Phandle to the regulator dt node, mentioned as the vcc/vdd - supply in eMMC/SD specs. - -- sd-uhs-sdr50: To enable the SDR50 in the mmcss. - See: Documentation/devicetree/bindings/mmc/mmc.txt. - -- sd-uhs-sdr104: To enable the SDR104 in the mmcss. - See: Documentation/devicetree/bindings/mmc/mmc.txt. - -- sd-uhs-ddr50: To enable the DDR50 in the mmcss. - See: Documentation/devicetree/bindings/mmc/mmc.txt. - -Example: - -/* Example stih416e eMMC configuration */ - -mmc0: sdhci@fe81e000 { - compatible = "st,sdhci"; - reg = <0xfe81e000 0x1000>; - interrupts = ; - interrupt-names = "mmcirq"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_mmc0>; - clock-names = "mmc"; - clocks = <&clk_s_a1_ls 1>; - bus-width = <8> - -/* Example SD stih407 family configuration */ - -mmc1: sdhci@9080000 { - compatible = "st,sdhci-stih407", "st,sdhci"; - reg = <0x09080000 0x7ff>; - reg-names = "mmc"; - interrupts = ; - interrupt-names = "mmcirq"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_sd1>; - clock-names = "mmc"; - clocks = <&clk_s_c0_flexgen CLK_MMC_1>; - resets = <&softreset STIH407_MMC1_SOFTRESET>; - bus-width = <4>; -}; - -/* Example eMMC stih407 family configuration */ - -mmc0: sdhci@9060000 { - compatible = "st,sdhci-stih407", "st,sdhci"; - reg = <0x09060000 0x7ff>, <0x9061008 0x20>; - reg-names = "mmc", "top-mmc-delay"; - interrupts = ; - interrupt-names = "mmcirq"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_mmc0>; - clock-names = "mmc"; - clocks = <&clk_s_c0_flexgen CLK_MMC_0>; - vqmmc-supply = <&vmmc_reg>; - max-frequency = <200000000>; - bus-width = <8>; - non-removable; - sd-uhs-sdr50; - sd-uhs-sdr104; - sd-uhs-ddr50; -}; diff --git a/Documentation/devicetree/bindings/mmc/st,sdhci.yaml b/Documentation/devicetree/bindings/mmc/st,sdhci.yaml new file mode 100644 index 000000000000..798af599d374 --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/st,sdhci.yaml @@ -0,0 +1,105 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/st,sdhci.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: STMicroelectronics SDHCI-ST MMC/SD Controller + +maintainers: + - Peter Griffin + +description: + The STMicroelectronics SDHCI-ST MMC/SD host controller is compliant with + the SD Host Controller Interface (SDHCI) specification and is used to + interface with MMC, SD and SDIO cards. The ST SDHCI controller extends the + standard SDHCI capabilities with platform-specific configurations such as + additional register regions, clock inputs, and delay control mechanisms + required for signal timing adjustments to support high-speed modes across + different ST SoCs. + +allOf: + - $ref: mmc-controller.yaml# + - if: + properties: + reg: + minItems: 2 + required: + - reg + then: + required: + - reg-names + +properties: + compatible: + oneOf: + - const: st,sdhci + - items: + - const: st,sdhci-stih407 + - const: st,sdhci + + reg: + minItems: 1 + items: + - description: MMC controller base registers + - description: FlashSS Top registers for TX/RX DLL delay configuration + + reg-names: + minItems: 1 + items: + - const: mmc + - const: top-mmc-delay + + clocks: + minItems: 1 + items: + - description: Clock for the MMC controller + - description: Interconnect (ICN) clock + + clock-names: + minItems: 1 + items: + - const: mmc + - const: icn + + interrupts: + maxItems: 1 + + interrupt-names: + const: mmcirq + + resets: + maxItems: 1 + + max-frequency: + enum: [200000000, 100000000, 50000000] + default: 50000000 + +required: + - reg + - compatible + - clocks + - clock-names + - interrupts + - interrupt-names + +unevaluatedProperties: false + +examples: + - | + #include + #include + mmc@9060000 { + compatible = "st,sdhci-stih407", "st,sdhci"; + reg = <0x09060000 0x7ff>, <0x9061008 0x20>; + reg-names = "mmc", "top-mmc-delay"; + interrupts = ; + interrupt-names = "mmcirq"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mmc0>; + clock-names = "mmc", "icn"; + clocks = <&clk_s_c0_flexgen CLK_MMC_0>, + <&clk_s_c0_flexgen CLK_RX_ICN_HVA>; + bus-width = <8>; + }; +... diff --git a/Documentation/devicetree/bindings/mmc/ti,omap2420-mmc.yaml b/Documentation/devicetree/bindings/mmc/ti,omap2420-mmc.yaml new file mode 100644 index 000000000000..794d5ec0b58e --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/ti,omap2420-mmc.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mmc/ti,omap2420-mmc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Texas Instruments MMC host controller for OMAP1 and 2420 + +maintainers: + - Eduard Bostina + +description: | + The MMC Host Controller on TI OMAP1 and 2420 family provides + an interface for MMC, SD, and SDIO types of memory cards. + +allOf: + - $ref: /schemas/mmc/mmc-controller.yaml# + +properties: + compatible: + const: ti,omap2420-mmc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + ti,hwmods: + description: | + Name of the hwmod associated to the MMC controller. Must be + "msdi" where n is the controller instance starting from 1. + $ref: /schemas/types.yaml#/definitions/string + pattern: "^msdi([1-9]|[1-9][0-9]+)$" + + dmas: + maxItems: 2 + + dma-names: + items: + - const: tx + - const: rx + +required: + - compatible + - reg + - interrupts + +unevaluatedProperties: false + +examples: + - | + mmc@4809c000 { + compatible = "ti,omap2420-mmc"; + ti,hwmods = "msdi1"; + reg = <0x4809c000 0x80>; + interrupts = <83>; + dmas = <&sdma 61 &sdma 62>; + dma-names = "tx", "rx"; + }; diff --git a/Documentation/devicetree/bindings/mmc/ti-omap.txt b/Documentation/devicetree/bindings/mmc/ti-omap.txt deleted file mode 100644 index 02fd31cf361d..000000000000 --- a/Documentation/devicetree/bindings/mmc/ti-omap.txt +++ /dev/null @@ -1,26 +0,0 @@ -* TI MMC host controller for OMAP1 and 2420 - -The MMC Host Controller on TI OMAP1 and 2420 family provides -an interface for MMC, SD, and SDIO types of memory cards. - -This file documents differences between the core properties described -by mmc.txt and the properties used by the omap mmc driver. - -Note that this driver will not work with omap2430 or later omaps, -please see the omap hsmmc driver for the current omaps. - -Required properties: -- compatible: Must be "ti,omap2420-mmc", for OMAP2420 controllers -- ti,hwmods: For 2420, must be "msdi", where n is controller - instance starting 1 - -Examples: - - msdi1: mmc@4809c000 { - compatible = "ti,omap2420-mmc"; - ti,hwmods = "msdi1"; - reg = <0x4809c000 0x80>; - interrupts = <83>; - dmas = <&sdma 61 &sdma 62>; - dma-names = "tx", "rx"; - }; diff --git a/MAINTAINERS b/MAINTAINERS index 957cd64170cf..cdeac48061e4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -27067,6 +27067,13 @@ Q: http://patchwork.linuxtv.org/project/linux-media/list/ T: git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git F: drivers/media/platform/ti/am437x/ +TI AM654 SDHCI DRIVER +M: Judith Mendez +L: linux-mmc@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/mmc/sdhci-am654.yaml +F: drivers/mmc/host/sdhci_am654.c + TI BANDGAP AND THERMAL DRIVER M: Eduardo Valentin M: Keerthy diff --git a/arch/arm/boot/dts/st/stih407-family.dtsi b/arch/arm/boot/dts/st/stih407-family.dtsi index 3e6a0542e3ae..08acba209c56 100644 --- a/arch/arm/boot/dts/st/stih407-family.dtsi +++ b/arch/arm/boot/dts/st/stih407-family.dtsi @@ -596,7 +596,7 @@ status = "disabled"; }; - mmc0: sdhci@9060000 { + mmc0: mmc@9060000 { compatible = "st,sdhci-stih407", "st,sdhci"; status = "disabled"; reg = <0x09060000 0x7ff>, <0x9061008 0x20>; @@ -611,7 +611,7 @@ bus-width = <8>; }; - mmc1: sdhci@9080000 { + mmc1: mmc@9080000 { compatible = "st,sdhci-stih407", "st,sdhci"; status = "disabled"; reg = <0x09080000 0x7ff>; diff --git a/arch/arm/boot/dts/st/stih410-b2260.dts b/arch/arm/boot/dts/st/stih410-b2260.dts index 736b1e059b0a..44048a98648e 100644 --- a/arch/arm/boot/dts/st/stih410-b2260.dts +++ b/arch/arm/boot/dts/st/stih410-b2260.dts @@ -141,14 +141,14 @@ status = "okay"; }; - mmc0: sdhci@9060000 { + mmc0: mmc@9060000 { pinctrl-0 = <&pinctrl_sd0>; bus-width = <4>; status = "okay"; }; /* high speed expansion connector */ - mmc1: sdhci@9080000 { + mmc1: mmc@9080000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/st/stih418-b2199.dts b/arch/arm/boot/dts/st/stih418-b2199.dts index 53ac6c2b7b7d..4ea174597365 100644 --- a/arch/arm/boot/dts/st/stih418-b2199.dts +++ b/arch/arm/boot/dts/st/stih418-b2199.dts @@ -82,11 +82,11 @@ st,i2c-min-sda-pulse-width-us = <5>; }; - mmc1: sdhci@9080000 { + mmc1: mmc@9080000 { status = "okay"; }; - mmc0: sdhci@9060000 { + mmc0: mmc@9060000 { status = "okay"; max-frequency = <200000000>; sd-uhs-sdr50; diff --git a/arch/arm/boot/dts/st/stih418.dtsi b/arch/arm/boot/dts/st/stih418.dtsi index 8fb8b3af5e49..1a5fbbedc8cd 100644 --- a/arch/arm/boot/dts/st/stih418.dtsi +++ b/arch/arm/boot/dts/st/stih418.dtsi @@ -136,7 +136,7 @@ phy-names = "usb"; }; - mmc0: sdhci@9060000 { + mmc0: mmc@9060000 { assigned-clocks = <&clk_s_c0_flexgen CLK_MMC_0>; assigned-clock-parents = <&clk_s_c0_pll1 0>; assigned-clock-rates = <200000000>; diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c index 1830e9ed2521..a127744918f4 100644 --- a/drivers/misc/cardreader/rtsx_usb.c +++ b/drivers/misc/cardreader/rtsx_usb.c @@ -312,6 +312,9 @@ int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status) if (ret < 0) return ret; + ucr->card_status_cache = *status; + ucr->card_status_valid = true; + return 0; } EXPORT_SYMBOL_GPL(rtsx_usb_get_card_status); @@ -623,6 +626,7 @@ static int rtsx_usb_probe(struct usb_interface *intf, { struct usb_device *usb_dev = interface_to_usbdev(intf); struct rtsx_ucr *ucr; + u16 status; int ret; dev_dbg(&intf->dev, @@ -659,6 +663,9 @@ static int rtsx_usb_probe(struct usb_interface *intf, if (ret) goto out_init_fail; + /* Prime cached status for runtime autosuspend decisions. */ + rtsx_usb_get_card_status(ucr, &status); + /* initialize USB SG transfer timer */ timer_setup(&ucr->sg_timer, rtsx_usb_sg_timed_out, 0); @@ -713,22 +720,29 @@ static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message) struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf); u16 val = 0; + bool valid = false; dev_dbg(&intf->dev, "%s called with pm message 0x%04x\n", __func__, message.event); if (PMSG_IS_AUTO(message)) { if (mutex_trylock(&ucr->dev_mutex)) { - rtsx_usb_get_card_status(ucr, &val); + valid = ucr->card_status_valid; + if (valid) + val = ucr->card_status_cache; mutex_unlock(&ucr->dev_mutex); - /* Defer the autosuspend if card exists */ - if (val & (SD_CD | MS_CD)) { + /* + * Do not issue USB commands from runtime autosuspend. + * Raw SD_CD is not authoritative on tray-based readers, + * while a real SD card is protected by the SD/MMC child + * runtime-PM reference once the card is powered. Keep + * the historical Memory Stick autosuspend deferral when + * the cached status says MS media is present. + */ + if (valid && (val & MS_CD)) { device_for_each_child(&intf->dev, NULL, rtsx_usb_resume_child); return -EAGAIN; - } else { - /* if the card does not exists, clear OCP status */ - rtsx_usb_write_register(ucr, OCPCTL, MS_OCP_CLEAR, MS_OCP_CLEAR); } } else { /* There is an ongoing operation*/ diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 54a923ba4f1e..e760d13ee325 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -3337,6 +3337,11 @@ static int __init mmc_blk_init(void) { int res; + if (perdev_minors <= 0) { + pr_err("mmcblk: invalid minors per device: %d\n", perdev_minors); + return -EINVAL; + } + res = bus_register(&mmc_rpmb_bus_type); if (res < 0) { pr_err("mmcblk: could not register RPMB bus type\n"); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 948948ca9b4a..c763efb10f64 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1379,15 +1379,10 @@ out: static int sd_enable_cache(struct mmc_card *card) { - u8 *reg_buf; int err; card->ext_perf.feature_enabled &= ~SD_EXT_PERF_CACHE; - reg_buf = kzalloc(512, GFP_KERNEL); - if (!reg_buf) - return -ENOMEM; - /* * Set Cache Enable at bit 0 in the performance enhancement register at * 260 bytes offset. @@ -1397,7 +1392,7 @@ static int sd_enable_cache(struct mmc_card *card) if (err) { pr_warn("%s: error %d writing Cache Enable bit\n", mmc_hostname(card->host), err); - goto out; + return err; } err = mmc_poll_for_busy(card, SD_WRITE_EXTR_SINGLE_TIMEOUT_MS, false, @@ -1405,8 +1400,6 @@ static int sd_enable_cache(struct mmc_card *card) if (!err) card->ext_perf.feature_enabled |= SD_EXT_PERF_CACHE; -out: - kfree(reg_buf); return err; } diff --git a/drivers/mmc/host/alcor.c b/drivers/mmc/host/alcor.c index 721db54739c1..45528909a758 100644 --- a/drivers/mmc/host/alcor.c +++ b/drivers/mmc/host/alcor.c @@ -1103,8 +1103,7 @@ static int alcor_pci_sdmmc_drv_probe(struct platform_device *pdev) alcor_irq, alcor_irq_thread, IRQF_SHARED, DRV_NAME_ALCOR_PCI_SDMMC, host); if (ret) - return dev_err_probe(&pdev->dev, ret, - "Failed to get irq for data line\n"); + return ret; mutex_init(&host->cmd_mutex); INIT_DELAYED_WORK(&host->timeout_work, alcor_timeout_timer); diff --git a/drivers/mmc/host/bcm2835.c b/drivers/mmc/host/bcm2835.c index ee63835b3ca0..c949a3eaae79 100644 --- a/drivers/mmc/host/bcm2835.c +++ b/drivers/mmc/host/bcm2835.c @@ -188,7 +188,7 @@ struct bcm2835_host { u32 drain_words; struct page *drain_page; u32 drain_offset; - bool use_dma; + struct device *dma_dev; }; static void bcm2835_dumpcmd(struct bcm2835_host *host, struct mmc_command *cmd, @@ -494,8 +494,7 @@ void bcm2835_prepare_dma(struct bcm2835_host *host, struct mmc_data *data) &host->dma_cfg_rx : &host->dma_cfg_tx); - sg_len = dma_map_sg(dma_chan->device->dev, data->sg, data->sg_len, - dir_data); + sg_len = dma_map_sg(host->dma_dev, data->sg, data->sg_len, dir_data); if (!sg_len) return; @@ -503,8 +502,7 @@ void bcm2835_prepare_dma(struct bcm2835_host *host, struct mmc_data *data) DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) { - dma_unmap_sg(dma_chan->device->dev, data->sg, data->sg_len, - dir_data); + dma_unmap_sg(host->dma_dev, data->sg, data->sg_len, dir_data); return; } @@ -1057,7 +1055,7 @@ static void bcm2835_dma_complete_work(struct work_struct *work) data = host->data; if (host->dma_chan) { - dma_unmap_sg(host->dma_chan->device->dev, + dma_unmap_sg(host->dma_dev, data->sg, data->sg_len, host->dma_dir); @@ -1201,7 +1199,7 @@ static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq) return; } - if (host->use_dma && mrq->data && (mrq->data->blocks > PIO_THRESHOLD)) + if (host->dma_dev && mrq->data && (mrq->data->blocks > PIO_THRESHOLD)) bcm2835_prepare_dma(host, mrq->data); host->use_sbc = !!mrq->sbc && host->mrq->data && @@ -1281,10 +1279,7 @@ static int bcm2835_add_host(struct bcm2835_host *host) if (!host->dma_chan_rxtx) { dev_warn(dev, "unable to initialise DMA channel. Falling back to PIO\n"); - host->use_dma = false; } else { - host->use_dma = true; - host->dma_cfg_tx.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; host->dma_cfg_tx.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; host->dma_cfg_tx.direction = DMA_MEM_TO_DEV; @@ -1297,15 +1292,21 @@ static int bcm2835_add_host(struct bcm2835_host *host) host->dma_cfg_rx.src_addr = host->phys_addr + SDDATA; host->dma_cfg_rx.dst_addr = 0; - if (dmaengine_slave_config(host->dma_chan_rxtx, - &host->dma_cfg_tx) != 0 || - dmaengine_slave_config(host->dma_chan_rxtx, - &host->dma_cfg_rx) != 0) - host->use_dma = false; + if (!dmaengine_slave_config(host->dma_chan_rxtx, + &host->dma_cfg_tx) && + !dmaengine_slave_config(host->dma_chan_rxtx, + &host->dma_cfg_rx)) { + host->dma_dev = + dmaengine_get_dma_device(host->dma_chan_rxtx); + } } mmc->max_segs = 128; - mmc->max_req_size = min_t(size_t, 524288, dma_max_mapping_size(dev)); + mmc->max_req_size = 524288; + if (host->dma_dev) { + mmc->max_req_size = min_t(size_t, mmc->max_req_size, + dma_max_mapping_size(host->dma_dev)); + } mmc->max_seg_size = mmc->max_req_size; mmc->max_blk_size = 1024; mmc->max_blk_count = 65535; @@ -1336,10 +1337,10 @@ static int bcm2835_add_host(struct bcm2835_host *host) } pio_limit_string[0] = '\0'; - if (host->use_dma && (PIO_THRESHOLD > 0)) + if (host->dma_dev && (PIO_THRESHOLD > 0)) sprintf(pio_limit_string, " (>%d)", PIO_THRESHOLD); dev_info(dev, "loaded - DMA %s%s\n", - host->use_dma ? "enabled" : "disabled", pio_limit_string); + host->dma_dev ? "enabled" : "disabled", pio_limit_string); return 0; } diff --git a/drivers/mmc/host/cavium-octeon.c b/drivers/mmc/host/cavium-octeon.c index 8a0daddd9200..1bfc1a4f9fe9 100644 --- a/drivers/mmc/host/cavium-octeon.c +++ b/drivers/mmc/host/cavium-octeon.c @@ -240,21 +240,15 @@ static int octeon_mmc_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, mmc_irq[i], cvm_mmc_interrupt, 0, cvm_mmc_irq_names[i], host); - if (ret < 0) { - dev_err(&pdev->dev, "Error: devm_request_irq %d\n", - mmc_irq[i]); + if (ret < 0) return ret; - } } } else { ret = devm_request_irq(&pdev->dev, mmc_irq[0], cvm_mmc_interrupt, 0, KBUILD_MODNAME, host); - if (ret < 0) { - dev_err(&pdev->dev, "Error: devm_request_irq %d\n", - mmc_irq[0]); + if (ret < 0) return ret; - } } host->global_pwr_gpiod = devm_gpiod_get_optional(&pdev->dev, diff --git a/drivers/mmc/host/cqhci-core.c b/drivers/mmc/host/cqhci-core.c index 178277d90c31..a466cd88b043 100644 --- a/drivers/mmc/host/cqhci-core.c +++ b/drivers/mmc/host/cqhci-core.c @@ -484,11 +484,11 @@ void cqhci_set_tran_desc(u8 *desc, dma_addr_t addr, int len, bool end, { __le32 *attr = (__le32 __force *)desc; - *attr = (CQHCI_VALID(1) | - CQHCI_END(end ? 1 : 0) | - CQHCI_INT(0) | - CQHCI_ACT(0x4) | - CQHCI_DAT_LENGTH(len)); + *attr = cpu_to_le32((CQHCI_VALID(1) | + CQHCI_END(end ? 1 : 0) | + CQHCI_INT(0) | + CQHCI_ACT(0x4) | + CQHCI_DAT_LENGTH(len))); if (dma64) { __le64 *dataddr = (__le64 __force *)(desc + 4); @@ -542,7 +542,7 @@ static int cqhci_prep_tran_desc(struct mmc_request *mrq, static void cqhci_prep_dcmd_desc(struct mmc_host *mmc, struct mmc_request *mrq) { - u64 *task_desc = NULL; + __le64 *task_desc = NULL; u64 data = 0; u8 resp_type; u8 *desc; @@ -574,7 +574,7 @@ static void cqhci_prep_dcmd_desc(struct mmc_host *mmc, CQHCI_CMD_TIMING(timing) | CQHCI_RESP_TYPE(resp_type)); if (cq_host->ops->update_dcmd_desc) cq_host->ops->update_dcmd_desc(mmc, mrq, &data); - *task_desc |= data; + *task_desc |= cpu_to_le64(data); desc = (u8 *)task_desc; pr_debug("%s: cqhci: dcmd: cmd: %d timing: %d resp: %d\n", mmc_hostname(mmc), mrq->cmd->opcode, timing, resp_type); @@ -819,8 +819,7 @@ static void cqhci_finish_mrq(struct mmc_host *mmc, unsigned int tag) mmc_cqe_request_done(mmc, mrq); } -irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error, - int data_error) +irqreturn_t cqhci_irq(struct mmc_host *mmc, int cmd_error, int data_error) { u32 status; unsigned long tag = 0, comp_status; diff --git a/drivers/mmc/host/cqhci.h b/drivers/mmc/host/cqhci.h index 3668856531c1..8fbbc48c3f85 100644 --- a/drivers/mmc/host/cqhci.h +++ b/drivers/mmc/host/cqhci.h @@ -315,8 +315,7 @@ static inline u32 cqhci_readl(struct cqhci_host *host, int reg) struct platform_device; -irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error, - int data_error); +irqreturn_t cqhci_irq(struct mmc_host *mmc, int cmd_error, int data_error); int cqhci_init(struct cqhci_host *cq_host, struct mmc_host *mmc, bool dma64); struct cqhci_host *cqhci_pltfm_init(struct platform_device *pdev); int cqhci_deactivate(struct mmc_host *mmc); diff --git a/drivers/mmc/host/dw_mmc-pltfm.h b/drivers/mmc/host/dw_mmc-pltfm.h index ef1b05d484c3..f3193662abf1 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.h +++ b/drivers/mmc/host/dw_mmc-pltfm.h @@ -11,6 +11,5 @@ extern int dw_mci_pltfm_register(struct platform_device *pdev, const struct dw_mci_drv_data *drv_data); extern void dw_mci_pltfm_remove(struct platform_device *pdev); -extern const struct dev_pm_ops dw_mci_pmops; #endif /* _DW_MMC_PLTFM_H_ */ diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index d734d010444d..cf5cecc5491d 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -2057,6 +2057,7 @@ static void dw_mci_work_func(struct work_struct *t) } dw_mci_stop_fault_timer(host); + dw_mci_stop_dma(host); host->data = NULL; set_bit(EVENT_DATA_COMPLETE, &host->completed_events); err = dw_mci_data_complete(host, data); diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index 9ffcd3946cff..38610c89d54a 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -19,6 +19,8 @@ #include #include +extern const struct dev_pm_ops dw_mci_pmops; + enum dw_mci_state { STATE_IDLE = 0, STATE_SENDING_CMD, diff --git a/drivers/mmc/host/litex_mmc.c b/drivers/mmc/host/litex_mmc.c index 06a6f24702e0..332fef8b6646 100644 --- a/drivers/mmc/host/litex_mmc.c +++ b/drivers/mmc/host/litex_mmc.c @@ -28,6 +28,7 @@ #define LITEX_PHY_CLOCKERDIV 0x04 #define LITEX_PHY_INITIALIZE 0x08 #define LITEX_PHY_WRITESTATUS 0x0C +#define LITEX_PHY_SETTINGS 0x18 #define LITEX_CORE_CMDARG 0x00 #define LITEX_CORE_CMDCMD 0x04 #define LITEX_CORE_CMDSND 0x08 @@ -71,6 +72,10 @@ #define SD_INIT_DELAY_US 1000 #define SD_INIT_CLK_HZ 400000 +#define SD_PHY_SPEED_1X 0 +#define SD_PHY_SPEED_4X 1 +#define SD_PHY_SPEED_8X 2 + #define SDIRQ_CARD_DETECT 1 #define SDIRQ_SD_TO_MEM_DONE 2 #define SDIRQ_MEM_TO_SD_DONE 4 @@ -95,11 +100,9 @@ struct litex_mmc_host { unsigned int ref_clk; unsigned int sd_clk; - u32 resp[4]; - u16 rca; + u8 width; - bool is_bus_width_set; - bool app_cmd; + u32 resp[4]; }; static int litex_mmc_sdcard_wait_done(void __iomem *reg, struct device *dev) @@ -164,11 +167,6 @@ static int litex_mmc_send_cmd(struct litex_mmc_host *host, host->sdcore + LITEX_CORE_CMDRSP, 0x10); } - if (!host->app_cmd && cmd == SD_SEND_RELATIVE_ADDR) - host->rca = (host->resp[3] >> 16); - - host->app_cmd = (cmd == MMC_APP_CMD); - if (transfer == SD_CTL_DATA_XFER_NONE) return ret; /* OK from prior litex_mmc_sdcard_wait_done() */ @@ -190,51 +188,6 @@ static int litex_mmc_send_cmd(struct litex_mmc_host *host, return ret; } -static int litex_mmc_send_app_cmd(struct litex_mmc_host *host) -{ - return litex_mmc_send_cmd(host, MMC_APP_CMD, host->rca << 16, - SD_CTL_RESP_SHORT, SD_CTL_DATA_XFER_NONE); -} - -static int litex_mmc_send_set_bus_w_cmd(struct litex_mmc_host *host, u32 width) -{ - return litex_mmc_send_cmd(host, SD_APP_SET_BUS_WIDTH, width, - SD_CTL_RESP_SHORT, SD_CTL_DATA_XFER_NONE); -} - -static int litex_mmc_set_bus_width(struct litex_mmc_host *host) -{ - bool app_cmd_sent; - int ret; - - if (host->is_bus_width_set) - return 0; - - /* Ensure 'app_cmd' precedes 'app_set_bus_width_cmd' */ - app_cmd_sent = host->app_cmd; /* was preceding command app_cmd? */ - if (!app_cmd_sent) { - ret = litex_mmc_send_app_cmd(host); - if (ret) - return ret; - } - - /* LiteSDCard only supports 4-bit bus width */ - ret = litex_mmc_send_set_bus_w_cmd(host, MMC_BUS_WIDTH_4); - if (ret) - return ret; - - /* Re-send 'app_cmd' if necessary */ - if (app_cmd_sent) { - ret = litex_mmc_send_app_cmd(host); - if (ret) - return ret; - } - - host->is_bus_width_set = true; - - return 0; -} - static int litex_mmc_get_cd(struct mmc_host *mmc) { struct litex_mmc_host *host = mmc_priv(mmc); @@ -247,9 +200,6 @@ static int litex_mmc_get_cd(struct mmc_host *mmc) if (ret) return ret; - /* Ensure bus width will be set (again) upon card (re)insertion */ - host->is_bus_width_set = false; - return 0; } @@ -365,39 +315,19 @@ static void litex_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) litex_mmc_response_len(sbc), SD_CTL_DATA_XFER_NONE); if (sbc->error) { - host->is_bus_width_set = false; mmc_request_done(mmc, mrq); return; } } - if (data) { - /* - * LiteSDCard only supports 4-bit bus width; therefore, we MUST - * inject a SET_BUS_WIDTH (acmd6) before the very first data - * transfer, earlier than when the mmc subsystem would normally - * get around to it! - */ - cmd->error = litex_mmc_set_bus_width(host); - if (cmd->error) { - dev_err(dev, "Can't set bus width!\n"); - mmc_request_done(mmc, mrq); - return; - } - + if (data) litex_mmc_do_dma(host, data, &len, &direct, &transfer); - } do { cmd->error = litex_mmc_send_cmd(host, cmd->opcode, cmd->arg, response_len, transfer); } while (cmd->error && retries-- > 0); - if (cmd->error) { - /* Card may be gone; don't assume bus width is still set */ - host->is_bus_width_set = false; - } - if (response_len == SD_CTL_RESP_SHORT) { /* Pull short response fields from appropriate host registers */ cmd->resp[0] = host->resp[3]; @@ -410,13 +340,10 @@ static void litex_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) } /* Send stop-transmission command if required */ - if (stop && (cmd->error || !sbc)) { + if (stop && (cmd->error || !sbc)) stop->error = litex_mmc_send_cmd(host, stop->opcode, stop->arg, litex_mmc_response_len(stop), SD_CTL_DATA_XFER_NONE); - if (stop->error) - host->is_bus_width_set = false; - } if (data) { dma_unmap_sg(dev, data->sg, data->sg_len, @@ -450,6 +377,24 @@ static void litex_mmc_setclk(struct litex_mmc_host *host, unsigned int freq) static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { struct litex_mmc_host *host = mmc_priv(mmc); + unsigned int bus_width = SD_PHY_SPEED_1X; + + switch (ios->bus_width) { + case MMC_BUS_WIDTH_1: + bus_width = SD_PHY_SPEED_1X; + break; + case MMC_BUS_WIDTH_4: + bus_width = SD_PHY_SPEED_4X; + break; + case MMC_BUS_WIDTH_8: + bus_width = SD_PHY_SPEED_8X; + break; + } + + if (host->width != ios->bus_width) { + litex_write8(host->sdphy + LITEX_PHY_SETTINGS, bus_width); + host->width = ios->bus_width; + } /* * The SD specification requires at least 74 idle clocks before CMD0. @@ -462,13 +407,6 @@ static void litex_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) return; } - /* - * NOTE: Ignore any ios->bus_width updates; they occur right after - * the mmc core sends its own acmd6 bus-width change notification, - * which is redundant since we snoop on the command flow and inject - * an early acmd6 before the first data transfer command is sent! - */ - /* Update sd_clk */ if (ios->clock != host->sd_clk) litex_mmc_setclk(host, ios->clock); @@ -546,14 +484,7 @@ static int litex_mmc_probe(struct platform_device *pdev) return dev_err_probe(dev, PTR_ERR(clk), "can't get clock\n"); host->ref_clk = clk_get_rate(clk); host->sd_clk = 0; - - /* - * LiteSDCard only supports 4-bit bus width; therefore, we MUST inject - * a SET_BUS_WIDTH (acmd6) before the very first data transfer, earlier - * than when the mmc subsystem would normally get around to it! - */ - host->is_bus_width_set = false; - host->app_cmd = false; + host->width = MMC_BUS_WIDTH_1; /* LiteSDCard can support 64-bit DMA addressing */ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); @@ -586,6 +517,9 @@ static int litex_mmc_probe(struct platform_device *pdev) litex_write8(host->sdreader + LITEX_BLK2MEM_ENA, 0); litex_write8(host->sdwriter + LITEX_MEM2BLK_ENA, 0); + /* Ensure the litex is at bus width x1 */ + litex_write8(host->sdphy + LITEX_PHY_SETTINGS, SD_PHY_SPEED_1X); + init_completion(&host->cmd_done); ret = litex_mmc_irq_init(pdev, host); if (ret) @@ -610,9 +544,8 @@ static int litex_mmc_probe(struct platform_device *pdev) if (ret) return ret; - /* Force 4-bit bus_width (only width supported by hardware) */ + /* Only drop 8-bit bus_width support */ mmc->caps &= ~MMC_CAP_8_BIT_DATA; - mmc->caps |= MMC_CAP_4_BIT_DATA; /* Set default capabilities */ mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | diff --git a/drivers/mmc/host/meson-mx-sdio.c b/drivers/mmc/host/meson-mx-sdio.c index 5921e2cb2180..bef5e843f449 100644 --- a/drivers/mmc/host/meson-mx-sdio.c +++ b/drivers/mmc/host/meson-mx-sdio.c @@ -683,11 +683,8 @@ static int meson_mx_mmc_probe(struct platform_device *pdev) meson_mx_mmc_irq, meson_mx_mmc_irq_thread, IRQF_ONESHOT, NULL, host); - if (ret) { - dev_err_probe(host->controller_dev, ret, - "Failed to request IRQ\n"); + if (ret) goto error_unregister_slot_pdev; - } core_clk = devm_clk_get_enabled(host->controller_dev, "core"); if (IS_ERR(core_clk)) { diff --git a/drivers/mmc/host/moxart-mmc.c b/drivers/mmc/host/moxart-mmc.c index 3dd8f232052f..28aed13549a6 100644 --- a/drivers/mmc/host/moxart-mmc.c +++ b/drivers/mmc/host/moxart-mmc.c @@ -26,8 +26,6 @@ #include #include #include -#include -#include #include #include #include @@ -264,6 +262,7 @@ static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host) u32 len, dir_slave; struct dma_async_tx_descriptor *desc = NULL; struct dma_chan *dma_chan; + long timeout; if (host->data_len == data->bytes_xfered) return; @@ -296,11 +295,17 @@ static void moxart_transfer_dma(struct mmc_data *data, struct moxart_host *host) dma_async_issue_pending(dma_chan); } - wait_for_completion_interruptible_timeout(&host->dma_complete, - host->timeout); + timeout = wait_for_completion_interruptible_timeout(&host->dma_complete, + host->timeout); + if (timeout <= 0) { + dmaengine_terminate_sync(dma_chan); + data->error = timeout ?: -ETIMEDOUT; + goto unmap; + } data->bytes_xfered = host->data_len; +unmap: dma_unmap_sg(dma_chan->device->dev, data->sg, data->sg_len, mmc_get_dma_dir(data)); @@ -548,8 +553,7 @@ static const struct mmc_host_ops moxart_ops = { static int moxart_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct device_node *node = dev->of_node; - struct resource res_mmc; + struct resource *res_mmc; struct mmc_host *mmc; struct moxart_host *host = NULL; struct dma_slave_config cfg; @@ -558,30 +562,24 @@ static int moxart_probe(struct platform_device *pdev) int irq, ret; u32 i; + reg_mmc = devm_platform_get_and_ioremap_resource(pdev, 0, &res_mmc); + if (IS_ERR(reg_mmc)) + return PTR_ERR(reg_mmc); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + mmc = devm_mmc_alloc_host(dev, sizeof(*host)); if (!mmc) { dev_err(dev, "devm_mmc_alloc_host failed\n"); return -ENOMEM; } - ret = of_address_to_resource(node, 0, &res_mmc); - if (ret) - return dev_err_probe(dev, ret, - "of_address_to_resource failed\n"); - - irq = irq_of_parse_and_map(node, 0); - if (irq <= 0) - return dev_err_probe(dev, -EINVAL, - "irq_of_parse_and_map failed\n"); - clk = devm_clk_get(dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk); - reg_mmc = devm_ioremap_resource(dev, &res_mmc); - if (IS_ERR(reg_mmc)) - return PTR_ERR(reg_mmc); - ret = mmc_of_parse(mmc); if (ret) return ret; @@ -589,7 +587,7 @@ static int moxart_probe(struct platform_device *pdev) host = mmc_priv(mmc); host->mmc = mmc; host->base = reg_mmc; - host->reg_phys = res_mmc.start; + host->reg_phys = res_mmc->start; host->timeout = msecs_to_jiffies(1000); host->sysclk = clk_get_rate(clk); host->fifo_width = readl(host->base + REG_FEATURE) << 2; diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c index b2680cc054bd..01ea3adbdf3b 100644 --- a/drivers/mmc/host/mtk-sd.c +++ b/drivers/mmc/host/mtk-sd.c @@ -1805,7 +1805,7 @@ static irqreturn_t msdc_cmdq_irq(struct msdc_host *host, u32 intsts) cmd_err, dat_err, intsts); } - return cqhci_irq(mmc, 0, cmd_err, dat_err); + return cqhci_irq(mmc, cmd_err, dat_err); } static irqreturn_t msdc_irq(int irq, void *dev_id) diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 79df2fa89a3f..cf705b265e21 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c @@ -764,10 +764,8 @@ static int mvsd_probe(struct platform_device *pdev) mvsd_power_down(host); ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host); - if (ret) { - dev_err(&pdev->dev, "cannot assign irq %d\n", irq); + if (ret) goto out; - } timer_setup(&host->timer, mvsd_timeout_timer, 0); platform_set_drvdata(pdev, mmc); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 58c881f2725b..308a8905e196 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1764,7 +1764,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) struct mmc_host *mmc; struct omap_hsmmc_host *host = NULL; struct resource *res; - int ret, irq; + int ret, irq, wake_irq; const struct of_device_id *match; const struct omap_mmc_of_data *data; void __iomem *base; @@ -1792,6 +1792,11 @@ static int omap_hsmmc_probe(struct platform_device *pdev) if (irq < 0) return irq; + wake_irq = platform_get_irq_optional(pdev, 1); + if (wake_irq == -EPROBE_DEFER) + return wake_irq; + wake_irq = max(wake_irq, 0); + base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(base)) return PTR_ERR(base); @@ -1811,6 +1816,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) host->use_dma = 1; host->dma_ch = -1; host->irq = irq; + host->wake_irq = wake_irq; host->mapbase = res->start + pdata->reg_offset; host->base = base + pdata->reg_offset; host->power_mode = MMC_POWER_OFF; @@ -1820,9 +1826,6 @@ static int omap_hsmmc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); - if (pdev->dev.of_node) - host->wake_irq = irq_of_parse_and_map(pdev->dev.of_node, 1); - mmc->ops = &omap_hsmmc_ops; mmc->f_min = OMAP_MMC_MIN_CLOCK; @@ -1915,10 +1918,8 @@ static int omap_hsmmc_probe(struct platform_device *pdev) /* Request IRQ for MMC operations */ ret = devm_request_irq(&pdev->dev, host->irq, omap_hsmmc_irq, 0, mmc_hostname(mmc), host); - if (ret) { - dev_err(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n"); + if (ret) goto err_irq; - } ret = omap_hsmmc_reg_get(host); if (ret) diff --git a/drivers/mmc/host/owl-mmc.c b/drivers/mmc/host/owl-mmc.c index 349082d76a99..d5b8a110267b 100644 --- a/drivers/mmc/host/owl-mmc.c +++ b/drivers/mmc/host/owl-mmc.c @@ -635,11 +635,8 @@ static int owl_mmc_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, owl_host->irq, owl_irq_handler, 0, dev_name(&pdev->dev), owl_host); - if (ret) { - dev_err(&pdev->dev, "Failed to request irq %d\n", - owl_host->irq); + if (ret) goto err_release_channel; - } ret = mmc_add_host(mmc); if (ret) { diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index b5ea058ed467..f8427f071c00 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -43,8 +43,7 @@ #define NR_SG 1 #define CLKRT_OFF (~0) -#define mmc_has_26MHz() (cpu_is_pxa300() || cpu_is_pxa310() \ - || cpu_is_pxa935()) +#define mmc_has_26MHz() (cpu_is_pxa300() || cpu_is_pxa310()) struct pxamci_host { struct mmc_host *mmc; diff --git a/drivers/mmc/host/rtsx_usb_sdmmc.c b/drivers/mmc/host/rtsx_usb_sdmmc.c index 84674659a84d..bf37fab233cf 100644 --- a/drivers/mmc/host/rtsx_usb_sdmmc.c +++ b/drivers/mmc/host/rtsx_usb_sdmmc.c @@ -44,6 +44,7 @@ struct rtsx_usb_sdmmc { bool double_clk; bool host_removal; bool card_exist; + bool suppress_cd; bool initial_mode; bool ddr_mode; @@ -774,6 +775,7 @@ static int sdmmc_get_cd(struct mmc_host *mmc) struct rtsx_ucr *ucr = host->ucr; int err; u16 val; + bool cd; if (host->host_removal) return -ENOMEDIUM; @@ -791,8 +793,14 @@ static int sdmmc_get_cd(struct mmc_host *mmc) /* get OCP status */ host->ocp_stat = (val >> 4) & 0x03; + cd = val & SD_CD; - if (val & SD_CD) { + if (!cd) { + WRITE_ONCE(host->suppress_cd, false); + goto no_card; + } + + if (!READ_ONCE(host->suppress_cd)) { host->card_exist = true; return 1; } @@ -874,6 +882,8 @@ finish_detect_card: * detect card when fail to update card existence state and * speed up card removal when retry */ + if (!mmc->card && cmd->error == -ETIMEDOUT) + WRITE_ONCE(host->suppress_cd, true); sdmmc_get_cd(mmc); dev_dbg(sdmmc_dev(host), "cmd->error = %d\n", cmd->error); } @@ -1359,6 +1369,7 @@ static void rtsx_usb_init_host(struct rtsx_usb_sdmmc *host) host->power_mode = MMC_POWER_OFF; host->ocp_stat = 0; + host->suppress_cd = false; } static int rtsx_usb_sdmmc_drv_probe(struct platform_device *pdev) diff --git a/drivers/mmc/host/sdhci-brcmstb.c b/drivers/mmc/host/sdhci-brcmstb.c index 57e45951644e..1de2f05fd958 100644 --- a/drivers/mmc/host/sdhci-brcmstb.c +++ b/drivers/mmc/host/sdhci-brcmstb.c @@ -430,7 +430,7 @@ static u32 sdhci_brcmstb_cqhci_irq(struct sdhci_host *host, u32 intmask) if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) return intmask; - cqhci_irq(host->mmc, intmask, cmd_error, data_error); + cqhci_irq(host->mmc, cmd_error, data_error); return 0; } diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 18f4905c15b9..6ab59d3e346f 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1513,7 +1513,7 @@ static u32 esdhc_cqhci_irq(struct sdhci_host *host, u32 intmask) if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) return intmask; - cqhci_irq(host->mmc, intmask, cmd_error, data_error); + cqhci_irq(host->mmc, cmd_error, data_error); return 0; } diff --git a/drivers/mmc/host/sdhci-esdhc-mcf.c b/drivers/mmc/host/sdhci-esdhc-mcf.c index 375fce5639d7..6853521e8b2c 100644 --- a/drivers/mmc/host/sdhci-esdhc-mcf.c +++ b/drivers/mmc/host/sdhci-esdhc-mcf.c @@ -55,7 +55,7 @@ static inline void esdhc_clrset_be(struct sdhci_host *host, if (reg == SDHCI_HOST_CONTROL) val |= ESDHC_PROCTL_D3CD; - writel((readl(base) & ~mask) | val, base); + mcf_write32((mcf_read32(base) & ~mask) | val, base); } /* @@ -71,7 +71,7 @@ static void esdhc_mcf_writeb_be(struct sdhci_host *host, u8 val, int reg) if (reg == SDHCI_HOST_CONTROL) { u32 host_ctrl = ESDHC_DEFAULT_HOST_CONTROL; u8 dma_bits = (val & SDHCI_CTRL_DMA_MASK) >> 3; - u8 tmp = readb(host->ioaddr + SDHCI_HOST_CONTROL + 1); + u8 tmp = mcf_read8(host->ioaddr + SDHCI_HOST_CONTROL + 1); tmp &= ~0x03; tmp |= dma_bits; @@ -82,12 +82,12 @@ static void esdhc_mcf_writeb_be(struct sdhci_host *host, u8 val, int reg) */ host_ctrl |= val; host_ctrl |= (dma_bits << 8); - writel(host_ctrl, host->ioaddr + SDHCI_HOST_CONTROL); + mcf_write32(host_ctrl, host->ioaddr + SDHCI_HOST_CONTROL); return; } - writel((readl(base) & mask) | (val << shift), base); + mcf_write32((mcf_read32(base) & mask) | (val << shift), base); } static void esdhc_mcf_writew_be(struct sdhci_host *host, u16 val, int reg) @@ -110,24 +110,24 @@ static void esdhc_mcf_writew_be(struct sdhci_host *host, u16 val, int reg) * As for the fsl driver, * we have to set the mode in a single write here. */ - writel(val << 16 | mcf_data->aside, + mcf_write32(val << 16 | mcf_data->aside, host->ioaddr + SDHCI_TRANSFER_MODE); return; } - writel((readl(base) & mask) | (val << shift), base); + mcf_write32((mcf_read32(base) & mask) | (val << shift), base); } static void esdhc_mcf_writel_be(struct sdhci_host *host, u32 val, int reg) { - writel(val, host->ioaddr + reg); + mcf_write32(val, host->ioaddr + reg); } static u8 esdhc_mcf_readb_be(struct sdhci_host *host, int reg) { if (reg == SDHCI_HOST_CONTROL) { u8 __iomem *base = host->ioaddr + (reg & ~3); - u16 val = readw(base + 2); + u16 val = mcf_read16(base + 2); u8 dma_bits = (val >> 5) & SDHCI_CTRL_DMA_MASK; u8 host_ctrl = val & 0xff; @@ -137,7 +137,7 @@ static u8 esdhc_mcf_readb_be(struct sdhci_host *host, int reg) return host_ctrl; } - return readb(host->ioaddr + (reg ^ 0x3)); + return mcf_read8(host->ioaddr + (reg ^ 0x3)); } static u16 esdhc_mcf_readw_be(struct sdhci_host *host, int reg) @@ -149,14 +149,14 @@ static u16 esdhc_mcf_readw_be(struct sdhci_host *host, int reg) if (reg == SDHCI_HOST_VERSION) reg -= 2; - return readw(host->ioaddr + (reg ^ 0x2)); + return mcf_read16(host->ioaddr + (reg ^ 0x2)); } static u32 esdhc_mcf_readl_be(struct sdhci_host *host, int reg) { u32 val; - val = readl(host->ioaddr + reg); + val = mcf_read32(host->ioaddr + reg); /* * RM (25.3.9) sd pin clock must never exceed 25Mhz. @@ -245,7 +245,7 @@ static void esdhc_mcf_pltfm_set_clock(struct sdhci_host *host, * fvco = fsys * outdvi1 + 1 * fshdc = fvco / outdiv3 + 1 */ - temp = readl(pll_dr); + temp = mcf_read32(pll_dr); fsys = pltfm_host->clock; fvco = fsys * ((temp & 0x1f) + 1); fesdhc = fvco / (((temp >> 10) & 0x1f) + 1); diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 0882ce74e0c9..4aff965f0e2e 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -2165,7 +2165,7 @@ static u32 sdhci_msm_cqe_irq(struct sdhci_host *host, u32 intmask) if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) return intmask; - cqhci_irq(host->mmc, intmask, cmd_error, data_error); + cqhci_irq(host->mmc, cmd_error, data_error); return 0; } @@ -2864,10 +2864,8 @@ static int sdhci_msm_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(&pdev->dev, msm_host->pwr_irq, NULL, sdhci_msm_pwr_irq, IRQF_ONESHOT, dev_name(&pdev->dev), host); - if (ret) { - dev_err(&pdev->dev, "Request IRQ failed (%d)\n", ret); + if (ret) goto clk_disable; - } msm_host->mmc->caps |= MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_NEED_RSP_BUSY; diff --git a/drivers/mmc/host/sdhci-of-arasan.c b/drivers/mmc/host/sdhci-of-arasan.c index 785d3acb18c5..4ca73e7d799e 100644 --- a/drivers/mmc/host/sdhci-of-arasan.c +++ b/drivers/mmc/host/sdhci-of-arasan.c @@ -555,7 +555,7 @@ static u32 sdhci_arasan_cqhci_irq(struct sdhci_host *host, u32 intmask) if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) return intmask; - cqhci_irq(host->mmc, intmask, cmd_error, data_error); + cqhci_irq(host->mmc, cmd_error, data_error); return 0; } diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c index c688f3eaf468..1baa2379c9c3 100644 --- a/drivers/mmc/host/sdhci-of-dwcmshc.c +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c @@ -624,7 +624,7 @@ static u32 dwcmshc_cqe_irq_handler(struct sdhci_host *host, u32 intmask) if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) return intmask; - cqhci_irq(host->mmc, intmask, cmd_error, data_error); + cqhci_irq(host->mmc, cmd_error, data_error); return 0; } @@ -2013,6 +2013,7 @@ static void dwcmshc_bf3_hw_reset(struct sdhci_host *host) { struct arm_smccc_res res = { 0 }; + pr_debug("%s: resetting...\n", __func__); arm_smccc_smc(BLUEFIELD_SMC_SET_EMMC_RST_N, 0, 0, 0, 0, 0, 0, 0, &res); if (res.a0) diff --git a/drivers/mmc/host/sdhci-of-ma35d1.c b/drivers/mmc/host/sdhci-of-ma35d1.c index a3b676894838..2a826de97779 100644 --- a/drivers/mmc/host/sdhci-of-ma35d1.c +++ b/drivers/mmc/host/sdhci-of-ma35d1.c @@ -290,6 +290,7 @@ static const struct of_device_id sdhci_ma35_dt_ids[] = { { .compatible = "nuvoton,ma35d1-sdhci" }, {} }; +MODULE_DEVICE_TABLE(of, sdhci_ma35_dt_ids); static struct platform_driver sdhci_ma35_driver = { .driver = { diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index c347fac24515..b121d896a804 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -215,7 +215,7 @@ static u32 sdhci_cqhci_irq(struct sdhci_host *host, u32 intmask) if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) return intmask; - cqhci_irq(host->mmc, intmask, cmd_error, data_error); + cqhci_irq(host->mmc, cmd_error, data_error); return 0; } diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index 6e4084407662..b55618566d65 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -1760,7 +1760,7 @@ static u32 sdhci_gl9763e_cqhci_irq(struct sdhci_host *host, u32 intmask) if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) return intmask; - cqhci_irq(host->mmc, intmask, cmd_error, data_error); + cqhci_irq(host->mmc, cmd_error, data_error); return 0; } diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c index 820ce4dae58b..221e48b59f48 100644 --- a/drivers/mmc/host/sdhci-tegra.c +++ b/drivers/mmc/host/sdhci-tegra.c @@ -1280,7 +1280,7 @@ static u32 sdhci_tegra_cqhci_irq(struct sdhci_host *host, u32 intmask) if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) return intmask; - cqhci_irq(host->mmc, intmask, cmd_error, data_error); + cqhci_irq(host->mmc, cmd_error, data_error); return 0; } diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c index d235b0aecfdb..2a27db2f558b 100644 --- a/drivers/mmc/host/sdhci_am654.c +++ b/drivers/mmc/host/sdhci_am654.c @@ -462,7 +462,7 @@ static u32 sdhci_am654_cqhci_irq(struct sdhci_host *host, u32 intmask) if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error)) return intmask; - cqhci_irq(host->mmc, intmask, cmd_error, data_error); + cqhci_irq(host->mmc, cmd_error, data_error); return 0; } diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 9831956de1c8..7706d01b149e 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1505,18 +1505,14 @@ static int sh_mmcif_probe(struct platform_device *pdev) name = irq[1] < 0 ? dev_name(dev) : "sh_mmc:error"; ret = devm_request_threaded_irq(dev, irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, name, host); - if (ret) { - dev_err(dev, "request_irq error (%s)\n", name); + if (ret) goto err_clk; - } if (irq[1] >= 0) { ret = devm_request_threaded_irq(dev, irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); - if (ret) { - dev_err(dev, "request_irq error (sh_mmc:int)\n"); + if (ret) goto err_clk; - } } mutex_init(&host->thread_lock); diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 8c049f8355cd..4910d0f444ba 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -1153,10 +1153,16 @@ static int via_sd_probe(struct pci_dev *pcidev, ret = mmc_add_host(mmc); if (ret) - goto unmap; + goto free_irq; return 0; +free_irq: + writeb(0x0, sdhost->pcictrl_mmiobase + VIA_CRDR_PCIINTCTRL); + free_irq(pcidev->irq, sdhost); + cancel_work_sync(&sdhost->carddet_work); + /* carddet_work may re-enable the interrupt via via_reset_pcictrl(). */ + writeb(0x0, sdhost->pcictrl_mmiobase + VIA_CRDR_PCIINTCTRL); unmap: iounmap(sdhost->mmiobase); release: @@ -1199,6 +1205,10 @@ static void via_sd_remove(struct pci_dev *pcidev) free_irq(pcidev->irq, sdhost); + cancel_work_sync(&sdhost->carddet_work); + /* carddet_work may re-enable the interrupt via via_reset_pcictrl(). */ + writeb(0x0, sdhost->pcictrl_mmiobase + VIA_CRDR_PCIINTCTRL); + timer_delete_sync(&sdhost->timer); cancel_work_sync(&sdhost->finish_bh_work); diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index c33a0223ce7f..51706898239e 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c @@ -52,9 +52,9 @@ #ifdef CONFIG_PNP static const struct pnp_device_id pnp_dev_table[] = { - { "WEC0517", 0 }, - { "WEC0518", 0 }, - { "", 0 }, + { .id = "WEC0517" }, + { .id = "WEC0518" }, + { } }; MODULE_DEVICE_TABLE(pnp, pnp_dev_table); diff --git a/include/linux/rtsx_usb.h b/include/linux/rtsx_usb.h index 276b509c03e3..0fc5a74700a8 100644 --- a/include/linux/rtsx_usb.h +++ b/include/linux/rtsx_usb.h @@ -61,6 +61,9 @@ struct rtsx_ucr { struct timer_list sg_timer; struct mutex dev_mutex; + + u16 card_status_cache; + bool card_status_valid; }; /* buffer size */ diff --git a/include/linux/soc/pxa/cpu.h b/include/linux/soc/pxa/cpu.h index 5782450ee45c..38bacdae684f 100644 --- a/include/linux/soc/pxa/cpu.h +++ b/include/linux/soc/pxa/cpu.h @@ -46,14 +46,6 @@ * PXA31x A2 0x69056892 0x2E649013 * PXA32x B1 0x69056825 0x5E642013 * PXA32x B2 0x69056826 0x6E642013 - * - * PXA930 B0 0x69056835 0x5E643013 - * PXA930 B1 0x69056837 0x7E643013 - * PXA930 B2 0x69056838 0x8E643013 - * - * PXA935 A0 0x56056931 0x1E653013 - * PXA935 B0 0x56056936 0x6E653013 - * PXA935 B1 0x56056938 0x8E653013 */ #ifdef CONFIG_PXA25x #define __cpu_is_pxa210(id) \ @@ -126,26 +118,6 @@ #define __cpu_is_pxa320(id) (0) #endif -#ifdef CONFIG_CPU_PXA930 -#define __cpu_is_pxa930(id) \ - ({ \ - unsigned int _id = (id) >> 4 & 0xfff; \ - _id == 0x683; \ - }) -#else -#define __cpu_is_pxa930(id) (0) -#endif - -#ifdef CONFIG_CPU_PXA935 -#define __cpu_is_pxa935(id) \ - ({ \ - unsigned int _id = (id) >> 4 & 0xfff; \ - _id == 0x693; \ - }) -#else -#define __cpu_is_pxa935(id) (0) -#endif - #define cpu_is_pxa210() \ ({ \ __cpu_is_pxa210(read_cpuid_id()); \ @@ -186,18 +158,6 @@ __cpu_is_pxa320(read_cpuid_id()); \ }) -#define cpu_is_pxa930() \ - ({ \ - __cpu_is_pxa930(read_cpuid_id()); \ - }) - -#define cpu_is_pxa935() \ - ({ \ - __cpu_is_pxa935(read_cpuid_id()); \ - }) - - - /* * CPUID Core Generation Bit * <= 0x2 for pxa21x/pxa25x/pxa26x/pxa27x @@ -218,22 +178,11 @@ __cpu_is_pxa300(id) \ || __cpu_is_pxa310(id) \ || __cpu_is_pxa320(id) \ - || __cpu_is_pxa93x(id); \ }) #else #define __cpu_is_pxa3xx(id) (0) #endif -#if defined(CONFIG_CPU_PXA930) || defined(CONFIG_CPU_PXA935) -#define __cpu_is_pxa93x(id) \ - ({ \ - __cpu_is_pxa930(id) \ - || __cpu_is_pxa935(id); \ - }) -#else -#define __cpu_is_pxa93x(id) (0) -#endif - #define cpu_is_pxa2xx() \ ({ \ __cpu_is_pxa2xx(read_cpuid_id()); \ @@ -244,9 +193,4 @@ __cpu_is_pxa3xx(read_cpuid_id()); \ }) -#define cpu_is_pxa93x() \ - ({ \ - __cpu_is_pxa93x(read_cpuid_id()); \ - }) - #endif