/* * Copyright (c) 2006-2024 RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2022-3-08 GuEe-GUI the first version */ #include "clk-rk3568.h" #define DBG_TAG "clk.rk3568" #define DBG_LVL DBG_INFO #include #include "rk3568-cru.h" #define APLL_HZ (816 * MHZ) #define GPLL_HZ (1188 * MHZ) #define CPLL_HZ (1000 * MHZ) #define PPLL_HZ (100 * MHZ) #define rt_abs(x) \ ({ \ long ret; \ if (sizeof(x) == sizeof(long)) \ { \ long __x = (x); \ ret = (__x < 0) ? -__x : __x; \ } \ else \ { \ int __x = (x); \ ret = (__x < 0) ? -__x : __x; \ } \ ret; \ }) struct rk_pll { rt_uint32_t con0; rt_uint32_t con1; rt_uint32_t con2; rt_uint32_t con3; rt_uint32_t con4; rt_uint32_t reserved0[3]; }; struct rk_pmucru { struct rk_pll pll[2]; rt_uint32_t reserved0[16]; rt_uint32_t mode_con00; rt_uint32_t reserved1[31]; rt_uint32_t pmu_clksel_con[10]; rt_uint32_t reserved2[22]; rt_uint32_t pmu_clkgate_con[3]; rt_uint32_t reserved3[29]; rt_uint32_t pmu_softrst_con[1]; }; struct rk_cru { struct rk_pll pll[6]; rt_uint32_t mode_con00; rt_uint32_t misc_con[3]; rt_uint32_t glb_cnt_th; rt_uint32_t glb_srst_fst; rt_uint32_t glb_srsr_snd; rt_uint32_t glb_rst_con; rt_uint32_t glb_rst_st; rt_uint32_t reserved0[7]; rt_uint32_t clksel_con[85]; rt_uint32_t reserved1[43]; rt_uint32_t clkgate_con[36]; rt_uint32_t reserved2[28]; rt_uint32_t softrst_con[30]; rt_uint32_t reserved3[2]; rt_uint32_t ssgtbl[32]; rt_uint32_t reserved4[32]; rt_uint32_t sdmmc0_con[2]; rt_uint32_t sdmmc1_con[2]; rt_uint32_t sdmmc2_con[2]; rt_uint32_t emmc_con[2]; }; struct rk_pmuclk_priv { struct rk_pmucru *pmucru; rt_ubase_t ppll_hz; rt_ubase_t hpll_hz; }; struct rk_clk_priv { struct rk_cru *cru; rt_ubase_t ppll_hz; rt_ubase_t hpll_hz; rt_ubase_t gpll_hz; rt_ubase_t cpll_hz; rt_ubase_t npll_hz; rt_ubase_t vpll_hz; rt_ubase_t armclk_hz; rt_ubase_t armclk_enter_hz; rt_ubase_t armclk_init_hz; rt_bool_t sync_kernel; rt_bool_t set_armclk_rate; }; struct rk_clk_platform_data { rt_uint32_t id; void *base; }; enum rk_clk_type { rk_clk_type_clk, rk_clk_type_pmuclk, }; struct rk_clk { struct rt_reset_controller_clk_node parent; void *base; enum rk_clk_type type; union { struct rk_clk_priv clk_info; struct rk_pmuclk_priv pmuclk_info; }; struct rk_clk_platform_data pdata[]; }; #define raw_to_rk_clk(raw) rt_container_of(raw, struct rk_clk, parent) #define PMU_MODE 0x80 #define PMU_PLL_CON(x) ((x) * 0x4) #define PLL_CON(x) ((x) * 0x4) #define MODE_CON 0xc0 enum pmu_plls { ppll, hpll, }; enum plls { apll, dpll, gpll, cpll, npll, vpll, }; enum { /* CRU_PMU_CLK_SEL0_CON */ RTC32K_SEL_SHIFT = 6, RTC32K_SEL_MASK = 0x3 << RTC32K_SEL_SHIFT, RTC32K_SEL_PMUPVTM = 0, RTC32K_SEL_OSC1_32K, RTC32K_SEL_OSC0_DIV32K, /* CRU_PMU_CLK_SEL1_CON */ RTC32K_FRAC_NUMERATOR_SHIFT = 16, RTC32K_FRAC_NUMERATOR_MASK = 0xffff << 16, RTC32K_FRAC_DENOMINATOR_SHIFT = 0, RTC32K_FRAC_DENOMINATOR_MASK = 0xffff, /* CRU_PMU_CLK_SEL2_CON */ PCLK_PDPMU_SEL_SHIFT = 15, PCLK_PDPMU_SEL_MASK = 1 << PCLK_PDPMU_SEL_SHIFT, PCLK_PDPMU_SEL_PPLL = 0, PCLK_PDPMU_SEL_GPLL, PCLK_PDPMU_DIV_SHIFT = 0, PCLK_PDPMU_DIV_MASK = 0x1f, /* CRU_PMU_CLK_SEL3_CON */ CLK_I2C0_DIV_SHIFT = 0, CLK_I2C0_DIV_MASK = 0x7f, /* PMUCRU_PMUCLKSEL_CON04 */ CLK_UART0_SEL_SHIFT = 10, CLK_UART0_SEL_MASK = 0x3 << CLK_UART0_SEL_SHIFT, CLK_UART0_SEL_DIV = 0, CLK_UART0_SEL_FRACDIV, CLK_UART0_SEL_XIN24M, CLK_UART0_DIV_SEL_SHIFT = 8, CLK_UART0_DIV_SEL_MASK = 0x3 << CLK_UART0_DIV_SEL_SHIFT, CLK_UART0_SRC_SEL_PPLL = 0, CLK_UART0_SRC_SEL_480M, CLK_UART0_SRC_SEL_CPLL, CLK_UART0_SRC_SEL_GPLL, CLK_UART0_DIV_DIV_SHIFT = 0, CLK_UART0_DIV_DIV_MASK = 0x3f << CLK_UART0_DIV_DIV_SHIFT, /* PMUCRU_PMUCLKSEL_CON05 */ CLK_UART0_FRAC_NUMERATOR_SHIFT = 16, CLK_UART0_FRAC_NUMERATOR_MASK = 0xffff << 16, CLK_UART0_FRAC_DENOMINATOR_SHIFT= 0, CLK_UART0_FRAC_DENOMINATOR_MASK = 0xffff, /* PMUCRU_PMUCLKSEL_CON09 */ CLK_PCIE_PHY2_REF_SEL_SHIFT = 11, CLK_PCIE_PHY2_REF_SEL_MASK = 1 << CLK_PCIE_PHY2_REF_SEL_SHIFT, CLK_PCIE_PHY1_REF_SEL_SHIFT = 7, CLK_PCIE_PHY1_REF_SEL_MASK = 1 << CLK_PCIE_PHY1_REF_SEL_SHIFT, CLK_PCIE_PHY0_REF_SEL_SHIFT = 3, CLK_PCIE_PHY0_REF_SEL_MASK = 1 << CLK_PCIE_PHY0_REF_SEL_SHIFT, CLK_PCIE_PHY_REF_SEL_24M = 0, CLK_PCIE_PHY_REF_SEL_PPLL, CLK_PCIE_PHY2_PLL_DIV_SHIFT = 8, CLK_PCIE_PHY2_PLL_DIV_MASK = 7 << CLK_PCIE_PHY2_PLL_DIV_SHIFT, CLK_PCIE_PHY1_PLL_DIV_SHIFT = 4, CLK_PCIE_PHY1_PLL_DIV_MASK = 7 << CLK_PCIE_PHY1_PLL_DIV_SHIFT, CLK_PCIE_PHY0_PLL_DIV_SHIFT = 0, CLK_PCIE_PHY0_PLL_DIV_MASK = 7 << CLK_PCIE_PHY0_PLL_DIV_SHIFT, /* CRU_PMU_CLK_SEL6_CON */ CLK_PWM0_SEL_SHIFT = 7, CLK_PWM0_SEL_MASK = 1 << CLK_PWM0_SEL_SHIFT, CLK_PWM0_SEL_XIN24M = 0, CLK_PWM0_SEL_PPLL, CLK_PWM0_DIV_SHIFT = 0, CLK_PWM0_DIV_MASK = 0x7f, /* CRU_CLK_SEL0_CON */ CLK_CORE_PRE_SEL_SHIFT = 7, CLK_CORE_PRE_SEL_MASK = 1 << CLK_CORE_PRE_SEL_SHIFT, CLK_CORE_PRE_SEL_SRC = 0, CLK_CORE_PRE_SEL_APLL, /* CRU_CLK_SEL2_CON */ SCLK_CORE_PRE_SEL_SHIFT = 15, SCLK_CORE_PRE_SEL_MASK = 1 << SCLK_CORE_PRE_SEL_SHIFT, SCLK_CORE_PRE_SEL_SRC = 0, SCLK_CORE_PRE_SEL_NPLL, SCLK_CORE_SRC_SEL_SHIFT = 8, SCLK_CORE_SRC_SEL_MASK = 3 << SCLK_CORE_SRC_SEL_SHIFT, SCLK_CORE_SRC_SEL_APLL = 0, SCLK_CORE_SRC_SEL_GPLL, SCLK_CORE_SRC_SEL_NPLL, SCLK_CORE_SRC_DIV_SHIFT = 0, SCLK_CORE_SRC_DIV_MASK = 0x1f << SCLK_CORE_SRC_DIV_SHIFT, /* CRU_CLK_SEL3_CON */ GICCLK_CORE_DIV_SHIFT = 8, GICCLK_CORE_DIV_MASK = 0x1f << GICCLK_CORE_DIV_SHIFT, ATCLK_CORE_DIV_SHIFT = 0, ATCLK_CORE_DIV_MASK = 0x1f << ATCLK_CORE_DIV_SHIFT, /* CRU_CLK_SEL4_CON */ PERIPHCLK_CORE_PRE_DIV_SHIFT = 8, PERIPHCLK_CORE_PRE_DIV_MASK = 0x1f << PERIPHCLK_CORE_PRE_DIV_SHIFT, PCLK_CORE_PRE_DIV_SHIFT = 0, PCLK_CORE_PRE_DIV_MASK = 0x1f << PCLK_CORE_PRE_DIV_SHIFT, /* CRU_CLK_SEL5_CON */ ACLK_CORE_NIU2BUS_SEL_SHIFT = 14, ACLK_CORE_NIU2BUS_SEL_MASK = 0x3 << ACLK_CORE_NIU2BUS_SEL_SHIFT, ACLK_CORE_NDFT_DIV_SHIFT = 8, ACLK_CORE_NDFT_DIV_MASK = 0x1f << ACLK_CORE_NDFT_DIV_SHIFT, /* CRU_CLK_SEL10_CON */ HCLK_PERIMID_SEL_SHIFT = 6, HCLK_PERIMID_SEL_MASK = 3 << HCLK_PERIMID_SEL_SHIFT, HCLK_PERIMID_SEL_150M = 0, HCLK_PERIMID_SEL_100M, HCLK_PERIMID_SEL_75M, HCLK_PERIMID_SEL_24M, ACLK_PERIMID_SEL_SHIFT = 4, ACLK_PERIMID_SEL_MASK = 3 << ACLK_PERIMID_SEL_SHIFT, ACLK_PERIMID_SEL_300M = 0, ACLK_PERIMID_SEL_200M, ACLK_PERIMID_SEL_100M, ACLK_PERIMID_SEL_24M, /* CRU_CLK_SEL27_CON */ CLK_CRYPTO_PKA_SEL_SHIFT = 6, CLK_CRYPTO_PKA_SEL_MASK = 3 << CLK_CRYPTO_PKA_SEL_SHIFT, CLK_CRYPTO_PKA_SEL_300M = 0, CLK_CRYPTO_PKA_SEL_200M, CLK_CRYPTO_PKA_SEL_100M, CLK_CRYPTO_CORE_SEL_SHIFT = 4, CLK_CRYPTO_CORE_SEL_MASK = 3 << CLK_CRYPTO_CORE_SEL_SHIFT, CLK_CRYPTO_CORE_SEL_200M = 0, CLK_CRYPTO_CORE_SEL_150M, CLK_CRYPTO_CORE_SEL_100M, HCLK_SECURE_FLASH_SEL_SHIFT = 2, HCLK_SECURE_FLASH_SEL_MASK = 3 << HCLK_SECURE_FLASH_SEL_SHIFT, HCLK_SECURE_FLASH_SEL_150M = 0, HCLK_SECURE_FLASH_SEL_100M, HCLK_SECURE_FLASH_SEL_75M, HCLK_SECURE_FLASH_SEL_24M, ACLK_SECURE_FLASH_SEL_SHIFT = 0, ACLK_SECURE_FLASH_SEL_MASK = 3 << ACLK_SECURE_FLASH_SEL_SHIFT, ACLK_SECURE_FLASH_SEL_200M = 0, ACLK_SECURE_FLASH_SEL_150M, ACLK_SECURE_FLASH_SEL_100M, ACLK_SECURE_FLASH_SEL_24M, /* CRU_CLK_SEL28_CON */ CCLK_EMMC_SEL_SHIFT = 12, CCLK_EMMC_SEL_MASK = 7 << CCLK_EMMC_SEL_SHIFT, CCLK_EMMC_SEL_24M = 0, CCLK_EMMC_SEL_200M, CCLK_EMMC_SEL_150M, CCLK_EMMC_SEL_100M, CCLK_EMMC_SEL_50M, CCLK_EMMC_SEL_375K, BCLK_EMMC_SEL_SHIFT = 8, BCLK_EMMC_SEL_MASK = 3 << BCLK_EMMC_SEL_SHIFT, BCLK_EMMC_SEL_200M = 0, BCLK_EMMC_SEL_150M, BCLK_EMMC_SEL_125M, SCLK_SFC_SEL_SHIFT = 4, SCLK_SFC_SEL_MASK = 7 << SCLK_SFC_SEL_SHIFT, SCLK_SFC_SEL_24M = 0, SCLK_SFC_SEL_50M, SCLK_SFC_SEL_75M, SCLK_SFC_SEL_100M, SCLK_SFC_SEL_125M, SCLK_SFC_SEL_150M, NCLK_NANDC_SEL_SHIFT = 0, NCLK_NANDC_SEL_MASK = 3 << NCLK_NANDC_SEL_SHIFT, NCLK_NANDC_SEL_200M = 0, NCLK_NANDC_SEL_150M, NCLK_NANDC_SEL_100M, NCLK_NANDC_SEL_24M, /* CRU_CLK_SEL30_CON */ CLK_SDMMC1_SEL_SHIFT = 12, CLK_SDMMC1_SEL_MASK = 7 << CLK_SDMMC1_SEL_SHIFT, CLK_SDMMC0_SEL_SHIFT = 8, CLK_SDMMC0_SEL_MASK = 7 << CLK_SDMMC0_SEL_SHIFT, CLK_SDMMC_SEL_24M = 0, CLK_SDMMC_SEL_400M, CLK_SDMMC_SEL_300M, CLK_SDMMC_SEL_100M, CLK_SDMMC_SEL_50M, CLK_SDMMC_SEL_750K, /* CRU_CLK_SEL31_CON */ CLK_MAC0_OUT_SEL_SHIFT = 14, CLK_MAC0_OUT_SEL_MASK = 3 << CLK_MAC0_OUT_SEL_SHIFT, CLK_MAC0_OUT_SEL_125M = 0, CLK_MAC0_OUT_SEL_50M, CLK_MAC0_OUT_SEL_25M, CLK_MAC0_OUT_SEL_24M, CLK_GMAC0_PTP_REF_SEL_SHIFT = 12, CLK_GMAC0_PTP_REF_SEL_MASK = 3 << CLK_GMAC0_PTP_REF_SEL_SHIFT, CLK_GMAC0_PTP_REF_SEL_62_5M = 0, CLK_GMAC0_PTP_REF_SEL_100M, CLK_GMAC0_PTP_REF_SEL_50M, CLK_GMAC0_PTP_REF_SEL_24M, CLK_MAC0_2TOP_SEL_SHIFT = 8, CLK_MAC0_2TOP_SEL_MASK = 3 << CLK_MAC0_2TOP_SEL_SHIFT, CLK_MAC0_2TOP_SEL_125M = 0, CLK_MAC0_2TOP_SEL_50M, CLK_MAC0_2TOP_SEL_25M, CLK_MAC0_2TOP_SEL_PPLL, RGMII0_CLK_SEL_SHIFT = 4, RGMII0_CLK_SEL_MASK = 3 << RGMII0_CLK_SEL_SHIFT, RGMII0_CLK_SEL_125M = 0, RGMII0_CLK_SEL_125M_1, RGMII0_CLK_SEL_2_5M, RGMII0_CLK_SEL_25M, RMII0_CLK_SEL_SHIFT = 3, RMII0_CLK_SEL_MASK = 1 << RMII0_CLK_SEL_SHIFT, RMII0_CLK_SEL_2_5M = 0, RMII0_CLK_SEL_25M, RMII0_EXTCLK_SEL_SHIFT = 2, RMII0_EXTCLK_SEL_MASK = 1 << RMII0_EXTCLK_SEL_SHIFT, RMII0_EXTCLK_SEL_MAC0_TOP = 0, RMII0_EXTCLK_SEL_IO, RMII0_MODE_SHIFT = 0, RMII0_MODE_MASK = 3 << RMII0_MODE_SHIFT, RMII0_MODE_SEL_RGMII = 0, RMII0_MODE_SEL_RMII, RMII0_MODE_SEL_GMII, /* CRU_CLK_SEL32_CON */ CLK_SDMMC2_SEL_SHIFT = 8, CLK_SDMMC2_SEL_MASK = 7 << CLK_SDMMC2_SEL_SHIFT, /* CRU_CLK_SEL38_CON */ ACLK_VOP_PRE_SEL_SHIFT = 6, ACLK_VOP_PRE_SEL_MASK = 3 << ACLK_VOP_PRE_SEL_SHIFT, ACLK_VOP_PRE_SEL_CPLL = 0, ACLK_VOP_PRE_SEL_GPLL, ACLK_VOP_PRE_SEL_HPLL, ACLK_VOP_PRE_SEL_VPLL, ACLK_VOP_PRE_DIV_SHIFT = 0, ACLK_VOP_PRE_DIV_MASK = 0x1f << ACLK_VOP_PRE_DIV_SHIFT, /* CRU_CLK_SEL39_CON */ DCLK0_VOP_SEL_SHIFT = 10, DCLK0_VOP_SEL_MASK = 3 << DCLK0_VOP_SEL_SHIFT, DCLK_VOP_SEL_HPLL = 0, DCLK_VOP_SEL_VPLL, DCLK_VOP_SEL_GPLL, DCLK_VOP_SEL_CPLL, DCLK0_VOP_DIV_SHIFT = 0, DCLK0_VOP_DIV_MASK = 0xff << DCLK0_VOP_DIV_SHIFT, /* CRU_CLK_SEL40_CON */ DCLK1_VOP_SEL_SHIFT = 10, DCLK1_VOP_SEL_MASK = 3 << DCLK1_VOP_SEL_SHIFT, DCLK1_VOP_DIV_SHIFT = 0, DCLK1_VOP_DIV_MASK = 0xff << DCLK1_VOP_DIV_SHIFT, /* CRU_CLK_SEL41_CON */ DCLK2_VOP_SEL_SHIFT = 10, DCLK2_VOP_SEL_MASK = 3 << DCLK2_VOP_SEL_SHIFT, DCLK2_VOP_DIV_SHIFT = 0, DCLK2_VOP_DIV_MASK = 0xff << DCLK2_VOP_DIV_SHIFT, /* CRU_CLK_SEL43_CON */ DCLK_EBC_SEL_SHIFT = 6, DCLK_EBC_SEL_MASK = 3 << DCLK_EBC_SEL_SHIFT, DCLK_EBC_SEL_GPLL_400M = 0, DCLK_EBC_SEL_CPLL_333M, DCLK_EBC_SEL_GPLL_200M, /* CRU_CLK_SEL47_CON */ ACLK_RKVDEC_SEL_SHIFT = 7, ACLK_RKVDEC_SEL_MASK = 1 << ACLK_RKVDEC_SEL_SHIFT, ACLK_RKVDEC_SEL_GPLL = 0, ACLK_RKVDEC_SEL_CPLL, ACLK_RKVDEC_DIV_SHIFT = 0, ACLK_RKVDEC_DIV_MASK = 0x1f << ACLK_RKVDEC_DIV_SHIFT, /* CRU_CLK_SEL49_CON */ CLK_RKVDEC_CORE_SEL_SHIFT = 14, CLK_RKVDEC_CORE_SEL_MASK = 0x3 << CLK_RKVDEC_CORE_SEL_SHIFT, CLK_RKVDEC_CORE_SEL_GPLL = 0, CLK_RKVDEC_CORE_SEL_CPLL, CLK_RKVDEC_CORE_SEL_NPLL, CLK_RKVDEC_CORE_SEL_VPLL, CLK_RKVDEC_CORE_DIV_SHIFT = 8, CLK_RKVDEC_CORE_DIV_MASK = 0x1f << CLK_RKVDEC_CORE_DIV_SHIFT, /* CRU_CLK_SEL50_CON */ PCLK_BUS_SEL_SHIFT = 4, PCLK_BUS_SEL_MASK = 3 << PCLK_BUS_SEL_SHIFT, PCLK_BUS_SEL_100M = 0, PCLK_BUS_SEL_75M, PCLK_BUS_SEL_50M, PCLK_BUS_SEL_24M, ACLK_BUS_SEL_SHIFT = 0, ACLK_BUS_SEL_MASK = 3 << ACLK_BUS_SEL_SHIFT, ACLK_BUS_SEL_200M = 0, ACLK_BUS_SEL_150M, ACLK_BUS_SEL_100M, ACLK_BUS_SEL_24M, /* CRU_CLK_SEL51_CON */ CLK_TSADC_DIV_SHIFT = 8, CLK_TSADC_DIV_MASK = 0x7f << CLK_TSADC_DIV_SHIFT, CLK_TSADC_TSEN_SEL_SHIFT = 4, CLK_TSADC_TSEN_SEL_MASK = 0x3 << CLK_TSADC_TSEN_SEL_SHIFT, CLK_TSADC_TSEN_SEL_24M = 0, CLK_TSADC_TSEN_SEL_100M, CLK_TSADC_TSEN_SEL_CPLL_100M, CLK_TSADC_TSEN_DIV_SHIFT = 0, CLK_TSADC_TSEN_DIV_MASK = 0x7 << CLK_TSADC_TSEN_DIV_SHIFT, /* CRU_CLK_SEL52_CON */ CLK_UART_SEL_SHIFT = 12, CLK_UART_SEL_MASK = 0x3 << CLK_UART_SEL_SHIFT, CLK_UART_SEL_SRC = 0, CLK_UART_SEL_FRAC, CLK_UART_SEL_XIN24M, CLK_UART_SRC_SEL_SHIFT = 8, CLK_UART_SRC_SEL_MASK = 0x3 << CLK_UART_SRC_SEL_SHIFT, CLK_UART_SRC_SEL_GPLL = 0, CLK_UART_SRC_SEL_CPLL, CLK_UART_SRC_SEL_480M, CLK_UART_SRC_DIV_SHIFT = 0, CLK_UART_SRC_DIV_MASK = 0x3f << CLK_UART_SRC_DIV_SHIFT, /* CRU_CLK_SEL53_CON */ CLK_UART_FRAC_NUMERATOR_SHIFT = 16, CLK_UART_FRAC_NUMERATOR_MASK = 0xffff << 16, CLK_UART_FRAC_DENOMINATOR_SHIFT = 0, CLK_UART_FRAC_DENOMINATOR_MASK = 0xffff, /* CRU_CLK_SEL71_CON */ CLK_I2C_SEL_SHIFT = 8, CLK_I2C_SEL_MASK = 3 << CLK_I2C_SEL_SHIFT, CLK_I2C_SEL_200M = 0, CLK_I2C_SEL_100M, CLK_I2C_SEL_24M, CLK_I2C_SEL_CPLL_100M, /* CRU_CLK_SEL72_CON */ CLK_PWM3_SEL_SHIFT = 12, CLK_PWM3_SEL_MASK = 3 << CLK_PWM3_SEL_SHIFT, CLK_PWM2_SEL_SHIFT = 10, CLK_PWM2_SEL_MASK = 3 << CLK_PWM2_SEL_SHIFT, CLK_PWM1_SEL_SHIFT = 8, CLK_PWM1_SEL_MASK = 3 << CLK_PWM1_SEL_SHIFT, CLK_PWM_SEL_100M = 0, CLK_PWM_SEL_24M, CLK_PWM_SEL_CPLL_100M, CLK_SPI3_SEL_SHIFT = 6, CLK_SPI3_SEL_MASK = 3 << CLK_SPI3_SEL_SHIFT, CLK_SPI2_SEL_SHIFT = 4, CLK_SPI2_SEL_MASK = 3 << CLK_SPI2_SEL_SHIFT, CLK_SPI1_SEL_SHIFT = 2, CLK_SPI1_SEL_MASK = 3 << CLK_SPI1_SEL_SHIFT, CLK_SPI0_SEL_SHIFT = 0, CLK_SPI0_SEL_MASK = 3 << CLK_SPI0_SEL_SHIFT, CLK_SPI_SEL_200M = 0, CLK_SPI_SEL_24M, CLK_SPI_SEL_CPLL_100M, /* CRU_CLK_SEL73_CON */ PCLK_TOP_SEL_SHIFT = 12, PCLK_TOP_SEL_MASK = 3 << PCLK_TOP_SEL_SHIFT, PCLK_TOP_SEL_100M = 0, PCLK_TOP_SEL_75M, PCLK_TOP_SEL_50M, PCLK_TOP_SEL_24M, HCLK_TOP_SEL_SHIFT = 8, HCLK_TOP_SEL_MASK = 3 << HCLK_TOP_SEL_SHIFT, HCLK_TOP_SEL_150M = 0, HCLK_TOP_SEL_100M, HCLK_TOP_SEL_75M, HCLK_TOP_SEL_24M, ACLK_TOP_LOW_SEL_SHIFT = 4, ACLK_TOP_LOW_SEL_MASK = 3 << ACLK_TOP_LOW_SEL_SHIFT, ACLK_TOP_LOW_SEL_400M = 0, ACLK_TOP_LOW_SEL_300M, ACLK_TOP_LOW_SEL_200M, ACLK_TOP_LOW_SEL_24M, ACLK_TOP_HIGH_SEL_SHIFT = 0, ACLK_TOP_HIGH_SEL_MASK = 3 << ACLK_TOP_HIGH_SEL_SHIFT, ACLK_TOP_HIGH_SEL_500M = 0, ACLK_TOP_HIGH_SEL_400M, ACLK_TOP_HIGH_SEL_300M, ACLK_TOP_HIGH_SEL_24M, /* CRU_CLK_SEL78_CON */ CPLL_500M_DIV_SHIFT = 8, CPLL_500M_DIV_MASK = 0x1f << CPLL_500M_DIV_SHIFT, /* CRU_CLK_SEL79_CON */ CPLL_250M_DIV_SHIFT = 8, CPLL_250M_DIV_MASK = 0x1f << CPLL_250M_DIV_SHIFT, CPLL_333M_DIV_SHIFT = 0, CPLL_333M_DIV_MASK = 0x1f << CPLL_333M_DIV_SHIFT, /* CRU_CLK_SEL80_CON */ CPLL_62P5M_DIV_SHIFT = 8, CPLL_62P5M_DIV_MASK = 0x1f << CPLL_62P5M_DIV_SHIFT, CPLL_125M_DIV_SHIFT = 0, CPLL_125M_DIV_MASK = 0x1f << CPLL_125M_DIV_SHIFT, /* CRU_CLK_SEL81_CON */ CPLL_25M_DIV_SHIFT = 8, CPLL_25M_DIV_MASK = 0x1f << CPLL_25M_DIV_SHIFT, CPLL_50M_DIV_SHIFT = 0, CPLL_50M_DIV_MASK = 0x1f << CPLL_50M_DIV_SHIFT, /* CRU_CLK_SEL82_CON */ CPLL_100M_DIV_SHIFT = 0, CPLL_100M_DIV_MASK = 0x1f << CPLL_100M_DIV_SHIFT, }; static struct rk_cpu_rate_table cpu_rates[] = { CPUCLK_RATE(1800000000, 1, 7), CPUCLK_RATE(1704000000, 1, 7), CPUCLK_RATE(1608000000, 1, 5), CPUCLK_RATE(1584000000, 1, 5), CPUCLK_RATE(1560000000, 1, 5), CPUCLK_RATE(1536000000, 1, 5), CPUCLK_RATE(1512000000, 1, 5), CPUCLK_RATE(1488000000, 1, 5), CPUCLK_RATE(1464000000, 1, 5), CPUCLK_RATE(1440000000, 1, 5), CPUCLK_RATE(1416000000, 1, 5), CPUCLK_RATE(1392000000, 1, 5), CPUCLK_RATE(1368000000, 1, 5), CPUCLK_RATE(1344000000, 1, 5), CPUCLK_RATE(1320000000, 1, 5), CPUCLK_RATE(1296000000, 1, 5), CPUCLK_RATE(1272000000, 1, 5), CPUCLK_RATE(1248000000, 1, 5), CPUCLK_RATE(1224000000, 1, 5), CPUCLK_RATE(1200000000, 1, 3), CPUCLK_RATE(1104000000, 1, 3), CPUCLK_RATE(1008000000, 1, 3), CPUCLK_RATE(912000000, 1, 3), CPUCLK_RATE(816000000, 1, 3), CPUCLK_RATE(696000000, 1, 3), CPUCLK_RATE(600000000, 1, 3), CPUCLK_RATE(408000000, 1, 3), CPUCLK_RATE(312000000, 1, 3), CPUCLK_RATE(216000000, 1, 3), CPUCLK_RATE(96000000, 1, 3), { /* sentinel */ }, }; static struct rk_pll_rate_table pll_rates[] = { /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ PLL_RATE(2208000000, 1, 92, 1, 1, 1, 0), PLL_RATE(2184000000, 1, 91, 1, 1, 1, 0), PLL_RATE(2160000000, 1, 90, 1, 1, 1, 0), PLL_RATE(2088000000, 1, 87, 1, 1, 1, 0), PLL_RATE(2064000000, 1, 86, 1, 1, 1, 0), PLL_RATE(2040000000, 1, 85, 1, 1, 1, 0), PLL_RATE(2016000000, 1, 84, 1, 1, 1, 0), PLL_RATE(1992000000, 1, 83, 1, 1, 1, 0), PLL_RATE(1920000000, 1, 80, 1, 1, 1, 0), PLL_RATE(1896000000, 1, 79, 1, 1, 1, 0), PLL_RATE(1800000000, 1, 75, 1, 1, 1, 0), PLL_RATE(1704000000, 1, 71, 1, 1, 1, 0), PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0), PLL_RATE(1600000000, 3, 200, 1, 1, 1, 0), PLL_RATE(1584000000, 1, 132, 2, 1, 1, 0), PLL_RATE(1560000000, 1, 130, 2, 1, 1, 0), PLL_RATE(1536000000, 1, 128, 2, 1, 1, 0), PLL_RATE(1512000000, 1, 126, 2, 1, 1, 0), PLL_RATE(1488000000, 1, 124, 2, 1, 1, 0), PLL_RATE(1464000000, 1, 122, 2, 1, 1, 0), PLL_RATE(1440000000, 1, 120, 2, 1, 1, 0), PLL_RATE(1416000000, 1, 118, 2, 1, 1, 0), PLL_RATE(1400000000, 3, 350, 2, 1, 1, 0), PLL_RATE(1392000000, 1, 116, 2, 1, 1, 0), PLL_RATE(1368000000, 1, 114, 2, 1, 1, 0), PLL_RATE(1344000000, 1, 112, 2, 1, 1, 0), PLL_RATE(1320000000, 1, 110, 2, 1, 1, 0), PLL_RATE(1296000000, 1, 108, 2, 1, 1, 0), PLL_RATE(1272000000, 1, 106, 2, 1, 1, 0), PLL_RATE(1248000000, 1, 104, 2, 1, 1, 0), PLL_RATE(1200000000, 1, 100, 2, 1, 1, 0), PLL_RATE(1188000000, 1, 99, 2, 1, 1, 0), PLL_RATE(1104000000, 1, 92, 2, 1, 1, 0), PLL_RATE(1100000000, 3, 275, 2, 1, 1, 0), PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0), PLL_RATE(1000000000, 3, 250, 2, 1, 1, 0), PLL_RATE(912000000, 1, 76, 2, 1, 1, 0), PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), PLL_RATE(800000000, 3, 200, 2, 1, 1, 0), PLL_RATE(700000000, 3, 350, 4, 1, 1, 0), PLL_RATE(696000000, 1, 116, 4, 1, 1, 0), PLL_RATE(600000000, 1, 100, 4, 1, 1, 0), PLL_RATE(594000000, 1, 99, 4, 1, 1, 0), PLL_RATE(500000000, 1, 125, 6, 1, 1, 0), PLL_RATE(408000000, 1, 68, 2, 2, 1, 0), PLL_RATE(312000000, 1, 78, 6, 1, 1, 0), PLL_RATE(297000000, 2, 99, 4, 1, 1, 0), PLL_RATE(241500000, 2, 161, 4, 2, 1, 0), PLL_RATE(216000000, 1, 72, 4, 2, 1, 0), PLL_RATE(200000000, 1, 100, 3, 4, 1, 0), PLL_RATE(148500000, 1, 99, 4, 4, 1, 0), PLL_RATE(135000000, 2, 45, 4, 1, 1, 0), PLL_RATE(119000000, 3, 119, 4, 2, 1, 0), PLL_RATE(108000000, 2, 45, 5, 1, 1, 0), PLL_RATE(100000000, 1, 150, 6, 6, 1, 0), PLL_RATE(96000000, 1, 96, 6, 4, 1, 0), PLL_RATE(78750000, 1, 96, 6, 4, 1, 0), PLL_RATE(74250000, 2, 99, 4, 4, 1, 0), { /* sentinel */ }, }; static struct rk_pll_clock pmu_pll_clks[] = { [ppll] = PLL(PLL_PPLL, PMU_PLL_CON(0), PMU_MODE, 0, 10, 0, pll_rates), [hpll] = PLL(PLL_HPLL, PMU_PLL_CON(16), PMU_MODE, 2, 10, 0, pll_rates), }; static struct rk_pll_clock pll_clks[] = { [apll] = PLL(PLL_APLL, PLL_CON(0), MODE_CON, 0, 10, 0, pll_rates), [dpll] = PLL(PLL_DPLL, PLL_CON(8), MODE_CON, 2, 10, 0, RT_NULL), [gpll] = PLL(PLL_HPLL, PLL_CON(16), MODE_CON, 6, 10, 0, pll_rates), [cpll] = PLL(PLL_CPLL, PLL_CON(24), MODE_CON, 4, 10, 0, pll_rates), [npll] = PLL(PLL_NPLL, PLL_CON(32), MODE_CON, 10, 10, 0, pll_rates), [vpll] = PLL(PLL_VPLL, PLL_CON(40), MODE_CON, 12, 10, 0, pll_rates), }; static struct rk_clk_gate clk_gates[] = { /* CRU_GATE_CON00 */ /* CRU_GATE_CON01 */ GATE(PCLK_CORE_PVTM, "pclk_core_pvtm", "pclk_core_pre", 1, 9), GATE(CLK_CORE_PVTM, "clk_core_pvtm", "xin24m", 1, 10), GATE(CLK_CORE_PVTM_CORE, "clk_core_pvtm_core", "armclk", 1, 11), GATE(CLK_CORE_PVTPLL, "clk_core_pvtpll", "armclk", 1, 12), /* CRU_GATE_CON02 */ GATE(CLK_GPU_SRC, "clk_gpu_src", "clk_gpu_pre_c", 2, 0), GATE(PCLK_GPU_PRE, "pclk_gpu_pre", "pclk_gpu_pre_div", 2, 2), GATE(CLK_GPU, "clk_gpu", "clk_gpu_pre_c", 2, 3), GATE(PCLK_GPU_PVTM, "pclk_gpu_pvtm", "pclk_gpu_pre", 2, 6), GATE(CLK_GPU_PVTM, "clk_gpu_pvtm", "xin24m", 2, 7), GATE(CLK_GPU_PVTM_CORE, "clk_gpu_pvtm_core", "clk_gpu_src", 2, 8), GATE(CLK_GPU_PVTPLL, "clk_gpu_pvtpll", "clk_gpu_src", 2, 9), GATE(ACLK_GPU_PRE, "aclk_gpu_pre", "aclk_gpu_pre_div", 2, 11), /* CRU_GATE_CON03 */ GATE(CLK_NPU_SRC, "clk_npu_src", "clk_npu_src_c", 3, 0), GATE(CLK_NPU_NP5, "clk_npu_np5", "clk_npu_np5_c", 3, 1), GATE(HCLK_NPU_PRE, "hclk_npu_pre", "hclk_npu_pre_div", 3, 2), GATE(PCLK_NPU_PRE, "pclk_npu_pre", "pclk_npu_pre_div", 3, 3), GATE(ACLK_NPU_PRE, "aclk_npu_pre", "clk_npu", 3, 4), GATE(ACLK_NPU, "aclk_npu", "aclk_npu_pre", 3, 7), GATE(HCLK_NPU, "hclk_npu", "hclk_npu_pre", 3, 8), GATE(PCLK_NPU_PVTM, "pclk_npu_pvtm", "pclk_npu_pre", 3, 9), GATE(CLK_NPU_PVTM, "clk_npu_pvtm", "xin24m", 3, 10), GATE(CLK_NPU_PVTM_CORE, "clk_npu_pvtm_core", "clk_npu_pre_ndft", 3, 11), GATE(CLK_NPU_PVTPLL, "clk_npu_pvtpll", "clk_npu_pre_ndft", 3, 12), /* CRU_GATE_CON04 */ GATE(CLK_DDRPHY1X_SRC, "clk_ddrphy1x_src", "clk_ddrphy1x_src_c", 4, 0), GATE(CLK_MSCH, "clk_msch", "clk_msch_div", 4, 2), GATE(CLK24_DDRMON, "clk24_ddrmon", "xin24m", 4, 15), /* CRU_GATE_CON05 */ GATE(ACLK_GIC_AUDIO, "aclk_gic_audio", "aclk_gic_audio_sel", 5, 0), GATE(HCLK_GIC_AUDIO, "hclk_gic_audio", "hclk_gic_audio_sel", 5, 1), GATE(ACLK_GIC600, "aclk_gic600", "aclk_gic_audio", 5, 4), GATE(ACLK_SPINLOCK, "aclk_spinlock", "aclk_gic_audio", 5, 7), GATE(HCLK_SDMMC_BUFFER, "hclk_sdmmc_buffer", "hclk_gic_audio", 5, 8), GATE(DCLK_SDMMC_BUFFER, "dclk_sdmmc_buffer", "dclk_sdmmc_buffer_sel", 5, 9), GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_gic_audio", 5, 10), GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_gic_audio", 5, 11), GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_gic_audio", 5, 12), GATE(HCLK_I2S3_2CH, "hclk_i2s3_2ch", "hclk_gic_audio", 5, 13), GATE(HCLK_PDM, "hclk_pdm", "hclk_gic_audio", 5, 14), GATE(MCLK_PDM, "mclk_pdm", "mclk_pdm_sel", 5, 15), /* CRU_GATE_CON06 */ GATE(CLK_I2S0_8CH_TX_SRC, "clk_i2s0_8ch_tx_src", "clk_i2s0_8ch_tx_src_c", 6, 0), GATE(CLK_I2S0_8CH_TX_FRAC, "clk_i2s0_8ch_tx_frac", "clk_i2s0_8ch_tx_frac_div", 6, 1), GATE(MCLK_I2S0_8CH_TX, "mclk_i2s0_8ch_tx", "clk_i2s0_8ch_tx", 6, 2), GATE(I2S0_MCLKOUT_TX, "i2s0_mclkout_tx", "i2s0_mclkout_tx_sel", 6, 3), GATE(CLK_I2S0_8CH_RX_SRC, "clk_i2s0_8ch_rx_src", "clk_i2s0_8ch_rx_src_c", 6, 4), GATE(CLK_I2S0_8CH_RX_FRAC, "clk_i2s0_8ch_rx_frac", "clk_i2s0_8ch_rx_frac_div", 6, 5), GATE(MCLK_I2S0_8CH_RX, "mclk_i2s0_8ch_rx", "clk_i2s0_8ch_rx", 6, 6), GATE(I2S0_MCLKOUT_RX, "i2s0_mclkout_rx", "i2s0_mclkout_rx_sel", 6, 7), GATE(CLK_I2S1_8CH_TX_SRC, "clk_i2s1_8ch_tx_src", "clk_i2s1_8ch_tx_src_c", 6, 8), GATE(CLK_I2S1_8CH_TX_FRAC, "clk_i2s1_8ch_tx_frac", "clk_i2s1_8ch_tx_frac_div", 6, 9), GATE(MCLK_I2S1_8CH_TX, "mclk_i2s1_8ch_tx", "clk_i2s1_8ch_tx", 6, 10), GATE(I2S1_MCLKOUT_TX, "i2s1_mclkout_tx", "i2s1_mclkout_tx_sel", 6, 11), GATE(CLK_I2S1_8CH_RX_SRC, "clk_i2s1_8ch_rx_src", "clk_i2s1_8ch_rx_src_c", 6, 12), GATE(CLK_I2S1_8CH_RX_FRAC, "clk_i2s1_8ch_rx_frac", "clk_i2s1_8ch_rx_frac_div", 6, 13), GATE(MCLK_I2S1_8CH_RX, "mclk_i2s1_8ch_rx", "clk_i2s1_8ch_rx", 6, 14), GATE(I2S1_MCLKOUT_RX, "i2s1_mclkout_rx", "i2s1_mclkout_rx_sel", 6, 15), /* CRU_GATE_CON07 */ GATE(CLK_I2S2_2CH_SRC, "clk_i2s2_2ch_src", "clk_i2s2_2ch_src_c", 7, 0), GATE(CLK_I2S2_2CH_FRAC, "clk_i2s2_2ch_frac", "clk_i2s2_2ch_frac_div", 7, 1), GATE(MCLK_I2S2_2CH, "mclk_i2s2_2ch", "clk_i2s2_2ch", 7, 2), GATE(I2S2_MCLKOUT, "i2s2_mclkout", "i2s2_mclkout_sel", 7, 3), GATE(CLK_I2S3_2CH_TX, "clk_i2s3_2ch_tx_src", "clk_i2s3_2ch_tx_src_c", 7, 4), GATE(CLK_I2S3_2CH_TX_FRAC, "clk_i2s3_2ch_tx_frac", "clk_i2s3_2ch_tx_frac_div", 7, 5), GATE(MCLK_I2S3_2CH_TX, "mclk_i2s3_2ch_tx", "clk_i2s3_2ch_tx", 7, 6), GATE(I2S3_MCLKOUT_TX, "i2s3_mclkout_tx", "i2s3_mclkout_tx_sel", 7, 7), GATE(CLK_I2S3_2CH_RX, "clk_i2s3_2ch_rx_src", "clk_i2s3_2ch_rx_src_div", 7, 8), GATE(CLK_I2S3_2CH_RX_FRAC, "clk_i2s3_2ch_rx_frac", "clk_i2s3_2ch_rx_frac_div", 7, 9), GATE(MCLK_I2S3_2CH_RX, "mclk_i2s3_2ch_rx", "clk_i2s3_2ch_rx", 7, 10), GATE(I2S3_MCLKOUT_RX, "i2s3_mclkout_rx", "i2s3_mclkout_rx_sel", 7, 11), GATE(HCLK_VAD, "hclk_vad", "hclk_gic_audio", 7, 12), GATE(HCLK_SPDIF_8CH, "hclk_spdif_8ch", "hclk_gic_audio", 7, 13), GATE(MCLK_SPDIF_8CH_SRC, "mclk_spdif_8ch_src", "mclk_spdif_8ch_src_c", 7, 14), GATE(MCLK_SPDIF_8CH_FRAC, "mclk_spdif_8ch_frac", "mclk_spdif_8ch_frac_div", 7, 15), /* CRU_GATE_CON08 */ GATE(HCLK_AUDPWM, "hclk_audpwm", "hclk_gic_audio", 8, 0), GATE(SCLK_AUDPWM_SRC, "sclk_audpwm_src", "sclk_audpwm_src_c", 8, 1), GATE(SCLK_AUDPWM_FRAC, "sclk_audpwm_frac", "sclk_audpwm_frac_frac", 8, 2), GATE(HCLK_ACDCDIG, "hclk_acdcdig", "hclk_gic_audio", 8, 3), GATE(CLK_ACDCDIG_I2C, "clk_acdcdig_i2c", "clk_acdcdig_i2c_sel", 8, 4), GATE(CLK_ACDCDIG_DAC, "clk_acdcdig_dac", "mclk_i2s3_2ch_tx", 8, 5), GATE(CLK_ACDCDIG_ADC, "clk_acdcdig_adc", "mclk_i2s3_2ch_rx", 8, 6), GATE(ACLK_SECURE_FLASH, "aclk_secure_flash", "aclk_secure_flash_sel", 8, 7), GATE(HCLK_SECURE_FLASH, "hclk_secure_flash", "hclk_secure_flash_sel", 8, 8), GATE(ACLK_CRYPTO_NS, "aclk_crypto_ns", "aclk_secure_flash", 8, 11), GATE(HCLK_CRYPTO_NS, "hclk_crypto_ns", "hclk_secure_flash", 8, 12), GATE(CLK_CRYPTO_NS_CORE, "clk_crypto_ns_core", "clk_crypto_ns_core_sel", 8, 13), GATE(CLK_CRYPTO_NS_PKA, "clk_crypto_ns_pka", "clk_crypto_ns_pka_sel", 8, 14), GATE(CLK_CRYPTO_NS_RNG, "clk_crypto_ns_rng", "hclk_secure_flash", 8, 15), /* CRU_GATE_CON09 */ GATE(HCLK_NANDC, "hclk_nandc", "hclk_secure_flash", 9, 0), GATE(NCLK_NANDC, "nclk_nandc", "nclk_nandc_sel", 9, 1), GATE(HCLK_SFC, "hclk_sfc", "hclk_secure_flash", 9, 2), GATE(HCLK_SFC_XIP, "hclk_sfc_xip", "hclk_secure_flash", 9, 3), GATE(SCLK_SFC, "sclk_sfc", "sclk_sfc_sel", 9, 4), GATE(ACLK_EMMC, "aclk_emmc", "aclk_secure_flash", 9, 5), GATE(HCLK_EMMC, "hclk_emmc", "hclk_secure_flash", 9, 6), GATE(BCLK_EMMC, "bclk_emmc", "bclk_emmc_sel", 9, 7), GATE(CCLK_EMMC, "cclk_emmc", "cclk_emmc_sel", 9, 8), GATE(TCLK_EMMC, "tclk_emmc", "xin24m", 9, 9), GATE(HCLK_TRNG_NS, "hclk_trng_ns", "hclk_secure_flash", 9, 10), GATE(CLK_TRNG_NS, "clk_trng_ns", "hclk_secure_flash", 9, 11), /* CRU_GATE_CON10 */ GATE(ACLK_PIPE, "aclk_pipe", "aclk_pipe_sel", 10, 0), GATE(PCLK_PIPE, "pclk_pipe", "pclk_pipe_div", 10, 1), GATE(CLK_XPCS_EEE, "clk_xpcs_eee", "clk_xpcs_eee_sel", 10, 4), GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_pipe", 10, 8), GATE(CLK_USB3OTG0_REF, "clk_usb3otg0_ref", "xin24m", 10, 9), GATE(CLK_USB3OTG0_SUSPEND, "clk_usb3otg0_suspend", "clk_usb3otg0_suspend_sel", 10, 10), GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_pipe", 10, 12), GATE(CLK_USB3OTG1_REF, "clk_usb3otg1_ref", "xin24m", 10, 13), GATE(CLK_USB3OTG1_SUSPEND, "clk_usb3otg1_suspend", "clk_usb3otg1_suspend_sel", 10, 14), /* CRU_GATE_CON11 */ GATE(ACLK_SATA0, "aclk_sata0", "aclk_pipe", 11, 0), GATE(CLK_SATA0_PMALIVE, "clk_sata0_pmalive", "clk_gpll_div_20m", 11, 1), GATE(CLK_SATA0_RXOOB, "clk_sata0_rxoob", "clk_cpll_div_50m", 11, 2), GATE(ACLK_SATA1, "aclk_sata1", "aclk_pipe", 11, 4), GATE(CLK_SATA1_PMALIVE, "clk_sata1_pmalive", "clk_gpll_div_20m", 11, 5), GATE(CLK_SATA1_RXOOB, "clk_sata1_rxoob", "clk_cpll_div_50m", 11, 6), GATE(ACLK_SATA2, "aclk_sata2", "aclk_pipe", 11, 8), GATE(CLK_SATA2_PMALIVE, "clk_sata2_pmalive", "clk_gpll_div_20m", 11, 9), GATE(CLK_SATA2_RXOOB, "clk_sata2_rxoob", "clk_cpll_div_50m", 11, 10), /* CRU_GATE_CON12 */ GATE(ACLK_PCIE20_MST, "aclk_pcie20_mst", "aclk_pipe", 12, 0), GATE(ACLK_PCIE20_SLV, "aclk_pcie20_slv", "aclk_pipe", 12, 1), GATE(ACLK_PCIE20_DBI, "aclk_pcie20_dbi", "aclk_pipe", 12, 2), GATE(PCLK_PCIE20, "pclk_pcie20", "pclk_pipe", 12, 3), GATE(CLK_PCIE20_AUX_NDFT, "clk_pcie20_aux_ndft", "xin24m", 12, 4), GATE(ACLK_PCIE30X1_MST, "aclk_pcie30x1_mst", "aclk_pipe", 12, 8), GATE(ACLK_PCIE30X1_SLV, "aclk_pcie30x1_slv", "aclk_pipe", 12, 9), GATE(ACLK_PCIE30X1_DBI, "aclk_pcie30x1_dbi", "aclk_pipe", 12, 10), GATE(PCLK_PCIE30X1, "pclk_pcie30x1", "pclk_pipe", 12, 11), GATE(CLK_PCIE30X1_AUX_NDFT, "clk_pcie30x1_aux_ndft", "xin24m", 12, 12), /* CRU_GATE_CON13 */ GATE(ACLK_PCIE30X2_MST, "aclk_pcie30x2_mst", "aclk_pipe", 13, 0), GATE(ACLK_PCIE30X2_SLV, "aclk_pcie30x2_slv", "aclk_pipe", 13, 1), GATE(ACLK_PCIE30X2_DBI, "aclk_pcie30x2_dbi", "aclk_pipe", 13, 2), GATE(PCLK_PCIE30X2, "pclk_pcie30x2", "pclk_pipe", 13, 3), GATE(CLK_PCIE30X2_AUX_NDFT, "clk_pcie30x2_aux_ndft", "xin24m", 13, 4), GATE(PCLK_XPCS, "pclk_xpcs", "pclk_pipe", 13, 6), /* CRU_GATE_CON14 */ GATE(ACLK_PERIMID, "aclk_perimid", "aclk_perimid_sel", 14, 0), GATE(HCLK_PERIMID, "hclk_perimid", "hclk_perimid_sel", 14, 1), GATE(ACLK_PHP, "aclk_php", "aclk_php_sel", 14, 8), GATE(HCLK_PHP, "hclk_php", "hclk_php_sel", 14, 9), GATE(PCLK_PHP, "pclk_php", "pclk_php_div", 14, 10), /* CRU_GATE_CON15 */ GATE(HCLK_SDMMC0, "hclk_sdmmc0", "hclk_php", 15, 0), GATE(CLK_SDMMC0, "clk_sdmmc0", "clk_sdmmc0_sel", 15, 1), GATE(HCLK_SDMMC1, "hclk_sdmmc1", "hclk_php", 15, 2), GATE(CLK_SDMMC1, "clk_sdmmc1", "clk_sdmmc1_sel", 15, 3), GATE(CLK_GMAC0_PTP_REF, "clk_gmac0_ptp_ref", "clk_gmac0_ptp_ref_sel", 15, 4), GATE(ACLK_GMAC0, "aclk_gmac0", "aclk_php", 15, 5), GATE(PCLK_GMAC0, "pclk_gmac0", "pclk_php", 15, 6), GATE(CLK_MAC0_2TOP, "clk_mac0_2top", "clk_mac0_2top_sel", 15, 7), GATE(CLK_MAC0_OUT, "clk_mac0_out", "clk_mac0_out_sel", 15, 8), GATE(CLK_MAC0_REFOUT, "clk_mac0_refout", "clk_mac0_2top", 15, 12), /* CRU_GATE_CON16 */ GATE(ACLK_USB, "aclk_usb", "aclk_usb_sel", 16, 0), GATE(HCLK_USB, "hclk_usb", "hclk_usb_sel", 16, 1), GATE(PCLK_USB, "pclk_usb", "pclk_usb_div", 16, 2), GATE(HCLK_USB2HOST0, "hclk_usb2host0", "hclk_usb", 16, 12), GATE(HCLK_USB2HOST0_ARB, "hclk_usb2host0_arb", "hclk_usb", 16, 13), GATE(HCLK_USB2HOST1, "hclk_usb2host1", "hclk_usb", 16, 14), GATE(HCLK_USB2HOST1_ARB, "hclk_usb2host1_arb", "hclk_usb", 16, 15), /* CRU_GATE_CON17 */ GATE(HCLK_SDMMC2, "hclk_sdmmc2", "hclk_usb", 17, 0), GATE(CLK_SDMMC2, "clk_sdmmc2", "clk_sdmmc2_sel", 17, 1), GATE(CLK_GMAC1_PTP_REF, "clK_gmac1_ptp_ref", "clk_gmac1_ptp_ref_sel", 17, 2), GATE(ACLK_GMAC1, "aclk_gmac1", "aclk_usb", 17, 3), GATE(PCLK_GMAC1, "pclk_gmac1", "pclk_usb", 17, 4), GATE(CLK_MAC1_2TOP, "clk_mac1_2top", "clk_mac1_2top_sel", 17, 5), GATE(CLK_MAC1_OUT, "clk_mac1_out", "clk_mac1_out_sel", 17, 6), GATE(CLK_MAC1_REFOUT, "clk_mac1_refout", "clk_mac1_2top", 17, 10), /* CRU_GATE_CON18 */ GATE(ACLK_VI, "aclk_vi", "aclk_vi_sel", 18, 0), GATE(HCLK_VI, "hclk_vi", "hclk_vi_div", 18, 1), GATE(PCLK_VI, "pclk_vi", "pclk_vi_div", 18, 2), GATE(ACLK_VICAP, "aclk_vicap", "aclk_vi", 18, 9), GATE(HCLK_VICAP, "hclk_vicap", "hclk_vi", 18, 10), GATE(DCLK_VICAP, "dclk_vicap", "dclk_vicap1_sel", 18, 11), /* CRU_GATE_CON19 */ GATE(ACLK_ISP, "aclk_isp", "aclk_vi", 19, 0), GATE(HCLK_ISP, "hclk_isp", "hclk_vi", 19, 1), GATE(CLK_ISP, "clk_isp", "clk_isp_c", 19, 2), GATE(PCLK_CSI2HOST1, "pclk_csi2host1", "pclk_vi", 19, 4), GATE(CLK_CIF_OUT, "clk_cif_out", "clk_cif_out_c", 19, 8), GATE(CLK_CAM0_OUT, "clk_cam0_out", "clk_cam0_out_c", 19, 9), GATE(CLK_CAM1_OUT, "clk_cam1_out", "clk_cam1_out_c", 19, 9), /* CRU_GATE_CON20 */ GATE(ACLK_VO, "aclk_vo", "aclk_vo_sel", 20, 0), GATE(HCLK_VO, "hclk_vo", "hclk_vo_div", 20, 1), GATE(PCLK_VO, "pclk_vo", "pclk_vo_div", 20, 2), GATE(ACLK_VOP_PRE, "aclk_vop_pre", "aclk_vop_pre_c", 20, 6), GATE(ACLK_VOP, "aclk_vop", "aclk_vop_pre", 20, 8), GATE(HCLK_VOP, "hclk_vop", "hclk_vo", 20, 9), GATE(DCLK_VOP0, "dclk_vop0", "dclk_vop0_c", 20, 10), GATE(DCLK_VOP1, "dclk_vop1", "dclk_vop1_c", 20, 11), GATE(DCLK_VOP2, "dclk_vop2", "dclk_vop2_c", 20, 12), GATE(CLK_VOP_PWM, "clk_vop_pwm", "xin24m", 20, 13), /* CRU_GATE_CON21 */ GATE(ACLK_HDCP, "aclk_hdcp", "aclk_vo", 21, 0), GATE(HCLK_HDCP, "hclk_hdcp", "hclk_vo", 21, 1), GATE(PCLK_HDCP, "pclk_hdcp", "pclk_vo", 21, 2), GATE(PCLK_HDMI_HOST, "pclk_hdmi_host", "pclk_vo", 21, 3), GATE(CLK_HDMI_SFR, "clk_hdmi_sfr", "xin24m", 21, 4), GATE(CLK_HDMI_CEC, "clk_hdmi_cec", "clk_rtc_32k", 21, 5), GATE(PCLK_DSITX_0, "pclk_dsitx_0", "pclk_vo", 21, 6), GATE(PCLK_DSITX_1, "pclk_dsitx_1", "pclk_vo", 21, 7), GATE(PCLK_EDP_CTRL, "pclk_edp_ctrl", "pclk_vo", 21, 8), GATE(CLK_EDP_200M, "clk_edp_200m", "clk_edp_200m_sel", 21, 9), /* CRU_GATE_CON22 */ GATE(ACLK_VPU_PRE, "aclk_vpu_pre", "aclk_vpu_pre_c", 22, 0), GATE(HCLK_VPU_PRE, "hclk_vpu_pre", "aclk_vpu_pre_c", 22, 1), GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", 22, 4), GATE(HCLK_VPU, "hclk_vpu", "hclk_vpu_pre", 22, 5), GATE(PCLK_RGA_PRE, "pclk_rga_pre", "pclk_rga_pre_div", 22, 12), GATE(PCLK_EINK, "pclk_eink", "pclk_rga_pre", 22, 14), GATE(HCLK_EINK, "hclk_eink", "hclk_rga_pre", 22, 15), /* CRU_GATE_CON23 */ GATE(ACLK_RGA_PRE, "aclk_rga_pre", "aclk_rga_pre_sel", 23, 0), GATE(HCLK_RGA_PRE, "hclk_rga_pre", "hclk_rga_pre_div", 23, 1), GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 23, 4), GATE(HCLK_RGA, "hclk_rga", "hclk_rga_pre", 23, 5), GATE(CLK_RGA_CORE, "clk_rga_core", "clk_rga_core_sel", 23, 6), GATE(ACLK_IEP, "aclk_iep", "aclk_rga_pre", 23, 7), GATE(HCLK_IEP, "hclk_iep", "hclk_rga_pre", 23, 8), GATE(CLK_IEP_CORE, "clk_iep_core", "clk_iep_core_sel", 23, 9), GATE(HCLK_EBC, "hclk_ebc", "hclk_rga_pre", 23, 10), GATE(DCLK_EBC, "dclk_ebc", "dclk_ebc_sel", 23, 11), GATE(ACLK_JDEC, "aclk_jdec", "aclk_rga_pre", 23, 12), GATE(HCLK_JDEC, "hclk_jdec", "hclk_rga_pre", 23, 13), GATE(ACLK_JENC, "aclk_jenc", "aclk_rga_pre", 23, 14), GATE(HCLK_JENC, "hclk_jenc", "hclk_rga_pre", 23, 15), /* CRU_GATE_CON24 */ GATE(ACLK_RKVENC_PRE, "aclk_rkvenc_pre", "aclk_rkvenc_pre_c", 24, 0), GATE(HCLK_RKVENC_PRE, "hclk_rkvenc_pre", "hclk_rkvenc_pre_div", 24, 1), GATE(ACLK_RKVENC, "aclk_rkvenc", "aclk_rkvenc_pre", 24, 6), GATE(HCLK_RKVENC, "hclk_rkvenc", "hclk_rkvenc_pre", 24, 7), GATE(CLK_RKVENC_CORE, "clk_rkvenc_core", "clk_rkvenc_core_c", 24, 8), GATE(ACLK_RKVDEC_PRE, "aclk_rkvdec_pre", "aclk_rkvdec_pre_c", 25, 0), /* CRU_GATE_CON25 */ GATE(HCLK_RKVDEC_PRE, "hclk_rkvdec_pre", "hclk_rkvdec_pre_div", 25, 1), GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_pre", 25, 4), GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", 25, 5), GATE(CLK_RKVDEC_CA, "clk_rkvdec_ca", "clk_rkvdec_ca_c", 25, 6), GATE(CLK_RKVDEC_CORE, "clk_rkvdec_core", "clk_rkvdec_core_c", 25, 7), GATE(CLK_RKVDEC_HEVC_CA, "clk_rkvdec_hevc_ca", "clk_rkvdec_hevc_ca_c", 25, 8), /* CRU_GATE_CON26 */ GATE(ACLK_BUS, "aclk_bus", "aclk_bus_sel", 26, 0), GATE(PCLK_BUS, "pclk_bus", "pclk_bus_sel", 26, 1), GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus", 26, 4), GATE(CLK_TSADC_TSEN, "clk_tsadc_tsen", "clk_tsadc_tsen_c", 26, 5), GATE(CLK_TSADC, "clk_tsadc", "clk_tsadc_div", 26, 6), GATE(PCLK_SARADC, "pclk_saradc", "pclk_bus", 26, 7), GATE(CLK_SARADC, "clk_saradc", "xin24m", 26, 8), GATE(PCLK_OTPC_NS, "pclk_otpc_ns", "hclk_secure_flash", 26, 9), GATE(CLK_OTPC_NS_SBPI, "clk_otpc_ns_sbpi", "xin24m", 26, 10), GATE(CLK_OTPC_NS_USR, "clk_otpc_ns_usr", "xin_osc0_half", 26, 11), GATE(PCLK_SCR, "pclk_scr", "pclk_bus", 26, 12), GATE(PCLK_WDT_NS, "pclk_wdt_ns", "pclk_bus", 26, 13), GATE(TCLK_WDT_NS, "tclk_wdt_ns", "xin24m", 26, 14), /* CRU_GATE_CON27 */ GATE(PCLK_CAN0, "pclk_can0", "pclk_bus", 27, 5), GATE(CLK_CAN0, "clk_can0", "clk_can0_c", 27, 6), GATE(PCLK_CAN1, "pclk_can1", "pclk_bus", 27, 7), GATE(CLK_CAN1, "clk_can1", "clk_can1_c", 27, 8), GATE(PCLK_CAN2, "pclk_can2", "pclk_bus", 27, 9), GATE(CLK_CAN2, "clk_can2", "clk_can2_c", 27, 10), GATE(PCLK_UART1, "pclk_uart1", "pclk_bus", 27, 12), GATE(CLK_UART1_SRC, "clk_uart1_src", "clk_uart1_src_c", 27, 13), GATE(CLK_UART1_FRAC, "clk_uart1_frac", "clk_uart1_frac_frac", 27, 14), GATE(SCLK_UART1, "sclk_uart1", "sclk_uart1_sel", 27, 15), /* CRU_GATE_CON28 */ GATE(PCLK_UART2, "pclk_uart2", "pclk_bus", 28, 0), GATE(CLK_UART2_SRC, "clk_uart2_src", "clk_uart2_src_c", 28, 1), GATE(CLK_UART2_FRAC, "clk_uart2_frac", "clk_uart2_frac_frac", 28, 2), GATE(SCLK_UART2, "sclk_uart2", "sclk_uart2_sel", 28, 3), GATE(PCLK_UART3, "pclk_uart3", "pclk_bus", 28, 4), GATE(CLK_UART3_SRC, "clk_uart3_src", "clk_uart3_src_c", 28, 5), GATE(CLK_UART3_FRAC, "clk_uart3_frac", "clk_uart3_frac_frac", 28, 6), GATE(SCLK_UART3, "sclk_uart3", "sclk_uart3_sel", 28, 7), GATE(PCLK_UART4, "pclk_uart4", "pclk_bus", 28, 8), GATE(CLK_UART4_SRC, "clk_uart4_src", "clk_uart4_src_c", 28, 9), GATE(CLK_UART4_FRAC, "clk_uart4_frac", "clk_uart4_frac_frac", 28, 10), GATE(SCLK_UART4, "sclk_uart4", "sclk_uart4_sel", 28, 11), GATE(PCLK_UART5, "pclk_uart5", "pclk_bus", 28, 12), GATE(CLK_UART5_SRC, "clk_uart5_src", "clk_uart5_src_c", 28, 13), GATE(CLK_UART5_FRAC, "clk_uart5_frac", "clk_uart5_frac_frac", 28, 14), GATE(SCLK_UART5, "sclk_uart5", "sclk_uart5_sel", 28, 15), /* CRU_GATE_CON29 */ GATE(PCLK_UART6, "pclk_uart6", "pclk_bus", 29, 0), GATE(CLK_UART6_SRC, "clk_uart6_src", "clk_uart6_src_c", 29, 1), GATE(CLK_UART6_FRAC, "clk_uart6_frac", "clk_uart6_frac_frac", 29, 2), GATE(SCLK_UART6, "sclk_uart6", "sclk_uart6_sel", 29, 3), GATE(PCLK_UART7, "pclk_uart7", "pclk_bus", 29, 4), GATE(CLK_UART7_SRC, "clk_uart7_src", "clk_uart7_src_c", 29, 5), GATE(CLK_UART7_FRAC, "clk_uart7_frac", "clk_uart7_frac_frac", 29, 6), GATE(SCLK_UART7, "sclk_uart7", "sclk_uart7_sel", 29, 7), GATE(PCLK_UART8, "pclk_uart8", "pclk_bus", 29, 8), GATE(CLK_UART8_SRC, "clk_uart8_src", "clk_uart8_src_c", 29, 9), GATE(CLK_UART8_FRAC, "clk_uart8_frac", "clk_uart8_frac_frac", 29, 10), GATE(SCLK_UART8, "sclk_uart8", "sclk_uart8_sel", 29, 11), GATE(PCLK_UART9, "pclk_uart9", "pclk_bus", 29, 12), GATE(CLK_UART9_SRC, "clk_uart9_src", "clk_uart9_src_c", 29, 13), GATE(CLK_UART9_FRAC, "clk_uart9_frac", "clk_uart9_frac_frac", 29, 14), GATE(SCLK_UART9, "sclk_uart9", "sclk_uart9_sel", 29, 15), /* CRU_GATE_CON30 */ GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus", 30, 0), GATE(CLK_I2C1, "clk_i2c1", "clk_i2c", 30, 1), GATE(PCLK_I2C2, "pclk_i2c2", "pclk_bus", 30, 2), GATE(CLK_I2C2, "clk_i2c2", "clk_i2c", 30, 3), GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus", 30, 4), GATE(CLK_I2C3, "clk_i2c3", "clk_i2c", 30, 5), GATE(PCLK_I2C4, "pclk_i2c4", "pclk_bus", 30, 6), GATE(CLK_I2C4, "clk_i2c4", "clk_i2c", 30, 7), GATE(PCLK_I2C5, "pclk_i2c5", "pclk_bus", 30, 8), GATE(CLK_I2C5, "clk_i2c5", "clk_i2c", 30, 9), GATE(PCLK_SPI0, "pclk_spi0", "pclk_bus", 30, 10), GATE(CLK_SPI0, "clk_spi0", "clk_spi0_sel", 30, 11), GATE(PCLK_SPI1, "pclk_spi1", "pclk_bus", 30, 12), GATE(CLK_SPI1, "clk_spi1", "clk_spi1_sel", 30, 13), GATE(PCLK_SPI2, "pclk_spi2", "pclk_bus", 30, 14), GATE(CLK_SPI2, "clk_spi2", "clk_spi2_sel", 30, 15), /* CRU_GATE_CON31 */ GATE(PCLK_SPI3, "pclk_spi3", "pclk_bus", 31, 0), GATE(CLK_SPI3, "clk_spi3", "clk_spi3_sel", 31, 1), GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_bus", 31, 2), GATE(DBCLK_GPIO1, "dbclk_gpio1", "dbclk_gpio", 31, 3), GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_bus", 31, 4), GATE(DBCLK_GPIO2, "dbclk_gpio2", "dbclk_gpio", 31, 5), GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_bus", 31, 6), GATE(DBCLK_GPIO3, "dbclk_gpio3", "dbclk_gpio", 31, 7), GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_bus", 31, 8), GATE(DBCLK_GPIO4, "dbclk_gpio4", "dbclk_gpio", 31, 9), GATE(PCLK_PWM1, "pclk_pwm1", "pclk_bus", 31, 10), GATE(CLK_PWM1, "clk_pwm1", "clk_pwm1_sel", 31, 11), GATE(CLK_PWM1_CAPTURE, "clk_pwm1_capture", "xin24m", 31, 12), GATE(PCLK_PWM2, "pclk_pwm2", "pclk_bus", 31, 13), GATE(CLK_PWM2, "clk_pwm2", "clk_pwm2_sel", 31, 14), GATE(CLK_PWM2_CAPTURE, "clk_pwm2_capture", "xin24m", 31, 15), /* CRU_GATE_CON32 */ GATE(PCLK_PWM3, "pclk_pwm3", "pclk_bus", 32, 0), GATE(CLK_PWM3, "clk_pwm3", "clk_pwm3_sel", 32, 1), GATE(CLK_PWM3_CAPTURE, "clk_pwm3_capture", "xin24m", 32, 2), GATE(PCLK_TIMER, "pclk_timer", "pclk_bus", 32, 3), GATE(CLK_TIMER0, "clk_timer0", "xin24m", 32, 4), GATE(CLK_TIMER1, "clk_timer1", "xin24m", 32, 5), GATE(CLK_TIMER2, "clk_timer2", "xin24m", 32, 6), GATE(CLK_TIMER3, "clk_timer3", "xin24m", 32, 7), GATE(CLK_TIMER4, "clk_timer4", "xin24m", 32, 8), GATE(CLK_TIMER5, "clk_timer5", "xin24m", 32, 9), GATE(CLK_I2C, "clk_i2c", "clk_i2c_sel", 32, 10), GATE(DBCLK_GPIO, "dbclk_gpio", "dbclk_gpio_sel", 32, 11), GATE(ACLK_MCU, "aclk_mcu", "aclk_bus", 32, 13), GATE(PCLK_INTMUX, "pclk_intmux", "pclk_bus", 32, 14), GATE(PCLK_MAILBOX, "pclk_mailbox", "pclk_bus", 32, 15), /* CRU_GATE_CON33 */ GATE(ACLK_TOP_HIGH, "aclk_top_high", "aclk_top_high_sel", 33, 0), GATE(ACLK_TOP_LOW, "aclk_top_low", "aclk_top_low_sel", 33, 1), GATE(HCLK_TOP, "hclk_top", "hclk_top_sel", 33, 2), GATE(PCLK_TOP, "pclk_top", "pclk_top_sel", 33, 3), GATE(PCLK_PCIE30PHY, "pclk_pcie30phy", "pclk_top", 33, 8), GATE(CLK_OPTC_ARB, "clk_optc_arb", "clk_optc_arb_sel", 33, 9), GATE(PCLK_MIPICSIPHY, "pclk_mipicsiphy", "pclk_top", 33, 13), GATE(PCLK_MIPIDSIPHY0, "pclk_mipidsiphy0", "pclk_top", 33, 14), GATE(PCLK_MIPIDSIPHY1, "pclk_mipidsiphy1", "pclk_top", 33, 15), /* CRU_GATE_CON34 */ GATE(PCLK_PIPEPHY0, "pclk_pipephy0", "pclk_top", 34, 4), GATE(PCLK_PIPEPHY1, "pclk_pipephy1", "pclk_top", 34, 5), GATE(PCLK_PIPEPHY2, "pclk_pipephy2", "pclk_top", 34, 6), GATE(PCLK_CPU_BOOST, "pclk_cpu_boost", "pclk_top", 34, 11), GATE(CLK_CPU_BOOST, "clk_cpu_boost", "xin24m", 34, 12), GATE(PCLK_OTPPHY, "pclk_otpphy", "pclk_top", 34, 13), GATE(PCLK_EDPPHY_GRF, "pclk_edpphy_grf", "pclk_top", 34, 14), /* CRU_GATE_CON35 */ GATE(CPLL_500M, "clk_cpll_div_500m", "clk_cpll_div_500m_div", 35, 7), GATE(CPLL_333M, "clk_cpll_div_333m", "clk_cpll_div_333m_div", 35, 8), GATE(CPLL_250M, "clk_cpll_div_250m", "clk_cpll_div_250m_div", 35, 9), GATE(CPLL_125M, "clk_cpll_div_125m", "clk_cpll_div_125m_div", 35, 10), GATE(CPLL_100M, "clk_cpll_div_100m", "clk_cpll_div_100m_div", 35, 11), GATE(CPLL_62P5M, "clk_cpll_div_62P5m", "clk_cpll_div_62P5m_div", 35, 12), GATE(CPLL_50M, "clk_cpll_div_50m", "clk_cpll_div_50m_div", 35, 13), GATE(CPLL_25M, "clk_cpll_div_25m", "clk_cpll_div_25m_div", 35, 14), }; static struct rk_clk_gate pmu_clk_gates[] = { /* PMUCRU_PMUGATE_CON00 */ GATE(XIN_OSC0_DIV, "xin_osc0_div", "xin_osc0_div_div", 0, 0), GATE(CLK_RTC_32K, "clk_rtc_32k", "clk_rtc_32k_mux", 0, 1), GATE(PCLK_PDPMU, "pclk_pdpmu", "pclk_pdpmu_pre", 0, 2), GATE(PCLK_PMU, "pclk_pmu", "pclk_pdpmu", 0, 6), GATE(CLK_PMU, "clk_pmu", "xin24m", 0, 7), /* PMUCRU_PMUGATE_CON01 */ GATE(PCLK_I2C0, "pclk_i2c0", "pclk_pdpmu", 1, 0), GATE(CLK_I2C0, "clk_i2c0", "clk_i2c0_div", 1, 1), GATE(PCLK_UART0, "pclk_uart0", "pclk_pdpmu", 1, 2), GATE(CLK_UART0_DIV, "sclk_uart0_div", "sclk_uart0_div_div", 1, 3), GATE(CLK_UART0_FRAC, "sclk_uart0_frac", "sclk_uart0_frac_div", 1, 4), GATE(SCLK_UART0, "sclk_uart0", "sclk_uart0_mux", 1, 5), GATE(PCLK_PWM0, "pclk_pwm0", "pclk_pdpmu", 1, 6), GATE(CLK_PWM0, "clk_pwm0", "clk_pwm0_div", 1, 7), GATE(CLK_CAPTURE_PWM0_NDFT, "clk_capture_pwm0_ndft", "xin24m", 1, 8), GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pdpmu", 1, 9), GATE(DBCLK_GPIO0, "dbclk_gpio0", "dbclk_gpio0_sel", 1, 10), GATE(PCLK_PMUPVTM, "pclk_pmupvtm", "pclk_pdpmu", 1, 11), GATE(CLK_PMUPVTM, "clk_pmupvtm", "xin24m", 1, 12), GATE(CLK_CORE_PMUPVTM, "clk_core_pmupvtm", "xin24m", 1, 13), /* PMUCRU_PMUGATE_CON02 */ GATE(CLK_REF24M, "clk_ref24m", "clk_ref24m_div", 2, 0), GATE(XIN_OSC0_USBPHY0_G, "xin_osc0_usbphy0_g", "xin24m", 2, 1), GATE(XIN_OSC0_USBPHY1_G, "xin_osc0_usbphy1_g", "xin24m", 2, 2), GATE(XIN_OSC0_MIPIDSIPHY0_G, "xin_osc0_mipidsiphy0_g", "xin24m", 2, 3), GATE(XIN_OSC0_MIPIDSIPHY1_G, "xin_osc0_mipidsiphy1_g", "xin24m", 2, 4), GATE(CLK_WIFI_DIV, "clk_wifi_div", "clk_wifi_div_div", 2, 5), GATE(CLK_WIFI_OSC0, "clk_wifi_osc0", "xin24m", 2, 6), GATE(CLK_PCIEPHY0_DIV, "clk_pciephy0_div", "clk_pciephy0_div_div", 2, 7), GATE(CLK_PCIEPHY0_OSC0, "clk_pciephy0_osc0", "xin24m", 2, 8), GATE(CLK_PCIEPHY1_DIV, "clk_pciephy1_div", "clk_pciephy1_div_div", 2, 9), GATE(CLK_PCIEPHY1_OSC0, "clk_pciephy1_osc0", "xin24m", 2, 10), GATE(CLK_PCIEPHY2_DIV, "clk_pciephy2_div", "clk_pciephy2_div_div", 2, 11), GATE(CLK_PCIEPHY2_OSC0, "clk_pciephy2_osc0", "xin24m", 2, 12), GATE(CLK_PCIE30PHY_REF_M, "clk_pcie30phy_ref_m", "ppll_ph0", 2, 13), GATE(CLK_PCIE30PHY_REF_N, "clk_pcie30phy_ref_n", "ppll_ph180", 2, 14), GATE(XIN_OSC0_EDPPHY_G, "xin_osc0_edpphy_g", "xin24m", 2, 15), }; #define PLL_MODE_MASK 0x1 #include "clk-pll-rk3568.c" #include "clk-mmc-phase.c" #include "softrst.c" static struct rk_pmuclk_priv *find_pmu(void) { struct rk_pmuclk_priv *pmu_priv = RT_NULL; const char *compatible = "rockchip,rk3568-pmucru"; struct rt_ofw_node *np = rt_ofw_find_node_by_compatible(RT_NULL, compatible); if (np) { struct rk_clk *rk_clk = rt_ofw_data(np); pmu_priv = &rk_clk->pmuclk_info; rt_ofw_node_put(np); } else { LOG_E("Find pmucru %s fail", compatible); } return pmu_priv; } static rt_ubase_t pmu_pll_set_rate(rt_ubase_t pll_id, rt_ubase_t rate) { struct rk_pmuclk_priv *pmu_priv = find_pmu(); if (pmu_priv) { rk_pll_set_rate(&pmu_pll_clks[pll_id], pmu_priv->pmucru, rate); } return 0; } static rt_ubase_t pmu_pll_get_rate(rt_ubase_t pll_id) { struct rk_pmuclk_priv *pmu_priv = find_pmu(); if (pmu_priv) { return rk_pll_get_rate(&pmu_pll_clks[pll_id], &pmu_priv->pmucru); } return 0; } static rt_ubase_t rtc32k_get_pmuclk(struct rk_pmuclk_priv *priv) { struct rk_pmucru *pmucru = priv->pmucru; rt_ubase_t m, n; rt_uint32_t fracdiv; fracdiv = HWREG32(&pmucru->pmu_clksel_con[1]); m = fracdiv & RTC32K_FRAC_NUMERATOR_MASK; m >>= RTC32K_FRAC_NUMERATOR_SHIFT; n = fracdiv & RTC32K_FRAC_DENOMINATOR_MASK; n >>= RTC32K_FRAC_DENOMINATOR_SHIFT; return OSC_HZ * m / n; } static rt_ubase_t rtc32k_set_pmuclk(struct rk_pmuclk_priv *priv, rt_ubase_t rate) { struct rk_pmucru *pmucru = priv->pmucru; rt_ubase_t m, n, val; rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK, RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT); rational_best_approximation(rate, OSC_HZ, RT_GENMASK(16 - 1, 0), RT_GENMASK(16 - 1, 0), &m, &n); val = m << RTC32K_FRAC_NUMERATOR_SHIFT | n; HWREG32(&pmucru->pmu_clksel_con[1]) = val; return rtc32k_get_pmuclk(priv); } static rt_ubase_t uart_get_pmuclk(struct rk_pmuclk_priv *priv, rt_ubase_t clk_id) { struct rk_pmucru *pmucru = priv->pmucru; rt_uint32_t reg, con, fracdiv, div, src, p_src, p_rate; rt_ubase_t m, n; switch (clk_id) { case SCLK_UART0: reg = 4; break; default: return -RT_ERROR; } con = HWREG32(&pmucru->pmu_clksel_con[reg]); src = (con & CLK_UART0_SEL_MASK) >> CLK_UART0_SEL_SHIFT; div = (con & CLK_UART0_DIV_DIV_MASK) >> CLK_UART0_DIV_DIV_SHIFT; p_src = (con & CLK_UART0_DIV_SEL_MASK) >> CLK_UART0_DIV_SEL_SHIFT; if (p_src == CLK_UART0_SRC_SEL_PPLL) { p_rate = priv->ppll_hz; } else if (p_src == CLK_UART0_SRC_SEL_GPLL) { p_rate = priv->hpll_hz; } else { p_rate = 480000000; } if (src == CLK_UART0_SEL_DIV) { return DIV_TO_RATE(p_rate, div); } else if (src == CLK_UART0_SEL_FRACDIV) { fracdiv = HWREG32(&pmucru->pmu_clksel_con[reg + 1]); n = fracdiv & CLK_UART0_FRAC_NUMERATOR_MASK; n >>= CLK_UART0_FRAC_NUMERATOR_SHIFT; m = fracdiv & CLK_UART0_FRAC_DENOMINATOR_MASK; m >>= CLK_UART0_FRAC_DENOMINATOR_SHIFT; return DIV_TO_RATE(p_rate, div) * n / m; } else { return OSC_HZ; } } static rt_ubase_t uart_set_pmuclk(struct rk_pmuclk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_pmucru *pmucru = priv->pmucru; rt_uint32_t reg, clk_src, uart_src, div; rt_ubase_t m = 0, n = 0, val; if (priv->ppll_hz % rate == 0) { clk_src = CLK_UART0_SRC_SEL_PPLL; uart_src = CLK_UART0_SEL_DIV; div = RT_DIV_ROUND_UP(priv->ppll_hz, rate); } else if (priv->hpll_hz % rate == 0) { clk_src = CLK_UART0_SRC_SEL_GPLL; uart_src = CLK_UART0_SEL_DIV; div = RT_DIV_ROUND_UP(priv->hpll_hz, rate); } else if (rate == OSC_HZ) { clk_src = CLK_UART0_SRC_SEL_GPLL; uart_src = CLK_UART0_SEL_XIN24M; div = 2; } switch (clk_id) { case SCLK_UART0: reg = 4; break; default: return -RT_ERROR; } rk_clrsetreg(&pmucru->pmu_clksel_con[reg], CLK_UART0_SEL_MASK | CLK_UART0_DIV_SEL_MASK | CLK_UART0_DIV_DIV_MASK, (clk_src << CLK_UART0_DIV_SEL_SHIFT) | (uart_src << CLK_UART0_SEL_SHIFT) | ((div - 1) << CLK_UART0_DIV_DIV_SHIFT)); if (m && n) { val = m << CLK_UART0_FRAC_NUMERATOR_SHIFT | n; HWREG32(&pmucru->pmu_clksel_con[reg + 1]) = val; } return uart_get_pmuclk(priv, clk_id); } static rt_ubase_t i2c_get_pmuclk(struct rk_pmuclk_priv *priv, rt_ubase_t clk_id) { struct rk_pmucru *pmucru = priv->pmucru; rt_uint32_t div, con; switch (clk_id) { case CLK_I2C0: con = HWREG32(&pmucru->pmu_clksel_con[3]); div = (con & CLK_I2C0_DIV_MASK) >> CLK_I2C0_DIV_SHIFT; break; default: return -RT_ERROR; } return DIV_TO_RATE(priv->ppll_hz, div); } static rt_ubase_t i2c_set_pmuclk(struct rk_pmuclk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_pmucru *pmucru = priv->pmucru; int src_clk_div; src_clk_div = RT_DIV_ROUND_UP(priv->ppll_hz, rate); RT_ASSERT(src_clk_div - 1 <= 127); switch (clk_id) { case CLK_I2C0: rk_clrsetreg(&pmucru->pmu_clksel_con[3], CLK_I2C0_DIV_MASK, (src_clk_div - 1) << CLK_I2C0_DIV_SHIFT); break; default: return -RT_ERROR; } return i2c_get_pmuclk(priv, clk_id); } static rt_ubase_t pwm_get_pmuclk(struct rk_pmuclk_priv *priv, rt_ubase_t clk_id) { struct rk_pmucru *pmucru = priv->pmucru; rt_uint32_t div, sel, con, parent; switch (clk_id) { case CLK_PWM0: con = HWREG32(&pmucru->pmu_clksel_con[6]); sel = (con & CLK_PWM0_SEL_MASK) >> CLK_PWM0_SEL_SHIFT; div = (con & CLK_PWM0_DIV_MASK) >> CLK_PWM0_DIV_SHIFT; if (sel == CLK_PWM0_SEL_XIN24M) { parent = OSC_HZ; } else { parent = priv->ppll_hz; } break; default: return -RT_ERROR; } return DIV_TO_RATE(parent, div); } static rt_ubase_t pwm_set_pmuclk(struct rk_pmuclk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_pmucru *pmucru = priv->pmucru; int src_clk_div; switch (clk_id) { case CLK_PWM0: if (rate == OSC_HZ) { rk_clrsetreg(&pmucru->pmu_clksel_con[6], CLK_PWM0_SEL_MASK | CLK_PWM0_DIV_MASK, (CLK_PWM0_SEL_XIN24M << CLK_PWM0_SEL_SHIFT) | 0 << CLK_PWM0_SEL_SHIFT); } else { src_clk_div = RT_DIV_ROUND_UP(priv->ppll_hz, rate); RT_ASSERT(src_clk_div - 1 <= 127); rk_clrsetreg(&pmucru->pmu_clksel_con[6], CLK_PWM0_DIV_MASK | CLK_PWM0_DIV_MASK, (CLK_PWM0_SEL_PPLL << CLK_PWM0_SEL_SHIFT) | (src_clk_div - 1) << CLK_PWM0_DIV_SHIFT); } break; default: return -RT_ERROR; } return pwm_get_pmuclk(priv, clk_id); } static int armclk_set_clk(struct rk_clk_priv *priv, rt_ubase_t hz) { struct rk_cru *cru = priv->cru; const struct rk_cpu_rate_table *rate; rt_ubase_t old_rate; rate = rk_get_cpu_settings(cpu_rates, hz); if (!rate) { LOG_E("Unsupport rate %u", hz); return -RT_ENOSYS; } LOG_I("set cpu_freq to %lu", hz); rk_clrsetreg(&cru->clksel_con[0], CLK_CORE_PRE_SEL_MASK, (CLK_CORE_PRE_SEL_SRC << CLK_CORE_PRE_SEL_SHIFT)); rk_clrsetreg(&cru->clksel_con[2], SCLK_CORE_PRE_SEL_MASK | SCLK_CORE_SRC_SEL_MASK | SCLK_CORE_SRC_DIV_MASK, (SCLK_CORE_PRE_SEL_SRC << SCLK_CORE_PRE_SEL_SHIFT) | (SCLK_CORE_SRC_SEL_APLL <cru); if (old_rate > hz) { if (rk_pll_set_rate(&pll_clks[apll], priv->cru, hz)) { LOG_E("cpu_rate adjust error"); return -RT_ENOSYS; } rk_clrsetreg(&cru->clksel_con[3], GICCLK_CORE_DIV_MASK | ATCLK_CORE_DIV_MASK, rate->pclk_div << GICCLK_CORE_DIV_SHIFT | rate->pclk_div << ATCLK_CORE_DIV_SHIFT); rk_clrsetreg(&cru->clksel_con[4], PERIPHCLK_CORE_PRE_DIV_MASK | PCLK_CORE_PRE_DIV_MASK, rate->pclk_div << PCLK_CORE_PRE_DIV_SHIFT | rate->pclk_div << PERIPHCLK_CORE_PRE_DIV_SHIFT); rk_clrsetreg(&cru->clksel_con[5], ACLK_CORE_NDFT_DIV_MASK, rate->aclk_div << ACLK_CORE_NDFT_DIV_SHIFT); } else if (old_rate < hz) { rk_clrsetreg(&cru->clksel_con[3], GICCLK_CORE_DIV_MASK | ATCLK_CORE_DIV_MASK, rate->pclk_div << GICCLK_CORE_DIV_SHIFT | rate->pclk_div << ATCLK_CORE_DIV_SHIFT); rk_clrsetreg(&cru->clksel_con[4], PERIPHCLK_CORE_PRE_DIV_MASK | PCLK_CORE_PRE_DIV_MASK, rate->pclk_div << PCLK_CORE_PRE_DIV_SHIFT | rate->pclk_div << PERIPHCLK_CORE_PRE_DIV_SHIFT); rk_clrsetreg(&cru->clksel_con[5], ACLK_CORE_NDFT_DIV_MASK, rate->aclk_div << ACLK_CORE_NDFT_DIV_SHIFT); if (rk_pll_set_rate(&pll_clks[apll], priv->cru, hz)) { LOG_E("cpu_rate adjust error"); return -RT_ENOSYS; } } return 0; } static rt_ubase_t cpll_div_get_rate(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; int div, mask, shift, con; switch (clk_id) { case CPLL_500M: con = 78; mask = CPLL_500M_DIV_MASK; shift = CPLL_500M_DIV_SHIFT; break; case CPLL_333M: con = 79; mask = CPLL_333M_DIV_MASK; shift = CPLL_333M_DIV_SHIFT; break; case CPLL_250M: con = 79; mask = CPLL_250M_DIV_MASK; shift = CPLL_250M_DIV_SHIFT; break; case CPLL_125M: con = 80; mask = CPLL_125M_DIV_MASK; shift = CPLL_125M_DIV_SHIFT; break; case CPLL_100M: con = 82; mask = CPLL_100M_DIV_MASK; shift = CPLL_100M_DIV_SHIFT; break; case CPLL_62P5M: con = 80; mask = CPLL_62P5M_DIV_MASK; shift = CPLL_62P5M_DIV_SHIFT; break; case CPLL_50M: con = 81; mask = CPLL_50M_DIV_MASK; shift = CPLL_50M_DIV_SHIFT; break; case CPLL_25M: con = 81; mask = CPLL_25M_DIV_MASK; shift = CPLL_25M_DIV_SHIFT; break; default: return -RT_ERROR; } div = (HWREG32(&cru->clksel_con[con]) & mask) >> shift; return DIV_TO_RATE(priv->cpll_hz, div); } static rt_ubase_t cpll_div_set_rate(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int div, mask, shift, con; switch (clk_id) { case CPLL_500M: con = 78; mask = CPLL_500M_DIV_MASK; shift = CPLL_500M_DIV_SHIFT; break; case CPLL_333M: con = 79; mask = CPLL_333M_DIV_MASK; shift = CPLL_333M_DIV_SHIFT; break; case CPLL_250M: con = 79; mask = CPLL_250M_DIV_MASK; shift = CPLL_250M_DIV_SHIFT; break; case CPLL_125M: con = 80; mask = CPLL_125M_DIV_MASK; shift = CPLL_125M_DIV_SHIFT; break; case CPLL_100M: con = 82; mask = CPLL_100M_DIV_MASK; shift = CPLL_100M_DIV_SHIFT; break; case CPLL_62P5M: con = 80; mask = CPLL_62P5M_DIV_MASK; shift = CPLL_62P5M_DIV_SHIFT; break; case CPLL_50M: con = 81; mask = CPLL_50M_DIV_MASK; shift = CPLL_50M_DIV_SHIFT; break; case CPLL_25M: con = 81; mask = CPLL_25M_DIV_MASK; shift = CPLL_25M_DIV_SHIFT; break; default: return -RT_ERROR; } div = RT_DIV_ROUND_UP(priv->cpll_hz, rate); RT_ASSERT(div - 1 <= 31); rk_clrsetreg(&cru->clksel_con[con], mask, (div - 1) << shift); return cpll_div_get_rate(priv, clk_id); } static rt_ubase_t bus_get_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t con, sel, rate; switch (clk_id) { case ACLK_BUS: con = HWREG32(&cru->clksel_con[50]); sel = (con & ACLK_BUS_SEL_MASK) >> ACLK_BUS_SEL_SHIFT; if (sel == ACLK_BUS_SEL_200M) { rate = 200 * MHZ; } else if (sel == ACLK_BUS_SEL_150M) { rate = 150 * MHZ; } else if (sel == ACLK_BUS_SEL_100M) { rate = 100 * MHZ; } else { rate = OSC_HZ; } break; case PCLK_BUS: case PCLK_WDT_NS: con = HWREG32(&cru->clksel_con[50]); sel = (con & PCLK_BUS_SEL_MASK) >> PCLK_BUS_SEL_SHIFT; if (sel == PCLK_BUS_SEL_100M) { rate = 100 * MHZ; } else if (sel == PCLK_BUS_SEL_75M) { rate = 75 * MHZ; } else if (sel == PCLK_BUS_SEL_50M) { rate = 50 * MHZ; } else { rate = OSC_HZ; } break; default: return -RT_ERROR; } return rate; } static rt_ubase_t bus_set_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; switch (clk_id) { case ACLK_BUS: if (rate == 200 * MHZ) { src_clk = ACLK_BUS_SEL_200M; } else if (rate == 150 * MHZ) { src_clk = ACLK_BUS_SEL_150M; } else if (rate == 100 * MHZ) { src_clk = ACLK_BUS_SEL_100M; } else { src_clk = ACLK_BUS_SEL_24M; } rk_clrsetreg(&cru->clksel_con[50], ACLK_BUS_SEL_MASK, src_clk << ACLK_BUS_SEL_SHIFT); break; case PCLK_BUS: case PCLK_WDT_NS: if (rate == 100 * MHZ) { src_clk = PCLK_BUS_SEL_100M; } else if (rate == 75 * MHZ) { src_clk = PCLK_BUS_SEL_75M; } else if (rate == 50 * MHZ) { src_clk = PCLK_BUS_SEL_50M; } else { src_clk = PCLK_BUS_SEL_24M; } rk_clrsetreg(&cru->clksel_con[50], PCLK_BUS_SEL_MASK, src_clk << PCLK_BUS_SEL_SHIFT); break; default: return -RT_ENOSYS; } return bus_get_clk(priv, clk_id); } static rt_ubase_t perimid_get_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t con, sel, rate; switch (clk_id) { case ACLK_PERIMID: con = HWREG32(&cru->clksel_con[10]); sel = (con & ACLK_PERIMID_SEL_MASK) >> ACLK_PERIMID_SEL_SHIFT; if (sel == ACLK_PERIMID_SEL_300M) { rate = 300 * MHZ; } else if (sel == ACLK_PERIMID_SEL_200M) { rate = 200 * MHZ; } else if (sel == ACLK_PERIMID_SEL_100M) { rate = 100 * MHZ; } else { rate = OSC_HZ; } break; case HCLK_PERIMID: con = HWREG32(&cru->clksel_con[10]); sel = (con & HCLK_PERIMID_SEL_MASK) >> HCLK_PERIMID_SEL_SHIFT; if (sel == HCLK_PERIMID_SEL_150M) { rate = 150 * MHZ; } else if (sel == HCLK_PERIMID_SEL_100M) { rate = 100 * MHZ; } else if (sel == HCLK_PERIMID_SEL_75M) { rate = 75 * MHZ; } else { rate = OSC_HZ; } break; default: return -RT_ERROR; } return rate; } static rt_ubase_t perimid_set_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; switch (clk_id) { case ACLK_PERIMID: if (rate == 300 * MHZ) { src_clk = ACLK_PERIMID_SEL_300M; } else if (rate == 200 * MHZ) { src_clk = ACLK_PERIMID_SEL_200M; } else if (rate == 100 * MHZ) { src_clk = ACLK_PERIMID_SEL_100M; } else { src_clk = ACLK_PERIMID_SEL_24M; } rk_clrsetreg(&cru->clksel_con[10], ACLK_PERIMID_SEL_MASK, src_clk << ACLK_PERIMID_SEL_SHIFT); break; case HCLK_PERIMID: if (rate == 150 * MHZ) { src_clk = HCLK_PERIMID_SEL_150M; } else if (rate == 100 * MHZ) { src_clk = HCLK_PERIMID_SEL_100M; } else if (rate == 75 * MHZ) { src_clk = HCLK_PERIMID_SEL_75M; } else { src_clk = HCLK_PERIMID_SEL_24M; } rk_clrsetreg(&cru->clksel_con[10], HCLK_PERIMID_SEL_MASK, src_clk << HCLK_PERIMID_SEL_SHIFT); break; default: return -RT_ENOSYS; } return perimid_get_clk(priv, clk_id); } static rt_ubase_t top_get_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t con, sel, rate; switch (clk_id) { case ACLK_TOP_HIGH: con = HWREG32(&cru->clksel_con[73]); sel = (con & ACLK_TOP_HIGH_SEL_MASK) >> ACLK_TOP_HIGH_SEL_SHIFT; if (sel == ACLK_TOP_HIGH_SEL_500M) { rate = 500 * MHZ; } else if (sel == ACLK_TOP_HIGH_SEL_400M) { rate = 400 * MHZ; } else if (sel == ACLK_TOP_HIGH_SEL_300M) { rate = 300 * MHZ; } else { rate = OSC_HZ; } break; case ACLK_TOP_LOW: con = HWREG32(&cru->clksel_con[73]); sel = (con & ACLK_TOP_LOW_SEL_MASK) >> ACLK_TOP_LOW_SEL_SHIFT; if (sel == ACLK_TOP_LOW_SEL_400M) { rate = 400 * MHZ; } else if (sel == ACLK_TOP_LOW_SEL_300M) { rate = 300 * MHZ; } else if (sel == ACLK_TOP_LOW_SEL_200M) { rate = 200 * MHZ; } else { rate = OSC_HZ; } break; case HCLK_TOP: con = HWREG32(&cru->clksel_con[73]); sel = (con & HCLK_TOP_SEL_MASK) >> HCLK_TOP_SEL_SHIFT; if (sel == HCLK_TOP_SEL_150M) { rate = 150 * MHZ; } else if (sel == HCLK_TOP_SEL_100M) { rate = 100 * MHZ; } else if (sel == HCLK_TOP_SEL_75M) { rate = 75 * MHZ; } else { rate = OSC_HZ; } break; case PCLK_TOP: con = HWREG32(&cru->clksel_con[73]); sel = (con & PCLK_TOP_SEL_MASK) >> PCLK_TOP_SEL_SHIFT; if (sel == PCLK_TOP_SEL_100M) { rate = 100 * MHZ; } else if (sel == PCLK_TOP_SEL_75M) { rate = 75 * MHZ; } else if (sel == PCLK_TOP_SEL_50M) { rate = 50 * MHZ; } else { rate = OSC_HZ; } break; default: return -RT_ERROR; } return rate; } static rt_ubase_t top_set_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; switch (clk_id) { case ACLK_TOP_HIGH: if (rate == 500 * MHZ) { src_clk = ACLK_TOP_HIGH_SEL_500M; } else if (rate == 400 * MHZ) { src_clk = ACLK_TOP_HIGH_SEL_400M; } else if (rate == 300 * MHZ) { src_clk = ACLK_TOP_HIGH_SEL_300M; } else { src_clk = ACLK_TOP_HIGH_SEL_24M; } rk_clrsetreg(&cru->clksel_con[73], ACLK_TOP_HIGH_SEL_MASK, src_clk << ACLK_TOP_HIGH_SEL_SHIFT); break; case ACLK_TOP_LOW: if (rate == 400 * MHZ) { src_clk = ACLK_TOP_LOW_SEL_400M; } else if (rate == 300 * MHZ) { src_clk = ACLK_TOP_LOW_SEL_300M; } else if (rate == 200 * MHZ) { src_clk = ACLK_TOP_LOW_SEL_200M; } else { src_clk = ACLK_TOP_LOW_SEL_24M; } rk_clrsetreg(&cru->clksel_con[73], ACLK_TOP_LOW_SEL_MASK, src_clk << ACLK_TOP_LOW_SEL_SHIFT); break; case HCLK_TOP: if (rate == 150 * MHZ) { src_clk = HCLK_TOP_SEL_150M; } else if (rate == 100 * MHZ) { src_clk = HCLK_TOP_SEL_100M; } else if (rate == 75 * MHZ) { src_clk = HCLK_TOP_SEL_75M; } else { src_clk = HCLK_TOP_SEL_24M; } rk_clrsetreg(&cru->clksel_con[73], HCLK_TOP_SEL_MASK, src_clk << HCLK_TOP_SEL_SHIFT); break; case PCLK_TOP: if (rate == 100 * MHZ) { src_clk = PCLK_TOP_SEL_100M; } else if (rate == 75 * MHZ) { src_clk = PCLK_TOP_SEL_75M; } else if (rate == 50 * MHZ) { src_clk = PCLK_TOP_SEL_50M; } else { src_clk = PCLK_TOP_SEL_24M; } rk_clrsetreg(&cru->clksel_con[73], PCLK_TOP_SEL_MASK, src_clk << PCLK_TOP_SEL_SHIFT); break; default: return -RT_ENOSYS; } return top_get_clk(priv, clk_id); } static rt_ubase_t i2c_get_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; rt_ubase_t rate; switch (clk_id) { case CLK_I2C1: case CLK_I2C2: case CLK_I2C3: case CLK_I2C4: case CLK_I2C5: con = HWREG32(&cru->clksel_con[71]); sel = (con & CLK_I2C_SEL_MASK) >> CLK_I2C_SEL_SHIFT; if (sel == CLK_I2C_SEL_200M) { rate = 200 * MHZ; } else if (sel == CLK_I2C_SEL_100M) { rate = 100 * MHZ; } else if (sel == CLK_I2C_SEL_CPLL_100M) { rate = 100 * MHZ; } else { rate = OSC_HZ; } break; default: return -RT_ERROR; } return rate; } static rt_ubase_t i2c_set_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; if (rate == 200 * MHZ) { src_clk = CLK_I2C_SEL_200M; } else if (rate == 100 * MHZ) { src_clk = CLK_I2C_SEL_100M; } else { src_clk = CLK_I2C_SEL_24M; } switch (clk_id) { case CLK_I2C1: case CLK_I2C2: case CLK_I2C3: case CLK_I2C4: case CLK_I2C5: rk_clrsetreg(&cru->clksel_con[71], CLK_I2C_SEL_MASK, src_clk << CLK_I2C_SEL_SHIFT); break; default: return -RT_ERROR; } return i2c_get_clk(priv, clk_id); } static rt_ubase_t spi_get_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; con = HWREG32(&cru->clksel_con[72]); switch (clk_id) { case CLK_SPI0: sel = (con & CLK_SPI0_SEL_MASK) >> CLK_SPI0_SEL_SHIFT; break; case CLK_SPI1: sel = (con & CLK_SPI1_SEL_MASK) >> CLK_SPI1_SEL_SHIFT; break; case CLK_SPI2: sel = (con & CLK_SPI2_SEL_MASK) >> CLK_SPI2_SEL_SHIFT; break; case CLK_SPI3: sel = (con & CLK_SPI3_SEL_MASK) >> CLK_SPI3_SEL_SHIFT; break; default: return -RT_ERROR; } switch (sel) { case CLK_SPI_SEL_200M: return 200 * MHZ; case CLK_SPI_SEL_24M: return OSC_HZ; case CLK_SPI_SEL_CPLL_100M: return 100 * MHZ; default: return -RT_ERROR; } } static rt_ubase_t spi_set_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; if (rate == 200 * MHZ) { src_clk = CLK_SPI_SEL_200M; } else if (rate == 100 * MHZ) { src_clk = CLK_SPI_SEL_CPLL_100M; } else { src_clk = CLK_SPI_SEL_24M; } switch (clk_id) { case CLK_SPI0: rk_clrsetreg(&cru->clksel_con[72], CLK_SPI0_SEL_MASK, src_clk << CLK_SPI0_SEL_SHIFT); break; case CLK_SPI1: rk_clrsetreg(&cru->clksel_con[72], CLK_SPI1_SEL_MASK, src_clk << CLK_SPI1_SEL_SHIFT); break; case CLK_SPI2: rk_clrsetreg(&cru->clksel_con[72], CLK_SPI2_SEL_MASK, src_clk << CLK_SPI2_SEL_SHIFT); break; case CLK_SPI3: rk_clrsetreg(&cru->clksel_con[72], CLK_SPI3_SEL_MASK, src_clk << CLK_SPI3_SEL_SHIFT); break; default: return -RT_ERROR; } return spi_get_clk(priv, clk_id); } static rt_ubase_t pwm_get_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; con = HWREG32(&cru->clksel_con[72]); switch (clk_id) { case CLK_PWM1: sel = (con & CLK_PWM1_SEL_MASK) >> CLK_PWM3_SEL_SHIFT; break; case CLK_PWM2: sel = (con & CLK_PWM2_SEL_MASK) >> CLK_PWM2_SEL_SHIFT; break; case CLK_PWM3: sel = (con & CLK_PWM3_SEL_MASK) >> CLK_PWM3_SEL_SHIFT; break; default: return -RT_ERROR; } switch (sel) { case CLK_PWM_SEL_100M: return 100 * MHZ; case CLK_PWM_SEL_24M: return OSC_HZ; case CLK_PWM_SEL_CPLL_100M: return 100 * MHZ; default: return -RT_ERROR; } } static rt_ubase_t pwm_set_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; if (rate == 100 * MHZ) { src_clk = CLK_PWM_SEL_100M; } else { src_clk = CLK_PWM_SEL_24M; } switch (clk_id) { case CLK_PWM1: rk_clrsetreg(&cru->clksel_con[72], CLK_PWM1_SEL_MASK, src_clk << CLK_PWM1_SEL_SHIFT); break; case CLK_PWM2: rk_clrsetreg(&cru->clksel_con[72], CLK_PWM2_SEL_MASK, src_clk << CLK_PWM2_SEL_SHIFT); break; case CLK_PWM3: rk_clrsetreg(&cru->clksel_con[72], CLK_PWM3_SEL_MASK, src_clk << CLK_PWM3_SEL_SHIFT); break; default: return -RT_ERROR; } return pwm_get_clk(priv, clk_id); } static rt_ubase_t adc_get_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t div, sel, con, prate; switch (clk_id) { case CLK_SARADC: return OSC_HZ; case CLK_TSADC_TSEN: con = HWREG32(&cru->clksel_con[51]); div = (con & CLK_TSADC_TSEN_DIV_MASK) >> CLK_TSADC_TSEN_DIV_SHIFT; sel = (con & CLK_TSADC_TSEN_SEL_MASK) >> CLK_TSADC_TSEN_SEL_SHIFT; if (sel == CLK_TSADC_TSEN_SEL_24M) { prate = OSC_HZ; } else { prate = 100 * MHZ; } return DIV_TO_RATE(prate, div); case CLK_TSADC: con = HWREG32(&cru->clksel_con[51]); div = (con & CLK_TSADC_DIV_MASK) >> CLK_TSADC_DIV_SHIFT; prate = adc_get_clk(priv, CLK_TSADC_TSEN); return DIV_TO_RATE(prate, div); default: return -RT_ERROR; } } static rt_ubase_t adc_set_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk_div; rt_ubase_t prate = 0; switch (clk_id) { case CLK_SARADC: return OSC_HZ; case CLK_TSADC_TSEN: if (!(OSC_HZ % rate)) { src_clk_div = RT_DIV_ROUND_UP(OSC_HZ, rate); RT_ASSERT(src_clk_div - 1 <= 7); rk_clrsetreg(&cru->clksel_con[51], CLK_TSADC_TSEN_SEL_MASK | CLK_TSADC_TSEN_DIV_MASK, (CLK_TSADC_TSEN_SEL_24M << CLK_TSADC_TSEN_SEL_SHIFT) | (src_clk_div - 1) << CLK_TSADC_TSEN_DIV_SHIFT); } else { src_clk_div = RT_DIV_ROUND_UP(100 * MHZ, rate); RT_ASSERT(src_clk_div - 1 <= 7); rk_clrsetreg(&cru->clksel_con[51], CLK_TSADC_TSEN_SEL_MASK | CLK_TSADC_TSEN_DIV_MASK, (CLK_TSADC_TSEN_SEL_100M << CLK_TSADC_TSEN_SEL_SHIFT) | (src_clk_div - 1) << CLK_TSADC_TSEN_DIV_SHIFT); } break; case CLK_TSADC: prate = adc_get_clk(priv, CLK_TSADC_TSEN); src_clk_div = RT_DIV_ROUND_UP(prate, rate); RT_ASSERT(src_clk_div - 1 <= 128); rk_clrsetreg(&cru->clksel_con[51], CLK_TSADC_DIV_MASK, (src_clk_div - 1) << CLK_TSADC_DIV_SHIFT); break; default: return -RT_ERROR; } return adc_get_clk(priv, clk_id); } static rt_ubase_t crypto_get_rate(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; switch (clk_id) { case ACLK_SECURE_FLASH: case ACLK_CRYPTO_NS: con = HWREG32(&cru->clksel_con[27]); sel = (con & ACLK_SECURE_FLASH_SEL_MASK) >> ACLK_SECURE_FLASH_SEL_SHIFT; if (sel == ACLK_SECURE_FLASH_SEL_200M) { return 200 * MHZ; } else if (sel == ACLK_SECURE_FLASH_SEL_150M) { return 150 * MHZ; } else if (sel == ACLK_SECURE_FLASH_SEL_100M) { return 100 * MHZ; } else { return 24 * MHZ; } case HCLK_SECURE_FLASH: case HCLK_CRYPTO_NS: case CLK_CRYPTO_NS_RNG: con = HWREG32(&cru->clksel_con[27]); sel = (con & HCLK_SECURE_FLASH_SEL_MASK) >> HCLK_SECURE_FLASH_SEL_SHIFT; if (sel == HCLK_SECURE_FLASH_SEL_150M) { return 150 * MHZ; } else if (sel == HCLK_SECURE_FLASH_SEL_100M) { return 100 * MHZ; } else if (sel == HCLK_SECURE_FLASH_SEL_75M) { return 75 * MHZ; } else { return 24 * MHZ; } case CLK_CRYPTO_NS_CORE: con = HWREG32(&cru->clksel_con[27]); sel = (con & CLK_CRYPTO_CORE_SEL_MASK) >> CLK_CRYPTO_CORE_SEL_SHIFT; if (sel == CLK_CRYPTO_CORE_SEL_200M) { return 200 * MHZ; } else if (sel == CLK_CRYPTO_CORE_SEL_150M) { return 150 * MHZ; } else { return 100 * MHZ; } case CLK_CRYPTO_NS_PKA: con = HWREG32(&cru->clksel_con[27]); sel = (con & CLK_CRYPTO_PKA_SEL_MASK) >> CLK_CRYPTO_PKA_SEL_SHIFT; if (sel == CLK_CRYPTO_PKA_SEL_300M) { return 300 * MHZ; } else if (sel == CLK_CRYPTO_PKA_SEL_200M) { return 200 * MHZ; } else { return 100 * MHZ; } default: return -RT_ERROR; } } static rt_ubase_t crypto_set_rate(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; rt_uint32_t src_clk, mask, shift; switch (clk_id) { case ACLK_SECURE_FLASH: case ACLK_CRYPTO_NS: mask = ACLK_SECURE_FLASH_SEL_MASK; shift = ACLK_SECURE_FLASH_SEL_SHIFT; if (rate == 200 * MHZ) { src_clk = ACLK_SECURE_FLASH_SEL_200M; } else if (rate == 150 * MHZ) { src_clk = ACLK_SECURE_FLASH_SEL_150M; } else if (rate == 100 * MHZ) { src_clk = ACLK_SECURE_FLASH_SEL_100M; } else { src_clk = ACLK_SECURE_FLASH_SEL_24M; } break; case HCLK_SECURE_FLASH: case HCLK_CRYPTO_NS: case CLK_CRYPTO_NS_RNG: mask = HCLK_SECURE_FLASH_SEL_MASK; shift = HCLK_SECURE_FLASH_SEL_SHIFT; if (rate == 150 * MHZ) { src_clk = HCLK_SECURE_FLASH_SEL_150M; } else if (rate == 100 * MHZ) { src_clk = HCLK_SECURE_FLASH_SEL_100M; } else if (rate == 75 * MHZ) { src_clk = HCLK_SECURE_FLASH_SEL_75M; } else { src_clk = HCLK_SECURE_FLASH_SEL_24M; } break; case CLK_CRYPTO_NS_CORE: mask = CLK_CRYPTO_CORE_SEL_MASK; shift = CLK_CRYPTO_CORE_SEL_SHIFT; if (rate == 200 * MHZ) { src_clk = CLK_CRYPTO_CORE_SEL_200M; } else if (rate == 150 * MHZ) { src_clk = CLK_CRYPTO_CORE_SEL_150M; } else { src_clk = CLK_CRYPTO_CORE_SEL_100M; } break; case CLK_CRYPTO_NS_PKA: mask = CLK_CRYPTO_PKA_SEL_MASK; shift = CLK_CRYPTO_PKA_SEL_SHIFT; if (rate == 300 * MHZ) { src_clk = CLK_CRYPTO_PKA_SEL_300M; } else if (rate == 200 * MHZ) { src_clk = CLK_CRYPTO_PKA_SEL_200M; } else { src_clk = CLK_CRYPTO_PKA_SEL_100M; } break; default: return -RT_ERROR; } rk_clrsetreg(&cru->clksel_con[27], mask, src_clk << shift); return crypto_get_rate(priv, clk_id); } static rt_ubase_t sdmmc_get_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; switch (clk_id) { case HCLK_SDMMC0: case CLK_SDMMC0: con = HWREG32(&cru->clksel_con[30]); sel = (con & CLK_SDMMC0_SEL_MASK) >> CLK_SDMMC0_SEL_SHIFT; break; case CLK_SDMMC1: con = HWREG32(&cru->clksel_con[30]); sel = (con & CLK_SDMMC1_SEL_MASK) >> CLK_SDMMC1_SEL_SHIFT; break; case CLK_SDMMC2: con = HWREG32(&cru->clksel_con[32]); sel = (con & CLK_SDMMC2_SEL_MASK) >> CLK_SDMMC2_SEL_SHIFT; break; default: return -RT_ERROR; } switch (sel) { case CLK_SDMMC_SEL_24M: return OSC_HZ; case CLK_SDMMC_SEL_400M: return 400 * MHZ; case CLK_SDMMC_SEL_300M: return 300 * MHZ; case CLK_SDMMC_SEL_100M: return 100 * MHZ; case CLK_SDMMC_SEL_50M: return 50 * MHZ; case CLK_SDMMC_SEL_750K: return 750 * KHZ; default: return -RT_ERROR; } } static rt_ubase_t sdmmc_set_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; switch (rate) { case OSC_HZ: src_clk = CLK_SDMMC_SEL_24M; break; case 400 * MHZ: src_clk = CLK_SDMMC_SEL_400M; break; case 300 * MHZ: src_clk = CLK_SDMMC_SEL_300M; break; case 100 * MHZ: src_clk = CLK_SDMMC_SEL_100M; break; case 52 * MHZ: case 50 * MHZ: src_clk = CLK_SDMMC_SEL_50M; break; case 750 * KHZ: case 400 * KHZ: src_clk = CLK_SDMMC_SEL_750K; break; default: return -RT_ERROR; } switch (clk_id) { case HCLK_SDMMC0: case CLK_SDMMC0: rk_clrsetreg(&cru->clksel_con[30], CLK_SDMMC0_SEL_MASK, src_clk << CLK_SDMMC0_SEL_SHIFT); break; case CLK_SDMMC1: rk_clrsetreg(&cru->clksel_con[30], CLK_SDMMC1_SEL_MASK, src_clk << CLK_SDMMC1_SEL_SHIFT); break; case CLK_SDMMC2: rk_clrsetreg(&cru->clksel_con[32], CLK_SDMMC2_SEL_MASK, src_clk << CLK_SDMMC2_SEL_SHIFT); break; default: return -RT_ERROR; } return sdmmc_get_clk(priv, clk_id); } static rt_ubase_t sfc_get_clk(struct rk_clk_priv *priv) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; con = HWREG32(&cru->clksel_con[28]); sel = (con & SCLK_SFC_SEL_MASK) >> SCLK_SFC_SEL_SHIFT; switch (sel) { case SCLK_SFC_SEL_24M: return OSC_HZ; case SCLK_SFC_SEL_50M: return 50 * MHZ; case SCLK_SFC_SEL_75M: return 75 * MHZ; case SCLK_SFC_SEL_100M: return 100 * MHZ; case SCLK_SFC_SEL_125M: return 125 * MHZ; case SCLK_SFC_SEL_150M: return 150 * KHZ; default: return -RT_ERROR; } } static rt_ubase_t sfc_set_clk(struct rk_clk_priv *priv, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; switch (rate) { case OSC_HZ: src_clk = SCLK_SFC_SEL_24M; break; case 50 * MHZ: src_clk = SCLK_SFC_SEL_50M; break; case 75 * MHZ: src_clk = SCLK_SFC_SEL_75M; break; case 100 * MHZ: src_clk = SCLK_SFC_SEL_100M; break; case 125 * MHZ: src_clk = SCLK_SFC_SEL_125M; break; case 150 * KHZ: src_clk = SCLK_SFC_SEL_150M; break; default: return -RT_ERROR; } rk_clrsetreg(&cru->clksel_con[28], SCLK_SFC_SEL_MASK, src_clk << SCLK_SFC_SEL_SHIFT); return sfc_get_clk(priv); } static rt_ubase_t nand_get_clk(struct rk_clk_priv *priv) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; con = HWREG32(&cru->clksel_con[28]); sel = (con & NCLK_NANDC_SEL_MASK) >> NCLK_NANDC_SEL_SHIFT; switch (sel) { case NCLK_NANDC_SEL_200M: return 200 * MHZ; case NCLK_NANDC_SEL_150M: return 150 * MHZ; case NCLK_NANDC_SEL_100M: return 100 * MHZ; case NCLK_NANDC_SEL_24M: return OSC_HZ; default: return -RT_ERROR; } } static rt_ubase_t nand_set_clk(struct rk_clk_priv *priv, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; switch (rate) { case OSC_HZ: src_clk = NCLK_NANDC_SEL_24M; break; case 100 * MHZ: src_clk = NCLK_NANDC_SEL_100M; break; case 150 * MHZ: src_clk = NCLK_NANDC_SEL_150M; break; case 200 * MHZ: src_clk = NCLK_NANDC_SEL_200M; break; default: return -RT_ERROR; } rk_clrsetreg(&cru->clksel_con[28], NCLK_NANDC_SEL_MASK, src_clk << NCLK_NANDC_SEL_SHIFT); return nand_get_clk(priv); } static rt_ubase_t emmc_get_clk(struct rk_clk_priv *priv) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; con = HWREG32(&cru->clksel_con[28]); sel = (con & CCLK_EMMC_SEL_MASK) >> CCLK_EMMC_SEL_SHIFT; switch (sel) { case CCLK_EMMC_SEL_200M: return 200 * MHZ; case CCLK_EMMC_SEL_150M: return 150 * MHZ; case CCLK_EMMC_SEL_100M: return 100 * MHZ; case CCLK_EMMC_SEL_50M: return 50 * MHZ; case CCLK_EMMC_SEL_375K: return 375 * KHZ; case CCLK_EMMC_SEL_24M: return OSC_HZ; default: return -RT_ERROR; } } static rt_ubase_t emmc_set_clk(struct rk_clk_priv *priv, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; switch (rate) { case OSC_HZ: src_clk = CCLK_EMMC_SEL_24M; break; case 52 * MHZ: case 50 * MHZ: src_clk = CCLK_EMMC_SEL_50M; break; case 100 * MHZ: src_clk = CCLK_EMMC_SEL_100M; break; case 150 * MHZ: src_clk = CCLK_EMMC_SEL_150M; break; case 200 * MHZ: src_clk = CCLK_EMMC_SEL_200M; break; case 400 * KHZ: case 375 * KHZ: src_clk = CCLK_EMMC_SEL_375K; break; default: return -RT_ERROR; } rk_clrsetreg(&cru->clksel_con[28], CCLK_EMMC_SEL_MASK, src_clk << CCLK_EMMC_SEL_SHIFT); return emmc_get_clk(priv); } static rt_ubase_t emmc_get_bclk(struct rk_clk_priv *priv) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; con = HWREG32(&cru->clksel_con[28]); sel = (con & BCLK_EMMC_SEL_MASK) >> BCLK_EMMC_SEL_SHIFT; switch (sel) { case BCLK_EMMC_SEL_200M: return 200 * MHZ; case BCLK_EMMC_SEL_150M: return 150 * MHZ; case BCLK_EMMC_SEL_125M: return 125 * MHZ; default: return -RT_ERROR; } } static rt_ubase_t emmc_set_bclk(struct rk_clk_priv *priv, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; switch (rate) { case 200 * MHZ: src_clk = BCLK_EMMC_SEL_200M; break; case 150 * MHZ: src_clk = BCLK_EMMC_SEL_150M; break; case 125 * MHZ: src_clk = BCLK_EMMC_SEL_125M; break; default: return -RT_ERROR; } rk_clrsetreg(&cru->clksel_con[28], BCLK_EMMC_SEL_MASK, src_clk << BCLK_EMMC_SEL_SHIFT); return emmc_get_bclk(priv); } static rt_ubase_t aclk_vop_get_clk(struct rk_clk_priv *priv) { struct rk_cru *cru = priv->cru; rt_uint32_t div, sel, con, parent; con = HWREG32(&cru->clksel_con[38]); div = (con & ACLK_VOP_PRE_DIV_MASK) >> ACLK_VOP_PRE_DIV_SHIFT; sel = (con & ACLK_VOP_PRE_SEL_MASK) >> ACLK_VOP_PRE_SEL_SHIFT; if (sel == ACLK_VOP_PRE_SEL_GPLL) { parent = priv->gpll_hz; } else if (sel == ACLK_VOP_PRE_SEL_CPLL) { parent = priv->cpll_hz; } else if (sel == ACLK_VOP_PRE_SEL_VPLL) { parent = priv->vpll_hz; } else { parent = priv->hpll_hz; } return DIV_TO_RATE(parent, div); } static rt_ubase_t aclk_vop_set_clk(struct rk_clk_priv *priv, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk_div, src_clk_mux; if ((priv->cpll_hz % rate) == 0) { src_clk_div = RT_DIV_ROUND_UP(priv->cpll_hz, rate); src_clk_mux = ACLK_VOP_PRE_SEL_CPLL; } else { src_clk_div = RT_DIV_ROUND_UP(priv->gpll_hz, rate); src_clk_mux = ACLK_VOP_PRE_SEL_GPLL; } RT_ASSERT(src_clk_div - 1 <= 31); rk_clrsetreg(&cru->clksel_con[38], ACLK_VOP_PRE_SEL_MASK | ACLK_VOP_PRE_DIV_MASK, src_clk_mux << ACLK_VOP_PRE_SEL_SHIFT | (src_clk_div - 1) << ACLK_VOP_PRE_DIV_SHIFT); return aclk_vop_get_clk(priv); } static rt_ubase_t dclk_vop_get_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t conid, div, sel, con, parent; switch (clk_id) { case DCLK_VOP0: conid = 39; break; case DCLK_VOP1: conid = 40; break; case DCLK_VOP2: conid = 41; break; default: return -RT_ERROR; } con = HWREG32(&cru->clksel_con[conid]); div = (con & DCLK0_VOP_DIV_MASK) >> DCLK0_VOP_DIV_SHIFT; sel = (con & DCLK0_VOP_SEL_MASK) >> DCLK0_VOP_SEL_SHIFT; if (sel == DCLK_VOP_SEL_HPLL) { parent = pmu_pll_get_rate(hpll); } else if (sel == DCLK_VOP_SEL_VPLL) { parent = rk_pll_get_rate(&pll_clks[vpll], &priv->cru); } else if (sel == DCLK_VOP_SEL_GPLL) { parent = priv->gpll_hz; } else if (sel == DCLK_VOP_SEL_CPLL) { parent = priv->cpll_hz; } else { return -RT_ERROR; } return DIV_TO_RATE(parent, div); } #define VOP_PLL_LIMIT_FREQ 600000000 static rt_ubase_t dclk_vop_set_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; rt_ubase_t pll_rate, now, best_rate = 0; rt_uint32_t i, conid, con, sel, div, best_div = 0, best_sel = 0; switch (clk_id) { case DCLK_VOP0: conid = 39; break; case DCLK_VOP1: conid = 40; break; case DCLK_VOP2: conid = 41; break; default: return -RT_ERROR; } con = HWREG32(&cru->clksel_con[conid]); sel = (con & DCLK0_VOP_SEL_MASK) >> DCLK0_VOP_SEL_SHIFT; if (sel == DCLK_VOP_SEL_HPLL) { div = 1; rk_clrsetreg(&cru->clksel_con[conid], DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK, (DCLK_VOP_SEL_HPLL << DCLK0_VOP_SEL_SHIFT) | ((div - 1) << DCLK0_VOP_DIV_SHIFT)); pmu_pll_set_rate(hpll, div * rate); } else if (sel == DCLK_VOP_SEL_VPLL) { div = RT_DIV_ROUND_UP(VOP_PLL_LIMIT_FREQ, rate); rk_clrsetreg(&cru->clksel_con[conid], DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK, (DCLK_VOP_SEL_VPLL << DCLK0_VOP_SEL_SHIFT) | ((div - 1) << DCLK0_VOP_DIV_SHIFT)); rk_pll_set_rate(&pll_clks[vpll], priv->cru, div * rate); } else { for (i = 0; i <= DCLK_VOP_SEL_CPLL; i++) { switch (i) { case DCLK_VOP_SEL_GPLL: pll_rate = priv->gpll_hz; break; case DCLK_VOP_SEL_CPLL: pll_rate = priv->cpll_hz; break; default: return -RT_ENOSYS; } div = RT_DIV_ROUND_UP(pll_rate, rate); if (div > 255) { continue; } now = pll_rate / div; if (rt_abs(rate - now) < rt_abs(rate - best_rate)) { best_rate = now; best_div = div; best_sel = i; } } if (best_rate) { rk_clrsetreg(&cru->clksel_con[conid], DCLK0_VOP_DIV_MASK | DCLK0_VOP_SEL_MASK, best_sel << DCLK0_VOP_SEL_SHIFT | (best_div - 1) << DCLK0_VOP_DIV_SHIFT); } else { return -RT_ENOSYS; } } return dclk_vop_get_clk(priv, clk_id); } static rt_ubase_t gmac_src_get_clk(struct rk_clk_priv *priv, rt_ubase_t mac_id) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; con = HWREG32(&cru->clksel_con[31 + mac_id * 2]); sel = (con & CLK_MAC0_2TOP_SEL_MASK) >> CLK_MAC0_2TOP_SEL_SHIFT; switch (sel) { case CLK_MAC0_2TOP_SEL_125M: return 125 * MHZ; case CLK_MAC0_2TOP_SEL_50M: return 50 * MHZ; case CLK_MAC0_2TOP_SEL_25M: return 25 * MHZ; case CLK_MAC0_2TOP_SEL_PPLL: return pmu_pll_get_rate(hpll); default: return -RT_ERROR; } } static rt_ubase_t gmac_src_set_clk(struct rk_clk_priv *priv, rt_ubase_t mac_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; switch (rate) { case 125 * MHZ: src_clk = CLK_MAC0_2TOP_SEL_125M; break; case 50 * MHZ: src_clk = CLK_MAC0_2TOP_SEL_50M; break; case 25 * MHZ: src_clk = CLK_MAC0_2TOP_SEL_25M; break; default: return -RT_ERROR; } rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2], CLK_MAC0_2TOP_SEL_MASK, src_clk << CLK_MAC0_2TOP_SEL_SHIFT); return gmac_src_get_clk(priv, mac_id); } static rt_ubase_t gmac_out_get_clk(struct rk_clk_priv *priv, rt_ubase_t mac_id) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; con = HWREG32(&cru->clksel_con[31 + mac_id * 2]); sel = (con & CLK_MAC0_OUT_SEL_MASK) >> CLK_MAC0_OUT_SEL_SHIFT; switch (sel) { case CLK_MAC0_OUT_SEL_125M: return 125 * MHZ; case CLK_MAC0_OUT_SEL_50M: return 50 * MHZ; case CLK_MAC0_OUT_SEL_25M: return 25 * MHZ; case CLK_MAC0_OUT_SEL_24M: return OSC_HZ; default: return -RT_ERROR; } } static rt_ubase_t gmac_out_set_clk(struct rk_clk_priv *priv, rt_ubase_t mac_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; switch (rate) { case 125 * MHZ: src_clk = CLK_MAC0_OUT_SEL_125M; break; case 50 * MHZ: src_clk = CLK_MAC0_OUT_SEL_50M; break; case 25 * MHZ: src_clk = CLK_MAC0_OUT_SEL_25M; break; case 24 * MHZ: src_clk = CLK_MAC0_OUT_SEL_24M; break; default: return -RT_ERROR; } rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2], CLK_MAC0_OUT_SEL_MASK, src_clk << CLK_MAC0_OUT_SEL_SHIFT); return gmac_out_get_clk(priv, mac_id); } static rt_ubase_t gmac_ptp_ref_get_clk(struct rk_clk_priv *priv, rt_ubase_t mac_id) { struct rk_cru *cru = priv->cru; rt_uint32_t sel, con; con = HWREG32(&cru->clksel_con[31 + mac_id * 2]); sel = (con & CLK_GMAC0_PTP_REF_SEL_MASK) >> CLK_GMAC0_PTP_REF_SEL_SHIFT; switch (sel) { case CLK_GMAC0_PTP_REF_SEL_62_5M: return 62500 * KHZ; case CLK_GMAC0_PTP_REF_SEL_100M: return 100 * MHZ; case CLK_GMAC0_PTP_REF_SEL_50M: return 50 * MHZ; case CLK_GMAC0_PTP_REF_SEL_24M: return OSC_HZ; default: return -RT_ERROR; } } static rt_ubase_t gmac_ptp_ref_set_clk(struct rk_clk_priv *priv, rt_ubase_t mac_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk; switch (rate) { case 62500 * KHZ: src_clk = CLK_GMAC0_PTP_REF_SEL_62_5M; break; case 100 * MHZ: src_clk = CLK_GMAC0_PTP_REF_SEL_100M; break; case 50 * MHZ: src_clk = CLK_GMAC0_PTP_REF_SEL_50M; break; case 24 * MHZ: src_clk = CLK_GMAC0_PTP_REF_SEL_24M; break; default: return -RT_ERROR; } rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2], CLK_GMAC0_PTP_REF_SEL_MASK, src_clk << CLK_GMAC0_PTP_REF_SEL_SHIFT); return gmac_ptp_ref_get_clk(priv, mac_id); } static rt_ubase_t gmac_tx_rx_set_clk(struct rk_clk_priv *priv, rt_ubase_t mac_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; rt_uint32_t con, sel, div_sel; con = HWREG32(&cru->clksel_con[31 + mac_id * 2]); sel = (con & RMII0_MODE_MASK) >> RMII0_MODE_SHIFT; if (sel == RMII0_MODE_SEL_RGMII) { if (rate == 2500000) { div_sel = RGMII0_CLK_SEL_2_5M; } else if (rate == 25000000) { div_sel = RGMII0_CLK_SEL_25M; } else { div_sel = RGMII0_CLK_SEL_125M; } rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2], RGMII0_CLK_SEL_MASK, div_sel << RGMII0_CLK_SEL_SHIFT); } else if (sel == RMII0_MODE_SEL_RMII) { if (rate == 2500000) { div_sel = RMII0_CLK_SEL_2_5M; } else { div_sel = RMII0_CLK_SEL_25M; } rk_clrsetreg(&cru->clksel_con[31 + mac_id * 2], RMII0_CLK_SEL_MASK, div_sel << RMII0_CLK_SEL_SHIFT); } return 0; } static rt_ubase_t ebc_get_clk(struct rk_clk_priv *priv) { struct rk_cru *cru = priv->cru; rt_uint32_t con, div, p_rate; con = HWREG32(&cru->clksel_con[79]); div = (con & CPLL_333M_DIV_MASK) >> CPLL_333M_DIV_SHIFT; p_rate = DIV_TO_RATE(priv->cpll_hz, div); con = HWREG32(&cru->clksel_con[43]); div = (con & DCLK_EBC_SEL_MASK) >> DCLK_EBC_SEL_SHIFT; switch (div) { case DCLK_EBC_SEL_GPLL_400M: return 400 * MHZ; case DCLK_EBC_SEL_CPLL_333M: return p_rate; case DCLK_EBC_SEL_GPLL_200M: return 200 * MHZ; default: return -RT_ERROR; } } static rt_ubase_t ebc_set_clk(struct rk_clk_priv *priv, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk_div; src_clk_div = RT_DIV_ROUND_UP(priv->cpll_hz, rate); RT_ASSERT(src_clk_div - 1 <= 31); rk_clrsetreg(&cru->clksel_con[79], CPLL_333M_DIV_MASK, (src_clk_div - 1) << CPLL_333M_DIV_SHIFT); rk_clrsetreg(&cru->clksel_con[43], DCLK_EBC_SEL_MASK, DCLK_EBC_SEL_CPLL_333M << DCLK_EBC_SEL_SHIFT); return ebc_get_clk(priv); } static rt_ubase_t rkvdec_get_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t con, div, src, p_rate; switch (clk_id) { case ACLK_RKVDEC_PRE: case ACLK_RKVDEC: con = HWREG32(&cru->clksel_con[47]); src = (con & ACLK_RKVDEC_SEL_MASK) >> ACLK_RKVDEC_SEL_SHIFT; div = (con & ACLK_RKVDEC_DIV_MASK) >> ACLK_RKVDEC_DIV_SHIFT; if (src == ACLK_RKVDEC_SEL_CPLL) { p_rate = priv->cpll_hz; } else { p_rate = priv->gpll_hz; } return DIV_TO_RATE(p_rate, div); case CLK_RKVDEC_CORE: con = HWREG32(&cru->clksel_con[49]); src = (con & CLK_RKVDEC_CORE_SEL_MASK) >> CLK_RKVDEC_CORE_SEL_SHIFT; div = (con & CLK_RKVDEC_CORE_DIV_MASK) >> CLK_RKVDEC_CORE_DIV_SHIFT; if (src == CLK_RKVDEC_CORE_SEL_CPLL) { p_rate = priv->cpll_hz; } else if (src == CLK_RKVDEC_CORE_SEL_NPLL) { p_rate = priv->npll_hz; } else if (src == CLK_RKVDEC_CORE_SEL_VPLL) { p_rate = priv->vpll_hz; } else { p_rate = priv->gpll_hz; } return DIV_TO_RATE(p_rate, div); default: return -RT_ERROR; } } static rt_ubase_t rkvdec_set_clk(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; int src_clk_div, src, p_rate; switch (clk_id) { case ACLK_RKVDEC_PRE: case ACLK_RKVDEC: src = (HWREG32(&cru->clksel_con[47]) & ACLK_RKVDEC_SEL_MASK) >> ACLK_RKVDEC_SEL_SHIFT; if (src == ACLK_RKVDEC_SEL_CPLL) { p_rate = priv->cpll_hz; } else { p_rate = priv->gpll_hz; } src_clk_div = RT_DIV_ROUND_UP(p_rate, rate); RT_ASSERT(src_clk_div - 1 <= 31); rk_clrsetreg(&cru->clksel_con[47], ACLK_RKVDEC_SEL_MASK | ACLK_RKVDEC_DIV_MASK, (src << ACLK_RKVDEC_SEL_SHIFT) | (src_clk_div - 1) << ACLK_RKVDEC_DIV_SHIFT); break; case CLK_RKVDEC_CORE: src = (HWREG32(&cru->clksel_con[49]) & CLK_RKVDEC_CORE_SEL_MASK) >> CLK_RKVDEC_CORE_SEL_SHIFT; if (src == CLK_RKVDEC_CORE_SEL_CPLL) { p_rate = priv->cpll_hz; } else if (src == CLK_RKVDEC_CORE_SEL_NPLL) { p_rate = priv->npll_hz; } else if (src == CLK_RKVDEC_CORE_SEL_VPLL) { p_rate = priv->vpll_hz; } else { p_rate = priv->gpll_hz; } src_clk_div = RT_DIV_ROUND_UP(p_rate, rate); RT_ASSERT(src_clk_div - 1 <= 31); rk_clrsetreg(&cru->clksel_con[49], CLK_RKVDEC_CORE_SEL_MASK | CLK_RKVDEC_CORE_DIV_MASK, (src << CLK_RKVDEC_CORE_SEL_SHIFT) | (src_clk_div - 1) << CLK_RKVDEC_CORE_DIV_SHIFT); break; default: return -RT_ERROR; } return rkvdec_get_clk(priv, clk_id); } static rt_ubase_t uart_get_rate(struct rk_clk_priv *priv, rt_ubase_t clk_id) { struct rk_cru *cru = priv->cru; rt_uint32_t reg, con, fracdiv, div, src, p_src, p_rate; rt_ubase_t m, n; switch (clk_id) { case SCLK_UART1: reg = 52; break; case SCLK_UART2: reg = 54; break; case SCLK_UART3: reg = 56; break; case SCLK_UART4: reg = 58; break; case SCLK_UART5: reg = 60; break; case SCLK_UART6: reg = 62; break; case SCLK_UART7: reg = 64; break; case SCLK_UART8: reg = 66; break; case SCLK_UART9: reg = 68; break; default: return -RT_ERROR; } con = HWREG32(&cru->clksel_con[reg]); src = (con & CLK_UART_SEL_MASK) >> CLK_UART_SEL_SHIFT; div = (con & CLK_UART_SRC_DIV_MASK) >> CLK_UART_SRC_DIV_SHIFT; p_src = (con & CLK_UART_SRC_SEL_MASK) >> CLK_UART_SRC_SEL_SHIFT; if (p_src == CLK_UART_SRC_SEL_GPLL) { p_rate = priv->gpll_hz; } else if (p_src == CLK_UART_SRC_SEL_CPLL) { p_rate = priv->cpll_hz; } else { p_rate = 480000000; } if (src == CLK_UART_SEL_SRC) { return DIV_TO_RATE(p_rate, div); } else if (src == CLK_UART_SEL_FRAC) { fracdiv = HWREG32(&cru->clksel_con[reg + 1]); n = fracdiv & CLK_UART_FRAC_NUMERATOR_MASK; n >>= CLK_UART_FRAC_NUMERATOR_SHIFT; m = fracdiv & CLK_UART_FRAC_DENOMINATOR_MASK; m >>= CLK_UART_FRAC_DENOMINATOR_SHIFT; return DIV_TO_RATE(p_rate, div) * n / m; } else { return OSC_HZ; } } static rt_ubase_t uart_set_rate(struct rk_clk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { struct rk_cru *cru = priv->cru; rt_uint32_t reg, clk_src, uart_src, div; rt_ubase_t m = 0, n = 0, val; if (priv->gpll_hz % rate == 0) { clk_src = CLK_UART_SRC_SEL_GPLL; uart_src = CLK_UART_SEL_SRC; div = RT_DIV_ROUND_UP(priv->gpll_hz, rate); } else if (priv->cpll_hz % rate == 0) { clk_src = CLK_UART_SRC_SEL_CPLL; uart_src = CLK_UART_SEL_SRC; div = RT_DIV_ROUND_UP(priv->gpll_hz, rate); } else if (rate == OSC_HZ) { clk_src = CLK_UART_SRC_SEL_GPLL; uart_src = CLK_UART_SEL_XIN24M; div = 2; } else { clk_src = CLK_UART_SRC_SEL_GPLL; uart_src = CLK_UART_SEL_FRAC; div = 2; rational_best_approximation(rate, priv->gpll_hz / div, RT_GENMASK(16 - 1, 0), RT_GENMASK(16 - 1, 0), &m, &n); } switch (clk_id) { case SCLK_UART1: reg = 52; break; case SCLK_UART2: reg = 54; break; case SCLK_UART3: reg = 56; break; case SCLK_UART4: reg = 58; break; case SCLK_UART5: reg = 60; break; case SCLK_UART6: reg = 62; break; case SCLK_UART7: reg = 64; break; case SCLK_UART8: reg = 66; break; case SCLK_UART9: reg = 68; break; default: return -RT_ERROR; } rk_clrsetreg(&cru->clksel_con[reg], CLK_UART_SEL_MASK | CLK_UART_SRC_SEL_MASK | CLK_UART_SRC_DIV_MASK, (clk_src << CLK_UART_SRC_SEL_SHIFT) | (uart_src << CLK_UART_SEL_SHIFT) | ((div - 1) << CLK_UART_SRC_DIV_SHIFT)); if (m && n) { val = m << CLK_UART_FRAC_NUMERATOR_SHIFT | n; HWREG32(&cru->clksel_con[reg + 1]) = val; } return uart_get_rate(priv, clk_id); } static rt_ubase_t pmu_get_pmuclk(struct rk_pmuclk_priv *priv) { struct rk_pmucru *pmucru = priv->pmucru; rt_uint32_t div, con, sel, parent; con = HWREG32(&pmucru->pmu_clksel_con[2]); sel = (con & PCLK_PDPMU_SEL_MASK) >> PCLK_PDPMU_SEL_SHIFT; div = (con & PCLK_PDPMU_DIV_MASK) >> PCLK_PDPMU_DIV_SHIFT; if (sel) { parent = GPLL_HZ; } else { parent = priv->ppll_hz; } return DIV_TO_RATE(parent, div); } static rt_ubase_t pmu_set_pmuclk(struct rk_pmuclk_priv *priv, rt_ubase_t rate) { struct rk_pmucru *pmucru = priv->pmucru; int src_clk_div; src_clk_div = RT_DIV_ROUND_UP(priv->ppll_hz, rate); RT_ASSERT(src_clk_div - 1 <= 31); rk_clrsetreg(&pmucru->pmu_clksel_con[2], PCLK_PDPMU_DIV_MASK | PCLK_PDPMU_SEL_MASK, (PCLK_PDPMU_SEL_PPLL << PCLK_PDPMU_SEL_SHIFT) | ((src_clk_div - 1) << PCLK_PDPMU_DIV_SHIFT)); return pmu_get_pmuclk(priv); } static rt_ubase_t pciephy_ref_get_pmuclk(struct rk_pmuclk_priv *priv, rt_ubase_t clk_id) { rt_uint32_t con, div, src; struct rk_pmucru *pmucru = priv->pmucru; switch (clk_id) { case CLK_PCIEPHY0_REF: con = HWREG32(&pmucru->pmu_clksel_con[9]); src = (con & CLK_PCIE_PHY0_REF_SEL_MASK) >> CLK_PCIE_PHY0_REF_SEL_SHIFT; con = HWREG32(&pmucru->pmu_clksel_con[9]); div = (con & CLK_PCIE_PHY0_PLL_DIV_MASK) >> CLK_PCIE_PHY0_PLL_DIV_SHIFT; break; case CLK_PCIEPHY1_REF: con = HWREG32(&pmucru->pmu_clksel_con[9]); src = (con & CLK_PCIE_PHY1_REF_SEL_MASK) >> CLK_PCIE_PHY1_REF_SEL_SHIFT; con = HWREG32(&pmucru->pmu_clksel_con[9]); div = (con & CLK_PCIE_PHY1_PLL_DIV_MASK) >> CLK_PCIE_PHY1_PLL_DIV_SHIFT; break; case CLK_PCIEPHY2_REF: con = HWREG32(&pmucru->pmu_clksel_con[9]); src = (con & CLK_PCIE_PHY2_REF_SEL_MASK) >> CLK_PCIE_PHY2_REF_SEL_SHIFT; con = HWREG32(&pmucru->pmu_clksel_con[9]); div = (con & CLK_PCIE_PHY2_PLL_DIV_MASK) >> CLK_PCIE_PHY2_PLL_DIV_SHIFT; break; } if (src == CLK_PCIE_PHY_REF_SEL_PPLL) { return DIV_TO_RATE(priv->ppll_hz, div); } else { return OSC_HZ; } } static rt_ubase_t pciephy_ref_set_pmuclk(struct rk_pmuclk_priv *priv, rt_ubase_t clk_id, rt_ubase_t rate) { rt_uint32_t clk_src, div; struct rk_pmucru *pmucru = priv->pmucru; if (rate == OSC_HZ) { clk_src = CLK_PCIE_PHY_REF_SEL_24M; div = 1; } else { clk_src = CLK_PCIE_PHY_REF_SEL_PPLL; div = RT_DIV_ROUND_UP(priv->ppll_hz, rate); } switch (clk_id) { case CLK_PCIEPHY0_REF: rk_clrsetreg(&pmucru->pmu_clksel_con[9], CLK_PCIE_PHY0_REF_SEL_MASK, (clk_src << CLK_PCIE_PHY0_REF_SEL_SHIFT)); rk_clrsetreg(&pmucru->pmu_clksel_con[9], CLK_PCIE_PHY0_PLL_DIV_MASK, ((div - 1) << CLK_PCIE_PHY0_PLL_DIV_SHIFT)); break; case CLK_PCIEPHY1_REF: rk_clrsetreg(&pmucru->pmu_clksel_con[9], CLK_PCIE_PHY1_REF_SEL_MASK, (clk_src << CLK_PCIE_PHY1_REF_SEL_SHIFT)); rk_clrsetreg(&pmucru->pmu_clksel_con[9], CLK_PCIE_PHY1_PLL_DIV_MASK, ((div - 1) << CLK_PCIE_PHY1_PLL_DIV_SHIFT)); break; case CLK_PCIEPHY2_REF: rk_clrsetreg(&pmucru->pmu_clksel_con[9], CLK_PCIE_PHY2_REF_SEL_MASK, (clk_src << CLK_PCIE_PHY2_REF_SEL_SHIFT)); rk_clrsetreg(&pmucru->pmu_clksel_con[9], CLK_PCIE_PHY2_PLL_DIV_MASK, ((div - 1) << CLK_PCIE_PHY2_PLL_DIV_SHIFT)); break; default: return -RT_EINVAL; } return pciephy_ref_get_pmuclk(priv, clk_id); } static rt_ubase_t rk_pmuclk_type_get_rate(struct rk_clk_platform_data *pdata, struct rk_clk *rk_clk) { struct rk_pmuclk_priv *priv = &rk_clk->pmuclk_info; rt_ubase_t rate = 0; if (!priv->ppll_hz) { return -RT_ERROR; } switch (pdata->id) { case PLL_PPLL: rate = rk_pll_get_rate(&pmu_pll_clks[ppll], &priv->pmucru); break; case PLL_HPLL: rate = rk_pll_get_rate(&pmu_pll_clks[hpll], &priv->pmucru); break; case CLK_RTC_32K: case CLK_RTC32K_FRAC: rate = rtc32k_get_pmuclk(priv); break; case SCLK_UART0: rate = uart_get_pmuclk(priv, pdata->id); break; case CLK_I2C0: rate = i2c_get_pmuclk(priv, pdata->id); break; case CLK_PWM0: rate = pwm_get_pmuclk(priv, pdata->id); break; case PCLK_PMU: rate = pmu_get_pmuclk(priv); break; case CLK_PCIEPHY0_REF: case CLK_PCIEPHY1_REF: case CLK_PCIEPHY2_REF: rate = pciephy_ref_get_pmuclk(priv, pdata->id); break; default: return -RT_ERROR; } return rate; } static rt_ubase_t rk_pmuclk_set_rate(struct rk_clk_platform_data *pdata, struct rk_clk *rk_clk, rt_ubase_t rate) { struct rk_pmuclk_priv *priv = &rk_clk->pmuclk_info; rt_ubase_t res = 0; if (!priv->ppll_hz) { return -RT_ERROR; } switch (pdata->id) { case PLL_PPLL: res = rk_pll_set_rate(&pmu_pll_clks[ppll], priv->pmucru, rate); priv->ppll_hz = rk_pll_get_rate(&pmu_pll_clks[ppll], &priv->pmucru); break; case PLL_HPLL: res = rk_pll_set_rate(&pmu_pll_clks[hpll], priv->pmucru, rate); priv->hpll_hz = rk_pll_get_rate(&pmu_pll_clks[hpll], &priv->pmucru); break; case CLK_RTC_32K: case CLK_RTC32K_FRAC: res = rtc32k_set_pmuclk(priv, rate); break; case SCLK_UART0: res = uart_set_pmuclk(priv, pdata->id, rate); break; case CLK_I2C0: res = i2c_set_pmuclk(priv, pdata->id, rate); break; case CLK_PWM0: res = pwm_set_pmuclk(priv, pdata->id, rate); break; case PCLK_PMU: res = pmu_set_pmuclk(priv, rate); break; case CLK_PCIEPHY0_REF: case CLK_PCIEPHY1_REF: case CLK_PCIEPHY2_REF: res = pciephy_ref_set_pmuclk(priv, pdata->id, rate); break; default: return -RT_ERROR; } return res; } static rt_ubase_t rk_clk_type_get_rate(struct rk_clk_platform_data *pdata, struct rk_clk *rk_clk) { struct rk_clk_priv *priv = &rk_clk->clk_info; rt_ubase_t rate = 0; if (!priv->gpll_hz) { return -RT_ERROR; } switch (pdata->id) { case PLL_APLL: case ARMCLK: rate = rk_pll_get_rate(&pll_clks[apll], &priv->cru); break; case PLL_CPLL: rate = rk_pll_get_rate(&pll_clks[cpll], &priv->cru); break; case PLL_GPLL: rate = rk_pll_get_rate(&pll_clks[gpll], &priv->cru); break; case PLL_NPLL: rate = rk_pll_get_rate(&pll_clks[npll], &priv->cru); break; case PLL_VPLL: rate = rk_pll_get_rate(&pll_clks[vpll], &priv->cru); break; case PLL_DPLL: rate = rk_pll_get_rate(&pll_clks[dpll], &priv->cru); break; case ACLK_BUS: case PCLK_BUS: case PCLK_WDT_NS: rate = bus_get_clk(priv, pdata->id); break; case ACLK_PERIMID: case HCLK_PERIMID: rate = perimid_get_clk(priv, pdata->id); break; case ACLK_TOP_HIGH: case ACLK_TOP_LOW: case HCLK_TOP: case PCLK_TOP: rate = top_get_clk(priv, pdata->id); break; case CLK_I2C1: case CLK_I2C2: case CLK_I2C3: case CLK_I2C4: case CLK_I2C5: rate = i2c_get_clk(priv, pdata->id); break; case CLK_SPI0: case CLK_SPI1: case CLK_SPI2: case CLK_SPI3: rate = spi_get_clk(priv, pdata->id); break; case CLK_PWM1: case CLK_PWM2: case CLK_PWM3: rate = pwm_get_clk(priv, pdata->id); break; case CLK_SARADC: case CLK_TSADC_TSEN: case CLK_TSADC: rate = adc_get_clk(priv, pdata->id); break; case HCLK_SDMMC0: case CLK_SDMMC0: case CLK_SDMMC1: case CLK_SDMMC2: rate = sdmmc_get_clk(priv, pdata->id); break; case SCLK_SFC: rate = sfc_get_clk(priv); break; case NCLK_NANDC: rate = nand_get_clk(priv); break; case CCLK_EMMC: rate = emmc_get_clk(priv); break; case BCLK_EMMC: rate = emmc_get_bclk(priv); break; case ACLK_VOP: rate = aclk_vop_get_clk(priv); break; case DCLK_VOP0: case DCLK_VOP1: case DCLK_VOP2: rate = dclk_vop_get_clk(priv, pdata->id); break; case SCLK_GMAC0: case CLK_MAC0_2TOP: case CLK_MAC0_REFOUT: rate = gmac_src_get_clk(priv, 0); break; case CLK_MAC0_OUT: rate = gmac_out_get_clk(priv, 0); break; case CLK_GMAC0_PTP_REF: rate = gmac_ptp_ref_get_clk(priv, 0); break; case SCLK_GMAC1: case CLK_MAC1_2TOP: case CLK_MAC1_REFOUT: rate = gmac_src_get_clk(priv, 1); break; case CLK_MAC1_OUT: rate = gmac_out_get_clk(priv, 1); break; case CLK_GMAC1_PTP_REF: rate = gmac_ptp_ref_get_clk(priv, 1); break; case DCLK_EBC: rate = ebc_get_clk(priv); break; case ACLK_RKVDEC_PRE: case ACLK_RKVDEC: case CLK_RKVDEC_CORE: rate = rkvdec_get_clk(priv, pdata->id); break; case TCLK_WDT_NS: rate = OSC_HZ; break; case SCLK_UART1: case SCLK_UART2: case SCLK_UART3: case SCLK_UART4: case SCLK_UART5: case SCLK_UART6: case SCLK_UART7: case SCLK_UART8: case SCLK_UART9: rate = uart_get_rate(priv, pdata->id); break; case ACLK_SECURE_FLASH: case ACLK_CRYPTO_NS: case HCLK_SECURE_FLASH: case HCLK_CRYPTO_NS: case CLK_CRYPTO_NS_RNG: case CLK_CRYPTO_NS_CORE: case CLK_CRYPTO_NS_PKA: rate = crypto_get_rate(priv, pdata->id); break; case CPLL_500M: case CPLL_333M: case CPLL_250M: case CPLL_125M: case CPLL_100M: case CPLL_62P5M: case CPLL_50M: case CPLL_25M: rate = cpll_div_get_rate(priv, pdata->id); break; case CLK_TIMER0: case CLK_TIMER1: case CLK_TIMER2: case CLK_TIMER3: case CLK_TIMER4: case CLK_TIMER5: rate = OSC_HZ; break; default: return -RT_ERROR; } return rate; }; static rt_ubase_t rk_clk_set_rate(struct rk_clk_platform_data *pdata, struct rk_clk *rk_clk, rt_ubase_t rate) { struct rk_clk_priv *priv = &rk_clk->clk_info; rt_ubase_t res = 0; if (!priv->gpll_hz) { return -RT_ERROR; } switch (pdata->id) { case PLL_APLL: case ARMCLK: if (priv->armclk_hz) { armclk_set_clk(priv, rate); } priv->armclk_hz = rate; break; case PLL_CPLL: res = rk_pll_set_rate(&pll_clks[cpll], priv->cru, rate); priv->cpll_hz = rk_pll_get_rate(&pll_clks[cpll], &priv->cru); break; case PLL_GPLL: res = rk_pll_set_rate(&pll_clks[gpll], priv->cru, rate); priv->gpll_hz = rk_pll_get_rate(&pll_clks[gpll], &priv->cru); break; case PLL_NPLL: res = rk_pll_set_rate(&pll_clks[npll], priv->cru, rate); break; case PLL_VPLL: res = rk_pll_set_rate(&pll_clks[vpll], priv->cru, rate); priv->vpll_hz = rk_pll_get_rate(&pll_clks[vpll], &priv->cru); break; case ACLK_BUS: case PCLK_BUS: case PCLK_WDT_NS: res = bus_set_clk(priv, pdata->id, rate); break; case ACLK_PERIMID: case HCLK_PERIMID: res = perimid_set_clk(priv, pdata->id, rate); break; case ACLK_TOP_HIGH: case ACLK_TOP_LOW: case HCLK_TOP: case PCLK_TOP: res = top_set_clk(priv, pdata->id, rate); break; case CLK_I2C1: case CLK_I2C2: case CLK_I2C3: case CLK_I2C4: case CLK_I2C5: res = i2c_set_clk(priv, pdata->id, rate); break; case CLK_SPI0: case CLK_SPI1: case CLK_SPI2: case CLK_SPI3: res = spi_set_clk(priv, pdata->id, rate); break; case CLK_PWM1: case CLK_PWM2: case CLK_PWM3: res = pwm_set_clk(priv, pdata->id, rate); break; case CLK_SARADC: case CLK_TSADC_TSEN: case CLK_TSADC: res = adc_set_clk(priv, pdata->id, rate); break; case HCLK_SDMMC0: case CLK_SDMMC0: case CLK_SDMMC1: case CLK_SDMMC2: res = sdmmc_set_clk(priv, pdata->id, rate); break; case SCLK_SFC: res = sfc_set_clk(priv, rate); break; case NCLK_NANDC: res = nand_set_clk(priv, rate); break; case CCLK_EMMC: res = emmc_set_clk(priv, rate); break; case BCLK_EMMC: res = emmc_set_bclk(priv, rate); break; case ACLK_VOP: res = aclk_vop_set_clk(priv, rate); break; case DCLK_VOP0: case DCLK_VOP1: case DCLK_VOP2: res = dclk_vop_set_clk(priv, pdata->id, rate); break; case SCLK_GMAC0: case CLK_MAC0_2TOP: case CLK_MAC0_REFOUT: res = gmac_src_set_clk(priv, 0, rate); break; case CLK_MAC0_OUT: res = gmac_out_set_clk(priv, 0, rate); break; case SCLK_GMAC0_RX_TX: res = gmac_tx_rx_set_clk(priv, 0, rate); break; case CLK_GMAC0_PTP_REF: res = gmac_ptp_ref_set_clk(priv, 0, rate); break; case SCLK_GMAC1: case CLK_MAC1_2TOP: case CLK_MAC1_REFOUT: res = gmac_src_set_clk(priv, 1, rate); break; case CLK_MAC1_OUT: res = gmac_out_set_clk(priv, 1, rate); break; case SCLK_GMAC1_RX_TX: res = gmac_tx_rx_set_clk(priv, 1, rate); break; case CLK_GMAC1_PTP_REF: res = gmac_ptp_ref_set_clk(priv, 1, rate); break; case DCLK_EBC: res = ebc_set_clk(priv, rate); break; case ACLK_RKVDEC_PRE: case ACLK_RKVDEC: case CLK_RKVDEC_CORE: res = rkvdec_set_clk(priv, pdata->id, rate); break; case TCLK_WDT_NS: res = OSC_HZ; break; case SCLK_UART1: case SCLK_UART2: case SCLK_UART3: case SCLK_UART4: case SCLK_UART5: case SCLK_UART6: case SCLK_UART7: case SCLK_UART8: case SCLK_UART9: res = uart_set_rate(priv, pdata->id, rate); break; case ACLK_SECURE_FLASH: case ACLK_CRYPTO_NS: case HCLK_SECURE_FLASH: case HCLK_CRYPTO_NS: case CLK_CRYPTO_NS_RNG: case CLK_CRYPTO_NS_CORE: case CLK_CRYPTO_NS_PKA: res = crypto_set_rate(priv, pdata->id, rate); break; case CPLL_500M: case CPLL_333M: case CPLL_250M: case CPLL_125M: case CPLL_100M: case CPLL_62P5M: case CPLL_50M: case CPLL_25M: res = cpll_div_set_rate(priv, pdata->id, rate); break; default: return -RT_ERROR; } return res; }; static rt_uint32_t rk_clk_get_rate(struct rk_clk_platform_data *pdata, struct rk_clk *rk_clk) { rt_uint32_t rate = 0; if (rk_clk->type == rk_clk_type_clk) { rate = rk_clk_type_get_rate(pdata, rk_clk); } else if (rk_clk->type == rk_clk_type_pmuclk) { rate = rk_pmuclk_type_get_rate(pdata, rk_clk); } return rate; } static rt_err_t rk_clk_wait_lock(struct rk_clk_platform_data *pdata) { rt_err_t err = RT_EOK; rt_uint32_t count = 0, pllcon; /* * Lock time typical 250, max 500 input clock cycles @24MHz, So define a * very safe maximum of 1000us, meaning 24000 cycles. */ do { pllcon = HWREG32(pdata->base + PLL_CON(1)); rt_hw_us_delay(100); ++count; } while (pllcon & PLLCON1_LOCK_STATUS && count < 10); if (count >= 10) { err = -RT_ETIMEOUT; } return err; } static rt_err_t rtc32k_set_parent(struct rk_clk_platform_data *pdata, struct rk_clk_platform_data *ppdata, struct rk_clk *rk_clk) { struct rk_pmuclk_priv *priv = &rk_clk->pmuclk_info; struct rk_pmucru *pmucru = priv->pmucru; if (ppdata->id == CLK_RTC32K_FRAC) { rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK, RTC32K_SEL_OSC0_DIV32K << RTC32K_SEL_SHIFT); } else { rk_clrsetreg(&pmucru->pmu_clksel_con[0], RTC32K_SEL_MASK, RTC32K_SEL_OSC1_32K << RTC32K_SEL_SHIFT); } return RT_EOK; } static rt_err_t rk_pmuclk_set_parent(struct rk_clk_platform_data *pdata, struct rk_clk_platform_data *ppdata, struct rk_clk *rk_clk) { switch (pdata->id) { case CLK_RTC_32K: return rtc32k_set_parent(pdata, ppdata, rk_clk); default: return -RT_EINVAL; } return RT_EOK; } static rt_err_t gmac0_src_set_parent(struct rk_clk_platform_data *pdata, struct rk_clk_platform_data *ppdata, struct rk_clk *rk_clk) { struct rk_clk_priv *priv = &rk_clk->clk_info; struct rk_cru *cru = priv->cru; if (ppdata->id == CLK_MAC0_2TOP) { rk_clrsetreg(&cru->clksel_con[31], RMII0_EXTCLK_SEL_MASK, RMII0_EXTCLK_SEL_MAC0_TOP << RMII0_EXTCLK_SEL_SHIFT); } else { rk_clrsetreg(&cru->clksel_con[31], RMII0_EXTCLK_SEL_MASK, RMII0_EXTCLK_SEL_IO << RMII0_EXTCLK_SEL_SHIFT); } return RT_EOK; } static rt_err_t gmac1_src_set_parent(struct rk_clk_platform_data *pdata, struct rk_clk_platform_data *ppdata, struct rk_clk *rk_clk) { struct rk_clk_priv *priv = &rk_clk->clk_info; struct rk_cru *cru = priv->cru; if (ppdata->id == CLK_MAC1_2TOP) { rk_clrsetreg(&cru->clksel_con[33], RMII0_EXTCLK_SEL_MASK, RMII0_EXTCLK_SEL_MAC0_TOP << RMII0_EXTCLK_SEL_SHIFT); } else { rk_clrsetreg(&cru->clksel_con[33], RMII0_EXTCLK_SEL_MASK, RMII0_EXTCLK_SEL_IO << RMII0_EXTCLK_SEL_SHIFT); } return RT_EOK; } static rt_err_t gmac0_tx_rx_set_parent(struct rk_clk_platform_data *pdata, struct rk_clk_platform_data *ppdata, struct rk_clk *rk_clk) { struct rk_clk_priv *priv = &rk_clk->clk_info; struct rk_cru *cru = priv->cru; if (ppdata->id == SCLK_GMAC0_RGMII_SPEED) { rk_clrsetreg(&cru->clksel_con[31], RMII0_MODE_MASK, RMII0_MODE_SEL_RGMII << RMII0_MODE_SHIFT); } else if (ppdata->id == SCLK_GMAC0_RMII_SPEED) { rk_clrsetreg(&cru->clksel_con[31], RMII0_MODE_MASK, RMII0_MODE_SEL_RMII << RMII0_MODE_SHIFT); } else { rk_clrsetreg(&cru->clksel_con[31], RMII0_MODE_MASK, RMII0_MODE_SEL_GMII << RMII0_MODE_SHIFT); } return RT_EOK; } static rt_err_t gmac1_tx_rx_set_parent(struct rk_clk_platform_data *pdata, struct rk_clk_platform_data *ppdata, struct rk_clk *rk_clk) { struct rk_clk_priv *priv = &rk_clk->clk_info; struct rk_cru *cru = priv->cru; if (ppdata->id == SCLK_GMAC1_RGMII_SPEED) { rk_clrsetreg(&cru->clksel_con[33], RMII0_MODE_MASK, RMII0_MODE_SEL_RGMII << RMII0_MODE_SHIFT); } else if (ppdata->id == SCLK_GMAC1_RMII_SPEED) { rk_clrsetreg(&cru->clksel_con[33], RMII0_MODE_MASK, RMII0_MODE_SEL_RMII << RMII0_MODE_SHIFT); } else { rk_clrsetreg(&cru->clksel_con[33], RMII0_MODE_MASK, RMII0_MODE_SEL_GMII << RMII0_MODE_SHIFT); } return RT_EOK; } static rt_err_t dclk_vop_set_parent(struct rk_clk_platform_data *pdata, struct rk_clk_platform_data *ppdata, struct rk_clk *rk_clk) { struct rk_clk_priv *priv = &rk_clk->clk_info; struct rk_cru *cru = priv->cru; rt_uint32_t con_id; switch (pdata->id) { case DCLK_VOP0: con_id = 39; break; case DCLK_VOP1: con_id = 40; break; case DCLK_VOP2: con_id = 41; break; default: return -RT_EINVAL; } if (ppdata->id == PLL_VPLL) { rk_clrsetreg(&cru->clksel_con[con_id], DCLK0_VOP_SEL_MASK, DCLK_VOP_SEL_VPLL << DCLK0_VOP_SEL_SHIFT); } else { rk_clrsetreg(&cru->clksel_con[con_id], DCLK0_VOP_SEL_MASK, DCLK_VOP_SEL_HPLL << DCLK0_VOP_SEL_SHIFT); } return RT_EOK; } static rt_err_t rkvdec_set_parent(struct rk_clk_platform_data *pdata, struct rk_clk_platform_data *ppdata, struct rk_clk *rk_clk) { struct rk_clk_priv *priv = &rk_clk->clk_info; struct rk_cru *cru = priv->cru; rt_uint32_t con_id, mask, shift; switch (pdata->id) { case ACLK_RKVDEC_PRE: con_id = 47; mask = ACLK_RKVDEC_SEL_MASK; shift = ACLK_RKVDEC_SEL_SHIFT; break; case CLK_RKVDEC_CORE: con_id = 49; mask = CLK_RKVDEC_CORE_SEL_MASK; shift = CLK_RKVDEC_CORE_SEL_SHIFT; break; default: return -RT_EINVAL; } if (ppdata->id == PLL_CPLL) { rk_clrsetreg(&cru->clksel_con[con_id], mask, ACLK_RKVDEC_SEL_CPLL << shift); } else { rk_clrsetreg(&cru->clksel_con[con_id], mask, ACLK_RKVDEC_SEL_GPLL << shift); } return RT_EOK; } static int rk_clk_set_parent(struct rk_clk_platform_data *pdata, struct rk_clk_platform_data *ppdata, struct rk_clk *rk_clk) { switch (pdata->id) { case SCLK_GMAC0: return gmac0_src_set_parent(pdata, ppdata, rk_clk); case SCLK_GMAC1: return gmac1_src_set_parent(pdata, ppdata, rk_clk); case SCLK_GMAC0_RX_TX: return gmac0_tx_rx_set_parent(pdata, ppdata, rk_clk); case SCLK_GMAC1_RX_TX: return gmac1_tx_rx_set_parent(pdata, ppdata, rk_clk); case DCLK_VOP0: case DCLK_VOP1: case DCLK_VOP2: return dclk_vop_set_parent(pdata, ppdata, rk_clk); case ACLK_RKVDEC_PRE: case CLK_RKVDEC_CORE: return rkvdec_set_parent(pdata, ppdata, rk_clk); default: return -RT_EINVAL; } return RT_EOK; } static rt_err_t mmc_set_phase(struct rk_clk_platform_data *pdata, struct rk_clk *rk_clk, rt_uint32_t degrees) { void *reg; rt_ubase_t rate; struct rk_clk_priv *priv = &rk_clk->clk_info; struct rk_cru *cru = priv->cru; rate = rk_clk_get_rate(pdata, rk_clk); switch (pdata->id) { case SCLK_SDMMC0_DRV: reg = &cru->emmc_con[0]; break; case SCLK_SDMMC0_SAMPLE: reg = &cru->emmc_con[1]; break; case SCLK_SDMMC1_DRV: reg = &cru->emmc_con[0]; break; case SCLK_SDMMC1_SAMPLE: reg = &cru->emmc_con[1]; break; case SCLK_SDMMC2_DRV: reg = &cru->emmc_con[0]; break; case SCLK_SDMMC2_SAMPLE: reg = &cru->emmc_con[1]; break; case SCLK_EMMC_DRV: reg = &cru->emmc_con[0]; break; case SCLK_EMMC_SAMPLE: reg = &cru->emmc_con[1]; break; } return rk_clk_mmc_set_phase(rate, reg, 1, degrees); } static rt_base_t mmc_get_phase(struct rk_clk_platform_data *pdata, struct rk_clk *rk_clk) { void *reg; rt_ubase_t rate; struct rk_clk_priv *priv = &rk_clk->clk_info; struct rk_cru *cru = priv->cru; rate = rk_clk_get_rate(pdata, rk_clk); switch (pdata->id) { case SCLK_SDMMC0_DRV: reg = &cru->emmc_con[0]; break; case SCLK_SDMMC0_SAMPLE: reg = &cru->emmc_con[1]; break; case SCLK_SDMMC1_DRV: reg = &cru->emmc_con[0]; break; case SCLK_SDMMC1_SAMPLE: reg = &cru->emmc_con[1]; break; case SCLK_SDMMC2_DRV: reg = &cru->emmc_con[0]; break; case SCLK_SDMMC2_SAMPLE: reg = &cru->emmc_con[1]; break; case SCLK_EMMC_DRV: reg = &cru->emmc_con[0]; break; case SCLK_EMMC_SAMPLE: reg = &cru->emmc_con[1]; break; } return rk_clk_mmc_get_phase(rate, reg, 1); } static rt_err_t rk3568_clk_init(struct rt_clk *clk, void *fw_data) { struct rk_clk *rk_clk = raw_to_rk_clk(clk->clk_np); struct rt_ofw_cell_args *args = fw_data; struct rk_clk_platform_data *pdata; rt_uint32_t clk_id = args->args[0]; rt_ubase_t reg_base; pdata = &rk_clk->pdata[clk_id]; if (rk_clk->type == rk_clk_type_pmuclk) { reg_base = (rt_ubase_t)rk_clk->pmuclk_info.pmucru; switch (clk_id) { case PLL_PPLL: reg_base += pmu_pll_clks[ppll].con_offset; break; case PLL_HPLL: reg_base += pmu_pll_clks[hpll].con_offset; break; default: reg_base = RT_NULL; break; } } else if (rk_clk->type == rk_clk_type_clk) { reg_base = (rt_ubase_t)rk_clk->clk_info.cru; switch (clk_id) { case PLL_APLL: case ARMCLK: reg_base += pll_clks[apll].con_offset; break; case PLL_CPLL: reg_base += pll_clks[cpll].con_offset; break; case PLL_GPLL: reg_base += pll_clks[gpll].con_offset; break; case PLL_NPLL: reg_base += pll_clks[npll].con_offset; break; case PLL_VPLL: reg_base += pll_clks[vpll].con_offset; break; case PLL_DPLL: reg_base += pll_clks[dpll].con_offset; break; default: reg_base = RT_NULL; break; } } else { LOG_E("Unknow type of rk clk = %d", rk_clk->type); RT_ASSERT(0); } pdata->id = clk_id; pdata->base = (void *)reg_base; clk->rate = rk_clk_get_rate(pdata, rk_clk); clk->priv = pdata; rk_clk_set_default_rates(clk, clk->clk_np->ops->set_rate, clk_id); return RT_EOK; } static rt_err_t rk3568_clk_enable(struct rt_clk *clk) { struct rk_clk_platform_data *pdata = clk->priv; struct rk_clk *rk_clk = raw_to_rk_clk(clk->clk_np); struct rk_cru *cru = rk_clk->clk_info.cru; struct rk_pmucru *pmucru = rk_clk->pmuclk_info.pmucru; if (pdata->base) { HWREG32(pdata->base + PLL_CON(1)) = HIWORD_UPDATE(0, PLLCON1_PWRDOWN, 0); rk_clk_wait_lock(pdata); } else { void *con_regs; struct rk_clk_gate *gate; if (rk_clk->type == rk_clk_type_clk) { gate = &clk_gates[pdata->id]; con_regs = &cru->clkgate_con[gate->con_idx]; } else if (rk_clk->type == rk_clk_type_pmuclk) { gate = &pmu_clk_gates[pdata->id]; con_regs = &pmucru->pmu_clkgate_con[gate->con_idx]; } else { return -RT_EINVAL; } rk_clrreg(con_regs, RT_BIT(gate->con_bit)); } return RT_EOK; } static void rk3568_clk_disable(struct rt_clk *clk) { struct rk_clk_platform_data *pdata = clk->priv; struct rk_clk *rk_clk = raw_to_rk_clk(clk->clk_np); struct rk_cru *cru = rk_clk->clk_info.cru; struct rk_pmucru *pmucru = rk_clk->pmuclk_info.pmucru; if (pdata->base) { HWREG32(pdata->base + PLL_CON(1)) = HIWORD_UPDATE(PLLCON1_PWRDOWN, PLLCON1_PWRDOWN, 0); } else { void *con_regs; struct rk_clk_gate *gate; if (rk_clk->type == rk_clk_type_clk) { gate = &clk_gates[pdata->id]; con_regs = &cru->clkgate_con[gate->con_idx]; } else if (rk_clk->type == rk_clk_type_pmuclk) { gate = &pmu_clk_gates[pdata->id]; con_regs = &pmucru->pmu_clkgate_con[gate->con_idx]; } else { return; } rk_setreg(con_regs, RT_BIT(gate->con_bit)); } } static rt_bool_t rk3568_clk_is_enabled(struct rt_clk *clk) { struct rk_clk_platform_data *pdata = clk->priv; if (pdata->base) { rt_uint32_t pllcon = HWREG32(pdata->base + PLL_CON(1)); return !(pllcon & PLLCON1_PWRDOWN); } return RT_TRUE; } static rt_err_t rk3568_clk_set_rate(struct rt_clk *clk, rt_ubase_t rate, rt_ubase_t parent_rate) { rt_ubase_t res_rate; struct rk_clk_platform_data *pdata = clk->priv; struct rk_clk *rk_clk = raw_to_rk_clk(clk->clk_np); if (rk_clk->type == rk_clk_type_clk) { res_rate = rk_clk_set_rate(pdata, rk_clk, rate); if ((rt_base_t)res_rate > 0) { clk->rate = res_rate; } } else if (rk_clk->type == rk_clk_type_pmuclk) { res_rate = rk_pmuclk_set_rate(pdata, rk_clk, rate); if ((rt_base_t)res_rate > 0) { clk->rate = res_rate; } } else { return -RT_EINVAL; } return (rt_ubase_t)res_rate > 0 ? RT_EOK : (rt_err_t)res_rate; } static rt_err_t rk3568_clk_set_parent(struct rt_clk *clk, struct rt_clk *parent) { rt_err_t err; struct rk_clk_platform_data *pdata = clk->priv, *ppdata = parent->priv; struct rk_clk *rk_clk = raw_to_rk_clk(clk->clk_np); struct rk_clk *rk_clk_parent = raw_to_rk_clk(clk->clk_np); if (rk_clk->type != rk_clk_parent->type) { return -RT_EINVAL; } if (rk_clk->type == rk_clk_type_clk) { err = rk_clk_set_parent(pdata, ppdata, rk_clk); } else if (rk_clk->type == rk_clk_type_pmuclk) { err = rk_pmuclk_set_parent(pdata, ppdata, rk_clk); } else { return -RT_EINVAL; } return err; } static rt_err_t rk3568_clk_set_phase(struct rt_clk *clk, int degrees) { rt_err_t res; struct rk_clk_platform_data *pdata = clk->priv; struct rk_clk *rk_clk = raw_to_rk_clk(clk->clk_np); switch (pdata->id) { case SCLK_SDMMC0_DRV: case SCLK_SDMMC0_SAMPLE: case SCLK_SDMMC1_DRV: case SCLK_SDMMC1_SAMPLE: case SCLK_SDMMC2_DRV: case SCLK_SDMMC2_SAMPLE: case SCLK_EMMC_DRV: case SCLK_EMMC_SAMPLE: res = mmc_set_phase(pdata, rk_clk, degrees); break; default: return -RT_EINVAL; } return res; } static rt_base_t rk3568_clk_get_phase(struct rt_clk *clk) { rt_base_t res; struct rk_clk_platform_data *pdata = clk->priv; struct rk_clk *rk_clk = raw_to_rk_clk(clk->clk_np); switch (pdata->id) { case SCLK_SDMMC0_DRV: case SCLK_SDMMC0_SAMPLE: case SCLK_SDMMC1_DRV: case SCLK_SDMMC1_SAMPLE: case SCLK_SDMMC2_DRV: case SCLK_SDMMC2_SAMPLE: case SCLK_EMMC_DRV: case SCLK_EMMC_SAMPLE: res = mmc_get_phase(pdata, rk_clk); break; default: return -RT_EINVAL; } return res; } static rt_base_t rk3568_clk_round_rate(struct rt_clk *clk, rt_ubase_t drate, rt_ubase_t *prate) { return rk_clk_pll_round_rate(pll_rates, RT_ARRAY_SIZE(pll_rates), drate, prate); } static const struct rt_clk_ops rk3568_clk_ops = { .init = rk3568_clk_init, .enable = rk3568_clk_enable, .disable = rk3568_clk_disable, .is_enabled = rk3568_clk_is_enabled, .set_rate = rk3568_clk_set_rate, .set_parent = rk3568_clk_set_parent, .set_phase = rk3568_clk_set_phase, .get_phase = rk3568_clk_get_phase, .round_rate = rk3568_clk_round_rate, }; static void rk3568_clk_type_init(struct rk_clk *rk_clk, struct rt_ofw_node *np) { rt_ubase_t cpu_freq = APLL_HZ; struct rk_clk_priv *priv = &rk_clk->clk_info; const char *rockchip_cpu_freq = rt_ofw_bootargs_select("rockchip.cpu_freq=", 0); priv->cru = (struct rk_cru *)rk_clk->base; if (!priv->armclk_enter_hz) { priv->armclk_enter_hz = rk_pll_get_rate(&pll_clks[apll], &priv->cru); priv->armclk_init_hz = priv->armclk_enter_hz; } if (rockchip_cpu_freq) { cpu_freq = atol(rockchip_cpu_freq); } else { cpu_freq = 1800000000; } if (!armclk_set_clk(priv, cpu_freq)) { priv->armclk_init_hz = cpu_freq; } if (priv->cpll_hz != CPLL_HZ) { if (!rk_pll_set_rate(&pll_clks[cpll], priv->cru, CPLL_HZ)) { priv->cpll_hz = CPLL_HZ; } } if (priv->gpll_hz != GPLL_HZ) { if (!rk_pll_set_rate(&pll_clks[gpll], priv->cru, GPLL_HZ)) { priv->gpll_hz = GPLL_HZ; } } priv->ppll_hz = pmu_pll_get_rate(ppll); priv->hpll_hz = pmu_pll_get_rate(hpll); } static void rk3568_pmu_clk_type_init(struct rk_clk *rk_clk, struct rt_ofw_node *np) { struct rk_pmuclk_priv *priv = &rk_clk->pmuclk_info; priv->pmucru = (struct rk_pmucru *)rk_clk->base; if (priv->ppll_hz != PPLL_HZ) { if (!rk_pll_set_rate(&pmu_pll_clks[ppll], priv->pmucru, PPLL_HZ)) { priv->ppll_hz = PPLL_HZ; } } /* Ungate PCIe30phy refclk_m and refclk_n */ rk_clrsetreg(&priv->pmucru->pmu_clkgate_con[2], 0x3 << 13, 0 << 13); } static rt_err_t clk_rk3568_probe(struct rt_platform_device *pdev) { rt_err_t err; rt_size_t data_size = 0; struct rk_clk *rk_clk; struct rt_ofw_node *np = pdev->parent.ofw_node; enum rk_clk_type type = (rt_ubase_t)pdev->id->data; if (type == rk_clk_type_clk) { data_size = CLK_NR_CLKS; } else if (type == rk_clk_type_pmuclk) { data_size = CLKPMU_NR_CLKS; } data_size *= sizeof(struct rk_clk_platform_data); rk_clk = rt_malloc(sizeof(*rk_clk) + data_size); if (rk_clk) { void *softrst_regs = RT_NULL; rt_memset(&rk_clk->parent, 0, sizeof(rk_clk->parent)); rk_clk->base = rt_ofw_iomap(np, 0); if (!rk_clk->base) { err = -RT_EIO; goto _fail; } if (type == rk_clk_type_clk) { rk_clk->type = rk_clk_type_clk; rk3568_clk_type_init(rk_clk, np); softrst_regs = &rk_clk->clk_info.cru->softrst_con; } else if (type == rk_clk_type_pmuclk) { rk_clk->type = rk_clk_type_pmuclk; rk3568_pmu_clk_type_init(rk_clk, np); softrst_regs = &rk_clk->pmuclk_info.pmucru->pmu_softrst_con; } rk_clk->parent.parent.ops = &rk3568_clk_ops; if ((err = rt_clk_register(&rk_clk->parent.parent, RT_NULL))) { goto _fail; } if ((err = rk_register_softrst(&rk_clk->parent.rstcer, np, softrst_regs, ROCKCHIP_SOFTRST_HIWORD_MASK))) { goto _fail; } rt_ofw_data(np) = &rk_clk->parent; } else { err = -RT_ENOMEM; } return err; _fail: if (rk_clk->base) { rt_iounmap(rk_clk->base); } rt_free(rk_clk); return err; } static const struct rt_ofw_node_id clk_rk3568_ofw_ids[] = { { .compatible = "rockchip,rk3568-cru", .data = (void *)rk_clk_type_clk }, { .compatible = "rockchip,rk3568-pmucru", .data = (void *)rk_clk_type_pmuclk }, { /* sentinel */ } }; static struct rt_platform_driver clk_rk3568_driver = { .name = "clk-rk3568", .ids = clk_rk3568_ofw_ids, .probe = clk_rk3568_probe, }; static int clk_rk3568_register(void) { rt_platform_driver_register(&clk_rk3568_driver); return 0; } INIT_SUBSYS_EXPORT(clk_rk3568_register);