From 1a3f02b5a3fbf8b3fe3252ac5486b89be57ee50a Mon Sep 17 00:00:00 2001 From: Rajan Vaja Date: Wed, 17 Jan 2018 02:39:26 -0800 Subject: [PATCH] zynqmp: pm: Implement clock APIs - Add clock entries and information to clock database. - Implement APIs to provide clock topology and other information to caller. - Implement APIs to control clocks and PLLs. Signed-off-by: Rajan Vaja Signed-off-by: Jolly Shah --- plat/xilinx/zynqmp/pm_service/pm_api_clock.c | 2853 +++++++++++++++++- plat/xilinx/zynqmp/pm_service/pm_api_clock.h | 256 ++ plat/xilinx/zynqmp/zynqmp_def.h | 80 +- 3 files changed, 3171 insertions(+), 18 deletions(-) diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c index 4096a8170..438bba146 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c @@ -20,6 +20,161 @@ #define CLK_NODE_MAX 6 +#define CLK_PARENTS_ID_LEN 16 +#define CLK_TOPOLOGY_NODE_OFFSET 16 +#define CLK_TOPOLOGY_PAYLOAD_LEN 12 +#define CLK_PARENTS_PAYLOAD_LEN 12 +#define CLK_INIT_ENABLE_SHIFT 1 +#define CLK_TYPE_SHIFT 2 +#define CLK_CLKFLAGS_SHIFT 8 +#define CLK_TYPEFLAGS_SHIFT 24 + +#define CLK_EXTERNAL_PARENT (PARENT_CLK_EXTERNAL << CLK_PARENTS_ID_LEN) + +#define NA_MULT 0 +#define NA_DIV 0 +#define NA_SHIFT 0 +#define NA_WIDTH 0 +#define NA_CLK_FLAGS 0 +#define NA_TYPE_FLAGS 0 + +/* PLL nodes related definitions */ +#define PLL_PRESRC_MUX_SHIFT 20 +#define PLL_PRESRC_MUX_WIDTH 3 +#define PLL_POSTSRC_MUX_SHIFT 24 +#define PLL_POSTSRC_MUX_WIDTH 3 +#define PLL_DIV2_MUX_SHIFT 16 +#define PLL_DIV2_MUX_WIDTH 1 +#define PLL_BYPASS_MUX_SHIFT 3 +#define PLL_BYPASS_MUX_WIDTH 1 + +/* Peripheral nodes related definitions */ +/* Peripheral Clocks */ +#define PERIPH_MUX_SHIFT 0 +#define PERIPH_MUX_WIDTH 3 +#define PERIPH_DIV1_SHIFT 8 +#define PERIPH_DIV1_WIDTH 6 +#define PERIPH_DIV2_SHIFT 16 +#define PERIPH_DIV2_WIDTH 6 +#define PERIPH_GATE_SHIFT 24 +#define PERIPH_GATE_WIDTH 1 + +#define USB_GATE_SHIFT 25 + +/* External clock related definitions */ + +#define EXT_CLK_MIO_DATA(mio) \ + [EXT_CLK_INDEX(EXT_CLK_MIO##mio)] = { \ + .name = "mio_clk_"#mio, \ + } + +#define EXT_CLK_INDEX(n) (n - CLK_MAX_OUTPUT_CLK) + +/* Clock control related definitions */ +#define BIT_MASK(x, y) (((1U << (y)) - 1) << (x)) + +#define ISPLL(id) (((id) == CLK_APLL_INT || \ + (id) == CLK_DPLL_INT || \ + (id) == CLK_VPLL_INT || \ + (id) == CLK_IOPLL_INT || \ + (id) == CLK_RPLL_INT) ? 1 : 0) + +#define PLLCTRL_BP_MASK BIT(3) +#define PLLCTRL_RESET_MASK 1 +#define PLL_FRAC_OFFSET 8 +#define PLL_FRAC_MODE 1 +#define PLL_INT_MODE 0 +#define PLL_FRAC_MODE_MASK 0x80000000 +#define PLL_FRAC_MODE_SHIFT 31 +#define PLL_FRAC_DATA_MASK 0xFFFF +#define PLL_FRAC_DATA_SHIFT 0 +#define PLL_FBDIV_MASK 0x7F00 +#define PLL_FBDIV_WIDTH 7 +#define PLL_FBDIV_SHIFT 8 + +#define CLK_PLL_RESET_ASSERT 1 +#define CLK_PLL_RESET_RELEASE 2 +#define CLK_PLL_RESET_PULSE (CLK_PLL_RESET_ASSERT | CLK_PLL_RESET_RELEASE) + +/* Common topology definitions */ +#define GENERIC_MUX \ + { \ + .type = TYPE_MUX, \ + .offset = PERIPH_MUX_SHIFT, \ + .width = PERIPH_MUX_WIDTH, \ + .clkflags = CLK_SET_RATE_NO_REPARENT | \ + CLK_IS_BASIC, \ + .typeflags = NA_TYPE_FLAGS, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define IGNORE_UNUSED_MUX \ + { \ + .type = TYPE_MUX, \ + .offset = PERIPH_MUX_SHIFT, \ + .width = PERIPH_MUX_WIDTH, \ + .clkflags = CLK_IGNORE_UNUSED | \ + CLK_SET_RATE_NO_REPARENT | \ + CLK_IS_BASIC, \ + .typeflags = NA_TYPE_FLAGS, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define GENERIC_DIV(id) \ + { \ + .type = TYPE_DIV##id, \ + .offset = PERIPH_DIV##id##_SHIFT, \ + .width = PERIPH_DIV##id##_WIDTH, \ + .clkflags = CLK_SET_RATE_NO_REPARENT | \ + CLK_IS_BASIC, \ + .typeflags = CLK_DIVIDER_ONE_BASED | \ + CLK_DIVIDER_ALLOW_ZERO, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define IGNORE_UNUSED_DIV(id) \ + { \ + .type = TYPE_DIV##id, \ + .offset = PERIPH_DIV##id##_SHIFT, \ + .width = PERIPH_DIV##id##_WIDTH, \ + .clkflags = CLK_IGNORE_UNUSED | \ + CLK_SET_RATE_NO_REPARENT | \ + CLK_IS_BASIC, \ + .typeflags = CLK_DIVIDER_ONE_BASED | \ + CLK_DIVIDER_ALLOW_ZERO, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define GENERIC_GATE \ + { \ + .type = TYPE_GATE, \ + .offset = PERIPH_GATE_SHIFT, \ + .width = PERIPH_GATE_WIDTH, \ + .clkflags = CLK_SET_RATE_PARENT | \ + CLK_SET_RATE_GATE | \ + CLK_IS_BASIC, \ + .typeflags = NA_TYPE_FLAGS, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + +#define IGNORE_UNUSED_GATE \ + { \ + .type = TYPE_GATE, \ + .offset = PERIPH_GATE_SHIFT, \ + .width = PERIPH_GATE_WIDTH, \ + .clkflags = CLK_SET_RATE_PARENT | \ + CLK_IGNORE_UNUSED | \ + CLK_IS_BASIC, \ + .typeflags = NA_TYPE_FLAGS, \ + .mult = NA_MULT, \ + .div = NA_DIV, \ + } + /** * struct pm_clock_node - Clock topology node information * @type: Topology type (mux/div1/div2/gate/pll/fixed factor) @@ -58,8 +213,2096 @@ struct pm_clock { struct pm_clock_node(*nodes)[]; }; +/** + * struct pm_clock - Clock structure + * @name: Clock name + */ +struct pm_ext_clock { + char name[CLK_NAME_LEN]; +}; + +/* PLL Clocks */ +static struct pm_clock_node generic_pll_nodes[] = { + { + .type = TYPE_PLL, + .offset = NA_SHIFT, + .width = NA_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node ignore_unused_pll_nodes[] = { + { + .type = TYPE_PLL, + .offset = NA_SHIFT, + .width = NA_WIDTH, + .clkflags = CLK_IGNORE_UNUSED | CLK_SET_RATE_NO_REPARENT, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_pll_pre_src_nodes[] = { + { + .type = TYPE_MUX, + .offset = PLL_PRESRC_MUX_SHIFT, + .width = PLL_PRESRC_MUX_WIDTH, + .clkflags = CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_pll_half_nodes[] = { + { + .type = TYPE_FIXEDFACTOR, + .offset = NA_SHIFT, + .width = NA_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, + .typeflags = NA_TYPE_FLAGS, + .mult = 1, + .div = 2, + }, +}; + +static struct pm_clock_node generic_pll_int_nodes[] = { + { + .type = TYPE_MUX, + .offset = PLL_DIV2_MUX_SHIFT, + .width = PLL_DIV2_MUX_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | + CLK_SET_RATE_PARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_pll_post_src_nodes[] = { + { + .type = TYPE_MUX, + .offset = PLL_POSTSRC_MUX_SHIFT, + .width = PLL_POSTSRC_MUX_WIDTH, + .clkflags = CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_pll_system_nodes[] = { + { + .type = TYPE_MUX, + .offset = PLL_BYPASS_MUX_SHIFT, + .width = PLL_BYPASS_MUX_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | + CLK_SET_RATE_PARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node acpu_nodes[] = { + { + .type = TYPE_MUX, + .offset = PERIPH_MUX_SHIFT, + .width = PERIPH_MUX_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_DIV1, + .offset = PERIPH_DIV1_SHIFT, + .width = PERIPH_DIV1_WIDTH, + .clkflags = CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_GATE, + .offset = PERIPH_GATE_SHIFT, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | + CLK_IGNORE_UNUSED | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_mux_div_nodes[] = { + GENERIC_MUX, + GENERIC_DIV(1), +}; + +static struct pm_clock_node generic_mux_div_gate_nodes[] = { + GENERIC_MUX, + GENERIC_DIV(1), + GENERIC_GATE, +}; + +static struct pm_clock_node generic_mux_div_unused_gate_nodes[] = { + GENERIC_MUX, + GENERIC_DIV(1), + IGNORE_UNUSED_GATE, +}; + +static struct pm_clock_node generic_mux_div_div_gate_nodes[] = { + GENERIC_MUX, + GENERIC_DIV(1), + GENERIC_DIV(2), + GENERIC_GATE, +}; + +static struct pm_clock_node dp_audio_video_ref_nodes[] = { + { + .type = TYPE_MUX, + .offset = PERIPH_MUX_SHIFT, + .width = PERIPH_MUX_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | + CLK_SET_RATE_PARENT | + CLK_FRAC | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_DIV1, + .offset = PERIPH_DIV1_SHIFT, + .width = PERIPH_DIV1_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT | + CLK_FRAC | CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_DIV2, + .offset = PERIPH_DIV2_SHIFT, + .width = PERIPH_DIV2_WIDTH, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT | + CLK_FRAC | CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_GATE, + .offset = PERIPH_GATE_SHIFT, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_GATE | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node usb_nodes[] = { + GENERIC_MUX, + GENERIC_DIV(1), + GENERIC_DIV(2), + { + .type = TYPE_GATE, + .offset = USB_GATE_SHIFT, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC | + CLK_SET_RATE_GATE, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node generic_domain_crossing_nodes[] = { + { + .type = TYPE_DIV1, + .offset = 8, + .width = 6, + .clkflags = CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node rpll_to_fpd_nodes[] = { + { + .type = TYPE_DIV1, + .offset = 8, + .width = 6, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node acpu_half_nodes[] = { + { + .type = TYPE_FIXEDFACTOR, + .offset = 0, + .width = 1, + .clkflags = 0, + .typeflags = 0, + .mult = 1, + .div = 2, + }, + { + .type = TYPE_GATE, + .offset = 25, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node wdt_nodes[] = { + { + .type = TYPE_MUX, + .offset = 0, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node ddr_nodes[] = { + GENERIC_MUX, + { + .type = TYPE_DIV1, + .offset = 8, + .width = 6, + .clkflags = CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node pl_nodes[] = { + GENERIC_MUX, + { + .type = TYPE_DIV1, + .offset = PERIPH_DIV1_SHIFT, + .width = PERIPH_DIV1_WIDTH, + .clkflags = CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_DIV2, + .offset = PERIPH_DIV2_SHIFT, + .width = PERIPH_DIV2_WIDTH, + .clkflags = CLK_IS_BASIC | CLK_SET_RATE_PARENT, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_GATE, + .offset = PERIPH_GATE_SHIFT, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gpu_pp0_nodes[] = { + { + .type = TYPE_GATE, + .offset = 25, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gpu_pp1_nodes[] = { + { + .type = TYPE_GATE, + .offset = 26, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem_nodes[] = { + GENERIC_MUX, + { + .type = TYPE_DIV1, + .offset = 8, + .width = 6, + .clkflags = CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_DIV2, + .offset = 16, + .width = 6, + .clkflags = CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_GATE, + .offset = 25, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem0_tx_nodes[] = { + { + .type = TYPE_MUX, + .offset = 1, + .width = 1, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_GATE, + .offset = 26, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem1_tx_nodes[] = { + { + .type = TYPE_MUX, + .offset = 6, + .width = 1, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_GATE, + .offset = 26, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem2_tx_nodes[] = { + { + .type = TYPE_MUX, + .offset = 11, + .width = 1, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_GATE, + .offset = 26, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem3_tx_nodes[] = { + { + .type = TYPE_MUX, + .offset = 16, + .width = 1, + .clkflags = CLK_SET_RATE_NO_REPARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, + { + .type = TYPE_GATE, + .offset = 26, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_SET_RATE_PARENT | CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node gem_tsu_nodes[] = { + { + .type = TYPE_MUX, + .offset = 20, + .width = 2, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node can0_mio_nodes[] = { + { + .type = TYPE_MUX, + .offset = 0, + .width = 7, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node can1_mio_nodes[] = { + { + .type = TYPE_MUX, + .offset = 15, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node can0_nodes[] = { + { + .type = TYPE_MUX, + .offset = 7, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node can1_nodes[] = { + { + .type = TYPE_MUX, + .offset = 22, + .width = 1, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node cpu_r5_core_nodes[] = { + { + .type = TYPE_GATE, + .offset = 25, + .width = PERIPH_GATE_WIDTH, + .clkflags = CLK_IGNORE_UNUSED | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node dll_ref_nodes[] = { + { + .type = TYPE_MUX, + .offset = 0, + .width = 3, + .clkflags = CLK_SET_RATE_PARENT | + CLK_SET_RATE_NO_REPARENT | + CLK_IS_BASIC, + .typeflags = NA_TYPE_FLAGS, + .mult = NA_MULT, + .div = NA_DIV, + }, +}; + +static struct pm_clock_node timestamp_ref_nodes[] = { + GENERIC_MUX, + { + .type = TYPE_DIV1, + .offset = 8, + .width = 6, + .clkflags = CLK_IS_BASIC, + .typeflags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + .mult = NA_MULT, + .div = NA_DIV, + }, + IGNORE_UNUSED_GATE, +}; + +static int32_t can_mio_parents[] = { + EXT_CLK_MIO0, EXT_CLK_MIO1, EXT_CLK_MIO2, EXT_CLK_MIO3, + EXT_CLK_MIO4, EXT_CLK_MIO5, EXT_CLK_MIO6, EXT_CLK_MIO7, + EXT_CLK_MIO8, EXT_CLK_MIO9, EXT_CLK_MIO10, EXT_CLK_MIO11, + EXT_CLK_MIO12, EXT_CLK_MIO13, EXT_CLK_MIO14, EXT_CLK_MIO15, + EXT_CLK_MIO16, EXT_CLK_MIO17, EXT_CLK_MIO18, EXT_CLK_MIO19, + EXT_CLK_MIO20, EXT_CLK_MIO21, EXT_CLK_MIO22, EXT_CLK_MIO23, + EXT_CLK_MIO24, EXT_CLK_MIO25, EXT_CLK_MIO26, EXT_CLK_MIO27, + EXT_CLK_MIO28, EXT_CLK_MIO29, EXT_CLK_MIO30, EXT_CLK_MIO31, + EXT_CLK_MIO32, EXT_CLK_MIO33, EXT_CLK_MIO34, EXT_CLK_MIO35, + EXT_CLK_MIO36, EXT_CLK_MIO37, EXT_CLK_MIO38, EXT_CLK_MIO39, + EXT_CLK_MIO40, EXT_CLK_MIO41, EXT_CLK_MIO42, EXT_CLK_MIO43, + EXT_CLK_MIO44, EXT_CLK_MIO45, EXT_CLK_MIO46, EXT_CLK_MIO47, + EXT_CLK_MIO48, EXT_CLK_MIO49, EXT_CLK_MIO50, EXT_CLK_MIO51, + EXT_CLK_MIO52, EXT_CLK_MIO53, EXT_CLK_MIO54, EXT_CLK_MIO55, + EXT_CLK_MIO56, EXT_CLK_MIO57, EXT_CLK_MIO58, EXT_CLK_MIO59, + EXT_CLK_MIO60, EXT_CLK_MIO61, EXT_CLK_MIO62, EXT_CLK_MIO63, + EXT_CLK_MIO64, EXT_CLK_MIO65, EXT_CLK_MIO66, EXT_CLK_MIO67, + EXT_CLK_MIO68, EXT_CLK_MIO69, EXT_CLK_MIO70, EXT_CLK_MIO71, + EXT_CLK_MIO72, EXT_CLK_MIO73, EXT_CLK_MIO74, EXT_CLK_MIO75, + EXT_CLK_MIO76, EXT_CLK_MIO77, CLK_NA_PARENT +}; + /* Clock array containing clock informaton */ -struct pm_clock clocks[] = {0}; +static struct pm_clock clocks[] = { + [CLK_APLL_INT] = { + .name = "apll_int", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_APLL_PRE_SRC, CLK_NA_PARENT}), + .nodes = &ignore_unused_pll_nodes, + .num_nodes = ARRAY_SIZE(ignore_unused_pll_nodes), + }, + [CLK_APLL_PRE_SRC] = { + .name = "apll_pre_src", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_pre_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes), + }, + [CLK_APLL_HALF] = { + .name = "apll_half", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_APLL_INT, CLK_NA_PARENT}), + .nodes = &generic_pll_half_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_half_nodes), + }, + [CLK_APLL_INT_MUX] = { + .name = "apll_int_mux", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_APLL_INT, + CLK_APLL_HALF, + CLK_NA_PARENT + }), + .nodes = &generic_pll_int_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_int_nodes), + }, + [CLK_APLL_POST_SRC] = { + .name = "apll_post_src", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_post_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes), + }, + [CLK_APLL] = { + .name = "apll", + .control_reg = CRF_APB_APLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_APLL_INT_MUX, + CLK_APLL_POST_SRC, + CLK_NA_PARENT + }), + .nodes = &generic_pll_system_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_system_nodes), + }, + [CLK_DPLL_INT] = { + .name = "dpll_int", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_DPLL_PRE_SRC, CLK_NA_PARENT}), + .nodes = &generic_pll_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_nodes), + }, + [CLK_DPLL_PRE_SRC] = { + .name = "dpll_pre_src", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_pre_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes), + }, + [CLK_DPLL_HALF] = { + .name = "dpll_half", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_DPLL_INT, CLK_NA_PARENT}), + .nodes = &generic_pll_half_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_half_nodes), + }, + [CLK_DPLL_INT_MUX] = { + .name = "dpll_int_mux", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_DPLL_INT, + CLK_DPLL_HALF, + CLK_NA_PARENT + }), + .nodes = &generic_pll_int_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_int_nodes), + }, + [CLK_DPLL_POST_SRC] = { + .name = "dpll_post_src", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_post_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes), + }, + [CLK_DPLL] = { + .name = "dpll", + .control_reg = CRF_APB_DPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_DPLL_INT_MUX, + CLK_DPLL_POST_SRC, + CLK_NA_PARENT + }), + .nodes = &generic_pll_system_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_system_nodes), + }, + [CLK_VPLL_INT] = { + .name = "vpll_int", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_VPLL_PRE_SRC, CLK_NA_PARENT}), + .nodes = &ignore_unused_pll_nodes, + .num_nodes = ARRAY_SIZE(ignore_unused_pll_nodes), + }, + [CLK_VPLL_PRE_SRC] = { + .name = "vpll_pre_src", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_pre_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes), + }, + [CLK_VPLL_HALF] = { + .name = "vpll_half", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_VPLL_INT, CLK_NA_PARENT}), + .nodes = &generic_pll_half_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_half_nodes), + }, + [CLK_VPLL_INT_MUX] = { + .name = "vpll_int_mux", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_VPLL_INT, + CLK_VPLL_HALF, + CLK_NA_PARENT + }), + .nodes = &generic_pll_int_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_int_nodes), + }, + [CLK_VPLL_POST_SRC] = { + .name = "vpll_post_src", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_post_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes), + }, + [CLK_VPLL] = { + .name = "vpll", + .control_reg = CRF_APB_VPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_VPLL_INT_MUX, + CLK_VPLL_POST_SRC, + CLK_NA_PARENT + }), + .nodes = &generic_pll_system_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_system_nodes), + }, + [CLK_IOPLL_INT] = { + .name = "iopll_int", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_IOPLL_PRE_SRC, CLK_NA_PARENT}), + .nodes = &generic_pll_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_nodes), + }, + [CLK_IOPLL_PRE_SRC] = { + .name = "iopll_pre_src", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_pre_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes), + }, + [CLK_IOPLL_HALF] = { + .name = "iopll_half", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_IOPLL_INT, CLK_NA_PARENT}), + .nodes = &generic_pll_half_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_half_nodes), + }, + [CLK_IOPLL_INT_MUX] = { + .name = "iopll_int_mux", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_IOPLL_INT, + CLK_IOPLL_HALF, + CLK_NA_PARENT + }), + .nodes = &generic_pll_int_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_int_nodes), + }, + [CLK_IOPLL_POST_SRC] = { + .name = "iopll_post_src", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_post_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes), + }, + [CLK_IOPLL] = { + .name = "iopll", + .control_reg = CRL_APB_IOPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_IOPLL_INT_MUX, + CLK_IOPLL_POST_SRC, + CLK_NA_PARENT + }), + .nodes = &generic_pll_system_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_system_nodes), + }, + [CLK_RPLL_INT] = { + .name = "rpll_int", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_RPLL_PRE_SRC, CLK_NA_PARENT}), + .nodes = &generic_pll_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_nodes), + }, + [CLK_RPLL_PRE_SRC] = { + .name = "rpll_pre_src", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + + .nodes = &generic_pll_pre_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_pre_src_nodes), + }, + [CLK_RPLL_HALF] = { + .name = "rpll_half", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) {CLK_RPLL_INT, CLK_NA_PARENT}), + .nodes = &generic_pll_half_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_half_nodes), + }, + [CLK_RPLL_INT_MUX] = { + .name = "rpll_int_mux", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_RPLL_INT, + CLK_RPLL_HALF, + CLK_NA_PARENT + }), + .nodes = &generic_pll_int_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_int_nodes), + }, + [CLK_RPLL_POST_SRC] = { + .name = "rpll_post_src", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRF_APB_PLL_STATUS, + .parents = &((int32_t []) { + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_VIDEO | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_ALT_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_AUX_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_GT_CRX_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &generic_pll_post_src_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_post_src_nodes), + }, + [CLK_RPLL] = { + .name = "rpll", + .control_reg = CRL_APB_RPLL_CTRL, + .status_reg = CRL_APB_PLL_STATUS, + .parents = &((int32_t []) { + CLK_RPLL_INT_MUX, + CLK_RPLL_POST_SRC, + CLK_NA_PARENT + }), + .nodes = &generic_pll_system_nodes, + .num_nodes = ARRAY_SIZE(generic_pll_system_nodes), + }, + /* Peripheral Clocks */ + [CLK_ACPU] = { + .name = "acpu", + .control_reg = CRF_APB_ACPU_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_APLL, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_VPLL, + CLK_NA_PARENT + }), + .nodes = &acpu_nodes, + .num_nodes = ARRAY_SIZE(acpu_nodes), + }, + [CLK_DBG_TRACE] = { + .name = "dbg_trace", + .control_reg = CRF_APB_DBG_TRACE_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_APLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_DBG_FPD] = { + .name = "dbg_fpd", + .control_reg = CRF_APB_DBG_FPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_APLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_DBG_TSTMP] = { + .name = "dbg_tstmp", + .control_reg = CRF_APB_DBG_TSTMP_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_APLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_nodes), + }, + [CLK_DP_VIDEO_REF] = { + .name = "dp_video_ref", + .control_reg = CRF_APB_DP_VIDEO_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_VPLL, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_RPLL_TO_FPD, + CLK_NA_PARENT + }), + .nodes = &dp_audio_video_ref_nodes, + .num_nodes = ARRAY_SIZE(dp_audio_video_ref_nodes), + }, + [CLK_DP_AUDIO_REF] = { + .name = "dp_audio_ref", + .control_reg = CRF_APB_DP_AUDIO_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_VPLL, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_RPLL_TO_FPD, + CLK_NA_PARENT + }), + .nodes = &dp_audio_video_ref_nodes, + .num_nodes = ARRAY_SIZE(dp_audio_video_ref_nodes), + }, + [CLK_DP_STC_REF] = { + .name = "dp_stc_ref", + .control_reg = CRF_APB_DP_STC_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_VPLL, + CLK_DUMMY_PARENT, + CLK_DPLL, + CLK_RPLL_TO_FPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_DPDMA_REF] = { + .name = "dpdma_ref", + .control_reg = CRF_APB_DPDMA_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_APLL, + CLK_DUMMY_PARENT, + CLK_VPLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_DDR_REF] = { + .name = "ddr_ref", + .control_reg = CRF_APB_DDR_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_DPLL, + CLK_VPLL, + CLK_NA_PARENT + }), + .nodes = &ddr_nodes, + .num_nodes = ARRAY_SIZE(ddr_nodes), + }, + [CLK_GPU_REF] = { + .name = "gpu_ref", + .control_reg = CRF_APB_GPU_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_VPLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_SATA_REF] = { + .name = "sata_ref", + .control_reg = CRF_APB_SATA_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_APLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_PCIE_REF] = { + .name = "pcie_ref", + .control_reg = CRF_APB_PCIE_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_RPLL_TO_FPD, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_GDMA_REF] = { + .name = "gdma_ref", + .control_reg = CRF_APB_GDMA_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_APLL, + CLK_DUMMY_PARENT, + CLK_VPLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_GTGREF0_REF] = { + .name = "gtgref0_ref", + .control_reg = CRF_APB_GTGREF0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL_TO_FPD, + CLK_DUMMY_PARENT, + CLK_APLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_TOPSW_MAIN] = { + .name = "topsw_main", + .control_reg = CRF_APB_TOPSW_MAIN_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_APLL, + CLK_DUMMY_PARENT, + CLK_VPLL, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_TOPSW_LSBUS] = { + .name = "topsw_lsbus", + .control_reg = CRF_APB_TOPSW_LSBUS_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_APLL, + CLK_DUMMY_PARENT, + CLK_IOPLL_TO_FPD, + CLK_DPLL, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_IOU_SWITCH] = { + .name = "iou_switch", + .control_reg = CRL_APB_IOU_SWITCH_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_GEM0_REF] = { + .name = "gem0_ref", + .control_reg = CRL_APB_GEM0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &gem_nodes, + .num_nodes = ARRAY_SIZE(gem_nodes), + }, + [CLK_GEM1_REF] = { + .name = "gem1_ref", + .control_reg = CRL_APB_GEM1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &gem_nodes, + .num_nodes = ARRAY_SIZE(gem_nodes), + }, + [CLK_GEM2_REF] = { + .name = "gem2_ref", + .control_reg = CRL_APB_GEM2_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &gem_nodes, + .num_nodes = ARRAY_SIZE(gem_nodes), + }, + [CLK_GEM3_REF] = { + .name = "gem3_ref", + .control_reg = CRL_APB_GEM3_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &gem_nodes, + .num_nodes = ARRAY_SIZE(gem_nodes), + }, + [CLK_USB0_BUS_REF] = { + .name = "usb0_bus_ref", + .control_reg = CRL_APB_USB0_BUS_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &usb_nodes, + .num_nodes = ARRAY_SIZE(usb_nodes), + }, + [CLK_USB1_BUS_REF] = { + .name = "usb1_bus_ref", + .control_reg = CRL_APB_USB1_BUS_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &usb_nodes, + .num_nodes = ARRAY_SIZE(usb_nodes), + }, + [CLK_USB3_DUAL_REF] = { + .name = "usb3_dual_ref", + .control_reg = CRL_APB_USB3_DUAL_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &usb_nodes, + .num_nodes = ARRAY_SIZE(usb_nodes), + }, + [CLK_QSPI_REF] = { + .name = "qspi_ref", + .control_reg = CRL_APB_QSPI_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_SDIO0_REF] = { + .name = "sdio0_ref", + .control_reg = CRL_APB_SDIO0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_VPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_SDIO1_REF] = { + .name = "sdio1_ref", + .control_reg = CRL_APB_SDIO1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_VPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_UART0_REF] = { + .name = "uart0_ref", + .control_reg = CRL_APB_UART0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_UART1_REF] = { + .name = "uart1_ref", + .control_reg = CRL_APB_UART1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_SPI0_REF] = { + .name = "spi0_ref", + .control_reg = CRL_APB_SPI0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_SPI1_REF] = { + .name = "spi1_ref", + .control_reg = CRL_APB_SPI1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_CAN0_REF] = { + .name = "can0_ref", + .control_reg = CRL_APB_CAN0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_CAN1_REF] = { + .name = "can1_ref", + .control_reg = CRL_APB_CAN1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_NAND_REF] = { + .name = "nand_ref", + .control_reg = CRL_APB_NAND_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_GEM_TSU_REF] = { + .name = "gem_tsu_ref", + .control_reg = CRL_APB_GEM_TSU_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_DLL_REF] = { + .name = "dll_ref", + .control_reg = CRL_APB_DLL_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_RPLL, + CLK_NA_PARENT + }), + .nodes = &dll_ref_nodes, + .num_nodes = ARRAY_SIZE(dll_ref_nodes), + }, + [CLK_ADMA_REF] = { + .name = "adma_ref", + .control_reg = CRL_APB_ADMA_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_DBG_LPD] = { + .name = "dbg_lpd", + .control_reg = CRL_APB_DBG_LPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_CPU_R5] = { + .name = "cpu_r5", + .control_reg = CRL_APB_CPU_R5_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_CSU_PLL] = { + .name = "csu_pll", + .control_reg = CRL_APB_CSU_PLL_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_PCAP] = { + .name = "pcap", + .control_reg = CRL_APB_PCAP_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_gate_nodes), + }, + [CLK_LPD_LSBUS] = { + .name = "lpd_lsbus", + .control_reg = CRL_APB_LPD_LSBUS_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_LPD_SWITCH] = { + .name = "lpd_switch", + .control_reg = CRL_APB_LPD_SWITCH_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_unused_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_unused_gate_nodes), + }, + [CLK_I2C0_REF] = { + .name = "i2c0_ref", + .control_reg = CRL_APB_I2C0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_I2C1_REF] = { + .name = "i2c1_ref", + .control_reg = CRL_APB_I2C1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_TIMESTAMP_REF] = { + .name = "timestamp_ref", + .control_reg = CRL_APB_TIMESTAMP_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + EXT_CLK_PSS_REF | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = ×tamp_ref_nodes, + .num_nodes = ARRAY_SIZE(timestamp_ref_nodes), + }, + [CLK_PL0_REF] = { + .name = "pl0_ref", + .control_reg = CRL_APB_PL0_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &pl_nodes, + .num_nodes = ARRAY_SIZE(pl_nodes), + }, + [CLK_PL1_REF] = { + .name = "pl1_ref", + .control_reg = CRL_APB_PL1_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &pl_nodes, + .num_nodes = ARRAY_SIZE(pl_nodes), + }, + [CLK_PL2_REF] = { + .name = "pl2_ref", + .control_reg = CRL_APB_PL2_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &pl_nodes, + .num_nodes = ARRAY_SIZE(pl_nodes), + }, + [CLK_PL3_REF] = { + .name = "pl3_ref", + .control_reg = CRL_APB_PL3_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_IOPLL, + CLK_DUMMY_PARENT, + CLK_RPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &pl_nodes, + .num_nodes = ARRAY_SIZE(pl_nodes), + }, + [CLK_AMS_REF] = { + .name = "ams_ref", + .control_reg = CRL_APB_AMS_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_RPLL, + CLK_DUMMY_PARENT, + CLK_IOPLL, + CLK_DPLL_TO_LPD, + CLK_NA_PARENT + }), + .nodes = &generic_mux_div_div_gate_nodes, + .num_nodes = ARRAY_SIZE(generic_mux_div_div_gate_nodes), + }, + [CLK_IOPLL_TO_FPD] = { + .name = "iopll_to_fpd", + .control_reg = CRL_APB_IOPLL_TO_FPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) {CLK_IOPLL, CLK_NA_PARENT}), + .nodes = &generic_domain_crossing_nodes, + .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes), + }, + [CLK_RPLL_TO_FPD] = { + .name = "rpll_to_fpd", + .control_reg = CRL_APB_RPLL_TO_FPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) {CLK_RPLL, CLK_NA_PARENT}), + .nodes = &rpll_to_fpd_nodes, + .num_nodes = ARRAY_SIZE(rpll_to_fpd_nodes), + }, + [CLK_APLL_TO_LPD] = { + .name = "apll_to_lpd", + .control_reg = CRF_APB_APLL_TO_LPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) {CLK_APLL, CLK_NA_PARENT}), + .nodes = &generic_domain_crossing_nodes, + .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes), + }, + [CLK_DPLL_TO_LPD] = { + .name = "dpll_to_lpd", + .control_reg = CRF_APB_DPLL_TO_LPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) {CLK_DPLL, CLK_NA_PARENT}), + .nodes = &generic_domain_crossing_nodes, + .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes), + }, + [CLK_VPLL_TO_LPD] = { + .name = "vpll_to_lpd", + .control_reg = CRF_APB_VPLL_TO_LPD_CTRL, + .status_reg = 0, + .parents = &((int32_t []) {CLK_VPLL, CLK_NA_PARENT}), + .nodes = &generic_domain_crossing_nodes, + .num_nodes = ARRAY_SIZE(generic_domain_crossing_nodes), + }, + /* + * This clock control requires different registers for mux and gate. + * Use control and status registers for the same. + */ + [CLK_GEM0_TX] = { + .name = "gem0_tx", + .control_reg = IOU_SLCR_GEM_CLK_CTRL, + .status_reg = CRL_APB_GEM0_REF_CTRL, + .parents = &((int32_t []) { + CLK_GEM0_REF | (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN), + EXT_CLK_GEM0_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem0_tx_nodes, + .num_nodes = ARRAY_SIZE(gem0_tx_nodes), + }, + /* + * This clock control requires different registers for mux and gate. + * Use control and status registers for the same. + */ + [CLK_GEM1_TX] = { + .name = "gem1_tx", + .control_reg = IOU_SLCR_GEM_CLK_CTRL, + .status_reg = CRL_APB_GEM1_REF_CTRL, + .parents = &((int32_t []) { + CLK_GEM1_REF | (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN), + EXT_CLK_GEM1_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem1_tx_nodes, + .num_nodes = ARRAY_SIZE(gem1_tx_nodes), + }, + /* + * This clock control requires different registers for mux and gate. + * Use control and status registers for the same. + */ + [CLK_GEM2_TX] = { + .name = "gem2_tx", + .control_reg = IOU_SLCR_GEM_CLK_CTRL, + .status_reg = CRL_APB_GEM2_REF_CTRL, + .parents = &((int32_t []) { + CLK_GEM2_REF | (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN), + EXT_CLK_GEM2_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem2_tx_nodes, + .num_nodes = ARRAY_SIZE(gem2_tx_nodes), + }, + /* + * This clock control requires different registers for mux and gate. + * Use control and status registers for the same. + */ + [CLK_GEM3_TX] = { + .name = "gem3_tx", + .control_reg = IOU_SLCR_GEM_CLK_CTRL, + .status_reg = CRL_APB_GEM3_REF_CTRL, + .parents = &((int32_t []) { + CLK_GEM3_REF | (PARENT_CLK_NODE3 << CLK_PARENTS_ID_LEN), + EXT_CLK_GEM3_EMIO | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem3_tx_nodes, + .num_nodes = ARRAY_SIZE(gem3_tx_nodes), + }, + [CLK_ACPU_HALF] = { + .name = "acpu_half", + .control_reg = CRF_APB_ACPU_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_ACPU | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN, + CLK_NA_PARENT + }), + .nodes = &acpu_half_nodes, + .num_nodes = ARRAY_SIZE(acpu_half_nodes), + }, + [CLK_WDT] = { + .name = "wdt", + .control_reg = IOU_SLCR_WDT_CLK_SEL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_TOPSW_LSBUS, + EXT_CLK_SWDT0 | CLK_EXTERNAL_PARENT, + EXT_CLK_SWDT1 | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &wdt_nodes, + .num_nodes = ARRAY_SIZE(wdt_nodes), + }, + [CLK_GPU_PP0_REF] = { + .name = "gpu_pp0_ref", + .control_reg = CRF_APB_GPU_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GPU_REF | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN, + CLK_NA_PARENT + }), + .nodes = &gpu_pp0_nodes, + .num_nodes = ARRAY_SIZE(gpu_pp0_nodes), + }, + [CLK_GPU_PP1_REF] = { + .name = "gpu_pp1_ref", + .control_reg = CRF_APB_GPU_REF_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GPU_REF | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN, + CLK_NA_PARENT + }), + .nodes = &gpu_pp1_nodes, + .num_nodes = ARRAY_SIZE(gpu_pp1_nodes), + }, + [CLK_GEM_TSU] = { + .name = "gem_tsu", + .control_reg = IOU_SLCR_GEM_CLK_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_GEM_TSU_REF, + CLK_GEM_TSU_REF, + EXT_CLK_MIO26 | CLK_EXTERNAL_PARENT, + EXT_CLK_MIO50_OR_MIO51 | CLK_EXTERNAL_PARENT, + CLK_NA_PARENT + }), + .nodes = &gem_tsu_nodes, + .num_nodes = ARRAY_SIZE(gem_tsu_nodes), + }, + [CLK_CPU_R5_CORE] = { + .name = "cpu_r5_core", + .control_reg = CRL_APB_CPU_R5_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_CPU_R5 | PARENT_CLK_NODE2 << CLK_PARENTS_ID_LEN, + CLK_DUMMY_PARENT, + CLK_NA_PARENT + }), + .nodes = &cpu_r5_core_nodes, + .num_nodes = ARRAY_SIZE(cpu_r5_core_nodes), + }, + [CLK_CAN0_MIO] = { + .name = "can0_mio", + .control_reg = IOU_SLCR_CAN_MIO_CTRL, + .status_reg = 0, + .parents = &can_mio_parents, + .nodes = &can0_mio_nodes, + .num_nodes = ARRAY_SIZE(can0_mio_nodes), + }, + [CLK_CAN1_MIO] = { + .name = "can1_mio", + .control_reg = IOU_SLCR_CAN_MIO_CTRL, + .status_reg = 0, + .parents = &can_mio_parents, + .nodes = &can1_mio_nodes, + .num_nodes = ARRAY_SIZE(can1_mio_nodes), + }, + [CLK_CAN0] = { + .name = "can0", + .control_reg = IOU_SLCR_CAN_MIO_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_CAN0_REF, + CLK_CAN0_MIO, + CLK_NA_PARENT + }), + .nodes = &can0_nodes, + .num_nodes = ARRAY_SIZE(can0_nodes), + }, + [CLK_CAN1] = { + .name = "can1", + .control_reg = IOU_SLCR_CAN_MIO_CTRL, + .status_reg = 0, + .parents = &((int32_t []) { + CLK_CAN1_REF, + CLK_CAN1_MIO, + CLK_NA_PARENT + }), + .nodes = &can1_nodes, + .num_nodes = ARRAY_SIZE(can1_nodes), + }, +}; + +static struct pm_ext_clock ext_clocks[] = { + [EXT_CLK_INDEX(EXT_CLK_PSS_REF)] = { + .name = "pss_ref_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_VIDEO)] = { + .name = "video_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_PSS_ALT_REF)] = { + .name = "pss_alt_ref_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_AUX_REF)] = { + .name = "aux_ref_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_GT_CRX_REF)] = { + .name = "video_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_SWDT0)] = { + .name = "swdt0_ext_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_SWDT1)] = { + .name = "swdt1_ext_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM0_EMIO)] = { + .name = "gem0_emio_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM1_EMIO)] = { + .name = "gem1_emio_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM2_EMIO)] = { + .name = "gem2_emio_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_GEM3_EMIO)] = { + .name = "gem3_emio_clk", + }, + [EXT_CLK_INDEX(EXT_CLK_MIO50_OR_MIO51)] = { + .name = "mio_clk_50_51", + }, + EXT_CLK_MIO_DATA(0), + EXT_CLK_MIO_DATA(1), + EXT_CLK_MIO_DATA(2), + EXT_CLK_MIO_DATA(3), + EXT_CLK_MIO_DATA(4), + EXT_CLK_MIO_DATA(5), + EXT_CLK_MIO_DATA(6), + EXT_CLK_MIO_DATA(7), + EXT_CLK_MIO_DATA(8), + EXT_CLK_MIO_DATA(9), + EXT_CLK_MIO_DATA(10), + EXT_CLK_MIO_DATA(11), + EXT_CLK_MIO_DATA(12), + EXT_CLK_MIO_DATA(13), + EXT_CLK_MIO_DATA(14), + EXT_CLK_MIO_DATA(15), + EXT_CLK_MIO_DATA(16), + EXT_CLK_MIO_DATA(17), + EXT_CLK_MIO_DATA(18), + EXT_CLK_MIO_DATA(19), + EXT_CLK_MIO_DATA(20), + EXT_CLK_MIO_DATA(21), + EXT_CLK_MIO_DATA(22), + EXT_CLK_MIO_DATA(23), + EXT_CLK_MIO_DATA(24), + EXT_CLK_MIO_DATA(25), + EXT_CLK_MIO_DATA(26), + EXT_CLK_MIO_DATA(27), + EXT_CLK_MIO_DATA(28), + EXT_CLK_MIO_DATA(29), + EXT_CLK_MIO_DATA(30), + EXT_CLK_MIO_DATA(31), + EXT_CLK_MIO_DATA(32), + EXT_CLK_MIO_DATA(33), + EXT_CLK_MIO_DATA(34), + EXT_CLK_MIO_DATA(35), + EXT_CLK_MIO_DATA(36), + EXT_CLK_MIO_DATA(37), + EXT_CLK_MIO_DATA(38), + EXT_CLK_MIO_DATA(39), + EXT_CLK_MIO_DATA(40), + EXT_CLK_MIO_DATA(41), + EXT_CLK_MIO_DATA(42), + EXT_CLK_MIO_DATA(43), + EXT_CLK_MIO_DATA(44), + EXT_CLK_MIO_DATA(45), + EXT_CLK_MIO_DATA(46), + EXT_CLK_MIO_DATA(47), + EXT_CLK_MIO_DATA(48), + EXT_CLK_MIO_DATA(49), + EXT_CLK_MIO_DATA(50), + EXT_CLK_MIO_DATA(51), + EXT_CLK_MIO_DATA(52), + EXT_CLK_MIO_DATA(53), + EXT_CLK_MIO_DATA(54), + EXT_CLK_MIO_DATA(55), + EXT_CLK_MIO_DATA(56), + EXT_CLK_MIO_DATA(57), + EXT_CLK_MIO_DATA(58), + EXT_CLK_MIO_DATA(59), + EXT_CLK_MIO_DATA(60), + EXT_CLK_MIO_DATA(61), + EXT_CLK_MIO_DATA(62), + EXT_CLK_MIO_DATA(63), + EXT_CLK_MIO_DATA(64), + EXT_CLK_MIO_DATA(65), + EXT_CLK_MIO_DATA(66), + EXT_CLK_MIO_DATA(67), + EXT_CLK_MIO_DATA(68), + EXT_CLK_MIO_DATA(69), + EXT_CLK_MIO_DATA(70), + EXT_CLK_MIO_DATA(71), + EXT_CLK_MIO_DATA(72), + EXT_CLK_MIO_DATA(73), + EXT_CLK_MIO_DATA(74), + EXT_CLK_MIO_DATA(75), + EXT_CLK_MIO_DATA(76), + EXT_CLK_MIO_DATA(77), +}; + +/* Array of clock which are invalid for this variant */ +uint32_t pm_clk_invalid_list[] = {CLK_USB0, CLK_USB1, CLK_CSU_SPB}; + +/* Array of clocks which needs to be enabled at init */ +uint32_t pm_clk_init_enable_list[] = { + CLK_ACPU, + CLK_DDR_REF, +}; + +/** + * pm_clock_valid - Check if clock is valid or not + * @clock_id Id of the clock to be queried + * + * This function is used to check if given clock is valid + * or not for the chip variant. + * + * List of invalid clocks are maintained in array list for + * different variants. + * + * Return: Returns 1 if clock is valid else 0. + */ +static unsigned int pm_clock_valid(unsigned int clock_id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pm_clk_invalid_list); i++) + if (pm_clk_invalid_list[i] == clock_id) + return 0; + + return 1; +} + +/** + * pm_clock_init_enable - Check if clock needs to be enabled at init + * @clock_id Id of the clock to be queried + * + * This function is used to check if given clock needs to be enabled + * at boot up or not. Some clocks needs to be enabled at init. + * + * Return: Returns 1 if clock needs to be enabled at boot up else 0. + */ +static unsigned int pm_clock_init_enable(unsigned int clock_id) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pm_clk_init_enable_list); i++) + if (pm_clk_init_enable_list[i] == clock_id) + return 1; + + return 0; +} + +/** + * pm_clock_type - Get clock's type + * @clock_id Id of the clock to be queried + * + * This function is used to check type of clock (OUTPUT/EXTERNAL). + * + * Return: Returns type of clock (OUTPUT/EXTERNAL). + */ +static unsigned int pm_clock_type(unsigned int clock_id) +{ + return (clock_id < CLK_MAX_OUTPUT_CLK) ? + CLK_TYPE_OUTPUT : CLK_TYPE_EXTERNAL; +} /** * pm_api_clock_get_name() - PM call to request a clock's name @@ -73,7 +2316,17 @@ struct pm_clock clocks[] = {0}; */ enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name) { - return PM_RET_ERROR_NOTSUPPORTED; + if (clock_id == CLK_MAX) + memcpy(name, END_OF_CLK, CLK_NAME_LEN); + else if (!pm_clock_valid(clock_id)) + memset(name, 0, CLK_NAME_LEN); + else if (clock_id < CLK_MAX_OUTPUT_CLK) + memcpy(name, clocks[clock_id].name, CLK_NAME_LEN); + else + memcpy(name, ext_clocks[clock_id - CLK_MAX_OUTPUT_CLK].name, + CLK_NAME_LEN); + + return PM_RET_SUCCESS; } /** @@ -93,7 +2346,36 @@ enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id, unsigned int index, uint32_t *topology) { - return PM_RET_ERROR_NOTSUPPORTED; + struct pm_clock_node *clock_nodes; + uint8_t num_nodes; + unsigned int i; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + + memset(topology, 0, CLK_TOPOLOGY_PAYLOAD_LEN); + clock_nodes = *clocks[clock_id].nodes; + num_nodes = clocks[clock_id].num_nodes; + + /* Skip parent till index */ + if (index >= num_nodes) + return PM_RET_SUCCESS; + + for (i = 0; i < 3; i++) { + if ((index + i) == num_nodes) + break; + topology[i] = clock_nodes[index + i].type; + topology[i] |= clock_nodes[index + i].clkflags << + CLK_CLKFLAGS_SHIFT; + topology[i] |= clock_nodes[index + i].typeflags << + CLK_TYPEFLAGS_SHIFT; + } + + return PM_RET_SUCCESS; } /** @@ -112,7 +2394,33 @@ enum pm_ret_status pm_api_clock_get_fixedfactor_params(unsigned int clock_id, uint32_t *mul, uint32_t *div) { - return PM_RET_ERROR_NOTSUPPORTED; + struct pm_clock_node *clock_nodes; + uint8_t num_nodes; + unsigned int type, i; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + clock_nodes = *clocks[clock_id].nodes; + num_nodes = clocks[clock_id].num_nodes; + + for (i = 0; i < num_nodes; i++) { + type = clock_nodes[i].type; + if (type == TYPE_FIXEDFACTOR) { + *mul = clock_nodes[i].mult; + *div = clock_nodes[i].div; + break; + } + } + + /* Clock is not fixed clock */ + if (i == num_nodes) + return PM_RET_ERROR_ARGS; + + return PM_RET_SUCCESS; } /** @@ -136,7 +2444,33 @@ enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id, unsigned int index, uint32_t *parents) { - return PM_RET_ERROR_NOTSUPPORTED; + int i; + int32_t *clk_parents; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + clk_parents = *clocks[clock_id].parents; + if (!clk_parents) + return PM_RET_ERROR_ARGS; + + memset(parents, 0, CLK_PARENTS_PAYLOAD_LEN); + + /* Skip parent till index */ + for (i = 0; i < index; i++) + if (clk_parents[i] == CLK_NA_PARENT) + return PM_RET_SUCCESS; + + for (i = 0; i < 3; i++) { + parents[i] = clk_parents[index + i]; + if (clk_parents[index + i] == CLK_NA_PARENT) + break; + } + + return PM_RET_SUCCESS; } /** @@ -152,7 +2486,123 @@ enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id, enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id, uint32_t *attr) { - return PM_RET_ERROR_NOTSUPPORTED; + if (clock_id >= CLK_MAX) + return PM_RET_ERROR_ARGS; + + /* Clock valid bit */ + *attr = pm_clock_valid(clock_id); + + /* If clock needs to be enabled during init */ + *attr |= (pm_clock_init_enable(clock_id) << CLK_INIT_ENABLE_SHIFT); + + /* Clock type (Output/External) */ + *attr |= (pm_clock_type(clock_id) << CLK_TYPE_SHIFT); + + return PM_RET_SUCCESS; +} + +/** + * pll_get_lockbit() - Returns lockbit index for pll id + * @pll_id: Id of the pll + * + * This function return the PLL_LOCKED bit index in + * pll status register accosiated with given pll id. + * + * Return: Returns bit index + */ +static int pll_get_lockbit(unsigned int pll_id) +{ + switch (pll_id) { + case CLK_APLL_INT: + case CLK_IOPLL_INT: + return 0; + case CLK_DPLL_INT: + case CLK_RPLL_INT: + return 1; + case CLK_VPLL_INT: + return 2; + default: + return -1; + } +} + +/** + * pm_api_pll_bypass_and_reset() - Bypass and reset PLL + * @clock_id: Id of the PLL + * + * This function is to bypass and reset PLL. + */ +static inline void pm_api_pll_bypass_and_reset(unsigned int clock_id, + unsigned int flag) +{ + unsigned int reg, val; + int lockbit; + + reg = clocks[clock_id].control_reg; + + if (flag & CLK_PLL_RESET_ASSERT) { + pm_mmio_write(reg, PLLCTRL_BP_MASK, PLLCTRL_BP_MASK); + pm_mmio_write(reg, PLLCTRL_RESET_MASK, PLLCTRL_RESET_MASK); + } + if (flag & CLK_PLL_RESET_RELEASE) { + pm_mmio_write(reg, PLLCTRL_RESET_MASK, ~PLLCTRL_RESET_MASK); + + lockbit = pll_get_lockbit(clock_id); + do { + pm_mmio_read(clocks[clock_id].status_reg, &val); + } while ((lockbit >= 0) && !(val & (1 << lockbit))); + + pm_mmio_write(reg, PLLCTRL_BP_MASK, + ~(unsigned int)PLLCTRL_BP_MASK); + } +} + +/** + * pm_api_clk_enable_disable() - Enable/Disable the clock for given id + * @clock_id: Id of the clock to be enabled + * @enable: Enable(1)/Disable(0) + * + * This function is to enable/disable the clock which is not PLL. + * + * Return: Returns status, either success or error+reason. + */ +static enum pm_ret_status pm_api_clk_enable_disable(unsigned int clock_id, + unsigned int enable) +{ + struct pm_clock_node *nodes = *clocks[clock_id].nodes; + uint8_t num_nodes = clocks[clock_id].num_nodes; + unsigned int reg, val; + int i = 0, offset = NA_SHIFT, width = NA_WIDTH; + + if (clock_id == CLK_GEM0_TX || clock_id == CLK_GEM1_TX || + clock_id == CLK_GEM2_TX || clock_id == CLK_GEM3_TX) + reg = clocks[clock_id].status_reg; + else + reg = clocks[clock_id].control_reg; + + for (i = 0; i < num_nodes; i++) { + if (nodes->type == TYPE_GATE) { + offset = nodes->offset; + width = nodes->width; + break; + } + nodes++; + } + if (width == NA_WIDTH) + return PM_RET_ERROR_NOTSUPPORTED; + + pm_mmio_read(reg, &val); + if ((val & BIT_MASK(offset, width)) == enable) + return PM_RET_SUCCESS; + + if (enable) + val |= BIT_MASK(offset, width); + else + val &= ~(BIT_MASK(offset, width)); + + pm_mmio_write(reg, BIT_MASK(offset, width), val); + + return PM_RET_SUCCESS; } /** @@ -166,7 +2616,20 @@ enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id, */ enum pm_ret_status pm_api_clock_enable(unsigned int clock_id) { - return PM_RET_ERROR_NOTSUPPORTED; + int ret = PM_RET_SUCCESS; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + if (ISPLL(clock_id)) + pm_api_pll_bypass_and_reset(clock_id, CLK_PLL_RESET_PULSE); + else + ret = pm_api_clk_enable_disable(clock_id, 1); + + return ret; } /** @@ -181,7 +2644,78 @@ enum pm_ret_status pm_api_clock_enable(unsigned int clock_id) enum pm_ret_status pm_api_clock_disable(unsigned int clock_id) { - return PM_RET_ERROR_NOTSUPPORTED; + int ret = PM_RET_SUCCESS; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + if (ISPLL(clock_id)) + pm_api_pll_bypass_and_reset(clock_id, CLK_PLL_RESET_ASSERT); + else + ret = pm_api_clk_enable_disable(clock_id, 0); + + return ret; +} + +/** + * pm_api_get_pll_state() - Get state of PLL + * @clock_id Id of the PLL + * @state State of PLL(1: Enable, 0: Reset) + * + * This function is to check state of PLL. + */ +static inline void pm_api_get_pll_state(unsigned int clock_id, + unsigned int *state) +{ + unsigned int reg, val; + + reg = clocks[clock_id].control_reg; + + pm_mmio_read(reg, &val); + + /* state: + * 1 - PLL is enabled + * 0 - PLL is in reset state + */ + *state = !(val & PLLCTRL_RESET_MASK); +} + +/** + * pm_api_get_clk_state() - Get the state of clock for given id + * @clock_id: Id of the clock to be enabled + * @state: Enable(1)/Disable(0) + * + * This function is to get state of the clock which is not PLL. + * + * Return: Returns status, either success or error+reason. + */ +static enum pm_ret_status pm_api_get_clk_state(unsigned int clock_id, + unsigned int *state) +{ + struct pm_clock_node *nodes = *clocks[clock_id].nodes; + uint8_t num_nodes = clocks[clock_id].num_nodes; + unsigned int reg, val; + int i = 0, offset = NA_SHIFT, width = NA_WIDTH; + + reg = clocks[clock_id].control_reg; + + for (i = 0; i < num_nodes; i++) { + if (nodes->type == TYPE_GATE) { + offset = nodes->offset; + width = nodes->width; + } + nodes++; + } + if (width == NA_WIDTH) + return PM_RET_ERROR_NOTSUPPORTED; + + pm_mmio_read(reg, &val); + *state = (val & BIT_MASK(offset, width)) >> offset; + + return PM_RET_SUCCESS; } /** @@ -197,7 +2731,74 @@ enum pm_ret_status pm_api_clock_disable(unsigned int clock_id) enum pm_ret_status pm_api_clock_getstate(unsigned int clock_id, unsigned int *state) { - return PM_RET_ERROR_NOTSUPPORTED; + int ret = PM_RET_SUCCESS; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + if (ISPLL(clock_id)) + pm_api_get_pll_state(clock_id, state); + else + ret = pm_api_get_clk_state(clock_id, state); + + return ret; +} + +static enum pm_ret_status pm_api_clk_set_divider(unsigned int clock_id, + uint32_t divider) +{ + struct pm_clock_node *nodes; + uint8_t num_nodes; + uint16_t div1, div2; + unsigned int reg, mask = 0, val = 0, i; + unsigned int div1_width = NA_WIDTH, div1_offset = NA_SHIFT; + unsigned int div2_width = NA_WIDTH, div2_offset = NA_SHIFT; + + div1 = divider & 0xFFFF; + div2 = (divider >> 16) & 0xFFFF; + + reg = clocks[clock_id].control_reg; + + nodes = *clocks[clock_id].nodes; + num_nodes = clocks[clock_id].num_nodes; + for (i = 0; i < num_nodes; i++) { + if (nodes->type == TYPE_DIV1) { + div1_offset = nodes->offset; + div1_width = nodes->width; + } + if (nodes->type == TYPE_DIV2) { + div2_offset = nodes->offset; + div2_width = nodes->width; + } + nodes++; + } + + if (div1 != (uint16_t)-1) { + if (div1_width == NA_WIDTH) + return PM_RET_ERROR_NOTSUPPORTED; + val |= div1 << div1_offset; + mask |= BIT_MASK(div1_offset, div1_width); + } + if (div2 != (uint16_t)-1) { + if (div2_width == NA_WIDTH) + return PM_RET_ERROR_NOTSUPPORTED; + val |= div2 << div2_offset; + mask |= BIT_MASK(div2_offset, div2_width); + } + pm_mmio_write(reg, mask, val); + + return PM_RET_SUCCESS; +} + +enum pm_ret_status pm_api_pll_set_divider(unsigned int clock_id, + unsigned int divider) +{ + unsigned int reg = clocks[clock_id].control_reg; + + return pm_mmio_write(reg, PLL_FBDIV_MASK, divider << PLL_FBDIV_SHIFT); } /** @@ -213,7 +2814,73 @@ enum pm_ret_status pm_api_clock_getstate(unsigned int clock_id, enum pm_ret_status pm_api_clock_setdivider(unsigned int clock_id, unsigned int divider) { - return PM_RET_ERROR_NOTSUPPORTED; + int ret; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + if (ISPLL(clock_id)) + ret = pm_api_pll_set_divider(clock_id, divider); + else + ret = pm_api_clk_set_divider(clock_id, divider); + + return ret; +} + +static enum pm_ret_status pm_api_clk_get_divider(unsigned int clock_id, + uint32_t *divider) +{ + struct pm_clock_node *nodes; + uint8_t num_nodes; + unsigned int reg, val, i, div1 = 0, div2 = 0; + unsigned int div1_width = NA_WIDTH, div1_offset = NA_SHIFT; + unsigned int div2_width = NA_WIDTH, div2_offset = NA_SHIFT; + + reg = clocks[clock_id].control_reg; + + nodes = *clocks[clock_id].nodes; + num_nodes = clocks[clock_id].num_nodes; + for (i = 0; i < num_nodes; i++) { + if (nodes->type == TYPE_DIV1) { + div1_offset = nodes->offset; + div1_width = nodes->width; + } + if (nodes->type == TYPE_DIV2) { + div2_offset = nodes->offset; + div2_width = nodes->width; + } + nodes++; + } + + pm_mmio_read(reg, &val); + + if (div1_width == NA_WIDTH) + return PM_RET_ERROR_ARGS; + + div1 = (val & BIT_MASK(div1_offset, div1_width)) >> div1_offset; + + if (div2_width != NA_WIDTH) + div2 = (val & BIT_MASK(div2_offset, div2_width)) >> div2_offset; + + *divider = div1 | (div2 << 16); + + return PM_RET_SUCCESS; +} + +enum pm_ret_status pm_api_pll_get_divider(unsigned int clock_id, + unsigned int *divider) +{ + unsigned int reg, val; + + reg = clocks[clock_id].control_reg; + + pm_mmio_read(reg, &val); + *divider = (val & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT; + + return PM_RET_SUCCESS; } /** @@ -229,7 +2896,20 @@ enum pm_ret_status pm_api_clock_setdivider(unsigned int clock_id, enum pm_ret_status pm_api_clock_getdivider(unsigned int clock_id, unsigned int *divider) { - return PM_RET_ERROR_NOTSUPPORTED; + int ret; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + if (ISPLL(clock_id)) + ret = pm_api_pll_get_divider(clock_id, divider); + else + ret = pm_api_clk_get_divider(clock_id, divider); + + return ret; } /** @@ -275,7 +2955,41 @@ enum pm_ret_status pm_api_clock_getrate(unsigned int clock_id, enum pm_ret_status pm_api_clock_setparent(unsigned int clock_id, unsigned int parent_idx) { - return PM_RET_ERROR_NOTSUPPORTED; + struct pm_clock_node *nodes; + uint8_t num_nodes; + unsigned int reg, val; + int32_t *clk_parents; + int i = 0, offset = NA_SHIFT, width = NA_WIDTH; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + clk_parents = *clocks[clock_id].parents; + + for (i = 0; i <= parent_idx; i++) + if (clk_parents[i] == CLK_NA_PARENT) + return PM_RET_ERROR_ARGS; + + nodes = *clocks[clock_id].nodes; + num_nodes = clocks[clock_id].num_nodes; + for (i = 0; i < num_nodes; i++) { + if (nodes->type == TYPE_MUX) { + offset = nodes->offset; + width = nodes->width; + } + nodes++; + } + if (width == NA_WIDTH) + return PM_RET_ERROR_NOTSUPPORTED; + + reg = clocks[clock_id].control_reg; + val = parent_idx << offset; + pm_mmio_write(reg, BIT_MASK(offset, width), val); + + return PM_RET_SUCCESS; } /** @@ -291,7 +3005,38 @@ enum pm_ret_status pm_api_clock_setparent(unsigned int clock_id, enum pm_ret_status pm_api_clock_getparent(unsigned int clock_id, unsigned int *parent_idx) { - return PM_RET_ERROR_NOTSUPPORTED; + struct pm_clock_node *nodes; + uint8_t num_nodes; + unsigned int reg, val; + int i = 0, offset = NA_SHIFT, width = NA_WIDTH; + + if (!pm_clock_valid(clock_id)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + nodes = *clocks[clock_id].nodes; + num_nodes = clocks[clock_id].num_nodes; + + for (i = 0; i < num_nodes; i++) { + if (nodes->type == TYPE_MUX) { + offset = nodes->offset; + width = nodes->width; + } + nodes++; + } + if (width == NA_WIDTH) + return PM_RET_ERROR_NOTSUPPORTED; + + reg = clocks[clock_id].control_reg; + pm_mmio_read(reg, &val); + val >>= offset; + val &= ((1U << width) - 1); + + *parent_idx = val; + + return PM_RET_SUCCESS; } /** @@ -306,7 +3051,25 @@ enum pm_ret_status pm_api_clock_getparent(unsigned int clock_id, enum pm_ret_status pm_api_clk_set_pll_mode(unsigned int pll, unsigned int mode) { - return PM_RET_ERROR_NOTSUPPORTED; + unsigned int reg; + + if (!pm_clock_valid(pll)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(pll) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + if (!ISPLL(pll)) + return PM_RET_ERROR_NOTSUPPORTED; + + if (mode != PLL_FRAC_MODE && mode != PLL_INT_MODE) + return PM_RET_ERROR_ARGS; + + reg = clocks[pll].control_reg + PLL_FRAC_OFFSET; + + pm_mmio_write(reg, PLL_FRAC_MODE_MASK, mode << PLL_FRAC_MODE_SHIFT); + + return PM_RET_SUCCESS; } /** @@ -321,7 +3084,27 @@ enum pm_ret_status pm_api_clk_set_pll_mode(unsigned int pll, enum pm_ret_status pm_api_clk_get_pll_mode(unsigned int pll, unsigned int *mode) { - return PM_RET_ERROR_NOTSUPPORTED; + unsigned int val, reg; + + if (!pm_clock_valid(pll)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(pll) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + if (!ISPLL(pll)) + return PM_RET_ERROR_NOTSUPPORTED; + + reg = clocks[pll].control_reg + PLL_FRAC_OFFSET; + + pm_mmio_read(reg, &val); + val = val & PLL_FRAC_MODE_MASK; + if (val) + *mode = PLL_FRAC_MODE; + else + *mode = PLL_INT_MODE; + + return PM_RET_SUCCESS; } /** @@ -337,7 +3120,27 @@ enum pm_ret_status pm_api_clk_get_pll_mode(unsigned int pll, enum pm_ret_status pm_api_clk_set_pll_frac_data(unsigned int pll, unsigned int data) { - return PM_RET_ERROR_NOTSUPPORTED; + unsigned int val, reg, mode; + + if (!pm_clock_valid(pll)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(pll) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + if (!ISPLL(pll)) + return PM_RET_ERROR_NOTSUPPORTED; + + pm_api_clk_get_pll_mode(pll, &mode); + if (mode == PLL_FRAC_MODE) { + reg = clocks[pll].control_reg + PLL_FRAC_OFFSET; + val = data << PLL_FRAC_DATA_SHIFT; + pm_mmio_write(reg, PLL_FRAC_DATA_MASK, val); + } else { + return PM_RET_ERROR_ARGS; + } + + return PM_RET_SUCCESS; } /** @@ -352,5 +3155,21 @@ enum pm_ret_status pm_api_clk_set_pll_frac_data(unsigned int pll, enum pm_ret_status pm_api_clk_get_pll_frac_data(unsigned int pll, unsigned int *data) { - return PM_RET_ERROR_NOTSUPPORTED; + unsigned int val, reg; + + if (!pm_clock_valid(pll)) + return PM_RET_ERROR_ARGS; + + if (pm_clock_type(pll) != CLK_TYPE_OUTPUT) + return PM_RET_ERROR_NOTSUPPORTED; + + if (!ISPLL(pll)) + return PM_RET_ERROR_NOTSUPPORTED; + + reg = clocks[pll].control_reg + PLL_FRAC_OFFSET; + + pm_mmio_read(reg, &val); + *data = (val & PLL_FRAC_DATA_MASK); + + return PM_RET_SUCCESS; } diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h index 2e7260e1e..666eda577 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h @@ -11,9 +11,264 @@ #ifndef _PM_API_CLOCK_H_ #define _PM_API_CLOCK_H_ +#include #include "pm_common.h" #define CLK_NAME_LEN 15 +#define MAX_PARENTS 100 +#define CLK_NA_PARENT -1 +#define CLK_DUMMY_PARENT -2 + +/* Flags for parent id */ +#define PARENT_CLK_SELF 0 +#define PARENT_CLK_NODE1 1 +#define PARENT_CLK_NODE2 2 +#define PARENT_CLK_NODE3 3 +#define PARENT_CLK_NODE4 4 +#define PARENT_CLK_EXTERNAL 5 +#define PARENT_CLK_MIO0_MIO77 6 + +#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */ +#define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */ +#define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */ +#define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */ +/* unused */ +#define CLK_IS_BASIC BIT(5) /* Basic clk, can't do a to_clk_foo() */ +#define CLK_GET_RATE_NOCACHE BIT(6) /* do not use the cached clk rate */ +#define CLK_SET_RATE_NO_REPARENT BIT(7) /* don't re-parent on rate change */ +#define CLK_GET_ACCURACY_NOCACHE BIT(8) /* do not use the cached clk accuracy */ +#define CLK_RECALC_NEW_RATES BIT(9) /* recalc rates after notifications */ +#define CLK_SET_RATE_UNGATE BIT(10) /* clock needs to run to set rate */ +#define CLK_IS_CRITICAL BIT(11) /* do not gate, ever */ +/* parents need enable during gate/ungate, set rate and re-parent */ +#define CLK_OPS_PARENT_ENABLE BIT(12) +#define CLK_FRAC BIT(13) + +#define CLK_DIVIDER_ONE_BASED BIT(0) +#define CLK_DIVIDER_POWER_OF_TWO BIT(1) +#define CLK_DIVIDER_ALLOW_ZERO BIT(2) +#define CLK_DIVIDER_HIWORD_MASK BIT(3) +#define CLK_DIVIDER_ROUND_CLOSEST BIT(4) +#define CLK_DIVIDER_READ_ONLY BIT(5) +#define CLK_DIVIDER_MAX_AT_ZERO BIT(6) + +#define END_OF_CLK "END_OF_CLK" + +enum clock_ids { + CLK_IOPLL, + CLK_RPLL, + CLK_APLL, + CLK_DPLL, + CLK_VPLL, + CLK_IOPLL_TO_FPD, + CLK_RPLL_TO_FPD, + CLK_APLL_TO_LPD, + CLK_DPLL_TO_LPD, + CLK_VPLL_TO_LPD, + CLK_ACPU, + CLK_ACPU_HALF, + CLK_DBG_FPD, + CLK_DBG_LPD, + CLK_DBG_TRACE, + CLK_DBG_TSTMP, + CLK_DP_VIDEO_REF, + CLK_DP_AUDIO_REF, + CLK_DP_STC_REF, + CLK_GDMA_REF, + CLK_DPDMA_REF, + CLK_DDR_REF, + CLK_SATA_REF, + CLK_PCIE_REF, + CLK_GPU_REF, + CLK_GPU_PP0_REF, + CLK_GPU_PP1_REF, + CLK_TOPSW_MAIN, + CLK_TOPSW_LSBUS, + CLK_GTGREF0_REF, + CLK_LPD_SWITCH, + CLK_LPD_LSBUS, + CLK_USB0_BUS_REF, + CLK_USB1_BUS_REF, + CLK_USB3_DUAL_REF, + CLK_USB0, + CLK_USB1, + CLK_CPU_R5, + CLK_CPU_R5_CORE, + CLK_CSU_SPB, + CLK_CSU_PLL, + CLK_PCAP, + CLK_IOU_SWITCH, + CLK_GEM_TSU_REF, + CLK_GEM_TSU, + CLK_GEM0_REF, + CLK_GEM1_REF, + CLK_GEM2_REF, + CLK_GEM3_REF, + CLK_GEM0_TX, + CLK_GEM1_TX, + CLK_GEM2_TX, + CLK_GEM3_TX, + CLK_QSPI_REF, + CLK_SDIO0_REF, + CLK_SDIO1_REF, + CLK_UART0_REF, + CLK_UART1_REF, + CLK_SPI0_REF, + CLK_SPI1_REF, + CLK_NAND_REF, + CLK_I2C0_REF, + CLK_I2C1_REF, + CLK_CAN0_REF, + CLK_CAN1_REF, + CLK_CAN0, + CLK_CAN1, + CLK_DLL_REF, + CLK_ADMA_REF, + CLK_TIMESTAMP_REF, + CLK_AMS_REF, + CLK_PL0_REF, + CLK_PL1_REF, + CLK_PL2_REF, + CLK_PL3_REF, + CLK_WDT, + CLK_IOPLL_INT, + CLK_IOPLL_PRE_SRC, + CLK_IOPLL_HALF, + CLK_IOPLL_INT_MUX, + CLK_IOPLL_POST_SRC, + CLK_RPLL_INT, + CLK_RPLL_PRE_SRC, + CLK_RPLL_HALF, + CLK_RPLL_INT_MUX, + CLK_RPLL_POST_SRC, + CLK_APLL_INT, + CLK_APLL_PRE_SRC, + CLK_APLL_HALF, + CLK_APLL_INT_MUX, + CLK_APLL_POST_SRC, + CLK_DPLL_INT, + CLK_DPLL_PRE_SRC, + CLK_DPLL_HALF, + CLK_DPLL_INT_MUX, + CLK_DPLL_POST_SRC, + CLK_VPLL_INT, + CLK_VPLL_PRE_SRC, + CLK_VPLL_HALF, + CLK_VPLL_INT_MUX, + CLK_VPLL_POST_SRC, + CLK_CAN0_MIO, + CLK_CAN1_MIO, + CLK_MAX_OUTPUT_CLK, +}; + +enum external_clk_ids { + EXT_CLK_PSS_REF = CLK_MAX_OUTPUT_CLK, + EXT_CLK_VIDEO, + EXT_CLK_PSS_ALT_REF, + EXT_CLK_AUX_REF, + EXT_CLK_GT_CRX_REF, + EXT_CLK_SWDT0, + EXT_CLK_SWDT1, + EXT_CLK_GEM0_EMIO, + EXT_CLK_GEM1_EMIO, + EXT_CLK_GEM2_EMIO, + EXT_CLK_GEM3_EMIO, + EXT_CLK_MIO50_OR_MIO51, + EXT_CLK_MIO0, + EXT_CLK_MIO1, + EXT_CLK_MIO2, + EXT_CLK_MIO3, + EXT_CLK_MIO4, + EXT_CLK_MIO5, + EXT_CLK_MIO6, + EXT_CLK_MIO7, + EXT_CLK_MIO8, + EXT_CLK_MIO9, + EXT_CLK_MIO10, + EXT_CLK_MIO11, + EXT_CLK_MIO12, + EXT_CLK_MIO13, + EXT_CLK_MIO14, + EXT_CLK_MIO15, + EXT_CLK_MIO16, + EXT_CLK_MIO17, + EXT_CLK_MIO18, + EXT_CLK_MIO19, + EXT_CLK_MIO20, + EXT_CLK_MIO21, + EXT_CLK_MIO22, + EXT_CLK_MIO23, + EXT_CLK_MIO24, + EXT_CLK_MIO25, + EXT_CLK_MIO26, + EXT_CLK_MIO27, + EXT_CLK_MIO28, + EXT_CLK_MIO29, + EXT_CLK_MIO30, + EXT_CLK_MIO31, + EXT_CLK_MIO32, + EXT_CLK_MIO33, + EXT_CLK_MIO34, + EXT_CLK_MIO35, + EXT_CLK_MIO36, + EXT_CLK_MIO37, + EXT_CLK_MIO38, + EXT_CLK_MIO39, + EXT_CLK_MIO40, + EXT_CLK_MIO41, + EXT_CLK_MIO42, + EXT_CLK_MIO43, + EXT_CLK_MIO44, + EXT_CLK_MIO45, + EXT_CLK_MIO46, + EXT_CLK_MIO47, + EXT_CLK_MIO48, + EXT_CLK_MIO49, + EXT_CLK_MIO50, + EXT_CLK_MIO51, + EXT_CLK_MIO52, + EXT_CLK_MIO53, + EXT_CLK_MIO54, + EXT_CLK_MIO55, + EXT_CLK_MIO56, + EXT_CLK_MIO57, + EXT_CLK_MIO58, + EXT_CLK_MIO59, + EXT_CLK_MIO60, + EXT_CLK_MIO61, + EXT_CLK_MIO62, + EXT_CLK_MIO63, + EXT_CLK_MIO64, + EXT_CLK_MIO65, + EXT_CLK_MIO66, + EXT_CLK_MIO67, + EXT_CLK_MIO68, + EXT_CLK_MIO69, + EXT_CLK_MIO70, + EXT_CLK_MIO71, + EXT_CLK_MIO72, + EXT_CLK_MIO73, + EXT_CLK_MIO74, + EXT_CLK_MIO75, + EXT_CLK_MIO76, + EXT_CLK_MIO77, + CLK_MAX, +}; + +enum clk_type { + CLK_TYPE_OUTPUT, + CLK_TYPE_EXTERNAL, +}; + +enum topology_type { + TYPE_INVALID, + TYPE_MUX, + TYPE_PLL, + TYPE_FIXEDFACTOR, + TYPE_DIV1, + TYPE_DIV2, + TYPE_GATE, +}; enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name); enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id, @@ -51,4 +306,5 @@ enum pm_ret_status pm_api_clk_set_pll_frac_data(unsigned int pll, unsigned int data); enum pm_ret_status pm_api_clk_get_pll_frac_data(unsigned int pll, unsigned int *data); + #endif /* _PM_API_CLOCK_H_ */ diff --git a/plat/xilinx/zynqmp/zynqmp_def.h b/plat/xilinx/zynqmp/zynqmp_def.h index f3180e901..3feae9d41 100644 --- a/plat/xilinx/zynqmp/zynqmp_def.h +++ b/plat/xilinx/zynqmp/zynqmp_def.h @@ -35,6 +35,7 @@ /* For cpu reset APU space here too 0xFE5F1000 CRF_APB*/ #define CRF_APB_BASE 0xFD1A0000 #define CRF_APB_SIZE 0x00600000 +#define CRF_APB_CLK_BASE 0xFD1A0020 /* CRF registers and bitfields */ #define CRF_APB_RST_FPD_APU (CRF_APB_BASE + 0X00000104) @@ -44,10 +45,10 @@ /* CRL registers and bitfields */ #define CRL_APB_BASE 0xFF5E0000 -#define CRL_APB_RPLL_CTRL (CRL_APB_BASE + 0x30) #define CRL_APB_BOOT_MODE_USER (CRL_APB_BASE + 0x200) #define CRL_APB_RESET_CTRL (CRL_APB_BASE + 0x218) #define CRL_APB_RST_LPD_TOP (CRL_APB_BASE + 0x23C) +#define CRL_APB_CLK_BASE 0xFF5E0020 #define CRL_APB_RPU_AMBA_RESET (1 << 2) #define CRL_APB_RPLL_CTRL_BYPASS (1 << 3) @@ -225,4 +226,81 @@ #define ZYNQMP_SD_OTAPDLYENA_MASK 0x40 #define ZYNQMP_SD_OTAPDLYENA 0x40 +/* Clock control registers */ +/* Full power domain clocks */ +#define CRF_APB_APLL_CTRL (CRF_APB_CLK_BASE + 0x00) +#define CRF_APB_DPLL_CTRL (CRF_APB_CLK_BASE + 0x0c) +#define CRF_APB_VPLL_CTRL (CRF_APB_CLK_BASE + 0x18) +#define CRF_APB_PLL_STATUS (CRF_APB_CLK_BASE + 0x24) +#define CRF_APB_APLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x28) +#define CRF_APB_DPLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x2c) +#define CRF_APB_VPLL_TO_LPD_CTRL (CRF_APB_CLK_BASE + 0x30) +/* Peripheral clocks */ +#define CRF_APB_ACPU_CTRL (CRF_APB_CLK_BASE + 0x40) +#define CRF_APB_DBG_TRACE_CTRL (CRF_APB_CLK_BASE + 0x44) +#define CRF_APB_DBG_FPD_CTRL (CRF_APB_CLK_BASE + 0x48) +#define CRF_APB_DP_VIDEO_REF_CTRL (CRF_APB_CLK_BASE + 0x50) +#define CRF_APB_DP_AUDIO_REF_CTRL (CRF_APB_CLK_BASE + 0x54) +#define CRF_APB_DP_STC_REF_CTRL (CRF_APB_CLK_BASE + 0x5c) +#define CRF_APB_DDR_CTRL (CRF_APB_CLK_BASE + 0x60) +#define CRF_APB_GPU_REF_CTRL (CRF_APB_CLK_BASE + 0x64) +#define CRF_APB_SATA_REF_CTRL (CRF_APB_CLK_BASE + 0x80) +#define CRF_APB_PCIE_REF_CTRL (CRF_APB_CLK_BASE + 0x94) +#define CRF_APB_GDMA_REF_CTRL (CRF_APB_CLK_BASE + 0x98) +#define CRF_APB_DPDMA_REF_CTRL (CRF_APB_CLK_BASE + 0x9c) +#define CRF_APB_TOPSW_MAIN_CTRL (CRF_APB_CLK_BASE + 0xa0) +#define CRF_APB_TOPSW_LSBUS_CTRL (CRF_APB_CLK_BASE + 0xa4) +#define CRF_APB_GTGREF0_REF_CTRL (CRF_APB_CLK_BASE + 0xa8) +#define CRF_APB_DBG_TSTMP_CTRL (CRF_APB_CLK_BASE + 0xd8) + +/* Low power domain clocks */ +#define CRL_APB_IOPLL_CTRL (CRL_APB_CLK_BASE + 0x00) +#define CRL_APB_RPLL_CTRL (CRL_APB_CLK_BASE + 0x10) +#define CRL_APB_PLL_STATUS (CRL_APB_CLK_BASE + 0x20) +#define CRL_APB_IOPLL_TO_FPD_CTRL (CRL_APB_CLK_BASE + 0x24) +#define CRL_APB_RPLL_TO_FPD_CTRL (CRL_APB_CLK_BASE + 0x28) +/* Peripheral clocks */ +#define CRL_APB_USB3_DUAL_REF_CTRL (CRL_APB_CLK_BASE + 0x2c) +#define CRL_APB_GEM0_REF_CTRL (CRL_APB_CLK_BASE + 0x30) +#define CRL_APB_GEM1_REF_CTRL (CRL_APB_CLK_BASE + 0x34) +#define CRL_APB_GEM2_REF_CTRL (CRL_APB_CLK_BASE + 0x38) +#define CRL_APB_GEM3_REF_CTRL (CRL_APB_CLK_BASE + 0x3c) +#define CRL_APB_USB0_BUS_REF_CTRL (CRL_APB_CLK_BASE + 0x40) +#define CRL_APB_USB1_BUS_REF_CTRL (CRL_APB_CLK_BASE + 0x44) +#define CRL_APB_QSPI_REF_CTRL (CRL_APB_CLK_BASE + 0x48) +#define CRL_APB_SDIO0_REF_CTRL (CRL_APB_CLK_BASE + 0x4c) +#define CRL_APB_SDIO1_REF_CTRL (CRL_APB_CLK_BASE + 0x50) +#define CRL_APB_UART0_REF_CTRL (CRL_APB_CLK_BASE + 0x54) +#define CRL_APB_UART1_REF_CTRL (CRL_APB_CLK_BASE + 0x58) +#define CRL_APB_SPI0_REF_CTRL (CRL_APB_CLK_BASE + 0x5c) +#define CRL_APB_SPI1_REF_CTRL (CRL_APB_CLK_BASE + 0x60) +#define CRL_APB_CAN0_REF_CTRL (CRL_APB_CLK_BASE + 0x64) +#define CRL_APB_CAN1_REF_CTRL (CRL_APB_CLK_BASE + 0x68) +#define CRL_APB_CPU_R5_CTRL (CRL_APB_CLK_BASE + 0x70) +#define CRL_APB_IOU_SWITCH_CTRL (CRL_APB_CLK_BASE + 0x7c) +#define CRL_APB_CSU_PLL_CTRL (CRL_APB_CLK_BASE + 0x80) +#define CRL_APB_PCAP_CTRL (CRL_APB_CLK_BASE + 0x84) +#define CRL_APB_LPD_SWITCH_CTRL (CRL_APB_CLK_BASE + 0x88) +#define CRL_APB_LPD_LSBUS_CTRL (CRL_APB_CLK_BASE + 0x8c) +#define CRL_APB_DBG_LPD_CTRL (CRL_APB_CLK_BASE + 0x90) +#define CRL_APB_NAND_REF_CTRL (CRL_APB_CLK_BASE + 0x94) +#define CRL_APB_ADMA_REF_CTRL (CRL_APB_CLK_BASE + 0x98) +#define CRL_APB_PL0_REF_CTRL (CRL_APB_CLK_BASE + 0xa0) +#define CRL_APB_PL1_REF_CTRL (CRL_APB_CLK_BASE + 0xa4) +#define CRL_APB_PL2_REF_CTRL (CRL_APB_CLK_BASE + 0xa8) +#define CRL_APB_PL3_REF_CTRL (CRL_APB_CLK_BASE + 0xac) +#define CRL_APB_PL0_THR_CNT (CRL_APB_CLK_BASE + 0xb4) +#define CRL_APB_PL1_THR_CNT (CRL_APB_CLK_BASE + 0xbc) +#define CRL_APB_PL2_THR_CNT (CRL_APB_CLK_BASE + 0xc4) +#define CRL_APB_PL3_THR_CNT (CRL_APB_CLK_BASE + 0xdc) +#define CRL_APB_GEM_TSU_REF_CTRL (CRL_APB_CLK_BASE + 0xe0) +#define CRL_APB_DLL_REF_CTRL (CRL_APB_CLK_BASE + 0xe4) +#define CRL_APB_AMS_REF_CTRL (CRL_APB_CLK_BASE + 0xe8) +#define CRL_APB_I2C0_REF_CTRL (CRL_APB_CLK_BASE + 0x100) +#define CRL_APB_I2C1_REF_CTRL (CRL_APB_CLK_BASE + 0x104) +#define CRL_APB_TIMESTAMP_REF_CTRL (CRL_APB_CLK_BASE + 0x108) +#define IOU_SLCR_GEM_CLK_CTRL (IOU_SLCR_BASEADDR + 0x308) +#define IOU_SLCR_CAN_MIO_CTRL (IOU_SLCR_BASEADDR + 0x304) +#define IOU_SLCR_WDT_CLK_SEL (IOU_SLCR_BASEADDR + 0x300) + #endif /* __ZYNQMP_DEF_H__ */