linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/8] Tegra20 External Memory Controller driver
@ 2018-10-21 18:30 Dmitry Osipenko
  2018-10-21 18:30 ` [PATCH v6 1/8] dt: bindings: tegra20-emc: Document interrupt property Dmitry Osipenko
                   ` (7 more replies)
  0 siblings, 8 replies; 19+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 18:30 UTC (permalink / raw)
  To: Thierry Reding, Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad
  Cc: linux-tegra, linux-clk, devicetree, linux-kernel

Changelog:

v6:
        - Driver now handles "refresh request overflow" interrupt by
          reporting error message.

        - EMC rate is set during driver initialization to ensure that clock
          divider is in a proper state.

v5:
        - Fixed wrong EMC clock divider type in the "Turn EMC clock gate into
          divider" patch. It is a Tegra's fractional 7.1 divider and not a
          simple integer divider. Peter, please take a look at the change.

v4:
        - Fixed "bad of_node_put()" error which was revealed by enabling
          some extra kernel debug config options.

        - The "emc-table" DT nodes are now parsed starting from the "emc"
          node instead of the DT root.

        - Adjusted code comment in the "Turn EMC clock gate into divider"
          patch as was suggested by Stephen Boyd to the v3.

v3:
        - Handle "nvidia,use-ram-code" DT property, its handling was missed
          in the previous versions.

        - Honor "emc-tables" DT node naming which is explicitly specified
          in the DT binding, also was missed in the previous versions.

        - Two new DT binding patches: one adds the EMC clock property,
          other relocates the binding doc file to the appropriate directory.
          One new patch that adds EMC clock property to the DTS file.

        - Addressed v2 review comments from Thierry Reding. Driver does not
          preserve backwards compatibility with older device tree binding.

        - The PLL_M and PLL_P clocks are kept internal to the driver because
          after some more considering I couldn't find a really good reason why
          these clocks should be in the device tree.

        - Some minor cleanups and fixes in the drivers code.

v2:
        - Minor code cleanups like consistent use of writel_relaxed instead
          of non-relaxed version, reworded error messages, etc.

        - Factored out use_pllm_ud bit checking into a standalone patch for
          consistency.

Dmitry Osipenko (8):
  dt: bindings: tegra20-emc: Document interrupt property
  dt: bindings: tegra20-emc: Document clock property
  dt: bindings: Move tegra20-emc binding to memory-controllers directory
  ARM: dts: tegra20: Add interrupt entry to External Memory Controller
  ARM: dts: tegra20: Add clock entry to External Memory Controller
  clk: tegra20: Turn EMC clock gate into divider
  clk: tegra20: Check whether direct PLLM sourcing is turned off for EMC
  memory: tegra: Introduce Tegra20 EMC driver

 .../nvidia,tegra20-emc.txt                    |   4 +
 arch/arm/boot/dts/tegra20.dtsi                |   2 +
 drivers/clk/tegra/clk-tegra20.c               |  46 +-
 drivers/memory/tegra/Kconfig                  |  10 +
 drivers/memory/tegra/Makefile                 |   1 +
 drivers/memory/tegra/tegra20-emc.c            | 591 ++++++++++++++++++
 6 files changed, 644 insertions(+), 10 deletions(-)
 rename Documentation/devicetree/bindings/{arm/tegra => memory-controllers}/nvidia,tegra20-emc.txt (95%)
 create mode 100644 drivers/memory/tegra/tegra20-emc.c

-- 
2.19.0


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

* [PATCH v6 1/8] dt: bindings: tegra20-emc: Document interrupt property
  2018-10-21 18:30 [PATCH v6 0/8] Tegra20 External Memory Controller driver Dmitry Osipenko
@ 2018-10-21 18:30 ` Dmitry Osipenko
  2018-10-25 14:25   ` Thierry Reding
  2018-10-21 18:30 ` [PATCH v6 2/8] dt: bindings: tegra20-emc: Document clock property Dmitry Osipenko
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 18:30 UTC (permalink / raw)
  To: Thierry Reding, Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad
  Cc: linux-tegra, linux-clk, devicetree, linux-kernel

EMC has a dedicated interrupt that is used to notify about completion of
HW operations. Document the interrupt property.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 .../devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt        | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt
index 4c33b29dc660..a6fe401d0d48 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt
@@ -10,6 +10,7 @@ Properties:
   and chosen using the ramcode board selector. If omitted, only one
   set of tables can be present and said tables will be used
   irrespective of ram-code configuration.
+- interrupts : Should contain EMC General interrupt.
 
 Child device nodes describe the memory settings for different configurations and clock rates.
 
@@ -20,6 +21,7 @@ Example:
 		#size-cells = < 0 >;
 		compatible = "nvidia,tegra20-emc";
 		reg = <0x7000f4000 0x200>;
+		interrupts = <0 78 0x04>;
 	}
 
 
-- 
2.19.0


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

* [PATCH v6 2/8] dt: bindings: tegra20-emc: Document clock property
  2018-10-21 18:30 [PATCH v6 0/8] Tegra20 External Memory Controller driver Dmitry Osipenko
  2018-10-21 18:30 ` [PATCH v6 1/8] dt: bindings: tegra20-emc: Document interrupt property Dmitry Osipenko
@ 2018-10-21 18:30 ` Dmitry Osipenko
  2018-10-25 14:26   ` Thierry Reding
  2018-10-21 18:30 ` [PATCH v6 3/8] dt: bindings: Move tegra20-emc binding to memory-controllers directory Dmitry Osipenko
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 18:30 UTC (permalink / raw)
  To: Thierry Reding, Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad
  Cc: linux-tegra, linux-clk, devicetree, linux-kernel

Embedded memory controller has a corresponding clock, document the clock
property.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 .../devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt        | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt
index a6fe401d0d48..add95367640b 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt
@@ -11,6 +11,7 @@ Properties:
   set of tables can be present and said tables will be used
   irrespective of ram-code configuration.
 - interrupts : Should contain EMC General interrupt.
+- clocks : Should contain EMC clock.
 
 Child device nodes describe the memory settings for different configurations and clock rates.
 
@@ -22,6 +23,7 @@ Example:
 		compatible = "nvidia,tegra20-emc";
 		reg = <0x7000f4000 0x200>;
 		interrupts = <0 78 0x04>;
+		clocks = <&tegra_car TEGRA20_CLK_EMC>;
 	}
 
 
-- 
2.19.0


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

* [PATCH v6 3/8] dt: bindings: Move tegra20-emc binding to memory-controllers directory
  2018-10-21 18:30 [PATCH v6 0/8] Tegra20 External Memory Controller driver Dmitry Osipenko
  2018-10-21 18:30 ` [PATCH v6 1/8] dt: bindings: tegra20-emc: Document interrupt property Dmitry Osipenko
  2018-10-21 18:30 ` [PATCH v6 2/8] dt: bindings: tegra20-emc: Document clock property Dmitry Osipenko
@ 2018-10-21 18:30 ` Dmitry Osipenko
  2018-10-25 14:27   ` Thierry Reding
  2018-10-21 18:30 ` [PATCH v6 4/8] ARM: dts: tegra20: Add interrupt entry to External Memory Controller Dmitry Osipenko
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 18:30 UTC (permalink / raw)
  To: Thierry Reding, Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad
  Cc: linux-tegra, linux-clk, devicetree, linux-kernel

