1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2018 MediaTek Inc. 4 * Author: Owen Chen <owen.chen@mediatek.com> 5 */ 6 7 #include <linux/of.h> 8 #include <linux/of_address.h> 9 #include <linux/slab.h> 10 #include <linux/mfd/syscon.h> 11 12 #include "clk-mtk.h" 13 #include "clk-mux.h" 14 15 static inline struct mtk_clk_mux *to_mtk_clk_mux(struct clk_hw *hw) 16 { 17 return container_of(hw, struct mtk_clk_mux, hw); 18 } 19 20 static int mtk_clk_mux_enable_setclr(struct clk_hw *hw) 21 { 22 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); 23 unsigned long flags = 0; 24 25 if (mux->lock) 26 spin_lock_irqsave(mux->lock, flags); 27 else 28 __acquire(mux->lock); 29 30 regmap_write(mux->regmap, mux->data->clr_ofs, 31 BIT(mux->data->gate_shift)); 32 33 /* 34 * If the parent has been changed when the clock was disabled, it will 35 * not be effective yet. Set the update bit to ensure the mux gets 36 * updated. 37 */ 38 if (mux->reparent && mux->data->upd_shift >= 0) { 39 regmap_write(mux->regmap, mux->data->upd_ofs, 40 BIT(mux->data->upd_shift)); 41 mux->reparent = false; 42 } 43 44 if (mux->lock) 45 spin_unlock_irqrestore(mux->lock, flags); 46 else 47 __release(mux->lock); 48 49 return 0; 50 } 51 52 static void mtk_clk_mux_disable_setclr(struct clk_hw *hw) 53 { 54 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); 55 56 regmap_write(mux->regmap, mux->data->set_ofs, 57 BIT(mux->data->gate_shift)); 58 } 59 60 static int mtk_clk_mux_is_enabled(struct clk_hw *hw) 61 { 62 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); 63 u32 val; 64 65 regmap_read(mux->regmap, mux->data->mux_ofs, &val); 66 67 return (val & BIT(mux->data->gate_shift)) == 0; 68 } 69 70 static u8 mtk_clk_mux_get_parent(struct clk_hw *hw) 71 { 72 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); 73 u32 mask = GENMASK(mux->data->mux_width - 1, 0); 74 u32 val; 75 76 regmap_read(mux->regmap, mux->data->mux_ofs, &val); 77 val = (val >> mux->data->mux_shift) & mask; 78 79 return val; 80 } 81 82 static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index) 83 { 84 struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); 85 u32 mask = GENMASK(mux->data->mux_width - 1, 0); 86 u32 val, orig; 87 unsigned long flags = 0; 88 89 if (mux->lock) 90 spin_lock_irqsave(mux->lock, flags); 91 else 92 __acquire(mux->lock); 93 94 regmap_read(mux->regmap, mux->data->mux_ofs, &orig); 95 val = (orig & ~(mask << mux->data->mux_shift)) 96 | (index << mux->data->mux_shift); 97 98 if (val != orig) { 99 regmap_write(mux->regmap, mux->data->clr_ofs, 100 mask << mux->data->mux_shift); 101 regmap_write(mux->regmap, mux->data->set_ofs, 102 index << mux->data->mux_shift); 103 104 if (mux->data->upd_shift >= 0) { 105 regmap_write(mux->regmap, mux->data->upd_ofs, 106 BIT(mux->data->upd_shift)); 107 mux->reparent = true; 108 } 109 } 110 111 if (mux->lock) 112 spin_unlock_irqrestore(mux->lock, flags); 113 else 114 __release(mux->lock); 115 116 return 0; 117 } 118 119 static const struct clk_ops mtk_mux_ops = { 120 .enable = mtk_clk_mux_enable_setclr, 121 .disable = mtk_clk_mux_disable_setclr, 122 .is_enabled = mtk_clk_mux_is_enabled, 123 .get_parent = mtk_clk_mux_get_parent, 124 .set_parent = mtk_clk_mux_set_parent_setclr_lock, 125 }; 126 127 static struct clk *mtk_clk_register_mux(const struct mtk_mux *mux, 128 struct regmap *regmap, 129 spinlock_t *lock) 130 { 131 struct mtk_clk_mux *clk_mux; 132 struct clk_init_data init = {}; 133 struct clk *clk; 134 135 clk_mux = kzalloc(sizeof(*clk_mux), GFP_KERNEL); 136 if (!clk_mux) 137 return ERR_PTR(-ENOMEM); 138 139 init.name = mux->name; 140 init.flags = mux->flags | CLK_SET_RATE_PARENT; 141 init.parent_names = mux->parent_names; 142 init.num_parents = mux->num_parents; 143 init.ops = &mtk_mux_ops; 144 145 clk_mux->regmap = regmap; 146 clk_mux->data = mux; 147 clk_mux->lock = lock; 148 clk_mux->hw.init = &init; 149 150 clk = clk_register(NULL, &clk_mux->hw); 151 if (IS_ERR(clk)) { 152 kfree(clk_mux); 153 return clk; 154 } 155 156 return clk; 157 } 158 159 int mtk_clk_register_muxes(const struct mtk_mux *muxes, 160 int num, struct device_node *node, 161 spinlock_t *lock, 162 struct clk_onecell_data *clk_data) 163 { 164 struct regmap *regmap; 165 struct clk *clk; 166 int i; 167 168 regmap = syscon_node_to_regmap(node); 169 if (IS_ERR(regmap)) { 170 pr_err("Cannot find regmap for %pOF: %ld\n", node, 171 PTR_ERR(regmap)); 172 return PTR_ERR(regmap); 173 } 174 175 for (i = 0; i < num; i++) { 176 const struct mtk_mux *mux = &muxes[i]; 177 178 if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) { 179 clk = mtk_clk_register_mux(mux, regmap, lock); 180 181 if (IS_ERR(clk)) { 182 pr_err("Failed to register clk %s: %ld\n", 183 mux->name, PTR_ERR(clk)); 184 continue; 185 } 186 187 clk_data->clks[mux->id] = clk; 188 } 189 } 190 191 return 0; 192 } 193