diff options
author | Boris Brezillon <boris.brezillon@free-electrons.com> | 2014-09-07 10:14:29 +0400 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2016-02-17 19:52:58 +0300 |
commit | 1bdf02326b71eae7e9b4b335b881856aaf9d1af6 (patch) | |
tree | a11ad267acd940e4e7aff9846d94689158c246b2 /drivers/clk/at91/clk-generated.c | |
parent | 863a81c3be1d931bdae6426e231add9334311f13 (diff) | |
download | linux-1bdf02326b71eae7e9b4b335b881856aaf9d1af6.tar.xz |
clk: at91: make use of syscon/regmap internally
Use the regmap coming from syscon to access the registers instead of using
pmc_read/pmc_write. This allows to avoid passing the at91_pmc structure to
the child nodes of the PMC.
The final benefit is to have each clock register itself instead of having
to iterate over the children.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Acked-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Diffstat (limited to 'drivers/clk/at91/clk-generated.c')
-rw-r--r-- | drivers/clk/at91/clk-generated.c | 93 |
1 files changed, 54 insertions, 39 deletions
diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c index abc80949e1dd..5866684a6657 100644 --- a/drivers/clk/at91/clk-generated.c +++ b/drivers/clk/at91/clk-generated.c @@ -17,6 +17,8 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/io.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> #include "pmc.h" @@ -28,8 +30,9 @@ struct clk_generated { struct clk_hw hw; - struct at91_pmc *pmc; + struct regmap *regmap; struct clk_range range; + spinlock_t *lock; u32 id; u32 gckdiv; u8 parent_id; @@ -41,49 +44,52 @@ struct clk_generated { static int clk_generated_enable(struct clk_hw *hw) { struct clk_generated *gck = to_clk_generated(hw); - struct at91_pmc *pmc = gck->pmc; - u32 tmp; + unsigned long flags; pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n", __func__, gck->gckdiv, gck->parent_id); - pmc_lock(pmc); - pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); - tmp = pmc_read(pmc, AT91_PMC_PCR) & - ~(AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK); - pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_GCKCSS(gck->parent_id) - | AT91_PMC_PCR_CMD - | AT91_PMC_PCR_GCKDIV(gck->gckdiv) - | AT91_PMC_PCR_GCKEN); - pmc_unlock(pmc); + 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_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK | + AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN, + AT91_PMC_PCR_GCKCSS(gck->parent_id) | + 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) { struct clk_generated *gck = to_clk_generated(hw); - struct at91_pmc *pmc = gck->pmc; - u32 tmp; - - pmc_lock(pmc); - pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); - tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_GCKEN; - pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_CMD); - pmc_unlock(pmc); + 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) { struct clk_generated *gck = to_clk_generated(hw); - struct at91_pmc *pmc = gck->pmc; - int ret; + unsigned long flags; + unsigned int status; - pmc_lock(pmc); - pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); - ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_GCKEN); - pmc_unlock(pmc); + 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 ret; + return status & AT91_PMC_PCR_GCKEN ? 1 : 0; } static unsigned long @@ -214,13 +220,14 @@ static const struct clk_ops generated_ops = { */ static void clk_generated_startup(struct clk_generated *gck) { - struct at91_pmc *pmc = gck->pmc; u32 tmp; + unsigned long flags; - pmc_lock(pmc); - pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK)); - tmp = pmc_read(pmc, AT91_PMC_PCR); - pmc_unlock(pmc); + 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; @@ -229,8 +236,8 @@ static void clk_generated_startup(struct clk_generated *gck) } static struct clk * __init -at91_clk_register_generated(struct at91_pmc *pmc, const char *name, - const char **parent_names, u8 num_parents, +at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, const char + *name, const char **parent_names, u8 num_parents, u8 id, const struct clk_range *range) { struct clk_generated *gck; @@ -249,7 +256,8 @@ at91_clk_register_generated(struct at91_pmc *pmc, const char *name, gck->id = id; gck->hw.init = &init; - gck->pmc = pmc; + gck->regmap = regmap; + gck->lock = lock; gck->range = *range; clk = clk_register(NULL, &gck->hw); @@ -261,8 +269,7 @@ at91_clk_register_generated(struct at91_pmc *pmc, const char *name, return clk; } -void __init of_sama5d2_clk_generated_setup(struct device_node *np, - struct at91_pmc *pmc) +void __init of_sama5d2_clk_generated_setup(struct device_node *np) { int num; u32 id; @@ -272,6 +279,7 @@ void __init of_sama5d2_clk_generated_setup(struct device_node *np, 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) @@ -283,6 +291,10 @@ void __init of_sama5d2_clk_generated_setup(struct device_node *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; @@ -296,11 +308,14 @@ void __init of_sama5d2_clk_generated_setup(struct device_node *np, of_at91_get_clk_range(gcknp, "atmel,clk-output-range", &range); - clk = at91_clk_register_generated(pmc, name, parent_names, - num_parents, id, &range); + clk = at91_clk_register_generated(regmap, &pmc_pcr_lock, name, + parent_names, num_parents, + id, &range); if (IS_ERR(clk)) continue; of_clk_add_provider(gcknp, of_clk_src_simple_get, clk); } } +CLK_OF_DECLARE(of_sama5d2_clk_generated_setup, "atmel,sama5d2-clk-generated", + of_sama5d2_clk_generated_setup); |