Move tegra20-emc binding to the memory-controllers directory for
consistency with the other Tegra memory bindings.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 .../{arm/tegra => memory-controllers}/nvidia,tegra20-emc.txt      | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename Documentation/devicetree/bindings/{arm/tegra => memory-controllers}/nvidia,tegra20-emc.txt (100%)

diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt b/Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.txt
similarity index 100%
rename from Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt
rename to Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.txt
-- 
2.19.0


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

* [PATCH v6 4/8] ARM: dts: tegra20: Add interrupt entry to External Memory Controller
  2018-10-21 18:30 [PATCH v6 0/8] Tegra20 External Memory Controller driver Dmitry Osipenko
                   ` (2 preceding siblings ...)
  2018-10-21 18:30 ` [PATCH v6 3/8] dt: bindings: Move tegra20-emc binding to memory-controllers directory Dmitry Osipenko
@ 2018-10-21 18:30 ` Dmitry Osipenko
  2018-10-25 14:28   ` Thierry Reding
  2018-10-25 14:28   ` Thierry Reding
  2018-10-21 18:30 ` [PATCH v6 5/8] ARM: dts: tegra20: Add clock " Dmitry Osipenko
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 19+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 18:30 UTC (permalink / raw)
  To: Thierry Reding, Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad
  Cc: linux-tegra, linux-clk, devicetree, linux-kernel

Add interrupt entry into the EMC DT node.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 arch/arm/boot/dts/tegra20.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 20869757d32f..526f623f201a 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -632,6 +632,7 @@
 	memory-controller@7000f400 {
 		compatible = "nvidia,tegra20-emc";
 		reg = <0x7000f400 0x200>;
+		interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 	};
-- 
2.19.0


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

* [PATCH v6 5/8] ARM: dts: tegra20: Add clock entry to External Memory Controller
  2018-10-21 18:30 [PATCH v6 0/8] Tegra20 External Memory Controller driver Dmitry Osipenko
                   ` (3 preceding siblings ...)
  2018-10-21 18:30 ` [PATCH v6 4/8] ARM: dts: tegra20: Add interrupt entry to External Memory Controller Dmitry Osipenko
@ 2018-10-21 18:30 ` Dmitry Osipenko
  2018-10-25 14:29   ` Thierry Reding
  2018-10-21 18:30 ` [PATCH v6 6/8] clk: tegra20: Turn EMC clock gate into divider Dmitry Osipenko
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 19+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 18:30 UTC (permalink / raw)
  To: Thierry Reding, Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad
  Cc: linux-tegra, linux-clk, devicetree, linux-kernel

Add clock entry into the EMC DT node.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
---
 arch/arm/boot/dts/tegra20.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 526f623f201a..dcad6d6128cf 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -633,6 +633,7 @@
 		compatible = "nvidia,tegra20-emc";
 		reg = <0x7000f400 0x200>;
 		interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&tegra_car TEGRA20_CLK_EMC>;
 		#address-cells = <1>;
 		#size-cells = <0>;
 	};
-- 
2.19.0


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

* [PATCH v6 6/8] clk: tegra20: Turn EMC clock gate into divider
  2018-10-21 18:30 [PATCH v6 0/8] Tegra20 External Memory Controller driver Dmitry Osipenko
                   ` (4 preceding siblings ...)
  2018-10-21 18:30 ` [PATCH v6 5/8] ARM: dts: tegra20: Add clock " Dmitry Osipenko
@ 2018-10-21 18:30 ` Dmitry Osipenko
  2018-10-25 14:30   ` Thierry Reding
  2018-10-21 18:30 ` [PATCH v6 7/8] clk: tegra20: Check whether direct PLLM sourcing is turned off for EMC Dmitry Osipenko
  2018-10-21 18:30 ` [PATCH v6 8/8] memory: tegra: Introduce Tegra20 EMC driver Dmitry Osipenko
  7 siblings, 1 reply; 19+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 18:30 UTC (permalink / raw)
  To: Thierry Reding, Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad
  Cc: linux-tegra, linux-clk, devicetree, linux-kernel

Kernel should never gate the EMC clock as it causes immediate lockup, so
removing clk-gate functionality doesn't affect anything. Turning EMC clk
gate into divider allows to implement glitch-less EMC scaling, avoiding
reparenting to a backup clock.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Acked-by: Stephen Boyd <sboyd@kernel.org>
---
 drivers/clk/tegra/clk-tegra20.c | 36 ++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 10 deletions(-)

diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index cfde3745a0db..d3df56b6f2d1 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -584,7 +584,6 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = {
 	[tegra_clk_afi] = { .dt_id = TEGRA20_CLK_AFI, .present = true },
 	[tegra_clk_fuse] = { .dt_id = TEGRA20_CLK_FUSE, .present = true },
 	[tegra_clk_kfuse] = { .dt_id = TEGRA20_CLK_KFUSE, .present = true },
-	[tegra_clk_emc] = { .dt_id = TEGRA20_CLK_EMC, .present = true },
 };
 
 static unsigned long tegra20_clk_measure_input_freq(void)
@@ -805,6 +804,31 @@ static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
 	TEGRA_INIT_DATA_NODIV("disp2",	mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26,  0, TEGRA20_CLK_DISP2),
 };
 
+static void __init tegra20_emc_clk_init(void)
+{
+	struct clk *clk;
+
+	clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
+			       ARRAY_SIZE(mux_pllmcp_clkm),
+			       CLK_SET_RATE_NO_REPARENT,
+			       clk_base + CLK_SOURCE_EMC,
+			       30, 2, 0, &emc_lock);
+
+	clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
+				    &emc_lock);
+	clks[TEGRA20_CLK_MC] = clk;
+
+	/*
+	 * Note that 'emc_mux' source and 'emc' rate shouldn't be changed at
+	 * the same time due to a HW bug, this won't happen because we're
+	 * defining 'emc_mux' and 'emc' as distinct clocks.
+	 */
+	clk = tegra_clk_register_divider("emc", "emc_mux",
+				clk_base + CLK_SOURCE_EMC, CLK_IS_CRITICAL,
+				TEGRA_DIVIDER_INT, 0, 8, 1, &emc_lock);
+	clks[TEGRA20_CLK_EMC] = clk;
+}
+
 static void __init tegra20_periph_clk_init(void)
 {
 	struct tegra_periph_init_data *data;
@@ -818,15 +842,7 @@ static void __init tegra20_periph_clk_init(void)
 	clks[TEGRA20_CLK_AC97] = clk;
 
 	/* emc */
-	clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
-			       ARRAY_SIZE(mux_pllmcp_clkm),
-			       CLK_SET_RATE_NO_REPARENT,
-			       clk_base + CLK_SOURCE_EMC,
-			       30, 2, 0, &emc_lock);
-
-	clk = tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOURCE_EMC,
-				    &emc_lock);
-	clks[TEGRA20_CLK_MC] = clk;
+	tegra20_emc_clk_init();
 
 	/* dsi */
 	clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0,
-- 
2.19.0


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

* [PATCH v6 7/8] clk: tegra20: Check whether direct PLLM sourcing is turned off for EMC
  2018-10-21 18:30 [PATCH v6 0/8] Tegra20 External Memory Controller driver Dmitry Osipenko
                   ` (5 preceding siblings ...)
  2018-10-21 18:30 ` [PATCH v6 6/8] clk: tegra20: Turn EMC clock gate into divider Dmitry Osipenko
@ 2018-10-21 18:30 ` Dmitry Osipenko
  2018-10-25 14:31   ` Thierry Reding
  2018-10-21 18:30 ` [PATCH v6 8/8] memory: tegra: Introduce Tegra20 EMC driver Dmitry Osipenko
  7 siblings, 1 reply; 19+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 18:30 UTC (permalink / raw)
  To: Thierry Reding, Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad
  Cc: linux-tegra, linux-clk, devicetree, linux-kernel

