^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * TI Multiplexer Clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 2013 Texas Instruments, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Tero Kristo <t-kristo@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * it under the terms of the GNU General Public License version 2 as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This program is distributed "as is" WITHOUT ANY WARRANTY of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * kind, whether express or implied; without even the implied warranty
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/clk/ti.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "clock.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #undef pr_fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define pr_fmt(fmt) "%s: " fmt, __func__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static u8 ti_clk_mux_get_parent(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) struct clk_omap_mux *mux = to_clk_omap_mux(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int num_parents = clk_hw_get_num_parents(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * FIXME need a mux-specific flag to determine if val is bitwise or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * numeric. e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * from 0x1 to 0x7 (index starts at one)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * val = 0x4 really means "bit 2, index starts at bit 0"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) val = ti_clk_ll_ops->clk_readl(&mux->reg) >> mux->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) val &= mux->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) if (mux->table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) for (i = 0; i < num_parents; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (mux->table[i] == val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (val && (mux->flags & CLK_MUX_INDEX_BIT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) val = ffs(val) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (val && (mux->flags & CLK_MUX_INDEX_ONE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) val--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) if (val >= num_parents)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct clk_omap_mux *mux = to_clk_omap_mux(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (mux->table) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) index = mux->table[index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (mux->flags & CLK_MUX_INDEX_BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) index = (1 << ffs(index));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (mux->flags & CLK_MUX_INDEX_ONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) index++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (mux->flags & CLK_MUX_HIWORD_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) val = mux->mask << (mux->shift + 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) val = ti_clk_ll_ops->clk_readl(&mux->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) val &= ~(mux->mask << mux->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) val |= index << mux->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) ti_clk_ll_ops->clk_writel(val, &mux->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ti_clk_latch(&mux->reg, mux->latch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * clk_mux_save_context - Save the parent selcted in the mux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * @hw: pointer struct clk_hw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * Save the parent mux value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static int clk_mux_save_context(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) struct clk_omap_mux *mux = to_clk_omap_mux(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) mux->saved_parent = ti_clk_mux_get_parent(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * clk_mux_restore_context - Restore the parent in the mux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * @hw: pointer struct clk_hw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * Restore the saved parent mux value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static void clk_mux_restore_context(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct clk_omap_mux *mux = to_clk_omap_mux(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ti_clk_mux_set_parent(hw, mux->saved_parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) const struct clk_ops ti_clk_mux_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .get_parent = ti_clk_mux_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .set_parent = ti_clk_mux_set_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) .determine_rate = __clk_mux_determine_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .save_context = clk_mux_save_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .restore_context = clk_mux_restore_context,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static struct clk *_register_mux(struct device *dev, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) const char * const *parent_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) u8 num_parents, unsigned long flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct clk_omap_reg *reg, u8 shift, u32 mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) s8 latch, u8 clk_mux_flags, u32 *table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) struct clk_omap_mux *mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /* allocate the mux */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) mux = kzalloc(sizeof(*mux), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (!mux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) init.ops = &ti_clk_mux_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) init.flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) init.parent_names = parent_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) init.num_parents = num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* struct clk_mux assignments */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) memcpy(&mux->reg, reg, sizeof(*reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) mux->shift = shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) mux->mask = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) mux->latch = latch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) mux->flags = clk_mux_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) mux->table = table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) mux->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) clk = ti_clk_register(dev, &mux->hw, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (IS_ERR(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) kfree(mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * of_mux_clk_setup - Setup function for simple mux rate clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * @node: DT node for the clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * Sets up a basic clock multiplexer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static void of_mux_clk_setup(struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) struct clk_omap_reg reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) unsigned int num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) const char **parent_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) u8 clk_mux_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) u32 mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) u32 shift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) s32 latch = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) u32 flags = CLK_SET_RATE_NO_REPARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) num_parents = of_clk_get_parent_count(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (num_parents < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) pr_err("mux-clock %pOFn must have parents\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (!parent_names)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) of_clk_parent_fill(node, parent_names, num_parents);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (ti_clk_get_reg_addr(node, 0, ®))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) of_property_read_u32(node, "ti,bit-shift", &shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) of_property_read_u32(node, "ti,latch-bit", &latch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (of_property_read_bool(node, "ti,index-starts-at-one"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) clk_mux_flags |= CLK_MUX_INDEX_ONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (of_property_read_bool(node, "ti,set-rate-parent"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) flags |= CLK_SET_RATE_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* Generate bit-mask based on parent info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) mask = num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) if (!(clk_mux_flags & CLK_MUX_INDEX_ONE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) mask--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) mask = (1 << fls(mask)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) clk = _register_mux(NULL, node->name, parent_names, num_parents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) flags, ®, shift, mask, latch, clk_mux_flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!IS_ERR(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) of_clk_add_provider(node, of_clk_src_simple_get, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) kfree(parent_names);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) CLK_OF_DECLARE(mux_clk, "ti,mux-clock", of_mux_clk_setup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct clk_omap_mux *mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (!setup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) mux = kzalloc(sizeof(*mux), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (!mux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) mux->shift = setup->bit_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) mux->latch = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) mux->reg.index = setup->module;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) mux->reg.offset = setup->reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (setup->flags & CLKF_INDEX_STARTS_AT_ONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) mux->flags |= CLK_MUX_INDEX_ONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) num_parents = setup->num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) mux->mask = num_parents - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) mux->mask = (1 << fls(mux->mask)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return &mux->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct clk_omap_mux *mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) unsigned int num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) mux = kzalloc(sizeof(*mux), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (!mux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (ti_clk_get_reg_addr(node, 0, &mux->reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (!of_property_read_u32(node, "ti,bit-shift", &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) mux->shift = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (of_property_read_bool(node, "ti,index-starts-at-one"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) mux->flags |= CLK_MUX_INDEX_ONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) num_parents = of_clk_get_parent_count(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) if (num_parents < 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) pr_err("%pOFn must have parents\n", node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) goto cleanup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) mux->mask = num_parents - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) mux->mask = (1 << fls(mux->mask)) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (!ti_clk_add_component(node, &mux->hw, CLK_COMPONENT_TYPE_MUX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) cleanup:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) kfree(mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) CLK_OF_DECLARE(ti_composite_mux_clk_setup, "ti,composite-mux-clock",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) of_ti_composite_mux_clk_setup);