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 const struct clk_ops mtk_mux_clr_set_upd_ops = { 120 .get_parent = mtk_clk_mux_get_parent, 121 .set_parent = mtk_clk_mux_set_parent_setclr_lock, 122 }; 123 124 const struct clk_ops mtk_mux_gate_clr_set_upd_ops = { 125 .enable = mtk_clk_mux_enable_setclr, 126 .disable = mtk_clk_mux_disable_setclr, 127 .is_enabled = mtk_clk_mux_is_enabled, 128 .get_parent = mtk_clk_mux_get_parent, 129 .set_parent = mtk_clk_mux_set_parent_setclr_lock, 130 }; 131 132 static struct clk *mtk_clk_register_mux(const struct mtk_mux *mux, 133 struct regmap *regmap, 134 spinlock_t *lock) 135 { 136 struct mtk_clk_mux *clk_mux; 137 struct clk_init_data init = {}; 138 struct clk *clk; 139 140 clk_mux = kzalloc(sizeof(*clk_mux), GFP_KERNEL); 141 if (!clk_mux) 142 return ERR_PTR(-ENOMEM); 143 144 init.name = mux->name; 145 init.flags = mux->flags | CLK_SET_RATE_PARENT; 146 init.parent_names = mux->parent_names; 147 init.num_parents = mux->num_parents; 148 init.ops = mux->ops; 149 150 clk_mux->regmap = regmap; 151 clk_mux->data = mux; 152 clk_mux->lock = lock; 153 clk_mux->hw.init = &init; 154 155 clk = clk_register(NULL, &clk_mux->hw); 156 if (IS_ERR(clk)) { 157 kfree(clk_mux); 158 return clk; 159 } 160 161 return clk; 162 } 163 164 int mtk_clk_register_muxes(const struct mtk_mux *muxes, 165 int num, struct device_node *node, 166 spinlock_t *lock, 167 struct clk_onecell_data *clk_data) 168 { 169 struct regmap *regmap; 170 struct clk *clk; 171 int i; 172 173 regmap = device_node_to_regmap(node); 174 if (IS_ERR(regmap)) { 175 pr_err("Cannot find regmap for %pOF: %ld\n", node, 176 PTR_ERR(regmap)); 177 return PTR_ERR(regmap); 178 } 179 180 for (i = 0; i < num; i++) { 181 const struct mtk_mux *mux = &muxes[i]; 182 183 if (IS_ERR_OR_NULL(clk_data->clks[mux->id])) { 184 clk = mtk_clk_register_mux(mux, regmap, lock); 185 186 if (IS_ERR(clk)) { 187 pr_err("Failed to register clk %s: %ld\n", 188 mux->name, PTR_ERR(clk)); 189 continue; 190 } 191 192 clk_data->clks[mux->id] = clk; 193 } 194 } 195 196 return 0; 197 } 198