summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/mmc/mtk-sd.txt75
-rw-r--r--Documentation/devicetree/bindings/mmc/mtk-sd.yaml176
-rw-r--r--drivers/memstick/core/memstick.c1
-rw-r--r--drivers/memstick/core/mspro_block.c2
-rw-r--r--drivers/memstick/host/jmb38x_ms.c2
-rw-r--r--drivers/memstick/host/tifm_ms.c2
-rw-r--r--drivers/misc/cardreader/rts5261.c61
-rw-r--r--drivers/misc/cardreader/rts5261.h39
-rw-r--r--drivers/misc/cardreader/rtsx_pcr.c5
-rw-r--r--drivers/mmc/core/core.c15
-rw-r--r--drivers/mmc/core/host.h6
-rw-r--r--drivers/mmc/core/sd_ops.c49
-rw-r--r--drivers/mmc/core/sd_ops.h1
-rw-r--r--drivers/mmc/host/Kconfig6
-rw-r--r--drivers/mmc/host/davinci_mmc.c2
-rw-r--r--drivers/mmc/host/dw_mmc.c17
-rw-r--r--drivers/mmc/host/meson-gx-mmc.c2
-rw-r--r--drivers/mmc/host/meson-mx-sdio.c5
-rw-r--r--drivers/mmc/host/moxart-mmc.c5
-rw-r--r--drivers/mmc/host/mtk-sd.c125
-rw-r--r--drivers/mmc/host/owl-mmc.c9
-rw-r--r--drivers/mmc/host/renesas_sdhi_core.c100
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c71
-rw-r--r--drivers/mmc/host/s3cmci.c2
-rw-r--r--drivers/mmc/host/sdhci-acpi.c38
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c91
-rw-r--r--drivers/mmc/host/sdhci-msm.c13
-rw-r--r--drivers/mmc/host/sdhci-pic32.c11
-rw-r--r--drivers/mmc/host/sdhci-sprd.c2
-rw-r--r--drivers/mmc/host/sdhci-st.c2
-rw-r--r--drivers/mmc/host/sdhci-tegra.c2
-rw-r--r--drivers/mmc/host/sunxi-mmc.c3
-rw-r--r--drivers/mmc/host/tmio_mmc.c3
-rw-r--r--drivers/mmc/host/tmio_mmc.h1
-rw-r--r--drivers/mmc/host/tmio_mmc_core.c4
-rw-r--r--include/linux/mmc/host.h7
-rw-r--r--include/linux/rtsx_pci.h30
37 files changed, 638 insertions, 347 deletions
diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.txt b/Documentation/devicetree/bindings/mmc/mtk-sd.txt
deleted file mode 100644
index 26a8f320a156..000000000000
--- a/Documentation/devicetree/bindings/mmc/mtk-sd.txt
+++ /dev/null
@@ -1,75 +0,0 @@
-* MTK MMC controller
-
-The MTK MSDC can act as a MMC controller
-to support MMC, SD, and SDIO types of memory cards.
-
-This file documents differences between the core properties in mmc.txt
-and the properties used by the msdc driver.
-
-Required properties:
-- compatible: value should be either of the following.
- "mediatek,mt8135-mmc": for mmc host ip compatible with mt8135
- "mediatek,mt8173-mmc": for mmc host ip compatible with mt8173
- "mediatek,mt8183-mmc": for mmc host ip compatible with mt8183
- "mediatek,mt8516-mmc": for mmc host ip compatible with mt8516
- "mediatek,mt6779-mmc": for mmc host ip compatible with mt6779
- "mediatek,mt2701-mmc": for mmc host ip compatible with mt2701
- "mediatek,mt2712-mmc": for mmc host ip compatible with mt2712
- "mediatek,mt7622-mmc": for MT7622 SoC
- "mediatek,mt7623-mmc", "mediatek,mt2701-mmc": for MT7623 SoC
- "mediatek,mt7620-mmc", for MT7621 SoC (and others)
-
-- reg: physical base address of the controller and length
-- interrupts: Should contain MSDC interrupt number
-- clocks: Should contain phandle for the clock feeding the MMC controller
-- clock-names: Should contain the following:
- "source" - source clock (required)
- "hclk" - HCLK which used for host (required)
- "source_cg" - independent source clock gate (required for MT2712)
- "bus_clk" - bus clock used for internal register access (required for MT2712 MSDC0/3)
-- pinctrl-names: should be "default", "state_uhs"
-- pinctrl-0: should contain default/high speed pin ctrl
-- pinctrl-1: should contain uhs mode pin ctrl
-- vmmc-supply: power to the Core
-- vqmmc-supply: power to the IO
-
-Optional properties:
-- assigned-clocks: PLL of the source clock
-- assigned-clock-parents: parent of source clock, used for HS400 mode to get 400Mhz source clock
-- hs400-ds-delay: HS400 DS delay setting
-- mediatek,hs200-cmd-int-delay: HS200 command internal delay setting.
- This field has total 32 stages.
- The value is an integer from 0 to 31.
-- mediatek,hs400-cmd-int-delay: HS400 command internal delay setting
- This field has total 32 stages.
- The value is an integer from 0 to 31.
-- mediatek,hs400-cmd-resp-sel-rising: HS400 command response sample selection
- If present,HS400 command responses are sampled on rising edges.
- If not present,HS400 command responses are sampled on falling edges.
-- mediatek,latch-ck: Some SoCs do not support enhance_rx, need set correct latch-ck to avoid data crc
- error caused by stop clock(fifo full)
- Valid range = [0:0x7]. if not present, default value is 0.
- applied to compatible "mediatek,mt2701-mmc".
-- resets: Phandle and reset specifier pair to softreset line of MSDC IP.
-- reset-names: Should be "hrst".
-
-Examples:
-mmc0: mmc@11230000 {
- compatible = "mediatek,mt8173-mmc", "mediatek,mt8135-mmc";
- reg = <0 0x11230000 0 0x108>;
- interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_LOW>;
- vmmc-supply = <&mt6397_vemc_3v3_reg>;
- vqmmc-supply = <&mt6397_vio18_reg>;
- clocks = <&pericfg CLK_PERI_MSDC30_0>,
- <&topckgen CLK_TOP_MSDC50_0_H_SEL>;
- clock-names = "source", "hclk";
- pinctrl-names = "default", "state_uhs";
- pinctrl-0 = <&mmc0_pins_default>;
- pinctrl-1 = <&mmc0_pins_uhs>;
- assigned-clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>;
- assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL_D2>;
- hs400-ds-delay = <0x14015>;
- mediatek,hs200-cmd-int-delay = <26>;
- mediatek,hs400-cmd-int-delay = <14>;
- mediatek,hs400-cmd-resp-sel-rising;
-};
diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
new file mode 100644
index 000000000000..030e3fdce492
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
@@ -0,0 +1,176 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/mtk-sd.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MTK MSDC Storage Host Controller Binding
+
+maintainers:
+ - Chaotian Jing <chaotian.jing@mediatek.com>
+ - Wenbin Mei <wenbin.mei@mediatek.com>
+
+allOf:
+ - $ref: mmc-controller.yaml#
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - mediatek,mt2701-mmc
+ - mediatek,mt2712-mmc
+ - mediatek,mt6779-mmc
+ - mediatek,mt7620-mmc
+ - mediatek,mt7622-mmc
+ - mediatek,mt8135-mmc
+ - mediatek,mt8173-mmc
+ - mediatek,mt8183-mmc
+ - mediatek,mt8516-mmc
+ - items:
+ - const: mediatek,mt7623-mmc
+ - const: mediatek,mt2701-mmc
+ - items:
+ - const: mediatek,mt8192-mmc
+ - const: mediatek,mt8183-mmc
+
+ clocks:
+ description:
+ Should contain phandle for the clock feeding the MMC controller.
+ minItems: 2
+ maxItems: 8
+ items:
+ - description: source clock (required).
+ - description: HCLK which used for host (required).
+ - description: independent source clock gate (required for MT2712).
+ - description: bus clock used for internal register access (required for MT2712 MSDC0/3).
+ - description: msdc subsys clock gate (required for MT8192).
+ - description: peripheral bus clock gate (required for MT8192).
+ - description: AXI bus clock gate (required for MT8192).
+ - description: AHB bus clock gate (required for MT8192).
+
+ clock-names:
+ minItems: 2
+ maxItems: 8
+ items:
+ - const: source
+ - const: hclk
+ - const: source_cg
+ - const: bus_clk
+ - const: sys_cg
+ - const: pclk_cg
+ - const: axi_cg
+ - const: ahb_cg
+
+ pinctrl-names:
+ items:
+ - const: default
+ - const: state_uhs
+
+ pinctrl-0:
+ description:
+ should contain default/high speed pin ctrl.
+ maxItems: 1
+
+ pinctrl-1:
+ description:
+ should contain uhs mode pin ctrl.
+ maxItems: 1
+
+ assigned-clocks:
+ description:
+ PLL of the source clock.
+ maxItems: 1
+
+ assigned-clock-parents:
+ description:
+ parent of source clock, used for HS400 mode to get 400Mhz source clock.
+ maxItems: 1
+
+ hs400-ds-delay:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ HS400 DS delay setting.
+ minimum: 0
+ maximum: 0xffffffff
+
+ mediatek,hs200-cmd-int-delay:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ HS200 command internal delay setting.
+ This field has total 32 stages.
+ The value is an integer from 0 to 31.
+ minimum: 0
+ maximum: 31
+
+ mediatek,hs400-cmd-int-delay:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ HS400 command internal delay setting.
+ This field has total 32 stages.
+ The value is an integer from 0 to 31.
+ minimum: 0
+ maximum: 31
+
+ mediatek,hs400-cmd-resp-sel-rising:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ HS400 command response sample selection.
+ If present, HS400 command responses are sampled on rising edges.
+ If not present, HS400 command responses are sampled on falling edges.
+
+ mediatek,latch-ck:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Some SoCs do not support enhance_rx, need set correct latch-ck to avoid
+ data crc error caused by stop clock(fifo full) Valid range = [0:0x7].
+ if not present, default value is 0.
+ applied to compatible "mediatek,mt2701-mmc".
+ minimum: 0
+ maximum: 7
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ const: hrst
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - pinctrl-names
+ - pinctrl-0
+ - pinctrl-1
+ - vmmc-supply
+ - vqmmc-supply
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/mt8173-clk.h>
+ mmc0: mmc@11230000 {
+ compatible = "mediatek,mt8173-mmc";
+ reg = <0x11230000 0x1000>;
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_LOW>;
+ vmmc-supply = <&mt6397_vemc_3v3_reg>;
+ vqmmc-supply = <&mt6397_vio18_reg>;
+ clocks = <&pericfg CLK_PERI_MSDC30_0>,
+ <&topckgen CLK_TOP_MSDC50_0_H_SEL>;
+ clock-names = "source", "hclk";
+ pinctrl-names = "default", "state_uhs";
+ pinctrl-0 = <&mmc0_pins_default>;
+ pinctrl-1 = <&mmc0_pins_uhs>;
+ assigned-clocks = <&topckgen CLK_TOP_MSDC50_0_SEL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_MSDCPLL_D2>;
+ hs400-ds-delay = <0x14015>;
+ mediatek,hs200-cmd-int-delay = <26>;
+ mediatek,hs400-cmd-int-delay = <14>;
+ mediatek,hs400-cmd-resp-sel-rising;
+ };
+
+...
diff --git a/drivers/memstick/core/memstick.c b/drivers/memstick/core/memstick.c
index ef03d6fafc5c..12bc3f5a6cbb 100644
--- a/drivers/memstick/core/memstick.c
+++ b/drivers/memstick/core/memstick.c
@@ -468,7 +468,6 @@ static void memstick_check(struct work_struct *work)
host->card = card;
if (device_register(&card->dev)) {
put_device(&card->dev);
- kfree(host->card);
host->card = NULL;
}
} else
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c
index cd6b8d4f2335..afb892e7ffc6 100644
--- a/drivers/memstick/core/mspro_block.c
+++ b/drivers/memstick/core/mspro_block.c
@@ -276,7 +276,7 @@ static const char *mspro_block_attr_name(unsigned char tag)
return "attr_devinfo";
default:
return NULL;
- };
+ }
}
typedef ssize_t (*sysfs_show_t)(struct device *dev,
diff --git a/drivers/memstick/host/jmb38x_ms.c b/drivers/memstick/host/jmb38x_ms.c
index e83c3ada9389..f9a93b0565e1 100644
--- a/drivers/memstick/host/jmb38x_ms.c
+++ b/drivers/memstick/host/jmb38x_ms.c
@@ -748,7 +748,7 @@ static int jmb38x_ms_set_param(struct memstick_host *msh,
clock_delay);
host->ifmode = value;
break;
- };
+ }
return 0;
}
diff --git a/drivers/memstick/host/tifm_ms.c b/drivers/memstick/host/tifm_ms.c
index 786e46798da2..57145374f6ac 100644
--- a/drivers/memstick/host/tifm_ms.c
+++ b/drivers/memstick/host/tifm_ms.c
@@ -528,7 +528,7 @@ static int tifm_ms_set_param(struct memstick_host *msh,
} else
return -EINVAL;
break;
- };
+ }
return 0;
}
diff --git a/drivers/misc/cardreader/rts5261.c b/drivers/misc/cardreader/rts5261.c
index 471961487ff8..6c64dade8e1a 100644
--- a/drivers/misc/cardreader/rts5261.c
+++ b/drivers/misc/cardreader/rts5261.c
@@ -26,16 +26,16 @@ static u8 rts5261_get_ic_version(struct rtsx_pcr *pcr)
static void rts5261_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
{
u8 driving_3v3[4][3] = {
- {0x13, 0x13, 0x13},
{0x96, 0x96, 0x96},
- {0x7F, 0x7F, 0x7F},
{0x96, 0x96, 0x96},
+ {0x7F, 0x7F, 0x7F},
+ {0x13, 0x13, 0x13},
};
u8 driving_1v8[4][3] = {
- {0x99, 0x99, 0x99},
+ {0xB3, 0xB3, 0xB3},
{0x3A, 0x3A, 0x3A},
{0xE6, 0xE6, 0xE6},
- {0xB3, 0xB3, 0xB3},
+ {0x99, 0x99, 0x99},
};
u8 (*driving)[3], drive_sel;
@@ -67,12 +67,17 @@ static void rtsx5261_fetch_vendor_settings(struct rtsx_pcr *pcr)
pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
if (!rts5261_vendor_setting_valid(reg)) {
+ /* Not support MMC default */
+ pcr->extra_caps |= EXTRA_CAPS_NO_MMC;
pcr_dbg(pcr, "skip fetch vendor setting\n");
return;
}
- pcr->card_drive_sel &= 0x3F;
- pcr->card_drive_sel |= rts5261_reg_to_card_drive_sel(reg);
+ if (!rts5261_reg_check_mmc_support(reg))
+ pcr->extra_caps |= EXTRA_CAPS_NO_MMC;
+
+ /* TO do: need to add rtd3 function */
+ pcr->rtd3_en = rts5261_reg_to_rtd3(reg);
if (rts5261_reg_check_reverse_socket(reg))
pcr->flags |= PCR_REVERSE_SOCKET;
@@ -171,6 +176,8 @@ static int rts5261_card_power_on(struct rtsx_pcr *pcr, int card)
if (option->ocp_en)
rtsx_pci_enable_ocp(pcr);
+ rtsx_pci_write_register(pcr, REG_CRC_DUMMY_0,
+ CFG_SD_POW_AUTO_PD, CFG_SD_POW_AUTO_PD);
rtsx_pci_write_register(pcr, RTS5261_LDO1_CFG1,
RTS5261_LDO1_TUNE_MASK, RTS5261_LDO1_33);
@@ -272,6 +279,9 @@ static void rts5261_enable_ocp(struct rtsx_pcr *pcr)
u8 val = 0;
val = SD_OCP_INT_EN | SD_DETECT_EN;
+ rtsx_pci_write_register(pcr, RTS5261_LDO1_CFG0,
+ RTS5261_LDO1_OCP_EN | RTS5261_LDO1_OCP_LMT_EN,
+ RTS5261_LDO1_OCP_EN | RTS5261_LDO1_OCP_LMT_EN);
rtsx_pci_write_register(pcr, REG_OCPCTL, 0xFF, val);
}
@@ -295,6 +305,8 @@ static int rts5261_card_power_off(struct rtsx_pcr *pcr, int card)
err = rtsx_pci_write_register(pcr, RTS5261_LDO1233318_POW_CTL,
RTS5261_LDO_POWERON_MASK, 0);
+ rtsx_pci_write_register(pcr, REG_CRC_DUMMY_0,
+ CFG_SD_POW_AUTO_PD, 0);
if (pcr->option.ocp_en)
rtsx_pci_disable_ocp(pcr);
@@ -340,7 +352,7 @@ static void rts5261_clear_ocpstat(struct rtsx_pcr *pcr)
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, val);
- udelay(10);
+ udelay(1000);
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0);
}
@@ -353,9 +365,9 @@ static void rts5261_process_ocp(struct rtsx_pcr *pcr)
rtsx_pci_get_ocpstat(pcr, &pcr->ocp_stat);
if (pcr->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
+ rts5261_clear_ocpstat(pcr);
rts5261_card_power_off(pcr, RTSX_SD_CARD);
rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0);
- rts5261_clear_ocpstat(pcr);
pcr->ocp_stat = 0;
}
@@ -467,6 +479,7 @@ static void rts5261_init_from_cfg(struct rtsx_pcr *pcr)
static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
{
struct rtsx_cr_option *option = &pcr->option;
+ u32 val;
rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG1,
CD_RESUME_EN_MASK, CD_RESUME_EN_MASK);
@@ -481,6 +494,10 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
AUX_CLK_ACTIVE_SEL_MASK, MAC_CKSW_DONE);
rtsx_pci_write_register(pcr, L1SUB_CONFIG3, 0xFF, 0);
+ if (is_version_higher_than(pcr, PID_5261, IC_VER_B)) {
+ val = rtsx_pci_readl(pcr, RTSX_DUM_REG);
+ rtsx_pci_writel(pcr, RTSX_DUM_REG, val | 0x1);
+ }
rtsx_pci_write_register(pcr, RTS5261_AUTOLOAD_CFG4,
RTS5261_AUX_CLK_16M_EN, 0);
@@ -502,6 +519,11 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
/* Configure driving */
rts5261_fill_driving(pcr, OUTPUT_3V3);
+ if (pcr->flags & PCR_REVERSE_SOCKET)
+ rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x30);
+ else
+ rtsx_pci_write_register(pcr, PETXCFG, 0x30, 0x00);
+
/*
* If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
* to drive low, and we forcibly request clock.
@@ -513,6 +535,7 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
rtsx_pci_write_register(pcr, PETXCFG,
FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
+ rtsx_pci_write_register(pcr, PWD_SUSPEND_EN, 0xFF, 0xFB);
rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x00);
rtsx_pci_write_register(pcr, RTS5261_REG_PME_FORCE_CTL,
FORCE_PM_CONTROL | FORCE_PM_VALUE, FORCE_PM_CONTROL);
@@ -526,22 +549,30 @@ static int rts5261_extra_init_hw(struct rtsx_pcr *pcr)
static void rts5261_enable_aspm(struct rtsx_pcr *pcr, bool enable)
{
+ u8 val = FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1;
+ u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1;
+
if (pcr->aspm_enabled == enable)
return;
+ val |= (pcr->aspm_en & 0x02);
+ rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val);
pcie_capability_clear_and_set_word(pcr->pci, PCI_EXP_LNKCTL,
PCI_EXP_LNKCTL_ASPMC, pcr->aspm_en);
pcr->aspm_enabled = enable;
-
}
static void rts5261_disable_aspm(struct rtsx_pcr *pcr, bool enable)
{
+ u8 val = FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1;
+ u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0 | FORCE_ASPM_CTL1;
+
if (pcr->aspm_enabled == enable)
return;
pcie_capability_clear_and_set_word(pcr->pci, PCI_EXP_LNKCTL,
PCI_EXP_LNKCTL_ASPMC, 0);
+ rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val);
rtsx_pci_write_register(pcr, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
udelay(10);
pcr->aspm_enabled = enable;
@@ -618,7 +649,7 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
if (initial_mode) {
/* We use 250k(around) here, in initial stage */
- if (is_version(pcr, PID_5261, IC_VER_D)) {
+ if (is_version_higher_than(pcr, PID_5261, IC_VER_C)) {
clk_divider = SD_CLK_DIVIDE_256;
card_clock = 60000000;
} else {
@@ -669,7 +700,7 @@ int rts5261_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
div++;
}
- n = (n / 2);
+ n = (n / 2) - 1;
pcr_dbg(pcr, "n = %d, div = %d\n", n, div);
ssc_depth = depth[ssc_depth];
@@ -738,15 +769,19 @@ void rts5261_init_params(struct rtsx_pcr *pcr)
{
struct rtsx_cr_option *option = &pcr->option;
struct rtsx_hw_param *hw_param = &pcr->hw_param;
+ u8 val;
pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
+ rtsx_pci_read_register(pcr, RTS5261_FW_STATUS, &val);
+ if (!(val & RTS5261_EXPRESS_LINK_FAIL_MASK))
+ pcr->extra_caps |= EXTRA_CAPS_SD_EXPRESS;
pcr->num_slots = 1;
pcr->ops = &rts5261_pcr_ops;
pcr->flags = 0;
pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
- pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
- pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
+ pcr->sd30_drive_sel_1v8 = 0x00;
+ pcr->sd30_drive_sel_3v3 = 0x00;
pcr->aspm_en = ASPM_L1_EN;
pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 11);
pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
diff --git a/drivers/misc/cardreader/rts5261.h b/drivers/misc/cardreader/rts5261.h
index ebfdd236a553..2344c560a637 100644
--- a/drivers/misc/cardreader/rts5261.h
+++ b/drivers/misc/cardreader/rts5261.h
@@ -12,12 +12,13 @@
/*New add*/
#define rts5261_vendor_setting_valid(reg) ((reg) & 0x010000)
-#define rts5261_reg_to_aspm(reg) (((reg) >> 28) ^ 0x03)
+#define rts5261_reg_to_aspm(reg) \
+ (((~(reg) >> 28) & 0x02) | (((reg) >> 28) & 0x01))
#define rts5261_reg_check_reverse_socket(reg) ((reg) & 0x04)
-#define rts5261_reg_to_card_drive_sel(reg) ((((reg) >> 6) & 0x01) << 6)
-#define rts5261_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 22) ^ 0x03)
-#define rts5261_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 16) ^ 0x03)
-
+#define rts5261_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 22) & 0x03)
+#define rts5261_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 16) & 0x03)
+#define rts5261_reg_to_rtd3(reg) ((reg) & 0x08)
+#define rts5261_reg_check_mmc_support(reg) ((reg) & 0x10)
#define RTS5261_AUTOLOAD_CFG0 0xFF7B
#define RTS5261_AUTOLOAD_CFG1 0xFF7C
@@ -60,28 +61,6 @@
/* DMACTL 0xFE2C */
#define RTS5261_DMA_PACK_SIZE_MASK 0xF0
-/* FW config info register */
-#define RTS5261_FW_CFG_INFO0 0xFF50
-#define RTS5261_FW_EXPRESS_TEST_MASK (0x01<<0)
-#define RTS5261_FW_EA_MODE_MASK (0x01<<5)
-
-/* FW config register */
-#define RTS5261_FW_CFG0 0xFF54
-#define RTS5261_FW_ENTER_EXPRESS (0x01<<0)
-
-#define RTS5261_FW_CFG1 0xFF55
-#define RTS5261_SYS_CLK_SEL_MCU_CLK (0x01<<7)
-#define RTS5261_CRC_CLK_SEL_MCU_CLK (0x01<<6)
-#define RTS5261_FAKE_MCU_CLOCK_GATING (0x01<<5)
-/*MCU_bus_mode_sel: 0=real 8051 1=fake mcu*/
-#define RTS5261_MCU_BUS_SEL_MASK (0x01<<4)
-/*MCU_clock_sel:VerA 00=aux16M 01=aux400K 1x=REFCLK100M*/
-/*MCU_clock_sel:VerB 00=aux400K 01=aux16M 10=REFCLK100M*/
-#define RTS5261_MCU_CLOCK_SEL_MASK (0x03<<2)
-#define RTS5261_MCU_CLOCK_SEL_16M (0x01<<2)
-#define RTS5261_MCU_CLOCK_GATING (0x01<<1)
-#define RTS5261_DRIVER_ENABLE_FW (0x01<<0)
-
/* FW status register */
#define RTS5261_FW_STATUS 0xFF56
#define RTS5261_EXPRESS_LINK_FAIL_MASK (0x01<<7)
@@ -121,12 +100,6 @@
#define RTS5261_DV3318_19 (0x04<<4)
#define RTS5261_DV3318_33 (0x07<<4)
-#define RTS5261_LDO1_CFG0 0xFF72
-#define RTS5261_LDO1_OCP_THD_MASK (0x07<<5)
-#define RTS5261_LDO1_OCP_EN (0x01<<4)
-#define RTS5261_LDO1_OCP_LMT_THD_MASK (0x03<<2)
-#define RTS5261_LDO1_OCP_LMT_EN (0x01<<1)
-
/* CRD6603-433 190319 request changed */
#define RTS5261_LDO1_OCP_THD_740 (0x00<<5)
#define RTS5261_LDO1_OCP_THD_800 (0x01<<5)
diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c
index 5d15607027e9..56f63fa7f646 100644
--- a/drivers/misc/cardreader/rtsx_pcr.c
+++ b/drivers/misc/cardreader/rtsx_pcr.c
@@ -990,6 +990,11 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
} else {
pcr->card_removed |= SD_EXIST;
pcr->card_inserted &= ~SD_EXIST;
+ if (PCI_PID(pcr) == PID_5261) {
+ rtsx_pci_write_register(pcr, RTS5261_FW_STATUS,
+ RTS5261_EXPRESS_LINK_FAIL_MASK, 0);
+ pcr->extra_caps |= EXTRA_CAPS_SD_EXPRESS;
+ }
}
pcr->dma_error_count = 0;
}
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index d42037f0f10d..19f1ee57fb34 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2147,8 +2147,12 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
mmc_go_idle(host);
- if (!(host->caps2 & MMC_CAP2_NO_SD))
- mmc_send_if_cond(host, host->ocr_avail);
+ if (!(host->caps2 & MMC_CAP2_NO_SD)) {
+ if (mmc_send_if_cond_pcie(host, host->ocr_avail))
+ goto out;
+ if (mmc_card_sd_express(host))
+ return 0;
+ }
/* Order's important: probe SDIO, then SD, then MMC */
if (!(host->caps2 & MMC_CAP2_NO_SDIO))
@@ -2163,6 +2167,7 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
if (!mmc_attach_mmc(host))
return 0;
+out:
mmc_power_off(host);
return -EIO;
}
@@ -2290,6 +2295,12 @@ void mmc_rescan(struct work_struct *work)
goto out;
}
+ /* If an SD express card is present, then leave it as is. */
+ if (mmc_card_sd_express(host)) {
+ mmc_release_host(host);
+ goto out;
+ }
+
for (i = 0; i < ARRAY_SIZE(freqs); i++) {
unsigned int freq = freqs[i];
if (freq > host->f_max) {
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h
index 5e3b9534ffb2..ba407617ed23 100644
--- a/drivers/mmc/core/host.h
+++ b/drivers/mmc/core/host.h
@@ -77,5 +77,11 @@ static inline bool mmc_card_hs400es(struct mmc_card *card)
return card->host->ios.enhanced_strobe;
}
+static inline bool mmc_card_sd_express(struct mmc_host *host)
+{
+ return host->ios.timing == MMC_TIMING_SD_EXP ||
+ host->ios.timing == MMC_TIMING_SD_EXP_1_2V;
+}
+
#endif
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c
index 22bf528294b9..d61ff811218c 100644
--- a/drivers/mmc/core/sd_ops.c
+++ b/drivers/mmc/core/sd_ops.c
@@ -158,7 +158,8 @@ int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr)
return err;
}
-int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
+static int __mmc_send_if_cond(struct mmc_host *host, u32 ocr, u8 pcie_bits,
+ u32 *resp)
{
struct mmc_command cmd = {};
int err;
@@ -171,7 +172,7 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
* SD 1.0 cards.
*/
cmd.opcode = SD_SEND_IF_COND;
- cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | test_pattern;
+ cmd.arg = ((ocr & 0xFF8000) != 0) << 8 | pcie_bits << 8 | test_pattern;
cmd.flags = MMC_RSP_SPI_R7 | MMC_RSP_R7 | MMC_CMD_BCR;
err = mmc_wait_for_cmd(host, &cmd, 0);
@@ -186,6 +187,50 @@ int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
if (result_pattern != test_pattern)
return -EIO;
+ if (resp)
+ *resp = cmd.resp[0];
+
+ return 0;
+}
+
+int mmc_send_if_cond(struct mmc_host *host, u32 ocr)
+{
+ return __mmc_send_if_cond(host, ocr, 0, NULL);
+}
+
+int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr)
+{
+ u32 resp = 0;
+ u8 pcie_bits = 0;
+ int ret;
+
+ if (host->caps2 & MMC_CAP2_SD_EXP) {
+ /* Probe card for SD express support via PCIe. */
+ pcie_bits = 0x10;
+ if (host->caps2 & MMC_CAP2_SD_EXP_1_2V)
+ /* Probe also for 1.2V support. */
+ pcie_bits = 0x30;
+ }
+
+ ret = __mmc_send_if_cond(host, ocr, pcie_bits, &resp);
+ if (ret)
+ return 0;
+
+ /* Continue with the SD express init, if the card supports it. */
+ resp &= 0x3000;
+ if (pcie_bits && resp) {
+ if (resp == 0x3000)
+ host->ios.timing = MMC_TIMING_SD_EXP_1_2V;
+ else
+ host->ios.timing = MMC_TIMING_SD_EXP;
+
+ /*
+ * According to the spec the clock shall also be gated, but
+ * let's leave this to the host driver for more flexibility.
+ */
+ return host->ops->init_sd_express(host, &host->ios);
+ }
+
return 0;
}
diff --git a/drivers/mmc/core/sd_ops.h b/drivers/mmc/core/sd_ops.h
index 2194cabfcfc5..3ba7b3cf4652 100644
--- a/drivers/mmc/core/sd_ops.h
+++ b/drivers/mmc/core/sd_ops.h
@@ -16,6 +16,7 @@ struct mmc_host;
int mmc_app_set_bus_width(struct mmc_card *card, int width);
int mmc_send_app_op_cond(struct mmc_host *host, u32 ocr, u32 *rocr);
int mmc_send_if_cond(struct mmc_host *host, u32 ocr);
+int mmc_send_if_cond_pcie(struct mmc_host *host, u32 ocr);
int mmc_send_relative_addr(struct mmc_host *host, unsigned int *rca);
int mmc_app_send_scr(struct mmc_card *card);