Tegra20 External Memory Controller driver
Subsystems (5)
v3 cover Tegra20 External Memory Controller driver
Hello,
Couple years ago the Tegra20 EMC driver was removed from the kernel due to incompatible changes in the Tegra's clock driver. This patchset introduces a modernized EMC driver. Currently the sole purpose of the driver is to initialize DRAM frequency to maximum rate during of the kernels boot-up. Later we may consider implementing dynamic memory frequency scaling, utilizing functionality provided by this driver.
Changelog:
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 | 574 ++++++++++++++++++
6 files changed, 627 insertions(+), 10 deletions(-)
rename Documentation/devicetree/bindings/{arm/tegra => memory-controllers}/nvidia,tegra20-emc.txt (95%)
create mode 100644 drivers/memory/tegra/tegra20-emc.cSignature · 1 line
2.17.1
PATCH v3 1/8 dt: bindings: tegra20-emc: Document interrupt property
EMC has a dedicated interrupt that is used to notify about completion of HW operations. Document the interrupt property.
--- .../devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt | 2 ++ 1 file changed, 2 insertions(+)
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt +2 -0
@@ -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>; }
Signature · 1 line
2.17.1
PATCH v3 2/8 dt: bindings: tegra20-emc: Document clock property
In reply to Dmitry OsipenkoEmbedded memory controller has a corresponding clock, document the clock property.
--- .../devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt | 2 ++ 1 file changed, 2 insertions(+)
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt +2 -0
@@ -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>; }
Signature · 1 line
2.17.1
Re: [PATCH v3 2/8] dt: bindings: tegra20-emc: Document clock property
Quoted 7 lines · Dmitry Osipenko
Embedded memory controller has a corresponding clock, document the clock property.
Signed-off-by Dmitry Osipenko <[email protected]>--- .../devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt | 2 ++ 1 file changed, 2 insertions(+)
PATCH v3 3/8 dt: bindings: Move tegra20-emc binding to memory-controllers directory
In reply to Dmitry OsipenkoMove tegra20-emc binding to the memory-controllers directory for consistency with the other Tegra memory bindings.
---
.../{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%)Documentation/devicetree/bindings/memory-controllers/nvidia,tegra20-emc.txt renamed from Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt +0 -0
Signature · 1 line
2.17.1
Re: [PATCH v3 3/8] dt: bindings: Move tegra20-emc binding to memory-controllers directory
Quoted 8 lines · Dmitry Osipenko
Move tegra20-emc binding to the memory-controllers directory for consistency with the other Tegra memory bindings.
Signed-off-by Dmitry Osipenko <[email protected]>--- .../{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%)
Thanks.
PATCH v3 4/8 ARM: dts: tegra20: Add interrupt entry to External Memory Controller
In reply to Dmitry OsipenkoAdd interrupt entry into the EMC DT node.
--- arch/arm/boot/dts/tegra20.dtsi | 1 + 1 file changed, 1 insertion(+)
arch/arm/boot/dts/tegra20.dtsi +1 -0
@@ -609,6 +609,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>; };
Signature · 1 line
2.17.1
PATCH v3 5/8 ARM: dts: tegra20: Add clock entry to External Memory Controller
In reply to Dmitry OsipenkoAdd clock entry into the EMC DT node.
--- arch/arm/boot/dts/tegra20.dtsi | 1 + 1 file changed, 1 insertion(+)
arch/arm/boot/dts/tegra20.dtsi +1 -0
@@ -610,6 +610,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>; };
Signature · 1 line
2.17.1
PATCH v3 6/8 clk: tegra20: Turn EMC clock gate into divider
In reply to Dmitry OsipenkoKernel 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.
--- drivers/clk/tegra/clk-tegra20.c | 36 ++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 10 deletions(-)
drivers/clk/tegra/clk-tegra20.c +26 -10
@@ -578,7 +578,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 )
@@ -799,6 +798,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 a distinct clocks. +*/ + clk =clk_register_divider (NULL ,"emc" ,"emc_mux" ,CLK_IS_CRITICAL , + clk_base +CLK_SOURCE_EMC ,0 ,7 , +0 , &emc_lock); + clks[TEGRA20_CLK_EMC ] = clk; +} +static void __init tegra20_periph_clk_init (void ) {struct tegra_periph_init_data *data;
@@ -812,15 +836,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,
Signature · 1 line
2.17.1
Stephen Boyd
maintainerRe: [PATCH v3 6/8] clk: tegra20: Turn EMC clock gate into divider
Quoting Dmitry Osipenko (2018-06-17 07:55:37)
Quoted 9 lines
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 <[email protected]>---
Who's supposed to apply this? Me? Thierry? The "To:" line is not useful when every maintainer is there.
drivers/clk/tegra/clk-tegr=
Quoted 1 line
drivers/clk/tegra/clk-tegr= renamed from drivers/clk/tegra/clk-tegra20.c +0
-0
a20.c
drivers/clk/tegra/clk-tegra20.c static struct tegra_periph_init_data tegra_periph_no=
Quoted 4 lines
index
cc857d4d4a86..2bd35418716a100644drivers/clk/tegra/clk-tegra20.c +0
-0@@ -799,6 +798,31 @@ static struct tegra_periph_init_data tegra_periph_no=
div_clk_list[] =3D {
drivers/clk/tegra/clk-tegra20.c static struct tegra_periph_init_data tegra_periph_no= · line 798
Quoted 1 line
drivers/clk/tegra/clk-tegra20.c +0
-0TEGRA_INIT_DATA_NODIV("disp2", mux_pllpdc_clkm, CLK_SOURCE_DISP2=
, 30, 2, 26, 0, TEGRA20_CLK_DISP2),
Quoted 4 lines
drivers/clk/tegra/clk-tegra20.c +1
-0}; = +static void __init tegra20_emc_clk_init (void )
drivers/clk/tegra/clk-tegra20.c static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
Quoted 10 lines
drivers/clk/tegra/clk-tegra20.c +10
-0+{ + struct clk *clk; + + clk =3D 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 =3D tegra_clk_register_mc("mc", "emc_mux", clk_base + CLK_SOU=
RCE_EMC,
drivers/clk/tegra/clk-tegra20.c static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
Quoted 5 lines
drivers/clk/tegra/clk-tegra20.c +5
-0+ &emc_lock); + clks[TEGRA20_CLK_MC] =3D clk; + +/* +* Note that 'emc_mux' source and 'emc' rate shouldn't be changed=
at
drivers/clk/tegra/clk-tegra20.c static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { · line 818
Quoted 2 lines
drivers/clk/tegra/clk-tegra20.c +2
-0+* the same time due to a HW bug, this won't happen because we're +* defining 'emc_mux' and 'emc' as a distinct clocks.
s/ a//
Re: [PATCH v3 6/8] clk: tegra20: Turn EMC clock gate into divider
Quoted 7 lines · On Monday, 9 July 2018 03:00:17 MSK Stephen Boyd wrote:
Quoting Dmitry Osipenko (2018-06-17 07:55:37)
Quoted 5 lines
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.
Quoted 6 lines
Quoted 3 lines
Signed-off-by Dmitry Osipenko <[email protected]>---
Who's supposed to apply this? Me? Thierry? The "To:" line is not useful when every maintainer is there.
That's up to you and Thierry to decide. Perhaps it would be less churning if you'll give your ack on the 'clk:' patches and Thierry will handle the whole series on his own.
Quoted 22 lines
Quoted 22 lines
(quoted diff) +0
-0
b/drivers/clk/tegra/clk-tegra20.cindexcc857d4d4a86..2bd35418716a100644drivers/clk/tegra/clk-tegra20.c +0
-0@@ -799,6 +798,31 @@ static struct tegra_periph_init_datategra_periph_nodiv_clk_list[] = {>
TEGRA_INIT_DATA_NODIV("disp2", mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26, 0, TEGRA20_CLK_DISP2),>
};drivers/clk/tegra/clk-tegra20.c +11
-0+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);
Quoted 8 lines
Quoted 6 lines
drivers/clk/tegra/clk-tegra20.c +4
-0+ 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 a distinct clocks.s/ a//
I can adjust the comment and re-spin the series if something more important will pop up, otherwise that could addressed while applying the patch.
PATCH v3 7/8 clk: tegra20: Check whether direct PLLM sourcing is turned off for EMC
In reply to Dmitry OsipenkoEnsure that direct PLLM sourcing is turned off for EMC as we don't support that configuration in the clk driver.
--- drivers/clk/tegra/clk-tegra20.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/clk/tegra/clk-tegra20.c +10 -0
@@ -800,7 +800,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),
@@ -812,6 +814,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
Signature · 1 line
2.17.1
PATCH v3 8/8 memory: tegra: Introduce Tegra20 EMC driver
In reply to Dmitry OsipenkoIntroduce 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.
--- drivers/memory/tegra/Kconfig | 10 + drivers/memory/tegra/Makefile | 1 + drivers/memory/tegra/tegra20-emc.c | 574 +++++++++++++++++++++++++++++ 3 files changed, 585 insertions(+) create mode 100644 drivers/memory/tegra/tegra20-emc.c
drivers/memory/tegra/Kconfig +10 -0
@@ -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
drivers/memory/tegra/Makefile +1 -0
@@ -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
drivers/memory/tegra/tegra20-emc.c new file +574 -0
574 lines not on this page · raw message
Signature · 1 line
2.17.1