| #ifndef __PWRCAL_CLK_H__ |
| #define __PWRCAL_CLK_H__ |
| |
| #ifndef NULL |
| #define NULL (0) |
| #endif |
| |
| #ifndef MHZ |
| #define MHZ ((unsigned long long)1000000) |
| #endif |
| #ifndef KHZ |
| #define KHZ ((unsigned int)1000) |
| #endif |
| |
| #ifndef FIN_HZ |
| #if defined(CONFIG_BOARD_FPGA) |
| #define FIN_HZ (5*MHZ) |
| #else |
| #define FIN_HZ (24*MHZ) |
| #endif |
| #endif |
| |
| #define CLK_WAIT_CNT 1000 |
| |
| #define TO_MASK(_size) (((unsigned int)1<<(_size))-1) |
| |
| #define invalid_mux_src_num 0xFF |
| #define mux_flag_user_mux (1<<0) |
| #define mux_flag_alwayson (1<<1) |
| |
| |
| #define mask_of_type 0x0F000000 |
| #define mask_of_group 0x00FF0000 |
| #define mask_of_id 0x00000FFF |
| #define fixed_rate_type 0x01000000 |
| #define fixed_factor_type 0x02000000 |
| #define pll_type 0x05000000 |
| #define mux_type 0x06000000 |
| #define user_mux_type 0x06001000 |
| #define div_type 0x07000000 |
| #define gate_type 0x08000000 |
| #define gate_root_type 0x09000000 |
| #define vclk_type 0x0A000000 |
| #define invalid_clk_id mask_of_id |
| #define empty_clk_id mask_of_id |
| |
| #define is_pll(a) (a && (a->id & mask_of_type) == pll_type) |
| #define is_mux(a) (a && (a->id & mask_of_type) == mux_type) |
| #define is_div(a) (a && (a->id & mask_of_type) == div_type) |
| #define is_gate(a) (a && (a->id & mask_of_type) == gate_type) |
| |
| enum clk_id; |
| |
| struct pwrcal_clk { |
| unsigned int id; |
| struct pwrcal_clk *parent; |
| unsigned int *offset; |
| unsigned short shift; |
| unsigned short width; |
| unsigned int *status; /* or lock_offset of pll */ |
| unsigned short s_shift; |
| unsigned short s_width; |
| unsigned int *enable; |
| unsigned short e_shift; |
| unsigned short e_width; |
| const char *name; |
| }; |
| |
| struct pwrcal_clk_none { |
| struct pwrcal_clk clk; |
| }; |
| extern struct pwrcal_clk_none clk_0; |
| #define CLK_NONE (&(clk_0.clk)) |
| #define CLK(_id) ((struct pwrcal_clk *)(&((clk_##_id).clk))) |
| |
| |
| struct pll_spec { |
| unsigned int pdiv_min; |
| unsigned int pdiv_max; |
| unsigned int mdiv_min; |
| unsigned int mdiv_max; |
| unsigned int sdiv_min; |
| unsigned int sdiv_max; |
| signed short kdiv_min; |
| signed short kdiv_max; |
| unsigned long long fref_min; |
| unsigned long long fref_max; |
| unsigned long long fvco_min; |
| unsigned long long fvco_max; |
| unsigned long long fout_min; |
| unsigned long long fout_max; |
| }; |
| |
| struct pwrcal_pll_rate_table { |
| unsigned long long rate; |
| unsigned short pdiv; |
| unsigned short mdiv; |
| unsigned short sdiv; |
| signed short kdiv; |
| }; |
| |
| struct pwrcal_pll_ops { |
| int (*is_enabled)(struct pwrcal_clk *clk); |
| int (*enable)(struct pwrcal_clk *clk); |
| int (*disable)(struct pwrcal_clk *clk); |
| int (*set_rate)(struct pwrcal_clk *clk, unsigned long long rate); |
| unsigned long long (*get_rate)(struct pwrcal_clk *clk); |
| }; |
| |
| struct pwrcal_pll { |
| struct pwrcal_clk clk; |
| unsigned int type; |
| struct pwrcal_pll_rate_table *rate_table; |
| unsigned int rate_count; |
| struct pwrcal_clk *mux; |
| struct pwrcal_pll_ops *ops; |
| }; |
| |
| #define CLK_PLL(_typ, _id, _pid, _lock, _con, _rtable, _mux, _ops) \ |
| struct pwrcal_pll clk_##_id __attribute__((unused, aligned(8), section(".clk_pll."))) = { \ |
| .clk.id = _id, \ |
| .clk.parent = &((clk_##_pid).clk), \ |
| .clk.offset = _con, \ |
| .clk.status = _lock, \ |
| .clk.name = #_id, \ |
| .type = _typ, \ |
| .rate_table = _rtable, \ |
| .rate_count = (sizeof(_rtable) / sizeof((_rtable)[0])), \ |
| .mux = &((clk_##_mux).clk), \ |
| .ops = _ops \ |
| } |
| |
| |
| extern struct pwrcal_clk_ops frate_ops; |
| struct pwrcal_clk_fixed_rate { |
| struct pwrcal_clk clk; |
| unsigned long long fixed_rate; |
| struct pwrcal_clk *gate; |
| }; |
| |
| #define FIXEDRATE(_id, _frate, _gate) \ |
| struct pwrcal_clk_fixed_rate clk_##_id __attribute__((unused, aligned(8), section(".clk_fixed_rate."))) = { \ |
| .clk.id = _id, \ |
| .clk.parent = &(clk_0.clk), \ |
| .clk.name = #_id, \ |
| .fixed_rate = _frate, \ |
| .gate = &((clk_##_gate).clk), \ |
| } |
| |
| |
| extern struct pwrcal_clk_ops fdiv_ops; |
| struct pwrcal_clk_fixed_factor { |
| struct pwrcal_clk clk; |
| unsigned short ratio; |
| struct pwrcal_clk *gate; |
| }; |
| |
| #define FIXEDFACTOR(_id, _pid, _ratio, _gate) \ |
| struct pwrcal_clk_fixed_factor clk_##_id __attribute__((unused, aligned(8), section(".clk_fixed_factor."))) = { \ |
| .clk.id = _id, \ |
| .clk.parent = &((clk_##_pid).clk), \ |
| .clk.name = #_id, \ |
| .ratio = _ratio, \ |
| .gate = &((clk_##_gate).clk), \ |
| } |
| |
| |
| extern struct pwrcal_clk_ops mux_ops; |
| struct pwrcal_mux { |
| struct pwrcal_clk clk; |
| struct pwrcal_clk **parents; |
| unsigned char num_parents; |
| struct pwrcal_clk *gate; |
| }; |
| |
| #define CLK_MUX(_id, _pids, _o, _s, _w, _so, _ss, _sw, \ |
| _eo, _es, _gate) \ |
| struct pwrcal_mux clk_##_id __attribute__((unused, aligned(8), section(".clk_mux."))) = { \ |
| .clk.id = _id, \ |
| .clk.name = #_id, \ |
| .clk.offset = _o, \ |
| .clk.shift = _s, \ |
| .clk.width = _w, \ |
| .clk.status = _so, \ |
| .clk.s_shift = _ss, \ |
| .clk.s_width = _sw, \ |
| .clk.enable = _eo, \ |
| .clk.e_shift = _es, \ |
| .parents = _pids, \ |
| .num_parents = (sizeof(_pids) / sizeof((_pids)[0])), \ |
| .gate = &((clk_##_gate).clk), \ |
| } |
| |
| |
| extern struct pwrcal_clk_ops div_ops; |
| struct pwrcal_div { |
| struct pwrcal_clk clk; |
| struct pwrcal_clk *gate; |
| }; |
| |
| #define CLK_DIV(_id, _pid, _o, _s, _w, _so, _ss, _sw, _gate) \ |
| struct pwrcal_div clk_##_id __attribute__((unused, aligned(8), section(".clk_div."))) = { \ |
| .clk.id = _id, \ |
| .clk.name = #_id, \ |
| .clk.parent = &((clk_##_pid).clk), \ |
| .clk.offset = _o, \ |
| .clk.shift = _s, \ |
| .clk.width = _w, \ |
| .clk.status = _so, \ |
| .clk.s_shift = _ss, \ |
| .clk.s_width = _sw, \ |
| .gate = &((clk_##_gate).clk), \ |
| } |
| |
| |
| extern struct pwrcal_clk_ops gate_ops; |
| struct pwrcal_gate { |
| struct pwrcal_clk clk; |
| }; |
| |
| #define CLK_GATE(_id, _pid, _o, _s) \ |
| struct pwrcal_gate clk_##_id __attribute__((unused, aligned(8), section(".clk_gate."))) = { \ |
| .clk.id = _id, \ |
| .clk.name = #_id, \ |
| .clk.parent = &((clk_##_pid).clk), \ |
| .clk.offset = _o, \ |
| .clk.shift = _s, \ |
| } |
| |
| #define PLL_EXTERN(_id) \ |
| extern struct pwrcal_pll clk_##_id; |
| #define FIXEDRATE_EXTERN(_id) \ |
| extern struct pwrcal_clk_fixed_rate clk_##_id; |
| #define FIXEDFACTOR_EXTERN(_id) \ |
| extern struct pwrcal_clk_fixed_factor clk_##_id; |
| #define MUX_EXTERN(_id) \ |
| extern struct pwrcal_mux clk_##_id; |
| #define DIV_EXTERN(_id) \ |
| extern struct pwrcal_div clk_##_id; |
| #define GATE_EXTERN(_id) \ |
| extern struct pwrcal_gate clk_##_id; |
| |
| |
| #define to_pll(_clk) container_of(_clk, struct pwrcal_pll, clk) |
| #define to_frate(_clk) container_of(_clk, struct pwrcal_clk_fixed_rate, clk) |
| #define to_ffactor(_clk) container_of(_clk, struct pwrcal_clk_fixed_factor, clk) |
| #define to_mux(_clk) container_of(_clk, struct pwrcal_mux, clk) |
| #define to_div(_clk) container_of(_clk, struct pwrcal_div, clk) |
| #define to_gate(_clk) container_of(_clk, struct pwrcal_gate, clk) |
| |
| struct clk_entry { |
| unsigned int id; |
| struct pwrcal_clk *clk; |
| }; |
| extern struct clk_entry pwrcal_clk_list[]; |
| |
| extern int pwrcal_mux_is_enabled(struct pwrcal_clk *clk); |
| extern int pwrcal_mux_enable(struct pwrcal_clk *clk); |
| extern int pwrcal_mux_disable(struct pwrcal_clk *clk); |
| extern int pwrcal_mux_get_src(struct pwrcal_clk *clk); |
| extern int pwrcal_mux_set_src(struct pwrcal_clk *clk, unsigned int src); |
| extern int pwrcal_mux_get_parents(struct pwrcal_clk *clk, |
| struct pwrcal_clk **parents); |
| extern struct pwrcal_clk *pwrcal_mux_get_parent(struct pwrcal_clk *clk); |
| extern int _pwrcal_is_private_mux_set_src(struct pwrcal_clk *clk); |
| extern int _pwrcal_private_mux_set_src(struct pwrcal_clk *clk, |
| unsigned int src); |
| |
| extern int pwrcal_div_is_enabled(struct pwrcal_clk *clk); |
| extern int pwrcal_div_enable(struct pwrcal_clk *clk); |
| extern int pwrcal_div_disable(struct pwrcal_clk *clk); |
| extern unsigned int pwrcal_div_get_ratio(struct pwrcal_clk *clk); |
| extern int pwrcal_div_set_ratio(struct pwrcal_clk *clk, unsigned int ratio); |
| extern unsigned int pwrcal_div_get_max_ratio(struct pwrcal_clk *clk); |
| |
| extern int pwrcal_pll_is_enabled(struct pwrcal_clk *clk); |
| extern int pwrcal_pll_enable(struct pwrcal_clk *clk); |
| extern int pwrcal_pll_disable(struct pwrcal_clk *clk); |
| extern unsigned long long pwrcal_pll_get_rate(struct pwrcal_clk *clk); |
| extern int pwrcal_pll_set_rate(struct pwrcal_clk *clk, unsigned long long rate); |
| extern unsigned long long clk_pll_getmaxfreq(struct pwrcal_clk *clk); |
| extern struct pll_spec *clk_pll_get_spec(struct pwrcal_clk *clk); |
| |
| extern int pwrcal_gate_is_enabled(struct pwrcal_clk *clk); |
| extern int pwrcal_gate_enable(struct pwrcal_clk *clk); |
| extern int pwrcal_gate_disable(struct pwrcal_clk *clk); |
| |
| extern struct pwrcal_clk *pwrcal_clk_get_parent(struct pwrcal_clk *clk); |
| extern unsigned long long pwrcal_clk_get_rate(struct pwrcal_clk *clk); |
| extern int pwrcal_clk_set_rate(struct pwrcal_clk *clk, unsigned long long rate); |
| extern int pwrcal_clk_enable(struct pwrcal_clk *clk); |
| extern int pwrcal_clk_disable(struct pwrcal_clk *clk); |
| |
| extern unsigned int _cal_clk_get(char *name); |
| extern struct pwrcal_clk *cal_get_clk(unsigned int id); |
| |
| extern void clk_init(void); |
| extern struct pwrcal_clk *clk_find(char *clk_name); |
| #endif |