2019-11-17 14:09:04

by Martin Blumenstingl

[permalink] [raw]
Subject: [PATCH v3 0/2] add the DDR clock controller on Meson8 and Meson8b

Meson8 and Meson8b SoCs embed a DDR clock controller in their MMCBUS
registers. This series:
- adds support for this DDR clock controller (patches 0 and 1)
- wires up the DDR PLL as input for two audio clocks (patches 2 and 3)
- adds the DDR clock controller to meson8.dtsi and meson8b.dtsi

Special thanks go out to Alexandre Mergnat for switching the Amlogic
clock drivers over to parent_hws and parent_data. That made this series
a lot easier for me!

This series depends on v3 my other series from [0]:
"provide the XTAL clock via OF on Meson8/8b/8m2"


Changes since v2 at [2]:
- add #include <linux/clk-provider.h> as suggested by Stephen Boyd
- drop unused includes
- use devm_platform_ioremap_resource instead of open-coding it as
suggested by Stephen Boyd
- drop trailing comma after sentinel element as suggested by Stephen
Boyd
- dropped patch #3 "clk: meson: meson8b: use of_clk_hw_register to
register the clocks" because it's now moved to my other series at
[0]
- dropped dts changes so this series exclusively targets clk-meson

Changes since v1 at [1]:
- fixed the license of the .yaml binding and added Rob's Reviewed-by
- drop unused syscon.h include (spotted by Jerome - thanks)
- drop fast_io from regmap_config and add max_register as suggested
by Jerome
- dropped original patch #4 "clk: meson: meson8b: add the ddr_pll
input for the audio clocks" because I could not test that yet (that
patch was a forward-port from Amlogic's 3.10 BSP kernel)


[0] https://patchwork.kernel.org/cover/11248377/
[1] https://patchwork.kernel.org/cover/11155553/
[2] https://patchwork.kernel.org/cover/11214227/


Martin Blumenstingl (2):
dt-bindings: clock: add the Amlogic Meson8 DDR clock controller
binding
clk: meson: add a driver for the Meson8/8b/8m2 DDR clock controller

.../clock/amlogic,meson8-ddr-clkc.yaml | 50 ++++++
drivers/clk/meson/Makefile | 2 +-
drivers/clk/meson/meson8-ddr.c | 149 ++++++++++++++++++
include/dt-bindings/clock/meson8-ddr-clkc.h | 4 +
4 files changed, 204 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml
create mode 100644 drivers/clk/meson/meson8-ddr.c
create mode 100644 include/dt-bindings/clock/meson8-ddr-clkc.h

--
2.24.0


2019-11-17 14:09:20

by Martin Blumenstingl

[permalink] [raw]
Subject: [PATCH v3 1/2] dt-bindings: clock: add the Amlogic Meson8 DDR clock controller binding

Amlogic Meson8, Meson8b and Meson8m2 SoCs have a DDR clock controller in
the MMCBUS registers. There is no public documentation on this, but the
GPL u-boot sources from the Amlogic BSP show that:
- it uses the same XTAL input as the main clock controller
- it contains a PLL which seems to be implemented just like the other
PLLs in this SoC
- there is a power-of-two PLL post-divider

Add the documentation and header file for this DDR clock controller.

Reviewed-by: Rob Herring <[email protected]>
Acked-by: Stephen Boyd <[email protected]>
Signed-off-by: Martin Blumenstingl <[email protected]>
---
.../clock/amlogic,meson8-ddr-clkc.yaml | 50 +++++++++++++++++++
include/dt-bindings/clock/meson8-ddr-clkc.h | 4 ++
2 files changed, 54 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml
create mode 100644 include/dt-bindings/clock/meson8-ddr-clkc.h

diff --git a/Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml
new file mode 100644
index 000000000000..4b8669f870ec
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/amlogic,meson8-ddr-clkc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic DDR Clock Controller Device Tree Bindings
+
+maintainers:
+ - Martin Blumenstingl <[email protected]>
+
+properties:
+ compatible:
+ enum:
+ - amlogic,meson8-ddr-clkc
+ - amlogic,meson8b-ddr-clkc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: xtal
+
+ "#clock-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ ddr_clkc: clock-controller@400 {
+ compatible = "amlogic,meson8-ddr-clkc";
+ reg = <0x400 0x20>;
+ clocks = <&xtal>;
+ clock-names = "xtal";
+ #clock-cells = <1>;
+ };
+
+...
diff --git a/include/dt-bindings/clock/meson8-ddr-clkc.h b/include/dt-bindings/clock/meson8-ddr-clkc.h
new file mode 100644
index 000000000000..a8e0fa2987ab
--- /dev/null
+++ b/include/dt-bindings/clock/meson8-ddr-clkc.h
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#define DDR_CLKID_DDR_PLL_DCO 0
+#define DDR_CLKID_DDR_PLL 1
--
2.24.0

2019-11-17 14:10:04

by Martin Blumenstingl

[permalink] [raw]
Subject: [PATCH v3 2/2] clk: meson: add a driver for the Meson8/8b/8m2 DDR clock controller

