diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-20 22:40:32 (GMT) |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-20 22:40:32 (GMT) |
commit | 46e595a17dcf11404f713845ecb5b06b92a94e43 (patch) | |
tree | 60e2d9d54af23f6853a93a477acd17c837a55dab /drivers/clk/at91/clk-programmable.c | |
parent | e3b1f64e04f57198ca0ab1216d824a5547be8446 (diff) | |
parent | 33b96d2c9579213cf3f36d7b29841b1e464750c4 (diff) | |
download | linux-46e595a17dcf11404f713845ecb5b06b92a94e43.tar.xz |
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC driver updates from Arnd Bergmann:
"Driver updates for ARM SoCs, these contain various things that touch
the drivers/ directory but got merged through arm-soc for practical
reasons:
- Rockchip rk3368 gains power domain support
- Small updates for the ARM spmi driver
- The Atmel PMC driver saw a larger rework, touching both
arch/arm/mach-at91 and drivers/clk/at91
- All reset controller driver changes alway get merged through
arm-soc, though this time the largest change is the addition of a
MIPS pistachio reset driver
- One bugfix for the NXP (formerly Freescale) i.MX weim bus driver"
* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (43 commits)
bus: imx-weim: Take the 'status' property value into account
clk: at91: remove useless includes
clk: at91: pmc: remove useless capacities handling
clk: at91: pmc: drop at91_pmc_base
usb: gadget: atmel: access the PMC using regmap
ARM: at91: remove useless includes and function prototypes
ARM: at91: pm: move idle functions to pm.c
ARM: at91: pm: find and remap the pmc
ARM: at91: pm: simply call at91_pm_init
clk: at91: pmc: move pmc structures to C file
clk: at91: pmc: merge at91_pmc_init in atmel_pmc_probe
clk: at91: remove IRQ handling and use polling
clk: at91: make use of syscon/regmap internally
clk: at91: make use of syscon to share PMC registers in several drivers
hwmon: (scpi) add energy meter support
firmware: arm_scpi: add support for 64-bit sensor values
firmware: arm_scpi: decrease Tx timeout to 20ms
firmware: arm_scpi: fix send_message and sensor_get_value for big-endian
reset: sti: Make reset_control_ops const
reset: zynq: Make reset_control_ops const
...
Diffstat (limited to 'drivers/clk/at91/clk-programmable.c')
-rw-r--r-- | drivers/clk/at91/clk-programmable.c | 96 |
1 files changed, 51 insertions, 45 deletions
diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c index 14b270b..bc0be62 100644 --- a/drivers/clk/at91/clk-programmable.c +++ b/drivers/clk/at91/clk-programmable.c @@ -12,10 +12,8 @@ #include <linux/clkdev.h> #include <linux/clk/at91_pmc.h> #include <linux/of.h> -#include <linux/of_address.h> -#include <linux/io.h> -#include <linux/wait.h> -#include <linux/sched.h> +#include <linux/mfd/syscon.h> +#include <linux/regmap.h> #include "pmc.h" @@ -24,6 +22,7 @@ #define PROG_STATUS_MASK(id) (1 << ((id) + 8)) #define PROG_PRES_MASK 0x7 +#define PROG_PRES(layout, pckr) ((pckr >> layout->pres_shift) & PROG_PRES_MASK) #define PROG_MAX_RM9200_CSS 3 struct clk_programmable_layout { @@ -34,7 +33,7 @@ struct clk_programmable_layout { struct clk_programmable { struct clk_hw hw; - struct at91_pmc *pmc; + struct regmap *regmap; u8 id; const struct clk_programmable_layout *layout; }; @@ -44,14 +43,12 @@ struct clk_programmable { static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { - u32 pres; struct clk_programmable *prog = to_clk_programmable(hw); - struct at91_pmc *pmc = prog->pmc; - const struct clk_programmable_layout *layout = prog->layout; + unsigned int pckr; + + regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr); - pres = (pmc_read(pmc, AT91_PMC_PCKR(prog->id)) >> layout->pres_shift) & - PROG_PRES_MASK; - return parent_rate >> pres; + return parent_rate >> PROG_PRES(prog->layout, pckr); } static int clk_programmable_determine_rate(struct clk_hw *hw, @@ -101,36 +98,36 @@ static int clk_programmable_set_parent(struct clk_hw *hw, u8 index) { struct clk_programmable *prog = to_clk_programmable(hw); const struct clk_programmable_layout *layout = prog->layout; - struct at91_pmc *pmc = prog->pmc; - u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & ~layout->css_mask; + unsigned int mask = layout->css_mask; + unsigned int pckr = 0; if (layout->have_slck_mck) - tmp &= AT91_PMC_CSSMCK_MCK; + mask |= AT91_PMC_CSSMCK_MCK; if (index > layout->css_mask) { - if (index > PROG_MAX_RM9200_CSS && layout->have_slck_mck) { - tmp |= AT91_PMC_CSSMCK_MCK; - return 0; - } else { + if (index > PROG_MAX_RM9200_CSS && !layout->have_slck_mck) return -EINVAL; - } + + pckr |= AT91_PMC_CSSMCK_MCK; } - pmc_write(pmc, AT91_PMC_PCKR(prog->id), tmp | index); + regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id), mask, pckr); + return 0; } static u8 clk_programmable_get_parent(struct clk_hw *hw) { - u32 tmp; - u8 ret; struct clk_programmable *prog = to_clk_programmable(hw); - struct at91_pmc *pmc = prog->pmc; const struct clk_programmable_layout *layout = prog->layout; + unsigned int pckr; + u8 ret; + + regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr); + + ret = pckr & layout->css_mask; - tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)); - ret = tmp & layout->css_mask; - if (layout->have_slck_mck && (tmp & AT91_PMC_CSSMCK_MCK) && !ret) + if (layout->have_slck_mck && (pckr & AT91_PMC_CSSMCK_MCK) && !ret) ret = PROG_MAX_RM9200_CSS + 1; return ret; @@ -140,26 +137,27 @@ static int clk_programmable_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_programmable *prog = to_clk_programmable(hw); - struct at91_pmc *pmc = prog->pmc; const struct clk_programmable_layout *layout = prog->layout; unsigned long div = parent_rate / rate; + unsigned int pckr; int shift = 0; - u32 tmp = pmc_read(pmc, AT91_PMC_PCKR(prog->id)) & - ~(PROG_PRES_MASK << layout->pres_shift); + + regmap_read(prog->regmap, AT91_PMC_PCKR(prog->id), &pckr); if (!div) return -EINVAL; shift = fls(div) - 1; - if (div != (1<<shift)) + if (div != (1 << shift)) return -EINVAL; if (shift >= PROG_PRES_MASK) return -EINVAL; - pmc_write(pmc, AT91_PMC_PCKR(prog->id), - tmp | (shift << layout->pres_shift)); + regmap_update_bits(prog->regmap, AT91_PMC_PCKR(prog->id), + PROG_PRES_MASK << layout->pres_shift, + shift << layout->pres_shift); return 0; } @@ -173,7 +171,7 @@ static const struct clk_ops programmable_ops = { }; static struct clk * __init -at91_clk_register_programmable(struct at91_pmc *pmc, +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) @@ -198,7 +196,7 @@ at91_clk_register_programmable(struct at91_pmc *pmc, prog->id = id; prog->layout = layout; prog->hw.init = &init; - prog->pmc = pmc; + prog->regmap = regmap; clk = clk_register(NULL, &prog->hw); if (IS_ERR(clk)) @@ -226,7 +224,7 @@ static const struct clk_programmable_layout at91sam9x5_programmable_layout = { }; static void __init -of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, +of_at91_clk_prog_setup(struct device_node *np, const struct clk_programmable_layout *layout) { int num; @@ -236,6 +234,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, 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) @@ -247,6 +246,10 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, if (!num || num > (PROG_ID_MAX + 1)) return; + regmap = syscon_node_to_regmap(of_get_parent(np)); + if (IS_ERR(regmap)) + return; + for_each_child_of_node(np, progclknp) { if (of_property_read_u32(progclknp, "reg", &id)) continue; @@ -254,7 +257,7 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, if (of_property_read_string(np, "clock-output-names", &name)) name = progclknp->name; - clk = at91_clk_register_programmable(pmc, name, + clk = at91_clk_register_programmable(regmap, name, parent_names, num_parents, id, layout); if (IS_ERR(clk)) @@ -265,20 +268,23 @@ of_at91_clk_prog_setup(struct device_node *np, struct at91_pmc *pmc, } -void __init of_at91rm9200_clk_prog_setup(struct device_node *np, - struct at91_pmc *pmc) +static void __init of_at91rm9200_clk_prog_setup(struct device_node *np) { - of_at91_clk_prog_setup(np, pmc, &at91rm9200_programmable_layout); + of_at91_clk_prog_setup(np, &at91rm9200_programmable_layout); } +CLK_OF_DECLARE(at91rm9200_clk_prog, "atmel,at91rm9200-clk-programmable", + of_at91rm9200_clk_prog_setup); -void __init of_at91sam9g45_clk_prog_setup(struct device_node *np, - struct at91_pmc *pmc) +static void __init of_at91sam9g45_clk_prog_setup(struct device_node *np) { - of_at91_clk_prog_setup(np, pmc, &at91sam9g45_programmable_layout); + of_at91_clk_prog_setup(np, &at91sam9g45_programmable_layout); } +CLK_OF_DECLARE(at91sam9g45_clk_prog, "atmel,at91sam9g45-clk-programmable", + of_at91sam9g45_clk_prog_setup); -void __init of_at91sam9x5_clk_prog_setup(struct device_node *np, - struct at91_pmc *pmc) +static void __init of_at91sam9x5_clk_prog_setup(struct device_node *np) { - of_at91_clk_prog_setup(np, pmc, &at91sam9x5_programmable_layout); + of_at91_clk_prog_setup(np, &at91sam9x5_programmable_layout); } +CLK_OF_DECLARE(at91sam9x5_clk_prog, "atmel,at91sam9x5-clk-programmable", + of_at91sam9x5_clk_prog_setup); |