From 3c30a4a357bd1011322782d6a60fa284d8bd8286 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 25 Nov 2015 17:32:16 +0100 Subject: clk/realview: stop using machine headers In order to move realview into multiplatform, we have to prevent device drivers from accessing the machine header files. In case of the clk driver, this is very simple, we just copy the small set of register definitions into the driver that needs them. Signed-off-by: Arnd Bergmann Signed-off-by: Linus Walleij --- drivers/clk/versatile/clk-realview.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'drivers/clk/versatile') diff --git a/drivers/clk/versatile/clk-realview.c b/drivers/clk/versatile/clk-realview.c index 86f7099..bd4dd24 100644 --- a/drivers/clk/versatile/clk-realview.c +++ b/drivers/clk/versatile/clk-realview.c @@ -11,11 +11,15 @@ #include #include -#include -#include - #include "clk-icst.h" +#define REALVIEW_SYS_OSC0_OFFSET 0x0C +#define REALVIEW_SYS_OSC1_OFFSET 0x10 +#define REALVIEW_SYS_OSC2_OFFSET 0x14 +#define REALVIEW_SYS_OSC3_OFFSET 0x18 +#define REALVIEW_SYS_OSC4_OFFSET 0x1C /* OSC1 for RealView/AB */ +#define REALVIEW_SYS_LOCK_OFFSET 0x20 + /* * Implementation of the ARM RealView clock trees. */ -- cgit v1.1 From 179c8fb3c2a6cc86cc746e6d071be00f611328de Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Oct 2015 15:52:50 +0200 Subject: clk: versatile-icst: convert to use regmap Instead of passing around register bases, pass around a regmap in this driver. This refactoring make things so much easier when we later want to manage an ICST that is part of a syscon. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Signed-off-by: Linus Walleij --- drivers/clk/versatile/Kconfig | 1 + drivers/clk/versatile/clk-icst.c | 88 +++++++++++++++++++++++++++------------- 2 files changed, 61 insertions(+), 28 deletions(-) (limited to 'drivers/clk/versatile') diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig index fc50b62..e733385 100644 --- a/drivers/clk/versatile/Kconfig +++ b/drivers/clk/versatile/Kconfig @@ -1,6 +1,7 @@ config COMMON_CLK_VERSATILE bool "Clock driver for ARM Reference designs" depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64 || COMPILE_TEST + select REGMAP_MMIO ---help--- Supports clocking on ARM Reference designs: - Integrator/AP and Integrator/CP diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 08c5ee9..80e955a 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -19,9 +19,13 @@ #include #include #include +#include #include "clk-icst.h" +/* Magic unlocking token used on all Versatile boards */ +#define VERSATILE_LOCK_VAL 0xA05F + /** * struct clk_icst - ICST VCO clock wrapper * @hw: corresponding clock hardware entry @@ -32,8 +36,9 @@ */ struct clk_icst { struct clk_hw hw; - void __iomem *vcoreg; - void __iomem *lockreg; + struct regmap *map; + u32 vcoreg_off; + u32 lockreg_off; struct icst_params *params; unsigned long rate; }; @@ -41,53 +46,67 @@ struct clk_icst { #define to_icst(_hw) container_of(_hw, struct clk_icst, hw) /** - * vco_get() - get ICST VCO settings from a certain register - * @vcoreg: register containing the VCO settings + * vco_get() - get ICST VCO settings from a certain ICST + * @icst: the ICST clock to get + * @vco: the VCO struct to return the value in */ -static struct icst_vco vco_get(void __iomem *vcoreg) +static int vco_get(struct clk_icst *icst, struct icst_vco *vco) { u32 val; - struct icst_vco vco; - - val = readl(vcoreg); - vco.v = val & 0x1ff; - vco.r = (val >> 9) & 0x7f; - vco.s = (val >> 16) & 03; - return vco; + int ret; + + ret = regmap_read(icst->map, icst->vcoreg_off, &val); + if (ret) + return ret; + vco->v = val & 0x1ff; + vco->r = (val >> 9) & 0x7f; + vco->s = (val >> 16) & 03; + return 0; } /** * vco_set() - commit changes to an ICST VCO - * @locreg: register to poke to unlock the VCO for writing - * @vcoreg: register containing the VCO settings - * @vco: ICST VCO parameters to commit + * @icst: the ICST clock to set + * @vco: the VCO struct to set the changes from */ -static void vco_set(void __iomem *lockreg, - void __iomem *vcoreg, - struct icst_vco vco) +static int vco_set(struct clk_icst *icst, struct icst_vco vco) { u32 val; + int ret; - val = readl(vcoreg) & ~0x7ffff; + ret = regmap_read(icst->map, icst->vcoreg_off, &val); + if (ret) + return ret; val |= vco.v | (vco.r << 9) | (vco.s << 16); /* This magic unlocks the VCO so it can be controlled */ - writel(0xa05f, lockreg); - writel(val, vcoreg); + ret = regmap_write(icst->map, icst->lockreg_off, VERSATILE_LOCK_VAL); + if (ret) + return ret; + ret = regmap_write(icst->map, icst->vcoreg_off, val); + if (ret) + return ret; /* This locks the VCO again */ - writel(0, lockreg); + ret = regmap_write(icst->map, icst->lockreg_off, 0); + if (ret) + return ret; + return 0; } - static unsigned long icst_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct clk_icst *icst = to_icst(hw); struct icst_vco vco; + int ret; if (parent_rate) icst->params->ref = parent_rate; - vco = vco_get(icst->vcoreg); + ret = vco_get(icst, &vco); + if (ret) { + pr_err("ICST: could not get VCO setting\n"); + return 0; + } icst->rate = icst_hz(icst->params, vco); return icst->rate; } @@ -112,8 +131,7 @@ static int icst_set_rate(struct clk_hw *hw, unsigned long rate, icst->params->ref = parent_rate; vco = icst_hz_to_vco(icst->params, rate); icst->rate = icst_hz(icst->params, vco); - vco_set(icst->lockreg, icst->vcoreg, vco); - return 0; + return vco_set(icst, vco); } static const struct clk_ops icst_ops = { @@ -132,6 +150,11 @@ struct clk *icst_clk_register(struct device *dev, struct clk_icst *icst; struct clk_init_data init; struct icst_params *pclone; + struct regmap_config icst_regmap_conf = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + }; icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); if (!icst) { @@ -151,10 +174,19 @@ struct clk *icst_clk_register(struct device *dev, init.flags = CLK_IS_ROOT; init.parent_names = (parent_name ? &parent_name : NULL); init.num_parents = (parent_name ? 1 : 0); + icst->map = regmap_init_mmio(dev, base, &icst_regmap_conf); + if (IS_ERR(icst->map)) { + int ret; + + pr_err("could not initialize ICST regmap\n"); + ret = PTR_ERR(icst->map); + kfree(icst); + return ERR_PTR(ret); + } icst->hw.init = &init; icst->params = pclone; - icst->vcoreg = base + desc->vco_offset; - icst->lockreg = base + desc->lock_offset; + icst->vcoreg_off = desc->vco_offset; + icst->lockreg_off = desc->lock_offset; clk = clk_register(dev, &icst->hw); if (IS_ERR(clk)) { -- cgit v1.1 From 384d977d74f434ea089e9419fa9233fcfa18602b Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Mon, 12 Oct 2015 16:14:28 +0200 Subject: clk: versatile-icst: refactor to allocate regmap separately Break out the registration function so it creates a regmap and pass to the setup function, so the latter can be shared with a device tree probe function that already has a regmap. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Signed-off-by: Linus Walleij --- drivers/clk/versatile/clk-icst.c | 47 ++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 19 deletions(-) (limited to 'drivers/clk/versatile') diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 80e955a..87bd466 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "clk-icst.h" @@ -140,21 +141,16 @@ static const struct clk_ops icst_ops = { .set_rate = icst_set_rate, }; -struct clk *icst_clk_register(struct device *dev, - const struct clk_icst_desc *desc, - const char *name, - const char *parent_name, - void __iomem *base) +static struct clk *icst_clk_setup(struct device *dev, + const struct clk_icst_desc *desc, + const char *name, + const char *parent_name, + struct regmap *map) { struct clk *clk; struct clk_icst *icst; struct clk_init_data init; struct icst_params *pclone; - struct regmap_config icst_regmap_conf = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - }; icst = kzalloc(sizeof(struct clk_icst), GFP_KERNEL); if (!icst) { @@ -174,15 +170,7 @@ struct clk *icst_clk_register(struct device *dev, init.flags = CLK_IS_ROOT; init.parent_names = (parent_name ? &parent_name : NULL); init.num_parents = (parent_name ? 1 : 0); - icst->map = regmap_init_mmio(dev, base, &icst_regmap_conf); - if (IS_ERR(icst->map)) { - int ret; - - pr_err("could not initialize ICST regmap\n"); - ret = PTR_ERR(icst->map); - kfree(icst); - return ERR_PTR(ret); - } + icst->map = map; icst->hw.init = &init; icst->params = pclone; icst->vcoreg_off = desc->vco_offset; @@ -196,4 +184,25 @@ struct clk *icst_clk_register(struct device *dev, return clk; } + +struct clk *icst_clk_register(struct device *dev, + const struct clk_icst_desc *desc, + const char *name, + const char *parent_name, + void __iomem *base) +{ + struct regmap_config icst_regmap_conf = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + }; + struct regmap *map; + + map = regmap_init_mmio(dev, base, &icst_regmap_conf); + if (IS_ERR(map)) { + pr_err("could not initialize ICST regmap\n"); + return ERR_CAST(map); + } + return icst_clk_setup(dev, desc, name, parent_name, map); +} EXPORT_SYMBOL_GPL(icst_clk_register); -- cgit v1.1 From d430819d69a51dc4798bb98d841afa9af2f5c83a Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 13 Oct 2015 14:29:54 +0200 Subject: clk: versatile-icst: add device tree support This adds support for the ARM syscon ICST clocks to initialized directly from the device tree syscon node on ARM Integrator, Versatile and RealView reference designs. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Signed-off-by: Linus Walleij --- drivers/clk/versatile/clk-icst.c | 89 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) (limited to 'drivers/clk/versatile') diff --git a/drivers/clk/versatile/clk-icst.c b/drivers/clk/versatile/clk-icst.c index 87bd466..e62f8cb 100644 --- a/drivers/clk/versatile/clk-icst.c +++ b/drivers/clk/versatile/clk-icst.c @@ -3,7 +3,7 @@ * We wrap the custom interface from into the generic * clock framework. * - * Copyright (C) 2012 Linus Walleij + * Copyright (C) 2012-2015 Linus Walleij * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -206,3 +206,90 @@ struct clk *icst_clk_register(struct device *dev, return icst_clk_setup(dev, desc, name, parent_name, map); } EXPORT_SYMBOL_GPL(icst_clk_register); + +#ifdef CONFIG_OF +/* + * In a device tree, an memory-mapped ICST clock appear as a child + * of a syscon node. Assume this and probe it only as a child of a + * syscon. + */ + +static const struct icst_params icst525_params = { + .vco_max = ICST525_VCO_MAX_5V, + .vco_min = ICST525_VCO_MIN, + .vd_min = 8, + .vd_max = 263, + .rd_min = 3, + .rd_max = 65, + .s2div = icst525_s2div, + .idx2s = icst525_idx2s, +}; + +static const struct icst_params icst307_params = { + .vco_max = ICST307_VCO_MAX, + .vco_min = ICST307_VCO_MIN, + .vd_min = 4 + 8, + .vd_max = 511 + 8, + .rd_min = 1 + 2, + .rd_max = 127 + 2, + .s2div = icst307_s2div, + .idx2s = icst307_idx2s, +}; + +static void __init of_syscon_icst_setup(struct device_node *np) +{ + struct device_node *parent; + struct regmap *map; + struct clk_icst_desc icst_desc; + const char *name = np->name; + const char *parent_name; + struct clk *regclk; + + /* We do not release this reference, we are using it perpetually */ + parent = of_get_parent(np); + if (!parent) { + pr_err("no parent node for syscon ICST clock\n"); + return; + } + map = syscon_node_to_regmap(parent); + if (IS_ERR(map)) { + pr_err("no regmap for syscon ICST clock parent\n"); + return; + } + + if (of_property_read_u32(np, "vco-offset", &icst_desc.vco_offset)) { + pr_err("no VCO register offset for ICST clock\n"); + return; + } + if (of_property_read_u32(np, "lock-offset", &icst_desc.lock_offset)) { + pr_err("no lock register offset for ICST clock\n"); + return; + } + + if (of_device_is_compatible(np, "arm,syscon-icst525")) + icst_desc.params = &icst525_params; + else if (of_device_is_compatible(np, "arm,syscon-icst307")) + icst_desc.params = &icst307_params; + else { + pr_err("unknown ICST clock %s\n", name); + return; + } + + /* Parent clock name is not the same as node parent */ + parent_name = of_clk_get_parent_name(np, 0); + + regclk = icst_clk_setup(NULL, &icst_desc, name, parent_name, map); + if (IS_ERR(regclk)) { + pr_err("error setting up syscon ICST clock %s\n", name); + return; + } + of_clk_add_provider(np, of_clk_src_simple_get, regclk); + pr_debug("registered syscon ICST clock %s\n", name); +} + +CLK_OF_DECLARE(arm_syscon_icst525_clk, + "arm,syscon-icst525", of_syscon_icst_setup); +CLK_OF_DECLARE(arm_syscon_icst307_clk, + "arm,syscon-icst307", of_syscon_icst_setup); + +#endif -- cgit v1.1 From 16956fed35fecde2201e23458cda193526b19559 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Tue, 8 Dec 2015 14:44:16 -0600 Subject: ARM: versatile: switch to DT only booting and remove legacy code With DT support for clocks, irqchips, timers, and PCI now in place, DT based booting has feature parity with non-DT legacy boot. The final piece is actually enabling common clock support on Versatile. Enabling full DT support requires either removing the old Versatile clock code, updating the legacy boot to use the common clock code, or making DT and legacy boot mutually exclusive. Given that removing legacy boot code is the goal anyway, I am going with the 1st option. Signed-off-by: Rob Herring Cc: Russell King Cc: Linus Walleij Cc: Mike Turquette Signed-off-by: Arnd Bergmann --- drivers/clk/versatile/Kconfig | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/clk/versatile') diff --git a/drivers/clk/versatile/Kconfig b/drivers/clk/versatile/Kconfig index fc50b62..369a2dc 100644 --- a/drivers/clk/versatile/Kconfig +++ b/drivers/clk/versatile/Kconfig @@ -1,6 +1,8 @@ config COMMON_CLK_VERSATILE bool "Clock driver for ARM Reference designs" - depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64 || COMPILE_TEST + depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \ + ARCH_VERSATILE || ARCH_VEXPRESS || ARM64 || \ + COMPILE_TEST ---help--- Supports clocking on ARM Reference designs: - Integrator/AP and Integrator/CP -- cgit v1.1