diff -drupN a/drivers/clk/ingenic/clk.h b/drivers/clk/ingenic/clk.h --- a/drivers/clk/ingenic/clk.h 1970-01-01 03:00:00.000000000 +0300 +++ b/drivers/clk/ingenic/clk.h 2022-06-09 05:02:28.000000000 +0300 @@ -0,0 +1,581 @@ +#ifndef __INGENIC_CLK_H +#define __INGENIC_CLK_H + +#include +#include "clk-pll.h" +#include "clk-div.h" +#include "clk-bus.h" +#include "power-gate.h" +#include + +struct clk; + +/** + * struct ingenic_clk_provider: information about clock provider + * @reg_base: virtual address for the register base. + * @clk_data: holds clock related data like clk* and number of clocks. + * @lock: maintains exclusion between callbacks for a given clock-provider. + */ +struct ingenic_clk_provider { + void __iomem *reg_base; + struct clk_onecell_data clk_data; + spinlock_t lock; +}; + +/** + * struct ingenic_clock_alias: information about mux clock + * @id: platform specific id of the clock. + * @dev_name: name of the device to which this clock belongs. + * @alias: optional clock alias name to be assigned to this clock. + */ +struct ingenic_clock_alias { + unsigned int id; + const char *dev_name; + const char *alias; +}; + +#define ALIAS(_id, dname, a) \ + { \ + .id = _id, \ + .dev_name = dname, \ + .alias = a, \ + } + +#define MHZ (1000 * 1000) + +/** + * struct ingenic_fixed_rate_clock: information about fixed-rate clock + * @id: platform specific id of the clock. + * @name: name of this fixed-rate clock. + * @parent_name: optional parent clock name. + * @flags: optional fixed-rate clock flags. + * @fixed-rate: fixed clock rate of this clock. + */ +struct ingenic_fixed_rate_clock { + unsigned int id; + char *name; + const char *parent_name; + unsigned long flags; + unsigned long fixed_rate; +}; + +#define FRATE(_id, cname, pname, f, frate) \ + { \ + .id = _id, \ + .name = cname, \ + .parent_name = pname, \ + .flags = (f | CLK_IGNORE_UNUSED), \ + .fixed_rate = frate, \ + } + +/* + * struct ingenic_fixed_factor_clock: information about fixed-factor clock + * @id: platform specific id of the clock. + * @name: name of this fixed-factor clock. + * @parent_name: parent clock name. + * @mult: fixed multiplication factor. + * @div: fixed division factor. + * @flags: optional fixed-factor clock flags. + */ +struct ingenic_fixed_factor_clock { + unsigned int id; + char *name; + const char *parent_name; + unsigned long mult; + unsigned long div; + unsigned long flags; +}; + +#define FFACTOR(_id, cname, pname, m, d, f) \ + { \ + .id = _id, \ + .name = cname, \ + .parent_name = pname, \ + .mult = m, \ + .div = d, \ + .flags = f, \ + } + +/** + * struct ingenic_mux_clock: information about mux clock + * @id: platform specific id of the clock. + * @dev_name: name of the device to which this clock belongs. + * @name: name of this mux clock. + * @table: mux table in regs. + * @parent_names: array of pointer to parent clock names. + * @num_parents: number of parents listed in @parent_names. + * @flags: optional flags for basic clock. + * @offset: offset of the register for configuring the mux. + * @shift: starting bit location of the mux control bit-field in @reg. + * @width: width of the mux control bit-field in @reg. + * @mux_flags: flags for mux-type clock. + * @alias: optional clock alias name to be assigned to this clock. + */ +struct ingenic_mux_clock { + unsigned int id; + const char *dev_name; + const char *name; + unsigned int *table; + const char **parent_names; + u8 num_parents; + unsigned long flags; + unsigned long offset; + u8 shift; + u8 width; + u8 mux_flags; + const char *alias; +}; + +#define __MUX(_id, dname, cname, tb, pnames, o, s, w, f, mf, a) \ + { \ + .id = _id, \ + .dev_name = dname, \ + .name = cname, \ + .table = tb, \ + .parent_names = pnames, \ + .num_parents = ARRAY_SIZE(pnames), \ + .flags = f, \ + .offset = o, \ + .shift = s, \ + .width = w, \ + .mux_flags = mf, \ + .alias = a, \ + } + +#define MUX(_id, cname, tb, pnames, o, s, w, f) \ + __MUX(_id, NULL, cname, tb, pnames, o, s, w, f, 0, cname) + +#define MUX_A(_id, cname, tb, pnames, o, s, w, a) \ + __MUX(_id, NULL, cname, tb, pnames, o, s, w, 0, 0, a) + +#define MUX_F(_id, cname, tb, pnames, o, s, w, f, mf) \ + __MUX(_id, NULL, cname, tb, pnames, o, s, w, f, mf, NULL) + +#define MUX_FA(_id, cname, tb, pnames, o, s, w, f, mf, a) \ + __MUX(_id, NULL, cname, tb, pnames, o, s, w, f, mf, a) + +/** + * @id: platform specific id of the clock. + * struct ingenic_div_clock: information about div clock + * @dev_name: name of the device to which this clock belongs. + * @name: name of this div clock. + * @parent_name: name of the parent clock. + * @flags: optional flags for basic clock. + * @offset: offset of the register for configuring the div. + * @shift: starting bit location of the div control bit-field in @reg. + * @busy_offset: offset of the register waiting for div stable. + * @busy_shift: bit-field of the busy bit in busy_reg, by finding the busy shift, we can also find the ce, and stop bit. + * @en_shift: points to some gateble clk in div cfg, ugly we gate clock in div clocks. + * @div_flags: divider flags. + * @alias: optional clock alias name to be assigned to this clock. + * @table: clk div table if possible. + */ +struct ingenic_div_clock { + unsigned int id; + const char *dev_name; + const char *name; + const char *parent_name; + unsigned long flags; + unsigned long offset; + u8 shift; + u8 width; + + unsigned long busy_offset; + int busy_shift; + int en_shift; + int stop_shift; + + int div_flags; + const char *alias; + struct clk_div_table *table; +}; + +#define __DIV(_id, dname, cname, pname, o, s, w, bs, e, st, f, df, a, t) \ + { \ + .id = _id, \ + .dev_name = dname, \ + .name = cname, \ + .parent_name = pname, \ + .flags = (f | CLK_IGNORE_UNUSED), \ + .offset = o, \ + .shift = s, \ + .width = w, \ + .div_flags = df, \ + .busy_shift = bs, \ + .en_shift = e, \ + .stop_shift = st, \ + .alias = a, \ + .table = t, \ + } + +#define DIV(_id, cname, pname, o, w, df, t) \ + __DIV(_id, NULL, cname, pname, o, 0, w, 28, 29, 27, 0, df, cname, t) + +#define DIV_EN(_id, cname, pname, o, s, w, bs, e) \ + __DIV(_id, NULL, cname, pname, o, s, w, bs, e, 0, 0, NULL, NULL) + +/** + * @id: platform specific id of the clock. + * struct ingenic_bus_clock: information about div clock + * @dev_name: name of the device to which this clock belongs. + * @name: name of this div clock. + * @parent_name: name of the parent clock. + * @flags: optional flags for basic clock. + * @cfg_offset: offset of the register for configuring the div. + * @div_shift: starting bit location of the div control bit-field in @reg. + * @div_width: bit width of the div field. + * @busy_offset: offset of the register waiting for div stable. + * @busy_shift: bit-field of the busy bit in busy_reg, by finding the busy shift, we can also find the ce, and stop bit. + * @en_shift: points to some gateble clk in div cfg, ugly we gate clock in div clocks. + * @div_flags: flags for div-type clock, For example, DIV_NO_BUSY. + * @alias: optional clock alias name to be assigned to this clock. + * @table: clk div table if possible. + */ + + +struct ingenic_bus_clock { + unsigned int id; + const char *dev_name; + const char *name; + const char *parent_name; + unsigned long flags; + unsigned long cfg_offset; + u8 div_shift1; + u8 div_width1; + u8 div_shift2; + u8 div_width2; + int ce_shift; + + int busy_offset; + int busy_shift; + + int div_flags; + int div_flags_2; + const char *alias; + struct clk_div_table *table; +}; + +#define __BUS_DIV(_id, dname, cname, pname, o, s1, w1, s2, w2, bo, bs, ce, f, df, df2, a, t) \ + { \ + .id = _id, \ + .dev_name = dname, \ + .name = cname, \ + .parent_name = pname, \ + .flags = (f | CLK_IGNORE_UNUSED), \ + .cfg_offset = o, \ + .div_shift1 = s1, \ + .div_width1 = w1, \ + .div_shift2 = s2, \ + .div_width2 = w2, \ + .ce_shift = ce, \ + .busy_offset = bo, \ + .busy_shift = bs, \ + .div_flags = df, \ + .alias = a, \ + .table = t, \ + .div_flags_2 = df2, \ + } + +#define BUS_DIV(_id, cname, pname, o, s1, w1, s2, w2, bo, bs, ce, df2) \ + __BUS_DIV(_id, NULL, cname, pname, o, s1, w1, s2, w2, bo, bs, ce, CLK_GET_RATE_NOCACHE, 0, df2, cname, NULL) + + + +struct ingenic_fra_div_clock { + unsigned int id; + const char *dev_name; + const char *name; + const char *parent_name; + unsigned long flags; + + unsigned long offset; + u8 mshift; + u8 mwidth; + u8 nshift; + u8 nwidth; + + int div_flags; + const char *alias; +}; + +#define __FRA_DIV(_id, dname, cname, pname, f, o, ms, mw, ns, nw, df, a) \ + { \ + .id = _id, \ + .dev_name = dname, \ + .name = cname, \ + .parent_name = pname, \ + .flags = f, \ + .offset = o, \ + .mshift = ms, \ + .mwidth = mw, \ + .nshift = ns, \ + .nwidth = nw, \ + .div_flags = df, \ + .alias = a, \ + } + +#define FRA_DIV(_id, cname, pname, o, ms, mw, ns, nw) \ + __FRA_DIV(_id, NULL, cname, pname, 0, o, ms, mw, ns, nw, 0, cname) + +/** + * struct ingenic_gate_clock: information about gate clock + * @id: platform specific id of the clock. + * @dev_name: name of the device to which this clock belongs. + * @name: name of this gate clock. + * @parent_name: name of the parent clock. + * @pwc_name: name of the power control clk under this clock gate. + * @flags: optional flags for basic clock. + * @offset: offset of the register for configuring the gate. + * @bit_idx: bit index of the gate control bit-field in @reg. + * @sram_offset: offset of the corresponding sram contrl reg. + * @sram_shift: shift for the sram control bit idx in sram_reg. + * @gate_flags: flags for gate-type clock. + * @alias: optional clock alias name to be assigned to this clock. + * @gate_flags: flags for gate clock. + * @alias: alias name for this clock. + */ +struct ingenic_gate_clock { + unsigned int id; + const char *dev_name; + const char *name; + const char *parent_name; + + unsigned long flags; + unsigned long offset; + u8 bit_idx; + int sram_offset; + int sram_shift; + u8 gate_flags; + const char *alias; + +}; + +#define __GATE(_id, dname, cname, pname, o, b, f, so, sps, gf, a) \ + { \ + .id = _id, \ + .dev_name = dname, \ + .name = cname, \ + .parent_name = pname, \ + .flags = f, \ + .offset = o, \ + .bit_idx = b, \ + .sram_offset = so, \ + .sram_shift = sps, \ + .gate_flags = gf, \ + .alias = a, \ + } + +#define GATE(_id, cname, pname, o, b, f, gf) \ + __GATE(_id, NULL, cname, pname, o, b, f, -1, -1, gf, cname) + + +#define GATE_SRAM(_id, cname, pname, o, b, f, gf, so, sps) \ + __GATE(_id, NULL, cname, pname, NULL, o, b, f, so, sps, gf, cname) + + +/** + * struct ingenic_power_clock: information about power clock + * @id: platform specific id of the clock. + * @dev_name: name of the device to which this clock belongs. + * @name: name of this gate clock. + * @parent_name: name of the parent clock. + * @flags: optional flags for basic clock. + * @offset: offset of the register for configuring the gate. + * @ctrl_bit: bit index of the power control bit-field in @reg. + * @wait_bit: bit index of the power status bit-field in @reg. + * @delay_ms: wait for ms time stable @reg. + * @gate_flags: flags for gate-type clock. + * @alias: optional clock alias name to be assigned to this clock. + * @clk_flags: ingneic special flags. + */ +struct ingenic_gate_power { + unsigned int id; + const char *dev_name; + const char *name; + const char *parent_name; + + unsigned long flags; + unsigned long offset; + u8 ctrl_bit; + u8 wait_bit; + u8 gate_flags; + const char *alias; + unsigned long power_flags; +}; + +#define __POWER(_id, dname, cname, pname, f, o, cb, wb, gf, a, pf) \ + { \ + .id = _id, \ + .dev_name = dname, \ + .name = cname, \ + .parent_name = pname, \ + .flags = f, \ + .offset = o, \ + .ctrl_bit = cb, \ + .wait_bit = wb, \ + .gate_flags = gf, \ + .alias = a, \ + .power_flags = pf, \ + } + +#define POWER(_id, cname, pname, o, cb, wb, f, gf, pf) \ + __POWER(_id, NULL, cname, pname, f, o, cb, wb, gf, cname, pf) + +#define PNAME(x) static const char *x[] __initdata + +/** + * struct ingenic_clk_reg_dump: register dump of clock controller registers. + * @offset: clock register offset from the controller base address. + * @value: the value to be register at offset. + */ +struct ingenic_clk_reg_dump { + u32 offset; + u32 value; +}; + +/** + * struct ingenic_pll_clock: information about pll clock + * @id: platform specific id of the clock. + * @dev_name: name of the device to which this clock belongs. + * @name: name of this pll clock. + * @parent_name: name of the parent clock. + * @flags: optional flags for basic clock. + * @con_offset: offset of the register for configuring the PLL. + * @lock_offset: offset of the register for locking the PLL. + * @type: Type of PLL to be registered. + * @alias: optional clock alias name to be assigned to this clock. + */ +struct ingenic_pll_clock { + unsigned int id; + const char *dev_name; + const char *name; + const char *parent_name; + + unsigned long flags; + int con_offset; + int lock_offset; + const char *alias; + struct ingenic_pll_hwdesc *hwdesc; + struct ingenic_pll_rate_table *rate_table; +}; + +#define PLL(_id, _name, _parent_name, _hwdesc, _rtable) \ +{ \ + .id = _id, \ + .dev_name = _name, \ + .name = _name, \ + .parent_name = _parent_name, \ + .hwdesc = _hwdesc, \ + .rate_table = _rtable, \ +} + +struct ingenic_clock_reg_cache { + struct list_head node; + void __iomem *reg_base; + struct ingenic_clk_reg_dump *rdump; + unsigned int rd_num; +}; + +struct ingenic_cmu_info { + /* list of pll clocks and respective count */ + struct ingenic_pll_clock *pll_clks; + unsigned int nr_pll_clks; + /* list of mux clocks and respective count */ + struct ingenic_mux_clock *mux_clks; + unsigned int nr_mux_clks; + /* list of div clocks and respective count */ + struct ingenic_div_clock *div_clks; + unsigned int nr_div_clks; + /* list of gate clocks and respective count */ + struct ingenic_gate_clock *gate_clks; + unsigned int nr_gate_clks; + /* list of fixed clocks and respective count */ + struct ingenic_fixed_rate_clock *fixed_clks; + unsigned int nr_fixed_clks; + /* list of fixed factor clocks and respective count */ + struct ingenic_fixed_factor_clock *fixed_factor_clks; + unsigned int nr_fixed_factor_clks; + /* total number of clocks with IDs assigned*/ + unsigned int nr_clk_ids; + + /* list and number of clocks registers */ + unsigned long *clk_regs; + unsigned int nr_clk_regs; +}; + +struct ingenic_cpm_info { + struct ingenic_power_clock *pwc_clks; + unsigned int nr_pwc_clks; + +}; + +extern struct ingenic_clk_provider *__init ingenic_clk_init( + struct device_node *np, void __iomem *base, + unsigned long nr_clks); +extern void __init ingenic_clk_of_add_provider(struct device_node *np, + struct ingenic_clk_provider *ctx); +extern void __init ingenic_clk_of_register_fixed_ext( + struct ingenic_clk_provider *ctx, + struct ingenic_fixed_rate_clock *fixed_rate_clk, + unsigned int nr_fixed_rate_clk, + const struct of_device_id *clk_matches); + +extern void ingenic_clk_add_lookup(struct ingenic_clk_provider *ctx, + struct clk *clk, unsigned int id); + +extern void __init ingenic_clk_register_alias(struct ingenic_clk_provider *ctx, + const struct ingenic_clock_alias *list, + unsigned int nr_clk); +extern void __init ingenic_clk_register_fixed_rate( + struct ingenic_clk_provider *ctx, + const struct ingenic_fixed_rate_clock *clk_list, + unsigned int nr_clk); +extern void __init ingenic_clk_register_fixed_factor( + struct ingenic_clk_provider *ctx, + const struct ingenic_fixed_factor_clock *list, + unsigned int nr_clk); +extern void __init ingenic_clk_register_mux(struct ingenic_clk_provider *ctx, + const struct ingenic_mux_clock *clk_list, + unsigned int nr_clk); +extern void __init ingenic_clk_register_cgu_div(struct ingenic_clk_provider *ctx, + const struct ingenic_div_clock *clk_list, + unsigned int nr_clk); + +extern void __init ingenic_clk_register_gate(struct ingenic_clk_provider *ctx, + const struct ingenic_gate_clock *list, + unsigned int nr_clk); + +extern void __init ingenic_power_register_gate(struct ingenic_clk_provider *ctx, + const struct ingenic_gate_power *list, + unsigned int nr_clk); + +extern void __init ingenic_clk_register_pll(struct ingenic_clk_provider *ctx, + const struct ingenic_pll_clock *pll_list, + unsigned int nr_clk, void __iomem *base); + +extern struct ingenic_clk_provider __init *ingenic_cmu_register_one( + struct device_node *, + struct ingenic_cmu_info *); + +extern unsigned long _get_rate(const char *clk_name); + +extern void ingenic_clk_save(void __iomem *base, + struct ingenic_clk_reg_dump *rd, + unsigned int num_regs); +extern void ingenic_clk_restore(void __iomem *base, + const struct ingenic_clk_reg_dump *rd, + unsigned int num_regs); +extern struct ingenic_clk_reg_dump *ingenic_clk_alloc_reg_dump( + const unsigned long *rdump, + unsigned long nr_rdump); + +extern void __init ingenic_clk_register_bus_div(struct ingenic_clk_provider *ctx, + const struct ingenic_bus_clock *list, + unsigned int nr_clk); + +extern void __init ingenic_clk_register_fra_div(struct ingenic_clk_provider *ctx, + const struct ingenic_fra_div_clock *list, + unsigned int nr_clk); + +void ingenic_clk_of_dump(struct ingenic_clk_provider *ctx); +#endif /* __INGENIC_CLK_H */