Skip to content

Commit 1ae1d2d

Browse files
benchuangglistorulf
authored andcommitted
mmc: sdhci-pci-gli: Add Genesys Logic GL9763E support
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 <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ulf Hansson <[email protected]>
1 parent 1be64c7 commit 1ae1d2d

File tree

3 files changed

+109
-0
lines changed

3 files changed

+109
-0
lines changed

drivers/mmc/host/sdhci-pci-core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,7 @@ static const struct pci_device_id pci_ids[] = {
17451745
SDHCI_PCI_DEVICE(SYNOPSYS, DWC_MSHC, snps),
17461746
SDHCI_PCI_DEVICE(GLI, 9750, gl9750),
17471747
SDHCI_PCI_DEVICE(GLI, 9755, gl9755),
1748+
SDHCI_PCI_DEVICE(GLI, 9763E, gl9763e),
17481749
SDHCI_PCI_DEVICE_CLASS(AMD, SYSTEM_SDHCI, PCI_CLASS_MASK, amd),
17491750
/* Generic SD host controller */
17501751
{PCI_DEVICE_CLASS(SYSTEM_SDHCI, PCI_CLASS_MASK)},

drivers/mmc/host/sdhci-pci-gli.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,19 @@
6363
#define SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY GENMASK(2, 0)
6464
#define GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE 0x1
6565

66+
#define SDHCI_GLI_9763E_CTRL_HS400 0x7
67+
68+
#define SDHCI_GLI_9763E_HS400_ES_REG 0x52C
69+
#define SDHCI_GLI_9763E_HS400_ES_BIT BIT(8)
70+
71+
#define PCIE_GLI_9763E_VHS 0x884
72+
#define GLI_9763E_VHS_REV GENMASK(19, 16)
73+
#define GLI_9763E_VHS_REV_R 0x0
74+
#define GLI_9763E_VHS_REV_M 0x1
75+
#define GLI_9763E_VHS_REV_W 0x2
76+
#define PCIE_GLI_9763E_SCR 0x8E0
77+
#define GLI_9763E_SCR_AXI_REQ BIT(9)
78+
6679
#define GLI_MAX_TUNING_LOOP 40
6780

6881
/* Genesys Logic chipset */
@@ -351,6 +364,81 @@ static int sdhci_pci_gli_resume(struct sdhci_pci_chip *chip)
351364
}
352365
#endif
353366

367+
static void gl9763e_hs400_enhanced_strobe(struct mmc_host *mmc,
368+
struct mmc_ios *ios)
369+
{
370+
struct sdhci_host *host = mmc_priv(mmc);
371+
u32 val;
372+
373+
val = sdhci_readl(host, SDHCI_GLI_9763E_HS400_ES_REG);
374+
if (ios->enhanced_strobe)
375+
val |= SDHCI_GLI_9763E_HS400_ES_BIT;
376+
else
377+
val &= ~SDHCI_GLI_9763E_HS400_ES_BIT;
378+
379+
sdhci_writel(host, val, SDHCI_GLI_9763E_HS400_ES_REG);
380+
}
381+
382+
static void sdhci_set_gl9763e_signaling(struct sdhci_host *host,
383+
unsigned int timing)
384+
{
385+
u16 ctrl_2;
386+
387+
ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2);
388+
ctrl_2 &= ~SDHCI_CTRL_UHS_MASK;
389+
if (timing == MMC_TIMING_MMC_HS200)
390+
ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
391+
else if (timing == MMC_TIMING_MMC_HS)
392+
ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
393+
else if (timing == MMC_TIMING_MMC_DDR52)
394+
ctrl_2 |= SDHCI_CTRL_UHS_DDR50;
395+
else if (timing == MMC_TIMING_MMC_HS400)
396+
ctrl_2 |= SDHCI_GLI_9763E_CTRL_HS400;
397+
398+
sdhci_writew(host, ctrl_2, SDHCI_HOST_CONTROL2);
399+
}
400+
401+
static void gli_set_gl9763e(struct sdhci_pci_slot *slot)
402+
{
403+
struct pci_dev *pdev = slot->chip->pdev;
404+
u32 value;
405+
406+
pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value);
407+
value &= ~GLI_9763E_VHS_REV;
408+
value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W);
409+
pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value);
410+
411+
pci_read_config_dword(pdev, PCIE_GLI_9763E_SCR, &value);
412+
value |= GLI_9763E_SCR_AXI_REQ;
413+
pci_write_config_dword(pdev, PCIE_GLI_9763E_SCR, value);
414+
415+
pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value);
416+
value &= ~GLI_9763E_VHS_REV;
417+
value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R);
418+
pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value);
419+
}
420+
421+
static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot)
422+
{
423+
struct sdhci_host *host = slot->host;
424+
425+
host->mmc->caps |= MMC_CAP_8_BIT_DATA |
426+
MMC_CAP_1_8V_DDR |
427+
MMC_CAP_NONREMOVABLE;
428+
host->mmc->caps2 |= MMC_CAP2_HS200_1_8V_SDR |
429+
MMC_CAP2_HS400_1_8V |
430+
MMC_CAP2_HS400_ES |
431+
MMC_CAP2_NO_SDIO |
432+
MMC_CAP2_NO_SD;
433+
gli_pcie_enable_msi(slot);
434+
host->mmc_host_ops.hs400_enhanced_strobe =
435+
gl9763e_hs400_enhanced_strobe;
436+
gli_set_gl9763e(slot);
437+
sdhci_enable_v4_mode(host);
438+
439+
return 0;
440+
}
441+
354442
static const struct sdhci_ops sdhci_gl9755_ops = {
355443
.set_clock = sdhci_set_clock,
356444
.enable_dma = sdhci_pci_enable_dma,
@@ -390,3 +478,21 @@ const struct sdhci_pci_fixes sdhci_gl9750 = {
390478
.resume = sdhci_pci_gli_resume,
391479
#endif
392480
};
481+
482+
static const struct sdhci_ops sdhci_gl9763e_ops = {
483+
.set_clock = sdhci_set_clock,
484+
.enable_dma = sdhci_pci_enable_dma,
485+
.set_bus_width = sdhci_set_bus_width,
486+
.reset = sdhci_reset,
487+
.set_uhs_signaling = sdhci_set_gl9763e_signaling,
488+
.voltage_switch = sdhci_gli_voltage_switch,
489+
};
490+
491+
const struct sdhci_pci_fixes sdhci_gl9763e = {
492+
.quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,
493+
.probe_slot = gli_probe_slot_gl9763e,
494+
.ops = &sdhci_gl9763e_ops,
495+
#ifdef CONFIG_PM_SLEEP
496+
.resume = sdhci_pci_gli_resume,
497+
#endif
498+
};

drivers/mmc/host/sdhci-pci.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272

7373
#define PCI_DEVICE_ID_GLI_9755 0x9755
7474
#define PCI_DEVICE_ID_GLI_9750 0x9750
75+
#define PCI_DEVICE_ID_GLI_9763E 0xe763
7576

7677
/*
7778
* PCI device class and mask
@@ -195,5 +196,6 @@ extern const struct sdhci_pci_fixes sdhci_snps;
195196
extern const struct sdhci_pci_fixes sdhci_o2;
196197
extern const struct sdhci_pci_fixes sdhci_gl9750;
197198
extern const struct sdhci_pci_fixes sdhci_gl9755;
199+
extern const struct sdhci_pci_fixes sdhci_gl9763e;
198200

199201
#endif /* __SDHCI_PCI_H */

0 commit comments

Comments
 (0)