1d058fd9eSRahul Tanwar /* SPDX-License-Identifier: GPL-2.0 */ 2d058fd9eSRahul Tanwar /* 3d058fd9eSRahul Tanwar * Copyright(c) 2020 Intel Corporation. 4d058fd9eSRahul Tanwar * Zhu YiXin <yixin.zhu@intel.com> 5d058fd9eSRahul Tanwar * Rahul Tanwar <rahul.tanwar@intel.com> 6d058fd9eSRahul Tanwar */ 7d058fd9eSRahul Tanwar 8d058fd9eSRahul Tanwar #ifndef __CLK_CGU_H 9d058fd9eSRahul Tanwar #define __CLK_CGU_H 10d058fd9eSRahul Tanwar 11d058fd9eSRahul Tanwar #include <linux/io.h> 12d058fd9eSRahul Tanwar 13d058fd9eSRahul Tanwar struct lgm_clk_mux { 14d058fd9eSRahul Tanwar struct clk_hw hw; 15d058fd9eSRahul Tanwar void __iomem *membase; 16d058fd9eSRahul Tanwar unsigned int reg; 17d058fd9eSRahul Tanwar u8 shift; 18d058fd9eSRahul Tanwar u8 width; 19d058fd9eSRahul Tanwar unsigned long flags; 20d058fd9eSRahul Tanwar spinlock_t lock; 21d058fd9eSRahul Tanwar }; 22d058fd9eSRahul Tanwar 23d058fd9eSRahul Tanwar struct lgm_clk_divider { 24d058fd9eSRahul Tanwar struct clk_hw hw; 25d058fd9eSRahul Tanwar void __iomem *membase; 26d058fd9eSRahul Tanwar unsigned int reg; 27d058fd9eSRahul Tanwar u8 shift; 28d058fd9eSRahul Tanwar u8 width; 29d058fd9eSRahul Tanwar u8 shift_gate; 30d058fd9eSRahul Tanwar u8 width_gate; 31d058fd9eSRahul Tanwar unsigned long flags; 32d058fd9eSRahul Tanwar const struct clk_div_table *table; 33d058fd9eSRahul Tanwar spinlock_t lock; 34d058fd9eSRahul Tanwar }; 35d058fd9eSRahul Tanwar 36d058fd9eSRahul Tanwar struct lgm_clk_ddiv { 37d058fd9eSRahul Tanwar struct clk_hw hw; 38d058fd9eSRahul Tanwar void __iomem *membase; 39d058fd9eSRahul Tanwar unsigned int reg; 40d058fd9eSRahul Tanwar u8 shift0; 41d058fd9eSRahul Tanwar u8 width0; 42d058fd9eSRahul Tanwar u8 shift1; 43d058fd9eSRahul Tanwar u8 width1; 44d058fd9eSRahul Tanwar u8 shift2; 45d058fd9eSRahul Tanwar u8 width2; 46d058fd9eSRahul Tanwar u8 shift_gate; 47d058fd9eSRahul Tanwar u8 width_gate; 48d058fd9eSRahul Tanwar unsigned int mult; 49d058fd9eSRahul Tanwar unsigned int div; 50d058fd9eSRahul Tanwar unsigned long flags; 51d058fd9eSRahul Tanwar spinlock_t lock; 52d058fd9eSRahul Tanwar }; 53d058fd9eSRahul Tanwar 54d058fd9eSRahul Tanwar struct lgm_clk_gate { 55d058fd9eSRahul Tanwar struct clk_hw hw; 56d058fd9eSRahul Tanwar void __iomem *membase; 57d058fd9eSRahul Tanwar unsigned int reg; 58d058fd9eSRahul Tanwar u8 shift; 59d058fd9eSRahul Tanwar unsigned long flags; 60d058fd9eSRahul Tanwar spinlock_t lock; 61d058fd9eSRahul Tanwar }; 62d058fd9eSRahul Tanwar 63d058fd9eSRahul Tanwar enum lgm_clk_type { 64d058fd9eSRahul Tanwar CLK_TYPE_FIXED, 65d058fd9eSRahul Tanwar CLK_TYPE_MUX, 66d058fd9eSRahul Tanwar CLK_TYPE_DIVIDER, 67d058fd9eSRahul Tanwar CLK_TYPE_FIXED_FACTOR, 68d058fd9eSRahul Tanwar CLK_TYPE_GATE, 69d058fd9eSRahul Tanwar CLK_TYPE_NONE, 70d058fd9eSRahul Tanwar }; 71d058fd9eSRahul Tanwar 72d058fd9eSRahul Tanwar /** 73d058fd9eSRahul Tanwar * struct lgm_clk_provider 74d058fd9eSRahul Tanwar * @membase: IO mem base address for CGU. 75d058fd9eSRahul Tanwar * @np: device node 76d058fd9eSRahul Tanwar * @dev: device 77d058fd9eSRahul Tanwar * @clk_data: array of hw clocks and clk number. 78d058fd9eSRahul Tanwar */ 79d058fd9eSRahul Tanwar struct lgm_clk_provider { 80d058fd9eSRahul Tanwar void __iomem *membase; 81d058fd9eSRahul Tanwar struct device_node *np; 82d058fd9eSRahul Tanwar struct device *dev; 83d058fd9eSRahul Tanwar struct clk_hw_onecell_data clk_data; 84d058fd9eSRahul Tanwar spinlock_t lock; 85d058fd9eSRahul Tanwar }; 86d058fd9eSRahul Tanwar 87d058fd9eSRahul Tanwar enum pll_type { 88d058fd9eSRahul Tanwar TYPE_ROPLL, 89d058fd9eSRahul Tanwar TYPE_LJPLL, 90d058fd9eSRahul Tanwar TYPE_NONE, 91d058fd9eSRahul Tanwar }; 92d058fd9eSRahul Tanwar 93d058fd9eSRahul Tanwar struct lgm_clk_pll { 94d058fd9eSRahul Tanwar struct clk_hw hw; 95d058fd9eSRahul Tanwar void __iomem *membase; 96d058fd9eSRahul Tanwar unsigned int reg; 97d058fd9eSRahul Tanwar unsigned long flags; 98d058fd9eSRahul Tanwar enum pll_type type; 99d058fd9eSRahul Tanwar spinlock_t lock; 100d058fd9eSRahul Tanwar }; 101d058fd9eSRahul Tanwar 102d058fd9eSRahul Tanwar /** 103d058fd9eSRahul Tanwar * struct lgm_pll_clk_data 104d058fd9eSRahul Tanwar * @id: platform specific id of the clock. 105d058fd9eSRahul Tanwar * @name: name of this pll clock. 106d058fd9eSRahul Tanwar * @parent_data: parent clock data. 107d058fd9eSRahul Tanwar * @num_parents: number of parents. 108d058fd9eSRahul Tanwar * @flags: optional flags for basic clock. 109d058fd9eSRahul Tanwar * @type: platform type of pll. 110d058fd9eSRahul Tanwar * @reg: offset of the register. 111d058fd9eSRahul Tanwar */ 112d058fd9eSRahul Tanwar struct lgm_pll_clk_data { 113d058fd9eSRahul Tanwar unsigned int id; 114d058fd9eSRahul Tanwar const char *name; 115d058fd9eSRahul Tanwar const struct clk_parent_data *parent_data; 116d058fd9eSRahul Tanwar u8 num_parents; 117d058fd9eSRahul Tanwar unsigned long flags; 118d058fd9eSRahul Tanwar enum pll_type type; 119d058fd9eSRahul Tanwar int reg; 120d058fd9eSRahul Tanwar }; 121d058fd9eSRahul Tanwar 122d058fd9eSRahul Tanwar #define LGM_PLL(_id, _name, _pdata, _flags, \ 123d058fd9eSRahul Tanwar _reg, _type) \ 124d058fd9eSRahul Tanwar { \ 125d058fd9eSRahul Tanwar .id = _id, \ 126d058fd9eSRahul Tanwar .name = _name, \ 127d058fd9eSRahul Tanwar .parent_data = _pdata, \ 128d058fd9eSRahul Tanwar .num_parents = ARRAY_SIZE(_pdata), \ 129d058fd9eSRahul Tanwar .flags = _flags, \ 130d058fd9eSRahul Tanwar .reg = _reg, \ 131d058fd9eSRahul Tanwar .type = _type, \ 132d058fd9eSRahul Tanwar } 133d058fd9eSRahul Tanwar 134d058fd9eSRahul Tanwar struct lgm_clk_ddiv_data { 135d058fd9eSRahul Tanwar unsigned int id; 136d058fd9eSRahul Tanwar const char *name; 137d058fd9eSRahul Tanwar const struct clk_parent_data *parent_data; 138d058fd9eSRahul Tanwar u8 flags; 139d058fd9eSRahul Tanwar unsigned long div_flags; 140d058fd9eSRahul Tanwar unsigned int reg; 141d058fd9eSRahul Tanwar u8 shift0; 142d058fd9eSRahul Tanwar u8 width0; 143d058fd9eSRahul Tanwar u8 shift1; 144d058fd9eSRahul Tanwar u8 width1; 145d058fd9eSRahul Tanwar u8 shift_gate; 146d058fd9eSRahul Tanwar u8 width_gate; 147d058fd9eSRahul Tanwar u8 ex_shift; 148d058fd9eSRahul Tanwar u8 ex_width; 149d058fd9eSRahul Tanwar }; 150d058fd9eSRahul Tanwar 151d058fd9eSRahul Tanwar #define LGM_DDIV(_id, _name, _pname, _flags, _reg, \ 152d058fd9eSRahul Tanwar _shft0, _wdth0, _shft1, _wdth1, \ 153d058fd9eSRahul Tanwar _shft_gate, _wdth_gate, _xshft, _df) \ 154d058fd9eSRahul Tanwar { \ 155d058fd9eSRahul Tanwar .id = _id, \ 156d058fd9eSRahul Tanwar .name = _name, \ 157d058fd9eSRahul Tanwar .parent_data = &(const struct clk_parent_data){ \ 158d058fd9eSRahul Tanwar .fw_name = _pname, \ 159d058fd9eSRahul Tanwar .name = _pname, \ 160d058fd9eSRahul Tanwar }, \ 161d058fd9eSRahul Tanwar .flags = _flags, \ 162d058fd9eSRahul Tanwar .reg = _reg, \ 163d058fd9eSRahul Tanwar .shift0 = _shft0, \ 164d058fd9eSRahul Tanwar .width0 = _wdth0, \ 165d058fd9eSRahul Tanwar .shift1 = _shft1, \ 166d058fd9eSRahul Tanwar .width1 = _wdth1, \ 167d058fd9eSRahul Tanwar .shift_gate = _shft_gate, \ 168d058fd9eSRahul Tanwar .width_gate = _wdth_gate, \ 169d058fd9eSRahul Tanwar .ex_shift = _xshft, \ 170d058fd9eSRahul Tanwar .ex_width = 1, \ 171d058fd9eSRahul Tanwar .div_flags = _df, \ 172d058fd9eSRahul Tanwar } 173d058fd9eSRahul Tanwar 174d058fd9eSRahul Tanwar struct lgm_clk_branch { 175d058fd9eSRahul Tanwar unsigned int id; 176d058fd9eSRahul Tanwar enum lgm_clk_type type; 177d058fd9eSRahul Tanwar const char *name; 178d058fd9eSRahul Tanwar const struct clk_parent_data *parent_data; 179d058fd9eSRahul Tanwar u8 num_parents; 180d058fd9eSRahul Tanwar unsigned long flags; 181d058fd9eSRahul Tanwar unsigned int mux_off; 182d058fd9eSRahul Tanwar u8 mux_shift; 183d058fd9eSRahul Tanwar u8 mux_width; 184d058fd9eSRahul Tanwar unsigned long mux_flags; 185d058fd9eSRahul Tanwar unsigned int mux_val; 186d058fd9eSRahul Tanwar unsigned int div_off; 187d058fd9eSRahul Tanwar u8 div_shift; 188d058fd9eSRahul Tanwar u8 div_width; 189d058fd9eSRahul Tanwar u8 div_shift_gate; 190d058fd9eSRahul Tanwar u8 div_width_gate; 191d058fd9eSRahul Tanwar unsigned long div_flags; 192d058fd9eSRahul Tanwar unsigned int div_val; 193d058fd9eSRahul Tanwar const struct clk_div_table *div_table; 194d058fd9eSRahul Tanwar unsigned int gate_off; 195d058fd9eSRahul Tanwar u8 gate_shift; 196d058fd9eSRahul Tanwar unsigned long gate_flags; 197d058fd9eSRahul Tanwar unsigned int gate_val; 198d058fd9eSRahul Tanwar unsigned int mult; 199d058fd9eSRahul Tanwar unsigned int div; 200d058fd9eSRahul Tanwar }; 201d058fd9eSRahul Tanwar 202d058fd9eSRahul Tanwar /* clock flags definition */ 203d058fd9eSRahul Tanwar #define CLOCK_FLAG_VAL_INIT BIT(16) 204d058fd9eSRahul Tanwar #define MUX_CLK_SW BIT(17) 205d058fd9eSRahul Tanwar 206d058fd9eSRahul Tanwar #define LGM_MUX(_id, _name, _pdata, _f, _reg, \ 207d058fd9eSRahul Tanwar _shift, _width, _cf, _v) \ 208d058fd9eSRahul Tanwar { \ 209d058fd9eSRahul Tanwar .id = _id, \ 210d058fd9eSRahul Tanwar .type = CLK_TYPE_MUX, \ 211d058fd9eSRahul Tanwar .name = _name, \ 212d058fd9eSRahul Tanwar .parent_data = _pdata, \ 213d058fd9eSRahul Tanwar .num_parents = ARRAY_SIZE(_pdata), \ 214d058fd9eSRahul Tanwar .flags = _f, \ 215d058fd9eSRahul Tanwar .mux_off = _reg, \ 216d058fd9eSRahul Tanwar .mux_shift = _shift, \ 217d058fd9eSRahul Tanwar .mux_width = _width, \ 218d058fd9eSRahul Tanwar .mux_flags = _cf, \ 219d058fd9eSRahul Tanwar .mux_val = _v, \ 220d058fd9eSRahul Tanwar } 221d058fd9eSRahul Tanwar 222d058fd9eSRahul Tanwar #define LGM_DIV(_id, _name, _pname, _f, _reg, _shift, _width, \ 223d058fd9eSRahul Tanwar _shift_gate, _width_gate, _cf, _v, _dtable) \ 224d058fd9eSRahul Tanwar { \ 225d058fd9eSRahul Tanwar .id = _id, \ 226d058fd9eSRahul Tanwar .type = CLK_TYPE_DIVIDER, \ 227d058fd9eSRahul Tanwar .name = _name, \ 228d058fd9eSRahul Tanwar .parent_data = &(const struct clk_parent_data){ \ 229d058fd9eSRahul Tanwar .fw_name = _pname, \ 230d058fd9eSRahul Tanwar .name = _pname, \ 231d058fd9eSRahul Tanwar }, \ 232d058fd9eSRahul Tanwar .num_parents = 1, \ 233d058fd9eSRahul Tanwar .flags = _f, \ 234d058fd9eSRahul Tanwar .div_off = _reg, \ 235d058fd9eSRahul Tanwar .div_shift = _shift, \ 236d058fd9eSRahul Tanwar .div_width = _width, \ 237d058fd9eSRahul Tanwar .div_shift_gate = _shift_gate, \ 238d058fd9eSRahul Tanwar .div_width_gate = _width_gate, \ 239d058fd9eSRahul Tanwar .div_flags = _cf, \ 240d058fd9eSRahul Tanwar .div_val = _v, \ 241d058fd9eSRahul Tanwar .div_table = _dtable, \ 242d058fd9eSRahul Tanwar } 243d058fd9eSRahul Tanwar 244d058fd9eSRahul Tanwar #define LGM_GATE(_id, _name, _pname, _f, _reg, \ 245d058fd9eSRahul Tanwar _shift, _cf, _v) \ 246d058fd9eSRahul Tanwar { \ 247d058fd9eSRahul Tanwar .id = _id, \ 248d058fd9eSRahul Tanwar .type = CLK_TYPE_GATE, \ 249d058fd9eSRahul Tanwar .name = _name, \ 250d058fd9eSRahul Tanwar .parent_data = &(const struct clk_parent_data){ \ 251d058fd9eSRahul Tanwar .fw_name = _pname, \ 252d058fd9eSRahul Tanwar .name = _pname, \ 253d058fd9eSRahul Tanwar }, \ 254d058fd9eSRahul Tanwar .num_parents = !_pname ? 0 : 1, \ 255d058fd9eSRahul Tanwar .flags = _f, \ 256d058fd9eSRahul Tanwar .gate_off = _reg, \ 257d058fd9eSRahul Tanwar .gate_shift = _shift, \ 258d058fd9eSRahul Tanwar .gate_flags = _cf, \ 259d058fd9eSRahul Tanwar .gate_val = _v, \ 260d058fd9eSRahul Tanwar } 261d058fd9eSRahul Tanwar 262d058fd9eSRahul Tanwar #define LGM_FIXED(_id, _name, _pname, _f, _reg, \ 263d058fd9eSRahul Tanwar _shift, _width, _cf, _freq, _v) \ 264d058fd9eSRahul Tanwar { \ 265d058fd9eSRahul Tanwar .id = _id, \ 266d058fd9eSRahul Tanwar .type = CLK_TYPE_FIXED, \ 267d058fd9eSRahul Tanwar .name = _name, \ 268d058fd9eSRahul Tanwar .parent_data = &(const struct clk_parent_data){ \ 269d058fd9eSRahul Tanwar .fw_name = _pname, \ 270d058fd9eSRahul Tanwar .name = _pname, \ 271d058fd9eSRahul Tanwar }, \ 272d058fd9eSRahul Tanwar .num_parents = !_pname ? 0 : 1, \ 273d058fd9eSRahul Tanwar .flags = _f, \ 274d058fd9eSRahul Tanwar .div_off = _reg, \ 275d058fd9eSRahul Tanwar .div_shift = _shift, \ 276d058fd9eSRahul Tanwar .div_width = _width, \ 277d058fd9eSRahul Tanwar .div_flags = _cf, \ 278d058fd9eSRahul Tanwar .div_val = _v, \ 279d058fd9eSRahul Tanwar .mux_flags = _freq, \ 280d058fd9eSRahul Tanwar } 281d058fd9eSRahul Tanwar 282d058fd9eSRahul Tanwar #define LGM_FIXED_FACTOR(_id, _name, _pname, _f, _reg, \ 283d058fd9eSRahul Tanwar _shift, _width, _cf, _v, _m, _d) \ 284d058fd9eSRahul Tanwar { \ 285d058fd9eSRahul Tanwar .id = _id, \ 286d058fd9eSRahul Tanwar .type = CLK_TYPE_FIXED_FACTOR, \ 287d058fd9eSRahul Tanwar .name = _name, \ 288d058fd9eSRahul Tanwar .parent_data = &(const struct clk_parent_data){ \ 289d058fd9eSRahul Tanwar .fw_name = _pname, \ 290d058fd9eSRahul Tanwar .name = _pname, \ 291d058fd9eSRahul Tanwar }, \ 292d058fd9eSRahul Tanwar .num_parents = 1, \ 293d058fd9eSRahul Tanwar .flags = _f, \ 294d058fd9eSRahul Tanwar .div_off = _reg, \ 295d058fd9eSRahul Tanwar .div_shift = _shift, \ 296d058fd9eSRahul Tanwar .div_width = _width, \ 297d058fd9eSRahul Tanwar .div_flags = _cf, \ 298d058fd9eSRahul Tanwar .div_val = _v, \ 299d058fd9eSRahul Tanwar .mult = _m, \ 300d058fd9eSRahul Tanwar .div = _d, \ 301d058fd9eSRahul Tanwar } 302d058fd9eSRahul Tanwar 303d058fd9eSRahul Tanwar static inline void lgm_set_clk_val(void __iomem *membase, u32 reg, 304d058fd9eSRahul Tanwar u8 shift, u8 width, u32 set_val) 305d058fd9eSRahul Tanwar { 306d058fd9eSRahul Tanwar u32 mask = (GENMASK(width - 1, 0) << shift); 307d058fd9eSRahul Tanwar u32 regval; 308d058fd9eSRahul Tanwar 309d058fd9eSRahul Tanwar regval = readl(membase + reg); 310d058fd9eSRahul Tanwar regval = (regval & ~mask) | ((set_val << shift) & mask); 311d058fd9eSRahul Tanwar writel(regval, membase + reg); 312d058fd9eSRahul Tanwar } 313d058fd9eSRahul Tanwar 314d058fd9eSRahul Tanwar static inline u32 lgm_get_clk_val(void __iomem *membase, u32 reg, 315d058fd9eSRahul Tanwar u8 shift, u8 width) 316d058fd9eSRahul Tanwar { 317d058fd9eSRahul Tanwar u32 mask = (GENMASK(width - 1, 0) << shift); 318d058fd9eSRahul Tanwar u32 val; 319d058fd9eSRahul Tanwar 320d058fd9eSRahul Tanwar val = readl(membase + reg); 321d058fd9eSRahul Tanwar val = (val & mask) >> shift; 322d058fd9eSRahul Tanwar 323d058fd9eSRahul Tanwar return val; 324d058fd9eSRahul Tanwar } 325d058fd9eSRahul Tanwar 326d058fd9eSRahul Tanwar int lgm_clk_register_branches(struct lgm_clk_provider *ctx, 327d058fd9eSRahul Tanwar const struct lgm_clk_branch *list, 328d058fd9eSRahul Tanwar unsigned int nr_clk); 329d058fd9eSRahul Tanwar int lgm_clk_register_plls(struct lgm_clk_provider *ctx, 330d058fd9eSRahul Tanwar const struct lgm_pll_clk_data *list, 331d058fd9eSRahul Tanwar unsigned int nr_clk); 332d058fd9eSRahul Tanwar int lgm_clk_register_ddiv(struct lgm_clk_provider *ctx, 333d058fd9eSRahul Tanwar const struct lgm_clk_ddiv_data *list, 334d058fd9eSRahul Tanwar unsigned int nr_clk); 335d058fd9eSRahul Tanwar #endif /* __CLK_CGU_H */ 336