Ensure that direct PLLM sourcing is turned off for EMC as we don't support
that configuration in the clk driver.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
Acked-by: Stephen Boyd <sboyd@kernel.org>
---
 drivers/clk/tegra/clk-tegra20.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index d3df56b6f2d1..f987ed361df6 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -806,7 +806,9 @@ static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
 
 static void __init tegra20_emc_clk_init(void)
 {
+	const u32 use_pllm_ud = BIT(29);
 	struct clk *clk;
+	u32 emc_reg;
 
 	clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
 			       ARRAY_SIZE(mux_pllmcp_clkm),
@@ -818,6 +820,14 @@ static void __init tegra20_emc_clk_init(void)
 				    &emc_lock);
 	clks[TEGRA20_CLK_MC] = clk;
 
+	/* un-divided pll_m_out0 is currently unsupported */
+	emc_reg = readl_relaxed(clk_base + CLK_SOURCE_EMC);
+	if (emc_reg & use_pllm_ud) {
+		pr_err("%s: un-divided PllM_out0 used as clock source\n",
+		       __func__);
+		return;
+	}
+
 	/*
 	 * Note that 'emc_mux' source and 'emc' rate shouldn't be changed at
 	 * the same time due to a HW bug, this won't happen because we're
-- 
2.19.0


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

* [PATCH v6 8/8] memory: tegra: Introduce Tegra20 EMC driver
  2018-10-21 18:30 [PATCH v6 0/8] Tegra20 External Memory Controller driver Dmitry Osipenko
                   ` (6 preceding siblings ...)
  2018-10-21 18:30 ` [PATCH v6 7/8] clk: tegra20: Check whether direct PLLM sourcing is turned off for EMC Dmitry Osipenko
@ 2018-10-21 18:30 ` Dmitry Osipenko
  2018-10-25 14:38   ` Thierry Reding
  7 siblings, 1 reply; 19+ messages in thread
From: Dmitry Osipenko @ 2018-10-21 18:30 UTC (permalink / raw)
  To: Thierry Reding, Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad
  Cc: linux-tegra, linux-clk, devicetree, linux-kernel

Introduce driver for the External Memory Controller (EMC) found on Tegra20
chips, which controls the external DRAM on the board. The purpose of this
driver is to program memory timing for external memory on the EMC clock
rate change.

Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
---
 drivers/memory/tegra/Kconfig       |  10 +
 drivers/memory/tegra/Makefile      |   1 +
 drivers/memory/tegra/tegra20-emc.c | 591 +++++++++++++++++++++++++++++
 3 files changed, 602 insertions(+)
 create mode 100644 drivers/memory/tegra/tegra20-emc.c

diff --git a/drivers/memory/tegra/Kconfig b/drivers/memory/tegra/Kconfig
index 6d74e499e18d..34e0b70f5c5f 100644
--- a/drivers/memory/tegra/Kconfig
+++ b/drivers/memory/tegra/Kconfig
@@ -6,6 +6,16 @@ config TEGRA_MC
 	  This driver supports the Memory Controller (MC) hardware found on
 	  NVIDIA Tegra SoCs.
 
+config TEGRA20_EMC
+	bool "NVIDIA Tegra20 External Memory Controller driver"
+	default y
+	depends on ARCH_TEGRA_2x_SOC
+	help
+	  This driver is for the External Memory Controller (EMC) found on
+	  Tegra20 chips. The EMC controls the external DRAM on the board.
+	  This driver is required to change memory timings / clock rate for
+	  external memory.
+
 config TEGRA124_EMC
 	bool "NVIDIA Tegra124 External Memory Controller driver"
 	default y
diff --git a/drivers/memory/tegra/Makefile b/drivers/memory/tegra/Makefile
index 94ab16ba075b..3971a6b7c487 100644
--- a/drivers/memory/tegra/Makefile
+++ b/drivers/memory/tegra/Makefile
@@ -10,5 +10,6 @@ tegra-mc-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
 
 obj-$(CONFIG_TEGRA_MC) += tegra-mc.o
 
+obj-$(CONFIG_TEGRA20_EMC)  += tegra20-emc.o
 obj-$(CONFIG_TEGRA124_EMC) += tegra124-emc.o
 obj-$(CONFIG_ARCH_TEGRA_186_SOC) += tegra186.o
diff --git a/drivers/memory/tegra/tegra20-emc.c b/drivers/memory/tegra/tegra20-emc.c
new file mode 100644
index 000000000000..9ee5bef49e47
--- /dev/null
+++ b/drivers/memory/tegra/tegra20-emc.c
@@ -0,0 +1,591 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Tegra20 External Memory Controller driver
+ *
+ * Author: Dmitry Osipenko <digetx@gmail.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/sort.h>
+#include <linux/types.h>
+
+#include <soc/tegra/fuse.h>
+
+#define EMC_INTSTATUS				0x000
+#define EMC_INTMASK				0x004
+#define EMC_TIMING_CONTROL			0x028
+#define EMC_RC					0x02c
+#define EMC_RFC					0x030
+#define EMC_RAS					0x034
+#define EMC_RP					0x038
+#define EMC_R2W					0x03c
+#define EMC_W2R					0x040
+#define EMC_R2P					0x044
+#define EMC_W2P					0x048
+#define EMC_RD_RCD				0x04c
+#define EMC_WR_RCD				0x050
+#define EMC_RRD					0x054
+#define EMC_REXT				0x058
+#define EMC_WDV					0x05c
+#define EMC_QUSE				0x060
+#define EMC_QRST				0x064
+#define EMC_QSAFE				0x068
+#define EMC_RDV					0x06c
+#define EMC_REFRESH				0x070
+#define EMC_BURST_REFRESH_NUM			0x074
+#define EMC_PDEX2WR				0x078
+#define EMC_PDEX2RD				0x07c
+#define EMC_PCHG2PDEN				0x080
+#define EMC_ACT2PDEN				0x084
+#define EMC_AR2PDEN				0x088
+#define EMC_RW2PDEN				0x08c
+#define EMC_TXSR				0x090
+#define EMC_TCKE				0x094
+#define EMC_TFAW				0x098
+#define EMC_TRPAB				0x09c
+#define EMC_TCLKSTABLE				0x0a0
+#define EMC_TCLKSTOP				0x0a4
+#define EMC_TREFBW				0x0a8
+#define EMC_QUSE_EXTRA				0x0ac
+#define EMC_ODT_WRITE				0x0b0
+#define EMC_ODT_READ				0x0b4
+#define EMC_FBIO_CFG5				0x104
+#define EMC_FBIO_CFG6				0x114
+#define EMC_AUTO_CAL_INTERVAL			0x2a8
+#define EMC_CFG_2				0x2b8
+#define EMC_CFG_DIG_DLL				0x2bc
+#define EMC_DLL_XFORM_DQS			0x2c0
+#define EMC_DLL_XFORM_QUSE			0x2c4
+#define EMC_ZCAL_REF_CNT			0x2e0
+#define EMC_ZCAL_WAIT_CNT			0x2e4
+#define EMC_CFG_CLKTRIM_0			0x2d0
+#define EMC_CFG_CLKTRIM_1			0x2d4
+#define EMC_CFG_CLKTRIM_2			0x2d8
+
+#define EMC_CLKCHANGE_REQ_ENABLE		BIT(0)
+#define EMC_CLKCHANGE_PD_ENABLE			BIT(1)
+#define EMC_CLKCHANGE_SR_ENABLE			BIT(2)
+
+#define EMC_TIMING_UPDATE			BIT(0)
+
+#define EMC_REFRESH_OVERFLOW_INT		BIT(3)
+#define EMC_CLKCHANGE_COMPLETE_INT		BIT(4)
+
+static const u16 emc_timing_registers[] = {
+	EMC_RC,
+	EMC_RFC,
+	EMC_RAS,
+	EMC_RP,
+	EMC_R2W,
+	EMC_W2R,
+	EMC_R2P,
+	EMC_W2P,
+	EMC_RD_RCD,
+	EMC_WR_RCD,
+	EMC_RRD,
+	EMC_REXT,
+	EMC_WDV,
+	EMC_QUSE,
+	EMC_QRST,
+	EMC_QSAFE,
+	EMC_RDV,
+	EMC_REFRESH,
+	EMC_BURST_REFRESH_NUM,
+	EMC_PDEX2WR,
+	EMC_PDEX2RD,
+	EMC_PCHG2PDEN,
+	EMC_ACT2PDEN,
+	EMC_AR2PDEN,
+	EMC_RW2PDEN,
+	EMC_TXSR,
+	EMC_TCKE,
+	EMC_TFAW,
+	EMC_TRPAB,
+	EMC_TCLKSTABLE,
+	EMC_TCLKSTOP,
+	EMC_TREFBW,
+	EMC_QUSE_EXTRA,
+	EMC_FBIO_CFG6,
+	EMC_ODT_WRITE,
+	EMC_ODT_READ,
+	EMC_FBIO_CFG5,
+	EMC_CFG_DIG_DLL,
+	EMC_DLL_XFORM_DQS,
+	EMC_DLL_XFORM_QUSE,
+	EMC_ZCAL_REF_CNT,
+	EMC_ZCAL_WAIT_CNT,
+	EMC_AUTO_CAL_INTERVAL,
+	EMC_CFG_CLKTRIM_0,
+	EMC_CFG_CLKTRIM_1,
+	EMC_CFG_CLKTRIM_2,
+};
+
+struct emc_timing {
+	unsigned long rate;
+	u32 data[ARRAY_SIZE(emc_timing_registers)];
+};
+
+struct tegra_emc {
+	struct device *dev;
+	struct completion clk_handshake_complete;
+	struct notifier_block clk_nb;
+	struct clk *backup_clk;
+	struct clk *emc_mux;
+	struct clk *pll_m;
+	struct clk *clk;
+	void __iomem *regs;
+
+	struct emc_timing *timings;
+	unsigned int num_timings;
+};
+
+static irqreturn_t tegra_emc_isr(int irq, void *data)
+{
+	struct tegra_emc *emc = data;
+	u32 intmask = EMC_REFRESH_OVERFLOW_INT | EMC_CLKCHANGE_COMPLETE_INT;
+	u32 status;
+
+	status = readl_relaxed(emc->regs + EMC_INTSTATUS) & intmask;
+	if (!status)
+		return IRQ_NONE;
+
+	/* notify about EMC-CAR handshake completion */
+	if (status & EMC_CLKCHANGE_COMPLETE_INT)
+		complete(&emc->clk_handshake_complete);
+
+	/* notify about HW problem */
+	if (status & EMC_REFRESH_OVERFLOW_INT)
+		dev_err_ratelimited(emc->dev,
+				    "refresh request overflow timeout\n");
+
+	/* clear interrupts */
+	writel_relaxed(status, emc->regs + EMC_INTSTATUS);
+
+	return IRQ_HANDLED;
+}
+
+static struct emc_timing *tegra_emc_find_timing(struct tegra_emc *emc,
+						unsigned long rate)
+{
+	struct emc_timing *timing = NULL;
+	unsigned int i;
+
+	for (i = 0; i < emc->num_timings; i++) {
+		if (emc->timings[i].rate >= rate) {
+			timing = &emc->timings[i];
+			break;
+		}
+	}
+
+	if (!timing) {
+		dev_err(emc->dev, "no timing for rate %lu\n", rate);
+		return NULL;
+	}
+
+	return timing;
+}
+
+static int emc_prepare_timing_change(struct tegra_emc *emc, unsigned long rate)
+{
+	struct emc_timing *timing = tegra_emc_find_timing(emc, rate);
+	unsigned int i;
+
+	if (!timing)
+		return -EINVAL;
+
+	dev_dbg(emc->dev, "%s: using timing rate %lu for requested rate %lu\n",
+		__func__, timing->rate, rate);
+
+	/* program shadow registers */
+	for (i = 0; i < ARRAY_SIZE(timing->data); i++)
+		writel_relaxed(timing->data[i],
+			       emc->regs + emc_timing_registers[i]);
+
+	/* wait until programming has settled */
+	readl_relaxed(emc->regs + emc_timing_registers[i - 1]);
+
+	reinit_completion(&emc->clk_handshake_complete);
+
+	return 0;
+}
+
+static int emc_complete_timing_change(struct tegra_emc *emc, bool flush)
+{
+	long timeout;
+
+	dev_dbg(emc->dev, "%s: flush %d\n", __func__, flush);
+
+	if (flush) {
+		/* manually initiate memory timing update */
+		writel_relaxed(EMC_TIMING_UPDATE,
+			       emc->regs + EMC_TIMING_CONTROL);
+		return 0;
+	}
+
+	timeout = wait_for_completion_timeout(&emc->clk_handshake_complete,
+					      usecs_to_jiffies(100));
+	if (timeout == 0) {
+		dev_err(emc->dev, "EMC-CAR handshake failed\n");
+		return -EIO;
+	} else if (timeout < 0) {
+		dev_err(emc->dev, "failed to wait for EMC-CAR handshake: %ld\n",
+			timeout);
+		return timeout;
+	}
+
+	return 0;
+}
+
+static int tegra_emc_clk_change_notify(struct notifier_block *nb,
+				       unsigned long msg, void *data)
+{
+	struct tegra_emc *emc = container_of(nb, struct tegra_emc, clk_nb);
+	struct clk_notifier_data *cnd = data;
+	int err;
+
+	switch (msg) {
+	case PRE_RATE_CHANGE:
+		err = emc_prepare_timing_change(emc, cnd->new_rate);
+		break;
+
+	case ABORT_RATE_CHANGE:
+		err = emc_prepare_timing_change(emc, cnd->old_rate);
+		if (err)
+			break;
+
+		err = emc_complete_timing_change(emc, true);
+		break;
+
+	case POST_RATE_CHANGE:
+		err = emc_complete_timing_change(emc, false);
+		break;
+
+	default:
+		return NOTIFY_DONE;
+	}
+
+	return notifier_from_errno(err);
+}
+
+static int load_one_timing_from_dt(struct tegra_emc *emc,
+				   struct emc_timing *timing,
+				   struct device_node *node)
+{
+	u32 rate;
+	int err;
+
+	if (!of_device_is_compatible(node, "nvidia,tegra20-emc-table")) {
+		dev_err(emc->dev, "incompatible DT node: %pOF\n", node);
+		return -EINVAL;
+	}
+
+	err = of_property_read_u32(node, "clock-frequency", &rate);
+	if (err) {
+		dev_err(emc->dev, "timing %pOF: failed to read rate: %d\n",
+			node, err);
+		return err;
+	}
+
+	err = of_property_read_u32_array(node, "nvidia,emc-registers",
+					 timing->data,
+					 ARRAY_SIZE(emc_timing_registers));
+	if (err) {
+		dev_err(emc->dev,
+			"timing %pOF: failed to read emc timing data: %d\n",
+			node, err);
+		return err;
+	}
+
+	/*
+	 * The EMC clock rate is twice the bus rate, and the bus rate is
+	 * measured in kHz.
+	 */
+	timing->rate = rate * 2 * 1000;
+
+	dev_dbg(emc->dev, "%s: %pOF: EMC rate %lu\n",
+		__func__, node, timing->rate);
+
+	return 0;
+}
+
+static int cmp_timings(const void *_a, const void *_b)
+{
+	const struct emc_timing *a = _a;
+	const struct emc_timing *b = _b;
+
+	if (a->rate < b->rate)
+		return -1;
+
+	if (a->rate > b->rate)
+		return 1;
+
+	return 0;
+}
+
+static int tegra_emc_load_timings_from_dt(struct tegra_emc *emc,
+					  struct device_node *node)
+{
+	struct device_node *child;
+	struct emc_timing *timing;
+	int child_count;
+	int err;
+
+	child_count = of_get_child_count(node);
+	if (!child_count) {
+		dev_err(emc->dev, "no memory timings in DT node: %pOF\n", node);
+		return -EINVAL;
+	}
+
+	emc->timings = devm_kcalloc(emc->dev, child_count, sizeof(*timing),
+				    GFP_KERNEL);
+	if (!emc->timings)
+		return -ENOMEM;
+
+	emc->num_timings = child_count;
+	timing = emc->timings;
+
+	for_each_child_of_node(node, child) {
+		err = load_one_timing_from_dt(emc, timing++, child);
+		if (err) {
+			of_node_put(child);
+			return err;
+		}
+	}
+
+	sort(emc->timings, emc->num_timings, sizeof(*timing), cmp_timings,
+	     NULL);
+
+	return 0;
+}
+
+static struct device_node *
+tegra_emc_find_node_by_ram_code(struct device *dev)
+{
+	struct device_node *np;
+	u32 value, ram_code;
+	int err;
+
+	if (!of_property_read_bool(dev->of_node, "nvidia,use-ram-code"))
+		return of_node_get(dev->of_node);
+
+	ram_code = tegra_read_ram_code();
+
+	for (np = of_find_node_by_name(dev->of_node, "emc-tables"); np;
+	     np = of_find_node_by_name(np, "emc-tables")) {
+		err = of_property_read_u32(np, "nvidia,ram-code", &value);
+		if (err || value != ram_code) {
+			of_node_put(np);
+			continue;
+		}
+
+		return np;
+	}
+
+	dev_err(dev, "no memory timings for RAM code %u found in device tree\n",
+		ram_code);
+
+	return NULL;
+}
+
+static int emc_setup_hw(struct tegra_emc *emc)
+{
+	u32 intmask = EMC_REFRESH_OVERFLOW_INT | EMC_CLKCHANGE_COMPLETE_INT;
+	u32 emc_cfg;
+
+	emc_cfg = readl_relaxed(emc->regs + EMC_CFG_2);
+
+	/*
+	 * Depending on a memory type, DRAM should enter either self-refresh
+	 * or power-down state on EMC clock change.
+	 */
+	if (!(emc_cfg & EMC_CLKCHANGE_PD_ENABLE) &&
+	    !(emc_cfg & EMC_CLKCHANGE_SR_ENABLE)) {
+		dev_err(emc->dev,
+			"bootloader didn't specify DRAM auto-suspend mode\n");
+		return -EINVAL;
+	}
+
+	/* enable EMC and CAR to handshake on PLL divider/source changes */
+	emc_cfg |= EMC_CLKCHANGE_REQ_ENABLE;
+	writel_relaxed(emc_cfg, emc->regs + EMC_CFG_2);
+
+	/* initialize interrupt */
+	writel_relaxed(intmask, emc->regs + EMC_INTMASK);
+	writel_relaxed(intmask, emc->regs + EMC_INTSTATUS);
+
+	return 0;
+}
+
+static int emc_init(struct tegra_emc *emc, unsigned long rate)
+{
+	int err;
+
+	err = clk_set_parent(emc->emc_mux, emc->backup_clk);
+	if (err) {
+		dev_err(emc->dev,
+			"failed to reparent to backup source: %d\n", err);
+		return err;
+	}
+
+	err = clk_set_rate(emc->pll_m, rate);
+	if (err) {
+		dev_err(emc->dev,
+			"failed to change pll_m rate: %d\n", err);
+		return err;
+	}
+
+	err = clk_set_parent(emc->emc_mux, emc->pll_m);
+	if (err) {
+		dev_err(emc->dev,
+			"failed to reparent to pll_m: %d\n", err);
+		return err;
+	}
+
+	err = clk_set_rate(emc->clk, rate);
+	if (err) {
+		dev_err(emc->dev,
+			"failed to change emc rate: %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+static int tegra_emc_probe(struct platform_device *pdev)
+{
+	struct device_node *np;
+	struct tegra_emc *emc;
+	struct resource *res;
+	int irq, err;
+
+	/* driver has nothing to do in a case of memory timing absence */
+	if (of_get_child_count(pdev->dev.of_node) == 0) {
+		dev_info(&pdev->dev,
+			 "EMC device tree node doesn't have memory timings\n");
+		return 0;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "interrupt not specified\n");
+		dev_err(&pdev->dev, "please update your device tree\n");
+		return irq;
+	}
+
+	np = tegra_emc_find_node_by_ram_code(&pdev->dev);
+	if (!np)
+		return -EINVAL;
+
+	emc = devm_kzalloc(&pdev->dev, sizeof(*emc), GFP_KERNEL);
+	if (!emc) {
+		of_node_put(np);
+		return -ENOMEM;
+	}
+
+	init_completion(&emc->clk_handshake_complete);
+	emc->clk_nb.notifier_call = tegra_emc_clk_change_notify;
+	emc->dev = &pdev->dev;
+
+	err = tegra_emc_load_timings_from_dt(emc, np);
+	of_node_put(np);
+	if (err)
+		return err;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	emc->regs = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(emc->regs))
+		return PTR_ERR(emc->regs);
+
+	err = emc_setup_hw(emc);
+	if (err)
+		return err;
+
+	err = devm_request_irq(&pdev->dev, irq, tegra_emc_isr, 0,
+			       dev_name(&pdev->dev), emc);
+	if (err) {
+		dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n", irq, err);
+		return err;
+	}
+
+	emc->clk = devm_clk_get(&pdev->dev, "emc");
+	if (IS_ERR(emc->clk)) {
+		err = PTR_ERR(emc->clk);
+		dev_err(&pdev->dev, "failed to get emc clock: %d\n", err);
+		return err;
+	}
+
+	emc->pll_m = clk_get_sys(NULL, "pll_m");
+	if (IS_ERR(emc->pll_m)) {
+		err = PTR_ERR(emc->pll_m);
+		dev_err(&pdev->dev, "failed to get pll_m clock: %d\n", err);
+		return err;
+	}
+
+	emc->backup_clk = clk_get_sys(NULL, "pll_p");
+	if (IS_ERR(emc->backup_clk)) {
+		err = PTR_ERR(emc->backup_clk);
+		dev_err(&pdev->dev, "failed to get pll_p clock: %d\n", err);
+		goto put_pll_m;
+	}
+
+	emc->emc_mux = clk_get_parent(emc->clk);
+	if (IS_ERR(emc->emc_mux)) {
+		err = PTR_ERR(emc->emc_mux);
+		dev_err(&pdev->dev, "failed to get emc_mux clock: %d\n", err);
+		goto put_backup;
+	}
+
+	err = clk_notifier_register(emc->clk, &emc->clk_nb);
+	if (err) {
+		dev_err(&pdev->dev, "failed to register clk notifier: %d\n",
+			err);
+		goto put_backup;
+	}
+
+	/* set DRAM clock rate to maximum */
+	err = emc_init(emc, emc->timings[emc->num_timings - 1].rate);
+	if (err) {
+		dev_err(&pdev->dev, "failed to initialize EMC clock rate: %d\n",
+			err);
+		goto unreg_notifier;
+	}
+
+	return 0;
+
+unreg_notifier:
+	clk_notifier_unregister(emc->clk, &emc->clk_nb);
+put_backup:
+	clk_put(emc->backup_clk);
+put_pll_m:
+	clk_put(emc->pll_m);
+
+	return err;
+}
+
+static const struct of_device_id tegra_emc_of_match[] = {
+	{ .compatible = "nvidia,tegra20-emc", },
+	{},
+};
+
+static struct platform_driver tegra_emc_driver = {
+	.probe = tegra_emc_probe,
+	.driver = {
+		.name = "tegra20-emc",
+		.of_match_table = tegra_emc_of_match,
+		.suppress_bind_attrs = true,
+	},
+};
+
+static int __init tegra_emc_init(void)
+{
+	return platform_driver_register(&tegra_emc_driver);
+}
+subsys_initcall(tegra_emc_init);
-- 
2.19.0


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

* Re: [PATCH v6 1/8] dt: bindings: tegra20-emc: Document interrupt property
  2018-10-21 18:30 ` [PATCH v6 1/8] dt: bindings: tegra20-emc: Document interrupt property Dmitry Osipenko
@ 2018-10-25 14:25   ` Thierry Reding
  0 siblings, 0 replies; 19+ messages in thread
From: Thierry Reding @ 2018-10-25 14:25 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad,
	linux-tegra, linux-clk, devicetree, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 524 bytes --]

