0001
0002
0003
0004
0005
0006
0007
0008 #ifndef __CLK_CGU_H
0009 #define __CLK_CGU_H
0010
0011 #include <linux/io.h>
0012
0013 struct lgm_clk_mux {
0014 struct clk_hw hw;
0015 void __iomem *membase;
0016 unsigned int reg;
0017 u8 shift;
0018 u8 width;
0019 unsigned long flags;
0020 spinlock_t lock;
0021 };
0022
0023 struct lgm_clk_divider {
0024 struct clk_hw hw;
0025 void __iomem *membase;
0026 unsigned int reg;
0027 u8 shift;
0028 u8 width;
0029 u8 shift_gate;
0030 u8 width_gate;
0031 unsigned long flags;
0032 const struct clk_div_table *table;
0033 spinlock_t lock;
0034 };
0035
0036 struct lgm_clk_ddiv {
0037 struct clk_hw hw;
0038 void __iomem *membase;
0039 unsigned int reg;
0040 u8 shift0;
0041 u8 width0;
0042 u8 shift1;
0043 u8 width1;
0044 u8 shift2;
0045 u8 width2;
0046 u8 shift_gate;
0047 u8 width_gate;
0048 unsigned int mult;
0049 unsigned int div;
0050 unsigned long flags;
0051 spinlock_t lock;
0052 };
0053
0054 struct lgm_clk_gate {
0055 struct clk_hw hw;
0056 void __iomem *membase;
0057 unsigned int reg;
0058 u8 shift;
0059 unsigned long flags;
0060 spinlock_t lock;
0061 };
0062
0063 enum lgm_clk_type {
0064 CLK_TYPE_FIXED,
0065 CLK_TYPE_MUX,
0066 CLK_TYPE_DIVIDER,
0067 CLK_TYPE_FIXED_FACTOR,
0068 CLK_TYPE_GATE,
0069 CLK_TYPE_NONE,
0070 };
0071
0072
0073
0074
0075
0076
0077
0078
0079 struct lgm_clk_provider {
0080 void __iomem *membase;
0081 struct device_node *np;
0082 struct device *dev;
0083 struct clk_hw_onecell_data clk_data;
0084 spinlock_t lock;
0085 };
0086
0087 enum pll_type {
0088 TYPE_ROPLL,
0089 TYPE_LJPLL,
0090 TYPE_NONE,
0091 };
0092
0093 struct lgm_clk_pll {
0094 struct clk_hw hw;
0095 void __iomem *membase;
0096 unsigned int reg;
0097 unsigned long flags;
0098 enum pll_type type;
0099 spinlock_t lock;
0100 };
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 struct lgm_pll_clk_data {
0113 unsigned int id;
0114 const char *name;
0115 const struct clk_parent_data *parent_data;
0116 u8 num_parents;
0117 unsigned long flags;
0118 enum pll_type type;
0119 int reg;
0120 };
0121
0122 #define LGM_PLL(_id, _name, _pdata, _flags, \
0123 _reg, _type) \
0124 { \
0125 .id = _id, \
0126 .name = _name, \
0127 .parent_data = _pdata, \
0128 .num_parents = ARRAY_SIZE(_pdata), \
0129 .flags = _flags, \
0130 .reg = _reg, \
0131 .type = _type, \
0132 }
0133
0134 struct lgm_clk_ddiv_data {
0135 unsigned int id;
0136 const char *name;
0137 const struct clk_parent_data *parent_data;
0138 u8 flags;
0139 unsigned long div_flags;
0140 unsigned int reg;
0141 u8 shift0;
0142 u8 width0;
0143 u8 shift1;
0144 u8 width1;
0145 u8 shift_gate;
0146 u8 width_gate;
0147 u8 ex_shift;
0148 u8 ex_width;
0149 };
0150
0151 #define LGM_DDIV(_id, _name, _pname, _flags, _reg, \
0152 _shft0, _wdth0, _shft1, _wdth1, \
0153 _shft_gate, _wdth_gate, _xshft, _df) \
0154 { \
0155 .id = _id, \
0156 .name = _name, \
0157 .parent_data = &(const struct clk_parent_data){ \
0158 .fw_name = _pname, \
0159 .name = _pname, \
0160 }, \
0161 .flags = _flags, \
0162 .reg = _reg, \
0163 .shift0 = _shft0, \
0164 .width0 = _wdth0, \
0165 .shift1 = _shft1, \
0166 .width1 = _wdth1, \
0167 .shift_gate = _shft_gate, \
0168 .width_gate = _wdth_gate, \
0169 .ex_shift = _xshft, \
0170 .ex_width = 1, \
0171 .div_flags = _df, \
0172 }
0173
0174 struct lgm_clk_branch {
0175 unsigned int id;
0176 enum lgm_clk_type type;
0177 const char *name;
0178 const struct clk_parent_data *parent_data;
0179 u8 num_parents;
0180 unsigned long flags;
0181 unsigned int mux_off;
0182 u8 mux_shift;
0183 u8 mux_width;
0184 unsigned long mux_flags;
0185 unsigned int mux_val;
0186 unsigned int div_off;
0187 u8 div_shift;
0188 u8 div_width;
0189 u8 div_shift_gate;
0190 u8 div_width_gate;
0191 unsigned long div_flags;
0192 unsigned int div_val;
0193 const struct clk_div_table *div_table;
0194 unsigned int gate_off;
0195 u8 gate_shift;
0196 unsigned long gate_flags;
0197 unsigned int gate_val;
0198 unsigned int mult;
0199 unsigned int div;
0200 };
0201
0202
0203 #define CLOCK_FLAG_VAL_INIT BIT(16)
0204 #define MUX_CLK_SW BIT(17)
0205
0206 #define LGM_MUX(_id, _name, _pdata, _f, _reg, \
0207 _shift, _width, _cf, _v) \
0208 { \
0209 .id = _id, \
0210 .type = CLK_TYPE_MUX, \
0211 .name = _name, \
0212 .parent_data = _pdata, \
0213 .num_parents = ARRAY_SIZE(_pdata), \
0214 .flags = _f, \
0215 .mux_off = _reg, \
0216 .mux_shift = _shift, \
0217 .mux_width = _width, \
0218 .mux_flags = _cf, \
0219 .mux_val = _v, \
0220 }
0221
0222 #define LGM_DIV(_id, _name, _pname, _f, _reg, _shift, _width, \
0223 _shift_gate, _width_gate, _cf, _v, _dtable) \
0224 { \
0225 .id = _id, \
0226 .type = CLK_TYPE_DIVIDER, \
0227 .name = _name, \
0228 .parent_data = &(const struct clk_parent_data){ \
0229 .fw_name = _pname, \
0230 .name = _pname, \
0231 }, \
0232 .num_parents = 1, \
0233 .flags = _f, \
0234 .div_off = _reg, \
0235 .div_shift = _shift, \
0236 .div_width = _width, \
0237 .div_shift_gate = _shift_gate, \
0238 .div_width_gate = _width_gate, \
0239 .div_flags = _cf, \
0240 .div_val = _v, \
0241 .div_table = _dtable, \
0242 }
0243
0244 #define LGM_GATE(_id, _name, _pname, _f, _reg, \
0245 _shift, _cf, _v) \
0246 { \
0247 .id = _id, \
0248 .type = CLK_TYPE_GATE, \
0249 .name = _name, \
0250 .parent_data = &(const struct clk_parent_data){ \
0251 .fw_name = _pname, \
0252 .name = _pname, \
0253 }, \
0254 .num_parents = !_pname ? 0 : 1, \
0255 .flags = _f, \
0256 .gate_off = _reg, \
0257 .gate_shift = _shift, \
0258 .gate_flags = _cf, \
0259 .gate_val = _v, \
0260 }
0261
0262 #define LGM_FIXED(_id, _name, _pname, _f, _reg, \
0263 _shift, _width, _cf, _freq, _v) \
0264 { \
0265 .id = _id, \
0266 .type = CLK_TYPE_FIXED, \
0267 .name = _name, \
0268 .parent_data = &(const struct clk_parent_data){ \
0269 .fw_name = _pname, \
0270 .name = _pname, \
0271 }, \
0272 .num_parents = !_pname ? 0 : 1, \
0273 .flags = _f, \
0274 .div_off = _reg, \
0275 .div_shift = _shift, \
0276 .div_width = _width, \
0277 .div_flags = _cf, \
0278 .div_val = _v, \
0279 .mux_flags = _freq, \
0280 }
0281
0282 #define LGM_FIXED_FACTOR(_id, _name, _pname, _f, _reg, \
0283 _shift, _width, _cf, _v, _m, _d) \
0284 { \
0285 .id = _id, \
0286 .type = CLK_TYPE_FIXED_FACTOR, \
0287 .name = _name, \
0288 .parent_data = &(const struct clk_parent_data){ \
0289 .fw_name = _pname, \
0290 .name = _pname, \
0291 }, \
0292 .num_parents = 1, \
0293 .flags = _f, \
0294 .div_off = _reg, \
0295 .div_shift = _shift, \
0296 .div_width = _width, \
0297 .div_flags = _cf, \
0298 .div_val = _v, \
0299 .mult = _m, \
0300 .div = _d, \
0301 }
0302
0303 static inline void lgm_set_clk_val(void __iomem *membase, u32 reg,
0304 u8 shift, u8 width, u32 set_val)
0305 {
0306 u32 mask = (GENMASK(width - 1, 0) << shift);
0307 u32 regval;
0308
0309 regval = readl(membase + reg);
0310 regval = (regval & ~mask) | ((set_val << shift) & mask);
0311 writel(regval, membase + reg);
0312 }
0313
0314 static inline u32 lgm_get_clk_val(void __iomem *membase, u32 reg,
0315 u8 shift, u8 width)
0316 {
0317 u32 mask = (GENMASK(width - 1, 0) << shift);
0318 u32 val;
0319
0320 val = readl(membase + reg);
0321 val = (val & mask) >> shift;
0322
0323 return val;
0324 }
0325
0326 int lgm_clk_register_branches(struct lgm_clk_provider *ctx,
0327 const struct lgm_clk_branch *list,
0328 unsigned int nr_clk);
0329 int lgm_clk_register_plls(struct lgm_clk_provider *ctx,
0330 const struct lgm_pll_clk_data *list,
0331 unsigned int nr_clk);
0332 int lgm_clk_register_ddiv(struct lgm_clk_provider *ctx,
0333 const struct lgm_clk_ddiv_data *list,
0334 unsigned int nr_clk);
0335 #endif