diff options
| -rw-r--r-- | drivers/clk/Makefile | 1 | ||||
| -rw-r--r-- | drivers/clk/pxa/Makefile | 1 | ||||
| -rw-r--r-- | drivers/clk/pxa/clk-pxa.c | 97 | ||||
| -rw-r--r-- | drivers/clk/pxa/clk-pxa.h | 107 | ||||
| -rw-r--r-- | include/dt-bindings/clock/pxa-clock.h | 77 |
5 files changed, 283 insertions, 0 deletions
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index f537a0b1f798..7891e4edaa07 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
| @@ -48,6 +48,7 @@ obj-$(CONFIG_ARCH_MMP) += mmp/ | |||
| 48 | endif | 48 | endif |
| 49 | obj-$(CONFIG_PLAT_ORION) += mvebu/ | 49 | obj-$(CONFIG_PLAT_ORION) += mvebu/ |
| 50 | obj-$(CONFIG_ARCH_MXS) += mxs/ | 50 | obj-$(CONFIG_ARCH_MXS) += mxs/ |
| 51 | obj-$(CONFIG_ARCH_PXA) += pxa/ | ||
| 51 | obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ | 52 | obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ |
| 52 | obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ | 53 | obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ |
| 53 | obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ | 54 | obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ |
diff --git a/drivers/clk/pxa/Makefile b/drivers/clk/pxa/Makefile new file mode 100644 index 000000000000..cb2bd8ff53da --- /dev/null +++ b/drivers/clk/pxa/Makefile | |||
| @@ -0,0 +1 @@ | |||
| obj-y += clk-pxa.o | |||
diff --git a/drivers/clk/pxa/clk-pxa.c b/drivers/clk/pxa/clk-pxa.c new file mode 100644 index 000000000000..ef3c05389c0a --- /dev/null +++ b/drivers/clk/pxa/clk-pxa.c | |||
| @@ -0,0 +1,97 @@ | |||
| 1 | /* | ||
| 2 | * Marvell PXA family clocks | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Robert Jarzmik | ||
| 5 | * | ||
| 6 | * Common clock code for PXA clocks ("CKEN" type clocks + DT) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; version 2 of the License. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | #include <linux/clk.h> | ||
| 14 | #include <linux/clk-provider.h> | ||
| 15 | #include <linux/clkdev.h> | ||
| 16 | #include <linux/of.h> | ||
| 17 | |||
| 18 | #include <dt-bindings/clock/pxa-clock.h> | ||
| 19 | #include "clk-pxa.h" | ||
| 20 | |||
| 21 | DEFINE_SPINLOCK(lock); | ||
| 22 | |||
| 23 | static struct clk *pxa_clocks[CLK_MAX]; | ||
| 24 | static struct clk_onecell_data onecell_data = { | ||
| 25 | .clks = pxa_clocks, | ||
| 26 | .clk_num = CLK_MAX, | ||
| 27 | }; | ||
| 28 | |||
| 29 | #define to_pxa_clk(_hw) container_of(_hw, struct pxa_clk_cken, hw) | ||
| 30 | |||
| 31 | static unsigned long cken_recalc_rate(struct clk_hw *hw, | ||
| 32 | unsigned long parent_rate) | ||
| 33 | { | ||
| 34 | struct pxa_clk_cken *pclk = to_pxa_clk(hw); | ||
| 35 | struct clk_fixed_factor *fix; | ||
| 36 | |||
| 37 | if (!pclk->is_in_low_power || pclk->is_in_low_power()) | ||
| 38 | fix = &pclk->lp; | ||
| 39 | else | ||
| 40 | fix = &pclk->hp; | ||
| 41 | fix->hw.clk = hw->clk; | ||
| 42 | return clk_fixed_factor_ops.recalc_rate(&fix->hw, parent_rate); | ||
| 43 | } | ||
| 44 | |||
| 45 | static struct clk_ops cken_rate_ops = { | ||
| 46 | .recalc_rate = cken_recalc_rate, | ||
| 47 | }; | ||
| 48 | |||
| 49 | static u8 cken_get_parent(struct clk_hw *hw) | ||
| 50 | { | ||
| 51 | struct pxa_clk_cken *pclk = to_pxa_clk(hw); | ||
| 52 | |||
| 53 | if (!pclk->is_in_low_power) | ||
| 54 | return 0; | ||
| 55 | return pclk->is_in_low_power() ? 0 : 1; | ||
| 56 | } | ||
| 57 | |||
| 58 | static struct clk_ops cken_mux_ops = { | ||
| 59 | .get_parent = cken_get_parent, | ||
| 60 | .set_parent = dummy_clk_set_parent, | ||
| 61 | }; | ||
| 62 | |||
| 63 | void __init clkdev_pxa_register(int ckid, const char *con_id, | ||
| 64 | const char *dev_id, struct clk *clk) | ||
| 65 | { | ||
| 66 | if (!IS_ERR(clk) && (ckid != CLK_NONE)) | ||
| 67 | pxa_clocks[ckid] = clk; | ||
| 68 | if (!IS_ERR(clk)) | ||
| 69 | clk_register_clkdev(clk, con_id, dev_id); | ||
| 70 | } | ||
| 71 | |||
| 72 | int __init clk_pxa_cken_init(struct pxa_clk_cken *clks, int nb_clks) | ||
| 73 | { | ||
| 74 | int i; | ||
| 75 | struct pxa_clk_cken *pclk; | ||
| 76 | struct clk *clk; | ||
| 77 | |||
| 78 | for (i = 0; i < nb_clks; i++) { | ||
| 79 | pclk = clks + i; | ||
| 80 | pclk->gate.lock = &lock; | ||
| 81 | clk = clk_register_composite(NULL, pclk->name, | ||
| 82 | pclk->parent_names, 2, | ||
| 83 | &pclk->hw, &cken_mux_ops, | ||
| 84 | &pclk->hw, &cken_rate_ops, | ||
| 85 | &pclk->gate.hw, &clk_gate_ops, | ||
| 86 | pclk->flags); | ||
| 87 | clkdev_pxa_register(pclk->ckid, pclk->con_id, pclk->dev_id, | ||
| 88 | clk); | ||
| 89 | } | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | static void __init pxa_dt_clocks_init(struct device_node *np) | ||
| 94 | { | ||
| 95 | of_clk_add_provider(np, of_clk_src_onecell_get, &onecell_data); | ||
| 96 | } | ||
| 97 | CLK_OF_DECLARE(pxa_clks, "marvell,pxa-clocks", pxa_dt_clocks_init); | ||
diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h new file mode 100644 index 000000000000..5fe219d06b49 --- /dev/null +++ b/drivers/clk/pxa/clk-pxa.h | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | /* | ||
| 2 | * Marvell PXA family clocks | ||
| 3 | * | ||
| 4 | * Copyright (C) 2014 Robert Jarzmik | ||
| 5 | * | ||
| 6 | * Common clock code for PXA clocks ("CKEN" type clocks + DT) | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; version 2 of the License. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | #ifndef _CLK_PXA_ | ||
| 14 | #define _CLK_PXA_ | ||
| 15 | |||
| 16 | #define PARENTS(name) \ | ||
| 17 | static const char *name ## _parents[] __initconst | ||
| 18 | #define MUX_RO_RATE_RO_OPS(name, clk_name) \ | ||
| 19 | static struct clk_hw name ## _mux_hw; \ | ||
| 20 | static struct clk_hw name ## _rate_hw; \ | ||
| 21 | static struct clk_ops name ## _mux_ops = { \ | ||
| 22 | .get_parent = name ## _get_parent, \ | ||
| 23 | .set_parent = dummy_clk_set_parent, \ | ||
| 24 | }; \ | ||
| 25 | static struct clk_ops name ## _rate_ops = { \ | ||
| 26 | .recalc_rate = name ## _get_rate, \ | ||
| 27 | }; \ | ||
| 28 | static struct clk *clk_register_ ## name(void) \ | ||
| 29 | { \ | ||
| 30 | return clk_register_composite(NULL, clk_name, \ | ||
| 31 | name ## _parents, \ | ||
| 32 | ARRAY_SIZE(name ## _parents), \ | ||
| 33 | &name ## _mux_hw, &name ## _mux_ops, \ | ||
| 34 | &name ## _rate_hw, &name ## _rate_ops, \ | ||
| 35 | NULL, NULL, CLK_GET_RATE_NOCACHE); \ | ||
| 36 | } | ||
| 37 | |||
| 38 | #define RATE_RO_OPS(name, clk_name) \ | ||
| 39 | static struct clk_hw name ## _rate_hw; \ | ||
| 40 | static struct clk_ops name ## _rate_ops = { \ | ||
| 41 | .recalc_rate = name ## _get_rate, \ | ||
| 42 | }; \ | ||
| 43 | static struct clk *clk_register_ ## name(void) \ | ||
| 44 | { \ | ||
| 45 | return clk_register_composite(NULL, clk_name, \ | ||
| 46 | name ## _parents, \ | ||
| 47 | ARRAY_SIZE(name ## _parents), \ | ||
| 48 | NULL, NULL, \ | ||
| 49 | &name ## _rate_hw, &name ## _rate_ops, \ | ||
| 50 | NULL, NULL, CLK_GET_RATE_NOCACHE); \ | ||
| 51 | } | ||
| 52 | |||
| 53 | /* | ||
| 54 | * CKEN clock type | ||
| 55 | * This clock takes it source from 2 possible parents : | ||
| 56 | * - a low power parent | ||
| 57 | * - a normal parent | ||
| 58 | * | ||
| 59 | * +------------+ +-----------+ | ||
| 60 | * | Low Power | --- | x mult_lp | | ||
| 61 | * | Clock | | / div_lp |\ | ||
| 62 | * +------------+ +-----------+ \+-----+ +-----------+ | ||
| 63 | * | Mux |---| CKEN gate | | ||
| 64 | * +------------+ +-----------+ /+-----+ +-----------+ | ||
| 65 | * | High Power | | x mult_hp |/ | ||
| 66 | * | Clock | --- | / div_hp | | ||
| 67 | * +------------+ +-----------+ | ||
| 68 | */ | ||
| 69 | struct pxa_clk_cken { | ||
| 70 | struct clk_hw hw; | ||
| 71 | int ckid; | ||
| 72 | const char *name; | ||
| 73 | const char *dev_id; | ||
| 74 | const char *con_id; | ||
| 75 | const char **parent_names; | ||
| 76 | struct clk_fixed_factor lp; | ||
| 77 | struct clk_fixed_factor hp; | ||
| 78 | struct clk_gate gate; | ||
| 79 | bool (*is_in_low_power)(void); | ||
| 80 | const unsigned long flags; | ||
| 81 | }; | ||
| 82 | |||
| 83 | |||
