Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 /*
0003  * Copyright(c) 2020 Intel Corporation.
0004  * Zhu YiXin <yixin.zhu@intel.com>
0005  * Rahul Tanwar <rahul.tanwar@intel.com>
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  * struct lgm_clk_provider
0074  * @membase: IO mem base address for CGU.
0075  * @np: device node
0076  * @dev: device
0077  * @clk_data: array of hw clocks and clk number.
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  * struct lgm_pll_clk_data
0104  * @id: platform specific id of the clock.
0105  * @name: name of this pll clock.
0106  * @parent_data: parent clock data.
0107  * @num_parents: number of parents.
0108  * @flags: optional flags for basic clock.
0109  * @type: platform type of pll.
0110  * @reg: offset of the register.
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 /* clock flags definition */
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  /* __CLK_CGU_H */