Skip to content

Commit f9e5b33

Browse files
Jason Laistorulf
authored andcommitted
mmc: host: Improve I/O read/write performance for GL9763E
Due to flaws in hardware design, GL9763E takes long time to exit from L1 state. The I/O performance will suffer severe impact if it often enter and exit L1 state during I/O requests. To improve I/O read/write performance and take battery life into account, let's turn on GL9763E L1 negotiation before entering runtime suspend and turn off GL9763E L1 negotiation while executing runtime resume. That is to say, GL9763E will not enter L1 state when executing I/O requests and enter L1 state when PCIe bus idle. Signed-off-by: Renius Chen <[email protected]> Signed-off-by: Jason Lai <[email protected]> Link: https://lore.kernel.org/r/[email protected] [Ulf: Improved the commit message a bit] Signed-off-by: Ulf Hansson <[email protected]>
1 parent f6c3397 commit f9e5b33

File tree

1 file changed

+34
-0
lines changed

1 file changed

+34
-0
lines changed

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@
9595
#define PCIE_GLI_9763E_SCR 0x8E0
9696
#define GLI_9763E_SCR_AXI_REQ BIT(9)
9797

98+
#define PCIE_GLI_9763E_CFG 0x8A0
99+
#define GLI_9763E_CFG_LPSN_DIS BIT(12)
100+
98101
#define PCIE_GLI_9763E_CFG2 0x8A4
99102
#define GLI_9763E_CFG2_L1DLY GENMASK(28, 19)
100103
#define GLI_9763E_CFG2_L1DLY_MID 0x54
@@ -828,6 +831,31 @@ static void sdhci_gl9763e_dumpregs(struct mmc_host *mmc)
828831
sdhci_dumpregs(mmc_priv(mmc));
829832
}
830833

834+
static void gl9763e_set_low_power_negotiation(struct sdhci_pci_slot *slot, bool enable)
835+
{
836+
struct pci_dev *pdev = slot->chip->pdev;
837+
u32 value;
838+
839+
pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value);
840+
value &= ~GLI_9763E_VHS_REV;
841+
value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_W);
842+
pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value);
843+
844+
pci_read_config_dword(pdev, PCIE_GLI_9763E_CFG, &value);
845+
846+
if (enable)
847+
value &= ~GLI_9763E_CFG_LPSN_DIS;
848+
else
849+
value |= GLI_9763E_CFG_LPSN_DIS;
850+
851+
pci_write_config_dword(pdev, PCIE_GLI_9763E_CFG, value);
852+
853+
pci_read_config_dword(pdev, PCIE_GLI_9763E_VHS, &value);
854+
value &= ~GLI_9763E_VHS_REV;
855+
value |= FIELD_PREP(GLI_9763E_VHS_REV, GLI_9763E_VHS_REV_R);
856+
pci_write_config_dword(pdev, PCIE_GLI_9763E_VHS, value);
857+
}
858+
831859
static void sdhci_gl9763e_cqe_pre_enable(struct mmc_host *mmc)
832860
{
833861
struct cqhci_host *cq_host = mmc->cqe_private;
@@ -969,6 +997,9 @@ static int gl9763e_runtime_suspend(struct sdhci_pci_chip *chip)
969997
struct sdhci_host *host = slot->host;
970998
u16 clock;
971999

1000+
/* Enable LPM negotiation to allow entering L1 state */
1001+
gl9763e_set_low_power_negotiation(slot, true);
1002+
9721003
clock = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
9731004
clock &= ~(SDHCI_CLOCK_PLL_EN | SDHCI_CLOCK_CARD_EN);
9741005
sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL);
@@ -1002,6 +1033,9 @@ static int gl9763e_runtime_resume(struct sdhci_pci_chip *chip)
10021033
clock |= SDHCI_CLOCK_CARD_EN;
10031034
sdhci_writew(host, clock, SDHCI_CLOCK_CONTROL);
10041035

1036+
/* Disable LPM negotiation to avoid entering L1 state. */
1037+
gl9763e_set_low_power_negotiation(slot, false);
1038+
10051039
return 0;
10061040
}
10071041
#endif

0 commit comments

Comments
 (0)