From d1a26232c3ce1db2e7c9c114150e93a9fc6ec42e Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 31 May 2017 16:07:23 +0200 Subject: [PATCH 1/5] dt-bindings: ap806: do not depend anymore of the *-clock-output-names This patch updates the documentation according to the change made in the patch "clk: mvebu: ap806: do not depend anymore of the *-clock-output-names": the clock names are no more part of the binding. Acked-by: Rob Herring Signed-off-by: Gregory CLEMENT Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/d502b5abc68cbb5739ce72ba8be27528f9042a28.1496239589.git-series.gregory.clement@free-electrons.com --- .../bindings/arm/marvell/ap806-system-controller.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt index 8968371d84e2..3faab71dff9f 100644 --- a/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +++ b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt @@ -21,15 +21,11 @@ Required properties: "marvell,ap806-system-controller", "syscon" - reg: register area of the AP806 system controller - #clock-cells: must be set to 1 - - clock-output-names: must be defined to: - "ap-cpu-cluster-0", "ap-cpu-cluster-1", "ap-fixed", "ap-mss" Example: syscon: system-controller@6f4000 { compatible = "marvell,ap806-system-controller", "syscon"; #clock-cells = <1>; - clock-output-names = "ap-cpu-cluster-0", "ap-cpu-cluster-1", - "ap-fixed", "ap-mss"; reg = <0x6f4000 0x1000>; }; From 7e5b11afecc0f558c5a6723970770f92f2529d4e Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 31 May 2017 16:07:25 +0200 Subject: [PATCH 2/5] dt-bindings: ap806: introduce a new binding This patch updates the documentation according to the changes made in the patch "clk: mvebu: ap806: introduce a new binding" Acked-by: Rob Herring Signed-off-by: Gregory CLEMENT Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/32e35c1d5919bdf9dc7d58678f0c0b462886d03e.1496239589.git-series.gregory.clement@free-electrons.com --- .../arm/marvell/ap806-system-controller.txt | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt index 3faab71dff9f..888c50e0d64f 100644 --- a/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt +++ b/Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt @@ -7,6 +7,14 @@ registers giving access to numerous features: clocks, pin-muxing and many other SoC configuration items. This DT binding allows to describe this system controller. +For the top level node: + - compatible: must be: "syscon", "simple-mfd"; + - reg: register area of the AP806 system controller + +Clocks: +------- + + The Device Tree node representing the AP806 system controller provides a number of clocks: @@ -17,15 +25,17 @@ a number of clocks: Required properties: - - compatible: must be: - "marvell,ap806-system-controller", "syscon" - - reg: register area of the AP806 system controller + - compatible: must be: "marvell,ap806-clock" - #clock-cells: must be set to 1 Example: syscon: system-controller@6f4000 { - compatible = "marvell,ap806-system-controller", "syscon"; - #clock-cells = <1>; + compatible = "syscon", "simple-mfd"; reg = <0x6f4000 0x1000>; + + ap_clk: clock { + compatible = "marvell,ap806-clock"; + #clock-cells = <1>; + }; }; From d9ff21eea139430ce61bce885605f7828debf028 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 31 May 2017 16:07:22 +0200 Subject: [PATCH 3/5] clk: mvebu: ap806: cosmetic improvement Instead of using &pdev->dev all over the place, introduce a pointer variable for it. Signed-off-by: Gregory CLEMENT Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/5a55e081d96fc6d2a28331b59df90f56d32a9f24.1496239589.git-series.gregory.clement@free-electrons.com --- drivers/clk/mvebu/ap806-system-controller.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/clk/mvebu/ap806-system-controller.c b/drivers/clk/mvebu/ap806-system-controller.c index 8155baccc98e..b2666b5c944f 100644 --- a/drivers/clk/mvebu/ap806-system-controller.c +++ b/drivers/clk/mvebu/ap806-system-controller.c @@ -36,20 +36,21 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) { unsigned int freq_mode, cpuclk_freq; const char *name, *fixedclk_name; - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct regmap *regmap; u32 reg; int ret; regmap = syscon_node_to_regmap(np); if (IS_ERR(regmap)) { - dev_err(&pdev->dev, "cannot get regmap\n"); + dev_err(dev, "cannot get regmap\n"); return PTR_ERR(regmap); } ret = regmap_read(regmap, AP806_SAR_REG, ®); if (ret) { - dev_err(&pdev->dev, "cannot read from regmap\n"); + dev_err(dev, "cannot read from regmap\n"); return ret; } @@ -89,7 +90,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) cpuclk_freq = 600; break; default: - dev_err(&pdev->dev, "invalid SAR value\n"); + dev_err(dev, "invalid SAR value\n"); return -EINVAL; } @@ -99,7 +100,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) /* CPU clocks depend on the Sample At Reset configuration */ of_property_read_string_index(np, "clock-output-names", 0, &name); - ap806_clks[0] = clk_register_fixed_rate(&pdev->dev, name, NULL, + ap806_clks[0] = clk_register_fixed_rate(dev, name, NULL, 0, cpuclk_freq); if (IS_ERR(ap806_clks[0])) { ret = PTR_ERR(ap806_clks[0]); @@ -108,7 +109,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) of_property_read_string_index(np, "clock-output-names", 1, &name); - ap806_clks[1] = clk_register_fixed_rate(&pdev->dev, name, NULL, 0, + ap806_clks[1] = clk_register_fixed_rate(dev, name, NULL, 0, cpuclk_freq); if (IS_ERR(ap806_clks[1])) { ret = PTR_ERR(ap806_clks[1]); @@ -118,7 +119,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) /* Fixed clock is always 1200 Mhz */ of_property_read_string_index(np, "clock-output-names", 2, &fixedclk_name); - ap806_clks[2] = clk_register_fixed_rate(&pdev->dev, fixedclk_name, NULL, + ap806_clks[2] = clk_register_fixed_rate(dev, fixedclk_name, NULL, 0, 1200 * 1000 * 1000); if (IS_ERR(ap806_clks[2])) { ret = PTR_ERR(ap806_clks[2]); From 55de4d06b4589e5fba9f27b6876884e5af68890e Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 31 May 2017 16:07:24 +0200 Subject: [PATCH 4/5] clk: mvebu: ap806: do not depend anymore of the *-clock-output-names As it was done for the cp110, this patch modifies the way the clock names are created. The name of each clock is now created by using its physical address as a prefix (as it was done for the platform device names). Thanks to this we have an automatic way to compute a unique name. Reviewed-by: Thomas Petazzoni Acked-by: Rob Herring Signed-off-by: Gregory CLEMENT Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/e66cdd54d36c6bef78460a51e577f171b6ccb031.1496239589.git-series.gregory.clement@free-electrons.com --- drivers/clk/mvebu/ap806-system-controller.c | 46 +++++++++++---------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/drivers/clk/mvebu/ap806-system-controller.c b/drivers/clk/mvebu/ap806-system-controller.c index b2666b5c944f..95ae16e203ea 100644 --- a/drivers/clk/mvebu/ap806-system-controller.c +++ b/drivers/clk/mvebu/ap806-system-controller.c @@ -32,6 +32,18 @@ static struct clk_onecell_data ap806_clk_data = { .clk_num = AP806_CLK_NUM, }; +static char *ap806_unique_name(struct device *dev, struct device_node *np, + char *name) +{ + const __be32 *reg; + u64 addr; + + reg = of_get_property(np, "reg", NULL); + addr = of_translate_address(np, reg); + return devm_kasprintf(dev, GFP_KERNEL, "%llx-%s", + (unsigned long long)addr, name); +} + static int ap806_syscon_clk_probe(struct platform_device *pdev) { unsigned int freq_mode, cpuclk_freq; @@ -98,8 +110,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) cpuclk_freq *= 1000 * 1000; /* CPU clocks depend on the Sample At Reset configuration */ - of_property_read_string_index(np, "clock-output-names", - 0, &name); + name = ap806_unique_name(dev, np, "cpu-cluster-0"); ap806_clks[0] = clk_register_fixed_rate(dev, name, NULL, 0, cpuclk_freq); if (IS_ERR(ap806_clks[0])) { @@ -107,8 +118,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) goto fail0; } - of_property_read_string_index(np, "clock-output-names", - 1, &name); + name = ap806_unique_name(dev, np, "cpu-cluster-1"); ap806_clks[1] = clk_register_fixed_rate(dev, name, NULL, 0, cpuclk_freq); if (IS_ERR(ap806_clks[1])) { @@ -117,8 +127,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) } /* Fixed clock is always 1200 Mhz */ - of_property_read_string_index(np, "clock-output-names", - 2, &fixedclk_name); + fixedclk_name = ap806_unique_name(dev, np, "fixed"); ap806_clks[2] = clk_register_fixed_rate(dev, fixedclk_name, NULL, 0, 1200 * 1000 * 1000); if (IS_ERR(ap806_clks[2])) { @@ -127,8 +136,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) } /* MSS Clock is fixed clock divided by 6 */ - of_property_read_string_index(np, "clock-output-names", - 3, &name); + name = ap806_unique_name(dev, np, "mss"); ap806_clks[3] = clk_register_fixed_factor(NULL, name, fixedclk_name, 0, 1, 6); if (IS_ERR(ap806_clks[3])) { @@ -136,20 +144,14 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) goto fail3; } - /* eMMC Clock is fixed clock divided by 3 */ - if (of_property_read_string_index(np, "clock-output-names", - 4, &name)) { - ap806_clk_data.clk_num--; - dev_warn(&pdev->dev, - "eMMC clock missing: update the device tree!\n"); - } else { - ap806_clks[4] = clk_register_fixed_factor(NULL, name, - fixedclk_name, - 0, 1, 3); - if (IS_ERR(ap806_clks[4])) { - ret = PTR_ERR(ap806_clks[4]); - goto fail4; - } + /* SDIO(/eMMC) Clock is fixed clock divided by 3 */ + name = ap806_unique_name(dev, np, "sdio"); + ap806_clks[4] = clk_register_fixed_factor(NULL, name, + fixedclk_name, + 0, 1, 3); + if (IS_ERR(ap806_clks[4])) { + ret = PTR_ERR(ap806_clks[4]); + goto fail4; } of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data); From b90da67543e5aae5cb8162402ac5b483fb660dbd Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Wed, 31 May 2017 16:07:26 +0200 Subject: [PATCH 5/5] clk: mvebu: ap806: introduce a new binding As for cp110, the initial intent when the binding of the ap806 system controller was to have one flat node. The idea being that what is currently a clock-only driver in drivers would become a MFD driver, exposing the clock, GPIO and pinctrl functionality. However, after taking a step back, this would lead to a messy binding. Indeed, a single node would be a GPIO controller, clock controller, pinmux controller, and more. This patch adopts a more classical solution of a top-level syscon node with sub-nodes for the individual devices. The main benefit will be to have each functional block associated to its own sub-node where we can put its own properties. The introduction of the Armada 7K/8K is still in the early stage so the plan is to remove the old binding. However, we don't want to break the device tree compatibility for the few devices already in the field. For this we still keep the support of the legacy compatible string with a big warning in the kernel about updating the device tree. Acked-by: Rob Herring Signed-off-by: Gregory CLEMENT Signed-off-by: Michael Turquette Link: lkml.kernel.org/r/cc8c8c40fa4c4e71133033358992ec38e5aa2be5.1496239589.git-series.gregory.clement@free-electrons.com --- drivers/clk/mvebu/ap806-system-controller.c | 56 ++++++++++++++++----- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/drivers/clk/mvebu/ap806-system-controller.c b/drivers/clk/mvebu/ap806-system-controller.c index 95ae16e203ea..fa2fbd2cef4a 100644 --- a/drivers/clk/mvebu/ap806-system-controller.c +++ b/drivers/clk/mvebu/ap806-system-controller.c @@ -44,7 +44,8 @@ static char *ap806_unique_name(struct device *dev, struct device_node *np, (unsigned long long)addr, name); } -static int ap806_syscon_clk_probe(struct platform_device *pdev) +static int ap806_syscon_common_probe(struct platform_device *pdev, + struct device_node *syscon_node) { unsigned int freq_mode, cpuclk_freq; const char *name, *fixedclk_name; @@ -54,7 +55,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) u32 reg; int ret; - regmap = syscon_node_to_regmap(np); + regmap = syscon_node_to_regmap(syscon_node); if (IS_ERR(regmap)) { dev_err(dev, "cannot get regmap\n"); return PTR_ERR(regmap); @@ -110,7 +111,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) cpuclk_freq *= 1000 * 1000; /* CPU clocks depend on the Sample At Reset configuration */ - name = ap806_unique_name(dev, np, "cpu-cluster-0"); + name = ap806_unique_name(dev, syscon_node, "cpu-cluster-0"); ap806_clks[0] = clk_register_fixed_rate(dev, name, NULL, 0, cpuclk_freq); if (IS_ERR(ap806_clks[0])) { @@ -118,7 +119,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) goto fail0; } - name = ap806_unique_name(dev, np, "cpu-cluster-1"); + name = ap806_unique_name(dev, syscon_node, "cpu-cluster-1"); ap806_clks[1] = clk_register_fixed_rate(dev, name, NULL, 0, cpuclk_freq); if (IS_ERR(ap806_clks[1])) { @@ -127,7 +128,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) } /* Fixed clock is always 1200 Mhz */ - fixedclk_name = ap806_unique_name(dev, np, "fixed"); + fixedclk_name = ap806_unique_name(dev, syscon_node, "fixed"); ap806_clks[2] = clk_register_fixed_rate(dev, fixedclk_name, NULL, 0, 1200 * 1000 * 1000); if (IS_ERR(ap806_clks[2])) { @@ -136,7 +137,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) } /* MSS Clock is fixed clock divided by 6 */ - name = ap806_unique_name(dev, np, "mss"); + name = ap806_unique_name(dev, syscon_node, "mss"); ap806_clks[3] = clk_register_fixed_factor(NULL, name, fixedclk_name, 0, 1, 6); if (IS_ERR(ap806_clks[3])) { @@ -145,7 +146,7 @@ static int ap806_syscon_clk_probe(struct platform_device *pdev) } /* SDIO(/eMMC) Clock is fixed clock divided by 3 */ - name = ap806_unique_name(dev, np, "sdio"); + name = ap806_unique_name(dev, syscon_node, "sdio"); ap806_clks[4] = clk_register_fixed_factor(NULL, name, fixedclk_name, 0, 1, 3); @@ -175,17 +176,48 @@ fail0: return ret; } -static const struct of_device_id ap806_syscon_of_match[] = { +static int ap806_syscon_legacy_probe(struct platform_device *pdev) +{ + dev_warn(&pdev->dev, FW_WARN "Using legacy device tree binding\n"); + dev_warn(&pdev->dev, FW_WARN "Update your device tree:\n"); + dev_warn(&pdev->dev, FW_WARN + "This binding won't be supported in future kernel\n"); + + return ap806_syscon_common_probe(pdev, pdev->dev.of_node); + +} + +static int ap806_clock_probe(struct platform_device *pdev) +{ + return ap806_syscon_common_probe(pdev, pdev->dev.of_node->parent); +} + +static const struct of_device_id ap806_syscon_legacy_of_match[] = { { .compatible = "marvell,ap806-system-controller", }, { } }; -static struct platform_driver ap806_syscon_driver = { - .probe = ap806_syscon_clk_probe, +static struct platform_driver ap806_syscon_legacy_driver = { + .probe = ap806_syscon_legacy_probe, .driver = { .name = "marvell-ap806-system-controller", - .of_match_table = ap806_syscon_of_match, + .of_match_table = ap806_syscon_legacy_of_match, .suppress_bind_attrs = true, }, }; -builtin_platform_driver(ap806_syscon_driver); +builtin_platform_driver(ap806_syscon_legacy_driver); + +static const struct of_device_id ap806_clock_of_match[] = { + { .compatible = "marvell,ap806-clock", }, + { } +}; + +static struct platform_driver ap806_clock_driver = { + .probe = ap806_clock_probe, + .driver = { + .name = "marvell-ap806-clock", + .of_match_table = ap806_clock_of_match, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver(ap806_clock_driver);