On Sun, Oct 21, 2018 at 09:30:45PM +0300, Dmitry Osipenko wrote:
> EMC has a dedicated interrupt that is used to notify about completion of
> HW operations. Document the interrupt property.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> Acked-by: Rob Herring <robh@kernel.org>
> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
>  .../devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt        | 2 ++
>  1 file changed, 2 insertions(+)

Applied to for-4.21/dt-bindings, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v6 2/8] dt: bindings: tegra20-emc: Document clock property
  2018-10-21 18:30 ` [PATCH v6 2/8] dt: bindings: tegra20-emc: Document clock property Dmitry Osipenko
@ 2018-10-25 14:26   ` Thierry Reding
  0 siblings, 0 replies; 19+ messages in thread
From: Thierry Reding @ 2018-10-25 14:26 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad,
	linux-tegra, linux-clk, devicetree, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 428 bytes --]

On Sun, Oct 21, 2018 at 09:30:46PM +0300, Dmitry Osipenko wrote:
> Embedded memory controller has a corresponding clock, document the clock
> property.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
>  .../devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt        | 2 ++
>  1 file changed, 2 insertions(+)

Applied to for-4.21/dt-bindings, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v6 3/8] dt: bindings: Move tegra20-emc binding to memory-controllers directory
  2018-10-21 18:30 ` [PATCH v6 3/8] dt: bindings: Move tegra20-emc binding to memory-controllers directory Dmitry Osipenko
@ 2018-10-25 14:27   ` Thierry Reding
  0 siblings, 0 replies; 19+ messages in thread
