Lines Matching +full:divider +full:- +full:width
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
17 #include "clk-stm32-core.h"
18 #include "reset-stm32.h"
26 const struct stm32_rcc_match_data *data = match->data; in stm32_rcc_clock_init()
27 struct clk_hw_onecell_data *clk_data = data->hw_clks; in stm32_rcc_clock_init()
31 max_binding = data->maxbinding; in stm32_rcc_clock_init()
35 return -ENOMEM; in stm32_rcc_clock_init()
37 clk_data->num = max_binding; in stm32_rcc_clock_init()
39 hws = clk_data->hws; in stm32_rcc_clock_init()
42 hws[n] = ERR_PTR(-ENOENT); in stm32_rcc_clock_init()
44 for (n = 0; n < data->num_clocks; n++) { in stm32_rcc_clock_init()
45 const struct clock_config *cfg_clock = &data->tab_clocks[n]; in stm32_rcc_clock_init()
46 struct clk_hw *hw = ERR_PTR(-ENOENT); in stm32_rcc_clock_init()
48 if (data->check_security && in stm32_rcc_clock_init()
49 data->check_security(dev->of_node, base, cfg_clock)) in stm32_rcc_clock_init()
52 if (cfg_clock->func) in stm32_rcc_clock_init()
53 hw = (*cfg_clock->func)(dev, data, base, &rlock, in stm32_rcc_clock_init()
62 if (cfg_clock->id != NO_ID) in stm32_rcc_clock_init()
63 hws[cfg_clock->id] = hw; in stm32_rcc_clock_init()
79 return -ENODEV; in stm32_rcc_init()
82 rcc_match_data = match->data; in stm32_rcc_init()
85 err = stm32_rcc_reset_init(dev, rcc_match_data->reset_data, base); in stm32_rcc_init()
105 const struct stm32_mux_cfg *mux = &data->muxes[mux_id]; in stm32_mux_get_parent()
106 u32 mask = BIT(mux->width) - 1; in stm32_mux_get_parent()
109 val = readl(base + mux->offset) >> mux->shift; in stm32_mux_get_parent()
119 const struct stm32_mux_cfg *mux = &data->muxes[mux_id]; in stm32_mux_set_parent()
121 u32 mask = BIT(mux->width) - 1; in stm32_mux_set_parent()
122 u32 reg = readl(base + mux->offset); in stm32_mux_set_parent()
123 u32 val = index << mux->shift; in stm32_mux_set_parent()
125 reg &= ~(mask << mux->shift); in stm32_mux_set_parent()
128 writel(reg, base + mux->offset); in stm32_mux_set_parent()
137 const struct stm32_gate_cfg *gate = &data->gates[gate_id]; in stm32_gate_endisable()
138 void __iomem *addr = base + gate->offset; in stm32_gate_endisable()
141 if (data->gate_cpt[gate_id]++ > 0) in stm32_gate_endisable()
144 if (gate->set_clr != 0) in stm32_gate_endisable()
145 writel(BIT(gate->bit_idx), addr); in stm32_gate_endisable()
147 writel(readl(addr) | BIT(gate->bit_idx), addr); in stm32_gate_endisable()
149 if (--data->gate_cpt[gate_id] > 0) in stm32_gate_endisable()
152 if (gate->set_clr != 0) in stm32_gate_endisable()
153 writel(BIT(gate->bit_idx), addr + gate->set_clr); in stm32_gate_endisable()
155 writel(readl(addr) & ~BIT(gate->bit_idx), addr); in stm32_gate_endisable()
163 const struct stm32_gate_cfg *gate = &data->gates[gate_id]; in stm32_gate_disable_unused()
164 void __iomem *addr = base + gate->offset; in stm32_gate_disable_unused()
166 if (data->gate_cpt[gate_id] > 0) in stm32_gate_disable_unused()
169 if (gate->set_clr != 0) in stm32_gate_disable_unused()
170 writel(BIT(gate->bit_idx), addr + gate->set_clr); in stm32_gate_disable_unused()
172 writel(readl(addr) & ~BIT(gate->bit_idx), addr); in stm32_gate_disable_unused()
179 const struct stm32_gate_cfg *gate = &data->gates[gate_id]; in stm32_gate_is_enabled()
181 return (readl(base + gate->offset) & BIT(gate->bit_idx)) != 0; in stm32_gate_is_enabled()
189 for (clkt = table; clkt->div; clkt++) in _get_table_div()
190 if (clkt->val == val) in _get_table_div()
191 return clkt->div; in _get_table_div()
196 unsigned int val, unsigned long flags, u8 width) in _get_div() argument
212 const struct stm32_div_cfg *divider = &data->dividers[div_id]; in stm32_divider_get_rate() local
216 val = readl(base + divider->offset) >> divider->shift; in stm32_divider_get_rate()
217 val &= clk_div_mask(divider->width); in stm32_divider_get_rate()
218 div = _get_div(divider->table, val, divider->flags, divider->width); in stm32_divider_get_rate()
221 WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO), in stm32_divider_get_rate()
235 const struct stm32_div_cfg *divider = &data->dividers[div_id]; in stm32_divider_set_rate() local
239 value = divider_get_val(rate, parent_rate, divider->table, in stm32_divider_set_rate()
240 divider->width, divider->flags); in stm32_divider_set_rate()
244 if (divider->flags & CLK_DIVIDER_HIWORD_MASK) { in stm32_divider_set_rate()
245 val = clk_div_mask(divider->width) << (divider->shift + 16); in stm32_divider_set_rate()
247 val = readl(base + divider->offset); in stm32_divider_set_rate()
248 val &= ~(clk_div_mask(divider->width) << divider->shift); in stm32_divider_set_rate()
251 val |= (u32)value << divider->shift; in stm32_divider_set_rate()
253 writel(val, base + divider->offset); in stm32_divider_set_rate()
262 return stm32_mux_get_parent(mux->base, mux->clock_data, mux->mux_id); in clk_stm32_mux_get_parent()
270 spin_lock_irqsave(mux->lock, flags); in clk_stm32_mux_set_parent()
272 stm32_mux_set_parent(mux->base, mux->clock_data, mux->mux_id, index); in clk_stm32_mux_set_parent()
274 spin_unlock_irqrestore(mux->lock, flags); in clk_stm32_mux_set_parent()
290 spin_lock_irqsave(gate->lock, flags); in clk_stm32_gate_endisable()
292 stm32_gate_endisable(gate->base, gate->clock_data, gate->gate_id, enable); in clk_stm32_gate_endisable()
294 spin_unlock_irqrestore(gate->lock, flags); in clk_stm32_gate_endisable()
313 return stm32_gate_is_enabled(gate->base, gate->clock_data, gate->gate_id); in clk_stm32_gate_is_enabled()
321 spin_lock_irqsave(gate->lock, flags); in clk_stm32_gate_disable_unused()
323 stm32_gate_disable_unused(gate->base, gate->clock_data, gate->gate_id); in clk_stm32_gate_disable_unused()
325 spin_unlock_irqrestore(gate->lock, flags); in clk_stm32_gate_disable_unused()
342 if (div->div_id == NO_STM32_DIV) in clk_stm32_divider_set_rate()
345 spin_lock_irqsave(div->lock, flags); in clk_stm32_divider_set_rate()
347 ret = stm32_divider_set_rate(div->base, div->clock_data, div->div_id, rate, parent_rate); in clk_stm32_divider_set_rate()
349 spin_unlock_irqrestore(div->lock, flags); in clk_stm32_divider_set_rate()
358 const struct stm32_div_cfg *divider; in clk_stm32_divider_round_rate() local
360 if (div->div_id == NO_STM32_DIV) in clk_stm32_divider_round_rate()
363 divider = &div->clock_data->dividers[div->div_id]; in clk_stm32_divider_round_rate()
366 if (divider->flags & CLK_DIVIDER_READ_ONLY) { in clk_stm32_divider_round_rate()
369 val = readl(div->base + divider->offset) >> divider->shift; in clk_stm32_divider_round_rate()
370 val &= clk_div_mask(divider->width); in clk_stm32_divider_round_rate()
372 return divider_ro_round_rate(hw, rate, prate, divider->table, in clk_stm32_divider_round_rate()
373 divider->width, divider->flags, in clk_stm32_divider_round_rate()
378 rate, prate, divider->table, in clk_stm32_divider_round_rate()
379 divider->width, divider->flags); in clk_stm32_divider_round_rate()
387 if (div->div_id == NO_STM32_DIV) in clk_stm32_divider_recalc_rate()
390 return stm32_divider_get_rate(div->base, div->clock_data, div->div_id, parent_rate); in clk_stm32_divider_recalc_rate()
406 if (composite->div_id == NO_STM32_DIV) in clk_stm32_composite_set_rate()
409 spin_lock_irqsave(composite->lock, flags); in clk_stm32_composite_set_rate()
411 ret = stm32_divider_set_rate(composite->base, composite->clock_data, in clk_stm32_composite_set_rate()
412 composite->div_id, rate, parent_rate); in clk_stm32_composite_set_rate()
414 spin_unlock_irqrestore(composite->lock, flags); in clk_stm32_composite_set_rate()
424 if (composite->div_id == NO_STM32_DIV) in clk_stm32_composite_recalc_rate()
427 return stm32_divider_get_rate(composite->base, composite->clock_data, in clk_stm32_composite_recalc_rate()
428 composite->div_id, parent_rate); in clk_stm32_composite_recalc_rate()
435 const struct stm32_div_cfg *divider; in clk_stm32_composite_determine_rate() local
438 if (composite->div_id == NO_STM32_DIV) in clk_stm32_composite_determine_rate()
441 divider = &composite->clock_data->dividers[composite->div_id]; in clk_stm32_composite_determine_rate()
444 if (divider->flags & CLK_DIVIDER_READ_ONLY) { in clk_stm32_composite_determine_rate()
447 val = readl(composite->base + divider->offset) >> divider->shift; in clk_stm32_composite_determine_rate()
448 val &= clk_div_mask(divider->width); in clk_stm32_composite_determine_rate()
450 rate = divider_ro_round_rate(hw, req->rate, &req->best_parent_rate, in clk_stm32_composite_determine_rate()
451 divider->table, divider->width, divider->flags, in clk_stm32_composite_determine_rate()
456 req->rate = rate; in clk_stm32_composite_determine_rate()
461 req->rate, &req->best_parent_rate, in clk_stm32_composite_determine_rate()
462 divider->table, divider->width, divider->flags); in clk_stm32_composite_determine_rate()
466 req->rate = rate; in clk_stm32_composite_determine_rate()
474 return stm32_mux_get_parent(composite->base, composite->clock_data, composite->mux_id); in clk_stm32_composite_get_parent()
482 spin_lock_irqsave(composite->lock, flags); in clk_stm32_composite_set_parent()
484 stm32_mux_set_parent(composite->base, composite->clock_data, composite->mux_id, index); in clk_stm32_composite_set_parent()
486 spin_unlock_irqrestore(composite->lock, flags); in clk_stm32_composite_set_parent()
488 if (composite->clock_data->is_multi_mux) { in clk_stm32_composite_set_parent()
489 struct clk_hw *other_mux_hw = composite->clock_data->is_multi_mux(hw); in clk_stm32_composite_set_parent()
505 if (composite->gate_id == NO_STM32_GATE) in clk_stm32_composite_is_enabled()
506 return (__clk_get_enable_count(hw->clk) > 0); in clk_stm32_composite_is_enabled()
508 return stm32_gate_is_enabled(composite->base, composite->clock_data, composite->gate_id); in clk_stm32_composite_is_enabled()
516 const struct stm32_mux_cfg *mux = &composite->clock_data->muxes[composite->mux_id]; in clk_stm32_has_safe_mux()
518 return !!(mux->flags & MUX_SAFE); in clk_stm32_has_safe_mux()
528 if (composite->clock_data->is_multi_mux) { in clk_stm32_set_safe_position_mux()
531 other_mux_hw = composite->clock_data->is_multi_mux(hw); in clk_stm32_set_safe_position_mux()
537 spin_lock_irqsave(composite->lock, flags); in clk_stm32_set_safe_position_mux()
539 stm32_mux_set_parent(composite->base, composite->clock_data, in clk_stm32_set_safe_position_mux()
540 composite->mux_id, MUX_SAFE_POSITION); in clk_stm32_set_safe_position_mux()
542 spin_unlock_irqrestore(composite->lock, flags); in clk_stm32_set_safe_position_mux()
552 spin_lock_irqsave(composite->lock, flags); in clk_stm32_safe_restore_position_mux()
554 stm32_mux_set_parent(composite->base, composite->clock_data, composite->mux_id, sel); in clk_stm32_safe_restore_position_mux()
556 spin_unlock_irqrestore(composite->lock, flags); in clk_stm32_safe_restore_position_mux()
564 spin_lock_irqsave(composite->lock, flags); in clk_stm32_composite_gate_endisable()
566 stm32_gate_endisable(composite->base, composite->clock_data, composite->gate_id, enable); in clk_stm32_composite_gate_endisable()
568 spin_unlock_irqrestore(composite->lock, flags); in clk_stm32_composite_gate_endisable()
575 if (composite->gate_id == NO_STM32_GATE) in clk_stm32_composite_gate_enable()
580 if (composite->mux_id != NO_STM32_MUX && clk_stm32_has_safe_mux(hw)) in clk_stm32_composite_gate_enable()
590 if (composite->gate_id == NO_STM32_GATE) in clk_stm32_composite_gate_disable()
595 if (composite->mux_id != NO_STM32_MUX && clk_stm32_has_safe_mux(hw)) in clk_stm32_composite_gate_disable()
604 if (composite->gate_id == NO_STM32_GATE) in clk_stm32_composite_disable_unused()
607 spin_lock_irqsave(composite->lock, flags); in clk_stm32_composite_disable_unused()
609 stm32_gate_disable_unused(composite->base, composite->clock_data, composite->gate_id); in clk_stm32_composite_disable_unused()
611 spin_unlock_irqrestore(composite->lock, flags); in clk_stm32_composite_disable_unused()
632 struct clk_stm32_mux *mux = cfg->clock_cfg; in clk_stm32_mux_register()
633 struct clk_hw *hw = &mux->hw; in clk_stm32_mux_register()
636 mux->base = base; in clk_stm32_mux_register()
637 mux->lock = lock; in clk_stm32_mux_register()
638 mux->clock_data = data->clock_data; in clk_stm32_mux_register()
653 struct clk_stm32_gate *gate = cfg->clock_cfg; in clk_stm32_gate_register()
654 struct clk_hw *hw = &gate->hw; in clk_stm32_gate_register()
657 gate->base = base; in clk_stm32_gate_register()
658 gate->lock = lock; in clk_stm32_gate_register()
659 gate->clock_data = data->clock_data; in clk_stm32_gate_register()
674 struct clk_stm32_div *div = cfg->clock_cfg; in clk_stm32_div_register()
675 struct clk_hw *hw = &div->hw; in clk_stm32_div_register()
678 div->base = base; in clk_stm32_div_register()
679 div->lock = lock; in clk_stm32_div_register()
680 div->clock_data = data->clock_data; in clk_stm32_div_register()
695 struct clk_stm32_composite *composite = cfg->clock_cfg; in clk_stm32_composite_register()
696 struct clk_hw *hw = &composite->hw; in clk_stm32_composite_register()
699 composite->base = base; in clk_stm32_composite_register()
700 composite->lock = lock; in clk_stm32_composite_register()
701 composite->clock_data = data->clock_data; in clk_stm32_composite_register()