All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] mmc: meson-gx: add basic tuning
@ 2017-04-04 18:58 ` Heiner Kallweit
  0 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-04-04 18:58 UTC (permalink / raw)
  To: Ulf Hansson, Kevin Hilman; +Cc: linux-mmc, linux-amlogic

With a 128GB Hardkernel eMMC card my Odroid C2 boots up to 60MHz only
(tons of CRC errors otherwise). I made some tests and with changed
clock phase configuration it runs rock-solid with 200 MHz.
Changing the clock phase configuration in general most likely wouldn't
be a good idea as this might break other combinations of MMC device and
speed.
Therefore add basic tuning. So far it changes the rx clock phase only
as default core and tx clock phase work fine.

Heiner Kallweit (2):
  mmc: meson-gx: introduce struct meson_tuning_params
  mmc: meson-gx: add basic tuning for rx clock phase

 drivers/mmc/host/meson-gx-mmc.c | 66 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 65 insertions(+), 1 deletion(-)

-- 
2.12.1


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

* [PATCH 0/2] mmc: meson-gx: add basic tuning
@ 2017-04-04 18:58 ` Heiner Kallweit
  0 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-04-04 18:58 UTC (permalink / raw)
  To: linus-amlogic

With a 128GB Hardkernel eMMC card my Odroid C2 boots up to 60MHz only
(tons of CRC errors otherwise). I made some tests and with changed
clock phase configuration it runs rock-solid with 200 MHz.
Changing the clock phase configuration in general most likely wouldn't
be a good idea as this might break other combinations of MMC device and
speed.
Therefore add basic tuning. So far it changes the rx clock phase only
as default core and tx clock phase work fine.

Heiner Kallweit (2):
  mmc: meson-gx: introduce struct meson_tuning_params
  mmc: meson-gx: add basic tuning for rx clock phase

 drivers/mmc/host/meson-gx-mmc.c | 66 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 65 insertions(+), 1 deletion(-)

-- 
2.12.1

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

* [PATCH 1/2] mmc: meson-gx: introduce struct meson_tuning_params
  2017-04-04 18:58 ` Heiner Kallweit
@ 2017-04-04 19:03   ` Heiner Kallweit
  -1 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-04-04 19:03 UTC (permalink / raw)
  To: Ulf Hansson, Kevin Hilman; +Cc: linux-mmc, linux-amlogic

Introduce struct meson_tuning_params for storing the clock phase
configurations. There's no functional change because tx and rx
clock phase were implicitely set to CLK_PHASE_0 before.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/mmc/host/meson-gx-mmc.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 0036680b..3a6e51c8 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -49,6 +49,8 @@
 #define   CLK_SRC_PLL 1    /* FCLK_DIV2 */
 #define   CLK_SRC_PLL_RATE 1000000000
 #define   CLK_CORE_PHASE_MASK GENMASK(9, 8)
+#define   CLK_TX_PHASE_MASK GENMASK(11, 10)
+#define   CLK_RX_PHASE_MASK GENMASK(13, 12)
 #define   CLK_PHASE_0 0
 #define   CLK_PHASE_90 1
 #define   CLK_PHASE_180 2
@@ -111,6 +113,12 @@
 #define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */
 #define MUX_CLK_NUM_PARENTS 2
 
+struct meson_tuning_params {
+	u8 core_phase;
+	u8 tx_phase;
+	u8 rx_phase;
+};
+
 struct meson_host {
 	struct	device		*dev;
 	struct	mmc_host	*mmc;
@@ -130,6 +138,7 @@ struct meson_host {
 	void *bounce_buf;
 	dma_addr_t bounce_dma_addr;
 
+	struct meson_tuning_params tp;
 	bool vqmmc_enabled;
 };
 
@@ -312,7 +321,9 @@ static int meson_mmc_clk_init(struct meson_host *host)
 
 	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
 	clk_reg = 0;
-	clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, CLK_PHASE_180);
+	clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, host->tp.core_phase);
+	clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, host->tp.tx_phase);
+	clk_reg |= FIELD_PREP(CLK_RX_PHASE_MASK, host->tp.rx_phase);
 	clk_reg |= FIELD_PREP(CLK_SRC_MASK, CLK_SRC_XTAL);
 	clk_reg |= FIELD_PREP(CLK_DIV_MASK, CLK_DIV_MAX);
 	clk_reg &= ~CLK_ALWAYS_ON;
@@ -757,6 +768,10 @@ static int meson_mmc_probe(struct platform_device *pdev)
 	if (ret)
 		goto free_host;
 
+	host->tp.core_phase = CLK_PHASE_180;
+	host->tp.tx_phase = CLK_PHASE_0;
+	host->tp.rx_phase = CLK_PHASE_0;
+
 	ret = meson_mmc_clk_init(host);
 	if (ret)
 		goto err_core_clk;
