From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from metis.ext.pengutronix.de ([2001:67c:670:201:290:27ff:fe1d:cc33]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gw0AX-0007ik-Lv for barebox@lists.infradead.org; Tue, 19 Feb 2019 07:50:26 +0000 Received: from gallifrey.ext.pengutronix.de ([2001:67c:670:201:5054:ff:fe8d:eefb] helo=a3f-osx.local) by metis.ext.pengutronix.de with esmtp (Exim 4.89) (envelope-from ) id 1gw0AU-0005A4-BM for barebox@lists.infradead.org; Tue, 19 Feb 2019 08:50:18 +0100 References: <20190218194759.9557-1-sam@ravnborg.org> <20190218194759.9557-10-sam@ravnborg.org> From: Ahmad Fatoum Message-ID: <171ac237-ef8f-502b-1433-83382d050ba1@pengutronix.de> Date: Tue, 19 Feb 2019 08:50:17 +0100 MIME-Version: 1.0 In-Reply-To: <20190218194759.9557-10-sam@ravnborg.org> Content-Language: en-US List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "barebox" Errors-To: barebox-bounces+u.kleine-koenig=pengutronix.de@lists.infradead.org Subject: Re: [PATCH v3 9/9] clk: at91: update to PMC bindings To: barebox@lists.infradead.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 > Tested-by: Ladislav Michl > --- > 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 > -#include > +#include > +#include > +#include > +#include > +#include > #include > -#include > -#include > -#include > +#include > +#include > > #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 > -#include > +#include > +#include > +#include > +#include > #include > -#include > -#include > -#include > +#include > + > > #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 > #include > -#include > #include > #include > #include > @@ -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 > #include > -#include > #include > #include > #include > @@ -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 > #include > -#include > #include > #include > #include > @@ -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 > #include > -#include > #include > #include > #include > @@ -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 > #include > -#include > #include > #include > #include > @@ -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 > #include > -#include > #include > #include > #include > @@ -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 > #include > -#include > #include > #include > #include > @@ -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 > #include > -#include > #include > #include > #include > @@ -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 > #include > -#include > #include > #include > #include > #include > #include > > +#include > + > #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 > #include > > +#include > + > #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 > +#include > +#include > + > +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 > + * > + * 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