linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] mmc: sdhci-pci-gli: Set SDR104's clock to 205MHz and enable SSC for GL975x
@ 2020-07-17  3:33 Ben Chuang
  2020-08-05  6:33 ` Ulf Hansson
  0 siblings, 1 reply; 5+ messages in thread
From: Ben Chuang @ 2020-07-17  3:33 UTC (permalink / raw)
  To: adrian.hunter, ulf.hansson
  Cc: linux-mmc, linux-kernel, ben.chuang, greg.tu, SeanHY.Chen, Ben Chuang

From: Ben Chuang <ben.chuang@genesyslogic.com.tw>

Set SDR104's clock to 205MHz and enable SSC for GL9750 and GL9755

Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>
---
 drivers/mmc/host/sdhci-pci-gli.c | 220 ++++++++++++++++++++++++++++++-
 1 file changed, 218 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
index ca0166d9bf82..5da2b06d84ae 100644
--- a/drivers/mmc/host/sdhci-pci-gli.c
+++ b/drivers/mmc/host/sdhci-pci-gli.c
@@ -31,10 +31,18 @@
 #define   SDHCI_GLI_9750_ALL_RST      (BIT(24)|BIT(25)|BIT(28)|BIT(30))
 
 #define SDHCI_GLI_9750_PLL	      0x864
+#define   SDHCI_GLI_9750_PLL_LDIV       GENMASK(9, 0)
+#define   SDHCI_GLI_9750_PLL_PDIV       GENMASK(14, 12)
+#define   SDHCI_GLI_9750_PLL_DIR        BIT(15)
 #define   SDHCI_GLI_9750_PLL_TX2_INV    BIT(23)
 #define   SDHCI_GLI_9750_PLL_TX2_DLY    GENMASK(22, 20)
 #define   GLI_9750_PLL_TX2_INV_VALUE    0x1
 #define   GLI_9750_PLL_TX2_DLY_VALUE    0x0
+#define   SDHCI_GLI_9750_PLLSSC_STEP    GENMASK(28, 24)
+#define   SDHCI_GLI_9750_PLLSSC_EN      BIT(31)
+
+#define SDHCI_GLI_9750_PLLSSC        0x86C
+#define   SDHCI_GLI_9750_PLLSSC_PPM    GENMASK(31, 16)
 
 #define SDHCI_GLI_9750_SW_CTRL      0x874
 #define   SDHCI_GLI_9750_SW_CTRL_4    GENMASK(7, 6)
@@ -76,6 +84,21 @@
 #define PCIE_GLI_9763E_SCR	 0x8E0
 #define   GLI_9763E_SCR_AXI_REQ	   BIT(9)
 
+#define PCI_GLI_9755_WT       0x800
+#define   PCI_GLI_9755_WT_EN    BIT(0)
+#define   GLI_9755_WT_EN_ON     0x1
+#define   GLI_9755_WT_EN_OFF    0x0
+
+#define PCI_GLI_9755_PLL            0x64
+#define   PCI_GLI_9755_PLL_LDIV       GENMASK(9, 0)
+#define   PCI_GLI_9755_PLL_PDIV       GENMASK(14, 12)
+#define   PCI_GLI_9755_PLL_DIR        BIT(15)
+#define   PCI_GLI_9755_PLLSSC_STEP    GENMASK(28, 24)
+#define   PCI_GLI_9755_PLLSSC_EN      BIT(31)
+
+#define PCI_GLI_9755_PLLSSC        0x68
+#define   PCI_GLI_9755_PLLSSC_PPM    GENMASK(15, 0)
+
 #define GLI_MAX_TUNING_LOOP 40
 
 /* Genesys Logic chipset */
@@ -280,6 +303,84 @@ static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode)
 	return 0;
 }
 
+static void gl9750_disable_ssc_pll(struct sdhci_host *host)
+{
+	u32 pll;
+
+	gl9750_wt_on(host);
+	pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
+	pll &= ~(SDHCI_GLI_9750_PLL_DIR | SDHCI_GLI_9750_PLLSSC_EN);
+	sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
+	gl9750_wt_off(host);
+}
+
+static void gl9750_set_pll(struct sdhci_host *host, u8 dir, u16 ldiv, u8 pdiv)
+{
+	u32 pll;
+
+	gl9750_wt_on(host);
+	pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
+	pll &= ~(SDHCI_GLI_9750_PLL_LDIV |
+		 SDHCI_GLI_9750_PLL_PDIV |
+		 SDHCI_GLI_9750_PLL_DIR);
+	pll |= FIELD_PREP(SDHCI_GLI_9750_PLL_LDIV, ldiv) |
+	       FIELD_PREP(SDHCI_GLI_9750_PLL_PDIV, pdiv) |
+	       FIELD_PREP(SDHCI_GLI_9750_PLL_DIR, dir);
+	sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
+	gl9750_wt_off(host);
+
+	/* wait for pll stable */
+	mdelay(1);
+}
+
+static void gl9750_set_ssc(struct sdhci_host *host, u8 enable, u8 step, u16 ppm)
+{
+	u32 pll;
+	u32 ssc;
+
+	gl9750_wt_on(host);
+	pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
+	ssc = sdhci_readl(host, SDHCI_GLI_9750_PLLSSC);
+	pll &= ~(SDHCI_GLI_9750_PLLSSC_STEP |
+		 SDHCI_GLI_9750_PLLSSC_EN);
+	ssc &= ~SDHCI_GLI_9750_PLLSSC_PPM;
+	pll |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_STEP, step) |
+	       FIELD_PREP(SDHCI_GLI_9750_PLLSSC_EN, enable);
+	ssc |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_PPM, ppm);
+	sdhci_writel(host, ssc, SDHCI_GLI_9750_PLLSSC);
+	sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
+	gl9750_wt_off(host);
+}
+
+static void gl9750_set_ssc_pll_205mhz(struct sdhci_host *host)
+{
+	/* set pll to 205MHz and enable ssc */
+	gl9750_set_ssc(host, 0x1, 0x1F, 0xFFE7);
+	gl9750_set_pll(host, 0x1, 0x246, 0x0);
+}
+
+static void sdhci_gl9750_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	struct mmc_ios *ios = &host->mmc->ios;
+	u16 clk;
+
+	host->mmc->actual_clock = 0;
+
+	gl9750_disable_ssc_pll(host);
+	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+	if (clock == 0)
+		return;
+
+	clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
+	if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
+		host->mmc->actual_clock = 205000000;
+		gl9750_set_ssc_pll_205mhz(host);
+	}
+
+	sdhci_enable_clk(host, clk);
+}
+
 static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
 {
 	int ret;
@@ -295,6 +396,121 @@ static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
 	slot->host->irq = pci_irq_vector(slot->chip->pdev, 0);
 }
 
+static inline void gl9755_wt_on(struct pci_dev *pdev)
+{
+	u32 wt_value;
+	u32 wt_enable;
+
+	pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value);
+	wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value);
+
+	if (wt_enable == GLI_9755_WT_EN_ON)
+		return;
+
+	wt_value &= ~PCI_GLI_9755_WT_EN;
+	wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_ON);
+
+	pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value);
+}
+
+static inline void gl9755_wt_off(struct pci_dev *pdev)
+{
+	u32 wt_value;
+	u32 wt_enable;
+
+	pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value);
+	wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value);
+
+	if (wt_enable == GLI_9755_WT_EN_OFF)
+		return;
+
+	wt_value &= ~PCI_GLI_9755_WT_EN;
+	wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_OFF);
+
+	pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value);
+}
+
+static void gl9755_disable_ssc_pll(struct pci_dev *pdev)
+{
+	u32 pll;
+
+	gl9755_wt_on(pdev);
+	pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
+	pll &= ~(PCI_GLI_9755_PLL_DIR | PCI_GLI_9755_PLLSSC_EN);
+	pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
+	gl9755_wt_off(pdev);
+}
+
+static void gl9755_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv)
+{
+	u32 pll;
+
+	gl9755_wt_on(pdev);
+	pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
+	pll &= ~(PCI_GLI_9755_PLL_LDIV |
+		 PCI_GLI_9755_PLL_PDIV |
+		 PCI_GLI_9755_PLL_DIR);
+	pll |= FIELD_PREP(PCI_GLI_9755_PLL_LDIV, ldiv) |
+	       FIELD_PREP(PCI_GLI_9755_PLL_PDIV, pdiv) |
+	       FIELD_PREP(PCI_GLI_9755_PLL_DIR, dir);
+	pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
+	gl9755_wt_off(pdev);
+
+	/* wait for pll stable */
+	mdelay(1);
+}
+
+static void gl9755_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm)
+{
+	u32 pll;
+	u32 ssc;
+
+	gl9755_wt_on(pdev);
+	pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
+	pci_read_config_dword(pdev, PCI_GLI_9755_PLLSSC, &ssc);
+	pll &= ~(PCI_GLI_9755_PLLSSC_STEP |
+		 PCI_GLI_9755_PLLSSC_EN);
+	ssc &= ~PCI_GLI_9755_PLLSSC_PPM;
+	pll |= FIELD_PREP(PCI_GLI_9755_PLLSSC_STEP, step) |
+	       FIELD_PREP(PCI_GLI_9755_PLLSSC_EN, enable);
+	ssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_PPM, ppm);
+	pci_write_config_dword(pdev, PCI_GLI_9755_PLLSSC, ssc);
+	pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
+	gl9755_wt_off(pdev);
+}
+
+static void gl9755_set_ssc_pll_205mhz(struct pci_dev *pdev)
+{
+	/* set pll to 205MHz and enable ssc */
+	gl9755_set_ssc(pdev, 0x1, 0x1F, 0xFFE7);
+	gl9755_set_pll(pdev, 0x1, 0x246, 0x0);
+}
+
+static void sdhci_gl9755_set_clock(struct sdhci_host *host, unsigned int clock)
+{
+	struct sdhci_pci_slot *slot = sdhci_priv(host);
+	struct mmc_ios *ios = &host->mmc->ios;
+	struct pci_dev *pdev;
+	u16 clk;
+
+	pdev = slot->chip->pdev;
+	host->mmc->actual_clock = 0;
+
+	gl9755_disable_ssc_pll(pdev);
+	sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
+
+	if (clock == 0)
+		return;
+
+	clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
+	if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
+		host->mmc->actual_clock = 205000000;
+		gl9755_set_ssc_pll_205mhz(pdev);
+	}
+
+	sdhci_enable_clk(host, clk);
+}
+
 static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
 {
 	struct sdhci_host *host = slot->host;
@@ -440,7 +656,7 @@ static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot)
 }
 
 static const struct sdhci_ops sdhci_gl9755_ops = {
-	.set_clock		= sdhci_set_clock,
+	.set_clock		= sdhci_gl9755_set_clock,
 	.enable_dma		= sdhci_pci_enable_dma,
 	.set_bus_width		= sdhci_set_bus_width,
 	.reset			= sdhci_reset,
@@ -460,7 +676,7 @@ const struct sdhci_pci_fixes sdhci_gl9755 = {
 
 static const struct sdhci_ops sdhci_gl9750_ops = {
 	.read_l                 = sdhci_gl9750_readl,
-	.set_clock		= sdhci_set_clock,
+	.set_clock		= sdhci_gl9750_set_clock,
 	.enable_dma		= sdhci_pci_enable_dma,
 	.set_bus_width		= sdhci_set_bus_width,
 	.reset			= sdhci_gl9750_reset,
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] mmc: sdhci-pci-gli: Set SDR104's clock to 205MHz and enable SSC for GL975x
  2020-07-17  3:33 [PATCH] mmc: sdhci-pci-gli: Set SDR104's clock to 205MHz and enable SSC for GL975x Ben Chuang
@ 2020-08-05  6:33 ` Ulf Hansson
  2020-10-12  8:41   ` Ben Chuang
  0 siblings, 1 reply; 5+ messages in thread
From: Ulf Hansson @ 2020-08-05  6:33 UTC (permalink / raw)
  To: Ben Chuang
  Cc: Adrian Hunter, linux-mmc, Linux Kernel Mailing List, Ben Chuang,
	greg.tu, SeanHY.Chen

On Fri, 17 Jul 2020 at 05:33, Ben Chuang <benchuanggli@gmail.com> wrote:
>
> From: Ben Chuang <ben.chuang@genesyslogic.com.tw>
>
> Set SDR104's clock to 205MHz and enable SSC for GL9750 and GL9755
>
> Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>

Applied for next (a while ago), thanks!

Kind regards
Uffe


> ---
>  drivers/mmc/host/sdhci-pci-gli.c | 220 ++++++++++++++++++++++++++++++-
>  1 file changed, 218 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
> index ca0166d9bf82..5da2b06d84ae 100644
> --- a/drivers/mmc/host/sdhci-pci-gli.c
> +++ b/drivers/mmc/host/sdhci-pci-gli.c
> @@ -31,10 +31,18 @@
>  #define   SDHCI_GLI_9750_ALL_RST      (BIT(24)|BIT(25)|BIT(28)|BIT(30))
>
>  #define SDHCI_GLI_9750_PLL           0x864
> +#define   SDHCI_GLI_9750_PLL_LDIV       GENMASK(9, 0)
> +#define   SDHCI_GLI_9750_PLL_PDIV       GENMASK(14, 12)
> +#define   SDHCI_GLI_9750_PLL_DIR        BIT(15)
>  #define   SDHCI_GLI_9750_PLL_TX2_INV    BIT(23)
>  #define   SDHCI_GLI_9750_PLL_TX2_DLY    GENMASK(22, 20)
>  #define   GLI_9750_PLL_TX2_INV_VALUE    0x1
>  #define   GLI_9750_PLL_TX2_DLY_VALUE    0x0
> +#define   SDHCI_GLI_9750_PLLSSC_STEP    GENMASK(28, 24)
> +#define   SDHCI_GLI_9750_PLLSSC_EN      BIT(31)
> +
> +#define SDHCI_GLI_9750_PLLSSC        0x86C
> +#define   SDHCI_GLI_9750_PLLSSC_PPM    GENMASK(31, 16)
>
>  #define SDHCI_GLI_9750_SW_CTRL      0x874
>  #define   SDHCI_GLI_9750_SW_CTRL_4    GENMASK(7, 6)
> @@ -76,6 +84,21 @@
>  #define PCIE_GLI_9763E_SCR      0x8E0
>  #define   GLI_9763E_SCR_AXI_REQ           BIT(9)
>
> +#define PCI_GLI_9755_WT       0x800
> +#define   PCI_GLI_9755_WT_EN    BIT(0)
> +#define   GLI_9755_WT_EN_ON     0x1
> +#define   GLI_9755_WT_EN_OFF    0x0
> +
> +#define PCI_GLI_9755_PLL            0x64
> +#define   PCI_GLI_9755_PLL_LDIV       GENMASK(9, 0)
> +#define   PCI_GLI_9755_PLL_PDIV       GENMASK(14, 12)
> +#define   PCI_GLI_9755_PLL_DIR        BIT(15)
> +#define   PCI_GLI_9755_PLLSSC_STEP    GENMASK(28, 24)
> +#define   PCI_GLI_9755_PLLSSC_EN      BIT(31)
> +
> +#define PCI_GLI_9755_PLLSSC        0x68
> +#define   PCI_GLI_9755_PLLSSC_PPM    GENMASK(15, 0)
> +
>  #define GLI_MAX_TUNING_LOOP 40
>
>  /* Genesys Logic chipset */
> @@ -280,6 +303,84 @@ static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode)
>         return 0;
>  }
>
> +static void gl9750_disable_ssc_pll(struct sdhci_host *host)
> +{
> +       u32 pll;
> +
> +       gl9750_wt_on(host);
> +       pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
> +       pll &= ~(SDHCI_GLI_9750_PLL_DIR | SDHCI_GLI_9750_PLLSSC_EN);
> +       sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
> +       gl9750_wt_off(host);
> +}
> +
> +static void gl9750_set_pll(struct sdhci_host *host, u8 dir, u16 ldiv, u8 pdiv)
> +{
> +       u32 pll;
> +
> +       gl9750_wt_on(host);
> +       pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
> +       pll &= ~(SDHCI_GLI_9750_PLL_LDIV |
> +                SDHCI_GLI_9750_PLL_PDIV |
> +                SDHCI_GLI_9750_PLL_DIR);
> +       pll |= FIELD_PREP(SDHCI_GLI_9750_PLL_LDIV, ldiv) |
> +              FIELD_PREP(SDHCI_GLI_9750_PLL_PDIV, pdiv) |
> +              FIELD_PREP(SDHCI_GLI_9750_PLL_DIR, dir);
> +       sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
> +       gl9750_wt_off(host);
> +
> +       /* wait for pll stable */
> +       mdelay(1);
> +}
> +
> +static void gl9750_set_ssc(struct sdhci_host *host, u8 enable, u8 step, u16 ppm)
> +{
> +       u32 pll;
> +       u32 ssc;
> +
> +       gl9750_wt_on(host);
> +       pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
> +       ssc = sdhci_readl(host, SDHCI_GLI_9750_PLLSSC);
> +       pll &= ~(SDHCI_GLI_9750_PLLSSC_STEP |
> +                SDHCI_GLI_9750_PLLSSC_EN);
> +       ssc &= ~SDHCI_GLI_9750_PLLSSC_PPM;
> +       pll |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_STEP, step) |
> +              FIELD_PREP(SDHCI_GLI_9750_PLLSSC_EN, enable);
> +       ssc |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_PPM, ppm);
> +       sdhci_writel(host, ssc, SDHCI_GLI_9750_PLLSSC);
> +       sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
> +       gl9750_wt_off(host);
> +}
> +
> +static void gl9750_set_ssc_pll_205mhz(struct sdhci_host *host)
> +{
> +       /* set pll to 205MHz and enable ssc */
> +       gl9750_set_ssc(host, 0x1, 0x1F, 0xFFE7);
> +       gl9750_set_pll(host, 0x1, 0x246, 0x0);
> +}
> +
> +static void sdhci_gl9750_set_clock(struct sdhci_host *host, unsigned int clock)
> +{
> +       struct mmc_ios *ios = &host->mmc->ios;
> +       u16 clk;
> +
> +       host->mmc->actual_clock = 0;
> +
> +       gl9750_disable_ssc_pll(host);
> +       sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
> +
> +       if (clock == 0)
> +               return;
> +
> +       clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
> +       if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
> +               host->mmc->actual_clock = 205000000;
> +               gl9750_set_ssc_pll_205mhz(host);
> +       }
> +
> +       sdhci_enable_clk(host, clk);
> +}
> +
>  static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
>  {
>         int ret;
> @@ -295,6 +396,121 @@ static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
>         slot->host->irq = pci_irq_vector(slot->chip->pdev, 0);
>  }
>
> +static inline void gl9755_wt_on(struct pci_dev *pdev)
> +{
> +       u32 wt_value;
> +       u32 wt_enable;
> +
> +       pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value);
> +       wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value);
> +
> +       if (wt_enable == GLI_9755_WT_EN_ON)
> +               return;
> +
> +       wt_value &= ~PCI_GLI_9755_WT_EN;
> +       wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_ON);
> +
> +       pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value);
> +}
> +
> +static inline void gl9755_wt_off(struct pci_dev *pdev)
> +{
> +       u32 wt_value;
> +       u32 wt_enable;
> +
> +       pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value);
> +       wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value);
> +
> +       if (wt_enable == GLI_9755_WT_EN_OFF)
> +               return;
> +
> +       wt_value &= ~PCI_GLI_9755_WT_EN;
> +       wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_OFF);
> +
> +       pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value);
> +}
> +
> +static void gl9755_disable_ssc_pll(struct pci_dev *pdev)
> +{
> +       u32 pll;
> +
> +       gl9755_wt_on(pdev);
> +       pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
> +       pll &= ~(PCI_GLI_9755_PLL_DIR | PCI_GLI_9755_PLLSSC_EN);
> +       pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
> +       gl9755_wt_off(pdev);
> +}
> +
> +static void gl9755_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv)
> +{
> +       u32 pll;
> +
> +       gl9755_wt_on(pdev);
> +       pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
> +       pll &= ~(PCI_GLI_9755_PLL_LDIV |
> +                PCI_GLI_9755_PLL_PDIV |
> +                PCI_GLI_9755_PLL_DIR);
> +       pll |= FIELD_PREP(PCI_GLI_9755_PLL_LDIV, ldiv) |
> +              FIELD_PREP(PCI_GLI_9755_PLL_PDIV, pdiv) |
> +              FIELD_PREP(PCI_GLI_9755_PLL_DIR, dir);
> +       pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
> +       gl9755_wt_off(pdev);
> +
> +       /* wait for pll stable */
> +       mdelay(1);
> +}
> +
> +static void gl9755_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm)
> +{
> +       u32 pll;
> +       u32 ssc;
> +
> +       gl9755_wt_on(pdev);
> +       pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
> +       pci_read_config_dword(pdev, PCI_GLI_9755_PLLSSC, &ssc);
> +       pll &= ~(PCI_GLI_9755_PLLSSC_STEP |
> +                PCI_GLI_9755_PLLSSC_EN);
> +       ssc &= ~PCI_GLI_9755_PLLSSC_PPM;
> +       pll |= FIELD_PREP(PCI_GLI_9755_PLLSSC_STEP, step) |
> +              FIELD_PREP(PCI_GLI_9755_PLLSSC_EN, enable);
> +       ssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_PPM, ppm);
> +       pci_write_config_dword(pdev, PCI_GLI_9755_PLLSSC, ssc);
> +       pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
> +       gl9755_wt_off(pdev);
> +}
> +
> +static void gl9755_set_ssc_pll_205mhz(struct pci_dev *pdev)
> +{
> +       /* set pll to 205MHz and enable ssc */
> +       gl9755_set_ssc(pdev, 0x1, 0x1F, 0xFFE7);
> +       gl9755_set_pll(pdev, 0x1, 0x246, 0x0);
> +}
> +
> +static void sdhci_gl9755_set_clock(struct sdhci_host *host, unsigned int clock)
> +{
> +       struct sdhci_pci_slot *slot = sdhci_priv(host);
> +       struct mmc_ios *ios = &host->mmc->ios;
> +       struct pci_dev *pdev;
> +       u16 clk;
> +
> +       pdev = slot->chip->pdev;
> +       host->mmc->actual_clock = 0;
> +
> +       gl9755_disable_ssc_pll(pdev);
> +       sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
> +
> +       if (clock == 0)
> +               return;
> +
> +       clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
> +       if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
> +               host->mmc->actual_clock = 205000000;
> +               gl9755_set_ssc_pll_205mhz(pdev);
> +       }
> +
> +       sdhci_enable_clk(host, clk);
> +}
> +
>  static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
>  {
>         struct sdhci_host *host = slot->host;
> @@ -440,7 +656,7 @@ static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot)
>  }
>
>  static const struct sdhci_ops sdhci_gl9755_ops = {
> -       .set_clock              = sdhci_set_clock,
> +       .set_clock              = sdhci_gl9755_set_clock,
>         .enable_dma             = sdhci_pci_enable_dma,
>         .set_bus_width          = sdhci_set_bus_width,
>         .reset                  = sdhci_reset,
> @@ -460,7 +676,7 @@ const struct sdhci_pci_fixes sdhci_gl9755 = {
>
>  static const struct sdhci_ops sdhci_gl9750_ops = {
>         .read_l                 = sdhci_gl9750_readl,
> -       .set_clock              = sdhci_set_clock,
> +       .set_clock              = sdhci_gl9750_set_clock,
>         .enable_dma             = sdhci_pci_enable_dma,
>         .set_bus_width          = sdhci_set_bus_width,
>         .reset                  = sdhci_gl9750_reset,
> --
> 2.27.0
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] mmc: sdhci-pci-gli: Set SDR104's clock to 205MHz and enable SSC for GL975x
  2020-08-05  6:33 ` Ulf Hansson
