diff options
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); |