Skip to content

Commit

Permalink
mmc: sdhci-pci-gli: Add Genesys Logic GL9763E support
Browse files Browse the repository at this point in the history
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>
Link: https://lore.kernel.org/r/20200508064154.13473-1-benchuanggli@gmail.com
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
  • Loading branch information
benchuanggli authored and storulf committed May 28, 2020
1 parent 1be64c7 commit 1ae1d2d
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 0 deletions.
1 change: 1 addition & 0 deletions drivers/mmc/host/sdhci-pci-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)},
Expand Down
106 changes: 106 additions & 0 deletions drivers/mmc/host/sdhci-pci-gli.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
};
2 changes: 2 additions & 0 deletions drivers/mmc/host/sdhci-pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */

0 comments on commit 1ae1d2d

Please sign in to comment.