-- 
2.12.1



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

* [PATCH 1/2] mmc: meson-gx: introduce struct meson_tuning_params
@ 2017-04-04 19:03   ` Heiner Kallweit
  0 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-04-04 19:03 UTC (permalink / raw)
  To: linus-amlogic

Introduce struct meson_tuning_params for storing the clock phase
configurations. There's no functional change because tx and rx
clock phase were implicitely set to CLK_PHASE_0 before.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/mmc/host/meson-gx-mmc.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 0036680b..3a6e51c8 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -49,6 +49,8 @@
 #define   CLK_SRC_PLL 1    /* FCLK_DIV2 */
 #define   CLK_SRC_PLL_RATE 1000000000
 #define   CLK_CORE_PHASE_MASK GENMASK(9, 8)
+#define   CLK_TX_PHASE_MASK GENMASK(11, 10)
+#define   CLK_RX_PHASE_MASK GENMASK(13, 12)
 #define   CLK_PHASE_0 0
 #define   CLK_PHASE_90 1
 #define   CLK_PHASE_180 2
@@ -111,6 +113,12 @@
 #define SD_EMMC_CFG_CMD_GAP 16 /* in clock cycles */
 #define MUX_CLK_NUM_PARENTS 2
 
+struct meson_tuning_params {
+	u8 core_phase;
+	u8 tx_phase;
+	u8 rx_phase;
+};
+
 struct meson_host {
 	struct	device		*dev;
 	struct	mmc_host	*mmc;
@@ -130,6 +138,7 @@ struct meson_host {
 	void *bounce_buf;
 	dma_addr_t bounce_dma_addr;
 
+	struct meson_tuning_params tp;
 	bool vqmmc_enabled;
 };
 
@@ -312,7 +321,9 @@ static int meson_mmc_clk_init(struct meson_host *host)
 
 	/* init SD_EMMC_CLOCK to sane defaults w/min clock rate */
 	clk_reg = 0;
-	clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, CLK_PHASE_180);
+	clk_reg |= FIELD_PREP(CLK_CORE_PHASE_MASK, host->tp.core_phase);
+	clk_reg |= FIELD_PREP(CLK_TX_PHASE_MASK, host->tp.tx_phase);
+	clk_reg |= FIELD_PREP(CLK_RX_PHASE_MASK, host->tp.rx_phase);
 	clk_reg |= FIELD_PREP(CLK_SRC_MASK, CLK_SRC_XTAL);
 	clk_reg |= FIELD_PREP(CLK_DIV_MASK, CLK_DIV_MAX);
 	clk_reg &= ~CLK_ALWAYS_ON;
@@ -757,6 +768,10 @@ static int meson_mmc_probe(struct platform_device *pdev)
 	if (ret)
 		goto free_host;
 
+	host->tp.core_phase = CLK_PHASE_180;
+	host->tp.tx_phase = CLK_PHASE_0;
+	host->tp.rx_phase = CLK_PHASE_0;
+
 	ret = meson_mmc_clk_init(host);
 	if (ret)
 		goto err_core_clk;
-- 
2.12.1

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

* [PATCH 2/2] mmc: meson-gx: add basic tuning for rx clock phase
  2017-04-04 18:58 ` Heiner Kallweit
