| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- /*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date Author Notes
- * 2022-3-08 GuEe-GUI the first version
- */
- #include "clk-rk-mux.h"
- rt_inline rt_uint32_t clk_mux_readl(struct rockchip_clk_cell *rk_cell)
- {
- void *base = rk_cell->provider->reg_base;
- if (rk_cell->mux_flags & CLK_MUX_BIG_ENDIAN)
- {
- return rt_be32_to_cpu(HWREG32(base + rk_cell->muxdiv_offset));
- }
- return HWREG32(base + rk_cell->muxdiv_offset);
- }
- rt_inline void clk_mux_writel(struct rockchip_clk_cell *rk_cell, rt_uint32_t val)
- {
- void *base = rk_cell->provider->reg_base;
- if (rk_cell->mux_flags & CLK_MUX_BIG_ENDIAN)
- {
- HWREG32(base + rk_cell->muxdiv_offset) = rt_cpu_to_be32(val);
- }
- else
- {
- HWREG32(base + rk_cell->muxdiv_offset) = val;
- }
- }
- static int clk_mux_val_to_index(struct rt_clk_cell *cell,
- const rt_uint32_t *table, rt_uint32_t flags, rt_uint32_t val)
- {
- int num_parents = cell->parents_nr;
- if (table)
- {
- for (int i = 0; i < num_parents; ++i)
- {
- if (table[i] == val)
- {
- return i;
- }
- }
- return -RT_EINVAL;
- }
- if (val && (flags & CLK_MUX_INDEX_BIT))
- {
- val = __rt_ffs(val) - 1;
- }
- if (val && (flags & CLK_MUX_INDEX_ONE))
- {
- --val;
- }
- if (val >= num_parents)
- {
- return -RT_EINVAL;
- }
- return val;
- }
- static rt_uint32_t clk_mux_index_to_val(const rt_uint32_t *table, rt_uint32_t flags, rt_uint8_t index)
- {
- rt_uint32_t val = index;
- if (table)
- {
- val = table[index];
- }
- else
- {
- if (flags & CLK_MUX_INDEX_BIT)
- {
- val = 1 << index;
- }
- if (flags & CLK_MUX_INDEX_ONE)
- {
- val++;
- }
- }
- return val;
- }
- static rt_err_t rockchip_mux_clk_set_parent(struct rt_clk_cell *cell, rt_uint8_t index)
- {
- rt_uint32_t val, reg;
- struct rockchip_clk_cell *rk_cell = cell_to_rockchip_clk_cell(cell);
- val = clk_mux_index_to_val(rk_cell->mux_table, rk_cell->mux_flags, index);
- if (rk_cell->mux_flags & CLK_MUX_HIWORD_MASK)
- {
- reg = rk_cell->mux_mask << (rk_cell->mux_shift + 16);
- }
- else
- {
- reg = clk_mux_readl(rk_cell);
- reg &= ~(rk_cell->mux_mask << rk_cell->mux_shift);
- }
- val = val << rk_cell->mux_shift;
- reg |= val;
- clk_mux_writel(rk_cell, reg);
- return RT_EOK;
- }
- static rt_uint8_t rockchip_mux_clk_get_parent(struct rt_clk_cell *cell)
- {
- rt_uint32_t val;
- struct rockchip_clk_cell *rk_cell = cell_to_rockchip_clk_cell(cell);
- val = clk_mux_readl(rk_cell) >> rk_cell->mux_shift;
- val &= rk_cell->mux_mask;
- return clk_mux_val_to_index(cell, rk_cell->mux_table, rk_cell->mux_flags, val);
- }
- const struct rt_clk_ops rockchip_mux_clk_ops =
- {
- .set_parent = rockchip_mux_clk_set_parent,
- .get_parent = rockchip_mux_clk_get_parent,
- };
- const struct rt_clk_ops rockchip_mux_ro_clk_ops =
- {
- .get_parent = rockchip_mux_clk_get_parent,
- };
- void rockchip_mux_clk_cell_init(struct rockchip_clk_cell *rk_cell)
- {
- rk_cell->mux_mask = RT_BIT(rk_cell->mux_width) - 1;
- if (!rk_cell->cell.ops)
- {
- if (!((rk_cell->mux_flags & CLK_MUX_READ_ONLY)))
- {
- rk_cell->cell.ops = &rockchip_mux_clk_ops;
- }
- else
- {
- rk_cell->cell.ops = &rockchip_mux_ro_clk_ops;
- }
- }
- }
|