4801 lines
139 KiB
C
4801 lines
139 KiB
C
/*
|
|
* 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 <rtdbg.h>
|
|
|
|
#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 <<SCLK_CORE_SRC_SEL_SHIFT) |
|
|
(1 << SCLK_CORE_SRC_DIV_SHIFT));
|
|
|
|
/*
|
|
* set up dependent divisors for DBG and ACLK clocks.
|
|
*/
|
|
old_rate = rk_pll_get_rate(&pll_clks[apll], &priv->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);
|