1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright (c) 2023 Linaro Ltd. 4 * Sam Protsenko <semen.protsenko@linaro.org> 5 * 6 * Common Clock Framework support for all Samsung platforms. 7 */ 8 9 #ifndef __EXYNOS_CLK_H 10 #define __EXYNOS_CLK_H 11 12 #include <errno.h> 13 #include <linux/clk-provider.h> 14 #include "clk-pll.h" 15 16 #define _SAMSUNG_CLK_OPS(_name, _cmu) \ 17 static int _name##_of_xlate(struct clk *clk, \ 18 struct ofnode_phandle_args *args) \ 19 { \ 20 if (args->args_count > 1) { \ 21 debug("Invalid args_count: %d\n", args->args_count); \ 22 return -EINVAL; \ 23 } \ 24 \ 25 if (args->args_count) \ 26 clk->id = SAMSUNG_TO_CLK_ID(_cmu, args->args[0]); \ 27 else \ 28 clk->id = 0; \ 29 \ 30 return 0; \ 31 } \ 32 \ 33 static const struct clk_ops _name##_clk_ops = { \ 34 .set_rate = ccf_clk_set_rate, \ 35 .get_rate = ccf_clk_get_rate, \ 36 .set_parent = ccf_clk_set_parent, \ 37 .enable = ccf_clk_enable, \ 38 .disable = ccf_clk_disable, \ 39 .of_xlate = _name##_of_xlate, \ 40 } 41 42 /** 43 * SAMSUNG_CLK_OPS - Define clock operations structure for specified CMU. 44 * @name: name of generated structure 45 * @cmu: CMU index 46 * 47 * Like ccf_clk_ops, but with custom .of_xlate callback. 48 */ 49 #define SAMSUNG_CLK_OPS(name, cmu) _SAMSUNG_CLK_OPS(name, cmu) 50 51 /** 52 * SAMSUNG_TO_CLK_ID - Calculate a global clock index. 53 * @_cmu: CMU index 54 * @_id: local clock index (unique across @_cmu) 55 * 56 * Return: A global clock index unique across all CMUs. 57 * Keeps a range of 256 available clocks for every CMU. 58 */ 59 #define SAMSUNG_TO_CLK_ID(_cmu, _id) (((_cmu) << 8) | ((_id) & 0xff)) 60 61 /** 62 * struct samsung_mux_clock - information about mux clock 63 * @id: platform specific id of the clock 64 * @name: name of this mux clock 65 * @parent_names: array of pointer to parent clock names 66 * @num_parents: number of parents listed in @parent_names 67 * @flags: optional flags for basic clock 68 * @offset: offset of the register for configuring the mux 69 * @shift: starting bit location of the mux control bit-field in @reg 70 * @width: width of the mux control bit-field in @reg 71 * @mux_flags: flags for mux-type clock 72 */ 73 struct samsung_mux_clock { 74 unsigned int id; 75 const char *name; 76 const char * const *parent_names; 77 u8 num_parents; 78 unsigned long flags; 79 unsigned long offset; 80 u8 shift; 81 u8 width; 82 u8 mux_flags; 83 }; 84 85 #define PNAME(x) static const char * const x[] 86 87 #define __MUX(_id, cname, pnames, o, s, w, f, mf) \ 88 { \ 89 .id = _id, \ 90 .name = cname, \ 91 .parent_names = pnames, \ 92 .num_parents = ARRAY_SIZE(pnames), \ 93 .flags = (f) | CLK_SET_RATE_NO_REPARENT, \ 94 .offset = o, \ 95 .shift = s, \ 96 .width = w, \ 97 .mux_flags = mf, \ 98 } 99 100 #define MUX(_id, cname, pnames, o, s, w) \ 101 __MUX(_id, cname, pnames, o, s, w, 0, 0) 102 103 #define MUX_F(_id, cname, pnames, o, s, w, f, mf) \ 104 __MUX(_id, cname, pnames, o, s, w, f, mf) 105 106 /** 107 * struct samsung_div_clock - information about div clock 108 * @id: platform specific id of the clock 109 * @name: name of this div clock 110 * @parent_name: name of the parent clock 111 * @flags: optional flags for basic clock 112 * @offset: offset of the register for configuring the div 113 * @shift: starting bit location of the div control bit-field in @reg 114 * @width: width of the bitfield 115 * @div_flags: flags for div-type clock 116 */ 117 struct samsung_div_clock { 118 unsigned int id; 119 const char *name; 120 const char *parent_name; 121 unsigned long flags; 122 unsigned long offset; 123 u8 shift; 124 u8 width; 125 u8 div_flags; 126 }; 127 128 #define __DIV(_id, cname, pname, o, s, w, f, df) \ 129 { \ 130 .id = _id, \ 131 .name = cname, \ 132 .parent_name = pname, \ 133 .flags = f, \ 134 .offset = o, \ 135 .shift = s, \ 136 .width = w, \ 137 .div_flags = df, \ 138 } 139 140 #define DIV(_id, cname, pname, o, s, w) \ 141 __DIV(_id, cname, pname, o, s, w, 0, 0) 142 143 #define DIV_F(_id, cname, pname, o, s, w, f, df) \ 144 __DIV(_id, cname, pname, o, s, w, f, df) 145 146 /** 147 * struct samsung_gate_clock - information about gate clock 148 * @id: platform specific id of the clock 149 * @name: name of this gate clock 150 * @parent_name: name of the parent clock 151 * @flags: optional flags for basic clock 152 * @offset: offset of the register for configuring the gate 153 * @bit_idx: bit index of the gate control bit-field in @reg 154 * @gate_flags: flags for gate-type clock 155 */ 156 struct samsung_gate_clock { 157 unsigned int id; 158 const char *name; 159 const char *parent_name; 160 unsigned long flags; 161 unsigned long offset; 162 u8 bit_idx; 163 u8 gate_flags; 164 }; 165 166 #define __GATE(_id, cname, pname, o, b, f, gf) \ 167 { \ 168 .id = _id, \ 169 .name = cname, \ 170 .parent_name = pname, \ 171 .flags = f, \ 172 .offset = o, \ 173 .bit_idx = b, \ 174 .gate_flags = gf, \ 175 } 176 177 #define GATE(_id, cname, pname, o, b, f, gf) \ 178 __GATE(_id, cname, pname, o, b, f, gf) 179 180 /** 181 * struct samsung_pll_clock - information about pll clock 182 * @id: platform specific id of the clock 183 * @name: name of this pll clock 184 * @parent_name: name of the parent clock 185 * @flags: optional flags for basic clock 186 * @con_offset: offset of the register for configuring the PLL 187 * @type: type of PLL to be registered 188 */ 189 struct samsung_pll_clock { 190 unsigned int id; 191 const char *name; 192 const char *parent_name; 193 unsigned long flags; 194 int con_offset; 195 enum samsung_pll_type type; 196 }; 197 198 #define PLL(_typ, _id, _name, _pname, _con) \ 199 { \ 200 .id = _id, \ 201 .name = _name, \ 202 .parent_name = _pname, \ 203 .flags = CLK_GET_RATE_NOCACHE, \ 204 .con_offset = _con, \ 205 .type = _typ, \ 206 } 207 208 enum samsung_clock_type { 209 S_CLK_MUX, 210 S_CLK_DIV, 211 S_CLK_GATE, 212 S_CLK_PLL, 213 }; 214 215 /** 216 * struct samsung_clock_group - contains a list of clocks of one type 217 * @type: type of clocks this structure contains 218 * @clk_list: list of clocks 219 * @nr_clk: count of clocks in @clk_list 220 */ 221 struct samsung_clk_group { 222 enum samsung_clock_type type; 223 const void *clk_list; 224 unsigned int nr_clk; 225 }; 226 227 int samsung_cmu_register_one(struct udevice *dev, unsigned int cmu_id, 228 const struct samsung_clk_group *clk_groups, 229 unsigned int nr_groups); 230 231 /** 232 * samsung_register_cmu - Register CMU clocks ensuring parent CMU is present 233 * @dev: CMU device 234 * @cmu_id: CMU index number 235 * @clk_groups: list of CMU clock groups 236 * @parent_drv: name of parent CMU driver 237 * 238 * Register provided CMU clocks, but make sure CMU_TOP driver is instantiated 239 * first. 240 * 241 * Return: 0 on success or negative value on error. 242 */ 243 #define samsung_register_cmu(dev, cmu_id, clk_groups, parent_drv) \ 244 ({ \ 245 struct udevice *__parent; \ 246 int __ret; \ 247 \ 248 __ret = uclass_get_device_by_driver(UCLASS_CLK, \ 249 DM_DRIVER_GET(parent_drv), &__parent); \ 250 if (__ret || !__parent) \ 251 __ret = -ENOENT; \ 252 else \ 253 __ret = samsung_cmu_register_one(dev, cmu_id, \ 254 clk_groups, ARRAY_SIZE(clk_groups)); \ 255 __ret; \ 256 }) 257 258 #endif /* __EXYNOS_CLK_H */ 259