Skip to content

Commit 786d33c

Browse files
benchuangglistorulf
authored andcommitted
mmc: sdhci-pci-gli: Set SDR104's clock to 205MHz and enable SSC for GL975x
Set SDR104's clock to 205MHz and enable SSC for GL9750 and GL9755 Signed-off-by: Ben Chuang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ulf Hansson <[email protected]>
1 parent 9050865 commit 786d33c

File tree

1 file changed

+218
-2
lines changed

1 file changed

+218
-2
lines changed

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

Lines changed: 218 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,18 @@
3131
#define SDHCI_GLI_9750_ALL_RST (BIT(24)|BIT(25)|BIT(28)|BIT(30))
3232

3333
#define SDHCI_GLI_9750_PLL 0x864
34+
#define SDHCI_GLI_9750_PLL_LDIV GENMASK(9, 0)
35+
#define SDHCI_GLI_9750_PLL_PDIV GENMASK(14, 12)
36+
#define SDHCI_GLI_9750_PLL_DIR BIT(15)
3437
#define SDHCI_GLI_9750_PLL_TX2_INV BIT(23)
3538
#define SDHCI_GLI_9750_PLL_TX2_DLY GENMASK(22, 20)
3639
#define GLI_9750_PLL_TX2_INV_VALUE 0x1
3740
#define GLI_9750_PLL_TX2_DLY_VALUE 0x0
41+
#define SDHCI_GLI_9750_PLLSSC_STEP GENMASK(28, 24)
42+
#define SDHCI_GLI_9750_PLLSSC_EN BIT(31)
43+
44+
#define SDHCI_GLI_9750_PLLSSC 0x86C
45+
#define SDHCI_GLI_9750_PLLSSC_PPM GENMASK(31, 16)
3846

3947
#define SDHCI_GLI_9750_SW_CTRL 0x874
4048
#define SDHCI_GLI_9750_SW_CTRL_4 GENMASK(7, 6)
@@ -76,6 +84,21 @@
7684
#define PCIE_GLI_9763E_SCR 0x8E0
7785
#define GLI_9763E_SCR_AXI_REQ BIT(9)
7886

87+
#define PCI_GLI_9755_WT 0x800
88+
#define PCI_GLI_9755_WT_EN BIT(0)
89+
#define GLI_9755_WT_EN_ON 0x1
90+
#define GLI_9755_WT_EN_OFF 0x0
91+
92+
#define PCI_GLI_9755_PLL 0x64
93+
#define PCI_GLI_9755_PLL_LDIV GENMASK(9, 0)
94+
#define PCI_GLI_9755_PLL_PDIV GENMASK(14, 12)
95+
#define PCI_GLI_9755_PLL_DIR BIT(15)
96+
#define PCI_GLI_9755_PLLSSC_STEP GENMASK(28, 24)
97+
#define PCI_GLI_9755_PLLSSC_EN BIT(31)
98+
99+
#define PCI_GLI_9755_PLLSSC 0x68
100+
#define PCI_GLI_9755_PLLSSC_PPM GENMASK(15, 0)
101+
79102
#define GLI_MAX_TUNING_LOOP 40
80103

81104
/* Genesys Logic chipset */
@@ -280,6 +303,84 @@ static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode)
280303
return 0;
281304
}
282305

