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

clk: actions: Add composite clock support

Add support for Actions Semi composite clock. This clock
consists of gate, mux, divider, factor and fixed factor clocks.

Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Manivannan Sadhasivam and committed by
Stephen Boyd
bb150645 c5351964

+324
+1
drivers/clk/actions/Makefile
··· 5 5 clk-owl-y += owl-mux.o 6 6 clk-owl-y += owl-divider.o 7 7 clk-owl-y += owl-factor.o 8 + clk-owl-y += owl-composite.o
+199
drivers/clk/actions/owl-composite.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // OWL composite clock driver 4 + // 5 + // Copyright (c) 2014 Actions Semi Inc. 6 + // Author: David Liu <liuwei@actions-semi.com> 7 + // 8 + // Copyright (c) 2018 Linaro Ltd. 9 + // Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> 10 + 11 + #include <linux/clk-provider.h> 12 + #include <linux/regmap.h> 13 + 14 + #include "owl-composite.h" 15 + 16 + static u8 owl_comp_get_parent(struct clk_hw *hw) 17 + { 18 + struct owl_composite *comp = hw_to_owl_comp(hw); 19 + 20 + return owl_mux_helper_get_parent(&comp->common, &comp->mux_hw); 21 + } 22 + 23 + static int owl_comp_set_parent(struct clk_hw *hw, u8 index) 24 + { 25 + struct owl_composite *comp = hw_to_owl_comp(hw); 26 + 27 + return owl_mux_helper_set_parent(&comp->common, &comp->mux_hw, index); 28 + } 29 + 30 + static void owl_comp_disable(struct clk_hw *hw) 31 + { 32 + struct owl_composite *comp = hw_to_owl_comp(hw); 33 + struct owl_clk_common *common = &comp->common; 34 + 35 + owl_gate_set(common, &comp->gate_hw, false); 36 + } 37 + 38 + static int owl_comp_enable(struct clk_hw *hw) 39 + { 40 + struct owl_composite *comp = hw_to_owl_comp(hw); 41 + struct owl_clk_common *common = &comp->common; 42 + 43 + owl_gate_set(common, &comp->gate_hw, true); 44 + 45 + return 0; 46 + } 47 + 48 + static int owl_comp_is_enabled(struct clk_hw *hw) 49 + { 50 + struct owl_composite *comp = hw_to_owl_comp(hw); 51 + struct owl_clk_common *common = &comp->common; 52 + 53 + return owl_gate_clk_is_enabled(common, &comp->gate_hw); 54 + } 55 + 56 + static long owl_comp_div_round_rate(struct clk_hw *hw, unsigned long rate, 57 + unsigned long *parent_rate) 58 + { 59 + struct owl_composite *comp = hw_to_owl_comp(hw); 60 + 61 + return owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw, 62 + rate, parent_rate); 63 + } 64 + 65 + static unsigned long owl_comp_div_recalc_rate(struct clk_hw *hw, 66 + unsigned long parent_rate) 67 + { 68 + struct owl_composite *comp = hw_to_owl_comp(hw); 69 + 70 + return owl_divider_helper_recalc_rate(&comp->common, &comp->rate.div_hw, 71 + parent_rate); 72 + } 73 + 74 + static int owl_comp_div_set_rate(struct clk_hw *hw, unsigned long rate, 75 + unsigned long parent_rate) 76 + { 77 + struct owl_composite *comp = hw_to_owl_comp(hw); 78 + 79 + return owl_divider_helper_set_rate(&comp->common, &comp->rate.div_hw, 80 + rate, parent_rate); 81 + } 82 + 83 + static long owl_comp_fact_round_rate(struct clk_hw *hw, unsigned long rate, 84 + unsigned long *parent_rate) 85 + { 86 + struct owl_composite *comp = hw_to_owl_comp(hw); 87 + 88 + return owl_factor_helper_round_rate(&comp->common, 89 + &comp->rate.factor_hw, 90 + rate, parent_rate); 91 + } 92 + 93 + static unsigned long owl_comp_fact_recalc_rate(struct clk_hw *hw, 94 + unsigned long parent_rate) 95 + { 96 + struct owl_composite *comp = hw_to_owl_comp(hw); 97 + 98 + return owl_factor_helper_recalc_rate(&comp->common, 99 + &comp->rate.factor_hw, 100 + parent_rate); 101 + } 102 + 103 + static int owl_comp_fact_set_rate(struct clk_hw *hw, unsigned long rate, 104 + unsigned long parent_rate) 105 + { 106 + struct owl_composite *comp = hw_to_owl_comp(hw); 107 + 108 + return owl_factor_helper_set_rate(&comp->common, 109 + &comp->rate.factor_hw, 110 + rate, parent_rate); 111 + } 112 + 113 + static long owl_comp_fix_fact_round_rate(struct clk_hw *hw, unsigned long rate, 114 + unsigned long *parent_rate) 115 + { 116 + struct owl_composite *comp = hw_to_owl_comp(hw); 117 + struct clk_fixed_factor *fix_fact_hw = &comp->rate.fix_fact_hw; 118 + 119 + return comp->fix_fact_ops->round_rate(&fix_fact_hw->hw, rate, parent_rate); 120 + } 121 + 122 + static unsigned long owl_comp_fix_fact_recalc_rate(struct clk_hw *hw, 123 + unsigned long parent_rate) 124 + { 125 + struct owl_composite *comp = hw_to_owl_comp(hw); 126 + struct clk_fixed_factor *fix_fact_hw = &comp->rate.fix_fact_hw; 127 + 128 + return comp->fix_fact_ops->recalc_rate(&fix_fact_hw->hw, parent_rate); 129 + 130 + } 131 + 132 + static int owl_comp_fix_fact_set_rate(struct clk_hw *hw, unsigned long rate, 133 + unsigned long parent_rate) 134 + { 135 + /* 136 + * We must report success but we can do so unconditionally because 137 + * owl_comp_fix_fact_round_rate returns values that ensure this call is 138 + * a nop. 139 + */ 140 + 141 + return 0; 142 + } 143 + 144 + const struct clk_ops owl_comp_div_ops = { 145 + /* mux_ops */ 146 + .get_parent = owl_comp_get_parent, 147 + .set_parent = owl_comp_set_parent, 148 + 149 + /* gate_ops */ 150 + .disable = owl_comp_disable, 151 + .enable = owl_comp_enable, 152 + .is_enabled = owl_comp_is_enabled, 153 + 154 + /* div_ops */ 155 + .round_rate = owl_comp_div_round_rate, 156 + .recalc_rate = owl_comp_div_recalc_rate, 157 + .set_rate = owl_comp_div_set_rate, 158 + }; 159 + 160 + 161 + const struct clk_ops owl_comp_fact_ops = { 162 + /* mux_ops */ 163 + .get_parent = owl_comp_get_parent, 164 + .set_parent = owl_comp_set_parent, 165 + 166 + /* gate_ops */ 167 + .disable = owl_comp_disable, 168 + .enable = owl_comp_enable, 169 + .is_enabled = owl_comp_is_enabled, 170 + 171 + /* fact_ops */ 172 + .round_rate = owl_comp_fact_round_rate, 173 + .recalc_rate = owl_comp_fact_recalc_rate, 174 + .set_rate = owl_comp_fact_set_rate, 175 + }; 176 + 177 + const struct clk_ops owl_comp_fix_fact_ops = { 178 + /* gate_ops */ 179 + .disable = owl_comp_disable, 180 + .enable = owl_comp_enable, 181 + .is_enabled = owl_comp_is_enabled, 182 + 183 + /* fix_fact_ops */ 184 + .round_rate = owl_comp_fix_fact_round_rate, 185 + .recalc_rate = owl_comp_fix_fact_recalc_rate, 186 + .set_rate = owl_comp_fix_fact_set_rate, 187 + }; 188 + 189 + 190 + const struct clk_ops owl_comp_pass_ops = { 191 + /* mux_ops */ 192 + .get_parent = owl_comp_get_parent, 193 + .set_parent = owl_comp_set_parent, 194 + 195 + /* gate_ops */ 196 + .disable = owl_comp_disable, 197 + .enable = owl_comp_enable, 198 + .is_enabled = owl_comp_is_enabled, 199 + };
+124
drivers/clk/actions/owl-composite.h
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + // 3 + // OWL composite clock driver 4 + // 5 + // Copyright (c) 2014 Actions Semi Inc. 6 + // Author: David Liu <liuwei@actions-semi.com> 7 + // 8 + // Copyright (c) 2018 Linaro Ltd. 9 + // Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> 10 + 11 + #ifndef _OWL_COMPOSITE_H_ 12 + #define _OWL_COMPOSITE_H_ 13 + 14 + #include "owl-common.h" 15 + #include "owl-mux.h" 16 + #include "owl-gate.h" 17 + #include "owl-factor.h" 18 + #include "owl-fixed-factor.h" 19 + #include "owl-divider.h" 20 + 21 + union owl_rate { 22 + struct owl_divider_hw div_hw; 23 + struct owl_factor_hw factor_hw; 24 + struct clk_fixed_factor fix_fact_hw; 25 + }; 26 + 27 + struct owl_composite { 28 + struct owl_mux_hw mux_hw; 29 + struct owl_gate_hw gate_hw; 30 + union owl_rate rate; 31 + 32 + const struct clk_ops *fix_fact_ops; 33 + 34 + struct owl_clk_common common; 35 + }; 36 + 37 + #define OWL_COMP_DIV(_struct, _name, _parent, \ 38 + _mux, _gate, _div, _flags) \ 39 + struct owl_composite _struct = { \ 40 + .mux_hw = _mux, \ 41 + .gate_hw = _gate, \ 42 + .rate.div_hw = _div, \ 43 + .common = { \ 44 + .regmap = NULL, \ 45 + .hw.init = CLK_HW_INIT_PARENTS(_name, \ 46 + _parent, \ 47 + &owl_comp_div_ops,\ 48 + _flags), \ 49 + }, \ 50 + } 51 + 52 + #define OWL_COMP_DIV_FIXED(_struct, _name, _parent, \ 53 + _gate, _div, _flags) \ 54 + struct owl_composite _struct = { \ 55 + .gate_hw = _gate, \ 56 + .rate.div_hw = _div, \ 57 + .common = { \ 58 + .regmap = NULL, \ 59 + .hw.init = CLK_HW_INIT(_name, \ 60 + _parent, \ 61 + &owl_comp_div_ops,\ 62 + _flags), \ 63 + }, \ 64 + } 65 + 66 + #define OWL_COMP_FACTOR(_struct, _name, _parent, \ 67 + _mux, _gate, _factor, _flags) \ 68 + struct owl_composite _struct = { \ 69 + .mux_hw = _mux, \ 70 + .gate_hw = _gate, \ 71 + .rate.factor_hw = _factor, \ 72 + .common = { \ 73 + .regmap = NULL, \ 74 + .hw.init = CLK_HW_INIT_PARENTS(_name, \ 75 + _parent, \ 76 + &owl_comp_fact_ops,\ 77 + _flags), \ 78 + }, \ 79 + } 80 + 81 + #define OWL_COMP_FIXED_FACTOR(_struct, _name, _parent, \ 82 + _gate, _mul, _div, _flags) \ 83 + struct owl_composite _struct = { \ 84 + .gate_hw = _gate, \ 85 + .rate.fix_fact_hw.mult = _mul, \ 86 + .rate.fix_fact_hw.div = _div, \ 87 + .fix_fact_ops = &clk_fixed_factor_ops, \ 88 + .common = { \ 89 + .regmap = NULL, \ 90 + .hw.init = CLK_HW_INIT(_name, \ 91 + _parent, \ 92 + &owl_comp_fix_fact_ops,\ 93 + _flags), \ 94 + }, \ 95 + } 96 + 97 + #define OWL_COMP_PASS(_struct, _name, _parent, \ 98 + _mux, _gate, _flags) \ 99 + struct owl_composite _struct = { \ 100 + .mux_hw = _mux, \ 101 + .gate_hw = _gate, \ 102 + .common = { \ 103 + .regmap = NULL, \ 104 + .hw.init = CLK_HW_INIT_PARENTS(_name, \ 105 + _parent, \ 106 + &owl_comp_pass_ops,\ 107 + _flags), \ 108 + }, \ 109 + } 110 + 111 + static inline struct owl_composite *hw_to_owl_comp(const struct clk_hw *hw) 112 + { 113 + struct owl_clk_common *common = hw_to_owl_clk_common(hw); 114 + 115 + return container_of(common, struct owl_composite, common); 116 + } 117 + 118 + extern const struct clk_ops owl_comp_div_ops; 119 + extern const struct clk_ops owl_comp_fact_ops; 120 + extern const struct clk_ops owl_comp_fix_fact_ops; 121 + extern const struct clk_ops owl_comp_pass_ops; 122 + extern const struct clk_ops clk_fixed_factor_ops; 123 + 124 + #endif /* _OWL_COMPOSITE_H_ */