@ 2020-10-12  8:41   ` Ben Chuang
  2020-10-12 10:25     ` Ulf Hansson
  0 siblings, 1 reply; 5+ messages in thread
From: Ben Chuang @ 2020-10-12  8:41 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Adrian Hunter, linux-mmc, Linux Kernel Mailing List, Ben Chuang,
	greg.tu, SeanHY.Chen

Hi Ulf,

Regarding this patch, we also want to fix the EMI of one hardware
using the old version(such as v5.4).
Is there a chance to append a Fixes tag on this patch ?
Or what should I do ?

Best Regards,
Ben

On Wed, Aug 5, 2020 at 2:34 PM Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
> On Fri, 17 Jul 2020 at 05:33, Ben Chuang <benchuanggli@gmail.com> wrote:
> >
> > From: Ben Chuang <ben.chuang@genesyslogic.com.tw>
> >
> > Set SDR104's clock to 205MHz and enable SSC for GL9750 and GL9755
> >
> > Signed-off-by: Ben Chuang <ben.chuang@genesyslogic.com.tw>
>
> Applied for next (a while ago), thanks!
>
> Kind regards
> Uffe
>
>
> > ---
> >  drivers/mmc/host/sdhci-pci-gli.c | 220 ++++++++++++++++++++++++++++++-
> >  1 file changed, 218 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/mmc/host/sdhci-pci-gli.c b/drivers/mmc/host/sdhci-pci-gli.c
> > index ca0166d9bf82..5da2b06d84ae 100644
> > --- a/drivers/mmc/host/sdhci-pci-gli.c
> > +++ b/drivers/mmc/host/sdhci-pci-gli.c
> > @@ -31,10 +31,18 @@
> >  #define   SDHCI_GLI_9750_ALL_RST      (BIT(24)|BIT(25)|BIT(28)|BIT(30))
> >
> >  #define SDHCI_GLI_9750_PLL           0x864
> > +#define   SDHCI_GLI_9750_PLL_LDIV       GENMASK(9, 0)
> > +#define   SDHCI_GLI_9750_PLL_PDIV       GENMASK(14, 12)
> > +#define   SDHCI_GLI_9750_PLL_DIR        BIT(15)
> >  #define   SDHCI_GLI_9750_PLL_TX2_INV    BIT(23)
> >  #define   SDHCI_GLI_9750_PLL_TX2_DLY    GENMASK(22, 20)
> >  #define   GLI_9750_PLL_TX2_INV_VALUE    0x1
> >  #define   GLI_9750_PLL_TX2_DLY_VALUE    0x0
> > +#define   SDHCI_GLI_9750_PLLSSC_STEP    GENMASK(28, 24)
> > +#define   SDHCI_GLI_9750_PLLSSC_EN      BIT(31)
> > +
> > +#define SDHCI_GLI_9750_PLLSSC        0x86C
> > +#define   SDHCI_GLI_9750_PLLSSC_PPM    GENMASK(31, 16)
> >
> >  #define SDHCI_GLI_9750_SW_CTRL      0x874
> >  #define   SDHCI_GLI_9750_SW_CTRL_4    GENMASK(7, 6)
> > @@ -76,6 +84,21 @@
> >  #define PCIE_GLI_9763E_SCR      0x8E0
> >  #define   GLI_9763E_SCR_AXI_REQ           BIT(9)
> >
> > +#define PCI_GLI_9755_WT       0x800
> > +#define   PCI_GLI_9755_WT_EN    BIT(0)
> > +#define   GLI_9755_WT_EN_ON     0x1
> > +#define   GLI_9755_WT_EN_OFF    0x0
> > +
> > +#define PCI_GLI_9755_PLL            0x64
> > +#define   PCI_GLI_9755_PLL_LDIV       GENMASK(9, 0)
> > +#define   PCI_GLI_9755_PLL_PDIV       GENMASK(14, 12)
> > +#define   PCI_GLI_9755_PLL_DIR        BIT(15)
> > +#define   PCI_GLI_9755_PLLSSC_STEP    GENMASK(28, 24)
> > +#define   PCI_GLI_9755_PLLSSC_EN      BIT(31)
> > +
> > +#define PCI_GLI_9755_PLLSSC        0x68
> > +#define   PCI_GLI_9755_PLLSSC_PPM    GENMASK(15, 0)
> > +
> >  #define GLI_MAX_TUNING_LOOP 40
> >
> >  /* Genesys Logic chipset */
> > @@ -280,6 +303,84 @@ static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode)
> >         return 0;
> >  }
> >
> > +static void gl9750_disable_ssc_pll(struct sdhci_host *host)
> > +{
> > +       u32 pll;
> > +
> > +       gl9750_wt_on(host);
> > +       pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
> > +       pll &= ~(SDHCI_GLI_9750_PLL_DIR | SDHCI_GLI_9750_PLLSSC_EN);
> > +       sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
> > +       gl9750_wt_off(host);
> > +}
> > +
> > +static void gl9750_set_pll(struct sdhci_host *host, u8 dir, u16 ldiv, u8 pdiv)
> > +{
> > +       u32 pll;
> > +
> > +       gl9750_wt_on(host);
> > +       pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
> > +       pll &= ~(SDHCI_GLI_9750_PLL_LDIV |
> > +                SDHCI_GLI_9750_PLL_PDIV |
> > +                SDHCI_GLI_9750_PLL_DIR);
> > +       pll |= FIELD_PREP(SDHCI_GLI_9750_PLL_LDIV, ldiv) |
> > +              FIELD_PREP(SDHCI_GLI_9750_PLL_PDIV, pdiv) |
> > +              FIELD_PREP(SDHCI_GLI_9750_PLL_DIR, dir);
> > +       sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
> > +       gl9750_wt_off(host);
> > +
> > +       /* wait for pll stable */
> > +       mdelay(1);
> > +}
> > +
> > +static void gl9750_set_ssc(struct sdhci_host *host, u8 enable, u8 step, u16 ppm)
> > +{
> > +       u32 pll;
> > +       u32 ssc;
> > +
> > +       gl9750_wt_on(host);
> > +       pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
> > +       ssc = sdhci_readl(host, SDHCI_GLI_9750_PLLSSC);
> > +       pll &= ~(SDHCI_GLI_9750_PLLSSC_STEP |
> > +                SDHCI_GLI_9750_PLLSSC_EN);
> > +       ssc &= ~SDHCI_GLI_9750_PLLSSC_PPM;
> > +       pll |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_STEP, step) |
> > +              FIELD_PREP(SDHCI_GLI_9750_PLLSSC_EN, enable);
> > +       ssc |= FIELD_PREP(SDHCI_GLI_9750_PLLSSC_PPM, ppm);
> > +       sdhci_writel(host, ssc, SDHCI_GLI_9750_PLLSSC);
> > +       sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
> > +       gl9750_wt_off(host);
> > +}
> > +
> > +static void gl9750_set_ssc_pll_205mhz(struct sdhci_host *host)
> > +{
> > +       /* set pll to 205MHz and enable ssc */
> > +       gl9750_set_ssc(host, 0x1, 0x1F, 0xFFE7);
> > +       gl9750_set_pll(host, 0x1, 0x246, 0x0);
> > +}
> > +
> > +static void sdhci_gl9750_set_clock(struct sdhci_host *host, unsigned int clock)
> > +{
> > +       struct mmc_ios *ios = &host->mmc->ios;
> > +       u16 clk;
> > +
> > +       host->mmc->actual_clock = 0;
> > +
> > +       gl9750_disable_ssc_pll(host);
> > +       sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
> > +
> > +       if (clock == 0)
> > +               return;
> > +
> > +       clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
> > +       if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
> > +               host->mmc->actual_clock = 205000000;
> > +               gl9750_set_ssc_pll_205mhz(host);
> > +       }
> > +
> > +       sdhci_enable_clk(host, clk);
> > +}
> > +
> >  static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
> >  {
> >         int ret;
> > @@ -295,6 +396,121 @@ static void gli_pcie_enable_msi(struct sdhci_pci_slot *slot)
> >         slot->host->irq = pci_irq_vector(slot->chip->pdev, 0);
> >  }
> >
> > +static inline void gl9755_wt_on(struct pci_dev *pdev)
> > +{
> > +       u32 wt_value;
> > +       u32 wt_enable;
> > +
> > +       pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value);
> > +       wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value);
> > +
> > +       if (wt_enable == GLI_9755_WT_EN_ON)
> > +               return;
> > +
> > +       wt_value &= ~PCI_GLI_9755_WT_EN;
> > +       wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_ON);
> > +
> > +       pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value);
> > +}
> > +
> > +static inline void gl9755_wt_off(struct pci_dev *pdev)
> > +{
> > +       u32 wt_value;
> > +       u32 wt_enable;
> > +
> > +       pci_read_config_dword(pdev, PCI_GLI_9755_WT, &wt_value);
> > +       wt_enable = FIELD_GET(PCI_GLI_9755_WT_EN, wt_value);
> > +
> > +       if (wt_enable == GLI_9755_WT_EN_OFF)
> > +               return;
> > +
> > +       wt_value &= ~PCI_GLI_9755_WT_EN;
> > +       wt_value |= FIELD_PREP(PCI_GLI_9755_WT_EN, GLI_9755_WT_EN_OFF);
> > +
> > +       pci_write_config_dword(pdev, PCI_GLI_9755_WT, wt_value);
> > +}
> > +
> > +static void gl9755_disable_ssc_pll(struct pci_dev *pdev)
> > +{
> > +       u32 pll;
> > +
> > +       gl9755_wt_on(pdev);
> > +       pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
> > +       pll &= ~(PCI_GLI_9755_PLL_DIR | PCI_GLI_9755_PLLSSC_EN);
> > +       pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
> > +       gl9755_wt_off(pdev);
> > +}
> > +
> > +static void gl9755_set_pll(struct pci_dev *pdev, u8 dir, u16 ldiv, u8 pdiv)
> > +{
> > +       u32 pll;
> > +
> > +       gl9755_wt_on(pdev);
> > +       pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
> > +       pll &= ~(PCI_GLI_9755_PLL_LDIV |
> > +                PCI_GLI_9755_PLL_PDIV |
> > +                PCI_GLI_9755_PLL_DIR);
> > +       pll |= FIELD_PREP(PCI_GLI_9755_PLL_LDIV, ldiv) |
> > +              FIELD_PREP(PCI_GLI_9755_PLL_PDIV, pdiv) |
> > +              FIELD_PREP(PCI_GLI_9755_PLL_DIR, dir);
> > +       pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
> > +       gl9755_wt_off(pdev);
> > +
> > +       /* wait for pll stable */
> > +       mdelay(1);
> > +}
> > +
> > +static void gl9755_set_ssc(struct pci_dev *pdev, u8 enable, u8 step, u16 ppm)
> > +{
> > +       u32 pll;
> > +       u32 ssc;
> > +
> > +       gl9755_wt_on(pdev);
> > +       pci_read_config_dword(pdev, PCI_GLI_9755_PLL, &pll);
> > +       pci_read_config_dword(pdev, PCI_GLI_9755_PLLSSC, &ssc);
> > +       pll &= ~(PCI_GLI_9755_PLLSSC_STEP |
> > +                PCI_GLI_9755_PLLSSC_EN);
> > +       ssc &= ~PCI_GLI_9755_PLLSSC_PPM;
> > +       pll |= FIELD_PREP(PCI_GLI_9755_PLLSSC_STEP, step) |
> > +              FIELD_PREP(PCI_GLI_9755_PLLSSC_EN, enable);
> > +       ssc |= FIELD_PREP(PCI_GLI_9755_PLLSSC_PPM, ppm);
> > +       pci_write_config_dword(pdev, PCI_GLI_9755_PLLSSC, ssc);
> > +       pci_write_config_dword(pdev, PCI_GLI_9755_PLL, pll);
> > +       gl9755_wt_off(pdev);
> > +}
> > +
> > +static void gl9755_set_ssc_pll_205mhz(struct pci_dev *pdev)
> > +{
> > +       /* set pll to 205MHz and enable ssc */
> > +       gl9755_set_ssc(pdev, 0x1, 0x1F, 0xFFE7);
> > +       gl9755_set_pll(pdev, 0x1, 0x246, 0x0);
> > +}
> > +
> > +static void sdhci_gl9755_set_clock(struct sdhci_host *host, unsigned int clock)
> > +{
> > +       struct sdhci_pci_slot *slot = sdhci_priv(host);
> > +       struct mmc_ios *ios = &host->mmc->ios;
> > +       struct pci_dev *pdev;
> > +       u16 clk;
> > +
> > +       pdev = slot->chip->pdev;
> > +       host->mmc->actual_clock = 0;
> > +
> > +       gl9755_disable_ssc_pll(pdev);
> > +       sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
> > +
> > +       if (clock == 0)
> > +               return;
> > +
> > +       clk = sdhci_calc_clk(host, clock, &host->mmc->actual_clock);
> > +       if (clock == 200000000 && ios->timing == MMC_TIMING_UHS_SDR104) {
> > +               host->mmc->actual_clock = 205000000;
> > +               gl9755_set_ssc_pll_205mhz(pdev);
> > +       }
> > +
> > +       sdhci_enable_clk(host, clk);
> > +}
> > +
> >  static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot)
> >  {
> >         struct sdhci_host *host = slot->host;
> > @@ -440,7 +656,7 @@ static int gli_probe_slot_gl9763e(struct sdhci_pci_slot *slot)
> >  }
> >
> >  static const struct sdhci_ops sdhci_gl9755_ops = {
> > -       .set_clock              = sdhci_set_clock,
> > +       .set_clock              = sdhci_gl9755_set_clock,
> >         .enable_dma             = sdhci_pci_enable_dma,
> >         .set_bus_width          = sdhci_set_bus_width,
> >         .reset                  = sdhci_reset,
> > @@ -460,7 +676,7 @@ const struct sdhci_pci_fixes sdhci_gl9755 = {
> >
> >  static const struct sdhci_ops sdhci_gl9750_ops = {
> >         .read_l                 = sdhci_gl9750_readl,
> > -       .set_clock              = sdhci_set_clock,
> > +       .set_clock              = sdhci_gl9750_set_clock,
> >         .enable_dma             = sdhci_pci_enable_dma,
> >         .set_bus_width          = sdhci_set_bus_width,
> >         .reset                  = sdhci_gl9750_reset,
> > --
> > 2.27.0
> >

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] mmc: sdhci-pci-gli: Set SDR104's clock to 205MHz and enable SSC for GL975x
  2020-10-12  8:41   ` Ben Chuang
@ 2020-10-12 10:25     ` Ulf Hansson
  2020-10-12 10:42       ` Ben Chuang
  0 siblings, 1 reply; 5+ messages in thread
From: Ulf Hansson @ 2020-10-12 10:25 UTC (permalink / raw)
  To: Ben Chuang
  Cc: Adrian Hunter, linux-mmc, Linux Kernel Mailing List, Ben Chuang,
	greg.tu, SeanHY.Chen

On Mon, 12 Oct 2020 at 10:41, Ben Chuang <benchuanggli@gmail.com> wrote:
>
> Hi Ulf,
>
> Regarding this patch, we also want to fix the EMI of one hardware
> using the old version(such as v5.4).
> Is there a chance to append a Fixes tag on this patch ?

Unfortunately no. $subject patch is a part of the pull request with
mmc updates for v5.10, that I just sent to Linus.

> Or what should I do ?

If you think that $subject patch should be included into an LTS
kernel, please send a manual backport to stable@vger.kernel.org. For
more information about the process, please have a look at
Documentation/process/stable-kernel-rules.rst

[...]

Kind regards
Uffe

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] mmc: sdhci-pci-gli: Set SDR104's clock to 205MHz and enable SSC for GL975x
  2020-10-12 10:25     ` Ulf Hansson
@ 2020-10-12 10:42       ` Ben Chuang
  0 siblings, 0 replies; 5+ messages in thread
From: Ben Chuang @ 2020-10-12 10:42 UTC (permalink / raw)
  To: Ulf Hansson
  Cc: Adrian Hunter, linux-mmc, Linux Kernel Mailing List, Ben Chuang,
	greg.tu, SeanHY.Chen

Hi Ulf,

On Mon, Oct 12, 2020 at 6:25 PM Ulf Hansson <ulf.hansson@linaro.org> wrote:
>
> On Mon, 12 Oct 2020 at 10:41, Ben Chuang <benchuanggli@gmail.com> wrote:
> >
> > Hi Ulf,
> >
> > Regarding this patch, we also want to fix the EMI of one hardware
> > using the old version(such as v5.4).
> > Is there a chance to append a Fixes tag on this patch ?
>
> Unfortunately no. $subject patch is a part of the pull request with
> mmc updates for v5.10, that I just sent to Linus.
>
> > Or what should I do ?
>
> If you think that $subject patch should be included into an LTS
> kernel, please send a manual backport to stable@vger.kernel.org. For
> more information about the process, please have a look at
> Documentation/process/stable-kernel-rules.rst
>
> [...]

I got it. Thanks for your answer.

Best regards,
Ben

>
> Kind regards
> Uffe

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2020-10-12 10:42 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-17  3:33 [PATCH] mmc: sdhci-pci-gli: Set SDR104's clock to 205MHz and enable SSC for GL975x Ben Chuang
2020-08-05  6:33 ` Ulf Hansson
2020-10-12  8:41   ` Ben Chuang
2020-10-12 10:25     ` Ulf Hansson
2020-10-12 10:42       ` Ben Chuang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).