306+
static void gl9750_disable_ssc_pll(struct sdhci_host *host)
307+
{
308+
u32 pll;
309+
310+
gl9750_wt_on(host);
311+
pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
312+
pll &= ~(SDHCI_GLI_9750_PLL_DIR | SDHCI_GLI_9750_PLLSSC_EN);
313+
sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
314+
gl9750_wt_off(host);
315+
}
316+
317+
static void gl9750_set_pll(struct sdhci_host *host, u8 dir, u16 ldiv, u8 pdiv)
318+
{
319+
u32 pll;
320+
321+
gl9750_wt_on(host);
322+
pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
323+
pll &= ~(SDHCI_GLI_9750_PLL_LDIV |
324+
SDHCI_GLI_9750_PLL_PDIV |
325+
SDHCI_GLI_9750_PLL_DIR);
326+
pll |= FIELD_PREP(SDHCI_GLI_9750_PLL_LDIV, ldiv) |
327+
FIELD_PREP(SDHCI_GLI_9750_PLL_PDIV, pdiv) |
328+
FIELD_PREP(SDHCI_GLI_9750_PLL_DIR, dir);
329+
sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
330+
gl9750_wt_off(host);
331+
332+
/* wait for pll stable */
333+
mdelay(1);
334+
}
335+
336+
static void gl9750_set_ssc(struct sdhci_host *host, u8 enable, u8 step, u16 ppm)
337+
{
338+
u32 pll;
339+
u32 ssc;
340+
341+
gl9750_wt_on(host);
342+
pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
343+
ssc = sdhci_readl(host, SDHCI_GLI_9750_PLLSSC);
344+
pll &= ~(SDHCI_GLI_9750_PLLSSC_STEP |
345+
SDHCI_GLI_9750_PLLSSC_EN);
346+
ssc &= ~SDHCI_GLI_9750_PLLSSC_PPM;
347+
pll |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_STEP, step) |
348+
FIELD_PREP(SDHCI_GLI_9750_PLLSSC_EN, enable);
349+
ssc |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_PPM, ppm);
350+
sdhci_writel(host, ssc, SDHCI_GLI_9750_PLLSSC);
351+
sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
352+
gl9750_wt_off(host);
353+
}
354+
355+
static void gl9750_set_ssc_pll_205mhz(struct sdhci_host *host)
356+
{
357+
/* set pll to 205MHz and enable ssc */
358+
gl9750_set_ssc(host, 0x1, 0x1F, 0xFFE7);
359+
gl9750_set_pll(host, 0x1, 0x246, 0x0);
360+
}
361+
362+
static void sdhci_gl9750_set_clock(struct sdhci_host *host, unsigned int clock)
363+
{
364+
struct mmc_ios *ios = &host->mmc->ios;
365+
u16 clk;
366+
367+
host->mmc->actual_clock = 0;
368+
369+
gl9750_disable_ssc_pll(host);
370+
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
371+
372+
if (clock == 0)
373+
return;
374+
375+
clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
376+
if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
377+
host->mmc->actual_clock = 205000000;
378+
gl9750_set_ssc_pll_205mhz(host);
379+
}
380+
381+
sdhci_enable_clk(host, clk);
382+
}
383+
283384
static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
284385
{
285386
int ret;
@@ -295,6 +396,121 @@ static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
295396
slot->host->irq = pci_irq_vector(slot->chip->pdev, 0);
296397
}
297398

