From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Subject: Re: [PATCH v3 9/9] clk: at91: update to PMC bindings
Date: Tue, 19 Feb 2019 08:50:17 +0100 [thread overview]
Message-ID: <171ac237-ef8f-502b-1433-83382d050ba1@pengutronix.de> (raw)
In-Reply-To: <20190218194759.9557-10-sam@ravnborg.org>
Hello Sam,
On 18/2/19 20:47, Sam Ravnborg wrote:
> Based on kernel 5.0-rc6 update at91 clk support
> to match the new PMC bindings.
>
> Manually added all changes done in the kernel from 4.9-rc3
> to 5.0-rc6.
> New drivers required was added as seperate commits.
>
> The kernel has a dt-compat file for all the backward
> compatibility code.
> As barebox has only a few DT enabled at91 targets this was not ported
> over.
There's a DT enabled sama5d3 based second stage (microchip-ksz9477-evb),
which is now broken now by this change omitting the dt-compat code.
I'll reply to this mail with a fixup.
>
> clk-programmable saw some extra changes - it had never been bulit.
> It is used only by at91sama5d2 - and barebox has no baord support for
> this cpu (yet).
Great! I have a sama5d27-som1-ek board sitting (without fully functioning
barebox yet though) on my desk as well.
>
> For the SOC config symbols updated these to match the kernel,
> to enable the same set of clk features in barebox as in the kernel.
>
> In the kernel CLK_OF_DECLARE_DRIVER() can be used for a two step init.
> In barebox this is a simple one step init.
> It was added to have less differences between the kernel and the barebox
> versions of the drivers.
>
> Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
> Tested-by: Ladislav Michl <ladis@linux-mips.org>
> ---
> arch/arm/mach-at91/Kconfig | 17 ++-
> drivers/clk/at91/Makefile | 5 +
> drivers/clk/at91/clk-generated.c | 185 +++++----------------------
> drivers/clk/at91/clk-h32mx.c | 55 ++++----
> drivers/clk/at91/clk-main.c | 112 +---------------
> drivers/clk/at91/clk-master.c | 94 +-------------
> drivers/clk/at91/clk-peripheral.c | 82 +-----------
> drivers/clk/at91/clk-pll.c | 174 +------------------------
> drivers/clk/at91/clk-plldiv.c | 27 +---
> drivers/clk/at91/clk-programmable.c | 83 +-----------
> drivers/clk/at91/clk-slow.c | 33 +----
> drivers/clk/at91/clk-smd.c | 33 +----
> drivers/clk/at91/clk-system.c | 42 +-----
> drivers/clk/at91/clk-usb.c | 94 +-------------
> drivers/clk/at91/clk-utmi.c | 100 +++++++++------
> drivers/clk/at91/pmc.c | 248 ++++++++++++++++++++++++++++++++++++
> drivers/clk/at91/pmc.h | 169 ++++++++++++++++++++++++
> include/linux/clk.h | 7 +
> include/soc/at91/atmel-sfr.h | 34 +++++
> 19 files changed, 619 insertions(+), 975 deletions(-)
> create mode 100644 include/soc/at91/atmel-sfr.h
>
> diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig
> index a2737a367..344344429 100644
> --- a/arch/arm/mach-at91/Kconfig
> +++ b/arch/arm/mach-at91/Kconfig
> @@ -53,6 +53,9 @@ config SOC_AT91SAM9
> select AT91SAM9_SMC
> select CLOCKSOURCE_ATMEL_PIT
> select PINCTRL
> + select HAVE_AT91_SMD
> + select HAVE_AT91_USB_CLK
> + select HAVE_AT91_UTMI
>
> config SOC_SAMA5
> bool
> @@ -63,12 +66,19 @@ config SOC_SAMA5D3
> select SOC_SAMA5
> select AT91SAM9_SMC
> select CLOCKSOURCE_ATMEL_PIT
> + select HAVE_AT91_SMD
> + select HAVE_AT91_USB_CLK
> + select HAVE_AT91_UTMI
>
> config SOC_SAMA5D4
> bool
> select SOC_SAMA5
> select AT91SAM9_SMC
> select CLOCKSOURCE_ATMEL_PIT
> + select HAVE_AT91_H32MX
> + select HAVE_AT91_SMD
> + select HAVE_AT91_USB_CLK
> + select HAVE_AT91_UTMI
>
> config ARCH_TEXT_BASE
> hex
> @@ -92,8 +102,9 @@ comment "Atmel AT91 System-on-Chip"
> config SOC_AT91RM9200
> bool
> select CPU_ARM920T
> - select HAVE_AT91_DBGU0
> select HAS_AT91_ETHER
> + select HAVE_AT91_DBGU0
> + select HAVE_AT91_USB_CLK
>
> config SOC_AT91SAM9260
> bool
> @@ -132,9 +143,6 @@ config SOC_AT91SAM9X5
> select SOC_AT91SAM9
> select HAVE_AT91_DBGU0
> select HAS_MACB
> - select HAVE_AT91_SMD
> - select HAVE_AT91_USB_CLK
> - select HAVE_AT91_UTMI
> select COMMON_CLK_OF_PROVIDER
> help
> Select this if you are using one of Atmel's AT91SAM9x5 family SoC.
> @@ -532,7 +540,6 @@ config MACH_AT91SAM9263EK
> depends on ARCH_AT91SAM9263
> select OFDEVICE
> select COMMON_CLK_OF_PROVIDER
> - select HAVE_AT91_USB_CLK
> select HAVE_NAND_ATMEL_BUSWIDTH_16
> select HAVE_AT91_BOOTSTRAP
> select AT91SAM926X_BOARD_INIT
> diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile
> index 13e67bd35..ec41c15fa 100644
> --- a/drivers/clk/at91/Makefile
> +++ b/drivers/clk/at91/Makefile
> @@ -11,3 +11,8 @@ obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o
> obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o
> obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o
> obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o
> +obj-$(CONFIG_SOC_AT91SAM9) += at91sam9260.o
> +obj-$(CONFIG_SOC_AT91SAM9) += at91sam9rl.o
> +obj-$(CONFIG_SOC_AT91SAM9) += at91sam9x5.o
> +obj-$(CONFIG_SOC_SAMA5D2) += sama5d2.o
> +obj-$(CONFIG_SOC_SAMA5D4) += sama5d4.o
> diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c
> index 4e1cd5aa6..60516ca10 100644
> --- a/drivers/clk/at91/clk-generated.c
> +++ b/drivers/clk/at91/clk-generated.c
> @@ -11,26 +11,23 @@
> *
> */
>
> -#include <linux/clk-provider.h>
> -#include <linux/clkdev.h>
> +#include <common.h>
> +#include <clock.h>
> +#include <io.h>
> +#include <linux/list.h>
> +#include <linux/clk.h>
> #include <linux/clk/at91_pmc.h>
> -#include <linux/of.h>
> -#include <linux/mfd/syscon.h>
> -#include <linux/regmap.h>
> +#include <mfd/syscon.h>
> +#include <regmap.h>
>
> #include "pmc.h"
>
> -#define PERIPHERAL_MAX 64
> -#define PERIPHERAL_ID_MIN 2
> -
> -#define GENERATED_SOURCE_MAX 6
> #define GENERATED_MAX_DIV 255
>
> struct clk_generated {
> - struct clk_hw hw;
> + struct clk hw;
> struct regmap *regmap;
> struct clk_range range;
> - spinlock_t *lock;
> u32 id;
> u32 gckdiv;
> u8 parent_id;
> @@ -39,15 +36,13 @@ struct clk_generated {
> #define to_clk_generated(hw) \
> container_of(hw, struct clk_generated, hw)
>
> -static int clk_generated_enable(struct clk_hw *hw)
> +static int clk_generated_enable(struct clk *hw)
> {
> struct clk_generated *gck = to_clk_generated(hw);
> - unsigned long flags;
>
> pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
> __func__, gck->gckdiv, gck->parent_id);
>
> - spin_lock_irqsave(gck->lock, flags);
> regmap_write(gck->regmap, AT91_PMC_PCR,
> (gck->id & AT91_PMC_PCR_PID_MASK));
> regmap_update_bits(gck->regmap, AT91_PMC_PCR,
> @@ -57,41 +52,34 @@ static int clk_generated_enable(struct clk_hw *hw)
> AT91_PMC_PCR_CMD |
> AT91_PMC_PCR_GCKDIV(gck->gckdiv) |
> AT91_PMC_PCR_GCKEN);
> - spin_unlock_irqrestore(gck->lock, flags);
> return 0;
> }
>
> -static void clk_generated_disable(struct clk_hw *hw)
> +static void clk_generated_disable(struct clk *hw)
> {
> struct clk_generated *gck = to_clk_generated(hw);
> - unsigned long flags;
>
> - spin_lock_irqsave(gck->lock, flags);
> regmap_write(gck->regmap, AT91_PMC_PCR,
> (gck->id & AT91_PMC_PCR_PID_MASK));
> regmap_update_bits(gck->regmap, AT91_PMC_PCR,
> AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN,
> AT91_PMC_PCR_CMD);
> - spin_unlock_irqrestore(gck->lock, flags);
> }
>
> -static int clk_generated_is_enabled(struct clk_hw *hw)
> +static int clk_generated_is_enabled(struct clk *hw)
> {
> struct clk_generated *gck = to_clk_generated(hw);
> - unsigned long flags;
> unsigned int status;
>
> - spin_lock_irqsave(gck->lock, flags);
> regmap_write(gck->regmap, AT91_PMC_PCR,
> (gck->id & AT91_PMC_PCR_PID_MASK));
> regmap_read(gck->regmap, AT91_PMC_PCR, &status);
> - spin_unlock_irqrestore(gck->lock, flags);
>
> return status & AT91_PMC_PCR_GCKEN ? 1 : 0;
> }
>
> static unsigned long
> -clk_generated_recalc_rate(struct clk_hw *hw,
> +clk_generated_recalc_rate(struct clk *hw,
> unsigned long parent_rate)
> {
> struct clk_generated *gck = to_clk_generated(hw);
> @@ -99,75 +87,19 @@ clk_generated_recalc_rate(struct clk_hw *hw,
> return DIV_ROUND_CLOSEST(parent_rate, gck->gckdiv + 1);
> }
>
> -static int clk_generated_determine_rate(struct clk_hw *hw,
> - struct clk_rate_request *req)
> -{
> - struct clk_generated *gck = to_clk_generated(hw);
> - struct clk_hw *parent = NULL;
> - long best_rate = -EINVAL;
> - unsigned long tmp_rate, min_rate;
> - int best_diff = -1;
> - int tmp_diff;
> - int i;
> -
> - for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
> - u32 div;
> - unsigned long parent_rate;
> -
> - parent = clk_hw_get_parent_by_index(hw, i);
> - if (!parent)
> - continue;
> -
> - parent_rate = clk_hw_get_rate(parent);
> - min_rate = DIV_ROUND_CLOSEST(parent_rate, GENERATED_MAX_DIV + 1);
> - if (!parent_rate ||
> - (gck->range.max && min_rate > gck->range.max))
> - continue;
> -
> - for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {
> - tmp_rate = DIV_ROUND_CLOSEST(parent_rate, div);
> - tmp_diff = abs(req->rate - tmp_rate);
> -
> - if (best_diff < 0 || best_diff > tmp_diff) {
> - best_rate = tmp_rate;
> - best_diff = tmp_diff;
> - req->best_parent_rate = parent_rate;
> - req->best_parent_hw = parent;
> - }
> -
> - if (!best_diff || tmp_rate < req->rate)
> - break;
> - }
> -
> - if (!best_diff)
> - break;
> - }
> -
> - pr_debug("GCLK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
> - __func__, best_rate,
> - __clk_get_name((req->best_parent_hw)->clk),
> - req->best_parent_rate);
> -
> - if (best_rate < 0)
> - return best_rate;
> -
> - req->rate = best_rate;
> - return 0;
> -}
> -
> /* No modification of hardware as we have the flag CLK_SET_PARENT_GATE set */
> -static int clk_generated_set_parent(struct clk_hw *hw, u8 index)
> +static int clk_generated_set_parent(struct clk *hw, u8 index)
> {
> struct clk_generated *gck = to_clk_generated(hw);
>
> - if (index >= clk_hw_get_num_parents(hw))
> + if (index >= clk_get_num_parents(hw))
> return -EINVAL;
>
> gck->parent_id = index;
> return 0;
> }
>
> -static u8 clk_generated_get_parent(struct clk_hw *hw)
> +static int clk_generated_get_parent(struct clk *hw)
> {
> struct clk_generated *gck = to_clk_generated(hw);
>
> @@ -175,7 +107,7 @@ static u8 clk_generated_get_parent(struct clk_hw *hw)
> }
>
> /* No modification of hardware as we have the flag CLK_SET_RATE_GATE set */
> -static int clk_generated_set_rate(struct clk_hw *hw,
> +static int clk_generated_set_rate(struct clk *hw,
> unsigned long rate,
> unsigned long parent_rate)
> {
> @@ -201,7 +133,6 @@ static const struct clk_ops generated_ops = {
> .disable = clk_generated_disable,
> .is_enabled = clk_generated_is_enabled,
> .recalc_rate = clk_generated_recalc_rate,
> - .determine_rate = clk_generated_determine_rate,
> .get_parent = clk_generated_get_parent,
> .set_parent = clk_generated_set_parent,
> .set_rate = clk_generated_set_rate,
> @@ -219,13 +150,10 @@ static const struct clk_ops generated_ops = {
> static void clk_generated_startup(struct clk_generated *gck)
> {
> u32 tmp;
> - unsigned long flags;
>
> - spin_lock_irqsave(gck->lock, flags);
> regmap_write(gck->regmap, AT91_PMC_PCR,
> (gck->id & AT91_PMC_PCR_PID_MASK));
> regmap_read(gck->regmap, AT91_PMC_PCR, &tmp);
> - spin_unlock_irqrestore(gck->lock, flags);
>
> gck->parent_id = (tmp & AT91_PMC_PCR_GCKCSS_MASK)
> >> AT91_PMC_PCR_GCKCSS_OFFSET;
> @@ -233,35 +161,37 @@ static void clk_generated_startup(struct clk_generated *gck)
> >> AT91_PMC_PCR_GCKDIV_OFFSET;
> }
>
> -static struct clk_hw * __init
> -at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
> +struct clk * __init
> +at91_clk_register_generated(struct regmap *regmap,
> const char *name, const char **parent_names,
> - u8 num_parents, u8 id,
> + u8 num_parents, u8 id, bool pll_audio,
> const struct clk_range *range)
> {
> + size_t parents_array_size;
> struct clk_generated *gck;
> - struct clk_init_data init;
> - struct clk_hw *hw;
> + struct clk *hw;
> int ret;
>
> gck = kzalloc(sizeof(*gck), GFP_KERNEL);
> if (!gck)
> return ERR_PTR(-ENOMEM);
>
> - init.name = name;
> - init.ops = &generated_ops;
> - init.parent_names = parent_names;
> - init.num_parents = num_parents;
> - init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
> -
> gck->id = id;
> - gck->hw.init = &init;
> + gck->hw.name = name;
> + gck->hw.ops = &generated_ops;
> +
> + parents_array_size = num_parents * sizeof(gck->hw.parent_names[0]);
> + gck->hw.parent_names = xzalloc(parents_array_size);
> + memcpy(gck->hw.parent_names, parent_names, parents_array_size);
> + gck->hw.num_parents = num_parents;
> +
> + /* gck->hw.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; */
> gck->regmap = regmap;
> - gck->lock = lock;
> gck->range = *range;
> + /* gck->audio_pll_allowed = pll_audio; */
>
> hw = &gck->hw;
> - ret = clk_hw_register(NULL, &gck->hw);
> + ret = clk_register(&gck->hw);
> if (ret) {
> kfree(gck);
> hw = ERR_PTR(ret);
> @@ -270,54 +200,3 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
>
> return hw;
> }
> -
> -static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
> -{
> - int num;
> - u32 id;
> - const char *name;
> - struct clk_hw *hw;
> - unsigned int num_parents;
> - const char *parent_names[GENERATED_SOURCE_MAX];
> - struct device_node *gcknp;
> - struct clk_range range = CLK_RANGE(0, 0);
> - struct regmap *regmap;
> -
> - num_parents = of_clk_get_parent_count(np);
> - if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX)
> - return;
> -
> - of_clk_parent_fill(np, parent_names, num_parents);
> -
> - num = of_get_child_count(np);
> - if (!num || num > PERIPHERAL_MAX)
> - return;
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return;
> -
> - for_each_child_of_node(np, gcknp) {
> - if (of_property_read_u32(gcknp, "reg", &id))
> - continue;
> -
> - if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
> - continue;
> -
> - if (of_property_read_string(np, "clock-output-names", &name))
> - name = gcknp->name;
> -
> - of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
> - &range);
> -
> - hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
> - parent_names, num_parents,
> - id, &range);
> - if (IS_ERR(hw))
> - continue;
> -
> - of_clk_add_hw_provider(gcknp, of_clk_hw_simple_get, hw);
> - }
> -}
> -CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated",
> - of_sama5d2_clk_generated_setup);
> diff --git a/drivers/clk/at91/clk-h32mx.c b/drivers/clk/at91/clk-h32mx.c
> index e0daa4a31..31906a9e2 100644
> --- a/drivers/clk/at91/clk-h32mx.c
> +++ b/drivers/clk/at91/clk-h32mx.c
> @@ -12,25 +12,27 @@
> *
> */
>
> -#include <linux/clk-provider.h>
> -#include <linux/clkdev.h>
> +#include <common.h>
> +#include <clock.h>
> +#include <linux/list.h>
> +#include <linux/clk.h>
> #include <linux/clk/at91_pmc.h>
> -#include <linux/of.h>
> -#include <linux/regmap.h>
> -#include <linux/mfd/syscon.h>
> +#include <regmap.h>
> +
>
> #include "pmc.h"
>
> #define H32MX_MAX_FREQ 90000000
>
> struct clk_sama5d4_h32mx {
> - struct clk_hw hw;
> + struct clk hw;
> struct regmap *regmap;
> + const char *parent;
> };
>
> #define to_clk_sama5d4_h32mx(hw) container_of(hw, struct clk_sama5d4_h32mx, hw)
>
> -static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk_hw *hw,
> +static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk *hw,
> unsigned long parent_rate)
> {
> struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw);
> @@ -45,7 +47,7 @@ static unsigned long clk_sama5d4_h32mx_recalc_rate(struct clk_hw *hw,
> return parent_rate;
> }
>
> -static long clk_sama5d4_h32mx_round_rate(struct clk_hw *hw, unsigned long rate,
> +static long clk_sama5d4_h32mx_round_rate(struct clk *hw, unsigned long rate,
> unsigned long *parent_rate)
> {
> unsigned long div;
> @@ -62,7 +64,7 @@ static long clk_sama5d4_h32mx_round_rate(struct clk_hw *hw, unsigned long rate,
> return *parent_rate;
> }
>
> -static int clk_sama5d4_h32mx_set_rate(struct clk_hw *hw, unsigned long rate,
> +static int clk_sama5d4_h32mx_set_rate(struct clk *hw, unsigned long rate,
> unsigned long parent_rate)
> {
> struct clk_sama5d4_h32mx *h32mxclk = to_clk_sama5d4_h32mx(hw);
> @@ -86,40 +88,31 @@ static const struct clk_ops h32mx_ops = {
> .set_rate = clk_sama5d4_h32mx_set_rate,
> };
>
> -static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np)
> +struct clk *
> +at91_clk_register_h32mx(struct regmap *regmap, const char *name,
> + const char *parent_name)
> {
> struct clk_sama5d4_h32mx *h32mxclk;
> - struct clk_init_data init;
> - const char *parent_name;
> - struct regmap *regmap;
> int ret;
>
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return;
> -
> h32mxclk = kzalloc(sizeof(*h32mxclk), GFP_KERNEL);
> if (!h32mxclk)
> - return;
> -
> - parent_name = of_clk_get_parent_name(np, 0);
> + return ERR_PTR(-ENOMEM);
>
> - init.name = np->name;
> - init.ops = &h32mx_ops;
> - init.parent_names = parent_name ? &parent_name : NULL;
> - init.num_parents = parent_name ? 1 : 0;
> - init.flags = CLK_SET_RATE_GATE;
> + h32mxclk->parent = parent_name;
> + h32mxclk->hw.name = name;
> + h32mxclk->hw.ops = &h32mx_ops;
> + h32mxclk->hw.parent_names = &h32mxclk->parent;
> + h32mxclk->hw.num_parents = 1;
> + /* h32mxclk.hw.flags = CLK_SET_RATE_GATE; */
>
> - h32mxclk->hw.init = &init;
> h32mxclk->regmap = regmap;
>
> - ret = clk_hw_register(NULL, &h32mxclk->hw);
> + ret = clk_register(&h32mxclk->hw);
> if (ret) {
> kfree(h32mxclk);
> - return;
> + return ERR_PTR(ret);
> }
>
> - of_clk_add_hw_provider(np, of_clk_hw_simple_get, &h32mxclk->hw);
> + return &h32mxclk->hw;
> }
> -CLK_OF_DECLARE(of_sama5d4_clk_h32mx_setup, "atmel,sama5d4-clk-h32mx",
> - of_sama5d4_clk_h32mx_setup);
> diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c
> index 77dfdef51..4d4127dd0 100644
> --- a/drivers/clk/at91/clk-main.c
> +++ b/drivers/clk/at91/clk-main.c
> @@ -9,7 +9,6 @@
> */
> #include <common.h>
> #include <clock.h>
> -#include <of.h>
> #include <linux/list.h>
> #include <linux/clk.h>
> #include <linux/clk/at91_pmc.h>
> @@ -129,7 +128,7 @@ static const struct clk_ops main_osc_ops = {
> .is_enabled = clk_main_osc_is_enabled,
> };
>
> -static struct clk *
> +struct clk *
> at91_clk_register_main_osc(struct regmap *regmap,
> const char *name,
> const char *parent_name,
> @@ -165,31 +164,6 @@ at91_clk_register_main_osc(struct regmap *regmap,
> return &osc->clk;
> }
>
> -static int of_at91rm9200_clk_main_osc_setup(struct device_node *np)
> -{
> - struct clk *clk;
> - const char *name = np->name;
> - const char *parent_name;
> - struct regmap *regmap;
> - bool bypass;
> -
> - of_property_read_string(np, "clock-output-names", &name);
> - bypass = of_property_read_bool(np, "atmel,osc-bypass");
> - parent_name = of_clk_get_parent_name(np, 0);
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - clk = at91_clk_register_main_osc(regmap, name, parent_name, bypass);
> - if (IS_ERR(clk))
> - return PTR_ERR(clk);
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -CLK_OF_DECLARE(at91rm9200_clk_main_osc, "atmel,at91rm9200-clk-main-osc",
> - of_at91rm9200_clk_main_osc_setup);
> -
> static bool clk_main_rc_osc_ready(struct regmap *regmap)
> {
> unsigned int status;
> @@ -260,10 +234,10 @@ static const struct clk_ops main_rc_osc_ops = {
> .recalc_rate = clk_main_rc_osc_recalc_rate,
> };
>
> -static struct clk *
> +struct clk *
> at91_clk_register_main_rc_osc(struct regmap *regmap,
> const char *name,
> - u32 frequency)
> + u32 frequency, u32 accuracy)
> {
> int ret;
> struct clk_main_rc_osc *osc;
> @@ -290,30 +264,6 @@ at91_clk_register_main_rc_osc(struct regmap *regmap,
> return &osc->clk;
> }
>
> -static int of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np)
> -{
> - struct clk *clk;
> - u32 frequency = 0;
> - const char *name = np->name;
> - struct regmap *regmap;
> -
> - of_property_read_string(np, "clock-output-names", &name);
> - of_property_read_u32(np, "clock-frequency", &frequency);
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - clk = at91_clk_register_main_rc_osc(regmap, name, frequency);
> - if (IS_ERR(clk))
> - return PTR_ERR(clk);
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -CLK_OF_DECLARE(at91sam9x5_clk_main_rc_osc, "atmel,at91sam9x5-clk-main-rc-osc",
> - of_at91sam9x5_clk_main_rc_osc_setup);
> -
> -
> static int clk_main_probe_frequency(struct regmap *regmap)
> {
> unsigned int mcfr;
> @@ -375,7 +325,7 @@ static const struct clk_ops rm9200_main_ops = {
> .recalc_rate = clk_rm9200_main_recalc_rate,
> };
>
> -static struct clk *
> +struct clk *
> at91_clk_register_rm9200_main(struct regmap *regmap,
> const char *name,
> const char *parent_name)
> @@ -407,29 +357,6 @@ at91_clk_register_rm9200_main(struct regmap *regmap,
> return &clkmain->clk;
> }
>
> -static int of_at91rm9200_clk_main_setup(struct device_node *np)
> -{
> - struct clk *clk;
> - const char *parent_name;
> - const char *name = np->name;
> - struct regmap *regmap;
> -
> - parent_name = of_clk_get_parent_name(np, 0);
> - of_property_read_string(np, "clock-output-names", &name);
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - clk = at91_clk_register_rm9200_main(regmap, name, parent_name);
> - if (IS_ERR(clk))
> - return PTR_ERR(clk);
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -CLK_OF_DECLARE(at91rm9200_clk_main, "atmel,at91rm9200-clk-main",
> - of_at91rm9200_clk_main_setup);
> -
> static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
> {
> unsigned int status;
> @@ -506,7 +433,7 @@ static const struct clk_ops sam9x5_main_ops = {
> .get_parent = clk_sam9x5_main_get_parent,
> };
>
> -static struct clk *
> +struct clk *
> at91_clk_register_sam9x5_main(struct regmap *regmap,
> const char *name,
> const char **parent_names,
> @@ -546,32 +473,3 @@ at91_clk_register_sam9x5_main(struct regmap *regmap,
>
> return &clkmain->clk;
> }
> -
> -static int of_at91sam9x5_clk_main_setup(struct device_node *np)
> -{
> - struct clk *clk;
> - const char *parent_names[2];
> - unsigned int num_parents;
> - const char *name = np->name;
> - struct regmap *regmap;
> -
> - num_parents = of_clk_get_parent_count(np);
> - if (num_parents == 0 || num_parents > 2)
> - return -EINVAL;
> -
> - of_clk_parent_fill(np, parent_names, num_parents);
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - of_property_read_string(np, "clock-output-names", &name);
> -
> - clk = at91_clk_register_sam9x5_main(regmap, name, parent_names,
> - num_parents);
> - if (IS_ERR(clk))
> - return PTR_ERR(clk);
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -CLK_OF_DECLARE(at91sam9x5_clk_main, "atmel,at91sam9x5-clk-main",
> - of_at91sam9x5_clk_main_setup);
> diff --git a/drivers/clk/at91/clk-master.c b/drivers/clk/at91/clk-master.c
> index b3a50ce54..f7a0fb1d1 100644
> --- a/drivers/clk/at91/clk-master.c
> +++ b/drivers/clk/at91/clk-master.c
> @@ -9,7 +9,6 @@
> */
> #include <common.h>
> #include <clock.h>
> -#include <of.h>
> #include <linux/list.h>
> #include <linux/clk.h>
> #include <linux/clk/at91_pmc.h>
> @@ -25,17 +24,6 @@
> #define MASTER_DIV_SHIFT 8
> #define MASTER_DIV_MASK 0x3
>
> -struct clk_master_characteristics {
> - struct clk_range output;
> - u32 divisors[4];
> - u8 have_div3_pres;
> -};
> -
> -struct clk_master_layout {
> - u32 mask;
> - u8 pres_shift;
> -};
> -
> #define to_clk_master(clk) container_of(clk, struct clk_master, clk)
>
> struct clk_master {
> @@ -122,7 +110,7 @@ static const struct clk_ops master_ops = {
> .get_parent = clk_master_get_parent,
> };
>
> -static struct clk *
> +struct clk *
> at91_clk_register_master(struct regmap *regmap,
> const char *name, int num_parents,
> const char **parent_names,
> @@ -158,88 +146,12 @@ at91_clk_register_master(struct regmap *regmap,
> }
>
>
> -static const struct clk_master_layout at91rm9200_master_layout = {
> +const struct clk_master_layout at91rm9200_master_layout = {
> .mask = 0x31F,
> .pres_shift = 2,
> };
>
> -static const struct clk_master_layout at91sam9x5_master_layout = {
> +const struct clk_master_layout at91sam9x5_master_layout = {
> .mask = 0x373,
> .pres_shift = 4,
> };
> -
> -
> -static struct clk_master_characteristics *
> -of_at91_clk_master_get_characteristics(struct device_node *np)
> -{
> - struct clk_master_characteristics *characteristics;
> -
> - characteristics = xzalloc(sizeof(*characteristics));
> -
> - if (of_at91_get_clk_range(np, "atmel,clk-output-range", &characteristics->output))
> - goto out_free_characteristics;
> -
> - of_property_read_u32_array(np, "atmel,clk-divisors",
> - characteristics->divisors, 4);
> -
> - characteristics->have_div3_pres =
> - of_property_read_bool(np, "atmel,master-clk-have-div3-pres");
> -
> - return characteristics;
> -
> -out_free_characteristics:
> - kfree(characteristics);
> - return NULL;
> -}
> -
> -static int
> -of_at91_clk_master_setup(struct device_node *np,
> - const struct clk_master_layout *layout)
> -{
> - struct clk *clk;
> - unsigned int num_parents;
> - const char *parent_names[MASTER_SOURCE_MAX];
> - const char *name = np->name;
> - struct clk_master_characteristics *characteristics;
> - struct regmap *regmap;
> -
> - num_parents = of_clk_get_parent_count(np);
> - if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX)
> - return -EINVAL;
> -
> - of_clk_parent_fill(np, parent_names, num_parents);
> -
> - of_property_read_string(np, "clock-output-names", &name);
> -
> - characteristics = of_at91_clk_master_get_characteristics(np);
> - if (!characteristics)
> - return -EINVAL;
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - clk = at91_clk_register_master(regmap, name, num_parents,
> - parent_names, layout,
> - characteristics);
> - if (IS_ERR(clk)) {
> - kfree(characteristics);
> - return PTR_ERR(clk);
> - }
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -
> -static void __init of_at91rm9200_clk_master_setup(struct device_node *np)
> -{
> - of_at91_clk_master_setup(np, &at91rm9200_master_layout);
> -}
> -CLK_OF_DECLARE(at91rm9200_clk_master, "atmel,at91rm9200-clk-master",
> - of_at91rm9200_clk_master_setup);
> -
> -static void __init of_at91sam9x5_clk_master_setup(struct device_node *np)
> -{
> - of_at91_clk_master_setup(np, &at91sam9x5_master_layout);
> -}
> -CLK_OF_DECLARE(at91sam9x5_clk_master, "atmel,at91sam9x5-clk-master",
> - of_at91sam9x5_clk_master_setup);
> diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c
> index bbe6ffac6..00852672d 100644
> --- a/drivers/clk/at91/clk-peripheral.c
> +++ b/drivers/clk/at91/clk-peripheral.c
> @@ -10,7 +10,6 @@
>
> #include <common.h>
> #include <clock.h>
> -#include <of.h>
> #include <linux/list.h>
> #include <linux/clk.h>
> #include <linux/clk/at91_pmc.h>
> @@ -19,11 +18,6 @@
>
> #include "pmc.h"
>
> -#define PERIPHERAL_MAX 64
> -
> -#define PERIPHERAL_AT91RM9200 0
> -#define PERIPHERAL_AT91SAM9X5 1
> -
> #define PERIPHERAL_ID_MIN 2
> #define PERIPHERAL_ID_MAX 31
> #define PERIPHERAL_MASK(id) (1 << ((id) & PERIPHERAL_ID_MAX))
> @@ -105,7 +99,7 @@ static const struct clk_ops peripheral_ops = {
> .is_enabled = clk_peripheral_is_enabled,
> };
>
> -static struct clk *
> +struct clk *
> at91_clk_register_peripheral(struct regmap *regmap, const char *name,
> const char *parent_name, u32 id)
> {
> @@ -317,7 +311,7 @@ static const struct clk_ops sam9x5_peripheral_ops = {
> .set_rate = clk_sam9x5_peripheral_set_rate,
> };
>
> -static struct clk *
> +struct clk *
> at91_clk_register_sam9x5_peripheral(struct regmap *regmap,
> const char *name, const char *parent_name,
> u32 id, const struct clk_range *range)
> @@ -355,75 +349,3 @@ at91_clk_register_sam9x5_peripheral(struct regmap *regmap,
>
> return &periph->clk;
> }
> -
> -static int
> -of_at91_clk_periph_setup(struct device_node *np, u8 type)
> -{
> - int num;
> - u32 id;
> - struct clk *clk;
> - const char *parent_name;
> - const char *name;
> - struct device_node *periphclknp;
> - struct regmap *regmap;
> -
> - parent_name = of_clk_get_parent_name(np, 0);
> - if (!parent_name)
> - return -ENOENT;
> -
> - num = of_get_child_count(np);
> - if (!num || num > PERIPHERAL_MAX)
> - return -EINVAL;
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - for_each_child_of_node(np, periphclknp) {
> - if (of_property_read_u32(periphclknp, "reg", &id))
> - continue;
> -
> - if (id >= PERIPHERAL_MAX)
> - continue;
> -
> - if (of_property_read_string(np, "clock-output-names", &name))
> - name = periphclknp->name;
> -
> - if (type == PERIPHERAL_AT91RM9200) {
> - clk = at91_clk_register_peripheral(regmap, name,
> - parent_name, id);
> - } else {
> - struct clk_range range = CLK_RANGE(0, 0);
> -
> - of_at91_get_clk_range(periphclknp,
> - "atmel,clk-output-range",
> - &range);
> -
> - clk = at91_clk_register_sam9x5_peripheral(regmap,
> - name,
> - parent_name,
> - id, &range);
> - }
> -
> - if (IS_ERR(clk))
> - continue;
> -
> - of_clk_add_provider(periphclknp, of_clk_src_simple_get, clk);
> - }
> -
> - return 0;
> -}
> -
> -static int of_at91rm9200_clk_periph_setup(struct device_node *np)
> -{
> - return of_at91_clk_periph_setup(np, PERIPHERAL_AT91RM9200);
> -}
> -CLK_OF_DECLARE(at91rm9200_clk_periph, "atmel,at91rm9200-clk-peripheral",
> - of_at91rm9200_clk_periph_setup);
> -
> -static int of_at91sam9x5_clk_periph_setup(struct device_node *np)
> -{
> - return of_at91_clk_periph_setup(np, PERIPHERAL_AT91SAM9X5);
> -}
> -CLK_OF_DECLARE(at91sam9x5_clk_periph, "atmel,at91sam9x5-clk-peripheral",
> - of_at91sam9x5_clk_periph_setup);
> diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c
> index e0af4fe5a..bc504e8a9 100644
> --- a/drivers/clk/at91/clk-pll.c
> +++ b/drivers/clk/at91/clk-pll.c
> @@ -36,20 +36,6 @@
> #define PLL_OUT_SHIFT 14
> #define PLL_MAX_ID 1
>
> -struct clk_pll_characteristics {
> - struct clk_range input;
> - int num_output;
> - struct clk_range *output;
> - u16 *icpll;
> - u8 *out;
> -};
> -
> -struct clk_pll_layout {
> - u32 pllr_mask;
> - u16 mul_mask;
> - u8 mul_shift;
> -};
> -
> #define to_clk_pll(clk) container_of(clk, struct clk_pll, clk)
>
> struct clk_pll {
> @@ -299,7 +285,7 @@ static const struct clk_ops pll_ops = {
> .set_rate = clk_pll_set_rate,
> };
>
> -static struct clk *
> +struct clk *
> at91_clk_register_pll(struct regmap *regmap, const char *name,
> const char *parent_name, u8 id,
> const struct clk_pll_layout *layout,
> @@ -341,176 +327,26 @@ at91_clk_register_pll(struct regmap *regmap, const char *name,
> }
>
>
> -static const struct clk_pll_layout at91rm9200_pll_layout = {
> +const struct clk_pll_layout at91rm9200_pll_layout = {
> .pllr_mask = 0x7FFFFFF,
> .mul_shift = 16,
> .mul_mask = 0x7FF,
> };
>
> -static const struct clk_pll_layout at91sam9g45_pll_layout = {
> +const struct clk_pll_layout at91sam9g45_pll_layout = {
> .pllr_mask = 0xFFFFFF,
> .mul_shift = 16,
> .mul_mask = 0xFF,
> };
>
> -static const struct clk_pll_layout at91sam9g20_pllb_layout = {
> +const struct clk_pll_layout at91sam9g20_pllb_layout = {
> .pllr_mask = 0x3FFFFF,
> .mul_shift = 16,
> .mul_mask = 0x3F,
> };
>
> -static const struct clk_pll_layout sama5d3_pll_layout = {
> +const struct clk_pll_layout sama5d3_pll_layout = {
> .pllr_mask = 0x1FFFFFF,
> .mul_shift = 18,
> .mul_mask = 0x7F,
> };
> -
> -
> -static struct clk_pll_characteristics *
> -of_at91_clk_pll_get_characteristics(struct device_node *np)
> -{
> - int i;
> - int offset;
> - u32 tmp;
> - int num_output;
> - u32 num_cells;
> - struct clk_range input;
> - struct clk_range *output;
> - u8 *out = NULL;
> - u16 *icpll = NULL;
> - struct clk_pll_characteristics *characteristics;
> -
> - if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input))
> - return NULL;
> -
> - if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells",
> - &num_cells))
> - return NULL;
> -
> - if (num_cells < 2 || num_cells > 4)
> - return NULL;
> -
> - if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp))
> - return NULL;
> - num_output = tmp / (sizeof(u32) * num_cells);
> -
> - characteristics = xzalloc(sizeof(*characteristics));
> - output = xzalloc(sizeof(*output) * num_output);
> -
> - if (num_cells > 2)
> - out = xzalloc(sizeof(*out) * num_output);
> -
> - if (num_cells > 3)
> - icpll = xzalloc(sizeof(*icpll) * num_output);
> -
> -
> - for (i = 0; i < num_output; i++) {
> - offset = i * num_cells;
> - if (of_property_read_u32_index(np,
> - "atmel,pll-clk-output-ranges",
> - offset, &tmp))
> - goto out_free_output;
> - output[i].min = tmp;
> - if (of_property_read_u32_index(np,
> - "atmel,pll-clk-output-ranges",
> - offset + 1, &tmp))
> - goto out_free_output;
> - output[i].max = tmp;
> -
> - if (num_cells == 2)
> - continue;
> -
> - if (of_property_read_u32_index(np,
> - "atmel,pll-clk-output-ranges",
> - offset + 2, &tmp))
> - goto out_free_output;
> - out[i] = tmp;
> -
> - if (num_cells == 3)
> - continue;
> -
> - if (of_property_read_u32_index(np,
> - "atmel,pll-clk-output-ranges",
> - offset + 3, &tmp))
> - goto out_free_output;
> - icpll[i] = tmp;
> - }
> -
> - characteristics->input = input;
> - characteristics->num_output = num_output;
> - characteristics->output = output;
> - characteristics->out = out;
> - characteristics->icpll = icpll;
> - return characteristics;
> -
> -out_free_output:
> - kfree(icpll);
> - kfree(out);
> - kfree(output);
> - kfree(characteristics);
> - return NULL;
> -}
> -
> -static int
> -of_at91_clk_pll_setup(struct device_node *np,
> - const struct clk_pll_layout *layout)
> -{
> - u32 id;
> - struct clk *clk;
> - struct regmap *regmap;
> - const char *parent_name;
> - const char *name = np->name;
> - struct clk_pll_characteristics *characteristics;
> -
> - if (of_property_read_u32(np, "reg", &id))
> - return -EINVAL;
> -
> - parent_name = of_clk_get_parent_name(np, 0);
> -
> - of_property_read_string(np, "clock-output-names", &name);
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - characteristics = of_at91_clk_pll_get_characteristics(np);
> - if (!characteristics)
> - return -EINVAL;
> -
> - clk = at91_clk_register_pll(regmap, name, parent_name, id, layout,
> - characteristics);
> - if (IS_ERR(clk)) {
> - kfree(characteristics);
> - return PTR_ERR(clk);
> - }
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -
> -static int of_at91rm9200_clk_pll_setup(struct device_node *np)
> -{
> - return of_at91_clk_pll_setup(np, &at91rm9200_pll_layout);
> -}
> -CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll",
> - of_at91rm9200_clk_pll_setup);
> -
> -static int of_at91sam9g45_clk_pll_setup(struct device_node *np)
> -{
> - return of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout);
> -}
> -CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll",
> - of_at91sam9g45_clk_pll_setup);
> -
> -static int of_at91sam9g20_clk_pllb_setup(struct device_node *np)
> -{
> - return of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout);
> -}
> -CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb",
> - of_at91sam9g20_clk_pllb_setup);
> -
> -static int of_sama5d3_clk_pll_setup(struct device_node *np)
> -{
> - return of_at91_clk_pll_setup(np, &sama5d3_pll_layout);
> -}
> -CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll",
> - of_sama5d3_clk_pll_setup);
> diff --git a/drivers/clk/at91/clk-plldiv.c b/drivers/clk/at91/clk-plldiv.c
> index 917108e84..98d79ef59 100644
> --- a/drivers/clk/at91/clk-plldiv.c
> +++ b/drivers/clk/at91/clk-plldiv.c
> @@ -78,7 +78,7 @@ static const struct clk_ops plldiv_ops = {
> .set_rate = clk_plldiv_set_rate,
> };
>
> -static struct clk *
> +struct clk *
> at91_clk_register_plldiv(struct regmap *regmap, const char *name,
> const char *parent_name)
> {
> @@ -108,28 +108,3 @@ at91_clk_register_plldiv(struct regmap *regmap, const char *name,
>
> return &plldiv->clk;
> }
> -
> -static int
> -of_at91sam9x5_clk_plldiv_setup(struct device_node *np)
> -{
> - struct clk *clk;
> - const char *parent_name;
> - const char *name = np->name;
> - struct regmap *regmap;
> -
> - parent_name = of_clk_get_parent_name(np, 0);
> -
> - of_property_read_string(np, "clock-output-names", &name);
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - clk = at91_clk_register_plldiv(regmap, name, parent_name);
> - if (IS_ERR(clk))
> - return PTR_ERR(clk);
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -CLK_OF_DECLARE(at91sam9x5_clk_plldiv, "atmel,at91sam9x5-clk-plldiv",
> - of_at91sam9x5_clk_plldiv_setup);
> diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
> index ddb18c0f7..857ede1ca 100644
> --- a/drivers/clk/at91/clk-programmable.c
> +++ b/drivers/clk/at91/clk-programmable.c
> @@ -10,7 +10,6 @@
>
> #include <common.h>
> #include <clock.h>
> -#include <of.h>
> #include <io.h>
> #include <linux/list.h>
> #include <linux/clk.h>
> @@ -28,12 +27,6 @@
> #define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & PROG_PRES_MASK)
> #define PROG_MAX_RM9200_CSS 3
>
> -struct clk_programmable_layout {
> - u8 pres_shift;
> - u8 css_mask;
> - u8 have_slck_mck;
> -};
> -
> struct clk_programmable {
> struct clk clk;
> struct regmap *regmap;
> @@ -130,7 +123,7 @@ static const struct clk_ops programmable_ops = {
> .set_rate = clk_programmable_set_rate,
> };
>
> -static struct clk *
> +struct clk *
> at91_clk_register_programmable(struct regmap *regmap,
> const char *name, const char **parent_names,
> u8 num_parents, u8 id,
> @@ -167,88 +160,20 @@ at91_clk_register_programmable(struct regmap *regmap,
> return &prog->clk;
> }
>
> -static const struct clk_programmable_layout at91rm9200_programmable_layout = {
> +const struct clk_programmable_layout at91rm9200_programmable_layout = {
> .pres_shift = 2,
> .css_mask = 0x3,
> .have_slck_mck = 0,
> };
>
> -static const struct clk_programmable_layout at91sam9g45_programmable_layout = {
> +const struct clk_programmable_layout at91sam9g45_programmable_layout = {
> .pres_shift = 2,
> .css_mask = 0x3,
> .have_slck_mck = 1,
> };
>
> -static const struct clk_programmable_layout at91sam9x5_programmable_layout = {
> +const struct clk_programmable_layout at91sam9x5_programmable_layout = {
> .pres_shift = 4,
> .css_mask = 0x7,
> .have_slck_mck = 0,
> };
> -
> -static int
> -of_at91_clk_prog_setup(struct device_node *np,
> - const struct clk_programmable_layout *layout)
> -{
> - int num;
> - u32 id;
> - struct clk *clk;
> - unsigned int num_parents;
> - const char *parent_names[PROG_SOURCE_MAX];
> - const char *name;
> - struct device_node *progclknp;
> - struct regmap *regmap;
> -
> - num_parents = of_clk_get_parent_count(np);
> - if (num_parents == 0 || num_parents > PROG_SOURCE_MAX)
> - return -EINVAL;
> -
> - of_clk_parent_fill(np, parent_names, num_parents);
> -
> - num = of_get_child_count(np);
> - if (!num || num > (PROG_ID_MAX + 1))
> - return -EINVAL;
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - for_each_child_of_node(np, progclknp) {
> - if (of_property_read_u32(progclknp, "reg", &id))
> - continue;
> -
> - if (of_property_read_string(np, "clock-output-names", &name))
> - name = progclknp->name;
> -
> - clk = at91_clk_register_programmable(regmap, name,
> - parent_names, num_parents,
> - id, layout);
> - if (IS_ERR(clk))
> - continue;
> -
> - of_clk_add_provider(progclknp, of_clk_src_simple_get, clk);
> - }
> -
> - return 0;
> -}
> -
> -
> -static void __init of_at91rm9200_clk_prog_setup(struct device_node *np)
> -{
> - of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout);
> -}
> -CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable",
> - of_at91rm9200_clk_prog_setup);
> -
> -static int of_at91sam9g45_clk_prog_setup(struct device_node *np)
> -{
> - return of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout);
> -}
> -CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable",
> - of_at91sam9g45_clk_prog_setup);
> -
> -static int of_at91sam9x5_clk_prog_setup(struct device_node *np)
> -{
> - return of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout);
> -}
> -CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable",
> - of_at91sam9x5_clk_prog_setup);
> diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c
> index d4981e7b4..d19f7e15a 100644
> --- a/drivers/clk/at91/clk-slow.c
> +++ b/drivers/clk/at91/clk-slow.c
> @@ -12,7 +12,6 @@
>
> #include <common.h>
> #include <clock.h>
> -#include <of.h>
> #include <io.h>
> #include <linux/list.h>
> #include <linux/clk.h>
> @@ -44,7 +43,7 @@ static const struct clk_ops sam9260_slow_ops = {
> .get_parent = clk_sam9260_slow_get_parent,
> };
>
> -static struct clk * __init
> +struct clk * __init
> at91_clk_register_sam9260_slow(struct regmap *regmap,
> const char *name,
> const char **parent_names,
> @@ -76,33 +75,3 @@ at91_clk_register_sam9260_slow(struct regmap *regmap,
>
> return &slowck->clk;
> }
> -
> -static int of_at91sam9260_clk_slow_setup(struct device_node *np)
> -{
> - struct clk *clk;
> - const char *parent_names[2];
> - unsigned int num_parents;
> - const char *name = np->name;
> - struct regmap *regmap;
> -
> - num_parents = of_clk_get_parent_count(np);
> - if (num_parents != 2)
> - return -EINVAL;
> -
> - of_clk_parent_fill(np, parent_names, num_parents);
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - of_property_read_string(np, "clock-output-names", &name);
> -
> - clk = at91_clk_register_sam9260_slow(regmap, name, parent_names,
> - num_parents);
> - if (IS_ERR(clk))
> - return PTR_ERR(clk);
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -
> -CLK_OF_DECLARE(at91sam9260_clk_slow, "atmel,at91sam9260-clk-slow",
> - of_at91sam9260_clk_slow_setup);
> diff --git a/drivers/clk/at91/clk-smd.c b/drivers/clk/at91/clk-smd.c
> index 65c53efbb..e81f0d4d4 100644
> --- a/drivers/clk/at91/clk-smd.c
> +++ b/drivers/clk/at91/clk-smd.c
> @@ -10,7 +10,6 @@
>
> #include <common.h>
> #include <clock.h>
> -#include <of.h>
> #include <io.h>
> #include <linux/list.h>
> #include <linux/clk.h>
> @@ -115,7 +114,7 @@ static const struct clk_ops at91sam9x5_smd_ops = {
> .set_rate = at91sam9x5_clk_smd_set_rate,
> };
>
> -static struct clk *
> +struct clk *
> at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
> const char **parent_names, u8 num_parents)
> {
> @@ -140,33 +139,3 @@ at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
>
> return &smd->clk;
> }
> -
> -static int of_at91sam9x5_clk_smd_setup(struct device_node *np)
> -{
> - struct clk *clk;
> - unsigned int num_parents;
> - const char *parent_names[SMD_SOURCE_MAX];
> - const char *name = np->name;
> - struct regmap *regmap;
> -
> - num_parents = of_clk_get_parent_count(np);
> - if (num_parents == 0 || num_parents > SMD_SOURCE_MAX)
> - return -EINVAL;
> -
> - of_clk_parent_fill(np, parent_names, num_parents);
> -
> - of_property_read_string(np, "clock-output-names", &name);
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - clk = at91sam9x5_clk_register_smd(regmap, name, parent_names,
> - num_parents);
> - if (IS_ERR(clk))
> - return PTR_ERR(clk);
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -CLK_OF_DECLARE(at91sam9x5_clk_smd, "atmel,at91sam9x5-clk-smd",
> - of_at91sam9x5_clk_smd_setup);
> diff --git a/drivers/clk/at91/clk-system.c b/drivers/clk/at91/clk-system.c
> index 021930e54..8be5c7f2b 100644
> --- a/drivers/clk/at91/clk-system.c
> +++ b/drivers/clk/at91/clk-system.c
> @@ -9,7 +9,6 @@
> */
> #include <common.h>
> #include <clock.h>
> -#include <of.h>
> #include <io.h>
> #include <linux/list.h>
> #include <linux/clk.h>
> @@ -91,7 +90,7 @@ static const struct clk_ops system_ops = {
> .is_enabled = clk_system_is_enabled,
> };
>
> -static struct clk *
> +struct clk *
> at91_clk_register_system(struct regmap *regmap, const char *name,
> const char *parent_name, u8 id)
> {
> @@ -119,42 +118,3 @@ at91_clk_register_system(struct regmap *regmap, const char *name,
>
> return &sys->clk;
> }
> -
> -static int of_at91rm9200_clk_sys_setup(struct device_node *np)
> -{
> - int num;
> - u32 id;
> - struct clk *clk;
> - const char *name;
> - struct device_node *sysclknp;
> - const char *parent_name;
> - struct regmap *regmap;
> -
> - num = of_get_child_count(np);
> - if (num > (SYSTEM_MAX_ID + 1))
> - return -EINVAL;
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - for_each_child_of_node(np, sysclknp) {
> - if (of_property_read_u32(sysclknp, "reg", &id))
> - continue;
> -
> - if (of_property_read_string(np, "clock-output-names", &name))
> - name = sysclknp->name;
> -
> - parent_name = of_clk_get_parent_name(sysclknp, 0);
> -
> - clk = at91_clk_register_system(regmap, name, parent_name, id);
> - if (IS_ERR(clk))
> - continue;
> -
> - of_clk_add_provider(sysclknp, of_clk_src_simple_get, clk);
> - }
> -
> - return 0;
> -}
> -CLK_OF_DECLARE(at91rm9200_clk_sys, "atmel,at91rm9200-clk-system",
> - of_at91rm9200_clk_sys_setup);
> diff --git a/drivers/clk/at91/clk-usb.c b/drivers/clk/at91/clk-usb.c
> index 99ba671c9..0eb0b1f5b 100644
> --- a/drivers/clk/at91/clk-usb.c
> +++ b/drivers/clk/at91/clk-usb.c
> @@ -10,7 +10,6 @@
>
> #include <common.h>
> #include <clock.h>
> -#include <of.h>
> #include <io.h>
> #include <linux/list.h>
> #include <linux/clk.h>
> @@ -144,7 +143,7 @@ static const struct clk_ops at91sam9n12_usb_ops = {
> .set_rate = at91sam9x5_clk_usb_set_rate,
> };
>
> -static struct clk *
> +struct clk *
> at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
> const char **parent_names, u8 num_parents)
> {
> @@ -172,7 +171,7 @@ at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
> return &usb->clk;
> }
>
> -static struct clk *
> +struct clk *
> at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
> const char *parent_name)
> {
> @@ -282,7 +281,7 @@ static const struct clk_ops at91rm9200_usb_ops = {
> .set_rate = at91rm9200_clk_usb_set_rate,
> };
>
> -static struct clk *
> +struct clk *
> at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
> const char *parent_name, const u32 *divisors)
> {
> @@ -308,90 +307,3 @@ at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
>
> return &usb->clk;
> }
> -
> -static int of_at91sam9x5_clk_usb_setup(struct device_node *np)
> -{
> - struct clk *clk;
> - unsigned int num_parents;
> - const char *parent_names[USB_SOURCE_MAX];
> - const char *name = np->name;
> - struct regmap *regmap;
> -
> - num_parents = of_clk_get_parent_count(np);
> - if (num_parents == 0 || num_parents > USB_SOURCE_MAX)
> - return -EINVAL;
> -
> - of_clk_parent_fill(np, parent_names, num_parents);
> -
> - of_property_read_string(np, "clock-output-names", &name);
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - clk = at91sam9x5_clk_register_usb(regmap, name, parent_names,
> - num_parents);
> - if (IS_ERR(clk))
> - return PTR_ERR(clk);
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -CLK_OF_DECLARE(at91sam9x5_clk_usb, "atmel,at91sam9x5-clk-usb",
> - of_at91sam9x5_clk_usb_setup);
> -
> -static int of_at91sam9n12_clk_usb_setup(struct device_node *np)
> -{
> - struct clk *clk;
> - const char *parent_name;
> - const char *name = np->name;
> - struct regmap *regmap;
> -
> - parent_name = of_clk_get_parent_name(np, 0);
> - if (!parent_name)
> - return -EINVAL;
> -
> - of_property_read_string(np, "clock-output-names", &name);
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - clk = at91sam9n12_clk_register_usb(regmap, name, parent_name);
> - if (IS_ERR(clk))
> - return PTR_ERR(clk);
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -CLK_OF_DECLARE(at91sam9n12_clk_usb, "atmel,at91sam9n12-clk-usb",
> - of_at91sam9n12_clk_usb_setup);
> -
> -static int of_at91rm9200_clk_usb_setup(struct device_node *np)
> -{
> - struct clk *clk;
> - const char *parent_name;
> - const char *name = np->name;
> - u32 divisors[4] = {0, 0, 0, 0};
> - struct regmap *regmap;
> -
> - parent_name = of_clk_get_parent_name(np, 0);
> - if (!parent_name)
> - return -EINVAL;
> -
> - of_property_read_u32_array(np, "atmel,clk-divisors", divisors, 4);
> - if (!divisors[0])
> - return -EINVAL;
> -
> - of_property_read_string(np, "clock-output-names", &name);
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return PTR_ERR(regmap);
> -
> - clk = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors);
> - if (IS_ERR(clk))
> - return PTR_ERR(clk);
> -
> - return of_clk_add_provider(np, of_clk_src_simple_get, clk);
> -}
> -CLK_OF_DECLARE(at91rm9200_clk_usb, "atmel,at91rm9200-clk-usb",
> - of_at91rm9200_clk_usb_setup);
> diff --git a/drivers/clk/at91/clk-utmi.c b/drivers/clk/at91/clk-utmi.c
> index 6a1c5e6df..c40af34d0 100644
> --- a/drivers/clk/at91/clk-utmi.c
> +++ b/drivers/clk/at91/clk-utmi.c
> @@ -10,21 +10,27 @@
>
> #include <common.h>
> #include <clock.h>
> -#include <of.h>
> #include <linux/list.h>
> #include <linux/clk.h>
> #include <linux/clk/at91_pmc.h>
> #include <mfd/syscon.h>
> #include <regmap.h>
>
> +#include <soc/at91/atmel-sfr.h>
> +
> #include "pmc.h"
>
> -#define UTMI_FIXED_MUL 40
> +/*
> + * The purpose of this clock is to generate a 480 MHz signal. A different
> + * rate can't be configured.
> + */
> +#define UTMI_RATE 480000000
>
> struct clk_utmi {
> struct clk clk;
> - struct regmap *regmap;
> const char *parent;
> + struct regmap *regmap_pmc;
> + struct regmap *regmap_sfr;
> };
>
> #define to_clk_utmi(clk) container_of(clk, struct clk_utmi, clk)
> @@ -40,13 +46,55 @@ static inline bool clk_utmi_ready(struct regmap *regmap)
>
> static int clk_utmi_enable(struct clk *clk)
> {
> + struct clk *hw_parent;
> struct clk_utmi *utmi = to_clk_utmi(clk);
> unsigned int uckr = AT91_PMC_UPLLEN | AT91_PMC_UPLLCOUNT |
> AT91_PMC_BIASEN;
> + unsigned int utmi_ref_clk_freq;
> + unsigned long parent_rate;
> +
> + /*
> + * If mainck rate is different from 12 MHz, we have to configure the
> + * FREQ field of the SFR_UTMICKTRIM register to generate properly
> + * the utmi clock.
> + */
> + hw_parent = clk_get_parent(clk);
> + parent_rate = clk_get_rate(hw_parent);
> +
> + switch (parent_rate) {
> + case 12000000:
> + utmi_ref_clk_freq = 0;
> + break;
> + case 16000000:
> + utmi_ref_clk_freq = 1;
> + break;
> + case 24000000:
> + utmi_ref_clk_freq = 2;
> + break;
> + /*
> + * Not supported on SAMA5D2 but it's not an issue since MAINCK
> + * maximum value is 24 MHz.
> + */
> + case 48000000:
> + utmi_ref_clk_freq = 3;
> + break;
> + default:
> + pr_err("UTMICK: unsupported mainck rate\n");
> + return -EINVAL;
> + }
> +
> +
> + if (utmi->regmap_sfr) {
> + regmap_write_bits(utmi->regmap_sfr, AT91_SFR_UTMICKTRIM,
> + AT91_UTMICKTRIM_FREQ, utmi_ref_clk_freq);
> + } else if (utmi_ref_clk_freq) {
> + pr_err("UTMICK: sfr node required\n");
> + return -EINVAL;
> + }
> + regmap_write_bits(utmi->regmap_pmc, AT91_CKGR_UCKR, uckr, uckr);
>
> - regmap_write_bits(utmi->regmap, AT91_CKGR_UCKR, uckr, uckr);
>
> - while (!clk_utmi_ready(utmi->regmap))
> + while (!clk_utmi_ready(utmi->regmap_pmc))
> barrier();
>
> return 0;
> @@ -56,21 +104,22 @@ static int clk_utmi_is_enabled(struct clk *clk)
> {
> struct clk_utmi *utmi = to_clk_utmi(clk);
>
> - return clk_utmi_ready(utmi->regmap);
> + return clk_utmi_ready(utmi->regmap_pmc);
> }
>
> static void clk_utmi_disable(struct clk *clk)
> {
> struct clk_utmi *utmi = to_clk_utmi(clk);
>
> - regmap_write_bits(utmi->regmap, AT91_CKGR_UCKR, AT91_PMC_UPLLEN, 0);
> + regmap_write_bits(utmi->regmap_pmc, AT91_CKGR_UCKR,
> + AT91_PMC_UPLLEN, 0);
> }
>
> static unsigned long clk_utmi_recalc_rate(struct clk *clk,
> unsigned long parent_rate)
> {
> - /* UTMI clk is a fixed clk multiplier */
> - return parent_rate * UTMI_FIXED_MUL;
> + /* UTMI clk rate is fixed */
> + return UTMI_RATE;
> }
>
> static const struct clk_ops utmi_ops = {
> @@ -80,8 +129,8 @@ static const struct clk_ops utmi_ops = {
> .recalc_rate = clk_utmi_recalc_rate,
> };
>
> -static struct clk * __init
> -at91_clk_register_utmi(struct regmap *regmap,
> +struct clk * __init
> +at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
> const char *name, const char *parent_name)
> {
> int ret;
> @@ -100,7 +149,8 @@ at91_clk_register_utmi(struct regmap *regmap,
>
> /* utmi->clk.flags = CLK_SET_RATE_GATE; */
>
> - utmi->regmap = regmap;
> + utmi->regmap_pmc = regmap_pmc;
> + utmi->regmap_sfr = regmap_sfr;
>
> ret = clk_register(&utmi->clk);
> if (ret) {
> @@ -110,29 +160,3 @@ at91_clk_register_utmi(struct regmap *regmap,
>
> return &utmi->clk;
> }
> -#if defined(CONFIG_OFTREE) && defined(CONFIG_COMMON_CLK_OF_PROVIDER)
> -static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np)
> -{
> - struct clk *clk;
> - const char *parent_name;
> - const char *name = np->name;
> - struct regmap *regmap;
> -
> - parent_name = of_clk_get_parent_name(np, 0);
> -
> - of_property_read_string(np, "clock-output-names", &name);
> -
> - regmap = syscon_node_to_regmap(of_get_parent(np));
> - if (IS_ERR(regmap))
> - return;
> -
> - clk = at91_clk_register_utmi(regmap, name, parent_name);
> - if (IS_ERR(clk))
> - return;
> -
> - of_clk_add_provider(np, of_clk_src_simple_get, clk);
> - return;
> -}
> -CLK_OF_DECLARE(at91sam9x5_clk_utmi, "atmel,at91sam9x5-clk-utmi",
> - of_at91sam9x5_clk_utmi_setup);
> -#endif
> diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
> index d156d50ca..aa73d61c5 100644
> --- a/drivers/clk/at91/pmc.c
> +++ b/drivers/clk/at91/pmc.c
> @@ -15,8 +15,13 @@
> #include <mfd/syscon.h>
> #include <regmap.h>
>
> +#include <dt-bindings/clock/at91.h>
> +
> #include "pmc.h"
>
> +#define PMC_MAX_IDS 128
> +#define PMC_MAX_PCKS 8
> +
> int of_at91_get_clk_range(struct device_node *np, const char *propname,
> struct clk_range *range)
> {
> @@ -39,3 +44,246 @@ int of_at91_get_clk_range(struct device_node *np, const char *propname,
> return 0;
> }
> EXPORT_SYMBOL_GPL(of_at91_get_clk_range);
> +
> +struct clk *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data)
> +{
> + unsigned int type = clkspec->args[0];
> + unsigned int idx = clkspec->args[1];
> + struct pmc_data *pmc_data = data;
> +
> + switch (type) {
> + case PMC_TYPE_CORE:
> + if (idx < pmc_data->ncore)
> + return pmc_data->chws[idx];
> + break;
> + case PMC_TYPE_SYSTEM:
> + if (idx < pmc_data->nsystem)
> + return pmc_data->shws[idx];
> + break;
> + case PMC_TYPE_PERIPHERAL:
> + if (idx < pmc_data->nperiph)
> + return pmc_data->phws[idx];
> + break;
> + case PMC_TYPE_GCK:
> + if (idx < pmc_data->ngck)
> + return pmc_data->ghws[idx];
> + break;
> + default:
> + break;
> + }
> +
> + pr_err("%s: invalid type (%u) or index (%u)\n", __func__, type, idx);
> +
> + return ERR_PTR(-EINVAL);
> +}
> +
> +void pmc_data_free(struct pmc_data *pmc_data)
> +{
> + kfree(pmc_data->chws);
> + kfree(pmc_data->shws);
> + kfree(pmc_data->phws);
> + kfree(pmc_data->ghws);
> +}
> +
> +struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
> + unsigned int nperiph, unsigned int ngck)
> +{
> + struct pmc_data *pmc_data = kzalloc(sizeof(*pmc_data), GFP_KERNEL);
> +
> + if (!pmc_data)
> + return NULL;
> +
> + pmc_data->ncore = ncore;
> + pmc_data->chws = kcalloc(ncore, sizeof(struct clk_hw *), GFP_KERNEL);
> + if (!pmc_data->chws)
> + goto err;
> +
> + pmc_data->nsystem = nsystem;
> + pmc_data->shws = kcalloc(nsystem, sizeof(struct clk_hw *), GFP_KERNEL);
> + if (!pmc_data->shws)
> + goto err;
> +
> + pmc_data->nperiph = nperiph;
> + pmc_data->phws = kcalloc(nperiph, sizeof(struct clk_hw *), GFP_KERNEL);
> + if (!pmc_data->phws)
> + goto err;
> +
> + pmc_data->ngck = ngck;
> + pmc_data->ghws = kcalloc(ngck, sizeof(struct clk_hw *), GFP_KERNEL);
> + if (!pmc_data->ghws)
> + goto err;
> +
> + return pmc_data;
> +
> +err:
> + pmc_data_free(pmc_data);
> +
> + return NULL;
> +}
> +
> +#ifdef CONFIG_PM
> +static struct regmap *pmcreg;
> +
> +static u8 registered_ids[PMC_MAX_IDS];
> +static u8 registered_pcks[PMC_MAX_PCKS];
> +
> +static struct
> +{
> + u32 scsr;
> + u32 pcsr0;
> + u32 uckr;
> + u32 mor;
> + u32 mcfr;
> + u32 pllar;
> + u32 mckr;
> + u32 usb;
> + u32 imr;
> + u32 pcsr1;
> + u32 pcr[PMC_MAX_IDS];
> + u32 audio_pll0;
> + u32 audio_pll1;
> + u32 pckr[PMC_MAX_PCKS];
> +} pmc_cache;
> +
> +/*
> + * As Peripheral ID 0 is invalid on AT91 chips, the identifier is stored
> + * without alteration in the table, and 0 is for unused clocks.
> + */
> +void pmc_register_id(u8 id)
> +{
> + int i;
> +
> + for (i = 0; i < PMC_MAX_IDS; i++) {
> + if (registered_ids[i] == 0) {
> + registered_ids[i] = id;
> + break;
> + }
> + if (registered_ids[i] == id)
> + break;
> + }
> +}
> +
> +/*
> + * As Programmable Clock 0 is valid on AT91 chips, there is an offset
> + * of 1 between the stored value and the real clock ID.
> + */
> +void pmc_register_pck(u8 pck)
> +{
> + int i;
> +
> + for (i = 0; i < PMC_MAX_PCKS; i++) {
> + if (registered_pcks[i] == 0) {
> + registered_pcks[i] = pck + 1;
> + break;
> + }
> + if (registered_pcks[i] == (pck + 1))
> + break;
> + }
> +}
> +
> +static int pmc_suspend(void)
> +{
> + int i;
> + u8 num;
> +
> + regmap_read(pmcreg, AT91_PMC_SCSR, &pmc_cache.scsr);
> + regmap_read(pmcreg, AT91_PMC_PCSR, &pmc_cache.pcsr0);
> + regmap_read(pmcreg, AT91_CKGR_UCKR, &pmc_cache.uckr);
> + regmap_read(pmcreg, AT91_CKGR_MOR, &pmc_cache.mor);
> + regmap_read(pmcreg, AT91_CKGR_MCFR, &pmc_cache.mcfr);
> + regmap_read(pmcreg, AT91_CKGR_PLLAR, &pmc_cache.pllar);
> + regmap_read(pmcreg, AT91_PMC_MCKR, &pmc_cache.mckr);
> + regmap_read(pmcreg, AT91_PMC_USB, &pmc_cache.usb);
> + regmap_read(pmcreg, AT91_PMC_IMR, &pmc_cache.imr);
> + regmap_read(pmcreg, AT91_PMC_PCSR1, &pmc_cache.pcsr1);
> +
> + for (i = 0; registered_ids[i]; i++) {
> + regmap_write(pmcreg, AT91_PMC_PCR,
> + (registered_ids[i] & AT91_PMC_PCR_PID_MASK));
> + regmap_read(pmcreg, AT91_PMC_PCR,
> + &pmc_cache.pcr[registered_ids[i]]);
> + }
> + for (i = 0; registered_pcks[i]; i++) {
> + num = registered_pcks[i] - 1;
> + regmap_read(pmcreg, AT91_PMC_PCKR(num), &pmc_cache.pckr[num]);
> + }
> +
> + return 0;
> +}
> +
> +static bool pmc_ready(unsigned int mask)
> +{
> + unsigned int status;
> +
> + regmap_read(pmcreg, AT91_PMC_SR, &status);
> +
> + return ((status & mask) == mask) ? 1 : 0;
> +}
> +
> +static void pmc_resume(void)
> +{
> + int i;
> + u8 num;
> + u32 tmp;
> + u32 mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
> +
> + regmap_read(pmcreg, AT91_PMC_MCKR, &tmp);
> + if (pmc_cache.mckr != tmp)
> + pr_warn("MCKR was not configured properly by the firmware\n");
> + regmap_read(pmcreg, AT91_CKGR_PLLAR, &tmp);
> + if (pmc_cache.pllar != tmp)
> + pr_warn("PLLAR was not configured properly by the firmware\n");
> +
> + regmap_write(pmcreg, AT91_PMC_SCER, pmc_cache.scsr);
> + regmap_write(pmcreg, AT91_PMC_PCER, pmc_cache.pcsr0);
> + regmap_write(pmcreg, AT91_CKGR_UCKR, pmc_cache.uckr);
> + regmap_write(pmcreg, AT91_CKGR_MOR, pmc_cache.mor);
> + regmap_write(pmcreg, AT91_CKGR_MCFR, pmc_cache.mcfr);
> + regmap_write(pmcreg, AT91_PMC_USB, pmc_cache.usb);
> + regmap_write(pmcreg, AT91_PMC_IMR, pmc_cache.imr);
> + regmap_write(pmcreg, AT91_PMC_PCER1, pmc_cache.pcsr1);
> +
> + for (i = 0; registered_ids[i]; i++) {
> + regmap_write(pmcreg, AT91_PMC_PCR,
> + pmc_cache.pcr[registered_ids[i]] |
> + AT91_PMC_PCR_CMD);
> + }
> + for (i = 0; registered_pcks[i]; i++) {
> + num = registered_pcks[i] - 1;
> + regmap_write(pmcreg, AT91_PMC_PCKR(num), pmc_cache.pckr[num]);
> + }
> +
> + if (pmc_cache.uckr & AT91_PMC_UPLLEN)
> + mask |= AT91_PMC_LOCKU;
> +
> + while (!pmc_ready(mask))
> + cpu_relax();
> +}
> +
> +static struct syscore_ops pmc_syscore_ops = {
> + .suspend = pmc_suspend,
> + .resume = pmc_resume,
> +};
> +
> +static const struct of_device_id sama5d2_pmc_dt_ids[] = {
> + { .compatible = "atmel,sama5d2-pmc" },
> + { /* sentinel */ }
> +};
> +
> +static int __init pmc_register_ops(void)
> +{
> + struct device_node *np;
> +
> + np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids);
> +
> + pmcreg = syscon_node_to_regmap(np);
> + if (IS_ERR(pmcreg))
> + return PTR_ERR(pmcreg);
> +
> + register_syscore_ops(&pmc_syscore_ops);
> +
> + return 0;
> +}
> +/* This has to happen before arch_initcall because of the tcb_clksrc driver */
> +postcore_initcall(pmc_register_ops);
> +#endif
> diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h
> index c6c14a79a..529498308 100644
> --- a/drivers/clk/at91/pmc.h
> +++ b/drivers/clk/at91/pmc.h
> @@ -13,6 +13,19 @@
> #define __PMC_H_
>
> #include <io.h>
> +#include <linux/spinlock.h>
> +#include <printk.h>
> +
> +struct pmc_data {
> + unsigned int ncore;
> + struct clk **chws;
> + unsigned int nsystem;
> + struct clk **shws;
> + unsigned int nperiph;
> + struct clk **phws;
> + unsigned int ngck;
> + struct clk **ghws;
> +};
>
> struct clk_range {
> unsigned long min;
> @@ -21,7 +34,163 @@ struct clk_range {
>
> #define CLK_RANGE(MIN, MAX) {.min = MIN, .max = MAX,}
>
> +struct clk_master_layout {
> + u32 mask;
> + u8 pres_shift;
> +};
> +
> +extern const struct clk_master_layout at91rm9200_master_layout;
> +extern const struct clk_master_layout at91sam9x5_master_layout;
> +
> +struct clk_master_characteristics {
> + struct clk_range output;
> + u32 divisors[4];
> + u8 have_div3_pres;
> +};
> +
> +struct clk_pll_layout {
> + u32 pllr_mask;
> + u16 mul_mask;
> + u8 mul_shift;
> +};
> +
> +extern const struct clk_pll_layout at91rm9200_pll_layout;
> +extern const struct clk_pll_layout at91sam9g45_pll_layout;
> +extern const struct clk_pll_layout at91sam9g20_pllb_layout;
> +extern const struct clk_pll_layout sama5d3_pll_layout;
> +
> +struct clk_pll_characteristics {
> + struct clk_range input;
> + int num_output;
> + struct clk_range *output;
> + u16 *icpll;
> + u8 *out;
> +};
> +
> +struct clk_programmable_layout {
> + u8 pres_shift;
> + u8 css_mask;
> + u8 have_slck_mck;
> +};
> +
> +extern const struct clk_programmable_layout at91rm9200_programmable_layout;
> +extern const struct clk_programmable_layout at91sam9g45_programmable_layout;
> +extern const struct clk_programmable_layout at91sam9x5_programmable_layout;
> +
> +#define ndck(a, s) (a[s - 1].id + 1)
> +#define nck(a) (a[ARRAY_SIZE(a) - 1].id + 1)
> +struct pmc_data *pmc_data_allocate(unsigned int ncore, unsigned int nsystem,
> + unsigned int nperiph, unsigned int ngck);
> +void pmc_data_free(struct pmc_data *pmc_data);
> +
> int of_at91_get_clk_range(struct device_node *np, const char *propname,
> struct clk_range *range);
>
> +struct clk *of_clk_hw_pmc_get(struct of_phandle_args *clkspec, void *data);
> +
> +struct clk *
> +at91_clk_register_audio_pll_frac(struct regmap *regmap, const char *name,
> + const char *parent_name);
> +
> +struct clk *
> +at91_clk_register_audio_pll_pad(struct regmap *regmap, const char *name,
> + const char *parent_name);
> +
> +struct clk *
> +at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
> + const char *parent_name);
> +
> +struct clk *
> +at91_clk_register_generated(struct regmap *regmap,
> + const char *name, const char **parent_names,
> + u8 num_parents, u8 id, bool pll_audio,
> + const struct clk_range *range);
> +
> +struct clk *
> +at91_clk_register_h32mx(struct regmap *regmap, const char *name,
> + const char *parent_name);
> +
> +struct clk *
> +at91_clk_i2s_mux_register(struct regmap *regmap, const char *name,
> + const char * const *parent_names,
> + unsigned int num_parents, u8 bus_id);
> +
> +struct clk *
> +at91_clk_register_main_rc_osc(struct regmap *regmap, const char *name,
> + u32 frequency, u32 accuracy);
> +struct clk *
> +at91_clk_register_main_osc(struct regmap *regmap, const char *name,
> + const char *parent_name, bool bypass);
> +struct clk *
> +at91_clk_register_rm9200_main(struct regmap *regmap,
> + const char *name,
> + const char *parent_name);
> +struct clk *
> +at91_clk_register_sam9x5_main(struct regmap *regmap, const char *name,
> + const char **parent_names, int num_parents);
> +
> +struct clk *
> +at91_clk_register_master(struct regmap *regmap, const char *name,
> + int num_parents, const char **parent_names,
> + const struct clk_master_layout *layout,
> + const struct clk_master_characteristics *characteristics);
> +
> +struct clk *
> +at91_clk_register_peripheral(struct regmap *regmap, const char *name,
> + const char *parent_name, u32 id);
> +struct clk *
> +at91_clk_register_sam9x5_peripheral(struct regmap *regmap,
> + const char *name, const char *parent_name,
> + u32 id, const struct clk_range *range);
> +
> +struct clk *
> +at91_clk_register_pll(struct regmap *regmap, const char *name,
> + const char *parent_name, u8 id,
> + const struct clk_pll_layout *layout,
> + const struct clk_pll_characteristics *characteristics);
> +struct clk *
> +at91_clk_register_plldiv(struct regmap *regmap, const char *name,
> + const char *parent_name);
> +
> +struct clk *
> +at91_clk_register_programmable(struct regmap *regmap, const char *name,
> + const char **parent_names, u8 num_parents, u8 id,
> + const struct clk_programmable_layout *layout);
> +
> +struct clk *
> +at91_clk_register_sam9260_slow(struct regmap *regmap,
> + const char *name,
> + const char **parent_names,
> + int num_parents);
> +
> +struct clk *
> +at91sam9x5_clk_register_smd(struct regmap *regmap, const char *name,
> + const char **parent_names, u8 num_parents);
> +
> +struct clk *
> +at91_clk_register_system(struct regmap *regmap, const char *name,
> + const char *parent_name, u8 id);
> +
> +struct clk *
> +at91sam9x5_clk_register_usb(struct regmap *regmap, const char *name,
> + const char **parent_names, u8 num_parents);
> +struct clk *
> +at91sam9n12_clk_register_usb(struct regmap *regmap, const char *name,
> + const char *parent_name);
> +struct clk *
> +at91rm9200_clk_register_usb(struct regmap *regmap, const char *name,
> + const char *parent_name, const u32 *divisors);
> +
> +struct clk *
> +at91_clk_register_utmi(struct regmap *regmap_pmc, struct regmap *regmap_sfr,
> + const char *name, const char *parent_name);
> +
> +#ifdef CONFIG_PM
> +void pmc_register_id(u8 id);
> +void pmc_register_pck(u8 pck);
> +#else
> +static inline void pmc_register_id(u8 id) {}
> +static inline void pmc_register_pck(u8 pck) {}
> +#endif
> +
> #endif /* __PMC_H_ */
> diff --git a/include/linux/clk.h b/include/linux/clk.h
> index 978a0a8a9..20498574f 100644
> --- a/include/linux/clk.h
> +++ b/include/linux/clk.h
> @@ -385,6 +385,11 @@ int of_clk_add_provider(struct device_node *np,
> struct clk *(*clk_src_get)(struct of_phandle_args *args,
> void *data),
> void *data);
> +
> +static inline unsigned int clk_get_num_parents(const struct clk *hw)
> +{
> + return hw->num_parents;
> +}
> #else
>
>
> @@ -430,6 +435,8 @@ static inline int of_clk_add_provider(struct device_node *np,
> }
> #endif
>
> +#define CLK_OF_DECLARE_DRIVER(name, compat, fn) CLK_OF_DECLARE(name, compat, fn)
> +
> struct string_list;
>
> int clk_name_complete(struct string_list *sl, char *instr);
> diff --git a/include/soc/at91/atmel-sfr.h b/include/soc/at91/atmel-sfr.h
> new file mode 100644
> index 000000000..482337af0
> --- /dev/null
> +++ b/include/soc/at91/atmel-sfr.h
> @@ -0,0 +1,34 @@
> +/*
> + * Atmel SFR (Special Function Registers) register offsets and bit definitions.
> + *
> + * Copyright (C) 2016 Atmel
> + *
> + * Author: Ludovic Desroches <ludovic.desroches@atmel.com>
> + *
> + * 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
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _LINUX_MFD_SYSCON_ATMEL_SFR_H
> +#define _LINUX_MFD_SYSCON_ATMEL_SFR_H
> +
> +#define AT91_SFR_DDRCFG 0x04 /* DDR Configuration Register */
> +/* 0x08 ~ 0x0c: Reserved */
> +#define AT91_SFR_OHCIICR 0x10 /* OHCI INT Configuration Register */
> +#define AT91_SFR_OHCIISR 0x14 /* OHCI INT Status Register */
> +#define AT91_SFR_UTMICKTRIM 0x30 /* UTMI Clock Trimming Register */
> +#define AT91_SFR_I2SCLKSEL 0x90 /* I2SC Register */
> +
> +/* Field definitions */
> +#define AT91_OHCIICR_SUSPEND_A BIT(8)
> +#define AT91_OHCIICR_SUSPEND_B BIT(9)
> +#define AT91_OHCIICR_SUSPEND_C BIT(10)
> +
> +#define AT91_OHCIICR_USB_SUSPEND (AT91_OHCIICR_SUSPEND_A | \
> + AT91_OHCIICR_SUSPEND_B | \
> + AT91_OHCIICR_SUSPEND_C)
> +
> +#define AT91_UTMICKTRIM_FREQ GENMASK(1, 0)
> +
> +#endif /* _LINUX_MFD_SYSCON_ATMEL_SFR_H */
>
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox
next prev parent reply other threads:[~2019-02-19 7:50 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-02-18 19:47 [PATCH v3 0/9] at91: Support PMC clock bindings Sam Ravnborg
2019-02-18 19:47 ` [PATCH v3 1/9] arm: at91: fix at91_configure_usart6 warning Sam Ravnborg
2019-02-18 19:47 ` [PATCH v3 2/9] clocksource: Do not mix depends and select for ATMEL_PIT Sam Ravnborg
2019-02-18 19:47 ` [PATCH v3 3/9] arm: at91: add SOC_SAMA5{D3,D4} Sam Ravnborg
2019-02-18 19:47 ` [PATCH v3 4/9] clk: at91: add at91sam9260 Sam Ravnborg
2019-02-18 19:47 ` [PATCH v3 5/9] clk: at91: add at91sam9rl Sam Ravnborg
2019-02-18 19:47 ` [PATCH v3 6/9] clk: at91: add at91sam9x5 Sam Ravnborg
2019-02-18 19:47 ` [PATCH v3 7/9] clk: at91: add sama5d2 Sam Ravnborg
2019-02-18 19:47 ` [PATCH v3 8/9] clk: at91: add sama5d4 Sam Ravnborg
2019-02-18 19:47 ` [PATCH v3 9/9] clk: at91: update to PMC bindings Sam Ravnborg
2019-02-19 7:50 ` Ahmad Fatoum [this message]
2019-02-19 7:52 ` [PATCH] fixup! " Ahmad Fatoum
2019-02-19 8:02 ` [PATCH] regmap: Implement syscon_regmap_lookup_by_compatible() Ahmad Fatoum
2019-02-19 10:04 ` [PATCH] fixup! clk: at91: update to PMC bindings Sam Ravnborg
2019-02-19 11:14 ` Ahmad Fatoum
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=171ac237-ef8f-502b-1433-83382d050ba1@pengutronix.de \
--to=a.fatoum@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox