blob: 7cbcb6ab296dbc72ca0103e2f0fcca3ea6970bf6 [file] [log] [blame]
#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