diff options
Diffstat (limited to 'drivers/clk/at91/clk-pll.c')
-rw-r--r-- | drivers/clk/at91/clk-pll.c | 109 |
1 files changed, 49 insertions, 60 deletions
diff --git a/drivers/clk/at91/clk-pll.c b/drivers/clk/at91/clk-pll.c index bc504e8a95..027e1fc773 100644 --- a/drivers/clk/at91/clk-pll.c +++ b/drivers/clk/at91/clk-pll.c @@ -1,21 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * */ -#include <common.h> -#include <clock.h> -#include <of.h> -#include <linux/list.h> -#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/clkdev.h> #include <linux/clk/at91_pmc.h> +#include <of.h> #include <mfd/syscon.h> -#include <regmap.h> +#include <linux/regmap.h> #include "pmc.h" @@ -36,10 +29,10 @@ #define PLL_OUT_SHIFT 14 #define PLL_MAX_ID 1 -#define to_clk_pll(clk) container_of(clk, struct clk_pll, clk) +#define to_clk_pll(hw) container_of(hw, struct clk_pll, hw) struct clk_pll { - struct clk clk; + struct clk_hw hw; struct regmap *regmap; u8 id; u8 div; @@ -47,7 +40,7 @@ struct clk_pll { u16 mul; const struct clk_pll_layout *layout; const struct clk_pll_characteristics *characteristics; - const char *parent; + struct at91_clk_pms pms; }; static inline bool clk_pll_ready(struct regmap *regmap, int id) @@ -59,9 +52,9 @@ static inline bool clk_pll_ready(struct regmap *regmap, int id) return status & PLL_STATUS_MASK(id) ? 1 : 0; } -static int clk_pll_enable(struct clk *clk) +static int clk_pll_prepare(struct clk_hw *hw) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); struct regmap *regmap = pll->regmap; const struct clk_pll_layout *layout = pll->layout; const struct clk_pll_characteristics *characteristics = @@ -88,52 +81,44 @@ static int clk_pll_enable(struct clk *clk) out = characteristics->out[pll->range]; if (characteristics->icpll) - regmap_write_bits(regmap, AT91_PMC_PLLICPR, PLL_ICPR_MASK(id), + regmap_update_bits(regmap, AT91_PMC_PLLICPR, PLL_ICPR_MASK(id), characteristics->icpll[pll->range] << PLL_ICPR_SHIFT(id)); - regmap_write_bits(regmap, offset, layout->pllr_mask, - pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | - (out << PLL_OUT_SHIFT) | - ((pll->mul & layout->mul_mask) << layout->mul_shift)); + regmap_update_bits(regmap, offset, layout->pllr_mask, + pll->div | (PLL_MAX_COUNT << PLL_COUNT_SHIFT) | + (out << PLL_OUT_SHIFT) | + ((pll->mul & layout->mul_mask) << layout->mul_shift)); while (!clk_pll_ready(regmap, pll->id)) - barrier(); + cpu_relax(); return 0; } -static int clk_pll_is_enabled(struct clk *clk) +static int clk_pll_is_prepared(struct clk_hw *hw) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); return clk_pll_ready(pll->regmap, pll->id); } -static void clk_pll_disable(struct clk *clk) +static void clk_pll_unprepare(struct clk_hw *hw) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); unsigned int mask = pll->layout->pllr_mask; - regmap_write_bits(pll->regmap, PLL_REG(pll->id), mask, ~mask); + regmap_update_bits(pll->regmap, PLL_REG(pll->id), mask, ~mask); } -static unsigned long clk_pll_recalc_rate(struct clk *clk, +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - struct clk_pll *pll = to_clk_pll(clk); - unsigned int pllr; - u16 mul; - u8 div; + struct clk_pll *pll = to_clk_pll(hw); - regmap_read(pll->regmap, PLL_REG(pll->id), &pllr); - - div = PLL_DIV(pllr); - mul = PLL_MUL(pllr, pll->layout); - - if (!div || !mul) + if (!pll->div || !pll->mul) return 0; - return (parent_rate / div) * (mul + 1); + return (parent_rate / pll->div) * (pll->mul + 1); } static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, @@ -246,19 +231,19 @@ static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate, return bestrate; } -static long clk_pll_round_rate(struct clk *clk, unsigned long rate, - unsigned long *parent_rate) +static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); return clk_pll_get_best_div_mul(pll, rate, *parent_rate, NULL, NULL, NULL); } -static int clk_pll_set_rate(struct clk *clk, unsigned long rate, +static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_pll *pll = to_clk_pll(clk); + struct clk_pll *pll = to_clk_pll(hw); long ret; u32 div; u32 mul; @@ -277,21 +262,23 @@ static int clk_pll_set_rate(struct clk *clk, unsigned long rate, } static const struct clk_ops pll_ops = { - .enable = clk_pll_enable, - .disable = clk_pll_disable, - .is_enabled = clk_pll_is_enabled, + .enable = clk_pll_prepare, + .disable = clk_pll_unprepare, + .is_enabled = clk_pll_is_prepared, .recalc_rate = clk_pll_recalc_rate, .round_rate = clk_pll_round_rate, .set_rate = clk_pll_set_rate, }; -struct clk * +struct clk_hw * __init 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_pll *pll; + struct clk_hw *hw; + struct clk_init_data init; int offset = PLL_REG(id); unsigned int pllr; int ret; @@ -299,17 +286,18 @@ at91_clk_register_pll(struct regmap *regmap, const char *name, if (id > PLL_MAX_ID) return ERR_PTR(-EINVAL); - pll = xzalloc(sizeof(*pll)); - - pll->parent = parent_name; - pll->clk.name = name; - pll->clk.ops = &pll_ops; - pll->clk.parent_names = &pll->parent; - pll->clk.num_parents = 1; + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); - /* init.flags = CLK_SET_RATE_GATE; */ + init.name = name; + init.ops = &pll_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_SET_RATE_GATE; pll->id = id; + pll->hw.init = &init; pll->layout = layout; pll->characteristics = characteristics; pll->regmap = regmap; @@ -317,13 +305,14 @@ at91_clk_register_pll(struct regmap *regmap, const char *name, pll->div = PLL_DIV(pllr); pll->mul = PLL_MUL(pllr, layout); - ret = clk_register(&pll->clk); + hw = &pll->hw; + ret = clk_hw_register(NULL, &pll->hw); if (ret) { kfree(pll); - return ERR_PTR(ret); + hw = ERR_PTR(ret); } - return &pll->clk; + return hw; } |