Hi, Adrian On Wed, May 31, 2023 at 3:15 PM Adrian Hunter <adrian.hunter@xxxxxxxxx> wrote: > > On 30/05/23 12:53, Victor Shih wrote: > > From: Victor Shih <victor.shih@xxxxxxxxxxxxxxxxxxx> > > > > Add support SD Express card for GL9767. The workflow of the > > SD Express card in GL9767 is as below. > > 1. GL9767 operates in SD mode and set MMC_CAP2_SD_EXP flag. > > 2. If card is inserted, Host send CMD8 to ask the capabilities > > of the card. > > 3. If the card has PCIe capability, then init_sd_express() > > will be invoked. > > 4. If the card has been put in write protect state then the > > SD features supported by SD mode but not supported by > > PCIe mode, therefore GL9767 switch to SD mode. > > 5. If the card has not been put in write protect state then > > GL9767 switch from SD mode to PCIe/NVMe mode and mmc driver > > handover control to NVMe driver. > > 6. If card is removed, GL9767 will return to SD mode. > > > > Signed-off-by: Ben Chuang <ben.chuang@xxxxxxxxxxxxxxxxxxx> > > Signed-off-by: Victor Shih <victor.shih@xxxxxxxxxxxxxxxxxxx> > > Acked-by: Adrian Hunter <adrian.hunter@xxxxxxxxx> > Excuse me, I will adjust the order of definitions and modify the if-else condition and content in gl9767_init_sd_express() function, please help to review it once, thank you. > > --- > > drivers/mmc/host/sdhci-pci-gli.c | 105 +++++++++++++++++++++++++++++++ > > 1 file changed, 105 insertions(+) > > > > diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c > > index 178253a7e86f..c7fa92fdadcd 100644 > > --- a/drivers/mmc/host/sdhci-pci-gli.c > > +++ b/drivers/mmc/host/sdhci-pci-gli.c > > @@ -164,6 +164,10 @@ > > #define PCIE_GLI_9767_CFG 0x8A0 > > #define PCIE_GLI_9767_CFG_LOW_PWR_OFF BIT(12) > > > > +#define PCIE_GLI_9767_COMBO_MUX_CTL 0x8C8 > > +#define PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN BIT(6) > > +#define PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN BIT(10) > > + > > #define PCIE_GLI_9767_PWR_MACRO_CTL 0x8D0 > > #define PCIE_GLI_9767_PWR_MACRO_CTL_LOW_VOLTAGE GENMASK(3, 0) > > #define PCIE_GLI_9767_PWR_MACRO_CTL_LD0_LOW_OUTPUT_VOLTAGE GENMASK(15, 12) > > @@ -181,6 +185,26 @@ > > #define PCIE_GLI_9767_SCR_CORE_PWR_D3_OFF BIT(21) > > #define PCIE_GLI_9767_SCR_CFG_RST_DATA_LINK_DOWN BIT(30) > > > > +#define PCIE_GLI_9767_SDHC_CAP 0x91C > > +#define PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT BIT(5) > > + > > +#define PCIE_GLI_9767_SD_EXPRESS_CTL 0x940 > > +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE BIT(0) > > +#define PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE BIT(1) > > + > > +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL 0x944 > > +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME GENMASK(23, 16) > > +#define PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE 0x64 > > + > > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2 0x950 > > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE BIT(0) > > + > > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2 0x954 > > +#define PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN BIT(0) > > + > > +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2 0x958 > > +#define PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN BIT(0) > > + > > #define PCIE_GLI_9767_SD_PLL_CTL 0x938 > > #define PCIE_GLI_9767_SD_PLL_CTL_PLL_LDIV GENMASK(9, 0) > > #define PCIE_GLI_9767_SD_PLL_CTL_PLL_PDIV GENMASK(15, 12) > > @@ -935,6 +959,85 @@ static void sdhci_gl9767_reset(struct sdhci_host *host, u8 mask) > > gli_set_9767(host); > > } > > > > +static int gl9767_init_sd_express(struct mmc_host *mmc, struct mmc_ios *ios) > > +{ > > + struct sdhci_host *host = mmc_priv(mmc); > > + struct sdhci_pci_slot *slot = sdhci_priv(host); > > + struct pci_dev *pdev; > > + u32 value; > > + int i; > > + > > + pdev = slot->chip->pdev; > > + > > + if (mmc->ops->get_ro(mmc)) { > > + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V); > > + return 0; > > + } > > + > > + gl9767_vhs_write(pdev); > > + > > + pci_read_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, &value); > > + value &= ~(PCIE_GLI_9767_COMBO_MUX_CTL_RST_EN | PCIE_GLI_9767_COMBO_MUX_CTL_WAIT_PERST_EN); > > + pci_write_config_dword(pdev, PCIE_GLI_9767_COMBO_MUX_CTL, value); > > + > > + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, &value); > > + value &= ~PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME; > > + value |= FIELD_PREP(PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME, > > + PCIE_GLI_9767_SD_DATA_MULTI_CTL_DISCONNECT_TIME_VALUE); > > + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_DATA_MULTI_CTL, value); > > + > > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value); > > + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE; > > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, value); > > + > > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, &value); > > + value |= PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2_SDEI_COMPLETE_STATUS_EN; > > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_EN_REG2, value); > > + > > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, &value); > > + value |= PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2_SDEI_COMPLETE_SIGNAL_EN; > > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_SIGNAL_EN_REG2, value); > > + > > + pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value); > > + value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF; > > + pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); > > + > > + value = sdhci_readw(host, SDHCI_CLOCK_CONTROL); > > + value &= ~(SDHCI_CLOCK_CARD_EN | SDHCI_CLOCK_PLL_EN); > > + sdhci_writew(host, value, SDHCI_CLOCK_CONTROL); > > + > > + value = sdhci_readb(host, SDHCI_POWER_CONTROL); > > + value |= ((SDHCI_POWER_180 | SDHCI_POWER_ON) << 4); > > + sdhci_writeb(host, value, SDHCI_POWER_CONTROL); > > + > > + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value); > > + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SDEI_EXE; > > + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value); > > + > > + for (i = 0; i < 2; i++) { > > + msleep(10); > > + pci_read_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, &value); > > + if (value & PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2_SDEI_COMPLETE) { > > + pci_write_config_dword(pdev, PCIE_GLI_9767_NORMAL_ERR_INT_STATUS_REG2, > > + value); > > + break; > > + } > > + } > > + > > + pci_read_config_dword(pdev, PCIE_GLI_9767_SDHC_CAP, &value); > > + if ((value & PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) == PCIE_GLI_9767_SDHC_CAP_SDEI_RESULT) { > > + pci_read_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, &value); > > + value |= PCIE_GLI_9767_SD_EXPRESS_CTL_SD_EXPRESS_MODE; > > + pci_write_config_dword(pdev, PCIE_GLI_9767_SD_EXPRESS_CTL, value); > > + } else { > > + mmc->ios.timing &= ~(MMC_TIMING_SD_EXP | MMC_TIMING_SD_EXP_1_2V); > > + } > > + > > + gl9767_vhs_read(pdev); > > + > > + return 0; > > +} > > + > > static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot) > > { > > struct sdhci_host *host = slot->host; > > @@ -967,6 +1070,8 @@ static int gli_probe_slot_gl9767(struct sdhci_pci_slot *slot) > > gl9767_hw_setting(slot); > > gli_pcie_enable_msi(slot); > > slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; > > + host->mmc->caps2 |= MMC_CAP2_SD_EXP; > > + host->mmc_host_ops.init_sd_express = gl9767_init_sd_express; > > sdhci_enable_v4_mode(host); > > > > return 0; > Thanks, Victor Shih