Message ID | 20200508064154.13473-1-benchuanggli@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | mmc: sdhci-pci-gli: Add Genesys Logic GL9763E support | expand |
On Fri, 8 May 2020 at 08:42, Ben Chuang <benchuanggli@gmail.com> wrote: > > From: Ben Chuang <ben.chuang@genesyslogic.com.tw> > > GL9763E supports High Speed SDR, High Speed DDR, HS200, HS400, Enhanced > Strobe in HS400 mode, 1/4/8 bits data bus and 3.3/1.8V. > > Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw> Applied for next, thanks! Kind regards Uffe > --- > drivers/mmc/host/sdhci-pci-core.c | 1 + > drivers/mmc/host/sdhci-pci-gli.c | 106 ++++++++++++++++++++++++++++++ > drivers/mmc/host/sdhci-pci.h | 2 + > 3 files changed, 109 insertions(+) > > diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c > index af736afb4b91..bb6802448b2f 100644 > --- a/drivers/mmc/host/sdhci-pci-core.c > +++ b/drivers/mmc/host/sdhci-pci-core.c > @@ -1745,6 +1745,7 @@ static const struct pci_device_id pci_ids[] = { > SDHCI_PCI_DEVICE(SYNOPSYS, DWC_MSHC, snps), > SDHCI_PCI_DEVICE(GLI, 9750, gl9750), > SDHCI_PCI_DEVICE(GLI, 9755, gl9755), > + SDHCI_PCI_DEVICE(GLI, 9763E, gl9763e), > SDHCI_PCI_DEVICE_CLASS(AMD, SYSTEM_SDHCI, PCI_CLASS_MASK, amd), > /* Generic SD host controller */ > {PCI_DEVICE_CLASS(SYSTEM_SDHCI, PCI_CLASS_MASK)}, > diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c > index fd76aa672e02..ca0166d9bf82 100644 > --- a/drivers/mmc/host/sdhci-pci-gli.c > +++ b/drivers/mmc/host/sdhci-pci-gli.c > @@ -63,6 +63,19 @@ > #define SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY GENMASK(2, 0) > #define GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE 0x1 > > +#define SDHCI_GLI_9763E_CTRL_HS400 0x7 > + > +#define SDHCI_GLI_9763E_HS400_ES_REG 0x52C > +#define SDHCI_GLI_9763E_HS400_ES_BIT BIT(8) > + > +#define PCIE_GLI_9763E_VHS 0x884 > +#define GLI_9763E_VHS_REV GENMASK(19, 16) > +#define GLI_9763E_VHS_REV_R 0x0 > +#define GLI_9763E_VHS_REV_M 0x1 > +#define GLI_9763E_VHS_REV_W 0x2 > +#define PCIE_GLI_9763E_SCR 0x8E0 > +#define GLI_9763E_SCR_AXI_REQ BIT(9) > + > #define GLI_MAX_TUNING_LOOP 40 > > /* Genesys Logic chipset */ > @@ -351,6 +364,81 @@ static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip) > } > #endif > > +static void gl9763e_hs400_enhanced_strobe(struct mmc_host *mmc, > + struct mmc_ios *ios) > +{ > + struct sdhci_host *host = mmc_priv(mmc); > + u32 val; > + > + val = sdhci_readl(host, SDHCI_GLI_9763E_HS400_ES_REG); > + if (ios->enhanced_strobe) > + val |= SDHCI_GLI_9763E_HS400_ES_BIT; > + else > + val &= ~SDHCI_GLI_9763E_HS400_ES_BIT; > + > + sdhci_writel(host, val, SDHCI_GLI_9763E_HS400_ES_REG); > +} > + > +static void sdhci_set_gl9763e_signaling(struct sdhci_host *host, > + unsigned int timing) > +{ > + u16 ctrl_2; > + > + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); > + ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; > + if (timing == MMC_TIMING_MMC_HS200) > + ctrl_2 |= SDHCI_CTRL_UHS_SDR104; > + else if (timing == MMC_TIMING_MMC_HS) > + ctrl_2 |= SDHCI_CTRL_UHS_SDR25; > + else if (timing == MMC_TIMING_MMC_DDR52) > + ctrl_2 |= SDHCI_CTRL_UHS_DDR50; > + else if (timing == MMC_TIMING_MMC_HS400) > + ctrl_2 |= SDHCI_GLI_9763E_CTRL_HS400; > + > + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); > +} > + > +static void gli_set_gl9763e(struct sdhci_pci_slot *slot) > +{ > + struct pci_dev *pdev = slot->chip->pdev; > + u32 value; > + > + pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); > + value &= ~GLI_9763E_VHS_REV; > + value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); > + pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); > + > + pci_read_config_dword(pdev, PCIE_GLI_9763E_SCR, &value); > + value |= GLI_9763E_SCR_AXI_REQ; > + pci_write_config_dword(pdev, PCIE_GLI_9763E_SCR, value); > + > + pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); > + value &= ~GLI_9763E_VHS_REV; > + value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); > + pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); > +} > + > +static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot) > +{ > + struct sdhci_host *host = slot->host; > + > + host->mmc->caps |= MMC_CAP_8_BIT_DATA | > + MMC_CAP_1_8V_DDR | > + MMC_CAP_NONREMOVABLE; > + host->mmc->caps2 |= MMC_CAP2_HS200_1_8V_SDR | > + MMC_CAP2_HS400_1_8V | > + MMC_CAP2_HS400_ES | > + MMC_CAP2_NO_SDIO | > + MMC_CAP2_NO_SD; > + gli_pcie_enable_msi(slot); > + host->mmc_host_ops.hs400_enhanced_strobe = > + gl9763e_hs400_enhanced_strobe; > + gli_set_gl9763e(slot); > + sdhci_enable_v4_mode(host); > + > + return 0; > +} > + > static const struct sdhci_ops sdhci_gl9755_ops = { > .set_clock = sdhci_set_clock, > .enable_dma = sdhci_pci_enable_dma, > @@ -390,3 +478,21 @@ const struct sdhci_pci_fixes sdhci_gl9750 = { > .resume = sdhci_pci_gli_resume, > #endif > }; > + > +static const struct sdhci_ops sdhci_gl9763e_ops = { > + .set_clock = sdhci_set_clock, > + .enable_dma = sdhci_pci_enable_dma, > + .set_bus_width = sdhci_set_bus_width, > + .reset = sdhci_reset, > + .set_uhs_signaling = sdhci_set_gl9763e_signaling, > + .voltage_switch = sdhci_gli_voltage_switch, > +}; > + > +const struct sdhci_pci_fixes sdhci_gl9763e = { > + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, > + .probe_slot = gli_probe_slot_gl9763e, > + .ops = &sdhci_gl9763e_ops, > +#ifdef CONFIG_PM_SLEEP > + .resume = sdhci_pci_gli_resume, > +#endif > +}; > diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h > index 42ccd123b046..d0ed232af0eb 100644 > --- a/drivers/mmc/host/sdhci-pci.h > +++ b/drivers/mmc/host/sdhci-pci.h > @@ -72,6 +72,7 @@ > > #define PCI_DEVICE_ID_GLI_9755 0x9755 > #define PCI_DEVICE_ID_GLI_9750 0x9750 > +#define PCI_DEVICE_ID_GLI_9763E 0xe763 > > /* > * PCI device class and mask > @@ -195,5 +196,6 @@ extern const struct sdhci_pci_fixes sdhci_snps; > extern const struct sdhci_pci_fixes sdhci_o2; > extern const struct sdhci_pci_fixes sdhci_gl9750; > extern const struct sdhci_pci_fixes sdhci_gl9755; > +extern const struct sdhci_pci_fixes sdhci_gl9763e; > > #endif /* __SDHCI_PCI_H */ > -- > 2.26.2 >
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index af736afb4b91..bb6802448b2f 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -1745,6 +1745,7 @@ static const struct pci_device_id pci_ids[] = { SDHCI_PCI_DEVICE(SYNOPSYS, DWC_MSHC, snps), SDHCI_PCI_DEVICE(GLI, 9750, gl9750), SDHCI_PCI_DEVICE(GLI, 9755, gl9755), + SDHCI_PCI_DEVICE(GLI, 9763E, gl9763e), SDHCI_PCI_DEVICE_CLASS(AMD, SYSTEM_SDHCI, PCI_CLASS_MASK, amd), /* Generic SD host controller */ {PCI_DEVICE_CLASS(SYSTEM_SDHCI, PCI_CLASS_MASK)}, diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c index fd76aa672e02..ca0166d9bf82 100644 --- a/drivers/mmc/host/sdhci-pci-gli.c +++ b/drivers/mmc/host/sdhci-pci-gli.c @@ -63,6 +63,19 @@ #define SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY GENMASK(2, 0) #define GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE 0x1 +#define SDHCI_GLI_9763E_CTRL_HS400 0x7 + +#define SDHCI_GLI_9763E_HS400_ES_REG 0x52C +#define SDHCI_GLI_9763E_HS400_ES_BIT BIT(8) + +#define PCIE_GLI_9763E_VHS 0x884 +#define GLI_9763E_VHS_REV GENMASK(19, 16) +#define GLI_9763E_VHS_REV_R 0x0 +#define GLI_9763E_VHS_REV_M 0x1 +#define GLI_9763E_VHS_REV_W 0x2 +#define PCIE_GLI_9763E_SCR 0x8E0 +#define GLI_9763E_SCR_AXI_REQ BIT(9) + #define GLI_MAX_TUNING_LOOP 40 /* Genesys Logic chipset */ @@ -351,6 +364,81 @@ static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip) } #endif +static void gl9763e_hs400_enhanced_strobe(struct mmc_host *mmc, + struct mmc_ios *ios) +{ + struct sdhci_host *host = mmc_priv(mmc); + u32 val; + + val = sdhci_readl(host, SDHCI_GLI_9763E_HS400_ES_REG); + if (ios->enhanced_strobe) + val |= SDHCI_GLI_9763E_HS400_ES_BIT; + else + val &= ~SDHCI_GLI_9763E_HS400_ES_BIT; + + sdhci_writel(host, val, SDHCI_GLI_9763E_HS400_ES_REG); +} + +static void sdhci_set_gl9763e_signaling(struct sdhci_host *host, + unsigned int timing) +{ + u16 ctrl_2; + + ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); + ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; + if (timing == MMC_TIMING_MMC_HS200) + ctrl_2 |= SDHCI_CTRL_UHS_SDR104; + else if (timing == MMC_TIMING_MMC_HS) + ctrl_2 |= SDHCI_CTRL_UHS_SDR25; + else if (timing == MMC_TIMING_MMC_DDR52) + ctrl_2 |= SDHCI_CTRL_UHS_DDR50; + else if (timing == MMC_TIMING_MMC_HS400) + ctrl_2 |= SDHCI_GLI_9763E_CTRL_HS400; + + sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2); +} + +static void gli_set_gl9763e(struct sdhci_pci_slot *slot) +{ + struct pci_dev *pdev = slot->chip->pdev; + u32 value; + + pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); + value &= ~GLI_9763E_VHS_REV; + value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W); + pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); + + pci_read_config_dword(pdev, PCIE_GLI_9763E_SCR, &value); + value |= GLI_9763E_SCR_AXI_REQ; + pci_write_config_dword(pdev, PCIE_GLI_9763E_SCR, value); + + pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value); + value &= ~GLI_9763E_VHS_REV; + value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R); + pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value); +} + +static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot) +{ + struct sdhci_host *host = slot->host; + + host->mmc->caps |= MMC_CAP_8_BIT_DATA | + MMC_CAP_1_8V_DDR | + MMC_CAP_NONREMOVABLE; + host->mmc->caps2 |= MMC_CAP2_HS200_1_8V_SDR | + MMC_CAP2_HS400_1_8V | + MMC_CAP2_HS400_ES | + MMC_CAP2_NO_SDIO | + MMC_CAP2_NO_SD; + gli_pcie_enable_msi(slot); + host->mmc_host_ops.hs400_enhanced_strobe = + gl9763e_hs400_enhanced_strobe; + gli_set_gl9763e(slot); + sdhci_enable_v4_mode(host); + + return 0; +} + static const struct sdhci_ops sdhci_gl9755_ops = { .set_clock = sdhci_set_clock, .enable_dma = sdhci_pci_enable_dma, @@ -390,3 +478,21 @@ const struct sdhci_pci_fixes sdhci_gl9750 = { .resume = sdhci_pci_gli_resume, #endif }; + +static const struct sdhci_ops sdhci_gl9763e_ops = { + .set_clock = sdhci_set_clock, + .enable_dma = sdhci_pci_enable_dma, + .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_gl9763e_signaling, + .voltage_switch = sdhci_gli_voltage_switch, +}; + +const struct sdhci_pci_fixes sdhci_gl9763e = { + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, + .probe_slot = gli_probe_slot_gl9763e, + .ops = &sdhci_gl9763e_ops, +#ifdef CONFIG_PM_SLEEP + .resume = sdhci_pci_gli_resume, +#endif +}; diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h index 42ccd123b046..d0ed232af0eb 100644 --- a/drivers/mmc/host/sdhci-pci.h +++ b/drivers/mmc/host/sdhci-pci.h @@ -72,6 +72,7 @@ #define PCI_DEVICE_ID_GLI_9755 0x9755 #define PCI_DEVICE_ID_GLI_9750 0x9750 +#define PCI_DEVICE_ID_GLI_9763E 0xe763 /* * PCI device class and mask @@ -195,5 +196,6 @@ extern const struct sdhci_pci_fixes sdhci_snps; extern const struct sdhci_pci_fixes sdhci_o2; extern const struct sdhci_pci_fixes sdhci_gl9750; extern const struct sdhci_pci_fixes sdhci_gl9755; +extern const struct sdhci_pci_fixes sdhci_gl9763e; #endif /* __SDHCI_PCI_H */