From: Thierry Reding @ 2018-10-25 14:27 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad,
	linux-tegra, linux-clk, devicetree, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 584 bytes --]

On Sun, Oct 21, 2018 at 09:30:47PM +0300, Dmitry Osipenko wrote:
> Move tegra20-emc binding to the memory-controllers directory for
> consistency with the other Tegra memory bindings.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
>  .../{arm/tegra => memory-controllers}/nvidia,tegra20-emc.txt      | 0
>  1 file changed, 0 insertions(+), 0 deletions(-)
>  rename Documentation/devicetree/bindings/{arm/tegra => memory-controllers}/nvidia,tegra20-emc.txt (100%)

Applied to for-4.21/dt-bindings, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v6 4/8] ARM: dts: tegra20: Add interrupt entry to External Memory Controller
  2018-10-21 18:30 ` [PATCH v6 4/8] ARM: dts: tegra20: Add interrupt entry to External Memory Controller Dmitry Osipenko
@ 2018-10-25 14:28   ` Thierry Reding
  2018-10-25 14:28   ` Thierry Reding
  1 sibling, 0 replies; 19+ messages in thread
From: Thierry Reding @ 2018-10-25 14:28 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad,
	linux-tegra, linux-clk, devicetree, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 359 bytes --]

On Sun, Oct 21, 2018 at 09:30:48PM +0300, Dmitry Osipenko wrote:
> Add interrupt entry into the EMC DT node.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
>  arch/arm/boot/dts/tegra20.dtsi | 1 +
>  1 file changed, 1 insertion(+)

Applied to for-4.21/arm/dt, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v6 4/8] ARM: dts: tegra20: Add interrupt entry to External Memory Controller
  2018-10-21 18:30 ` [PATCH v6 4/8] ARM: dts: tegra20: Add interrupt entry to External Memory Controller Dmitry Osipenko
  2018-10-25 14:28   ` Thierry Reding
@ 2018-10-25 14:28   ` Thierry Reding
  1 sibling, 0 replies; 19+ messages in thread
