Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'sunxi-clocks-for-4.4' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into clk-next

Pull Allwinner clock additions for 4.4 from Maxime Ripard:

- Support for the Audio PLL and child clocks
- Support for the A33 AHB gates
- New clk-multiplier generic driver

* tag 'sunxi-clocks-for-4.4' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux:
clk: sunxi: mod1 clock support
clk: sunxi: codec clock support
clk: sunxi: pll2: Add A13 support
clk: sunxi: Add a driver for the PLL2
clk: Add a basic multiplier clock
clk: sunxi: Add A33 gates support

+623
+1
drivers/clk/Makefile
··· 6 6 obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o 7 7 obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o 8 8 obj-$(CONFIG_COMMON_CLK) += clk-gate.o 9 + obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o 9 10 obj-$(CONFIG_COMMON_CLK) += clk-mux.o 10 11 obj-$(CONFIG_COMMON_CLK) += clk-composite.o 11 12 obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
+181
drivers/clk/clk-multiplier.c
··· 1 + /* 2 + * Copyright (C) 2015 Maxime Ripard <maxime.ripard@free-electrons.com> 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + */ 8 + 9 + #include <linux/bitops.h> 10 + #include <linux/clk-provider.h> 11 + #include <linux/err.h> 12 + #include <linux/export.h> 13 + #include <linux/kernel.h> 14 + #include <linux/of.h> 15 + #include <linux/slab.h> 16 + 17 + #define to_clk_multiplier(_hw) container_of(_hw, struct clk_multiplier, hw) 18 + 19 + static unsigned long __get_mult(struct clk_multiplier *mult, 20 + unsigned long rate, 21 + unsigned long parent_rate) 22 + { 23 + if (mult->flags & CLK_MULTIPLIER_ROUND_CLOSEST) 24 + return DIV_ROUND_CLOSEST(rate, parent_rate); 25 + 26 + return rate / parent_rate; 27 + } 28 + 29 + static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw, 30 + unsigned long parent_rate) 31 + { 32 + struct clk_multiplier *mult = to_clk_multiplier(hw); 33 + unsigned long val; 34 + 35 + val = clk_readl(mult->reg) >> mult->shift; 36 + val &= GENMASK(mult->width - 1, 0); 37 + 38 + if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS) 39 + val = 1; 40 + 41 + return parent_rate * val; 42 + } 43 + 44 + static bool __is_best_rate(unsigned long rate, unsigned long new, 45 + unsigned long best, unsigned long flags) 46 + { 47 + if (flags & CLK_MULTIPLIER_ROUND_CLOSEST) 48 + return abs(rate - new) < abs(rate - best); 49 + 50 + return new >= rate && new < best; 51 + } 52 + 53 + static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate, 54 + unsigned long *best_parent_rate, 55 + u8 width, unsigned long flags) 56 + { 57 + unsigned long orig_parent_rate = *best_parent_rate; 58 + unsigned long parent_rate, current_rate, best_rate = ~0; 59 + unsigned int i, bestmult = 0; 60 + 61 + if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) 62 + return rate / *best_parent_rate; 63 + 64 + for (i = 1; i < ((1 << width) - 1); i++) { 65 + if (rate == orig_parent_rate * i) { 66 + /* 67 + * This is the best case for us if we have a 68 + * perfect match without changing the parent 69 + * rate. 70 + */ 71 + *best_parent_rate = orig_parent_rate; 72 + return i; 73 + } 74 + 75 + parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), 76 + rate / i); 77 + current_rate = parent_rate * i; 78 + 79 + if (__is_best_rate(rate, current_rate, best_rate, flags)) { 80 + bestmult = i; 81 + best_rate = current_rate; 82 + *best_parent_rate = parent_rate; 83 + } 84 + } 85 + 86 + return bestmult; 87 + } 88 + 89 + static long clk_multiplier_round_rate(struct clk_hw *hw, unsigned long rate, 90 + unsigned long *parent_rate) 91 + { 92 + struct clk_multiplier *mult = to_clk_multiplier(hw); 93 + unsigned long factor = __bestmult(hw, rate, parent_rate, 94 + mult->width, mult->flags); 95 + 96 + return *parent_rate * factor; 97 + } 98 + 99 + static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate, 100 + unsigned long parent_rate) 101 + { 102 + struct clk_multiplier *mult = to_clk_multiplier(hw); 103 + unsigned long factor = __get_mult(mult, rate, parent_rate); 104 + unsigned long flags = 0; 105 + unsigned long val; 106 + 107 + if (mult->lock) 108 + spin_lock_irqsave(mult->lock, flags); 109 + else 110 + __acquire(mult->lock); 111 + 112 + val = clk_readl(mult->reg); 113 + val &= ~GENMASK(mult->width + mult->shift - 1, mult->shift); 114 + val |= factor << mult->shift; 115 + clk_writel(val, mult->reg); 116 + 117 + if (mult->lock) 118 + spin_unlock_irqrestore(mult->lock, flags); 119 + else 120 + __release(mult->lock); 121 + 122 + return 0; 123 + } 124 + 125 + const struct clk_ops clk_multiplier_ops = { 126 + .recalc_rate = clk_multiplier_recalc_rate, 127 + .round_rate = clk_multiplier_round_rate, 128 + .set_rate = clk_multiplier_set_rate, 129 + }; 130 + EXPORT_SYMBOL_GPL(clk_multiplier_ops); 131 + 132 + struct clk *clk_register_multiplier(struct device *dev, const char *name, 133 + const char *parent_name, 134 + unsigned long flags, 135 + void __iomem *reg, u8 shift, u8 width, 136 + u8 clk_mult_flags, spinlock_t *lock) 137 + { 138 + struct clk_init_data init; 139 + struct clk_multiplier *mult; 140 + struct clk *clk; 141 + 142 + mult = kmalloc(sizeof(*mult), GFP_KERNEL); 143 + if (!mult) 144 + return ERR_PTR(-ENOMEM); 145 + 146 + init.name = name; 147 + init.ops = &clk_multiplier_ops; 148 + init.flags = flags | CLK_IS_BASIC; 149 + init.parent_names = &parent_name; 150 + init.num_parents = 1; 151 + 152 + mult->reg = reg; 153 + mult->shift = shift; 154 + mult->width = width; 155 + mult->flags = clk_mult_flags; 156 + mult->lock = lock; 157 + mult->hw.init = &init; 158 + 159 + clk = clk_register(dev, &mult->hw); 160 + if (IS_ERR(clk)) 161 + kfree(mult); 162 + 163 + return clk; 164 + } 165 + EXPORT_SYMBOL_GPL(clk_register_multiplier); 166 + 167 + void clk_unregister_multiplier(struct clk *clk) 168 + { 169 + struct clk_multiplier *mult; 170 + struct clk_hw *hw; 171 + 172 + hw = __clk_get_hw(clk); 173 + if (!hw) 174 + return; 175 + 176 + mult = to_clk_multiplier(hw); 177 + 178 + clk_unregister(clk); 179 + kfree(mult); 180 + } 181 + EXPORT_SYMBOL_GPL(clk_unregister_multiplier);
+3
drivers/clk/sunxi/Makefile
··· 3 3 # 4 4 5 5 obj-y += clk-sunxi.o clk-factors.o 6 + obj-y += clk-a10-codec.o 6 7 obj-y += clk-a10-hosc.o 8 + obj-y += clk-a10-mod1.o 9 + obj-y += clk-a10-pll2.o 7 10 obj-y += clk-a20-gmac.o 8 11 obj-y += clk-mod0.o 9 12 obj-y += clk-simple-gates.o
+44
drivers/clk/sunxi/clk-a10-codec.c
··· 1 + /* 2 + * Copyright 2013 Emilio López 3 + * 4 + * Emilio López <emilio@elopez.com.ar> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + */ 16 + 17 + #include <linux/clk-provider.h> 18 + #include <linux/of.h> 19 + #include <linux/of_address.h> 20 + 21 + #define SUN4I_CODEC_GATE 31 22 + 23 + static void __init sun4i_codec_clk_setup(struct device_node *node) 24 + { 25 + struct clk *clk; 26 + const char *clk_name = node->name, *parent_name; 27 + void __iomem *reg; 28 + 29 + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 30 + if (IS_ERR(reg)) 31 + return; 32 + 33 + of_property_read_string(node, "clock-output-names", &clk_name); 34 + parent_name = of_clk_get_parent_name(node, 0); 35 + 36 + clk = clk_register_gate(NULL, clk_name, parent_name, 37 + CLK_SET_RATE_PARENT, reg, 38 + SUN4I_CODEC_GATE, 0, NULL); 39 + 40 + if (!IS_ERR(clk)) 41 + of_clk_add_provider(node, of_clk_src_simple_get, clk); 42 + } 43 + CLK_OF_DECLARE(sun4i_codec, "allwinner,sun4i-a10-codec-clk", 44 + sun4i_codec_clk_setup);
+81
drivers/clk/sunxi/clk-a10-mod1.c
··· 1 + /* 2 + * Copyright 2013 Emilio López 3 + * 4 + * Emilio López <emilio@elopez.com.ar> 5 + * 6 + * This program is free software; you can redistribute it and/or modify 7 + * it under the terms of the GNU General Public License as published by 8 + * the Free Software Foundation; either version 2 of the License, or 9 + * (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + */ 16 + 17 + #include <linux/clk-provider.h> 18 + #include <linux/of.h> 19 + #include <linux/of_address.h> 20 + #include <linux/slab.h> 21 + 22 + static DEFINE_SPINLOCK(mod1_lock); 23 + 24 + #define SUN4I_MOD1_ENABLE 31 25 + #define SUN4I_MOD1_MUX 16 26 + #define SUN4I_MOD1_MUX_WIDTH 2 27 + #define SUN4I_MOD1_MAX_PARENTS 4 28 + 29 + static void __init sun4i_mod1_clk_setup(struct device_node *node) 30 + { 31 + struct clk *clk; 32 + struct clk_mux *mux; 33 + struct clk_gate *gate; 34 + const char *parents[4]; 35 + const char *clk_name = node->name; 36 + void __iomem *reg; 37 + int i; 38 + 39 + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 40 + if (IS_ERR(reg)) 41 + return; 42 + 43 + mux = kzalloc(sizeof(*mux), GFP_KERNEL); 44 + if (!mux) 45 + goto err_unmap; 46 + 47 + gate = kzalloc(sizeof(*gate), GFP_KERNEL); 48 + if (!gate) 49 + goto err_free_mux; 50 + 51 + of_property_read_string(node, "clock-output-names", &clk_name); 52 + i = of_clk_parent_fill(node, parents, SUN4I_MOD1_MAX_PARENTS); 53 + 54 + gate->reg = reg; 55 + gate->bit_idx = SUN4I_MOD1_ENABLE; 56 + gate->lock = &mod1_lock; 57 + mux->reg = reg; 58 + mux->shift = SUN4I_MOD1_MUX; 59 + mux->mask = BIT(SUN4I_MOD1_MUX_WIDTH) - 1; 60 + mux->lock = &mod1_lock; 61 + 62 + clk = clk_register_composite(NULL, clk_name, parents, i, 63 + &mux->hw, &clk_mux_ops, 64 + NULL, NULL, 65 + &gate->hw, &clk_gate_ops, 0); 66 + if (IS_ERR(clk)) 67 + goto err_free_gate; 68 + 69 + of_clk_add_provider(node, of_clk_src_simple_get, clk); 70 + 71 + return; 72 + 73 + err_free_gate: 74 + kfree(gate); 75 + err_free_mux: 76 + kfree(mux); 77 + err_unmap: 78 + iounmap(reg); 79 + } 80 + CLK_OF_DECLARE(sun4i_mod1, "allwinner,sun4i-a10-mod1-clk", 81 + sun4i_mod1_clk_setup);
+216
drivers/clk/sunxi/clk-a10-pll2.c
··· 1 + /* 2 + * Copyright 2013 Emilio López 3 + * Emilio López <emilio@elopez.com.ar> 4 + * 5 + * Copyright 2015 Maxime Ripard 6 + * Maxime Ripard <maxime.ripard@free-electrons.com> 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; either version 2 of the License, or 11 + * (at your option) any later version. 12 + * 13 + * This program is distributed in the hope that it will be useful, 14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 + * GNU General Public License for more details. 17 + */ 18 + 19 + #include <linux/clk-provider.h> 20 + #include <linux/of.h> 21 + #include <linux/of_address.h> 22 + #include <linux/slab.h> 23 + 24 + #include <dt-bindings/clock/sun4i-a10-pll2.h> 25 + 26 + #define SUN4I_PLL2_ENABLE 31 27 + 28 + #define SUN4I_PLL2_PRE_DIV_SHIFT 0 29 + #define SUN4I_PLL2_PRE_DIV_WIDTH 5 30 + #define SUN4I_PLL2_PRE_DIV_MASK GENMASK(SUN4I_PLL2_PRE_DIV_WIDTH - 1, 0) 31 + 32 + #define SUN4I_PLL2_N_SHIFT 8 33 + #define SUN4I_PLL2_N_WIDTH 7 34 + #define SUN4I_PLL2_N_MASK GENMASK(SUN4I_PLL2_N_WIDTH - 1, 0) 35 + 36 + #define SUN4I_PLL2_POST_DIV_SHIFT 26 37 + #define SUN4I_PLL2_POST_DIV_WIDTH 4 38 + #define SUN4I_PLL2_POST_DIV_MASK GENMASK(SUN4I_PLL2_POST_DIV_WIDTH - 1, 0) 39 + 40 + #define SUN4I_PLL2_POST_DIV_VALUE 4 41 + 42 + #define SUN4I_PLL2_OUTPUTS 4 43 + 44 + struct sun4i_pll2_data { 45 + u32 post_div_offset; 46 + u32 pre_div_flags; 47 + }; 48 + 49 + static DEFINE_SPINLOCK(sun4i_a10_pll2_lock); 50 + 51 + static void __init sun4i_pll2_setup(struct device_node *node, 52 + struct sun4i_pll2_data *data) 53 + { 54 + const char *clk_name = node->name, *parent; 55 + struct clk **clks, *base_clk, *prediv_clk; 56 + struct clk_onecell_data *clk_data; 57 + struct clk_multiplier *mult; 58 + struct clk_gate *gate; 59 + void __iomem *reg; 60 + u32 val; 61 + 62 + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 63 + if (IS_ERR(reg)) 64 + return; 65 + 66 + clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL); 67 + if (!clk_data) 68 + goto err_unmap; 69 + 70 + clks = kcalloc(SUN4I_PLL2_OUTPUTS, sizeof(struct clk *), GFP_KERNEL); 71 + if (!clks) 72 + goto err_free_data; 73 + 74 + parent = of_clk_get_parent_name(node, 0); 75 + prediv_clk = clk_register_divider(NULL, "pll2-prediv", 76 + parent, 0, reg, 77 + SUN4I_PLL2_PRE_DIV_SHIFT, 78 + SUN4I_PLL2_PRE_DIV_WIDTH, 79 + data->pre_div_flags, 80 + &sun4i_a10_pll2_lock); 81 + if (!prediv_clk) { 82 + pr_err("Couldn't register the prediv clock\n"); 83 + goto err_free_array; 84 + } 85 + 86 + /* Setup the gate part of the PLL2 */ 87 + gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); 88 + if (!gate) 89 + goto err_unregister_prediv; 90 + 91 + gate->reg = reg; 92 + gate->bit_idx = SUN4I_PLL2_ENABLE; 93 + gate->lock = &sun4i_a10_pll2_lock; 94 + 95 + /* Setup the multiplier part of the PLL2 */ 96 + mult = kzalloc(sizeof(struct clk_multiplier), GFP_KERNEL); 97 + if (!mult) 98 + goto err_free_gate; 99 + 100 + mult->reg = reg; 101 + mult->shift = SUN4I_PLL2_N_SHIFT; 102 + mult->width = 7; 103 + mult->flags = CLK_MULTIPLIER_ZERO_BYPASS | 104 + CLK_MULTIPLIER_ROUND_CLOSEST; 105 + mult->lock = &sun4i_a10_pll2_lock; 106 + 107 + parent = __clk_get_name(prediv_clk); 108 + base_clk = clk_register_composite(NULL, "pll2-base", 109 + &parent, 1, 110 + NULL, NULL, 111 + &mult->hw, &clk_multiplier_ops, 112 + &gate->hw, &clk_gate_ops, 113 + CLK_SET_RATE_PARENT); 114 + if (!base_clk) { 115 + pr_err("Couldn't register the base multiplier clock\n"); 116 + goto err_free_multiplier; 117 + } 118 + 119 + parent = __clk_get_name(base_clk); 120 + 121 + /* 122 + * PLL2-1x 123 + * 124 + * This is supposed to have a post divider, but we won't need 125 + * to use it, we just need to initialise it to 4, and use a 126 + * fixed divider. 127 + */ 128 + val = readl(reg); 129 + val &= ~(SUN4I_PLL2_POST_DIV_MASK << SUN4I_PLL2_POST_DIV_SHIFT); 130 + val |= (SUN4I_PLL2_POST_DIV_VALUE - data->post_div_offset) << SUN4I_PLL2_POST_DIV_SHIFT; 131 + writel(val, reg); 132 + 133 + of_property_read_string_index(node, "clock-output-names", 134 + SUN4I_A10_PLL2_1X, &clk_name); 135 + clks[SUN4I_A10_PLL2_1X] = clk_register_fixed_factor(NULL, clk_name, 136 + parent, 137 + CLK_SET_RATE_PARENT, 138 + 1, 139 + SUN4I_PLL2_POST_DIV_VALUE); 140 + WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_1X])); 141 + 142 + /* 143 + * PLL2-2x 144 + * 145 + * This clock doesn't use the post divider, and really is just 146 + * a fixed divider from the PLL2 base clock. 147 + */ 148 + of_property_read_string_index(node, "clock-output-names", 149 + SUN4I_A10_PLL2_2X, &clk_name); 150 + clks[SUN4I_A10_PLL2_2X] = clk_register_fixed_factor(NULL, clk_name, 151 + parent, 152 + CLK_SET_RATE_PARENT, 153 + 1, 2); 154 + WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_2X])); 155 + 156 + /* PLL2-4x */ 157 + of_property_read_string_index(node, "clock-output-names", 158 + SUN4I_A10_PLL2_4X, &clk_name); 159 + clks[SUN4I_A10_PLL2_4X] = clk_register_fixed_factor(NULL, clk_name, 160 + parent, 161 + CLK_SET_RATE_PARENT, 162 + 1, 1); 163 + WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_4X])); 164 + 165 + /* PLL2-8x */ 166 + of_property_read_string_index(node, "clock-output-names", 167 + SUN4I_A10_PLL2_8X, &clk_name); 168 + clks[SUN4I_A10_PLL2_8X] = clk_register_fixed_factor(NULL, clk_name, 169 + parent, 170 + CLK_SET_RATE_PARENT, 171 + 2, 1); 172 + WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_8X])); 173 + 174 + clk_data->clks = clks; 175 + clk_data->clk_num = SUN4I_PLL2_OUTPUTS; 176 + of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); 177 + 178 + return; 179 + 180 + err_free_multiplier: 181 + kfree(mult); 182 + err_free_gate: 183 + kfree(gate); 184 + err_unregister_prediv: 185 + clk_unregister_divider(prediv_clk); 186 + err_free_array: 187 + kfree(clks); 188 + err_free_data: 189 + kfree(clk_data); 190 + err_unmap: 191 + iounmap(reg); 192 + } 193 + 194 + static struct sun4i_pll2_data sun4i_a10_pll2_data = { 195 + .pre_div_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, 196 + }; 197 + 198 + static void __init sun4i_a10_pll2_setup(struct device_node *node) 199 + { 200 + sun4i_pll2_setup(node, &sun4i_a10_pll2_data); 201 + } 202 + 203 + CLK_OF_DECLARE(sun4i_a10_pll2, "allwinner,sun4i-a10-pll2-clk", 204 + sun4i_a10_pll2_setup); 205 + 206 + static struct sun4i_pll2_data sun5i_a13_pll2_data = { 207 + .post_div_offset = 1, 208 + }; 209 + 210 + static void __init sun5i_a13_pll2_setup(struct device_node *node) 211 + { 212 + sun4i_pll2_setup(node, &sun5i_a13_pll2_data); 213 + } 214 + 215 + CLK_OF_DECLARE(sun5i_a13_pll2, "allwinner,sun5i-a13-pll2-clk", 216 + sun5i_a13_pll2_setup);
+2
drivers/clk/sunxi/clk-simple-gates.c
··· 128 128 sunxi_simple_gates_init); 129 129 CLK_OF_DECLARE(sun8i_a23_apb2, "allwinner,sun8i-a23-apb2-gates-clk", 130 130 sunxi_simple_gates_init); 131 + CLK_OF_DECLARE(sun8i_a33_ahb1, "allwinner,sun8i-a33-ahb1-gates-clk", 132 + sunxi_simple_gates_init); 131 133 CLK_OF_DECLARE(sun9i_a80_ahb0, "allwinner,sun9i-a80-ahb0-gates-clk", 132 134 sunxi_simple_gates_init); 133 135 CLK_OF_DECLARE(sun9i_a80_ahb1, "allwinner,sun9i-a80-ahb1-gates-clk",
+53
include/dt-bindings/clock/sun4i-a10-pll2.h
··· 1 + /* 2 + * Copyright 2015 Maxime Ripard 3 + * 4 + * Maxime Ripard <maxime.ripard@free-electrons.com> 5 + * 6 + * This file is dual-licensed: you can use it either under the terms 7 + * of the GPL or the X11 license, at your option. Note that this dual 8 + * licensing only applies to this file, and not this project as a 9 + * whole. 10 + * 11 + * a) This file is free software; you can redistribute it and/or 12 + * modify it under the terms of the GNU General Public License as 13 + * published by the Free Software Foundation; either version 2 of the 14 + * License, or (at your option) any later version. 15 + * 16 + * This file is distributed in the hope that it will be useful, 17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 + * GNU General Public License for more details. 20 + * 21 + * Or, alternatively, 22 + * 23 + * b) Permission is hereby granted, free of charge, to any person 24 + * obtaining a copy of this software and associated documentation 25 + * files (the "Software"), to deal in the Software without 26 + * restriction, including without limitation the rights to use, 27 + * copy, modify, merge, publish, distribute, sublicense, and/or 28 + * sell copies of the Software, and to permit persons to whom the 29 + * Software is furnished to do so, subject to the following 30 + * conditions: 31 + * 32 + * The above copyright notice and this permission notice shall be 33 + * included in all copies or substantial portions of the Software. 34 + * 35 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 36 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 37 + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 38 + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 39 + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 40 + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 41 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 42 + * OTHER DEALINGS IN THE SOFTWARE. 43 + */ 44 + 45 + #ifndef __DT_BINDINGS_CLOCK_SUN4I_A10_PLL2_H_ 46 + #define __DT_BINDINGS_CLOCK_SUN4I_A10_PLL2_H_ 47 + 48 + #define SUN4I_A10_PLL2_1X 0 49 + #define SUN4I_A10_PLL2_2X 1 50 + #define SUN4I_A10_PLL2_4X 2 51 + #define SUN4I_A10_PLL2_8X 3 52 + 53 + #endif /* __DT_BINDINGS_CLOCK_SUN4I_A10_PLL2_H_ */
+42
include/linux/clk-provider.h
··· 519 519 void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, 520 520 u8 clk_divider_flags, spinlock_t *lock); 521 521 522 + /** 523 + * struct clk_multiplier - adjustable multiplier clock 524 + * 525 + * @hw: handle between common and hardware-specific interfaces 526 + * @reg: register containing the multiplier 527 + * @shift: shift to the multiplier bit field 528 + * @width: width of the multiplier bit field 529 + * @lock: register lock 530 + * 531 + * Clock with an adjustable multiplier affecting its output frequency. 532 + * Implements .recalc_rate, .set_rate and .round_rate 533 + * 534 + * Flags: 535 + * CLK_MULTIPLIER_ZERO_BYPASS - By default, the multiplier is the value read 536 + * from the register, with 0 being a valid value effectively 537 + * zeroing the output clock rate. If CLK_MULTIPLIER_ZERO_BYPASS is 538 + * set, then a null multiplier will be considered as a bypass, 539 + * leaving the parent rate unmodified. 540 + * CLK_MULTIPLIER_ROUND_CLOSEST - Makes the best calculated divider to be 541 + * rounded to the closest integer instead of the down one. 542 + */ 543 + struct clk_multiplier { 544 + struct clk_hw hw; 545 + void __iomem *reg; 546 + u8 shift; 547 + u8 width; 548 + u8 flags; 549 + spinlock_t *lock; 550 + }; 551 + 552 + #define CLK_MULTIPLIER_ZERO_BYPASS BIT(0) 553 + #define CLK_MULTIPLIER_ROUND_CLOSEST BIT(1) 554 + 555 + extern const struct clk_ops clk_multiplier_ops; 556 + 557 + struct clk *clk_register_multiplier(struct device *dev, const char *name, 558 + const char *parent_name, 559 + unsigned long flags, 560 + void __iomem *reg, u8 shift, u8 width, 561 + u8 clk_mult_flags, spinlock_t *lock); 562 + void clk_unregister_multiplier(struct clk *clk); 563 + 522 564 /*** 523 565 * struct clk_composite - aggregate clock of mux, divider and gate clocks 524 566 *