owl-composite.c (5087B)
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 16static 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 23static 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 30static 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 38static 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 48static 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 56static 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 65static 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 74static 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 83static 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 93static 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 103static 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 113static 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 122static 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 132static 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 144const 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 161const 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 177const 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 190const 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};