Lines Matching +full:t8103 +full:- +full:nco
1 // SPDX-License-Identifier: GPL-2.0-only OR MIT
4 * found on t8103 (M1) and other Apple chips
11 #include <linux/clk-provider.h>
37 * base divisor is adjusted on a cycle-by-cycle basis based on the state of a
38 * 32-bit phase accumulator to achieve a desired precise clock ratio over the
43 * bit of the 32-bit accumulator is set. The accumulator is incremented each
47 * Because the NCO hardware implements counting of input clock cycles in part
48 * in a Galois linear-feedback shift register, the higher bits of divisor
56 #define LFSR_PERIOD ((1 << LFSR_LEN) - 1)
82 val = readl_relaxed(chan->base + REG_CTRL); in applnco_enable_nolock()
83 writel_relaxed(val | CTRL_ENABLE, chan->base + REG_CTRL); in applnco_enable_nolock()
91 val = readl_relaxed(chan->base + REG_CTRL); in applnco_disable_nolock()
92 writel_relaxed(val & ~CTRL_ENABLE, chan->base + REG_CTRL); in applnco_disable_nolock()
99 return (readl_relaxed(chan->base + REG_CTRL) & CTRL_ENABLE) != 0; in applnco_is_enabled()
111 for (i = LFSR_PERIOD; i > 0; i--) { in applnco_compute_tables()
116 tbl->fwd[i] = state; in applnco_compute_tables()
117 tbl->inv[state] = i; in applnco_compute_tables()
120 /* Zero value is special-cased */ in applnco_compute_tables()
121 tbl->fwd[0] = 0; in applnco_compute_tables()
122 tbl->inv[0] = 0; in applnco_compute_tables()
140 return FIELD_PREP(DIV_COARSE, tbl->fwd[coarse - COARSE_DIV_OFFSET]) | in applnco_div_translate()
148 coarse = tbl->inv[FIELD_GET(DIV_COARSE, regval)] + COARSE_DIV_OFFSET; in applnco_div_translate_inv()
163 inc1 = 2 * parent_rate - div * rate; in applnco_set_rate()
164 inc2 = inc1 - rate; in applnco_set_rate()
167 return -EINVAL; in applnco_set_rate()
169 div = applnco_div_translate(chan->tbl, div); in applnco_set_rate()
171 spin_lock_irqsave(&chan->lock, flags); in applnco_set_rate()
175 writel_relaxed(div, chan->base + REG_DIV); in applnco_set_rate()
176 writel_relaxed(inc1, chan->base + REG_INC1); in applnco_set_rate()
177 writel_relaxed(inc2, chan->base + REG_INC2); in applnco_set_rate()
180 writel_relaxed(1 << 31, chan->base + REG_ACCINIT); in applnco_set_rate()
184 spin_unlock_irqrestore(&chan->lock, flags); in applnco_set_rate()
195 div = applnco_div_translate_inv(chan->tbl, in applnco_recalc_rate()
196 readl_relaxed(chan->base + REG_DIV)); in applnco_recalc_rate()
198 inc1 = readl_relaxed(chan->base + REG_INC1); in applnco_recalc_rate()
199 inc2 = readl_relaxed(chan->base + REG_INC2); in applnco_recalc_rate()
209 incbase = inc1 - inc2; in applnco_recalc_rate()
229 spin_lock_irqsave(&chan->lock, flags); in applnco_enable()
231 spin_unlock_irqrestore(&chan->lock, flags); in applnco_enable()
241 spin_lock_irqsave(&chan->lock, flags); in applnco_disable()
243 spin_unlock_irqrestore(&chan->lock, flags); in applnco_disable()
257 struct device_node *np = pdev->dev.of_node; in applnco_probe()
272 return -EINVAL; in applnco_probe()
273 nchannels = (resource_size(res) - NCO_CHANNEL_REGSIZE) in applnco_probe()
276 onecell_data = devm_kzalloc(&pdev->dev, struct_size(onecell_data, hws, in applnco_probe()
279 return -ENOMEM; in applnco_probe()
280 onecell_data->num = nchannels; in applnco_probe()
282 tbl = devm_kzalloc(&pdev->dev, sizeof(*tbl), GFP_KERNEL); in applnco_probe()
284 return -ENOMEM; in applnco_probe()
290 chan = devm_kzalloc(&pdev->dev, sizeof(*chan), GFP_KERNEL); in applnco_probe()
292 return -ENOMEM; in applnco_probe()
293 chan->base = base + NCO_CHANNEL_STRIDE * i; in applnco_probe()
294 chan->tbl = tbl; in applnco_probe()
295 spin_lock_init(&chan->lock); in applnco_probe()
298 init.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, in applnco_probe()
299 "%s-%d", np->name, i); in applnco_probe()
301 return -ENOMEM; in applnco_probe()
308 chan->hw.init = &init; in applnco_probe()
309 ret = devm_clk_hw_register(&pdev->dev, &chan->hw); in applnco_probe()
313 onecell_data->hws[i] = &chan->hw; in applnco_probe()
316 return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get, in applnco_probe()
321 { .compatible = "apple,nco" },
328 .name = "apple-nco",
336 MODULE_DESCRIPTION("Clock driver for NCO blocks on Apple SoCs");