[U-Boot] [PATCH V5 05/31] imx: mx8m: add clock driver
Stefano Babic
sbabic at denx.de
Sun Jan 21 16:28:17 UTC 2018
Hi Peng,
On 10/01/2018 06:20, Peng Fan wrote:
> Add clock driver to support i.MX8M.
>
> There are two kind PLLs, FRAC pll and SSCG pll. ROM already
> configured SYS PLL1/2, we only need to configure the output.
> ocotp/i2c/pll decoding and configuration/usdhc/lcdif/dram pll/
> enet clock are configured in the code.
>
> Signed-off-by: Peng Fan <peng.fan at nxp.com>
> Cc: Fabio Estevam <fabio.estevam at nxp.com>
> Cc: Stefano Babic <sbabic at denx.de>
> ---
> arch/arm/include/asm/arch-mx8m/clock.h | 657 +++++++++++++++++++++++++++
> arch/arm/mach-imx/mx8m/Makefile | 7 +
> arch/arm/mach-imx/mx8m/clock.c | 795 +++++++++++++++++++++++++++++++++
> arch/arm/mach-imx/mx8m/clock_slice.c | 742 ++++++++++++++++++++++++++++++
> 4 files changed, 2201 insertions(+)
> create mode 100644 arch/arm/include/asm/arch-mx8m/clock.h
> create mode 100644 arch/arm/mach-imx/mx8m/Makefile
> create mode 100644 arch/arm/mach-imx/mx8m/clock.c
> create mode 100644 arch/arm/mach-imx/mx8m/clock_slice.c
>
> diff --git a/arch/arm/include/asm/arch-mx8m/clock.h b/arch/arm/include/asm/arch-mx8m/clock.h
> new file mode 100644
> index 0000000000..555512b453
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-mx8m/clock.h
> @@ -0,0 +1,657 @@
> +/*
> + * Copyright 2017 NXP
> + *
> + * Peng Fan <peng.fan at nxp.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#ifndef _ASM_ARCH_IMX8M_CLOCK_H
> +#define _ASM_ARCH_IMX8M_CLOCK_H
> +
> +#include <linux/bitops.h>
> +
> +enum pll_clocks {
> + ANATOP_ARM_PLL,
> + ANATOP_GPU_PLL,
> + ANATOP_SYSTEM_PLL1,
> + ANATOP_SYSTEM_PLL2,
> + ANATOP_SYSTEM_PLL3,
> + ANATOP_AUDIO_PLL1,
> + ANATOP_AUDIO_PLL2,
> + ANATOP_VIDEO_PLL1,
> + ANATOP_VIDEO_PLL2,
> + ANATOP_DRAM_PLL,
> +};
> +
> +enum clk_slice_type {
> + CORE_CLOCK_SLICE,
> + BUS_CLOCK_SLICE,
> + IP_CLOCK_SLICE,
> + AHB_CLOCK_SLICE,
> + IPG_CLOCK_SLICE,
> + CORE_SEL_CLOCK_SLICE,
> + DRAM_SEL_CLOCK_SLICE,
> +};
> +
> +enum clk_root_index {
> + MXC_ARM_CLK = 0,
> + ARM_A53_CLK_ROOT = 0,
> + ARM_M4_CLK_ROOT = 1,
> + VPU_A53_CLK_ROOT = 2,
> + GPU_CORE_CLK_ROOT = 3,
> + GPU_SHADER_CLK_ROOT = 4,
> + MAIN_AXI_CLK_ROOT = 16,
> + ENET_AXI_CLK_ROOT = 17,
> + NAND_USDHC_BUS_CLK_ROOT = 18,
> + VPU_BUS_CLK_ROOT = 19,
> + DISPLAY_AXI_CLK_ROOT = 20,
> + DISPLAY_APB_CLK_ROOT = 21,
> + DISPLAY_RTRM_CLK_ROOT = 22,
> + USB_BUS_CLK_ROOT = 23,
> + GPU_AXI_CLK_ROOT = 24,
> + GPU_AHB_CLK_ROOT = 25,
> + NOC_CLK_ROOT = 26,
> + NOC_APB_CLK_ROOT = 27,
> + AHB_CLK_ROOT = 32,
> + IPG_CLK_ROOT = 33,
> + MXC_IPG_CLK = 33,
> + AUDIO_AHB_CLK_ROOT = 34,
> + MIPI_DSI_ESC_RX_CLK_ROOT = 36,
> + DRAM_SEL_CFG = 48,
> + CORE_SEL_CFG = 49,
> + DRAM_ALT_CLK_ROOT = 64,
> + DRAM_APB_CLK_ROOT = 65,
> + VPU_G1_CLK_ROOT = 66,
> + VPU_G2_CLK_ROOT = 67,
> + DISPLAY_DTRC_CLK_ROOT = 68,
> + DISPLAY_DC8000_CLK_ROOT = 69,
> + PCIE1_CTRL_CLK_ROOT = 70,
> + PCIE1_PHY_CLK_ROOT = 71,
> + PCIE1_AUX_CLK_ROOT = 72,
> + DC_PIXEL_CLK_ROOT = 73,
> + LCDIF_PIXEL_CLK_ROOT = 74,
> + SAI1_CLK_ROOT = 75,
> + SAI2_CLK_ROOT = 76,
> + SAI3_CLK_ROOT = 77,
> + SAI4_CLK_ROOT = 78,
> + SAI5_CLK_ROOT = 79,
> + SAI6_CLK_ROOT = 80,
> + SPDIF1_CLK_ROOT = 81,
> + SPDIF2_CLK_ROOT = 82,
> + ENET_REF_CLK_ROOT = 83,
> + ENET_TIMER_CLK_ROOT = 84,
> + ENET_PHY_REF_CLK_ROOT = 85,
> + NAND_CLK_ROOT = 86,
> + QSPI_CLK_ROOT = 87,
> + MXC_ESDHC_CLK = 88,
> + USDHC1_CLK_ROOT = 88,
> + MXC_ESDHC2_CLK = 89,
> + USDHC2_CLK_ROOT = 89,
> + I2C1_CLK_ROOT = 90,
> + MXC_I2C_CLK = 90,
> + I2C2_CLK_ROOT = 91,
> + I2C3_CLK_ROOT = 92,
> + I2C4_CLK_ROOT = 93,
> + UART1_CLK_ROOT = 94,
> + UART2_CLK_ROOT = 95,
> + UART3_CLK_ROOT = 96,
> + UART4_CLK_ROOT = 97,
> + USB_CORE_REF_CLK_ROOT = 98,
> + USB_PHY_REF_CLK_ROOT = 99,
> + GIC_CLK_ROOT = 100,
> + ECSPI1_CLK_ROOT = 101,
> + ECSPI2_CLK_ROOT = 102,
> + PWM1_CLK_ROOT = 103,
> + PWM2_CLK_ROOT = 104,
> + PWM3_CLK_ROOT = 105,
> + PWM4_CLK_ROOT = 106,
> + GPT1_CLK_ROOT = 107,
> + GPT2_CLK_ROOT = 108,
> + GPT3_CLK_ROOT = 109,
> + GPT4_CLK_ROOT = 110,
> + GPT5_CLK_ROOT = 111,
> + GPT6_CLK_ROOT = 112,
> + TRACE_CLK_ROOT = 113,
> + WDOG_CLK_ROOT = 114,
> + WRCLK_CLK_ROOT = 115,
> + IPP_DO_CLKO1 = 116,
> + IPP_DO_CLKO2 = 117,
> + MIPI_DSI_CORE_CLK_ROOT = 118,
> + MIPI_DSI_PHY_REF_CLK_ROOT = 119,
> + MIPI_DSI_DBI_CLK_ROOT = 120,
> + OLD_MIPI_DSI_ESC_CLK_ROOT = 121,
> + MIPI_CSI1_CORE_CLK_ROOT = 122,
> + MIPI_CSI1_PHY_REF_CLK_ROOT = 123,
> + MIPI_CSI1_ESC_CLK_ROOT = 124,
> + MIPI_CSI2_CORE_CLK_ROOT = 125,
> + MIPI_CSI2_PHY_REF_CLK_ROOT = 126,
> + MIPI_CSI2_ESC_CLK_ROOT = 127,
> + PCIE2_CTRL_CLK_ROOT = 128,
> + PCIE2_PHY_CLK_ROOT = 129,
> + PCIE2_AUX_CLK_ROOT = 130,
> + ECSPI3_CLK_ROOT = 131,
> + OLD_MIPI_DSI_ESC_RX_ROOT = 132,
> + DISPLAY_HDMI_CLK_ROOT = 133,
> + CLK_ROOT_MAX,
> +};
> +
Just to help board maintainers: add a comment to this structure to
reference to the manual where they are defined (Clock root table, table
5.1). This explains that the defines here reflects the hardware as
described in manual.
> +enum clk_root_src {
> + OSC_25M_CLK,
> + ARM_PLL_CLK,
> + DRAM_PLL1_CLK,
> + VIDEO_PLL2_CLK,
> + VPU_PLL_CLK,
> + GPU_PLL_CLK,
> + SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL1_400M_CLK,
> + SYSTEM_PLL1_266M_CLK,
> + SYSTEM_PLL1_200M_CLK,
> + SYSTEM_PLL1_160M_CLK,
> + SYSTEM_PLL1_133M_CLK,
> + SYSTEM_PLL1_100M_CLK,
> + SYSTEM_PLL1_80M_CLK,
> + SYSTEM_PLL1_40M_CLK,
> + SYSTEM_PLL2_1000M_CLK,
> + SYSTEM_PLL2_500M_CLK,
> + SYSTEM_PLL2_333M_CLK,
> + SYSTEM_PLL2_250M_CLK,
> + SYSTEM_PLL2_200M_CLK,
> + SYSTEM_PLL2_166M_CLK,
> + SYSTEM_PLL2_125M_CLK,
> + SYSTEM_PLL2_100M_CLK,
> + SYSTEM_PLL2_50M_CLK,
> + SYSTEM_PLL3_CLK,
> + AUDIO_PLL1_CLK,
> + AUDIO_PLL2_CLK,
> + VIDEO_PLL_CLK,
> + OSC_32K_CLK,
> + EXT_CLK_1,
> + EXT_CLK_2,
> + EXT_CLK_3,
> + EXT_CLK_4,
> + OSC_27M_CLK,
> +};
> +
> +/* CCGR index */
> +enum clk_ccgr_index {
> + CCGR_DVFS = 0,
> + CCGR_ANAMIX = 1,
> + CCGR_CPU = 2,
> + CCGR_CSU = 4,
> + CCGR_DRAM1 = 5,
> + CCGR_DRAM2_OBSOLETE = 6,
> + CCGR_ECSPI1 = 7,
> + CCGR_ECSPI2 = 8,
> + CCGR_ECSPI3 = 9,
> + CCGR_ENET1 = 10,
> + CCGR_GPIO1 = 11,
> + CCGR_GPIO2 = 12,
> + CCGR_GPIO3 = 13,
> + CCGR_GPIO4 = 14,
> + CCGR_GPIO5 = 15,
> + CCGR_GPT1 = 16,
> + CCGR_GPT2 = 17,
> + CCGR_GPT3 = 18,
> + CCGR_GPT4 = 19,
> + CCGR_GPT5 = 20,
> + CCGR_GPT6 = 21,
> + CCGR_HS = 22,
> + CCGR_I2C1 = 23,
> + CCGR_I2C2 = 24,
> + CCGR_I2C3 = 25,
> + CCGR_I2C4 = 26,
> + CCGR_IOMUX = 27,
> + CCGR_IOMUX1 = 28,
> + CCGR_IOMUX2 = 29,
> + CCGR_IOMUX3 = 30,
> + CCGR_IOMUX4 = 31,
> + CCGR_M4 = 32,
> + CCGR_MU = 33,
> + CCGR_OCOTP = 34,
> + CCGR_OCRAM = 35,
> + CCGR_OCRAM_S = 36,
> + CCGR_PCIE = 37,
> + CCGR_PERFMON1 = 38,
> + CCGR_PERFMON2 = 39,
> + CCGR_PWM1 = 40,
> + CCGR_PWM2 = 41,
> + CCGR_PWM3 = 42,
> + CCGR_PWM4 = 43,
> + CCGR_QOS = 44,
> + CCGR_DISMIX = 45,
> + CCGR_MEGAMIX = 46,
> + CCGR_QSPI = 47,
> + CCGR_RAWNAND = 48,
> + CCGR_RDC = 49,
> + CCGR_ROM = 50,
> + CCGR_SAI1 = 51,
> + CCGR_SAI2 = 52,
> + CCGR_SAI3 = 53,
> + CCGR_SAI4 = 54,
> + CCGR_SAI5 = 55,
> + CCGR_SAI6 = 56,
> + CCGR_SCTR = 57,
> + CCGR_SDMA1 = 58,
> + CCGR_SDMA2 = 59,
> + CCGR_SEC_DEBUG = 60,
> + CCGR_SEMA1 = 61,
> + CCGR_SEMA2 = 62,
> + CCGR_SIM_DISPLAY = 63,
> + CCGR_SIM_ENET = 64,
> + CCGR_SIM_M = 65,
> + CCGR_SIM_MAIN = 66,
> + CCGR_SIM_S = 67,
> + CCGR_SIM_WAKEUP = 68,
> + CCGR_SIM_USB = 69,
> + CCGR_SIM_VPU = 70,
> + CCGR_SNVS = 71,
> + CCGR_TRACE = 72,
> + CCGR_UART1 = 73,
> + CCGR_UART2 = 74,
> + CCGR_UART3 = 75,
> + CCGR_UART4 = 76,
> + CCGR_USB_CTRL1 = 77,
> + CCGR_USB_CTRL2 = 78,
> + CCGR_USB_PHY1 = 79,
> + CCGR_USB_PHY2 = 80,
> + CCGR_USDHC1 = 81,
> + CCGR_USDHC2 = 82,
> + CCGR_WDOG1 = 83,
> + CCGR_WDOG2 = 84,
> + CCGR_WDOG3 = 85,
> + CCGR_VA53 = 86,
> + CCGR_GPU = 87,
> + CCGR_HEVC = 88,
> + CCGR_AVC = 89,
> + CCGR_VP9 = 90,
> + CCGR_HEVC_INTER = 91,
> + CCGR_GIC = 92,
> + CCGR_DISPLAY = 93,
> + CCGR_HDMI = 94,
> + CCGR_HDMI_PHY = 95,
> + CCGR_XTAL = 96,
> + CCGR_PLL = 97,
> + CCGR_TSENSOR = 98,
> + CCGR_VPU_DEC = 99,
> + CCGR_PCIE2 = 100,
> + CCGR_MIPI_CSI1 = 101,
> + CCGR_MIPI_CSI2 = 102,
> + CCGR_MAX,
> +};
> +
> +/* src index */
> +enum clk_src_index {
> + CLK_SRC_CKIL_SYNC_REQ = 0,
> + CLK_SRC_ARM_PLL_EN = 1,
> + CLK_SRC_GPU_PLL_EN = 2,
> + CLK_SRC_VPU_PLL_EN = 3,
> + CLK_SRC_DRAM_PLL_EN = 4,
> + CLK_SRC_SYSTEM_PLL1_EN = 5,
> + CLK_SRC_SYSTEM_PLL2_EN = 6,
> + CLK_SRC_SYSTEM_PLL3_EN = 7,
> + CLK_SRC_AUDIO_PLL1_EN = 8,
> + CLK_SRC_AUDIO_PLL2_EN = 9,
> + CLK_SRC_VIDEO_PLL1_EN = 10,
> + CLK_SRC_VIDEO_PLL2_EN = 11,
> + CLK_SRC_ARM_PLL = 12,
> + CLK_SRC_GPU_PLL = 13,
> + CLK_SRC_VPU_PLL = 14,
> + CLK_SRC_DRAM_PLL = 15,
> + CLK_SRC_SYSTEM_PLL1_800M = 16,
> + CLK_SRC_SYSTEM_PLL1_400M = 17,
> + CLK_SRC_SYSTEM_PLL1_266M = 18,
> + CLK_SRC_SYSTEM_PLL1_200M = 19,
> + CLK_SRC_SYSTEM_PLL1_160M = 20,
> + CLK_SRC_SYSTEM_PLL1_133M = 21,
> + CLK_SRC_SYSTEM_PLL1_100M = 22,
> + CLK_SRC_SYSTEM_PLL1_80M = 23,
> + CLK_SRC_SYSTEM_PLL1_40M = 24,
> + CLK_SRC_SYSTEM_PLL2_1000M = 25,
> + CLK_SRC_SYSTEM_PLL2_500M = 26,
> + CLK_SRC_SYSTEM_PLL2_333M = 27,
> + CLK_SRC_SYSTEM_PLL2_250M = 28,
> + CLK_SRC_SYSTEM_PLL2_200M = 29,
> + CLK_SRC_SYSTEM_PLL2_166M = 30,
> + CLK_SRC_SYSTEM_PLL2_125M = 31,
> + CLK_SRC_SYSTEM_PLL2_100M = 32,
> + CLK_SRC_SYSTEM_PLL2_50M = 33,
> + CLK_SRC_SYSTEM_PLL3 = 34,
> + CLK_SRC_AUDIO_PLL1 = 35,
> + CLK_SRC_AUDIO_PLL2 = 36,
> + CLK_SRC_VIDEO_PLL1 = 37,
> + CLK_SRC_VIDEO_PLL2 = 38,
> + CLK_SRC_OSC_25M = 39,
> + CLK_SRC_OSC_27M = 40,
> +};
ok, fine
> +
> +enum root_pre_div {
> + CLK_ROOT_PRE_DIV1 = 0,
> + CLK_ROOT_PRE_DIV2,
> + CLK_ROOT_PRE_DIV3,
> + CLK_ROOT_PRE_DIV4,
> + CLK_ROOT_PRE_DIV5,
> + CLK_ROOT_PRE_DIV6,
> + CLK_ROOT_PRE_DIV7,
> + CLK_ROOT_PRE_DIV8,
> +};
> +
> +enum root_post_div {
> + CLK_ROOT_POST_DIV1 = 0,
> + CLK_ROOT_POST_DIV2,
> + CLK_ROOT_POST_DIV3,
> + CLK_ROOT_POST_DIV4,
> + CLK_ROOT_POST_DIV5,
> + CLK_ROOT_POST_DIV6,
> + CLK_ROOT_POST_DIV7,
> + CLK_ROOT_POST_DIV8,
> + CLK_ROOT_POST_DIV9,
> + CLK_ROOT_POST_DIV10,
> + CLK_ROOT_POST_DIV11,
> + CLK_ROOT_POST_DIV12,
> + CLK_ROOT_POST_DIV13,
> + CLK_ROOT_POST_DIV14,
> + CLK_ROOT_POST_DIV15,
> + CLK_ROOT_POST_DIV16,
> + CLK_ROOT_POST_DIV17,
> + CLK_ROOT_POST_DIV18,
> + CLK_ROOT_POST_DIV19,
> + CLK_ROOT_POST_DIV20,
> + CLK_ROOT_POST_DIV21,
> + CLK_ROOT_POST_DIV22,
> + CLK_ROOT_POST_DIV23,
> + CLK_ROOT_POST_DIV24,
> + CLK_ROOT_POST_DIV25,
> + CLK_ROOT_POST_DIV26,
> + CLK_ROOT_POST_DIV27,
> + CLK_ROOT_POST_DIV28,
> + CLK_ROOT_POST_DIV29,
> + CLK_ROOT_POST_DIV30,
> + CLK_ROOT_POST_DIV31,
> + CLK_ROOT_POST_DIV32,
> + CLK_ROOT_POST_DIV33,
> + CLK_ROOT_POST_DIV34,
> + CLK_ROOT_POST_DIV35,
> + CLK_ROOT_POST_DIV36,
> + CLK_ROOT_POST_DIV37,
> + CLK_ROOT_POST_DIV38,
> + CLK_ROOT_POST_DIV39,
> + CLK_ROOT_POST_DIV40,
> + CLK_ROOT_POST_DIV41,
> + CLK_ROOT_POST_DIV42,
> + CLK_ROOT_POST_DIV43,
> + CLK_ROOT_POST_DIV44,
> + CLK_ROOT_POST_DIV45,
> + CLK_ROOT_POST_DIV46,
> + CLK_ROOT_POST_DIV47,
> + CLK_ROOT_POST_DIV48,
> + CLK_ROOT_POST_DIV49,
> + CLK_ROOT_POST_DIV50,
> + CLK_ROOT_POST_DIV51,
> + CLK_ROOT_POST_DIV52,
> + CLK_ROOT_POST_DIV53,
> + CLK_ROOT_POST_DIV54,
> + CLK_ROOT_POST_DIV55,
> + CLK_ROOT_POST_DIV56,
> + CLK_ROOT_POST_DIV57,
> + CLK_ROOT_POST_DIV58,
> + CLK_ROOT_POST_DIV59,
> + CLK_ROOT_POST_DIV60,
> + CLK_ROOT_POST_DIV61,
> + CLK_ROOT_POST_DIV62,
> + CLK_ROOT_POST_DIV63,
> + CLK_ROOT_POST_DIV64,
> +};
I am asking myself which is the information carry out by these two
previous enum. It does not make a big sense IMHO. Why do we need a
CLK_ROOT_POST_DIVX to store the value (x-1) ?
> +
> +struct clk_root_map {
> + enum clk_root_index entry;
> + enum clk_slice_type slice_type;
> + u32 slice_index;
> + u8 src_mux[8];
> +};
> +
> +struct ccm_ccgr {
> + u32 ccgr;
> + u32 ccgr_set;
> + u32 ccgr_clr;
> + u32 ccgr_tog;
> +};
> +
> +struct ccm_root {
> + u32 target_root;
> + u32 target_root_set;
> + u32 target_root_clr;
> + u32 target_root_tog;
> + u32 misc;
> + u32 misc_set;
> + u32 misc_clr;
> + u32 misc_tog;
> + u32 nm_post;
> + u32 nm_post_root_set;
> + u32 nm_post_root_clr;
> + u32 nm_post_root_tog;
> + u32 nm_pre;
> + u32 nm_pre_root_set;
> + u32 nm_pre_root_clr;
> + u32 nm_pre_root_tog;
> + u32 db_post;
> + u32 db_post_root_set;
> + u32 db_post_root_clr;
> + u32 db_post_root_tog;
> + u32 db_pre;
> + u32 db_pre_root_set;
> + u32 db_pre_root_clr;
> + u32 db_pre_root_tog;
> + u32 reserved[4];
> + u32 access_ctrl;
> + u32 access_ctrl_root_set;
> + u32 access_ctrl_root_clr;
> + u32 access_ctrl_root_tog;
> +};
> +
> +struct ccm_reg {
> + u32 reserved_0[4096];
> + struct ccm_ccgr ccgr_array[192];
> + u32 reserved_1[3328];
> + struct ccm_root core_root[5];
> + u32 reserved_2[352];
> + struct ccm_root bus_root[12];
> + u32 reserved_3[128];
> + struct ccm_root ahb_ipg_root[4];
> + u32 reserved_4[384];
> + struct ccm_root dram_sel;
> + struct ccm_root core_sel;
> + u32 reserved_5[448];
> + struct ccm_root ip_root[78];
> +};
> +
> +#define CCGR_CLK_ON_MASK 0x03
> +#define CLK_SRC_ON_MASK 0x03
> +
> +#define CLK_ROOT_ON BIT(28)
> +#define CLK_ROOT_OFF (0 << 28)
> +#define CLK_ROOT_ENABLE_MASK BIT(28)
> +#define CLK_ROOT_ENABLE_SHIFT 28
> +#define CLK_ROOT_SOURCE_SEL(n) (((n) & 0x7) << 24)
> +
> +/* For SEL, only use 1 bit */
> +#define CLK_ROOT_SRC_MUX_MASK 0x07000000
> +#define CLK_ROOT_SRC_MUX_SHIFT 24
> +#define CLK_ROOT_SRC_0 0x00000000
> +#define CLK_ROOT_SRC_1 0x01000000
> +#define CLK_ROOT_SRC_2 0x02000000
> +#define CLK_ROOT_SRC_3 0x03000000
> +#define CLK_ROOT_SRC_4 0x04000000
> +#define CLK_ROOT_SRC_5 0x05000000
> +#define CLK_ROOT_SRC_6 0x06000000
> +#define CLK_ROOT_SRC_7 0x07000000
> +
> +#define CLK_ROOT_PRE_DIV_MASK (0x00070000)
> +#define CLK_ROOT_PRE_DIV_SHIFT 16
> +#define CLK_ROOT_PRE_DIV(n) (((n) << 16) & 0x00070000)
> +
> +#define CLK_ROOT_AUDO_SLOW_EN 0x1000
> +
> +#define CLK_ROOT_AUDO_DIV_MASK 0x700
> +#define CLK_ROOT_AUDO_DIV_SHIFT 0x8
> +#define CLK_ROOT_AUDO_DIV(n) (((n) << 8) & 0x700)
> +
> +/* For CORE: mask is 0x7; For IPG: mask is 0x3 */
> +#define CLK_ROOT_POST_DIV_MASK 0x3f
> +#define CLK_ROOT_CORE_POST_DIV_MASK 0x7
> +#define CLK_ROOT_IPG_POST_DIV_MASK 0x3
> +#define CLK_ROOT_POST_DIV_SHIFT 0
> +#define CLK_ROOT_POST_DIV(n) ((n) & 0x3f)
> +
> +/* AUDIO PLL1/2 VIDEO PLL1 GPU PLL VPU PLL ARM PLL*/
> +#define FRAC_PLL_LOCK_MASK BIT(31)
> +#define FRAC_PLL_CLKE_MASK BIT(21)
> +#define FRAC_PLL_PD_MASK BIT(19)
> +#define FRAC_PLL_REFCLK_SEL_MASK BIT(16)
> +#define FRAC_PLL_LOCK_SEL_MASK BIT(15)
> +#define FRAC_PLL_BYPASS_MASK BIT(14)
> +#define FRAC_PLL_COUNTCLK_SEL_MASK BIT(13)
> +#define FRAC_PLL_NEWDIV_VAL_MASK BIT(12)
> +#define FRAC_PLL_NEWDIV_ACK_MASK BIT(11)
> +#define FRAC_PLL_REFCLK_DIV_VAL(n) (((n) << 5) & (0x3f << 5))
> +#define FRAC_PLL_REFCLK_DIV_VAL_MASK (0x3f << 5)
> +#define FRAC_PLL_REFCLK_DIV_VAL_SHIFT 5
> +#define FRAC_PLL_OUTPUT_DIV_VAL_MASK 0x1f
> +#define FRAC_PLL_OUTPUT_DIV_VAL(n) ((n) & 0x1f)
> +
> +#define FRAC_PLL_REFCLK_SEL_OSC_25M (0 << 16)
> +#define FRAC_PLL_REFCLK_SEL_OSC_27M BIT(16)
> +#define FRAC_PLL_REFCLK_SEL_HDMI_PHY_27M (2 << 16)
> +#define FRAC_PLL_REFCLK_SEL_CLK_PN (3 << 16)
> +
> +#define FRAC_PLL_FRAC_DIV_CTL_MASK (0x1ffffff << 7)
> +#define FRAC_PLL_FRAC_DIV_CTL_SHIFT 7
> +#define FRAC_PLL_INT_DIV_CTL_MASK 0x7f
> +#define FRAC_PLL_INT_DIV_CTL_VAL(n) ((n) & 0x7f)
> +
> +/* SYS PLL1/2/3 VIDEO PLL2 DRAM PLL */
> +#define SSCG_PLL_LOCK_MASK BIT(31)
> +#define SSCG_PLL_CLKE_MASK BIT(25)
> +#define SSCG_PLL_DIV2_CLKE_MASK BIT(23)
> +#define SSCG_PLL_DIV3_CLKE_MASK BIT(21)
> +#define SSCG_PLL_DIV4_CLKE_MASK BIT(19)
> +#define SSCG_PLL_DIV5_CLKE_MASK BIT(17)
> +#define SSCG_PLL_DIV6_CLKE_MASK BIT(15)
> +#define SSCG_PLL_DIV8_CLKE_MASK BIT(13)
> +#define SSCG_PLL_DIV10_CLKE_MASK BIT(11)
> +#define SSCG_PLL_DIV20_CLKE_MASK BIT(9)
> +#define SSCG_PLL_VIDEO_PLL2_CLKE_MASK BIT(9)
> +#define SSCG_PLL_DRAM_PLL_CLKE_MASK BIT(9)
> +#define SSCG_PLL_PLL3_CLKE_MASK BIT(9)
> +#define SSCG_PLL_PD_MASK BIT(7)
> +#define SSCG_PLL_BYPASS1_MASK BIT(5)
> +#define SSCG_PLL_BYPASS2_MASK BIT(4)
> +#define SSCG_PLL_LOCK_SEL_MASK BIT(3)
> +#define SSCG_PLL_COUNTCLK_SEL_MASK BIT(2)
> +#define SSCG_PLL_REFCLK_SEL_MASK 0x3
> +#define SSCG_PLL_REFCLK_SEL_OSC_25M (0 << 16)
> +#define SSCG_PLL_REFCLK_SEL_OSC_27M BIT(16)
> +#define SSCG_PLL_REFCLK_SEL_HDMI_PHY_27M (2 << 16)
> +#define SSCG_PLL_REFCLK_SEL_CLK_PN (3 << 16)
> +
> +#define SSCG_PLL_SSDS_MASK BIT(8)
> +#define SSCG_PLL_SSMD_MASK (0x7 << 5)
> +#define SSCG_PLL_SSMF_MASK (0xf << 1)
> +#define SSCG_PLL_SSE_MASK 0x1
> +
> +#define SSCG_PLL_REF_DIVR1_MASK (0x7 << 25)
> +#define SSCG_PLL_REF_DIVR1_SHIFT 25
> +#define SSCG_PLL_REF_DIVR1_VAL(n) (((n) << 25) & SSCG_PLL_REF_DIVR1_MASK)
> +#define SSCG_PLL_REF_DIVR2_MASK (0x3f << 19)
> +#define SSCG_PLL_REF_DIVR2_SHIFT 19
> +#define SSCG_PLL_REF_DIVR2_VAL(n) (((n) << 19) & SSCG_PLL_REF_DIVR2_MASK)
> +#define SSCG_PLL_FEEDBACK_DIV_F1_MASK (0x3f << 13)
> +#define SSCG_PLL_FEEDBACK_DIV_F1_SHIFT 13
> +#define SSCG_PLL_FEEDBACK_DIV_F1_VAL(n) (((n) << 13) & \
> + SSCG_PLL_FEEDBACK_DIV_F1_MASK)
> +#define SSCG_PLL_FEEDBACK_DIV_F2_MASK (0x3f << 7)
> +#define SSCG_PLL_FEEDBACK_DIV_F2_SHIFT 7
> +#define SSCG_PLL_FEEDBACK_DIV_F2_VAL(n) (((n) << 7) & \
> + SSCG_PLL_FEEDBACK_DIV_F2_MASK)
> +#define SSCG_PLL_OUTPUT_DIV_VAL_MASK (0x3f << 1)
> +#define SSCG_PLL_OUTPUT_DIV_VAL_SHIFT 1
> +#define SSCG_PLL_OUTPUT_DIV_VAL(n) (((n) << 1) & \
> + SSCG_PLL_OUTPUT_DIV_VAL_MASK)
> +#define SSCG_PLL_FILTER_RANGE_MASK 0x1
> +
> +#define HW_DIGPROG_MAJOR_UPPER_MASK (0xff << 16)
> +#define HW_DIGPROG_MAJOR_LOWER_MASK (0xff << 8)
> +#define HW_DIGPROG_MINOR_MASK 0xff
> +
> +#define HW_OSC_27M_CLKE_MASK BIT(4)
> +#define HW_OSC_25M_CLKE_MASK BIT(2)
> +#define HW_OSC_32K_SEL_MASK 0x1
> +#define HW_OSC_32K_SEL_RTC 0x1
> +#define HW_OSC_32K_SEL_25M_DIV800 0x0
> +
> +#define HW_FRAC_ARM_PLL_DIV_MASK (0x7 << 20)
> +#define HW_FRAC_ARM_PLL_DIV_SHIFT 20
> +#define HW_FRAC_VPU_PLL_DIV_MASK (0x7 << 16)
> +#define HW_FRAC_VPU_PLL_DIV_SHIFT 16
> +#define HW_FRAC_GPU_PLL_DIV_MASK (0x7 << 12)
> +#define HW_FRAC_GPU_PLL_DIV_SHIFT 12
> +#define HW_FRAC_VIDEO_PLL1_DIV_MASK (0x7 << 10)
> +#define HW_FRAC_VIDEO_PLL1_DIV_SHIFT 10
> +#define HW_FRAC_AUDIO_PLL2_DIV_MASK (0x7 << 4)
> +#define HW_FRAC_AUDIO_PLL2_DIV_SHIFT 4
> +#define HW_FRAC_AUDIO_PLL1_DIV_MASK 0x7
> +#define HW_FRAC_AUDIO_PLL1_DIV_SHIFT 0
> +
> +#define HW_SSCG_VIDEO_PLL2_DIV_MASK (0x7 << 16)
> +#define HW_SSCG_VIDEO_PLL2_DIV_SHIFT 16
> +#define HW_SSCG_DRAM_PLL_DIV_MASK (0x7 << 14)
> +#define HW_SSCG_DRAM_PLL_DIV_SHIFT 14
> +#define HW_SSCG_SYSTEM_PLL3_DIV_MASK (0x7 << 8)
> +#define HW_SSCG_SYSTEM_PLL3_DIV_SHIFT 8
> +#define HW_SSCG_SYSTEM_PLL2_DIV_MASK (0x7 << 4)
> +#define HW_SSCG_SYSTEM_PLL2_DIV_SHIFT 4
> +#define HW_SSCG_SYSTEM_PLL1_DIV_MASK 0x7
> +#define HW_SSCG_SYSTEM_PLL1_DIV_SHIFT 0
> +
> +#define ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK 0x01000000
> +#define ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK 0x02000000
> +#define ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK 0x03000000
> +#define ENET_AXI_CLK_ROOT_FROM_PLL_SYS_PFD4_CLK 0x07000000
> +#define ENET_AXI_CLK_ROOT_FROM_SYS1_PLL_266M 0x01000000
> +#define ENET1_TIME_CLK_ROOT_FROM_PLL_ENET_MAIN_100M_CLK 0x01000000
> +#define ENET_PHY_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK 0x01000000
> +
> +enum enet_freq {
> + ENET_25MHZ = 0,
> + ENET_50MHZ,
> + ENET_125MHZ,
> +};
Soon or later we should move this enum where it belongs to (FEC), we
duplicate this for all SOCs.
> +
> +enum frac_pll_out_val {
> + FRAC_PLL_OUT_1000M,
> + FRAC_PLL_OUT_1600M,
> +};
> +
> +u32 imx_get_fecclk(void);
> +u32 imx_get_uartclk(void);
> +int clock_init(void);
> +void init_clk_usdhc(u32 index);
> +void init_uart_clk(u32 index);
> +void init_wdog_clk(void);
> +unsigned int mxc_get_clock(enum clk_root_index clk);
> +int clock_enable(enum clk_ccgr_index index, bool enable);
> +int clock_root_enabled(enum clk_root_index clock_id);
> +int clock_root_cfg(enum clk_root_index clock_id, enum root_pre_div pre_div,
> + enum root_post_div post_div, enum clk_root_src clock_src);
> +int clock_set_target_val(enum clk_root_index clock_id, u32 val);
> +int clock_get_target_val(enum clk_root_index clock_id, u32 *val);
> +int clock_get_prediv(enum clk_root_index clock_id, enum root_pre_div *pre_div);
> +int clock_get_postdiv(enum clk_root_index clock_id,
> + enum root_post_div *post_div);
> +int clock_get_src(enum clk_root_index clock_id, enum clk_root_src *p_clock_src);
> +void mxs_set_lcdclk(u32 base_addr, u32 freq);
> +int set_clk_qspi(void);
> +void enable_ocotp_clk(unsigned char enable);
> +int enable_i2c_clk(unsigned char enable, unsigned int i2c_num);
> +int set_clk_enet(enum enet_freq type);
Wow ! We export a very large API, much more as on other i.MXes. I am
bothering if we really need this, that is if a board maintainer (or
driver, of course) need all of them. Some of them are just between
clock.c and clock_slice.c. We maybe could add a clock_priv.h that is
shared between internal modules in mx8m, but are not exported globally
because they are not needed. Goal is to have the cleanest interface for
new MX8M boards that we can have.
> +#endif
> diff --git a/arch/arm/mach-imx/mx8m/Makefile b/arch/arm/mach-imx/mx8m/Makefile
> new file mode 100644
> index 0000000000..05f38842f0
> --- /dev/null
> +++ b/arch/arm/mach-imx/mx8m/Makefile
> @@ -0,0 +1,7 @@
> +#
> +# Copyright 2017 NXP
> +#
> +# SPDX-License-Identifier: GPL-2.0+
> +#
> +
> +obj-y += clock.o clock_slice.o
> diff --git a/arch/arm/mach-imx/mx8m/clock.c b/arch/arm/mach-imx/mx8m/clock.c
> new file mode 100644
> index 0000000000..c56ba99d5c
> --- /dev/null
> +++ b/arch/arm/mach-imx/mx8m/clock.c
> @@ -0,0 +1,795 @@
> +/*
> + * Copyright 2017 NXP
> + *
> + * Peng Fan <peng.fan at nxp.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/imx-regs.h>
> +#include <asm/io.h>
> +#include <asm/arch/sys_proto.h>
> +#include <errno.h>
> +#include <linux/iopoll.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static struct anamix_pll *ana_pll = (struct anamix_pll *)ANATOP_BASE_ADDR;
> +
> +static u32 decode_frac_pll(enum clk_root_src frac_pll)
> +{
> + u32 pll_cfg0, pll_cfg1, pllout;
> + u32 pll_refclk_sel, pll_refclk;
> + u32 divr_val, divq_val, divf_val, divff, divfi;
> + u32 pllout_div_shift, pllout_div_mask, pllout_div;
> +
> + switch (frac_pll) {
> + case ARM_PLL_CLK:
> + pll_cfg0 = readl(&ana_pll->arm_pll_cfg0);
> + pll_cfg1 = readl(&ana_pll->arm_pll_cfg1);
> + pllout_div_shift = HW_FRAC_ARM_PLL_DIV_SHIFT;
> + pllout_div_mask = HW_FRAC_ARM_PLL_DIV_MASK;
> + break;
> + default:
> + printf("Frac PLL %d not supporte\n", frac_pll);
> + return 0;
> + }
> +
> + pllout_div = readl(&ana_pll->frac_pllout_div_cfg);
> + pllout_div = (pllout_div & pllout_div_mask) >> pllout_div_shift;
> +
> + /* Power down */
> + if (pll_cfg0 & FRAC_PLL_PD_MASK)
> + return 0;
> +
> + /* output not enabled */
> + if ((pll_cfg0 & FRAC_PLL_CLKE_MASK) == 0)
> + return 0;
> +
> + pll_refclk_sel = pll_cfg0 & FRAC_PLL_REFCLK_SEL_MASK;
> +
> + if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_OSC_25M)
> + pll_refclk = 25000000u;
> + else if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_OSC_27M)
> + pll_refclk = 27000000u;
> + else if (pll_refclk_sel == FRAC_PLL_REFCLK_SEL_HDMI_PHY_27M)
> + pll_refclk = 27000000u;
> + else
> + pll_refclk = 0;
> +
> + if (pll_cfg0 & FRAC_PLL_BYPASS_MASK)
> + return pll_refclk;
> +
> + divr_val = (pll_cfg0 & FRAC_PLL_REFCLK_DIV_VAL_MASK) >>
> + FRAC_PLL_REFCLK_DIV_VAL_SHIFT;
> + divq_val = pll_cfg0 & FRAC_PLL_OUTPUT_DIV_VAL_MASK;
> +
> + divff = (pll_cfg1 & FRAC_PLL_FRAC_DIV_CTL_MASK) >>
> + FRAC_PLL_FRAC_DIV_CTL_SHIFT;
> + divfi = pll_cfg1 & FRAC_PLL_INT_DIV_CTL_MASK;
> +
> + divf_val = 1 + divfi + divff / (1 << 24);
> +
> + pllout = pll_refclk / (divr_val + 1) * 8 * divf_val /
> + ((divq_val + 1) * 2);
> +
> + return pllout / (pllout_div + 1);
> +}
> +
> +static u32 decode_sscg_pll(enum clk_root_src sscg_pll)
> +{
> + u32 pll_cfg0, pll_cfg1, pll_cfg2;
> + u32 pll_refclk_sel, pll_refclk;
> + u32 divr1, divr2, divf1, divf2, divq, div;
> + u32 sse;
> + u32 pll_clke;
> + u32 pllout_div_shift, pllout_div_mask, pllout_div;
> + u32 pllout;
> +
> + switch (sscg_pll) {
> + case SYSTEM_PLL1_800M_CLK:
> + case SYSTEM_PLL1_400M_CLK:
> + case SYSTEM_PLL1_266M_CLK:
> + case SYSTEM_PLL1_200M_CLK:
> + case SYSTEM_PLL1_160M_CLK:
> + case SYSTEM_PLL1_133M_CLK:
> + case SYSTEM_PLL1_100M_CLK:
> + case SYSTEM_PLL1_80M_CLK:
> + case SYSTEM_PLL1_40M_CLK:
> + pll_cfg0 = readl(&ana_pll->sys_pll1_cfg0);
> + pll_cfg1 = readl(&ana_pll->sys_pll1_cfg1);
> + pll_cfg2 = readl(&ana_pll->sys_pll1_cfg2);
> + pllout_div_shift = HW_SSCG_SYSTEM_PLL1_DIV_SHIFT;
> + pllout_div_mask = HW_SSCG_SYSTEM_PLL1_DIV_MASK;
> + break;
> + case SYSTEM_PLL2_1000M_CLK:
> + case SYSTEM_PLL2_500M_CLK:
> + case SYSTEM_PLL2_333M_CLK:
> + case SYSTEM_PLL2_250M_CLK:
> + case SYSTEM_PLL2_200M_CLK:
> + case SYSTEM_PLL2_166M_CLK:
> + case SYSTEM_PLL2_125M_CLK:
> + case SYSTEM_PLL2_100M_CLK:
> + case SYSTEM_PLL2_50M_CLK:
> + pll_cfg0 = readl(&ana_pll->sys_pll2_cfg0);
> + pll_cfg1 = readl(&ana_pll->sys_pll2_cfg1);
> + pll_cfg2 = readl(&ana_pll->sys_pll2_cfg2);
> + pllout_div_shift = HW_SSCG_SYSTEM_PLL2_DIV_SHIFT;
> + pllout_div_mask = HW_SSCG_SYSTEM_PLL2_DIV_MASK;
> + break;
> + case SYSTEM_PLL3_CLK:
> + pll_cfg0 = readl(&ana_pll->sys_pll3_cfg0);
> + pll_cfg1 = readl(&ana_pll->sys_pll3_cfg1);
> + pll_cfg2 = readl(&ana_pll->sys_pll3_cfg2);
> + pllout_div_shift = HW_SSCG_SYSTEM_PLL3_DIV_SHIFT;
> + pllout_div_mask = HW_SSCG_SYSTEM_PLL3_DIV_MASK;
> + break;
> + case DRAM_PLL1_CLK:
> + pll_cfg0 = readl(&ana_pll->dram_pll_cfg0);
> + pll_cfg1 = readl(&ana_pll->dram_pll_cfg1);
> + pll_cfg2 = readl(&ana_pll->dram_pll_cfg2);
> + pllout_div_shift = HW_SSCG_DRAM_PLL_DIV_SHIFT;
> + pllout_div_mask = HW_SSCG_DRAM_PLL_DIV_MASK;
> + break;
The code in the switch looks a bit clumsy. The same action is done in
all cases.
> + default:
> + printf("sscg pll %d not supporte\n", sscg_pll);
> + return 0;
> + }
> +
> + switch (sscg_pll) {
> + case DRAM_PLL1_CLK:
> + pll_clke = SSCG_PLL_DRAM_PLL_CLKE_MASK;
> + div = 1;
> + break;
> + case SYSTEM_PLL3_CLK:
> + pll_clke = SSCG_PLL_PLL3_CLKE_MASK;
> + div = 1;
> + break;
> + case SYSTEM_PLL2_1000M_CLK:
> + case SYSTEM_PLL1_800M_CLK:
> + pll_clke = SSCG_PLL_CLKE_MASK;
> + div = 1;
> + break;
> + case SYSTEM_PLL2_500M_CLK:
> + case SYSTEM_PLL1_400M_CLK:
> + pll_clke = SSCG_PLL_DIV2_CLKE_MASK;
> + div = 2;
> + break;
> + case SYSTEM_PLL2_333M_CLK:
> + case SYSTEM_PLL1_266M_CLK:
> + pll_clke = SSCG_PLL_DIV3_CLKE_MASK;
> + div = 3;
> + break;
> + case SYSTEM_PLL2_250M_CLK:
> + case SYSTEM_PLL1_200M_CLK:
> + pll_clke = SSCG_PLL_DIV4_CLKE_MASK;
> + div = 4;
> + break;
> + case SYSTEM_PLL2_200M_CLK:
> + case SYSTEM_PLL1_160M_CLK:
> + pll_clke = SSCG_PLL_DIV5_CLKE_MASK;
> + div = 5;
> + break;
> + case SYSTEM_PLL2_166M_CLK:
> + case SYSTEM_PLL1_133M_CLK:
> + pll_clke = SSCG_PLL_DIV6_CLKE_MASK;
> + div = 6;
> + break;
> + case SYSTEM_PLL2_125M_CLK:
> + case SYSTEM_PLL1_100M_CLK:
> + pll_clke = SSCG_PLL_DIV8_CLKE_MASK;
> + div = 8;
> + break;
> + case SYSTEM_PLL2_100M_CLK:
> + case SYSTEM_PLL1_80M_CLK:
> + pll_clke = SSCG_PLL_DIV10_CLKE_MASK;
> + div = 10;
> + break;
> + case SYSTEM_PLL2_50M_CLK:
> + case SYSTEM_PLL1_40M_CLK:
> + pll_clke = SSCG_PLL_DIV20_CLKE_MASK;
> + div = 20;
> + break;
> + default:
> + printf("sscg pll %d not supporte\n", sscg_pll);
> + return 0;
> + }
> +
> + /* Power down */
> + if (pll_cfg0 & SSCG_PLL_PD_MASK)
> + return 0;
> +
> + /* output not enabled */
> + if ((pll_cfg0 & pll_clke) == 0)
> + return 0;
> +
> + pllout_div = readl(&ana_pll->sscg_pllout_div_cfg);
> + pllout_div = (pllout_div & pllout_div_mask) >> pllout_div_shift;
> +
> + pll_refclk_sel = pll_cfg0 & SSCG_PLL_REFCLK_SEL_MASK;
> +
> + if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_OSC_25M)
> + pll_refclk = 25000000u;
> + else if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_OSC_27M)
> + pll_refclk = 27000000u;
> + else if (pll_refclk_sel == SSCG_PLL_REFCLK_SEL_HDMI_PHY_27M)
> + pll_refclk = 27000000u;
> + else
> + pll_refclk = 0;
> +
> + /* We assume bypass1/2 are the same value */
> + if ((pll_cfg0 & SSCG_PLL_BYPASS1_MASK) ||
> + (pll_cfg0 & SSCG_PLL_BYPASS2_MASK))
> + return pll_refclk;
> +
> + divr1 = (pll_cfg2 & SSCG_PLL_REF_DIVR1_MASK) >>
> + SSCG_PLL_REF_DIVR1_SHIFT;
> + divr2 = (pll_cfg2 & SSCG_PLL_REF_DIVR2_MASK) >>
> + SSCG_PLL_REF_DIVR2_SHIFT;
> + divf1 = (pll_cfg2 & SSCG_PLL_FEEDBACK_DIV_F1_MASK) >>
> + SSCG_PLL_FEEDBACK_DIV_F1_SHIFT;
> + divf2 = (pll_cfg2 & SSCG_PLL_FEEDBACK_DIV_F2_MASK) >>
> + SSCG_PLL_FEEDBACK_DIV_F2_SHIFT;
> + divq = (pll_cfg2 & SSCG_PLL_OUTPUT_DIV_VAL_MASK) >>
> + SSCG_PLL_OUTPUT_DIV_VAL_SHIFT;
> + sse = pll_cfg1 & SSCG_PLL_SSE_MASK;
> +
> + if (sse)
> + sse = 8;
> + else
> + sse = 2;
> +
> + pllout = pll_refclk / (divr1 + 1) * sse * (divf1 + 1) /
> + (divr2 + 1) * (divf2 + 1) / (divq + 1);
> +
> + return pllout / (pllout_div + 1) / div;
> +}
> +
> +static u32 get_root_src_clk(enum clk_root_src root_src)
> +{
> + switch (root_src) {
> + case OSC_25M_CLK:
> + return 25000000;
> + case OSC_27M_CLK:
> + return 25000000;
> + case OSC_32K_CLK:
> + return 32000;
> + case ARM_PLL_CLK:
> + return decode_frac_pll(root_src);
> + case SYSTEM_PLL1_800M_CLK:
> + case SYSTEM_PLL1_400M_CLK:
> + case SYSTEM_PLL1_266M_CLK:
> + case SYSTEM_PLL1_200M_CLK:
> + case SYSTEM_PLL1_160M_CLK:
> + case SYSTEM_PLL1_133M_CLK:
> + case SYSTEM_PLL1_100M_CLK:
> + case SYSTEM_PLL1_80M_CLK:
> + case SYSTEM_PLL1_40M_CLK:
> + case SYSTEM_PLL2_1000M_CLK:
> + case SYSTEM_PLL2_500M_CLK:
> + case SYSTEM_PLL2_333M_CLK:
> + case SYSTEM_PLL2_250M_CLK:
> + case SYSTEM_PLL2_200M_CLK:
> + case SYSTEM_PLL2_166M_CLK:
> + case SYSTEM_PLL2_125M_CLK:
> + case SYSTEM_PLL2_100M_CLK:
> + case SYSTEM_PLL2_50M_CLK:
> + case SYSTEM_PLL3_CLK:
> + return decode_sscg_pll(root_src);
> + default:
> + return 0;
> + }
> +
> + return 0;
> +}
> +
> +static u32 get_root_clk(enum clk_root_index clock_id)
> +{
> + enum clk_root_src root_src;
> + u32 post_podf, pre_podf, root_src_clk;
> +
> + if (clock_root_enabled(clock_id) <= 0)
> + return 0;
> +
> + if (clock_get_prediv(clock_id, &pre_podf) < 0)
> + return 0;
> +
> + if (clock_get_postdiv(clock_id, &post_podf) < 0)
> + return 0;
> +
> + if (clock_get_src(clock_id, &root_src) < 0)
> + return 0;
> +
> + root_src_clk = get_root_src_clk(root_src);
> +
> + return root_src_clk / (post_podf + 1) / (pre_podf + 1);
> +}
> +
> +#ifdef CONFIG_MXC_OCOTP
> +void enable_ocotp_clk(unsigned char enable)
> +{
> + clock_enable(CCGR_OCOTP, !!enable);
> +}
> +#endif
> +
> +int enable_i2c_clk(unsigned char enable, unsigned int i2c_num)
> +{
> + /* 0 - 3 is valid i2c num */
> + if (i2c_num > 3)
> + return -EINVAL;
> +
> + clock_enable(CCGR_I2C1 + i2c_num, !!enable);
> +
> + return 0;
> +}
> +
> +unsigned int mxc_get_clock(enum clk_root_index clk)
> +{
> + u32 val;
> +
> + if (clk >= CLK_ROOT_MAX)
> + return 0;
> +
> + if (clk == MXC_ARM_CLK)
> + return get_root_clk(ARM_A53_CLK_ROOT);
> +
> + if (clk == MXC_IPG_CLK) {
> + clock_get_target_val(IPG_CLK_ROOT, &val);
> + val = val & 0x3;
> + return get_root_clk(AHB_CLK_ROOT) / (val + 1);
> + }
> +
> + return get_root_clk(clk);
> +}
> +
> +u32 imx_get_uartclk(void)
> +{
> + return mxc_get_clock(UART1_CLK_ROOT);
> +}
> +
> +void mxs_set_lcdclk(u32 base_addr, u32 freq)
> +{
> + /*
> + * LCDIF_PIXEL_CLK: select 800MHz root clock,
> + * select pre divider 8, output is 100 MHz
> + */
> + clock_set_target_val(LCDIF_PIXEL_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(4) |
> + CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV8));
> +}
> +
> +void init_wdog_clk(void)
> +{
> + clock_enable(CCGR_WDOG1, 0);
> + clock_enable(CCGR_WDOG2, 0);
> + clock_enable(CCGR_WDOG3, 0);
> + clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(0));
> + clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(0));
> + clock_set_target_val(WDOG_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(0));
> + clock_enable(CCGR_WDOG1, 1);
> + clock_enable(CCGR_WDOG2, 1);
> + clock_enable(CCGR_WDOG3, 1);
> +}
> +
> +void init_usb_clk(void)
> +{
> + if (!is_usb_boot()) {
> + clock_enable(CCGR_USB_CTRL1, 0);
> + clock_enable(CCGR_USB_CTRL2, 0);
> + clock_enable(CCGR_USB_PHY1, 0);
> + clock_enable(CCGR_USB_PHY2, 0);
> + /* 500MHz */
> + clock_set_target_val(USB_BUS_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(1));
> + /* 100MHz */
> + clock_set_target_val(USB_CORE_REF_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(1));
> + /* 100MHz */
> + clock_set_target_val(USB_PHY_REF_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(1));
> + clock_enable(CCGR_USB_CTRL1, 1);
> + clock_enable(CCGR_USB_CTRL2, 1);
> + clock_enable(CCGR_USB_PHY1, 1);
> + clock_enable(CCGR_USB_PHY2, 1);
> + }
> +}
> +
> +void init_uart_clk(u32 index)
> +{
> + /* Set uart clock root 25M OSC */
> + switch (index) {
> + case 0:
> + clock_enable(CCGR_UART1, 0);
> + clock_set_target_val(UART1_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(0));
> + clock_enable(CCGR_UART1, 1);
> + return;
> + case 1:
> + clock_enable(CCGR_UART2, 0);
> + clock_set_target_val(UART2_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(0));
> + clock_enable(CCGR_UART2, 1);
> + return;
> + case 2:
> + clock_enable(CCGR_UART3, 0);
> + clock_set_target_val(UART3_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(0));
> + clock_enable(CCGR_UART3, 1);
> + return;
> + case 3:
> + clock_enable(CCGR_UART4, 0);
> + clock_set_target_val(UART4_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(0));
> + clock_enable(CCGR_UART4, 1);
> + return;
> + default:
> + printf("Invalid uart index\n");
> + return;
> + }
> +}
> +
> +void init_clk_usdhc(u32 index)
> +{
> + /*
> + * set usdhc clock root
> + * sys pll1 400M
> + */
> + switch (index) {
> + case 0:
> + clock_enable(CCGR_USDHC1, 0);
> + clock_set_target_val(USDHC1_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(1) |
> + CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2));
> + clock_enable(CCGR_USDHC1, 1);
> + return;
> + case 1:
> + clock_enable(CCGR_USDHC2, 0);
> + clock_set_target_val(USDHC2_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(1) |
> + CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2));
> + clock_enable(CCGR_USDHC2, 1);
> + return;
> + default:
> + printf("Invalid usdhc index\n");
> + return;
> + }
> +}
> +
> +int set_clk_qspi(void)
> +{
> + /*
> + * set qspi root
> + * sys pll1 100M
> + */
> + clock_enable(CCGR_QSPI, 0);
> + clock_set_target_val(QSPI_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(7));
> + clock_enable(CCGR_QSPI, 1);
> +
> + return 0;
> +}
> +
> +#ifdef CONFIG_FEC_MXC
> +int set_clk_enet(enum enet_freq type)
> +{
> + u32 target;
> + u32 enet1_ref;
> +
> + switch (type) {
> + case ENET_125MHZ:
> + enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_125M_CLK;
> + break;
> + case ENET_50MHZ:
> + enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_50M_CLK;
> + break;
> + case ENET_25MHZ:
> + enet1_ref = ENET1_REF_CLK_ROOT_FROM_PLL_ENET_MAIN_25M_CLK;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + /* disable the clock first */
> + clock_enable(CCGR_ENET1, 0);
> + clock_enable(CCGR_SIM_ENET, 0);
> +
> + /* set enet axi clock 266Mhz */
> + target = CLK_ROOT_ON | ENET_AXI_CLK_ROOT_FROM_SYS1_PLL_266M |
> + CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) |
> + CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1);
> + clock_set_target_val(ENET_AXI_CLK_ROOT, target);
> +
> + target = CLK_ROOT_ON | enet1_ref |
> + CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) |
> + CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1);
> + clock_set_target_val(ENET_REF_CLK_ROOT, target);
> +
> + target = CLK_ROOT_ON |
> + ENET1_TIME_CLK_ROOT_FROM_PLL_ENET_MAIN_100M_CLK |
> + CLK_ROOT_PRE_DIV(CLK_ROOT_PRE_DIV1) |
> + CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV4);
> + clock_set_target_val(ENET_TIMER_CLK_ROOT, target);
> +
> + /* enable clock */
> + clock_enable(CCGR_SIM_ENET, 1);
> + clock_enable(CCGR_ENET1, 1);
> +
> + return 0;
> +}
> +#endif
> +
> +u32 imx_get_fecclk(void)
> +{
> + return get_root_clk(ENET_AXI_CLK_ROOT);
> +}
> +
> +#ifdef CONFIG_SPL_BUILD
> +void dram_pll_init(void)
> +{
> + struct src *src = (struct src *)SRC_BASE_ADDR;
> + void __iomem *pll_control_reg = &ana_pll->dram_pll_cfg0;
> + u32 pwdn_mask = 0, pll_clke = 0, bypass1 = 0, bypass2 = 0;
> + u32 val;
> + int ret;
> +
> + setbits_le32(GPC_BASE_ADDR + 0xEC, BIT(7));
> + setbits_le32(GPC_BASE_ADDR + 0xF8, BIT(5));
> +
> + pwdn_mask = SSCG_PLL_PD_MASK;
> + pll_clke = SSCG_PLL_DRAM_PLL_CLKE_MASK;
> + bypass1 = SSCG_PLL_BYPASS1_MASK;
> + bypass2 = SSCG_PLL_BYPASS2_MASK;
> +
> + /* Enable DDR1 and DDR2 domain */
> + writel(SRC_DDR1_ENABLE_MASK, &src->ddr1_rcr);
> + writel(SRC_DDR1_ENABLE_MASK, &src->ddr2_rcr);
> +
> + /* Clear power down bit */
> + clrbits_le32(pll_control_reg, pwdn_mask);
> + /* Eanble ARM_PLL/SYS_PLL */
> + setbits_le32(pll_control_reg, pll_clke);
> +
> + /* Clear bypass */
> + clrbits_le32(pll_control_reg, bypass1);
> + __udelay(100);
> + clrbits_le32(pll_control_reg, bypass2);
> + /* Wait lock */
> + ret = readl_poll_timeout(pll_control_reg, val,
> + val & SSCG_PLL_LOCK_MASK, 1);
> + if (ret)
> + printf("%s timeout\n", __func__);
> +}
> +
> +int frac_pll_init(u32 pll, enum frac_pll_out_val val)
> +{
> + void __iomem *pll_cfg0, __iomem *pll_cfg1;
> + u32 val_cfg0, val_cfg1;
> + int ret;
> +
> + switch (pll) {
> + case ANATOP_ARM_PLL:
> + pll_cfg0 = &ana_pll->arm_pll_cfg0;
> + pll_cfg1 = &ana_pll->arm_pll_cfg1;
> +
> + if (val == FRAC_PLL_OUT_1000M)
> + val_cfg1 = FRAC_PLL_INT_DIV_CTL_VAL(49);
> + else
> + val_cfg1 = FRAC_PLL_INT_DIV_CTL_VAL(79);
> + val_cfg0 = FRAC_PLL_CLKE_MASK | FRAC_PLL_REFCLK_SEL_OSC_25M |
> + FRAC_PLL_LOCK_SEL_MASK | FRAC_PLL_NEWDIV_VAL_MASK |
> + FRAC_PLL_REFCLK_DIV_VAL(4) |
> + FRAC_PLL_OUTPUT_DIV_VAL(0);
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + /* bypass the clock */
> + setbits_le32(pll_cfg0, FRAC_PLL_BYPASS_MASK);
> + /* Set the value */
> + writel(val_cfg1, pll_cfg1);
> + writel(val_cfg0 | FRAC_PLL_BYPASS_MASK, pll_cfg0);
> + val_cfg0 = readl(pll_cfg0);
> + /* unbypass the clock */
> + clrbits_le32(pll_cfg0, FRAC_PLL_BYPASS_MASK);
> + ret = readl_poll_timeout(pll_cfg0, val_cfg0,
> + val_cfg0 & FRAC_PLL_LOCK_MASK, 1);
> + if (ret)
> + printf("%s timeout\n", __func__);
> + clrbits_le32(pll_cfg0, FRAC_PLL_NEWDIV_VAL_MASK);
> +
> + return 0;
> +}
> +
> +int sscg_pll_init(u32 pll)
> +{
> + void __iomem *pll_cfg0, __iomem *pll_cfg1, __iomem *pll_cfg2;
> + u32 val_cfg0, val_cfg1, val_cfg2, val;
> + u32 bypass1_mask = 0x20, bypass2_mask = 0x10;
> + int ret;
> +
> + switch (pll) {
> + case ANATOP_SYSTEM_PLL1:
> + pll_cfg0 = &ana_pll->sys_pll1_cfg0;
> + pll_cfg1 = &ana_pll->sys_pll1_cfg1;
> + pll_cfg2 = &ana_pll->sys_pll1_cfg2;
> + /* 800MHz */
> + val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) |
> + SSCG_PLL_FEEDBACK_DIV_F2_VAL(3);
> + val_cfg1 = 0;
> + val_cfg0 = SSCG_PLL_CLKE_MASK | SSCG_PLL_DIV2_CLKE_MASK |
> + SSCG_PLL_DIV3_CLKE_MASK | SSCG_PLL_DIV4_CLKE_MASK |
> + SSCG_PLL_DIV5_CLKE_MASK | SSCG_PLL_DIV6_CLKE_MASK |
> + SSCG_PLL_DIV8_CLKE_MASK | SSCG_PLL_DIV10_CLKE_MASK |
> + SSCG_PLL_DIV20_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK |
> + SSCG_PLL_REFCLK_SEL_OSC_25M;
> + break;
> + case ANATOP_SYSTEM_PLL2:
> + pll_cfg0 = &ana_pll->sys_pll2_cfg0;
> + pll_cfg1 = &ana_pll->sys_pll2_cfg1;
> + pll_cfg2 = &ana_pll->sys_pll2_cfg2;
> + /* 1000MHz */
> + val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) |
> + SSCG_PLL_FEEDBACK_DIV_F2_VAL(4);
> + val_cfg1 = 0;
> + val_cfg0 = SSCG_PLL_CLKE_MASK | SSCG_PLL_DIV2_CLKE_MASK |
> + SSCG_PLL_DIV3_CLKE_MASK | SSCG_PLL_DIV4_CLKE_MASK |
> + SSCG_PLL_DIV5_CLKE_MASK | SSCG_PLL_DIV6_CLKE_MASK |
> + SSCG_PLL_DIV8_CLKE_MASK | SSCG_PLL_DIV10_CLKE_MASK |
> + SSCG_PLL_DIV20_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK |
> + SSCG_PLL_REFCLK_SEL_OSC_25M;
> + break;
> + case ANATOP_SYSTEM_PLL3:
> + pll_cfg0 = &ana_pll->sys_pll3_cfg0;
> + pll_cfg1 = &ana_pll->sys_pll3_cfg1;
> + pll_cfg2 = &ana_pll->sys_pll3_cfg2;
> + /* 800MHz */
> + val_cfg2 = SSCG_PLL_FEEDBACK_DIV_F1_VAL(3) |
> + SSCG_PLL_FEEDBACK_DIV_F2_VAL(3);
> + val_cfg1 = 0;
> + val_cfg0 = SSCG_PLL_PLL3_CLKE_MASK | SSCG_PLL_LOCK_SEL_MASK |
> + SSCG_PLL_REFCLK_SEL_OSC_25M;
> + break;
> + default:
> + return -EINVAL;
> + }
> +
> + /*bypass*/
> + setbits_le32(pll_cfg0, bypass1_mask | bypass2_mask);
> + /* set value */
> + writel(val_cfg2, pll_cfg2);
> + writel(val_cfg1, pll_cfg1);
> + /*unbypass1 and wait 70us */
> + writel(val_cfg0 | bypass2_mask, pll_cfg1);
> +
> + __udelay(70);
> +
> + /* unbypass2 and wait lock */
> + writel(val_cfg0, pll_cfg1);
> + ret = readl_poll_timeout(pll_cfg0, val, val & SSCG_PLL_LOCK_MASK, 1);
> + if (ret)
> + printf("%s timeout\n", __func__);
> +
> + return ret;
> +}
> +
> +int clock_init(void)
> +{
> + u32 grade;
> +
> + clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(0));
> +
> + /*
> + * 8MQ only supports two grades: consumer and industrial.
> + * We set ARM clock to 1Ghz for consumer, 800Mhz for industrial
> + */
> + grade = get_cpu_temp_grade(NULL, NULL);
> + if (!grade) {
> + frac_pll_init(ANATOP_ARM_PLL, FRAC_PLL_OUT_1000M);
> + clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(1) |
> + CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV1));
> + } else {
> + frac_pll_init(ANATOP_ARM_PLL, FRAC_PLL_OUT_1600M);
> + clock_set_target_val(ARM_A53_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(1) |
> + CLK_ROOT_POST_DIV(CLK_ROOT_POST_DIV2));
> + }
> + /*
> + * According to ANAMIX SPEC
> + * sys pll1 fixed at 800MHz
> + * sys pll2 fixed at 1GHz
> + * Here we only enable the outputs.
> + */
> + setbits_le32(&ana_pll->sys_pll1_cfg0, SSCG_PLL_CLKE_MASK |
> + SSCG_PLL_DIV2_CLKE_MASK | SSCG_PLL_DIV3_CLKE_MASK |
> + SSCG_PLL_DIV4_CLKE_MASK | SSCG_PLL_DIV5_CLKE_MASK |
> + SSCG_PLL_DIV6_CLKE_MASK | SSCG_PLL_DIV8_CLKE_MASK |
> + SSCG_PLL_DIV10_CLKE_MASK | SSCG_PLL_DIV20_CLKE_MASK);
> +
> + setbits_le32(&ana_pll->sys_pll2_cfg0, SSCG_PLL_CLKE_MASK |
> + SSCG_PLL_DIV2_CLKE_MASK | SSCG_PLL_DIV3_CLKE_MASK |
> + SSCG_PLL_DIV4_CLKE_MASK | SSCG_PLL_DIV5_CLKE_MASK |
> + SSCG_PLL_DIV6_CLKE_MASK | SSCG_PLL_DIV8_CLKE_MASK |
> + SSCG_PLL_DIV10_CLKE_MASK | SSCG_PLL_DIV20_CLKE_MASK);
> +
> + clock_set_target_val(NAND_USDHC_BUS_CLK_ROOT, CLK_ROOT_ON |
> + CLK_ROOT_SOURCE_SEL(1));
> +
> + init_wdog_clk();
> + clock_enable(CCGR_TSENSOR, 1);
> +
> + return 0;
> +}
> +#endif
> +
> +/*
> + * Dump some clockes.
> + */
> +#ifndef CONFIG_SPL_BUILD
> +int do_mx8m_showclocks(cmd_tbl_t *cmdtp, int flag, int argc,
> + char * const argv[])
> +{
> + u32 freq;
> +
> + freq = decode_frac_pll(ARM_PLL_CLK);
> + printf("ARM_PLL %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL1_800M_CLK);
> + printf("SYS_PLL1_800 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL1_400M_CLK);
> + printf("SYS_PLL1_400 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL1_266M_CLK);
> + printf("SYS_PLL1_266 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL1_200M_CLK);
> + printf("SYS_PLL1_200 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL1_160M_CLK);
> + printf("SYS_PLL1_160 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL1_133M_CLK);
> + printf("SYS_PLL1_133 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL1_100M_CLK);
> + printf("SYS_PLL1_100 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL1_80M_CLK);
> + printf("SYS_PLL1_80 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL1_40M_CLK);
> + printf("SYS_PLL1_40 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL2_1000M_CLK);
> + printf("SYS_PLL2_1000 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL2_500M_CLK);
> + printf("SYS_PLL2_500 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL2_333M_CLK);
> + printf("SYS_PLL2_333 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL2_250M_CLK);
> + printf("SYS_PLL2_250 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL2_200M_CLK);
> + printf("SYS_PLL2_200 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL2_166M_CLK);
> + printf("SYS_PLL2_166 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL2_125M_CLK);
> + printf("SYS_PLL2_125 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL2_100M_CLK);
> + printf("SYS_PLL2_100 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL2_50M_CLK);
> + printf("SYS_PLL2_50 %8d MHz\n", freq / 1000000);
> + freq = decode_sscg_pll(SYSTEM_PLL3_CLK);
> + printf("SYS_PLL3 %8d MHz\n", freq / 1000000);
> + freq = mxc_get_clock(UART1_CLK_ROOT);
> + printf("UART1 %8d MHz\n", freq / 1000000);
> + freq = mxc_get_clock(USDHC1_CLK_ROOT);
> + printf("USDHC1 %8d MHz\n", freq / 1000000);
> + freq = mxc_get_clock(QSPI_CLK_ROOT);
> + printf("QSPI %8d MHz\n", freq / 1000000);
> + return 0;
> +}
> +
> +U_BOOT_CMD(
> + clocks, CONFIG_SYS_MAXARGS, 1, do_mx8m_showclocks,
> + "display clocks",
> + ""
> +);
> +#endif
> diff --git a/arch/arm/mach-imx/mx8m/clock_slice.c b/arch/arm/mach-imx/mx8m/clock_slice.c
> new file mode 100644
> index 0000000000..e734498b94
> --- /dev/null
> +++ b/arch/arm/mach-imx/mx8m/clock_slice.c
> @@ -0,0 +1,742 @@
> +/*
> + * Copyright 2017 NXP
> + *
> + * Peng Fan <peng.fan at nxp.com>
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/imx-regs.h>
> +#include <asm/io.h>
> +#include <errno.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static struct ccm_reg *ccm_reg = (struct ccm_reg *)CCM_BASE_ADDR;
> +
> +static struct clk_root_map root_array[] = {
> + {ARM_A53_CLK_ROOT, CORE_CLOCK_SLICE, 0,
> + {OSC_25M_CLK, ARM_PLL_CLK, SYSTEM_PLL2_500M_CLK,
> + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL1_400M_CLK, AUDIO_PLL1_CLK, SYSTEM_PLL3_CLK}
> + },
> + {ARM_M4_CLK_ROOT, CORE_CLOCK_SLICE, 1,
> + {OSC_25M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL2_250M_CLK,
> + SYSTEM_PLL1_266M_CLK, SYSTEM_PLL1_800M_CLK,
> + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, SYSTEM_PLL3_CLK}
> + },
> + {VPU_A53_CLK_ROOT, CORE_CLOCK_SLICE, 2,
> + {OSC_25M_CLK, ARM_PLL_CLK, SYSTEM_PLL2_500M_CLK,
> + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL1_400M_CLK, AUDIO_PLL1_CLK, VPU_PLL_CLK}
> + },
> + {GPU_CORE_CLK_ROOT, CORE_CLOCK_SLICE, 3,
> + {OSC_25M_CLK, GPU_PLL_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_1000M_CLK,
> + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, AUDIO_PLL2_CLK}
> + },
> + {GPU_SHADER_CLK_ROOT, CORE_CLOCK_SLICE, 4,
> + {OSC_25M_CLK, GPU_PLL_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_1000M_CLK,
> + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, AUDIO_PLL2_CLK}
> + },
> + {MAIN_AXI_CLK_ROOT, BUS_CLOCK_SLICE, 0,
> + {OSC_25M_CLK, SYSTEM_PLL2_333M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_250M_CLK, SYSTEM_PLL2_1000M_CLK,
> + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, SYSTEM_PLL1_100M_CLK}
> + },
> + {ENET_AXI_CLK_ROOT, BUS_CLOCK_SLICE, 1,
> + {OSC_25M_CLK, SYSTEM_PLL1_266M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_250M_CLK, SYSTEM_PLL2_200M_CLK,
> + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, SYSTEM_PLL3_CLK}
> + },
> + {NAND_USDHC_BUS_CLK_ROOT, BUS_CLOCK_SLICE, 2,
> + {OSC_25M_CLK, SYSTEM_PLL1_266M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_133M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_250M_CLK, AUDIO_PLL1_CLK}
> + },
> + {VPU_BUS_CLK_ROOT, BUS_CLOCK_SLICE, 3,
> + {OSC_25M_CLK, SYSTEM_PLL1_800M_CLK, VPU_PLL_CLK,
> + AUDIO_PLL2_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_1000M_CLK,
> + SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_100M_CLK}
> + },
> + {DISPLAY_AXI_CLK_ROOT, BUS_CLOCK_SLICE, 4,
> + {OSC_25M_CLK, SYSTEM_PLL2_125M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL1_400M_CLK, AUDIO_PLL2_CLK,
> + EXT_CLK_1, EXT_CLK_4}
> + },
> + {DISPLAY_APB_CLK_ROOT, BUS_CLOCK_SLICE, 5,
> + {OSC_25M_CLK, SYSTEM_PLL2_125M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL1_400M_CLK, AUDIO_PLL2_CLK,
> + EXT_CLK_1, EXT_CLK_3}
> + },
> + {DISPLAY_RTRM_CLK_ROOT, BUS_CLOCK_SLICE, 6,
> + {OSC_25M_CLK, SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_200M_CLK,
> + SYSTEM_PLL1_400M_CLK, AUDIO_PLL1_CLK, VIDEO_PLL_CLK,
> + EXT_CLK_2, EXT_CLK_3}
> + },
> + {USB_BUS_CLK_ROOT, BUS_CLOCK_SLICE, 7,
> + {OSC_25M_CLK, SYSTEM_PLL2_500M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL2_200M_CLK,
> + EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK}
> + },
> + {GPU_AXI_CLK_ROOT, BUS_CLOCK_SLICE, 8,
> + {OSC_25M_CLK, SYSTEM_PLL1_800M_CLK, GPU_PLL_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_1000M_CLK,
> + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, AUDIO_PLL2_CLK}
> + },
> + {GPU_AHB_CLK_ROOT, BUS_CLOCK_SLICE, 9,
> + {OSC_25M_CLK, SYSTEM_PLL1_800M_CLK, GPU_PLL_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_1000M_CLK,
> + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, AUDIO_PLL2_CLK}
> + },
> + {NOC_CLK_ROOT, BUS_CLOCK_SLICE, 10,
> + {OSC_25M_CLK, SYSTEM_PLL1_800M_CLK, SYSTEM_PLL3_CLK,
> + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL2_500M_CLK,
> + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, AUDIO_PLL2_CLK}
> + },
> + {NOC_APB_CLK_ROOT, BUS_CLOCK_SLICE, 11,
> + {OSC_25M_CLK, SYSTEM_PLL1_400M_CLK, SYSTEM_PLL3_CLK,
> + SYSTEM_PLL2_333M_CLK, SYSTEM_PLL2_200M_CLK,
> + SYSTEM_PLL1_800M_CLK, AUDIO_PLL1_CLK, VIDEO_PLL_CLK}
> + },
> + {AHB_CLK_ROOT, AHB_CLOCK_SLICE, 0,
> + {OSC_25M_CLK, SYSTEM_PLL1_133M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL1_400M_CLK, SYSTEM_PLL2_125M_CLK,
> + SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL_CLK}
> + },
> + {IPG_CLK_ROOT, IPG_CLOCK_SLICE, 0,
> + {}
> + },
> + {AUDIO_AHB_CLK_ROOT, AHB_CLOCK_SLICE, 1,
> + {OSC_25M_CLK, SYSTEM_PLL2_500M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL2_166M_CLK,
> + SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL_CLK}
> + },
> + {MIPI_DSI_ESC_RX_CLK_ROOT, AHB_CLOCK_SLICE, 2,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_40M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL1_CLK },
> + },
> + {DRAM_ALT_CLK_ROOT, IP_CLOCK_SLICE, 0,
> + {OSC_25M_CLK, SYSTEM_PLL1_800M_CLK, SYSTEM_PLL1_100M_CLK,
> + SYSTEM_PLL2_500M_CLK, SYSTEM_PLL2_250M_CLK,
> + SYSTEM_PLL1_400M_CLK, AUDIO_PLL1_CLK, SYSTEM_PLL1_266M_CLK}
> + },
> + {DRAM_APB_CLK_ROOT, IP_CLOCK_SLICE, 1,
> + {OSC_25M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_40M_CLK,
> + SYSTEM_PLL1_160M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_250M_CLK, AUDIO_PLL2_CLK}
> + },
> + {VPU_G1_CLK_ROOT, IP_CLOCK_SLICE, 2,
> + {OSC_25M_CLK, VPU_PLL_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL1_100M_CLK,
> + SYSTEM_PLL2_125M_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK}
> + },
> + {VPU_G2_CLK_ROOT, IP_CLOCK_SLICE, 3,
> + {OSC_25M_CLK, VPU_PLL_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL1_100M_CLK,
> + SYSTEM_PLL2_125M_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK}
> + },
> + {DISPLAY_DTRC_CLK_ROOT, IP_CLOCK_SLICE, 4,
> + {OSC_25M_CLK, VPU_PLL_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL1_160M_CLK,
> + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK}
> + },
> + {DISPLAY_DC8000_CLK_ROOT, IP_CLOCK_SLICE, 5,
> + {OSC_25M_CLK, VPU_PLL_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL1_160M_CLK,
> + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK}
> + },
> + {PCIE1_CTRL_CLK_ROOT, IP_CLOCK_SLICE, 6,
> + {OSC_25M_CLK, SYSTEM_PLL2_250M_CLK, SYSTEM_PLL2_200M_CLK,
> + SYSTEM_PLL1_266M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_500M_CLK, SYSTEM_PLL2_333M_CLK, SYSTEM_PLL3_CLK}
> + },
> + {PCIE1_PHY_CLK_ROOT, IP_CLOCK_SLICE, 7,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL2_500M_CLK,
> + EXT_CLK_1, EXT_CLK_2, EXT_CLK_3, EXT_CLK_4,
> + SYSTEM_PLL1_400M_CLK}
> + },
> + {PCIE1_AUX_CLK_ROOT, IP_CLOCK_SLICE, 8,
> + {OSC_25M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL2_50M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_80M_CLK,
> + SYSTEM_PLL1_160M_CLK, SYSTEM_PLL1_200M_CLK}
> + },
> + {DC_PIXEL_CLK_ROOT, IP_CLOCK_SLICE, 9,
> + {OSC_25M_CLK, VIDEO_PLL_CLK, AUDIO_PLL2_CLK,
> + AUDIO_PLL1_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4}
> + },
> + {LCDIF_PIXEL_CLK_ROOT, IP_CLOCK_SLICE, 10,
> + {OSC_25M_CLK, VIDEO_PLL_CLK, AUDIO_PLL2_CLK,
> + AUDIO_PLL1_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4}
> + },
> + {SAI1_CLK_ROOT, IP_CLOCK_SLICE, 11,
> + {OSC_25M_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK,
> + VIDEO_PLL_CLK, SYSTEM_PLL1_133M_CLK,
> + OSC_27M_CLK, EXT_CLK_1, EXT_CLK_2}
> + },
> + {SAI2_CLK_ROOT, IP_CLOCK_SLICE, 12,
> + {OSC_25M_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK,
> + VIDEO_PLL_CLK, SYSTEM_PLL1_133M_CLK,
> + OSC_27M_CLK, EXT_CLK_2, EXT_CLK_3}
> + },
> + {SAI3_CLK_ROOT, IP_CLOCK_SLICE, 13,
> + {OSC_25M_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK,
> + VIDEO_PLL_CLK, SYSTEM_PLL1_133M_CLK,
> + OSC_27M_CLK, EXT_CLK_3, EXT_CLK_4}
> + },
> + {SAI4_CLK_ROOT, IP_CLOCK_SLICE, 14,
> + {OSC_25M_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK,
> + VIDEO_PLL_CLK, SYSTEM_PLL1_133M_CLK,
> + OSC_27M_CLK, EXT_CLK_1, EXT_CLK_2}
> + },
> + {SAI5_CLK_ROOT, IP_CLOCK_SLICE, 15,
> + {OSC_25M_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK,
> + VIDEO_PLL_CLK, SYSTEM_PLL1_133M_CLK,
> + OSC_27M_CLK, EXT_CLK_2, EXT_CLK_3}
> + },
> + {SAI6_CLK_ROOT, IP_CLOCK_SLICE, 16,
> + {OSC_25M_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK,
> + VIDEO_PLL_CLK, SYSTEM_PLL1_133M_CLK,
> + OSC_27M_CLK, EXT_CLK_3, EXT_CLK_4}
> + },
> + {SPDIF1_CLK_ROOT, IP_CLOCK_SLICE, 17,
> + {OSC_25M_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK,
> + VIDEO_PLL_CLK, SYSTEM_PLL1_133M_CLK,
> + OSC_27M_CLK, EXT_CLK_2, EXT_CLK_3}
> + },
> + {SPDIF2_CLK_ROOT, IP_CLOCK_SLICE, 18,
> + {OSC_25M_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK,
> + VIDEO_PLL_CLK, SYSTEM_PLL1_133M_CLK,
> + OSC_27M_CLK, EXT_CLK_3, EXT_CLK_4}
> + },
> + {ENET_REF_CLK_ROOT, IP_CLOCK_SLICE, 19,
> + {OSC_25M_CLK, SYSTEM_PLL2_125M_CLK, SYSTEM_PLL2_50M_CLK,
> + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_160M_CLK,
> + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, EXT_CLK_4}
> + },
> + {ENET_TIMER_CLK_ROOT, IP_CLOCK_SLICE, 20,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, AUDIO_PLL1_CLK,
> + EXT_CLK_1, EXT_CLK_2, EXT_CLK_3, EXT_CLK_4,
> + VIDEO_PLL_CLK}
> + },
> + {ENET_PHY_REF_CLK_ROOT, IP_CLOCK_SLICE, 21,
> + {OSC_25M_CLK, SYSTEM_PLL2_50M_CLK, SYSTEM_PLL2_125M_CLK,
> + SYSTEM_PLL2_200M_CLK, SYSTEM_PLL2_500M_CLK,
> + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, AUDIO_PLL2_CLK}
> + },
> + {NAND_CLK_ROOT, IP_CLOCK_SLICE, 22,
> + {OSC_25M_CLK, SYSTEM_PLL2_500M_CLK, AUDIO_PLL1_CLK,
> + SYSTEM_PLL1_400M_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL3_CLK,
> + SYSTEM_PLL2_250M_CLK, VIDEO_PLL_CLK}
> + },
> + {QSPI_CLK_ROOT, IP_CLOCK_SLICE, 23,
> + {OSC_25M_CLK, SYSTEM_PLL1_400M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_500M_CLK, AUDIO_PLL2_CLK,
> + SYSTEM_PLL1_266M_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL1_100M_CLK}
> + },
> + {USDHC1_CLK_ROOT, IP_CLOCK_SLICE, 24,
> + {OSC_25M_CLK, SYSTEM_PLL1_400M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_500M_CLK, AUDIO_PLL2_CLK,
> + SYSTEM_PLL1_266M_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL1_100M_CLK}
> + },
> + {USDHC2_CLK_ROOT, IP_CLOCK_SLICE, 25,
> + {OSC_25M_CLK, SYSTEM_PLL1_400M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_500M_CLK, AUDIO_PLL2_CLK,
> + SYSTEM_PLL1_266M_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL1_100M_CLK}
> + },
> + {I2C1_CLK_ROOT, IP_CLOCK_SLICE, 26,
> + {OSC_25M_CLK, SYSTEM_PLL1_160M_CLK, SYSTEM_PLL2_50M_CLK,
> + SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL_CLK,
> + AUDIO_PLL2_CLK, SYSTEM_PLL1_133M_CLK}
> + },
> + {I2C2_CLK_ROOT, IP_CLOCK_SLICE, 27,
> + {OSC_25M_CLK, SYSTEM_PLL1_160M_CLK, SYSTEM_PLL2_50M_CLK,
> + SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL_CLK,
> + AUDIO_PLL2_CLK, SYSTEM_PLL1_133M_CLK}
> + },
> + {I2C3_CLK_ROOT, IP_CLOCK_SLICE, 28,
> + {OSC_25M_CLK, SYSTEM_PLL1_160M_CLK, SYSTEM_PLL2_50M_CLK,
> + SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL_CLK,
> + AUDIO_PLL2_CLK, SYSTEM_PLL1_133M_CLK}
> + },
> + {I2C4_CLK_ROOT, IP_CLOCK_SLICE, 29,
> + {OSC_25M_CLK, SYSTEM_PLL1_160M_CLK, SYSTEM_PLL2_50M_CLK,
> + SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL_CLK,
> + AUDIO_PLL2_CLK, SYSTEM_PLL1_133M_CLK}
> + },
> + {UART1_CLK_ROOT, IP_CLOCK_SLICE, 30,
> + {OSC_25M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK,
> + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK,
> + EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK}
> + },
> + {UART2_CLK_ROOT, IP_CLOCK_SLICE, 31,
> + {OSC_25M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK,
> + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK,
> + EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK}
> + },
> + {UART3_CLK_ROOT, IP_CLOCK_SLICE, 32,
> + {OSC_25M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK,
> + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK,
> + EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK}
> + },
> + {UART4_CLK_ROOT, IP_CLOCK_SLICE, 33,
> + {OSC_25M_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_200M_CLK,
> + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL3_CLK,
> + EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK}
> + },
> + {USB_CORE_REF_CLK_ROOT, IP_CLOCK_SLICE, 34,
> + {OSC_25M_CLK, SYSTEM_PLL1_100M_CLK, SYSTEM_PLL1_40M_CLK,
> + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL2_200M_CLK,
> + EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK}
> + },
> + {USB_PHY_REF_CLK_ROOT, IP_CLOCK_SLICE, 35,
> + {OSC_25M_CLK, SYSTEM_PLL1_100M_CLK, SYSTEM_PLL1_40M_CLK,
> + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL2_200M_CLK,
> + EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK}
> + },
> + {GIC_CLK_ROOT, IP_CLOCK_SLICE, 36,
> + {OSC_25M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_40M_CLK,
> + SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_800M_CLK,
> + EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK}
> + },
> + {ECSPI1_CLK_ROOT, IP_CLOCK_SLICE, 37,
> + {OSC_25M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_40M_CLK,
> + SYSTEM_PLL1_160M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_250M_CLK, AUDIO_PLL2_CLK}
> + },
> + {ECSPI2_CLK_ROOT, IP_CLOCK_SLICE, 38,
> + {OSC_25M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_40M_CLK,
> + SYSTEM_PLL1_160M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_250M_CLK, AUDIO_PLL2_CLK}
> + },
> + {PWM1_CLK_ROOT, IP_CLOCK_SLICE, 39,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_160M_CLK,
> + SYSTEM_PLL1_40M_CLK, SYSTEM_PLL3_CLK, EXT_CLK_1,
> + SYSTEM_PLL1_80M_CLK, VIDEO_PLL_CLK}
> + },
> + {PWM2_CLK_ROOT, IP_CLOCK_SLICE, 40,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_160M_CLK,
> + SYSTEM_PLL1_40M_CLK, SYSTEM_PLL3_CLK, EXT_CLK_1,
> + SYSTEM_PLL1_80M_CLK, VIDEO_PLL_CLK}
> + },
> + {PWM3_CLK_ROOT, IP_CLOCK_SLICE, 41,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_160M_CLK,
> + SYSTEM_PLL1_40M_CLK, SYSTEM_PLL3_CLK, EXT_CLK_1,
> + SYSTEM_PLL1_80M_CLK, VIDEO_PLL_CLK}
> + },
> + {PWM4_CLK_ROOT, IP_CLOCK_SLICE, 42,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_160M_CLK,
> + SYSTEM_PLL1_40M_CLK, SYSTEM_PLL3_CLK, EXT_CLK_1,
> + SYSTEM_PLL1_80M_CLK, VIDEO_PLL_CLK}
> + },
> + {GPT1_CLK_ROOT, IP_CLOCK_SLICE, 43,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_400M_CLK,
> + SYSTEM_PLL1_40M_CLK, VIDEO_PLL_CLK,
> + SYSTEM_PLL1_80M_CLK, AUDIO_PLL1_CLK, EXT_CLK_1}
> + },
> + {GPT2_CLK_ROOT, IP_CLOCK_SLICE, 44,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_400M_CLK,
> + SYSTEM_PLL1_40M_CLK, VIDEO_PLL_CLK,
> + SYSTEM_PLL1_80M_CLK, AUDIO_PLL1_CLK, EXT_CLK_2}
> + },
> + {GPT3_CLK_ROOT, IP_CLOCK_SLICE, 45,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_400M_CLK,
> + SYSTEM_PLL1_40M_CLK, VIDEO_PLL_CLK,
> + SYSTEM_PLL1_80M_CLK, AUDIO_PLL1_CLK, EXT_CLK_3}
> + },
> + {GPT4_CLK_ROOT, IP_CLOCK_SLICE, 46,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_400M_CLK,
> + SYSTEM_PLL1_40M_CLK, VIDEO_PLL_CLK,
> + SYSTEM_PLL1_80M_CLK, AUDIO_PLL1_CLK, EXT_CLK_1}
> + },
> + {GPT5_CLK_ROOT, IP_CLOCK_SLICE, 47,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_400M_CLK,
> + SYSTEM_PLL1_40M_CLK, VIDEO_PLL_CLK,
> + SYSTEM_PLL1_80M_CLK, AUDIO_PLL1_CLK, EXT_CLK_2}
> + },
> + {GPT6_CLK_ROOT, IP_CLOCK_SLICE, 48,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_400M_CLK,
> + SYSTEM_PLL1_40M_CLK, VIDEO_PLL_CLK,
> + SYSTEM_PLL1_80M_CLK, AUDIO_PLL1_CLK, EXT_CLK_3}
> + },
> + {TRACE_CLK_ROOT, IP_CLOCK_SLICE, 49,
> + {OSC_25M_CLK, SYSTEM_PLL1_133M_CLK, SYSTEM_PLL1_160M_CLK,
> + VPU_PLL_CLK, SYSTEM_PLL2_125M_CLK,
> + SYSTEM_PLL3_CLK, EXT_CLK_1, EXT_CLK_3}
> + },
> + {WDOG_CLK_ROOT, IP_CLOCK_SLICE, 50,
> + {OSC_25M_CLK, SYSTEM_PLL1_133M_CLK, SYSTEM_PLL1_160M_CLK,
> + VPU_PLL_CLK, SYSTEM_PLL2_125M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL1_80M_CLK, SYSTEM_PLL2_166M_CLK}
> + },
> + {WRCLK_CLK_ROOT, IP_CLOCK_SLICE, 51,
> + {OSC_25M_CLK, SYSTEM_PLL1_40M_CLK, VPU_PLL_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_200M_CLK,
> + SYSTEM_PLL1_266M_CLK, SYSTEM_PLL2_500M_CLK, SYSTEM_PLL1_100M_CLK}
> + },
> + {IPP_DO_CLKO1, IP_CLOCK_SLICE, 52,
> + {OSC_25M_CLK, SYSTEM_PLL1_800M_CLK, OSC_27M_CLK,
> + SYSTEM_PLL1_200M_CLK, AUDIO_PLL2_CLK,
> + SYSTEM_PLL2_500M_CLK, VPU_PLL_CLK, SYSTEM_PLL1_80M_CLK}
> + },
> + {IPP_DO_CLKO2, IP_CLOCK_SLICE, 53,
> + {OSC_25M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_400M_CLK,
> + SYSTEM_PLL2_166M_CLK, SYSTEM_PLL3_CLK,
> + AUDIO_PLL1_CLK, VIDEO_PLL_CLK, OSC_32K_CLK}
> + },
> + {MIPI_DSI_CORE_CLK_ROOT, IP_CLOCK_SLICE, 54,
> + {OSC_25M_CLK, SYSTEM_PLL1_266M_CLK, SYSTEM_PLL2_250M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL_CLK}
> + },
> + {MIPI_DSI_PHY_REF_CLK_ROOT, IP_CLOCK_SLICE, 55,
> + {OSC_25M_CLK, SYSTEM_PLL2_125M_CLK, SYSTEM_PLL2_100M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL_CLK}
> + },
> + {MIPI_DSI_DBI_CLK_ROOT, IP_CLOCK_SLICE, 56,
> + {OSC_25M_CLK, SYSTEM_PLL1_266M_CLK, SYSTEM_PLL2_100M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL_CLK}
> + },
> + {OLD_MIPI_DSI_ESC_CLK_ROOT, IP_CLOCK_SLICE, 57,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_80M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK}
> + },
> + {MIPI_CSI1_CORE_CLK_ROOT, IP_CLOCK_SLICE, 58,
> + {OSC_25M_CLK, SYSTEM_PLL1_266M_CLK, SYSTEM_PLL2_250M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL_CLK}
> + },
> + {MIPI_CSI1_PHY_REF_CLK_ROOT, IP_CLOCK_SLICE, 59,
> + {OSC_25M_CLK, SYSTEM_PLL2_125M_CLK, SYSTEM_PLL2_100M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL_CLK}
> + },
> + {MIPI_CSI1_ESC_CLK_ROOT, IP_CLOCK_SLICE, 60,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_80M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK}
> + },
> + {MIPI_CSI2_CORE_CLK_ROOT, IP_CLOCK_SLICE, 61,
> + {OSC_25M_CLK, SYSTEM_PLL1_266M_CLK, SYSTEM_PLL2_250M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL_CLK}
> + },
> + {MIPI_CSI2_PHY_REF_CLK_ROOT, IP_CLOCK_SLICE, 62,
> + {OSC_25M_CLK, SYSTEM_PLL2_125M_CLK, SYSTEM_PLL2_100M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL_CLK}
> + },
> + {MIPI_CSI2_ESC_CLK_ROOT, IP_CLOCK_SLICE, 63,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_80M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK}
> + },
> + {PCIE2_CTRL_CLK_ROOT, IP_CLOCK_SLICE, 64,
> + {OSC_25M_CLK, SYSTEM_PLL2_250M_CLK, SYSTEM_PLL2_200M_CLK,
> + SYSTEM_PLL1_266M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_500M_CLK, SYSTEM_PLL2_333M_CLK, SYSTEM_PLL3_CLK}
> + },
> + {PCIE2_PHY_CLK_ROOT, IP_CLOCK_SLICE, 65,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL2_500M_CLK,
> + EXT_CLK_1, EXT_CLK_2, EXT_CLK_3,
> + EXT_CLK_4, SYSTEM_PLL1_400M_CLK}
> + },
> + {PCIE2_AUX_CLK_ROOT, IP_CLOCK_SLICE, 66,
> + {OSC_25M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL2_50M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_100M_CLK,
> + SYSTEM_PLL1_80M_CLK, SYSTEM_PLL1_160M_CLK, SYSTEM_PLL1_200M_CLK}
> + },
> + {ECSPI3_CLK_ROOT, IP_CLOCK_SLICE, 67,
> + {OSC_25M_CLK, SYSTEM_PLL2_200M_CLK, SYSTEM_PLL1_40M_CLK,
> + SYSTEM_PLL1_160M_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL3_CLK, SYSTEM_PLL2_250M_CLK, AUDIO_PLL2_CLK}
> + },
> + {OLD_MIPI_DSI_ESC_RX_ROOT, IP_CLOCK_SLICE, 68,
> + {OSC_25M_CLK, SYSTEM_PLL2_100M_CLK, SYSTEM_PLL1_80M_CLK,
> + SYSTEM_PLL1_800M_CLK, SYSTEM_PLL2_1000M_CLK,
> + SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK},
> + },
> + {DISPLAY_HDMI_CLK_ROOT, IP_CLOCK_SLICE, 69,
> + {OSC_25M_CLK, SYSTEM_PLL1_200M_CLK, SYSTEM_PLL2_200M_CLK,
> + VPU_PLL_CLK, SYSTEM_PLL1_800M_CLK,
> + SYSTEM_PLL2_1000M_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4}
> + },
> + {DRAM_SEL_CFG, DRAM_SEL_CLOCK_SLICE, 0,
> + {DRAM_PLL1_CLK}
> + },
> + {CORE_SEL_CFG, CORE_SEL_CLOCK_SLICE, 0,
> + {DRAM_PLL1_CLK}
> + },
> +};
> +
> +static int select(enum clk_root_index clock_id)
> +{
> + int i, size;
> + struct clk_root_map *p = root_array;
> +
> + size = ARRAY_SIZE(root_array);
> +
> + for (i = 0; i < size; i++, p++) {
> + if (clock_id == p->entry)
> + return i;
> + }
> +
> + return -EINVAL;
> +}
> +
> +static void __iomem *get_clk_root_target(enum clk_slice_type slice_type,
> + u32 slice_index)
> +{
> + void __iomem *clk_root_target;
> +
> + switch (slice_type) {
> + case CORE_CLOCK_SLICE:
> + clk_root_target =
> + (void __iomem *)&ccm_reg->core_root[slice_index];
> + break;
> + case BUS_CLOCK_SLICE:
> + clk_root_target =
> + (void __iomem *)&ccm_reg->bus_root[slice_index];
> + break;
> + case IP_CLOCK_SLICE:
> + clk_root_target =
> + (void __iomem *)&ccm_reg->ip_root[slice_index];
> + break;
> + case AHB_CLOCK_SLICE:
> + clk_root_target =
> + (void __iomem *)&ccm_reg->ahb_ipg_root[slice_index * 2];
> + break;
> + case IPG_CLOCK_SLICE:
> + clk_root_target =
> + (void __iomem *)&ccm_reg->ahb_ipg_root[slice_index * 2 + 1];
> + break;
> + case CORE_SEL_CLOCK_SLICE:
> + clk_root_target = (void __iomem *)&ccm_reg->core_sel;
> + break;
> + case DRAM_SEL_CLOCK_SLICE:
> + clk_root_target = (void __iomem *)&ccm_reg->dram_sel;
> + break;
> + default:
> + return NULL;
> + }
> +
> + return clk_root_target;
> +}
> +
> +int clock_get_target_val(enum clk_root_index clock_id, u32 *val)
> +{
> + int root_entry;
> + struct clk_root_map *p;
> + void __iomem *clk_root_target;
> +
> + if (clock_id >= CLK_ROOT_MAX)
> + return -EINVAL;
> +
> + root_entry = select(clock_id);
> + if (root_entry < 0)
> + return -EINVAL;
> +
> + p = &root_array[root_entry];
> + clk_root_target = get_clk_root_target(p->slice_type, p->slice_index);
> + if (!clk_root_target)
> + return -EINVAL;
> +
> + *val = readl(clk_root_target);
> +
> + return 0;
> +}
> +
> +int clock_set_target_val(enum clk_root_index clock_id, u32 val)
> +{
> + int root_entry;
> + struct clk_root_map *p;
> + void __iomem *clk_root_target;
> +
> + if (clock_id >= CLK_ROOT_MAX)
> + return -EINVAL;
> +
> + root_entry = select(clock_id);
> + if (root_entry < 0)
> + return -EINVAL;
> +
> + p = &root_array[root_entry];
> + clk_root_target = get_clk_root_target(p->slice_type, p->slice_index);
> + if (!clk_root_target)
> + return -EINVAL;
> +
> + writel(val, clk_root_target);
> +
> + return 0;
> +}
> +
> +int clock_root_enabled(enum clk_root_index clock_id)
> +{
> + void __iomem *clk_root_target;
> + u32 slice_index, slice_type;
> + u32 val;
> + int root_entry;
> +
> + if (clock_id >= CLK_ROOT_MAX)
> + return -EINVAL;
> +
> + root_entry = select(clock_id);
> + if (root_entry < 0)
> + return -EINVAL;
> +
> + slice_type = root_array[root_entry].slice_type;
> + slice_index = root_array[root_entry].slice_index;
> +
> + if ((slice_type == IPG_CLOCK_SLICE) ||
> + (slice_type == DRAM_SEL_CLOCK_SLICE) ||
> + (slice_type == CORE_SEL_CLOCK_SLICE)) {
> + /*
> + * Not supported, from CCM doc
> + * TODO
> + */
> + return 0;
> + }
> +
> + clk_root_target = get_clk_root_target(slice_type, slice_index);
> + if (!clk_root_target)
> + return -EINVAL;
> +
> + val = readl(clk_root_target);
> +
> + return (val & CLK_ROOT_ON) ? 1 : 0;
> +}
> +
> +/* CCGR CLK gate operation */
> +int clock_enable(enum clk_ccgr_index index, bool enable)
> +{
> + void __iomem *ccgr;
> +
> + if (index >= CCGR_MAX)
> + return -EINVAL;
> +
> + if (enable)
> + ccgr = (void __iomem *)&ccm_reg->ccgr_array[index].ccgr_set;
> + else
> + ccgr = (void __iomem *)&ccm_reg->ccgr_array[index].ccgr_clr;
> +
> + writel(CCGR_CLK_ON_MASK, ccgr);
> +
> + return 0;
> +}
> +
> +int clock_get_prediv(enum clk_root_index clock_id, enum root_pre_div *pre_div)
> +{
> + u32 val;
> + int root_entry;
> + struct clk_root_map *p;
> + void __iomem *clk_root_target;
> +
> + if (clock_id >= CLK_ROOT_MAX)
> + return -EINVAL;
> +
> + root_entry = select(clock_id);
> + if (root_entry < 0)
> + return -EINVAL;
> +
> + p = &root_array[root_entry];
> +
> + if ((p->slice_type == CORE_CLOCK_SLICE) ||
> + (p->slice_type == IPG_CLOCK_SLICE) ||
> + (p->slice_type == CORE_SEL_CLOCK_SLICE) ||
> + (p->slice_type == DRAM_SEL_CLOCK_SLICE)) {
> + *pre_div = 0;
> + return 0;
> + }
> +
> + clk_root_target = get_clk_root_target(p->slice_type, p->slice_index);
> + if (!clk_root_target)
> + return -EINVAL;
> +
> + val = readl(clk_root_target);
> + val &= CLK_ROOT_PRE_DIV_MASK;
> + val >>= CLK_ROOT_PRE_DIV_SHIFT;
> +
> + *pre_div = val;
> +
> + return 0;
> +}
> +
> +int clock_get_postdiv(enum clk_root_index clock_id,
> + enum root_post_div *post_div)
> +{
> + u32 val, mask;
> + int root_entry;
> + struct clk_root_map *p;
> + void __iomem *clk_root_target;
> +
> + if (clock_id >= CLK_ROOT_MAX)
> + return -EINVAL;
> +
> + root_entry = select(clock_id);
> + if (root_entry < 0)
> + return -EINVAL;
> +
> + p = &root_array[root_entry];
> +
> + if ((p->slice_type == CORE_SEL_CLOCK_SLICE) ||
> + (p->slice_type == DRAM_SEL_CLOCK_SLICE)) {
> + *post_div = 0;
> + return 0;
> + }
> +
> + clk_root_target = get_clk_root_target(p->slice_type, p->slice_index);
> + if (!clk_root_target)
> + return -EINVAL;
> +
> + if (p->slice_type == IPG_CLOCK_SLICE)
> + mask = CLK_ROOT_IPG_POST_DIV_MASK;
> + else if (p->slice_type == CORE_CLOCK_SLICE)
> + mask = CLK_ROOT_CORE_POST_DIV_MASK;
> + else
> + mask = CLK_ROOT_POST_DIV_MASK;
> +
> + val = readl(clk_root_target);
> + val &= mask;
> + val >>= CLK_ROOT_POST_DIV_SHIFT;
> +
> + *post_div = val;
> +
> + return 0;
> +}
> +
> +int clock_get_src(enum clk_root_index clock_id, enum clk_root_src *p_clock_src)
> +{
> + u32 val;
> + int root_entry;
> + struct clk_root_map *p;
> + void __iomem *clk_root_target;
> +
> + if (clock_id >= CLK_ROOT_MAX)
> + return -EINVAL;
> +
> + root_entry = select(clock_id);
> + if (root_entry < 0)
> + return -EINVAL;
> +
> + p = &root_array[root_entry];
> +
> + clk_root_target = get_clk_root_target(p->slice_type, p->slice_index);
> + if (!clk_root_target)
> + return -EINVAL;
> +
> + val = readl(clk_root_target);
> + val &= CLK_ROOT_SRC_MUX_MASK;
> + val >>= CLK_ROOT_SRC_MUX_SHIFT;
> +
> + *p_clock_src = p->src_mux[val];
> +
> + return 0;
> +}
>
Best regards,
Stefano Babic
--
=====================================================================
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================
More information about the U-Boot
mailing list