^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2015 Linaro Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "clk-mtk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include "clk-cpumux.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) static inline struct mtk_clk_cpumux *to_mtk_clk_cpumux(struct clk_hw *_hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) return container_of(_hw, struct mtk_clk_cpumux, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static u8 clk_cpumux_get_parent(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) unsigned int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) regmap_read(mux->regmap, mux->reg, &val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) val >>= mux->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) val &= mux->mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static int clk_cpumux_set_parent(struct clk_hw *hw, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) u32 mask, val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) val = index << mux->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) mask = mux->mask << mux->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return regmap_update_bits(mux->regmap, mux->reg, mask, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static const struct clk_ops clk_cpumux_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) .get_parent = clk_cpumux_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) .set_parent = clk_cpumux_set_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static struct clk *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) mtk_clk_register_cpumux(const struct mtk_composite *mux,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct regmap *regmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct mtk_clk_cpumux *cpumux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) cpumux = kzalloc(sizeof(*cpumux), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (!cpumux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) init.name = mux->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) init.ops = &clk_cpumux_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) init.parent_names = mux->parent_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) init.num_parents = mux->num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) init.flags = mux->flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) cpumux->reg = mux->mux_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) cpumux->shift = mux->mux_shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) cpumux->mask = BIT(mux->mux_width) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) cpumux->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) cpumux->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) clk = clk_register(NULL, &cpumux->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (IS_ERR(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) kfree(cpumux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int mtk_clk_register_cpumuxes(struct device_node *node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) const struct mtk_composite *clks, int num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct clk_onecell_data *clk_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) regmap = syscon_node_to_regmap(node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (IS_ERR(regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) pr_err("Cannot find regmap for %pOF: %ld\n", node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) PTR_ERR(regmap));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return PTR_ERR(regmap);
^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) for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) const struct mtk_composite *mux = &clks[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) clk = mtk_clk_register_cpumux(mux, regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) pr_err("Failed to register clk %s: %ld\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) mux->name, PTR_ERR(clk));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) clk_data->clks[mux->id] = clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }