1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright (c) 2014 MediaTek Inc. 4 * Author: James Liao <jamesjj.liao@mediatek.com> 5 */ 6 7 #ifndef __DRV_CLK_MTK_H 8 #define __DRV_CLK_MTK_H 9 10 #include <linux/clk-provider.h> 11 #include <linux/io.h> 12 #include <linux/kernel.h> 13 #include <linux/spinlock.h> 14 #include <linux/types.h> 15 16 #include "reset.h" 17 18 #define MAX_MUX_GATE_BIT 31 19 #define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1) 20 21 #define MHZ (1000 * 1000) 22 23 #define MTK_WAIT_HWV_DONE_US 30 24 25 struct platform_device; 26 27 /* 28 * We need the clock IDs to start from zero but to maintain devicetree 29 * backwards compatibility we can't change bindings to start from zero. 30 * Only a few platforms are affected, so we solve issues given by the 31 * commonized MTK clocks probe function(s) by adding a dummy clock at 32 * the beginning where needed. 33 */ 34 #define CLK_DUMMY 0 35 36 extern const struct clk_ops mtk_clk_dummy_ops; 37 extern const struct mtk_gate_regs cg_regs_dummy; 38 39 #define GATE_DUMMY(_id, _name) { \ 40 .id = _id, \ 41 .name = _name, \ 42 .regs = &cg_regs_dummy, \ 43 .ops = &mtk_clk_dummy_ops, \ 44 } 45 46 struct mtk_fixed_clk { 47 int id; 48 const char *name; 49 const char *parent; 50 unsigned long rate; 51 }; 52 53 #define FIXED_CLK(_id, _name, _parent, _rate) { \ 54 .id = _id, \ 55 .name = _name, \ 56 .parent = _parent, \ 57 .rate = _rate, \ 58 } 59 60 int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num, 61 struct clk_hw_onecell_data *clk_data); 62 void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num, 63 struct clk_hw_onecell_data *clk_data); 64 65 struct mtk_fixed_factor { 66 int id; 67 const char *name; 68 const char *parent_name; 69 int mult; 70 int div; 71 unsigned long flags; 72 }; 73 74 #define FACTOR_FLAGS(_id, _name, _parent, _mult, _div, _fl) { \ 75 .id = _id, \ 76 .name = _name, \ 77 .parent_name = _parent, \ 78 .mult = _mult, \ 79 .div = _div, \ 80 .flags = _fl, \ 81 } 82 83 #define FACTOR(_id, _name, _parent, _mult, _div) \ 84 FACTOR_FLAGS(_id, _name, _parent, _mult, _div, CLK_SET_RATE_PARENT) 85 86 int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, 87 struct clk_hw_onecell_data *clk_data); 88 void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num, 89 struct clk_hw_onecell_data *clk_data); 90 91 struct mtk_composite { 92 int id; 93 const char *name; 94 const char * const *parent_names; 95 const char *parent; 96 unsigned flags; 97 98 uint32_t mux_reg; 99 uint32_t divider_reg; 100 uint32_t gate_reg; 101 102 signed char mux_shift; 103 signed char mux_width; 104 signed char gate_shift; 105 106 signed char divider_shift; 107 signed char divider_width; 108 109 u8 mux_flags; 110 111 signed char num_parents; 112 }; 113 114 #define MUX_GATE_FLAGS_2(_id, _name, _parents, _reg, _shift, \ 115 _width, _gate, _flags, _muxflags) { \ 116 .id = _id, \ 117 .name = _name, \ 118 .mux_reg = _reg, \ 119 .mux_shift = _shift, \ 120 .mux_width = _width, \ 121 .gate_reg = _reg, \ 122 .gate_shift = _gate, \ 123 .divider_shift = -1, \ 124 .parent_names = _parents, \ 125 .num_parents = ARRAY_SIZE(_parents), \ 126 .flags = _flags, \ 127 .mux_flags = _muxflags, \ 128 } 129 130 /* 131 * In case the rate change propagation to parent clocks is undesirable, 132 * this macro allows to specify the clock flags manually. 133 */ 134 #define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \ 135 _gate, _flags) \ 136 MUX_GATE_FLAGS_2(_id, _name, _parents, _reg, \ 137 _shift, _width, _gate, _flags, 0) 138 139 /* 140 * Unless necessary, all MUX_GATE clocks propagate rate changes to their 141 * parent clock by default. 142 */ 143 #define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) \ 144 MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \ 145 _gate, CLK_SET_RATE_PARENT) 146 147 #define MUX(_id, _name, _parents, _reg, _shift, _width) \ 148 MUX_FLAGS(_id, _name, _parents, _reg, \ 149 _shift, _width, CLK_SET_RATE_PARENT) 150 151 #define MUX_FLAGS(_id, _name, _parents, _reg, _shift, _width, _flags) { \ 152 .id = _id, \ 153 .name = _name, \ 154 .mux_reg = _reg, \ 155 .mux_shift = _shift, \ 156 .mux_width = _width, \ 157 .gate_shift = -1, \ 158 .divider_shift = -1, \ 159 .parent_names = _parents, \ 160 .num_parents = ARRAY_SIZE(_parents), \ 161 .flags = _flags, \ 162 } 163 164 #define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \ 165 _div_width, _div_shift) { \ 166 .id = _id, \ 167 .parent = _parent, \ 168 .name = _name, \ 169 .divider_reg = _div_reg, \ 170 .divider_shift = _div_shift, \ 171 .divider_width = _div_width, \ 172 .gate_reg = _gate_reg, \ 173 .gate_shift = _gate_shift, \ 174 .mux_shift = -1, \ 175 .flags = 0, \ 176 } 177 178 #define MUX_DIV_GATE(_id, _name, _parents, \ 179 _mux_reg, _mux_shift, _mux_width, \ 180 _div_reg, _div_shift, _div_width, \ 181 _gate_reg, _gate_shift) { \ 182 .id = _id, \ 183 .name = _name, \ 184 .parent_names = _parents, \ 185 .num_parents = ARRAY_SIZE(_parents), \ 186 .mux_reg = _mux_reg, \ 187 .mux_shift = _mux_shift, \ 188 .mux_width = _mux_width, \ 189 .divider_reg = _div_reg, \ 190 .divider_shift = _div_shift, \ 191 .divider_width = _div_width, \ 192 .gate_reg = _gate_reg, \ 193 .gate_shift = _gate_shift, \ 194 .flags = CLK_SET_RATE_PARENT, \ 195 } 196 197 int mtk_clk_register_composites(struct device *dev, 198 const struct mtk_composite *mcs, int num, 199 void __iomem *base, spinlock_t *lock, 200 struct clk_hw_onecell_data *clk_data); 201 void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num, 202 struct clk_hw_onecell_data *clk_data); 203 204 struct mtk_clk_divider { 205 int id; 206 const char *name; 207 const char *parent_name; 208 unsigned long flags; 209 210 u32 div_reg; 211 unsigned char div_shift; 212 unsigned char div_width; 213 unsigned char clk_divider_flags; 214 const struct clk_div_table *clk_div_table; 215 }; 216 217 #define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \ 218 .id = _id, \ 219 .name = _name, \ 220 .parent_name = _parent, \ 221 .div_reg = _reg, \ 222 .div_shift = _shift, \ 223 .div_width = _width, \ 224 } 225 226 int mtk_clk_register_dividers(struct device *dev, 227 const struct mtk_clk_divider *mcds, int num, 228 void __iomem *base, spinlock_t *lock, 229 struct clk_hw_onecell_data *clk_data); 230 void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num, 231 struct clk_hw_onecell_data *clk_data); 232 233 struct clk_hw_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); 234 struct clk_hw_onecell_data *mtk_devm_alloc_clk_data(struct device *dev, 235 unsigned int clk_num); 236 void mtk_free_clk_data(struct clk_hw_onecell_data *clk_data); 237 238 struct clk_hw *mtk_clk_register_ref2usb_tx(const char *name, 239 const char *parent_name, void __iomem *reg); 240 void mtk_clk_unregister_ref2usb_tx(struct clk_hw *hw); 241 242 struct mtk_clk_desc { 243 const struct mtk_gate *clks; 244 size_t num_clks; 245 const struct mtk_composite *composite_clks; 246 size_t num_composite_clks; 247 const struct mtk_clk_divider *divider_clks; 248 size_t num_divider_clks; 249 const struct mtk_fixed_clk *fixed_clks; 250 size_t num_fixed_clks; 251 const struct mtk_fixed_factor *factor_clks; 252 size_t num_factor_clks; 253 const struct mtk_mux *mux_clks; 254 size_t num_mux_clks; 255 const struct mtk_clk_rst_desc *rst_desc; 256 spinlock_t *clk_lock; 257 bool shared_io; 258 259 int (*clk_notifier_func)(struct device *dev, struct clk *clk); 260 unsigned int mfg_clk_idx; 261 262 bool need_runtime_pm; 263 }; 264 265 int mtk_clk_pdev_probe(struct platform_device *pdev); 266 void mtk_clk_pdev_remove(struct platform_device *pdev); 267 int mtk_clk_simple_probe(struct platform_device *pdev); 268 void mtk_clk_simple_remove(struct platform_device *pdev); 269 struct regmap *mtk_clk_get_hwv_regmap(struct device_node *node); 270 271 #endif /* __DRV_CLK_MTK_H */ 272