From: Thierry Reding @ 2018-10-25 14:28 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad,
	linux-tegra, linux-clk, devicetree, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 359 bytes --]

On Sun, Oct 21, 2018 at 09:30:48PM +0300, Dmitry Osipenko wrote:
> Add interrupt entry into the EMC DT node.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
>  arch/arm/boot/dts/tegra20.dtsi | 1 +
>  1 file changed, 1 insertion(+)

Applied to for-4.21/arm/dt, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v6 5/8] ARM: dts: tegra20: Add clock entry to External Memory Controller
  2018-10-21 18:30 ` [PATCH v6 5/8] ARM: dts: tegra20: Add clock " Dmitry Osipenko
@ 2018-10-25 14:29   ` Thierry Reding
  0 siblings, 0 replies; 19+ messages in thread
From: Thierry Reding @ 2018-10-25 14:29 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad,
	linux-tegra, linux-clk, devicetree, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 297 bytes --]

On Sun, Oct 21, 2018 at 09:30:49PM +0300, Dmitry Osipenko wrote:
> Add clock entry into the EMC DT node.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> ---
>  arch/arm/boot/dts/tegra20.dtsi | 1 +
>  1 file changed, 1 insertion(+)

Applied to for-4.21/arm/dt, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v6 6/8] clk: tegra20: Turn EMC clock gate into divider
  2018-10-21 18:30 ` [PATCH v6 6/8] clk: tegra20: Turn EMC clock gate into divider Dmitry Osipenko
@ 2018-10-25 14:30   ` Thierry Reding
  0 siblings, 0 replies; 19+ messages in thread
