Lines Matching +full:clk +full:- +full:div

1 // SPDX-License-Identifier: GPL-2.0-only
6 #include <linux/clk-provider.h>
13 #include "clk-iproc.h"
22 struct iproc_asiu_div div; member
38 struct iproc_asiu_clk *clk = to_asiu_clk(hw); in iproc_asiu_clk_enable() local
39 struct iproc_asiu *asiu = clk->asiu; in iproc_asiu_clk_enable()
43 if (clk->gate.offset == IPROC_CLK_INVALID_OFFSET) in iproc_asiu_clk_enable()
46 val = readl(asiu->gate_base + clk->gate.offset); in iproc_asiu_clk_enable()
47 val |= (1 << clk->gate.en_shift); in iproc_asiu_clk_enable()
48 writel(val, asiu->gate_base + clk->gate.offset); in iproc_asiu_clk_enable()
55 struct iproc_asiu_clk *clk = to_asiu_clk(hw); in iproc_asiu_clk_disable() local
56 struct iproc_asiu *asiu = clk->asiu; in iproc_asiu_clk_disable()
60 if (clk->gate.offset == IPROC_CLK_INVALID_OFFSET) in iproc_asiu_clk_disable()
63 val = readl(asiu->gate_base + clk->gate.offset); in iproc_asiu_clk_disable()
64 val &= ~(1 << clk->gate.en_shift); in iproc_asiu_clk_disable()
65 writel(val, asiu->gate_base + clk->gate.offset); in iproc_asiu_clk_disable()
71 struct iproc_asiu_clk *clk = to_asiu_clk(hw); in iproc_asiu_clk_recalc_rate() local
72 struct iproc_asiu *asiu = clk->asiu; in iproc_asiu_clk_recalc_rate()
77 clk->rate = 0; in iproc_asiu_clk_recalc_rate()
82 val = readl(asiu->div_base + clk->div.offset); in iproc_asiu_clk_recalc_rate()
83 if ((val & (1 << clk->div.en_shift)) == 0) { in iproc_asiu_clk_recalc_rate()
84 clk->rate = parent_rate; in iproc_asiu_clk_recalc_rate()
89 div_h = (val >> clk->div.high_shift) & bit_mask(clk->div.high_width); in iproc_asiu_clk_recalc_rate()
91 div_l = (val >> clk->div.low_shift) & bit_mask(clk->div.low_width); in iproc_asiu_clk_recalc_rate()
94 clk->rate = parent_rate / (div_h + div_l); in iproc_asiu_clk_recalc_rate()
96 __func__, clk->rate, parent_rate, div_h, div_l); in iproc_asiu_clk_recalc_rate()
98 return clk->rate; in iproc_asiu_clk_recalc_rate()
104 unsigned int div; in iproc_asiu_clk_round_rate() local
107 return -EINVAL; in iproc_asiu_clk_round_rate()
112 div = DIV_ROUND_CLOSEST(*parent_rate, rate); in iproc_asiu_clk_round_rate()
113 if (div < 2) in iproc_asiu_clk_round_rate()
116 return *parent_rate / div; in iproc_asiu_clk_round_rate()
122 struct iproc_asiu_clk *clk = to_asiu_clk(hw); in iproc_asiu_clk_set_rate() local
123 struct iproc_asiu *asiu = clk->asiu; in iproc_asiu_clk_set_rate()
124 unsigned int div, div_h, div_l; in iproc_asiu_clk_set_rate() local
128 return -EINVAL; in iproc_asiu_clk_set_rate()
132 val = readl(asiu->div_base + clk->div.offset); in iproc_asiu_clk_set_rate()
133 val &= ~(1 << clk->div.en_shift); in iproc_asiu_clk_set_rate()
134 writel(val, asiu->div_base + clk->div.offset); in iproc_asiu_clk_set_rate()
138 div = DIV_ROUND_CLOSEST(parent_rate, rate); in iproc_asiu_clk_set_rate()
139 if (div < 2) in iproc_asiu_clk_set_rate()
140 return -EINVAL; in iproc_asiu_clk_set_rate()
142 div_h = div_l = div >> 1; in iproc_asiu_clk_set_rate()
143 div_h--; in iproc_asiu_clk_set_rate()
144 div_l--; in iproc_asiu_clk_set_rate()
146 val = readl(asiu->div_base + clk->div.offset); in iproc_asiu_clk_set_rate()
147 val |= 1 << clk->div.en_shift; in iproc_asiu_clk_set_rate()
149 val &= ~(bit_mask(clk->div.high_width) in iproc_asiu_clk_set_rate()
150 << clk->div.high_shift); in iproc_asiu_clk_set_rate()
151 val |= div_h << clk->div.high_shift; in iproc_asiu_clk_set_rate()
153 val &= ~(bit_mask(clk->div.high_width) in iproc_asiu_clk_set_rate()
154 << clk->div.high_shift); in iproc_asiu_clk_set_rate()
157 val &= ~(bit_mask(clk->div.low_width) << clk->div.low_shift); in iproc_asiu_clk_set_rate()
158 val |= div_l << clk->div.low_shift; in iproc_asiu_clk_set_rate()
160 val &= ~(bit_mask(clk->div.low_width) << clk->div.low_shift); in iproc_asiu_clk_set_rate()
162 writel(val, asiu->div_base + clk->div.offset); in iproc_asiu_clk_set_rate()
176 const struct iproc_asiu_div *div, in iproc_asiu_setup() argument
183 if (WARN_ON(!gate || !div)) in iproc_asiu_setup()
190 asiu->clk_data = kzalloc(struct_size(asiu->clk_data, hws, num_clks), in iproc_asiu_setup()
192 if (WARN_ON(!asiu->clk_data)) in iproc_asiu_setup()
194 asiu->clk_data->num = num_clks; in iproc_asiu_setup()
196 asiu->clks = kcalloc(num_clks, sizeof(*asiu->clks), GFP_KERNEL); in iproc_asiu_setup()
197 if (WARN_ON(!asiu->clks)) in iproc_asiu_setup()
200 asiu->div_base = of_iomap(node, 0); in iproc_asiu_setup()
201 if (WARN_ON(!asiu->div_base)) in iproc_asiu_setup()
204 asiu->gate_base = of_iomap(node, 1); in iproc_asiu_setup()
205 if (WARN_ON(!asiu->gate_base)) in iproc_asiu_setup()
214 ret = of_property_read_string_index(node, "clock-output-names", in iproc_asiu_setup()
219 asiu_clk = &asiu->clks[i]; in iproc_asiu_setup()
220 asiu_clk->name = clk_name; in iproc_asiu_setup()
221 asiu_clk->asiu = asiu; in iproc_asiu_setup()
222 asiu_clk->div = div[i]; in iproc_asiu_setup()
223 asiu_clk->gate = gate[i]; in iproc_asiu_setup()
230 asiu_clk->hw.init = &init; in iproc_asiu_setup()
232 ret = clk_hw_register(NULL, &asiu_clk->hw); in iproc_asiu_setup()
235 asiu->clk_data->hws[i] = &asiu_clk->hw; in iproc_asiu_setup()
239 asiu->clk_data); in iproc_asiu_setup()
246 while (--i >= 0) in iproc_asiu_setup()
247 clk_hw_unregister(asiu->clk_data->hws[i]); in iproc_asiu_setup()
248 iounmap(asiu->gate_base); in iproc_asiu_setup()
251 iounmap(asiu->div_base); in iproc_asiu_setup()
254 kfree(asiu->clks); in iproc_asiu_setup()
257 kfree(asiu->clk_data); in iproc_asiu_setup()