clk: mvebu: ap806: introduce a new binding
authorGregory CLEMENT <gregory.clement@free-electrons.com>
Wed, 31 May 2017 14:07:26 +0000 (16:07 +0200)
committerMichael Turquette <mturquette@baylibre.com>
Thu, 1 Jun 2017 03:03:21 +0000 (12:03 +0900)
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 <robh@kernel.org>
Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Michael Turquette <mturquette@baylibre.com>
Link: lkml.kernel.org/r/cc8c8c40fa4c4e71133033358992ec38e5aa2be5.1496239589.git-series.gregory.clement@free-electrons.com

drivers/clk/mvebu/ap806-system-controller.c

index 95ae16e203eabd34a3fa08cea1df68b2fc2832c4..fa2fbd2cef4a343b50ccec04224c7dfc07dd6c52 100644 (file)
@@ -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_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_syscon_driver);
+builtin_platform_driver(ap806_clock_driver);