From: Thierry Reding @ 2018-10-25 14:30 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad,
	linux-tegra, linux-clk, devicetree, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 670 bytes --]

On Sun, Oct 21, 2018 at 09:30:50PM +0300, Dmitry Osipenko wrote:
> Kernel should never gate the EMC clock as it causes immediate lockup, so
> removing clk-gate functionality doesn't affect anything. Turning EMC clk
> gate into divider allows to implement glitch-less EMC scaling, avoiding
> reparenting to a backup clock.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> Acked-by: Stephen Boyd <sboyd@kernel.org>
> ---
>  drivers/clk/tegra/clk-tegra20.c | 36 ++++++++++++++++++++++++---------
>  1 file changed, 26 insertions(+), 10 deletions(-)

Applied to for-4.21/clk, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v6 7/8] clk: tegra20: Check whether direct PLLM sourcing is turned off for EMC
  2018-10-21 18:30 ` [PATCH v6 7/8] clk: tegra20: Check whether direct PLLM sourcing is turned off for EMC Dmitry Osipenko
@ 2018-10-25 14:31   ` Thierry Reding
  0 siblings, 0 replies; 19+ messages in thread
From: Thierry Reding @ 2018-10-25 14:31 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad,
	linux-tegra, linux-clk, devicetree, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 488 bytes --]