The Meson8/Meson8b/Meson8m2 SoCs embed a DDR clock controller in the
MMCBUS registers. There is no public documentation, but the u-boot GPL
sources from the Amlogic BSP show that the DDR clock controller is
identical on all three SoCs:
#define CFG_DDR_CLK 792
#define CFG_PLL_M (((CFG_DDR_CLK/12)*12)/24)
#define CFG_PLL_N 1
#define CFG_PLL_OD 1

// from set_ddr_clock:
t_ddr_pll_cntl= (CFG_PLL_OD << 16)|(CFG_PLL_N<<9)|(CFG_PLL_M<<0)
writel(timing_reg->t_ddr_pll_cntl|(1<<29),AM_DDR_PLL_CNTL);
writel(readl(AM_DDR_PLL_CNTL) & (~(1<<29)),AM_DDR_PLL_CNTL);

// from hx_ddr_power_down_enter: shut down DDR PLL
writel(readl(AM_DDR_PLL_CNTL)|(1<<30),AM_DDR_PLL_CNTL);

do { ... } while((readl(AM_DDR_PLL_CNTL)&(1<<31))==0)

This translates to:
- AM_DDR_PLL_CNTL[29] is the reset bit
- AM_DDR_PLL_CNTL[30] is the enable bit
- AM_DDR_PLL_CNTL[31] is the lock bit
- AM_DDR_PLL_CNTL[8:0] is the m value (assuming the width is 9 bits
based on the start of the n value)
- AM_DDR_PLL_CNTL[13:9] is the n value (assuming the width is 5 bits
based on the start of the od)
- AM_DDR_PLL_CNTL[17:16] is the od (assuming the width is 2 bits based
on other PLLs on this SoC)

Add a driver for this PLL setup because it's used as one of the inputs
of the audio clocks. There may be more clocks inside that clock
controller - those can be added in subsequent patches.

Signed-off-by: Martin Blumenstingl <[email protected]>
---
drivers/clk/meson/Makefile | 2 +-
drivers/clk/meson/meson8-ddr.c | 149 +++++++++++++++++++++++++++++++++
2 files changed, 150 insertions(+), 1 deletion(-)
create mode 100644 drivers/clk/meson/meson8-ddr.c

diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index 3939f218587a..6eca2a406ee3 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -18,4 +18,4 @@ obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
-obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
+obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o
diff --git a/drivers/clk/meson/meson8-ddr.c b/drivers/clk/meson/meson8-ddr.c
new file mode 100644
index 000000000000..4b73ea244b63
--- /dev/null
+++ b/drivers/clk/meson/meson8-ddr.c
@@ -0,0 +1,149 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Amlogic Meson8 DDR clock controller
+ *
+ * Copyright (C) 2019 Martin Blumenstingl <[email protected]>
+ */
+
+#include <dt-bindings/clock/meson8-ddr-clkc.h>
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-regmap.h"
+#include "clk-pll.h"
+
+#define AM_DDR_PLL_CNTL 0x00
+#define AM_DDR_PLL_CNTL1 0x04
+#define AM_DDR_PLL_CNTL2 0x08
+#define AM_DDR_PLL_CNTL3 0x0c
+#define AM_DDR_PLL_CNTL4 0x10
+#define AM_DDR_PLL_STS 0x14
+#define DDR_CLK_CNTL 0x18
+#define DDR_CLK_STS 0x1c
+
+static struct clk_regmap meson8_ddr_pll_dco = {
+ .data = &(struct meson_clk_pll_data){
+ .en = {
+ .reg_off = AM_DDR_PLL_CNTL,
+ .shift = 30,
+ .width = 1,
+ },
+ .m = {
+ .reg_off = AM_DDR_PLL_CNTL,
+ .shift = 0,
+ .width = 9,
+ },
+ .n = {
+ .reg_off = AM_DDR_PLL_CNTL,
+ .shift = 9,
+ .width = 5,
+ },
+ .l = {
+ .reg_off = AM_DDR_PLL_CNTL,
+ .shift = 31,
+ .width = 1,
+ },
+ .rst = {
+ .reg_off = AM_DDR_PLL_CNTL,
+ .shift = 29,
+ .width = 1,
+ },
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ddr_pll_dco",
+ .ops = &meson_clk_pll_ro_ops,
+ .parent_data = &(const struct clk_parent_data) {
+ .fw_name = "xtal",
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_regmap meson8_ddr_pll = {
+ .data = &(struct clk_regmap_div_data){
+ .offset = AM_DDR_PLL_CNTL,
+ .shift = 16,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ },
+ .hw.init = &(struct clk_init_data){
+ .name = "ddr_pll",
+ .ops = &clk_regmap_divider_ro_ops,
+ .parent_hws = (const struct clk_hw *[]) {
+ &meson8_ddr_pll_dco.hw
+ },
+ .num_parents = 1,
+ },
+};
+
+static struct clk_hw_onecell_data meson8_ddr_clk_hw_onecell_data = {
+ .hws = {
+ [DDR_CLKID_DDR_PLL_DCO] = &meson8_ddr_pll_dco.hw,
+ [DDR_CLKID_DDR_PLL] = &meson8_ddr_pll.hw,
+ },
+ .num = 2,
+};
+
+static struct clk_regmap *const meson8_ddr_clk_regmaps[] = {
+ &meson8_ddr_pll_dco,
+ &meson8_ddr_pll,
+};
+
+static const struct regmap_config meson8_ddr_clkc_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = DDR_CLK_STS,
+};
+
+static int meson8_ddr_clkc_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ void __iomem *base;
+ struct clk_hw *hw;
+ int ret, i;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ regmap = devm_regmap_init_mmio(&pdev->dev, base,
+ &meson8_ddr_clkc_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ /* Populate regmap */
+ for (i = 0; i < ARRAY_SIZE(meson8_ddr_clk_regmaps); i++)
+ meson8_ddr_clk_regmaps[i]->map = regmap;
+
+ /* Register all clks */
+ for (i = 0; i < meson8_ddr_clk_hw_onecell_data.num; i++) {
+ hw = meson8_ddr_clk_hw_onecell_data.hws[i];
+
+ ret = devm_clk_hw_register(&pdev->dev, hw);
+ if (ret) {
+ dev_err(&pdev->dev, "Clock registration failed\n");
+ return ret;
+ }
+ }
+
+ return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
+ &meson8_ddr_clk_hw_onecell_data);
+}
+
+static const struct of_device_id meson8_ddr_clkc_match_table[] = {
+ { .compatible = "amlogic,meson8-ddr-clkc" },
+ { .compatible = "amlogic,meson8b-ddr-clkc" },
+ { /* sentinel */ }
+};
+
+static struct platform_driver meson8_ddr_clkc_driver = {
+ .probe = meson8_ddr_clkc_probe,
+ .driver = {
+ .name = "meson8-ddr-clkc",
+ .of_match_table = meson8_ddr_clkc_match_table,
+ },
+};
+
+builtin_platform_driver(meson8_ddr_clkc_driver);
--
2.24.0

2019-11-18 09:57:04

by Jerome Brunet

[permalink] [raw]
Subject: Re: [PATCH v3 0/2] add the DDR clock controller on Meson8 and Meson8b


On Sun 17 Nov 2019 at 15:07, Martin Blumenstingl <[email protected]> wrote:

> Meson8 and Meson8b SoCs embed a DDR clock controller in their MMCBUS
> registers. This series:
> - adds support for this DDR clock controller (patches 0 and 1)
> - wires up the DDR PLL as input for two audio clocks (patches 2 and 3)
> - adds the DDR clock controller to meson8.dtsi and meson8b.dtsi
>
> Special thanks go out to Alexandre Mergnat for switching the Amlogic
> clock drivers over to parent_hws and parent_data. That made this series
> a lot easier for me!
>
> This series depends on v3 my other series from [0]:
> "provide the XTAL clock via OF on Meson8/8b/8m2"
>
>
> Changes since v2 at [2]:
> - add #include <linux/clk-provider.h> as suggested by Stephen Boyd
> - drop unused includes
> - use devm_platform_ioremap_resource instead of open-coding it as
> suggested by Stephen Boyd
> - drop trailing comma after sentinel element as suggested by Stephen
> Boyd
> - dropped patch #3 "clk: meson: meson8b: use of_clk_hw_register to
> register the clocks" because it's now moved to my other series at
> [0]
> - dropped dts changes so this series exclusively targets clk-meson
>
> Changes since v1 at [1]:
> - fixed the license of the .yaml binding and added Rob's Reviewed-by
> - drop unused syscon.h include (spotted by Jerome - thanks)
> - drop fast_io from regmap_config and add max_register as suggested
> by Jerome
> - dropped original patch #4 "clk: meson: meson8b: add the ddr_pll
> input for the audio clocks" because I could not test that yet (that
> patch was a forward-port from Amlogic's 3.10 BSP kernel)
>
>
> [0] https://patchwork.kernel.org/cover/11248377/
> [1] https://patchwork.kernel.org/cover/11155553/
> [2] https://patchwork.kernel.org/cover/11214227/
>
>
> Martin Blumenstingl (2):
> dt-bindings: clock: add the Amlogic Meson8 DDR clock controller
> binding
> clk: meson: add a driver for the Meson8/8b/8m2 DDR clock controller
>
> .../clock/amlogic,meson8-ddr-clkc.yaml | 50 ++++++
> drivers/clk/meson/Makefile | 2 +-
> drivers/clk/meson/meson8-ddr.c | 149 ++++++++++++++++++
> include/dt-bindings/clock/meson8-ddr-clkc.h | 4 +
> 4 files changed, 204 insertions(+), 1 deletion(-)
> create mode 100644 Documentation/devicetree/bindings/clock/amlogic,meson8-ddr-clkc.yaml
> create mode 100644 drivers/clk/meson/meson8-ddr.c
> create mode 100644 include/dt-bindings/clock/meson8-ddr-clkc.h

Applied for v5.6
Please note this will get rebased once v5.5-rc1 is out