Skip to content

Commit 8c68b56

Browse files
benchuangglistorulf
authored andcommitted
mmc: sdhci-pci-gli: GL9767: Fix low power mode on the set clock function
On sdhci_gl9767_set_clock(), the vendor header space(VHS) is read-only after calling gl9767_disable_ssc_pll() and gl9767_set_ssc_pll_205mhz(). So the low power negotiation mode cannot be enabled again. Introduce gl9767_set_low_power_negotiation() function to fix it. The explanation process is as below. static void sdhci_gl9767_set_clock() { ... gl9767_vhs_write(); ... value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF; pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); <--- (a) gl9767_disable_ssc_pll(); <--- (b) sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL); if (clock == 0) return; <-- (I) ... if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) { ... gl9767_set_ssc_pll_205mhz(); <--- (c) } ... value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF; pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value); <-- (II) gl9767_vhs_read(); } (a) disable low power negotiation mode. When return on (I), the low power mode is disabled. After (b) and (c), VHS is read-only, the low power mode cannot be enabled on (II). Reported-by: Georg Gottleuber <[email protected]> Fixes: d275435 ("mmc: sdhci-pci-gli: Set SDR104's clock to 205MHz and enable SSC for GL9767") Signed-off-by: Ben Chuang <[email protected]> Tested-by: Georg Gottleuber <[email protected]> Cc: [email protected] Message-ID: <[email protected]> Signed-off-by: Ulf Hansson <[email protected]>
1 parent 8e929cb commit 8c68b56

File tree

1 file changed

+21
-14
lines changed

1 file changed

+21
-14
lines changed

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

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -892,28 +892,40 @@ static void gl9767_disable_ssc_pll(struct pci_dev *pdev)
892892
gl9767_vhs_read(pdev);
893893
}
894894

895+
static void gl9767_set_low_power_negotiation(struct pci_dev *pdev, bool enable)
896+
{
897+
u32 value;
898+
899+
gl9767_vhs_write(pdev);
900+
901+
pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
902+
if (enable)
903+
value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF;
904+
else
905+
value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
906+
pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
907+
908+
gl9767_vhs_read(pdev);
909+
}
910+
895911
static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock)
896912
{
897913
struct sdhci_pci_slot *slot = sdhci_priv(host);
898914
struct mmc_ios *ios = &host->mmc->ios;
899915
struct pci_dev *pdev;
900-
u32 value;
901916
u16 clk;
902917

903918
pdev = slot->chip->pdev;
904919
host->mmc->actual_clock = 0;
905920

906-
gl9767_vhs_write(pdev);
907-
908-
pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
909-
value |= PCIE_GLI_9767_CFG_LOW_PWR_OFF;
910-
pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
911-
921+
gl9767_set_low_power_negotiation(pdev, false);
912922
gl9767_disable_ssc_pll(pdev);
913923
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
914924

915-
if (clock == 0)
925+
if (clock == 0) {
926+
gl9767_set_low_power_negotiation(pdev, true);
916927
return;
928+
}
917929

918930
clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
919931
if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
@@ -922,12 +934,7 @@ static void sdhci_gl9767_set_clock(struct sdhci_host *host, unsigned int clock)
922934
}
923935

924936
sdhci_enable_clk(host, clk);
925-
926-
pci_read_config_dword(pdev, PCIE_GLI_9767_CFG, &value);
927-
value &= ~PCIE_GLI_9767_CFG_LOW_PWR_OFF;
928-
pci_write_config_dword(pdev, PCIE_GLI_9767_CFG, value);
929-
930-
gl9767_vhs_read(pdev);
937+
gl9767_set_low_power_negotiation(pdev, true);
931938
}
932939

933940
static void gli_set_9767(struct sdhci_host *host)

0 commit comments

Comments
 (0)