On Sun, Oct 21, 2018 at 09:30:51PM +0300, Dmitry Osipenko wrote:
> Ensure that direct PLLM sourcing is turned off for EMC as we don't support
> that configuration in the clk driver.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> Acked-by: Stephen Boyd <sboyd@kernel.org>
> ---
>  drivers/clk/tegra/clk-tegra20.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)

Applied to for-4.21/clk, thanks.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v6 8/8] memory: tegra: Introduce Tegra20 EMC driver
  2018-10-21 18:30 ` [PATCH v6 8/8] memory: tegra: Introduce Tegra20 EMC driver Dmitry Osipenko
@ 2018-10-25 14:38   ` Thierry Reding
  2018-10-25 18:36     ` Dmitry Osipenko
  0 siblings, 1 reply; 19+ messages in thread
From: Thierry Reding @ 2018-10-25 14:38 UTC (permalink / raw)
  To: Dmitry Osipenko
  Cc: Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad,
	linux-tegra, linux-clk, devicetree, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 957 bytes --]

On Sun, Oct 21, 2018 at 09:30:52PM +0300, Dmitry Osipenko wrote:
> Introduce driver for the External Memory Controller (EMC) found on Tegra20
> chips, which controls the external DRAM on the board. The purpose of this
> driver is to program memory timing for external memory on the EMC clock
> rate change.
> 
> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
> ---
>  drivers/memory/tegra/Kconfig       |  10 +
>  drivers/memory/tegra/Makefile      |   1 +
>  drivers/memory/tegra/tegra20-emc.c | 591 +++++++++++++++++++++++++++++
>  3 files changed, 602 insertions(+)
>  create mode 100644 drivers/memory/tegra/tegra20-emc.c

Applied to for-4.21/memory, thanks.

Though I did notice that there's quite a bit of code that's very similar
between this and the existing Tegra124 driver, so I wonder if we can do
a pass over them and refactor some of it as a follow-up.

Thierry

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

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

* Re: [PATCH v6 8/8] memory: tegra: Introduce Tegra20 EMC driver
  2018-10-25 14:38   ` Thierry Reding
@ 2018-10-25 18:36     ` Dmitry Osipenko
  0 siblings, 0 replies; 19+ messages in thread
From: Dmitry Osipenko @ 2018-10-25 18:36 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Peter De Schrijver, Jonathan Hunter, Prashant Gaikwad,
	linux-tegra, linux-clk, devicetree, linux-kernel

On 10/25/18 5:38 PM, Thierry Reding wrote:
> On Sun, Oct 21, 2018 at 09:30:52PM +0300, Dmitry Osipenko wrote:
>> Introduce driver for the External Memory Controller (EMC) found on Tegra20
>> chips, which controls the external DRAM on the board. The purpose of this
>> driver is to program memory timing for external memory on the EMC clock
>> rate change.
>>
>> Signed-off-by: Dmitry Osipenko <digetx@gmail.com>
>> Acked-by: Peter De Schrijver <pdeschrijver@nvidia.com>
>> ---
>>  drivers/memory/tegra/Kconfig       |  10 +
>>  drivers/memory/tegra/Makefile      |   1 +
>>  drivers/memory/tegra/tegra20-emc.c | 591 +++++++++++++++++++++++++++++
>>  3 files changed, 602 insertions(+)
>>  create mode 100644 drivers/memory/tegra/tegra20-emc.c
> 
> Applied to for-4.21/memory, thanks.

Thank you! 

> Though I did notice that there's quite a bit of code that's very similar
> between this and the existing Tegra124 driver, so I wonder if we can do
> a pass over them and refactor some of it as a follow-up.
I don't think this will really worth the effort.

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

end of thread, other threads:[~2018-10-25 18:36 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-21 18:30 [PATCH v6 0/8] Tegra20 External Memory Controller driver Dmitry Osipenko
2018-10-21 18:30 ` [PATCH v6 1/8] dt: bindings: tegra20-emc: Document interrupt property Dmitry Osipenko
2018-10-25 14:25   ` Thierry Reding
2018-10-21 18:30 ` [PATCH v6 2/8] dt: bindings: tegra20-emc: Document clock property Dmitry Osipenko
2018-10-25 14:26   ` Thierry Reding
2018-10-21 18:30 ` [PATCH v6 3/8] dt: bindings: Move tegra20-emc binding to memory-controllers directory Dmitry Osipenko
2018-10-25 14:27   ` Thierry Reding
2018-10-21 18:30 ` [PATCH v6 4/8] ARM: dts: tegra20: Add interrupt entry to External Memory Controller Dmitry Osipenko
2018-10-25 14:28   ` Thierry Reding
2018-10-25 14:28   ` Thierry Reding
2018-10-21 18:30 ` [PATCH v6 5/8] ARM: dts: tegra20: Add clock " Dmitry Osipenko
2018-10-25 14:29   ` Thierry Reding
2018-10-21 18:30 ` [PATCH v6 6/8] clk: tegra20: Turn EMC clock gate into divider Dmitry Osipenko
2018-10-25 14:30   ` Thierry Reding
2018-10-21 18:30 ` [PATCH v6 7/8] clk: tegra20: Check whether direct PLLM sourcing is turned off for EMC Dmitry Osipenko
2018-10-25 14:31   ` Thierry Reding
2018-10-21 18:30 ` [PATCH v6 8/8] memory: tegra: Introduce Tegra20 EMC driver Dmitry Osipenko
2018-10-25 14:38   ` Thierry Reding
2018-10-25 18:36     ` Dmitry Osipenko

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).