399+
static inline void gl9755_wt_on(struct pci_dev *pdev)
400+
{
401+
u32 wt_value;
402+
u32 wt_enable;
403+
404+
pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value);
405+
wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value);
406+
407+
if (wt_enable == GLI_9755_WT_EN_ON)
408+
return;
409+
410+
wt_value &= ~PCI_GLI_9755_WT_EN;
411+
wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_ON);
412+
413+
pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value);
414+
}
415+
416+
static inline void gl9755_wt_off(struct pci_dev *pdev)
417+
{
418+
u32 wt_value;
419+
u32 wt_enable;
420+
421+
pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value);
422+
wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value);
423+
424+
if (wt_enable == GLI_9755_WT_EN_OFF)
425+
return;
426+
427+
wt_value &= ~PCI_GLI_9755_WT_EN;
428+
wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_OFF);
429+
430+
pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value);
431+
}
432+
433+
static void gl9755_disable_ssc_pll(struct pci_dev *pdev)
434+
{
435+
u32 pll;
436+
437+
gl9755_wt_on(pdev);
438+
pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
439+
pll &= ~(PCI_GLI_9755_PLL_DIR | PCI_GLI_9755_PLLSSC_EN);
440+
pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
441+
gl9755_wt_off(pdev);
442+
}
443+
444+
static void gl9755_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv)
445+
{
446+
u32 pll;
447+
448+
gl9755_wt_on(pdev);
449+
pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
450+
pll &= ~(PCI_GLI_9755_PLL_LDIV |
451+
PCI_GLI_9755_PLL_PDIV |
452+
PCI_GLI_9755_PLL_DIR);
453+
pll |= FIELD_PREP(PCI_GLI_9755_PLL_LDIV, ldiv) |
454+
FIELD_PREP(PCI_GLI_9755_PLL_PDIV, pdiv) |
455+
FIELD_PREP(PCI_GLI_9755_PLL_DIR, dir);
456+
pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
457+
gl9755_wt_off(pdev);
458+
459+
/* wait for pll stable */
460+
mdelay(1);
461+
}
462+
463+
static void gl9755_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm)
464+
{
465+
u32 pll;
466+
u32 ssc;
467+
468+
gl9755_wt_on(pdev);
469+
pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
470+
pci_read_config_dword(pdev, PCI_GLI_9755_PLLSSC, &ssc);
471+
pll &= ~(PCI_GLI_9755_PLLSSC_STEP |
472+
PCI_GLI_9755_PLLSSC_EN);
473+
ssc &= ~PCI_GLI_9755_PLLSSC_PPM;
474+
pll |= FIELD_PREP(PCI_GLI_9755_PLLSSC_STEP, step) |
475+
FIELD_PREP(PCI_GLI_9755_PLLSSC_EN, enable);
476+
ssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_PPM, ppm);
477+
pci_write_config_dword(pdev, PCI_GLI_9755_PLLSSC, ssc);
478+
pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
479+
gl9755_wt_off(pdev);
480+
}
481+
482+
static void gl9755_set_ssc_pll_205mhz(struct pci_dev *pdev)
483+
{
484+
/* set pll to 205MHz and enable ssc */
485+
gl9755_set_ssc(pdev, 0x1, 0x1F, 0xFFE7);
486+
gl9755_set_pll(pdev, 0x1, 0x246, 0x0);
487+
}
488+
489+
static void sdhci_gl9755_set_clock(struct sdhci_host *host, unsigned int clock)
490+
{
491+
struct sdhci_pci_slot *slot = sdhci_priv(host);
492+
struct mmc_ios *ios = &host->mmc->ios;
493+
struct pci_dev *pdev;
494+
u16 clk;
495+
496+
pdev = slot->chip->pdev;
497+
host->mmc->actual_clock = 0;
498+
499+
gl9755_disable_ssc_pll(pdev);
500+
sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
501+
502+
if (clock == 0)
503+
return;
504+
505+
clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
506+
if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
507+
host->mmc->actual_clock = 205000000;
508+
gl9755_set_ssc_pll_205mhz(pdev);
509+
}
510+
511+
sdhci_enable_clk(host, clk);
512+
}
513+
298514
static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
299515
{
300516
struct sdhci_host *host = slot->host;
@@ -440,7 +656,7 @@ static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot)
440656
}
441657

442658
static const struct sdhci_ops sdhci_gl9755_ops = {
443-
.set_clock = sdhci_set_clock,
659+
.set_clock = sdhci_gl9755_set_clock,
444660
.enable_dma = sdhci_pci_enable_dma,
445661
.set_bus_width = sdhci_set_bus_width,
446662
.reset = sdhci_reset,
@@ -460,7 +676,7 @@ const struct sdhci_pci_fixes sdhci_gl9755 = {
460676

461677
static const struct sdhci_ops sdhci_gl9750_ops = {
462678
.read_l = sdhci_gl9750_readl,
463-
.set_clock = sdhci_set_clock,
679+
.set_clock = sdhci_gl9750_set_clock,
464680
.enable_dma = sdhci_pci_enable_dma,
465681
.set_bus_width = sdhci_set_bus_width,
466682
.reset = sdhci_gl9750_reset,

0 commit comments

Comments
 (0)