@ 2017-04-04 19:11   ` Heiner Kallweit
  -1 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-04-04 19:11 UTC (permalink / raw)
  To: Ulf Hansson, Kevin Hilman; +Cc: linux-mmc, linux-amlogic

This patch adds basic tuning which changes the rx clock phase only
until a working setting is found.

On a Odroid C2 with 128GB eMMC card and 200 MHz MMC clock only
180° rx clock phase make the system boot w/o CRC errors.

With other MMC devices / clock speeds this might be different,
therefore don't change the driver config in general.

When retuning skip the currently active parameter set. This avoids
the current problematic config to be chosen again if it causes CRC
errors just occasionally.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/mmc/host/meson-gx-mmc.c | 49 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 3a6e51c8..eb5ee68d 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -349,6 +349,31 @@ static int meson_mmc_clk_init(struct meson_host *host)
 	return ret;
 }
 
+static void meson_mmc_set_tuning_params(struct mmc_host *mmc)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	u32 regval;
+
+	/* stop clock */
+	regval = readl(host->regs + SD_EMMC_CFG);
+	regval |= CFG_STOP_CLOCK;
+	writel(regval, host->regs + SD_EMMC_CFG);
+
+	regval = readl(host->regs + SD_EMMC_CLOCK);
+	regval &= ~CLK_CORE_PHASE_MASK;
+	regval |= FIELD_PREP(CLK_CORE_PHASE_MASK, host->tp.core_phase);
+	regval &= ~CLK_TX_PHASE_MASK;
+	regval |= FIELD_PREP(CLK_TX_PHASE_MASK, host->tp.tx_phase);
+	regval &= ~CLK_RX_PHASE_MASK;
+	regval |= FIELD_PREP(CLK_RX_PHASE_MASK, host->tp.rx_phase);
+	writel(regval, host->regs + SD_EMMC_CLOCK);
+
+	/* start clock */
+	regval = readl(host->regs + SD_EMMC_CFG);
+	regval &= ~CFG_STOP_CLOCK;
+	writel(regval, host->regs + SD_EMMC_CFG);
+}
+
 static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct meson_host *host = mmc_priv(mmc);
@@ -682,6 +707,29 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	struct meson_tuning_params tp_old = host->tp;
+	int ret = -EINVAL, i, cmd_error;
+
+	dev_info(mmc_dev(mmc), "(re)tuning...\n");
+
+	for (i = CLK_PHASE_0; i <= CLK_PHASE_270; i++) {
+		host->tp.rx_phase = i;
+		/* exclude the active parameter set if retuning */
+		if (!memcmp(&tp_old, &host->tp, sizeof(tp_old)) &&
+		    mmc->doing_retune)
+			continue;
+		meson_mmc_set_tuning_params(mmc);
+		ret = mmc_send_tuning(mmc, opcode, &cmd_error);
+		if (!ret)
+			break;
+	}
+
+	return ret;
+}
+
 /*
  * NOTE: we only need this until the GPIO/pinctrl driver can handle
  * interrupts.  For now, the MMC core will use this for polling.
@@ -712,6 +760,7 @@ static const struct mmc_host_ops meson_mmc_ops = {
 	.request	= meson_mmc_request,
 	.set_ios	= meson_mmc_set_ios,
 	.get_cd         = meson_mmc_get_cd,
+	.execute_tuning = meson_mmc_execute_tuning,
 };
 
 static int meson_mmc_probe(struct platform_device *pdev)
-- 
2.12.1



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

* [PATCH 2/2] mmc: meson-gx: add basic tuning for rx clock phase
@ 2017-04-04 19:11   ` Heiner Kallweit
  0 siblings, 0 replies; 8+ messages in thread
From: Heiner Kallweit @ 2017-04-04 19:11 UTC (permalink / raw)
  To: linus-amlogic

This patch adds basic tuning which changes the rx clock phase only
until a working setting is found.

On a Odroid C2 with 128GB eMMC card and 200 MHz MMC clock only
180? rx clock phase make the system boot w/o CRC errors.

With other MMC devices / clock speeds this might be different,
therefore don't change the driver config in general.

When retuning skip the currently active parameter set. This avoids
the current problematic config to be chosen again if it causes CRC
errors just occasionally.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
---
 drivers/mmc/host/meson-gx-mmc.c | 49 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c
index 3a6e51c8..eb5ee68d 100644
--- a/drivers/mmc/host/meson-gx-mmc.c
+++ b/drivers/mmc/host/meson-gx-mmc.c
@@ -349,6 +349,31 @@ static int meson_mmc_clk_init(struct meson_host *host)
 	return ret;
 }
 
+static void meson_mmc_set_tuning_params(struct mmc_host *mmc)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	u32 regval;
+
+	/* stop clock */
+	regval = readl(host->regs + SD_EMMC_CFG);
+	regval |= CFG_STOP_CLOCK;
+	writel(regval, host->regs + SD_EMMC_CFG);
+
+	regval = readl(host->regs + SD_EMMC_CLOCK);
+	regval &= ~CLK_CORE_PHASE_MASK;
+	regval |= FIELD_PREP(CLK_CORE_PHASE_MASK, host->tp.core_phase);
+	regval &= ~CLK_TX_PHASE_MASK;
+	regval |= FIELD_PREP(CLK_TX_PHASE_MASK, host->tp.tx_phase);
+	regval &= ~CLK_RX_PHASE_MASK;
+	regval |= FIELD_PREP(CLK_RX_PHASE_MASK, host->tp.rx_phase);
+	writel(regval, host->regs + SD_EMMC_CLOCK);
+
+	/* start clock */
+	regval = readl(host->regs + SD_EMMC_CFG);
+	regval &= ~CFG_STOP_CLOCK;
+	writel(regval, host->regs + SD_EMMC_CFG);
+}
+
 static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct meson_host *host = mmc_priv(mmc);
