diff options
Diffstat (limited to 'drivers/clk/renesas/rzv2h-cpg.h')
| -rw-r--r-- | drivers/clk/renesas/rzv2h-cpg.h | 199 |
1 files changed, 186 insertions, 13 deletions
diff --git a/drivers/clk/renesas/rzv2h-cpg.h b/drivers/clk/renesas/rzv2h-cpg.h index 819029c81904..dc957bdaf5e9 100644 --- a/drivers/clk/renesas/rzv2h-cpg.h +++ b/drivers/clk/renesas/rzv2h-cpg.h @@ -8,6 +8,37 @@ #ifndef __RENESAS_RZV2H_CPG_H__ #define __RENESAS_RZV2H_CPG_H__ +#include <linux/bitfield.h> +#include <linux/types.h> + +/** + * struct pll - Structure for PLL configuration + * + * @offset: STBY register offset + * @has_clkn: Flag to indicate if CLK1/2 are accessible or not + * @instance: PLL instance number + */ +struct pll { + unsigned int offset:9; + unsigned int has_clkn:1; + unsigned int instance:2; + const struct rzv2h_pll_limits *limits; +}; + +#define PLL_PACK_LIMITS(_offset, _has_clkn, _instance, _limits) \ + ((struct pll){ \ + .offset = _offset, \ + .has_clkn = _has_clkn, \ + .instance = _instance, \ + .limits = _limits \ + }) + +#define PLL_PACK(_offset, _has_clkn, _instance) \ + PLL_PACK_LIMITS(_offset, _has_clkn, _instance, NULL) + +#define PLLCA55 PLL_PACK(0x60, 1, 0) +#define PLLGPU PLL_PACK(0x120, 1, 0) + /** * struct ddiv - Structure for dynamic switching divider * @@ -15,14 +46,25 @@ * @shift: position of the divider bit * @width: width of the divider * @monbit: monitor bit in CPG_CLKSTATUS0 register + * @no_rmw: flag to indicate if the register is read-modify-write + * (1: no RMW, 0: RMW) */ struct ddiv { unsigned int offset:11; unsigned int shift:4; unsigned int width:4; unsigned int monbit:5; + unsigned int no_rmw:1; }; +/* + * On RZ/V2H(P), the dynamic divider clock supports up to 19 monitor bits, + * while on RZ/G3E, it supports up to 16 monitor bits. Use the maximum value + * `0x1f` to indicate that monitor bits are not supported for static divider + * clocks. + */ +#define CSDIV_NO_MON (0x1f) + #define DDIV_PACK(_offset, _shift, _width, _monbit) \ ((struct ddiv){ \ .offset = _offset, \ @@ -31,14 +73,96 @@ struct ddiv { .monbit = _monbit \ }) +#define DDIV_PACK_NO_RMW(_offset, _shift, _width, _monbit) \ + ((struct ddiv){ \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + .monbit = (_monbit), \ + .no_rmw = 1 \ + }) + +/** + * struct smuxed - Structure for static muxed clocks + * + * @offset: register offset + * @shift: position of the divider field + * @width: width of the divider field + */ +struct smuxed { + unsigned int offset:11; + unsigned int shift:4; + unsigned int width:4; +}; + +#define SMUX_PACK(_offset, _shift, _width) \ + ((struct smuxed){ \ + .offset = (_offset), \ + .shift = (_shift), \ + .width = (_width), \ + }) + +/** + * struct fixed_mod_conf - Structure for fixed module configuration + * + * @mon_index: monitor index + * @mon_bit: monitor bit + */ +struct fixed_mod_conf { + u8 mon_index; + u8 mon_bit; +}; + +#define FIXED_MOD_CONF_PACK(_index, _bit) \ + ((struct fixed_mod_conf){ \ + .mon_index = (_index), \ + .mon_bit = (_bit), \ + }) + +#define CPG_SSEL0 (0x300) +#define CPG_SSEL1 (0x304) #define CPG_CDDIV0 (0x400) #define CPG_CDDIV1 (0x404) +#define CPG_CDDIV2 (0x408) +#define CPG_CDDIV3 (0x40C) +#define CPG_CDDIV4 (0x410) +#define CPG_CSDIV0 (0x500) +#define CPG_CSDIV1 (0x504) +#define CDDIV0_DIVCTL1 DDIV_PACK(CPG_CDDIV0, 4, 3, 1) #define CDDIV0_DIVCTL2 DDIV_PACK(CPG_CDDIV0, 8, 3, 2) #define CDDIV1_DIVCTL0 DDIV_PACK(CPG_CDDIV1, 0, 2, 4) #define CDDIV1_DIVCTL1 DDIV_PACK(CPG_CDDIV1, 4, 2, 5) #define CDDIV1_DIVCTL2 DDIV_PACK(CPG_CDDIV1, 8, 2, 6) #define CDDIV1_DIVCTL3 DDIV_PACK(CPG_CDDIV1, 12, 2, 7) +#define CDDIV2_DIVCTL3 DDIV_PACK(CPG_CDDIV2, 12, 3, 11) +#define CDDIV3_DIVCTL1 DDIV_PACK(CPG_CDDIV3, 4, 3, 13) +#define CDDIV3_DIVCTL2 DDIV_PACK(CPG_CDDIV3, 8, 3, 14) +#define CDDIV3_DIVCTL3 DDIV_PACK(CPG_CDDIV3, 12, 1, 15) +#define CDDIV4_DIVCTL0 DDIV_PACK(CPG_CDDIV4, 0, 1, 16) +#define CDDIV4_DIVCTL1 DDIV_PACK(CPG_CDDIV4, 4, 1, 17) +#define CDDIV4_DIVCTL2 DDIV_PACK(CPG_CDDIV4, 8, 1, 18) + +#define CSDIV0_DIVCTL0 DDIV_PACK(CPG_CSDIV0, 0, 2, CSDIV_NO_MON) +#define CSDIV0_DIVCTL1 DDIV_PACK(CPG_CSDIV0, 4, 2, CSDIV_NO_MON) +#define CSDIV0_DIVCTL2 DDIV_PACK(CPG_CSDIV0, 8, 2, CSDIV_NO_MON) +#define CSDIV0_DIVCTL3 DDIV_PACK_NO_RMW(CPG_CSDIV0, 12, 2, CSDIV_NO_MON) +#define CSDIV1_DIVCTL2 DDIV_PACK(CPG_CSDIV1, 8, 4, CSDIV_NO_MON) + +#define SSEL0_SELCTL2 SMUX_PACK(CPG_SSEL0, 8, 1) +#define SSEL0_SELCTL3 SMUX_PACK(CPG_SSEL0, 12, 1) +#define SSEL1_SELCTL0 SMUX_PACK(CPG_SSEL1, 0, 1) +#define SSEL1_SELCTL1 SMUX_PACK(CPG_SSEL1, 4, 1) +#define SSEL1_SELCTL2 SMUX_PACK(CPG_SSEL1, 8, 1) +#define SSEL1_SELCTL3 SMUX_PACK(CPG_SSEL1, 12, 1) + +#define BUS_MSTOP_IDX_MASK GENMASK(31, 16) +#define BUS_MSTOP_BITS_MASK GENMASK(15, 0) +#define BUS_MSTOP(idx, mask) (FIELD_PREP_CONST(BUS_MSTOP_IDX_MASK, (idx)) | \ + FIELD_PREP_CONST(BUS_MSTOP_BITS_MASK, (mask))) +#define BUS_MSTOP_NONE GENMASK(31, 0) + +#define FIXED_MOD_CONF_XSPI FIXED_MOD_CONF_PACK(5, 1) /** * Definitions of CPG Core Clocks @@ -58,8 +182,14 @@ struct cpg_core_clk { union { unsigned int conf; struct ddiv ddiv; + struct pll pll; + struct smuxed smux; + struct fixed_mod_conf fixed_mod; } cfg; const struct clk_div_table *dtable; + const char * const *parent_names; + unsigned int num_parents; + u8 mux_flags; u32 flag; }; @@ -67,70 +197,106 @@ enum clk_types { /* Generic */ CLK_TYPE_IN, /* External Clock Input */ CLK_TYPE_FF, /* Fixed Factor Clock */ + CLK_TYPE_FF_MOD_STATUS, /* Fixed Factor Clock which can report the status of module clock */ CLK_TYPE_PLL, CLK_TYPE_DDIV, /* Dynamic Switching Divider */ + CLK_TYPE_SMUX, /* Static Mux */ + CLK_TYPE_PLLDSI, /* PLLDSI */ + CLK_TYPE_PLLDSI_DIV, /* PLLDSI divider */ }; -/* BIT(31) indicates if CLK1/2 are accessible or not */ -#define PLL_CONF(n) (BIT(31) | ((n) & ~GENMASK(31, 16))) -#define PLL_CLK_ACCESS(n) ((n) & BIT(31) ? 1 : 0) -#define PLL_CLK1_OFFSET(n) ((n) & ~GENMASK(31, 16)) -#define PLL_CLK2_OFFSET(n) (((n) & ~GENMASK(31, 16)) + (0x4)) - #define DEF_TYPE(_name, _id, _type...) \ { .name = _name, .id = _id, .type = _type } #define DEF_BASE(_name, _id, _type, _parent...) \ DEF_TYPE(_name, _id, _type, .parent = _parent) -#define DEF_PLL(_name, _id, _parent, _conf) \ - DEF_TYPE(_name, _id, CLK_TYPE_PLL, .parent = _parent, .cfg.conf = _conf) +#define DEF_PLL(_name, _id, _parent, _pll_packed) \ + DEF_TYPE(_name, _id, CLK_TYPE_PLL, .parent = _parent, .cfg.pll = _pll_packed) #define DEF_INPUT(_name, _id) \ DEF_TYPE(_name, _id, CLK_TYPE_IN) #define DEF_FIXED(_name, _id, _parent, _mult, _div) \ DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult) +#define DEF_FIXED_MOD_STATUS(_name, _id, _parent, _mult, _div, _gate) \ + DEF_BASE(_name, _id, CLK_TYPE_FF_MOD_STATUS, _parent, .div = _div, \ + .mult = _mult, .cfg.fixed_mod = _gate) #define DEF_DDIV(_name, _id, _parent, _ddiv_packed, _dtable) \ DEF_TYPE(_name, _id, CLK_TYPE_DDIV, \ .cfg.ddiv = _ddiv_packed, \ .parent = _parent, \ .dtable = _dtable, \ .flag = CLK_DIVIDER_HIWORD_MASK) +#define DEF_CSDIV(_name, _id, _parent, _ddiv_packed, _dtable) \ + DEF_DDIV(_name, _id, _parent, _ddiv_packed, _dtable) +#define DEF_SMUX(_name, _id, _smux_packed, _parent_names) \ + DEF_TYPE(_name, _id, CLK_TYPE_SMUX, \ + .cfg.smux = _smux_packed, \ + .parent_names = _parent_names, \ + .num_parents = ARRAY_SIZE(_parent_names), \ + .flag = CLK_SET_RATE_PARENT, \ + .mux_flags = CLK_MUX_HIWORD_MASK) +#define DEF_PLLDSI(_name, _id, _parent, _pll_packed) \ + DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI, .parent = _parent, .cfg.pll = _pll_packed) +#define DEF_PLLDSI_DIV(_name, _id, _parent, _ddiv_packed, _dtable) \ + DEF_TYPE(_name, _id, CLK_TYPE_PLLDSI_DIV, \ + .cfg.ddiv = _ddiv_packed, \ + .dtable = _dtable, \ + .parent = _parent, \ + .flag = CLK_SET_RATE_PARENT) /** * struct rzv2h_mod_clk - Module Clocks definitions * * @name: handle between common and hardware-specific interfaces + * @mstop_data: packed data mstop register offset and mask * @parent: id of parent clock * @critical: flag to indicate the clock is critical + * @no_pm: flag to indicate PM is not supported * @on_index: control register index * @on_bit: ON bit * @mon_index: monitor register index * @mon_bit: monitor bit + * @ext_clk_mux_index: mux index for external clock source, or -1 if internal */ struct rzv2h_mod_clk { const char *name; + u32 mstop_data; u16 parent; bool critical; + bool no_pm; u8 on_index; u8 on_bit; s8 mon_index; u8 mon_bit; + s8 ext_clk_mux_index; }; -#define DEF_MOD_BASE(_name, _parent, _critical, _onindex, _onbit, _monindex, _monbit) \ +#define DEF_MOD_BASE(_name, _mstop, _parent, _critical, _no_pm, _onindex, \ + _onbit, _monindex, _monbit, _ext_clk_mux_index) \ { \ .name = (_name), \ + .mstop_data = (_mstop), \ .parent = (_parent), \ .critical = (_critical), \ + .no_pm = (_no_pm), \ .on_index = (_onindex), \ .on_bit = (_onbit), \ .mon_index = (_monindex), \ .mon_bit = (_monbit), \ + .ext_clk_mux_index = (_ext_clk_mux_index), \ } -#define DEF_MOD(_name, _parent, _onindex, _onbit, _monindex, _monbit) \ - DEF_MOD_BASE(_name, _parent, false, _onindex, _onbit, _monindex, _monbit) +#define DEF_MOD(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \ + DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex, _onbit, _monindex, _monbit, -1) + +#define DEF_MOD_CRITICAL(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \ + DEF_MOD_BASE(_name, _mstop, _parent, true, false, _onindex, _onbit, _monindex, _monbit, -1) + +#define DEF_MOD_NO_PM(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop) \ + DEF_MOD_BASE(_name, _mstop, _parent, false, true, _onindex, _onbit, _monindex, _monbit, -1) -#define DEF_MOD_CRITICAL(_name, _parent, _onindex, _onbit, _monindex, _monbit) \ - DEF_MOD_BASE(_name, _parent, true, _onindex, _onbit, _monindex, _monbit) +#define DEF_MOD_MUX_EXTERNAL(_name, _parent, _onindex, _onbit, _monindex, _monbit, _mstop, \ + _ext_clk_mux_index) \ + DEF_MOD_BASE(_name, _mstop, _parent, false, false, _onindex, _onbit, _monindex, _monbit, \ + _ext_clk_mux_index) /** * struct rzv2h_reset - Reset definitions @@ -172,6 +338,9 @@ struct rzv2h_reset { * * @resets: Array of Module Reset definitions * @num_resets: Number of entries in resets[] + * + * @num_mstop_bits: Maximum number of MSTOP bits supported, equivalent to the + * number of CPG_BUS_m_MSTOP registers multiplied by 16. */ struct rzv2h_cpg_info { /* Core Clocks */ @@ -188,8 +357,12 @@ struct rzv2h_cpg_info { /* Resets */ const struct rzv2h_reset *resets; unsigned int num_resets; + + unsigned int num_mstop_bits; }; +extern const struct rzv2h_cpg_info r9a09g047_cpg_info; +extern const struct rzv2h_cpg_info r9a09g056_cpg_info; extern const struct rzv2h_cpg_info r9a09g057_cpg_info; #endif /* __RENESAS_RZV2H_CPG_H__ */ |
