Lines Matching +full:clk +full:- +full:div
16 #include <linux/clk-provider.h>
23 #include "clk-iproc.h"
32 struct iproc_asiu_div div; member
48 struct iproc_asiu_clk *clk = to_asiu_clk(hw); in iproc_asiu_clk_enable() local
49 struct iproc_asiu *asiu = clk->asiu; in iproc_asiu_clk_enable()
53 if (clk->gate.offset == IPROC_CLK_INVALID_OFFSET) in iproc_asiu_clk_enable()
56 val = readl(asiu->gate_base + clk->gate.offset); in iproc_asiu_clk_enable()
57 val |= (1 << clk->gate.en_shift); in iproc_asiu_clk_enable()
58 writel(val, asiu->gate_base + clk->gate.offset); in iproc_asiu_clk_enable()
65 struct iproc_asiu_clk *clk = to_asiu_clk(hw); in iproc_asiu_clk_disable() local
66 struct iproc_asiu *asiu = clk->asiu; in iproc_asiu_clk_disable()
70 if (clk->gate.offset == IPROC_CLK_INVALID_OFFSET) in iproc_asiu_clk_disable()
73 val = readl(asiu->gate_base + clk->gate.offset); in iproc_asiu_clk_disable()
74 val &= ~(1 << clk->gate.en_shift); in iproc_asiu_clk_disable()
75 writel(val, asiu->gate_base + clk->gate.offset); in iproc_asiu_clk_disable()
81 struct iproc_asiu_clk *clk = to_asiu_clk(hw); in iproc_asiu_clk_recalc_rate() local
82 struct iproc_asiu *asiu = clk->asiu; in iproc_asiu_clk_recalc_rate()
87 clk->rate = 0; in iproc_asiu_clk_recalc_rate()
92 val = readl(asiu->div_base + clk->div.offset); in iproc_asiu_clk_recalc_rate()
93 if ((val & (1 << clk->div.en_shift)) == 0) { in iproc_asiu_clk_recalc_rate()
94 clk->rate = parent_rate; in iproc_asiu_clk_recalc_rate()
99 div_h = (val >> clk->div.high_shift) & bit_mask(clk->div.high_width); in iproc_asiu_clk_recalc_rate()
101 div_l = (val >> clk->div.low_shift) & bit_mask(clk->div.low_width); in iproc_asiu_clk_recalc_rate()
104 clk->rate = parent_rate / (div_h + div_l); in iproc_asiu_clk_recalc_rate()
106 __func__, clk->rate, parent_rate, div_h, div_l); in iproc_asiu_clk_recalc_rate()
108 return clk->rate; in iproc_asiu_clk_recalc_rate()
114 unsigned int div; in iproc_asiu_clk_round_rate() local
117 return -EINVAL; in iproc_asiu_clk_round_rate()
122 div = DIV_ROUND_CLOSEST(*parent_rate, rate); in iproc_asiu_clk_round_rate()
123 if (div < 2) in iproc_asiu_clk_round_rate()
126 return *parent_rate / div; in iproc_asiu_clk_round_rate()
132 struct iproc_asiu_clk *clk = to_asiu_clk(hw); in iproc_asiu_clk_set_rate() local
133 struct iproc_asiu *asiu = clk->asiu; in iproc_asiu_clk_set_rate()
134 unsigned int div, div_h, div_l; in iproc_asiu_clk_set_rate() local
138 return -EINVAL; in iproc_asiu_clk_set_rate()
142 val = readl(asiu->div_base + clk->div.offset); in iproc_asiu_clk_set_rate()
143 val &= ~(1 << clk->div.en_shift); in iproc_asiu_clk_set_rate()
144 writel(val, asiu->div_base + clk->div.offset); in iproc_asiu_clk_set_rate()
148 div = DIV_ROUND_CLOSEST(parent_rate, rate); in iproc_asiu_clk_set_rate()
149 if (div < 2) in iproc_asiu_clk_set_rate()
150 return -EINVAL; in iproc_asiu_clk_set_rate()
152 div_h = div_l = div >> 1; in iproc_asiu_clk_set_rate()
153 div_h--; in iproc_asiu_clk_set_rate()
154 div_l--; in iproc_asiu_clk_set_rate()
156 val = readl(asiu->div_base + clk->div.offset); in iproc_asiu_clk_set_rate()
157 val |= 1 << clk->div.en_shift; in iproc_asiu_clk_set_rate()
159 val &= ~(bit_mask(clk->div.high_width) in iproc_asiu_clk_set_rate()
160 << clk->div.high_shift); in iproc_asiu_clk_set_rate()
161 val |= div_h << clk->div.high_shift; in iproc_asiu_clk_set_rate()
163 val &= ~(bit_mask(clk->div.high_width) in iproc_asiu_clk_set_rate()
164 << clk->div.high_shift); in iproc_asiu_clk_set_rate()
167 val &= ~(bit_mask(clk->div.low_width) << clk->div.low_shift); in iproc_asiu_clk_set_rate()
168 val |= div_l << clk->div.low_shift; in iproc_asiu_clk_set_rate()
170 val &= ~(bit_mask(clk->div.low_width) << clk->div.low_shift); in iproc_asiu_clk_set_rate()
172 writel(val, asiu->div_base + clk->div.offset); in iproc_asiu_clk_set_rate()
186 const struct iproc_asiu_div *div, in iproc_asiu_setup() argument
193 if (WARN_ON(!gate || !div)) in iproc_asiu_setup()
200 asiu->clk_data = kzalloc(struct_size(asiu->clk_data, hws, num_clks), in iproc_asiu_setup()
202 if (WARN_ON(!asiu->clk_data)) in iproc_asiu_setup()
204 asiu->clk_data->num = num_clks; in iproc_asiu_setup()
206 asiu->clks = kcalloc(num_clks, sizeof(*asiu->clks), GFP_KERNEL); in iproc_asiu_setup()
207 if (WARN_ON(!asiu->clks)) in iproc_asiu_setup()
210 asiu->div_base = of_iomap(node, 0); in iproc_asiu_setup()
211 if (WARN_ON(!asiu->div_base)) in iproc_asiu_setup()
214 asiu->gate_base = of_iomap(node, 1); in iproc_asiu_setup()
215 if (WARN_ON(!asiu->gate_base)) in iproc_asiu_setup()
224 ret = of_property_read_string_index(node, "clock-output-names", in iproc_asiu_setup()
229 asiu_clk = &asiu->clks[i]; in iproc_asiu_setup()
230 asiu_clk->name = clk_name; in iproc_asiu_setup()
231 asiu_clk->asiu = asiu; in iproc_asiu_setup()
232 asiu_clk->div = div[i]; in iproc_asiu_setup()
233 asiu_clk->gate = gate[i]; in iproc_asiu_setup()
240 asiu_clk->hw.init = &init; in iproc_asiu_setup()
242 ret = clk_hw_register(NULL, &asiu_clk->hw); in iproc_asiu_setup()
245 asiu->clk_data->hws[i] = &asiu_clk->hw; in iproc_asiu_setup()
249 asiu->clk_data); in iproc_asiu_setup()
256 while (--i >= 0) in iproc_asiu_setup()
257 clk_hw_unregister(asiu->clk_data->hws[i]); in iproc_asiu_setup()
258 iounmap(asiu->gate_base); in iproc_asiu_setup()
261 iounmap(asiu->div_base); in iproc_asiu_setup()
264 kfree(asiu->clks); in iproc_asiu_setup()
267 kfree(asiu->clk_data); in iproc_asiu_setup()