| #ifndef __CMUCAL_H__ |
| #define __CMUCAL_H__ |
| |
| #include <linux/types.h> |
| #include <linux/kernel.h> |
| #include "vclk.h" |
| |
| struct dentry; |
| |
| #ifndef abs |
| #define abs(x) ({ \ |
| long ret; \ |
| if (sizeof(x) == sizeof(long)) { \ |
| long __x = (x); \ |
| ret = (__x < 0) ? -__x : __x; \ |
| } else { \ |
| int __x = (x); \ |
| ret = (__x < 0) ? -__x : __x; \ |
| } \ |
| ret; \ |
| }) |
| #endif |
| |
| #ifndef do_div |
| #define do_div(a, b) (a /= b) |
| #endif |
| |
| #define EVCLKPERM 1 |
| #define EVCLKNOENT 2 |
| #define EVCLKAGAIN 11 |
| #define EVCLKNOMEM 12 |
| #define EVCLKFAULT 14 /* Bad address */ |
| #define EVCLKBUSY 16 |
| #define EVCLKINVAL 22 |
| #define EVCLKTIMEOUT 110 |
| |
| #define MASK_OF_TYPE 0x0F000000 |
| #define MASK_OF_SUBTYPE 0x00FF0000 |
| #define MASK_OF_ID 0x0000FFFF |
| #define FIXED_RATE_TYPE 0x01000000 |
| #define FIXED_FACTOR_TYPE 0x02000000 |
| #define PLL_TYPE 0x03000000 |
| #define MUX_TYPE 0x04000000 |
| #define USER_MUX_TYPE 0x04010000 |
| #define CONST_MUX_TYPE 0x04020000 |
| #define DIV_TYPE 0x05000000 |
| #define CONST_DIV_TYPE 0x05020000 |
| #define GATE_TYPE 0x06000000 |
| #define GATE_ROOT_TYPE 0x06010000 |
| #define QCH_TYPE 0x07000000 |
| #define SFR_BLOCK_TYPE 0x08000000 |
| #define SFR_TYPE 0x09000000 |
| #define SFR_ACCESS_TYPE 0x0A000000 |
| #define VCLK_TYPE 0x0B000000 |
| #define COMMON_VCLK_TYPE 0x0B010000 |
| #define DFS_VCLK_TYPE 0x0B020000 |
| #define GATE_VCLK_TYPE 0x0B030000 |
| #define ACPM_VCLK_TYPE 0x0B040000 |
| #define OPTION_TYPE 0x0C000000 |
| #define CLKOUT_TYPE 0x0D000000 |
| #define INVALID_CLK_ID MASK_OF_ID |
| #define EMPTY_CLK_ID MASK_OF_ID |
| #define EMPTY_CAL_ID MASK_OF_ID |
| |
| /** |
| * struct vclk_lut - Virtual clock Look-Up-Table |
| * @rate: virtual clock rate |
| * @params: clks setting parameters, number of params is num_clks |
| */ |
| struct vclk_lut { |
| unsigned int rate; |
| unsigned int *params; |
| }; |
| |
| /** |
| * struct vclk_seq - Virtual clock sequence |
| * @idx: index of struct vclk_clks |
| * @opt: option : TRANS_HIGH, TRANS_LOW, TRANS_FORCE |
| */ |
| struct vclk_seq { |
| unsigned int idx; |
| unsigned int opt; |
| }; |
| |
| /** |
| * struct vclk_switch - switching lut info |
| * @switch_rate: switch_rate |
| * @mux_value: mux value about source |
| * @div_value: div value about mout |
| */ |
| struct switch_lut { |
| unsigned int rate; |
| unsigned int mux_value; |
| unsigned int div_value; |
| }; |
| |
| /** |
| * struct vclk_switch - Virtual clock switching PLL info |
| * @switch_mux: switching MUX id |
| * @src_mux: switching PLL source MUX id |
| * @src_div: switching PLL source Divider id |
| * @lut: switch PLL Look-Up-Table pointer |
| */ |
| struct vclk_switch { |
| unsigned int switch_mux; |
| unsigned int src_mux; |
| unsigned int src_div; |
| unsigned int src_gate; |
| unsigned int src_umux; |
| struct switch_lut *lut; |
| unsigned int num_switches; |
| }; |
| |
| /** |
| * struct vclk - Virtual clock |
| * @id: vclk id |
| * @name: vclk name |
| * @vrate: vclk virtual clock frequency |
| * @lut: Look-Up-Table pointer |
| * @seq: clock setting sequnce pointer |
| * @clk_list: clock list pointer |
| * @num_rates: number of lut rates |
| * @num_clks: number of clks and seq |
| */ |
| struct vclk { |
| unsigned int id; |
| char *name; |
| unsigned int vrate; |
| struct vclk_lut *lut; |
| unsigned int *list; |
| struct vclk_seq *seq; |
| unsigned int num_rates; |
| unsigned int num_list; |
| unsigned int max_freq; |
| unsigned int min_freq; |
| unsigned int boot_freq; |
| unsigned int resume_freq; |
| int margin_id; |
| struct vclk_switch *switch_info; |
| struct vclk_trans_ops *ops; |
| #ifdef CONFIG_DEBUG_FS |
| struct dentry *dentry; |
| #endif |
| }; |
| |
| enum clk_pll_type { |
| PLL_1416X = 14160, |
| PLL_1417X = 14170, |
| PLL_1418X = 14180, |
| PLL_1419X = 14190, |
| PLL_1431X = 14310, |
| PLL_1450X = 14500, |
| PLL_1451X = 14510, |
| PLL_1452X = 14520, |
| PLL_1460X = 14600, |
| |
| PLL_1050X = 10500, |
| PLL_1051X = 10510, |
| PLL_1052X = 10520, |
| PLL_1054X = 10540, |
| PLL_1061X = 10610, |
| |
| PLL_1016X = 10160, |
| PLL_1017X = 10170, |
| PLL_1018X = 10180, |
| PLL_1019X = 10190, |
| PLL_1031X = 10310, |
| }; |
| |
| enum margin_id { |
| MARGIN_MIF, |
| MARGIN_INT, |
| MARGIN_BIG, |
| MARGIN_LIT, |
| MARGIN_G3D, |
| MARGIN_INTCAM, |
| MARGIN_CAM, |
| MARGIN_DISP, |
| MARGIN_G3DM, |
| MARGIN_CP, |
| MARGIN_FSYS0, |
| MARGIN_AUD, |
| MARGIN_IVA, |
| MARGIN_SCORE, |
| MAX_MARGIN_ID, |
| }; |
| |
| #define IS_FIXED_RATE(_id) ((_id & MASK_OF_TYPE) == FIXED_RATE_TYPE) |
| #define IS_FIXED_FACTOR(_id) ((_id & MASK_OF_TYPE) == FIXED_FACTOR_TYPE) |
| #define IS_PLL(_id) ((_id & MASK_OF_TYPE) == PLL_TYPE) |
| #define IS_MUX(_id) ((_id & MASK_OF_TYPE) == MUX_TYPE) |
| #define IS_USER_MUX(_id) ((_id & (MASK_OF_TYPE | MASK_OF_SUBTYPE)) == USER_MUX_TYPE) |
| #define IS_CONST_MUX(_id) ((_id & (MASK_OF_TYPE | MASK_OF_SUBTYPE)) == CONST_MUX_TYPE) |
| #define IS_DIV(_id) ((_id & MASK_OF_TYPE) == DIV_TYPE) |
| #define IS_CONST_DIV(_id) ((_id & MASK_OF_TYPE | MASK_OF_SUBTYPE) == CONST_DIV_TYPE) |
| #define IS_GATE(_id) ((_id & MASK_OF_TYPE) == GATE_TYPE) |
| #define IS_QCH(_id) ((_id & MASK_OF_TYPE) == QCH_TYPE) |
| #define IS_OPTION(_id) ((_id & MASK_OF_TYPE) == OPTION_TYPE) |
| |
| #define IS_VCLK(_id) ((_id & MASK_OF_TYPE) == VCLK_TYPE) |
| #define IS_DFS_VCLK(_id) ((_id & (MASK_OF_TYPE | MASK_OF_SUBTYPE)) == DFS_VCLK_TYPE) |
| #define IS_COMMON_VCLK(_id) ((_id & (MASK_OF_TYPE | MASK_OF_SUBTYPE)) == COMMON_VCLK_TYPE) |
| #define IS_GATE_VCLK(_id) ((_id & (MASK_OF_TYPE | MASK_OF_SUBTYPE)) == GATE_VCLK_TYPE) |
| #define IS_ACPM_VCLK(_id) ((_id & (MASK_OF_TYPE | MASK_OF_SUBTYPE)) == ACPM_VCLK_TYPE) |
| |
| #define GET_TYPE(_id) (_id & MASK_OF_TYPE) |
| #define GET_IDX(_id) (_id & MASK_OF_ID) |
| /* |
| * struct sfr_block - SFR block |
| * @id: id of sfr_block |
| * @name: name of sfr_block |
| * @pa: physical address |
| * @va: virtual address |
| * @size: sfr block size, 2 ^ n |
| */ |
| struct sfr_block { |
| unsigned int id; |
| char *name; |
| phys_addr_t pa; |
| void __iomem *va; |
| unsigned int size; |
| }; |
| |
| /* |
| * struct sfr - SFR |
| * @id: id of sfr |
| * @name: sfr name |
| * @offset: offset from block |
| * @block: index of block |
| */ |
| struct sfr { |
| unsigned int id; |
| char *name; |
| unsigned int offset; |
| unsigned int block; |
| }; |
| |
| /* |
| * struct sfr_access - SFR field |
| * @id: id of sfr |
| * @name: sfr field name |
| * @shift: shift value of field |
| * @width: width value of field |
| * @sfr: index of sfr |
| */ |
| struct sfr_access { |
| unsigned int id; |
| char *name; |
| unsigned char shift; |
| unsigned char width; |
| unsigned int sfr; |
| }; |
| |
| /* |
| * struct cmucal_clk - CMUCAL Clock node |
| * @id: id of clock node |
| * @paddr: physical addr of clock node |
| * @pid: parent id of clock node |
| * @name: name of clock node |
| * @offset_idx: index of offset |
| * @status_idx: index of status |
| * @enable_idx: index of enable |
| * @offset: offset address |
| * @status: status address, or lock_offset of pll |
| * @enable: enable address |
| * @shift: shift of offset |
| * @width: width of offset |
| * @s_shift: shift of status |
| * @s_width: width of status |
| * @e_shift: shift of enable |
| * @e_width: width of enable |
| */ |
| struct cmucal_clk { |
| unsigned int id; |
| unsigned int paddr; |
| unsigned int pid; |
| char *name; |
| union { |
| void __iomem *offset; |
| void __iomem *lock; |
| unsigned long offset_idx; |
| }; |
| union { |
| void __iomem *enable; |
| void __iomem *pll_con0; |
| unsigned long enable_idx; |
| }; |
| union { |
| void __iomem *status; |
| void __iomem *pll_con1; |
| unsigned long status_idx; |
| }; |
| unsigned char shift; |
| unsigned char width; |
| unsigned char s_shift; |
| unsigned char s_width; |
| unsigned char e_shift; |
| unsigned char e_width; |
| }; |
| |
| /* |
| * struct pll_spec |
| * @p,m,s,k min/max value |
| * @fref, fvco, fout min/max value |
| */ |
| 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; |
| unsigned int lock_time; |
| unsigned int flock_time; |
| }; |
| |
| /* |
| * struct cmucal_pll_table |
| * @rate: pll rate |
| * @pdiv, @mdiv, @sdiv, @kdiv: for rate |
| */ |
| struct cmucal_pll_table { |
| unsigned int rate; |
| unsigned short pdiv; |
| unsigned short mdiv; |
| unsigned short sdiv; |
| signed short kdiv; |
| }; |
| |
| /* |
| * struct cmucal_pll |
| * @clk: cmucal_rate structure |
| * @type: pll type |
| * @rate_table: rate table |
| * @rate_count: number of rate_table |
| * @lock_time: integer PLL locktime |
| * @flock_time: fractional PLL locktime |
| */ |
| struct cmucal_pll { |
| struct cmucal_clk clk; |
| unsigned int umux; |
| unsigned int type; |
| struct cmucal_pll_table *rate_table; |
| unsigned int rate_count; |
| unsigned int lock_time; |
| unsigned int flock_time; |
| unsigned int p_idx, m_idx, s_idx, k_idx; |
| unsigned char p_shift, m_shift, s_shift, k_shift; |
| unsigned char p_width, m_width, s_width, k_width; |
| }; |
| |
| struct cmucal_clk_fixed_rate { |
| struct cmucal_clk clk; |
| unsigned int fixed_rate; |
| }; |
| |
| struct cmucal_clk_fixed_factor { |
| struct cmucal_clk clk; |
| unsigned short ratio; |
| }; |
| |
| struct cmucal_mux { |
| struct cmucal_clk clk; |
| unsigned int *pid; |
| unsigned char num_parents; |
| }; |
| |
| struct cmucal_div { |
| struct cmucal_clk clk; |
| }; |
| |
| struct cmucal_gate { |
| struct cmucal_clk clk; |
| }; |
| |
| struct cmucal_qch { |
| struct cmucal_clk clk; |
| union { |
| void __iomem *ignore; |
| unsigned long ignore_idx; |
| }; |
| unsigned char ig_shift; |
| unsigned char ig_width; |
| }; |
| |
| struct cmucal_option { |
| struct cmucal_clk clk; |
| }; |
| |
| struct cmucal_clkout { |
| struct cmucal_clk clk; |
| unsigned int sel; |
| unsigned int en; |
| }; |
| |
| #define CMUCAL_VCLK(_id, _lut, _list, _seq, _switch) \ |
| [_id & MASK_OF_ID] = { \ |
| .id = _id, \ |
| .name = #_id, \ |
| .lut = _lut, \ |
| .list = _list, \ |
| .seq = _seq, \ |
| .num_rates = (sizeof(_lut) / sizeof((_lut)[0])), \ |
| .num_list = (sizeof(_list) / sizeof((_list)[0])), \ |
| .switch_info = _switch, \ |
| .ops = NULL, \ |
| } |
| |
| #define CMUCAL_VCLK2(_id, _lut, _list, _seq, _switch) \ |
| [_id & MASK_OF_ID] = { \ |
| .id = _id, \ |
| .name = #_id, \ |
| .lut = NULL, \ |
| .list = _list, \ |
| .seq = _seq, \ |
| .num_rates = 0, \ |
| .num_list = (sizeof(_list) / sizeof((_list)[0])), \ |
| .switch_info = _switch, \ |
| .ops = NULL, \ |
| } |
| |
| #define CMUCAL_ACPM_VCLK(_id, _lut, _list, _seq, _switch, _margin_id) \ |
| [_id & MASK_OF_ID] = { \ |
| .id = _id, \ |
| .name = #_id, \ |
| .lut = _lut, \ |
| .list = _list, \ |
| .seq = _seq, \ |
| .num_rates = (sizeof(_lut) / sizeof((_lut)[0])), \ |
| .num_list = (sizeof(_list) / sizeof((_list)[0])), \ |
| .switch_info = _switch, \ |
| .ops = NULL, \ |
| .margin_id = _margin_id, \ |
| } |
| |
| #define CMUCAL_ACPM_VCLK2(_id, _lut, _list, _seq, _switch, _margin_id) \ |
| [_id & MASK_OF_ID] = { \ |
| .id = _id, \ |
| .name = #_id, \ |
| .lut = _lut, \ |
| .list = _list, \ |
| .seq = _seq, \ |
| .num_rates = 0, \ |
| .num_list = 0, \ |
| .switch_info = _switch, \ |
| .ops = NULL, \ |
| .margin_id = _margin_id, \ |
| } |
| |
| #define SFR_BLOCK(_id, _pa, _size) \ |
| [_id & MASK_OF_ID] = { \ |
| .id = _id, \ |
| .pa = _pa, \ |
| .size = _size, \ |
| } |
| |
| #define SFR(_id, _offset, _block) \ |
| [_id & MASK_OF_ID] = { \ |
| .id = _id, \ |
| .offset = _offset, \ |
| .block = _block, \ |
| } |
| |
| #define SFR_ACCESS(_id, _shift, _width, _sfr) \ |
| [_id & MASK_OF_ID] = { \ |
| .id = _id, \ |
| .shift = _shift, \ |
| .width = _width, \ |
| .sfr = _sfr, \ |
| } |
| |
| #define CLK_PLL(_typ, _id, _pid, _lock, _enable, _stable, \ |
| _p, _m, _s, _k, \ |
| _rtable, _time, _ftime) \ |
| [_id & MASK_OF_ID] = { \ |
| .clk.id = _id, \ |
| .clk.pid = EMPTY_CLK_ID, \ |
| .clk.name = #_id, \ |
| .clk.offset_idx = _lock, \ |
| .clk.enable_idx = _enable, \ |
| .clk.status_idx = _stable, \ |
| .p_idx = _p, \ |
| .m_idx = _m, \ |
| .s_idx = _s, \ |
| .k_idx = _k, \ |
| .type = _typ, \ |
| .umux = _pid, \ |
| .rate_table = _rtable, \ |
| .rate_count = (sizeof(_rtable) / sizeof((_rtable)[0])), \ |
| .lock_time = _time, \ |
| .flock_time = _ftime, \ |
| } |
| |
| #define CLK_MUX(_id, _pids, _o, _so, _eo) \ |
| [_id & MASK_OF_ID] = { \ |
| .clk.id = _id, \ |
| .clk.name = #_id, \ |
| .clk.offset_idx = _o, \ |
| .clk.status_idx = _so, \ |
| .clk.enable_idx = _eo, \ |
| .pid = _pids, \ |
| .num_parents = (sizeof(_pids) / sizeof((_pids)[0])), \ |
| } |
| |
| #define CLK_MUX2(_id, _pids, _o, _so, _eo) \ |
| [_id & MASK_OF_ID] = { \ |
| .clk.id = _id, \ |
| .clk.name = #_id, \ |
| .clk.offset_idx = _o, \ |
| .clk.status_idx = _so, \ |
| .clk.enable_idx = _eo, \ |
| .pid = NULL, \ |
| .num_parents = 0, \ |
| } |
| |
| #define CLK_DIV(_id, _pid, _o, _so, _eo) \ |
| [_id & MASK_OF_ID] = { \ |
| .clk.id = _id, \ |
| .clk.name = #_id, \ |
| .clk.pid = _pid, \ |
| .clk.offset_idx = _o, \ |
| .clk.status_idx = _so, \ |
| .clk.enable_idx = _eo, \ |
| } |
| |
| #define CLK_GATE(_id, _pid, _o, _so, _eo) \ |
| [_id & MASK_OF_ID] = { \ |
| .clk.id = _id, \ |
| .clk.name = #_id, \ |
| .clk.pid = _pid, \ |
| .clk.offset_idx = _o, \ |
| .clk.status_idx = _so, \ |
| .clk.enable_idx = _eo, \ |
| } |
| #ifdef CONFIG_CMUCAL_QCH_IGNORE_SUPPORT |
| #define CLK_QCH(_id, _o, _so, _eo, _ig) \ |
| [_id & MASK_OF_ID] = { \ |
| .clk.id = _id, \ |
| .clk.name = #_id, \ |
| .clk.pid = EMPTY_CLK_ID, \ |
| .clk.offset_idx = _o, \ |
| .clk.status_idx = _so, \ |
| .clk.enable_idx = _eo, \ |
| .ignore_idx = _ig, \ |
| } |
| #else |
| #define CLK_QCH(_id, _o, _so, _eo) \ |
| [_id & MASK_OF_ID] = { \ |
| .clk.id = _id, \ |
| .clk.name = #_id, \ |
| .clk.pid = EMPTY_CLK_ID, \ |
| .clk.offset_idx = _o, \ |
| .clk.status_idx = _so, \ |
| .clk.enable_idx = _eo, \ |
| } |
| #endif |
| #define CLK_OPTION(_id, _o, _eo) \ |
| [_id & MASK_OF_ID] = { \ |
| .clk.id = _id, \ |
| .clk.name = #_id, \ |
| .clk.pid = EMPTY_CLK_ID, \ |
| .clk.offset_idx = _o, \ |
| .clk.enable_idx = _eo, \ |
| } |
| |
| #define FIXEDRATE(_id, _frate, _eo) \ |
| [_id & MASK_OF_ID] = { \ |
| .clk.id = _id, \ |
| .clk.pid = EMPTY_CLK_ID, \ |
| .clk.name = #_id, \ |
| .clk.enable_idx = _eo, \ |
| .fixed_rate = _frate, \ |
| } |
| |
| #define FIXEDFACTOR(_id, _pid, _ratio, _eo) \ |
| [_id & MASK_OF_ID] = { \ |
| .clk.id = _id, \ |
| .clk.pid = _pid, \ |
| .clk.name = #_id, \ |
| .clk.enable_idx = _eo, \ |
| .ratio = _ratio, \ |
| } |
| |
| #define CLKOUT(_id, _o, _s, _w, _sel, _es, _ew, _en) \ |
| [_id & MASK_OF_ID] = { \ |
| .clk.id = _id, \ |
| .clk.name = #_id, \ |
| .clk.offset_idx = _o, \ |
| .clk.shift = _s, \ |
| .clk.width = _w, \ |
| .clk.e_shift = _es, \ |
| .clk.e_width = _ew, \ |
| .sel = _sel, \ |
| .en = _en, \ |
| } |
| |
| #define PLL_RATE_MPS(_rate, _m, _p, _s) \ |
| { \ |
| .rate = (_rate), \ |
| .mdiv = (_m), \ |
| .pdiv = (_p), \ |
| .sdiv = (_s), \ |
| .kdiv = (0), \ |
| } |
| |
| #define PLL_RATE_MPSK(_rate, _m, _p, _s, _k) \ |
| { \ |
| .rate = (_rate), \ |
| .mdiv = (_m), \ |
| .pdiv = (_p), \ |
| .sdiv = (_s), \ |
| .kdiv = (_k), \ |
| } |
| |
| #define to_fixed_rate_clk(_clk) container_of(_clk, struct cmucal_clk_fixed_rate, clk) |
| #define to_fixed_factor_clk(_clk) container_of(_clk, struct cmucal_clk_fixed_factor, clk) |
| #define to_pll_clk(_clk) container_of(_clk, struct cmucal_pll, clk) |
| #define to_mux_clk(_clk) container_of(_clk, struct cmucal_mux, clk) |
| #define to_div_clk(_clk) container_of(_clk, struct cmucal_div, clk) |
| #define to_gate_clk(_clk) container_of(_clk, struct cmucal_gate, clk) |
| #define to_clkout(_clk) container_of(_clk, struct cmucal_clkout, clk) |
| #define to_qch(_clk) container_of(_clk, struct cmucal_qch, clk) |
| |
| extern unsigned int cmucal_get_list_size(unsigned int type); |
| extern void *cmucal_get_node(unsigned int id); |
| extern void *cmucal_get_sfr_node(unsigned int id); |
| extern unsigned int cmucal_get_id(char *name); |
| extern unsigned int cmucal_get_id_by_addr(unsigned int addr); |
| extern void (*cal_data_init)(void); |
| #endif |