@@ -682,6 +707,29 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
+static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
+{
+	struct meson_host *host = mmc_priv(mmc);
+	struct meson_tuning_params tp_old = host->tp;
+	int ret = -EINVAL, i, cmd_error;
+
+	dev_info(mmc_dev(mmc), "(re)tuning...\n");
+
+	for (i = CLK_PHASE_0; i <= CLK_PHASE_270; i++) {
+		host->tp.rx_phase = i;
+		/* exclude the active parameter set if retuning */
+		if (!memcmp(&tp_old, &host->tp, sizeof(tp_old)) &&
+		    mmc->doing_retune)
+			continue;
+		meson_mmc_set_tuning_params(mmc);
+		ret = mmc_send_tuning(mmc, opcode, &cmd_error);
+		if (!ret)
+			break;
+	}
+
+	return ret;
+}
+
 /*
  * NOTE: we only need this until the GPIO/pinctrl driver can handle
  * interrupts.  For now, the MMC core will use this for polling.
@@ -712,6 +760,7 @@ static const struct mmc_host_ops meson_mmc_ops = {
 	.request	= meson_mmc_request,
 	.set_ios	= meson_mmc_set_ios,
 	.get_cd         = meson_mmc_get_cd,
+	.execute_tuning = meson_mmc_execute_tuning,
 };
 
 static int meson_mmc_probe(struct platform_device *pdev)
-- 
2.12.1

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

* Re: [PATCH 0/2] mmc: meson-gx: add basic tuning
  2017-04-04 18:58 ` Heiner Kallweit
@ 2017-04-12 14:11   ` Ulf Hansson
  -1 siblings, 0 replies; 8+ messages in thread
From: Ulf Hansson @ 2017-04-12 14:11 UTC (permalink / raw)
  To: Heiner Kallweit; +Cc: Kevin Hilman, linux-mmc, linux-amlogic

On 4 April 2017 at 20:58, Heiner Kallweit <hkallweit1@gmail.com> wrote:
> With a 128GB Hardkernel eMMC card my Odroid C2 boots up to 60MHz only
> (tons of CRC errors otherwise). I made some tests and with changed
> clock phase configuration it runs rock-solid with 200 MHz.
> Changing the clock phase configuration in general most likely wouldn't
> be a good idea as this might break other combinations of MMC device and
> speed.
> Therefore add basic tuning. So far it changes the rx clock phase only
> as default core and tx clock phase work fine.
>
> Heiner Kallweit (2):
>   mmc: meson-gx: introduce struct meson_tuning_params
>   mmc: meson-gx: add basic tuning for rx clock phase
>
>  drivers/mmc/host/meson-gx-mmc.c | 66 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 65 insertions(+), 1 deletion(-)
>
> --
> 2.12.1
>

Thanks, applied for next!

Kind regards
Uffe

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

* [PATCH 0/2] mmc: meson-gx: add basic tuning
@ 2017-04-12 14:11   ` Ulf Hansson
  0 siblings, 0 replies; 8+ messages in thread
From: Ulf Hansson @ 2017-04-12 14:11 UTC (permalink / raw)
  To: linus-amlogic

On 4 April 2017 at 20:58, Heiner Kallweit <hkallweit1@gmail.com> wrote:
> With a 128GB Hardkernel eMMC card my Odroid C2 boots up to 60MHz only
> (tons of CRC errors otherwise). I made some tests and with changed
> clock phase configuration it runs rock-solid with 200 MHz.
> Changing the clock phase configuration in general most likely wouldn't
> be a good idea as this might break other combinations of MMC device and
> speed.
> Therefore add basic tuning. So far it changes the rx clock phase only
> as default core and tx clock phase work fine.
>
> Heiner Kallweit (2):
>   mmc: meson-gx: introduce struct meson_tuning_params
>   mmc: meson-gx: add basic tuning for rx clock phase
>
>  drivers/mmc/host/meson-gx-mmc.c | 66 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 65 insertions(+), 1 deletion(-)
>
> --
> 2.12.1
>

Thanks, applied for next!

Kind regards
Uffe

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

end of thread, other threads:[~2017-04-12 14:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-04-04 18:58 [PATCH 0/2] mmc: meson-gx: add basic tuning Heiner Kallweit
2017-04-04 18:58 ` Heiner Kallweit
2017-04-04 19:03 ` [PATCH 1/2] mmc: meson-gx: introduce struct meson_tuning_params Heiner Kallweit
2017-04-04 19:03   ` Heiner Kallweit
2017-04-04 19:11 ` [PATCH 2/2] mmc: meson-gx: add basic tuning for rx clock phase Heiner Kallweit
2017-04-04 19:11   ` Heiner Kallweit
2017-04-12 14:11 ` [PATCH 0/2] mmc: meson-gx: add basic tuning Ulf Hansson
2017-04-12 14:11   ` Ulf Hansson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.