rockchip: clk: add px30 clock driver

A patch from »rockchip: add support for px30« in state Mainline for u-boot

From: Kever Yang <kever.yang@...> Date: Thu, 11 Jul 2019 10:42:16 +0200

Commit-Message

The px30 contains 2 separate clock controllers, pmucru and cru. Add drivers for them. Signed-off-by: Kever Yang <kever.yang@...> Signed-off-by: Heiko Stuebner <heiko.stuebner@...>

Patch-Comment

arch/arm/include/asm/arch-rockchip/cru_px30.h | 432 +++++ drivers/clk/rockchip/Makefile | 1 + drivers/clk/rockchip/clk_px30.c | 1630 +++++++++++++++++ include/dt-bindings/clock/px30-cru.h | 389 ++++ 4 files changed, 2452 insertions(+) create mode 100644 arch/arm/include/asm/arch-rockchip/cru_px30.h create mode 100644 drivers/clk/rockchip/clk_px30.c create mode 100644 include/dt-bindings/clock/px30-cru.h

Statistics

  • 2452 lines added
  • 0 lines removed

Changes

---------------- arch/arm/include/asm/arch-rockchip/cru_px30.h -----------------
new file mode 100644
index 0000000000..7d9fd181ac
@@ -0,0 +1,432 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd.
+ */
+#ifndef _ASM_ARCH_CRU_PX30_H
+#define _ASM_ARCH_CRU_PX30_H
+
+#include <common.h>
+
+#define MHz 1000000
+#define KHz 1000
+#define OSC_HZ (24 * MHz)
+
+#define APLL_HZ (600 * MHz)
+#define GPLL_HZ (1200 * MHz)
+#define NPLL_HZ (1188 * MHz)
+#define ACLK_BUS_HZ (200 * MHz)
+#define HCLK_BUS_HZ (150 * MHz)
+#define PCLK_BUS_HZ (100 * MHz)
+#define ACLK_PERI_HZ (200 * MHz)
+#define HCLK_PERI_HZ (150 * MHz)
+#define PCLK_PMU_HZ (100 * MHz)
+
+/* PX30 pll id */
+enum px30_pll_id {
+ APLL,
+ DPLL,
+ CPLL,
+ NPLL,
+ GPLL,
+ PLL_COUNT,
+};
+
+struct px30_clk_priv {
+ struct px30_cru *cru;
+ ulong gpll_hz;
+};
+
+struct px30_pmuclk_priv {
+ struct px30_pmucru *pmucru;
+ ulong gpll_hz;
+};
+
+struct px30_pll {
+ unsigned int con0;
+ unsigned int con1;
+ unsigned int con2;
+ unsigned int con3;
+ unsigned int con4;
+ unsigned int reserved0[3];
+};
+
+struct px30_cru {
+ struct px30_pll pll[4];
+ unsigned int reserved1[8];
+ unsigned int mode;
+ unsigned int misc;
+ unsigned int reserved2[2];
+ unsigned int glb_cnt_th;
+ unsigned int glb_rst_st;
+ unsigned int glb_srst_fst;
+ unsigned int glb_srst_snd;
+ unsigned int glb_rst_con;
+ unsigned int reserved3[7];
+ unsigned int hwffc_con0;
+ unsigned int reserved4;
+ unsigned int hwffc_th;
+ unsigned int hwffc_intst;
+ unsigned int apll_con0_s;
+ unsigned int apll_con1_s;
+ unsigned int clksel_con0_s;
+ unsigned int reserved5;
+ unsigned int clksel_con[60];
+ unsigned int reserved6[4];
+ unsigned int clkgate_con[18];
+ unsigned int reserved7[(0x280 - 0x244) / 4 - 1];
+ unsigned int ssgtbl[32];
+ unsigned int softrst_con[12];
+ unsigned int reserved8[(0x380 - 0x32c) / 4 - 1];
+ unsigned int sdmmc_con[2];
+ unsigned int sdio_con[2];
+ unsigned int emmc_con[2];
+ unsigned int reserved9[(0x400 - 0x394) / 4 - 1];
+ unsigned int autocs_con[8];
+};
+
+check_member(px30_cru, autocs_con[7], 0x41c);
+
+struct px30_pmucru {
+ struct px30_pll pll;
+ unsigned int pmu_mode;
+ unsigned int reserved1[7];
+ unsigned int pmu_clksel_con[6];
+ unsigned int reserved2[10];
+ unsigned int pmu_clkgate_con[2];
+ unsigned int reserved3[14];
+ unsigned int pmu_autocs_con[2];
+};
+
+check_member(px30_pmucru, pmu_autocs_con[1], 0xc4);
+
+struct pll_rate_table {
+ unsigned long rate;
+ unsigned int fbdiv;
+ unsigned int postdiv1;
+ unsigned int refdiv;
+ unsigned int postdiv2;
+ unsigned int dsmpd;
+ unsigned int frac;
+};
+
+struct cpu_rate_table {
+ unsigned long rate;
+ unsigned int aclk_div;
+ unsigned int pclk_div;
+};
+
+enum {
+ /* PLLCON0*/
+ PLL_BP_SHIFT = 15,
+ PLL_POSTDIV1_SHIFT = 12,
+ PLL_POSTDIV1_MASK = 7 << PLL_POSTDIV1_SHIFT,
+ PLL_FBDIV_SHIFT = 0,
+ PLL_FBDIV_MASK = 0xfff,
+
+ /* PLLCON1 */
+ PLL_PDSEL_SHIFT = 15,
+ PLL_PD1_SHIFT = 14,
+ PLL_PD_SHIFT = 13,
+ PLL_PD_MASK = 1 << PLL_PD_SHIFT,
+ PLL_DSMPD_SHIFT = 12,
+ PLL_DSMPD_MASK = 1 << PLL_DSMPD_SHIFT,
+ PLL_LOCK_STATUS_SHIFT = 10,
+ PLL_LOCK_STATUS_MASK = 1 << PLL_LOCK_STATUS_SHIFT,
+ PLL_POSTDIV2_SHIFT = 6,
+ PLL_POSTDIV2_MASK = 7 << PLL_POSTDIV2_SHIFT,
+ PLL_REFDIV_SHIFT = 0,
+ PLL_REFDIV_MASK = 0x3f,
+
+ /* PLLCON2 */
+ PLL_FOUT4PHASEPD_SHIFT = 27,
+ PLL_FOUTVCOPD_SHIFT = 26,
+ PLL_FOUTPOSTDIVPD_SHIFT = 25,
+ PLL_DACPD_SHIFT = 24,
+ PLL_FRAC_DIV = 0xffffff,
+
+ /* CRU_MODE */
+ PLLMUX_FROM_XIN24M = 0,
+ PLLMUX_FROM_PLL,
+ PLLMUX_FROM_RTC32K,
+ USBPHY480M_MODE_SHIFT = 8,
+ USBPHY480M_MODE_MASK = 3 << USBPHY480M_MODE_SHIFT,
+ NPLL_MODE_SHIFT = 6,
+ NPLL_MODE_MASK = 3 << NPLL_MODE_SHIFT,
+ DPLL_MODE_SHIFT = 4,
+ DPLL_MODE_MASK = 3 << DPLL_MODE_SHIFT,
+ CPLL_MODE_SHIFT = 2,
+ CPLL_MODE_MASK = 3 << CPLL_MODE_SHIFT,
+ APLL_MODE_SHIFT = 0,
+ APLL_MODE_MASK = 3 << APLL_MODE_SHIFT,
+
+ /* CRU_CLK_SEL0_CON */
+ CORE_ACLK_DIV_SHIFT = 12,
+ CORE_ACLK_DIV_MASK = 0x07 << CORE_ACLK_DIV_SHIFT,
+ CORE_DBG_DIV_SHIFT = 8,
+ CORE_DBG_DIV_MASK = 0x03 << CORE_DBG_DIV_SHIFT,
+ CORE_CLK_PLL_SEL_SHIFT = 7,
+ CORE_CLK_PLL_SEL_MASK = 1 << CORE_CLK_PLL_SEL_SHIFT,
+ CORE_CLK_PLL_SEL_APLL = 0,
+ CORE_CLK_PLL_SEL_GPLL,
+ CORE_DIV_CON_SHIFT = 0,
+ CORE_DIV_CON_MASK = 0x0f << CORE_DIV_CON_SHIFT,
+
+ /* CRU_CLK_SEL3_CON */
+ ACLK_VO_PLL_SHIFT = 6,
+ ACLK_VO_PLL_MASK = 0x3 << ACLK_VO_PLL_SHIFT,
+ ACLK_VO_SEL_GPLL = 0,
+ ACLK_VO_SEL_CPLL,
+ ACLK_VO_SEL_NPLL,
+ ACLK_VO_DIV_SHIFT = 0,
+ ACLK_VO_DIV_MASK = 0x1f << ACLK_VO_DIV_SHIFT,
+
+ /* CRU_CLK_SEL5_CON */
+ DCLK_VOPB_SEL_SHIFT = 14,
+ DCLK_VOPB_SEL_MASK = 0x3 << DCLK_VOPB_SEL_SHIFT,
+ DCLK_VOPB_SEL_DIVOUT = 0,
+ DCLK_VOPB_SEL_FRACOUT,
+ DCLK_VOPB_SEL_24M,
+ DCLK_VOPB_PLL_SEL_SHIFT = 11,
+ DCLK_VOPB_PLL_SEL_MASK = 0x1 << DCLK_VOPB_PLL_SEL_SHIFT,
+ DCLK_VOPB_PLL_SEL_CPLL = 0,
+ DCLK_VOPB_PLL_SEL_NPLL,
+ DCLK_VOPB_DIV_SHIFT = 0,
+ DCLK_VOPB_DIV_MASK = 0xff,
+
+ /* CRU_CLK_SEL8_CON */
+ DCLK_VOPL_SEL_SHIFT = 14,
+ DCLK_VOPL_SEL_MASK = 0x3 << DCLK_VOPL_SEL_SHIFT,
+ DCLK_VOPL_SEL_DIVOUT = 0,
+ DCLK_VOPL_SEL_FRACOUT,
+ DCLK_VOPL_SEL_24M,
+ DCLK_VOPL_PLL_SEL_SHIFT = 11,
+ DCLK_VOPL_PLL_SEL_MASK = 0x1 << DCLK_VOPL_PLL_SEL_SHIFT,
+ DCLK_VOPL_PLL_SEL_NPLL = 0,
+ DCLK_VOPL_PLL_SEL_CPLL,
+ DCLK_VOPL_DIV_SHIFT = 0,
+ DCLK_VOPL_DIV_MASK = 0xff,
+
+ /* CRU_CLK_SEL14_CON */
+ PERI_PLL_SEL_SHIFT = 15,
+ PERI_PLL_SEL_MASK = 3 << PERI_PLL_SEL_SHIFT,
+ PERI_PLL_GPLL = 0,
+ PERI_PLL_CPLL,
+ PERI_HCLK_DIV_SHIFT = 8,
+ PERI_HCLK_DIV_MASK = 0x1f << PERI_HCLK_DIV_SHIFT,
+ PERI_ACLK_DIV_SHIFT = 0,
+ PERI_ACLK_DIV_MASK = 0x1f << PERI_ACLK_DIV_SHIFT,
+
+ /* CRU_CLKSEL15_CON */
+ NANDC_CLK_SEL_SHIFT = 15,
+ NANDC_CLK_SEL_MASK = 0x1 << NANDC_CLK_SEL_SHIFT,
+ NANDC_CLK_SEL_NANDC = 0,
+ NANDC_CLK_SEL_NANDC_DIV50,
+ NANDC_DIV50_SHIFT = 8,
+ NANDC_DIV50_MASK = 0x1f << NANDC_DIV50_SHIFT,
+ NANDC_PLL_SHIFT = 6,
+ NANDC_PLL_MASK = 0x3 << NANDC_PLL_SHIFT,
+ NANDC_SEL_GPLL = 0,
+ NANDC_SEL_CPLL,
+ NANDC_SEL_NPLL,
+ NANDC_DIV_SHIFT = 0,
+ NANDC_DIV_MASK = 0x1f << NANDC_DIV_SHIFT,
+
+ /* CRU_CLKSEL20_CON */
+ EMMC_PLL_SHIFT = 14,
+ EMMC_PLL_MASK = 3 << EMMC_PLL_SHIFT,
+ EMMC_SEL_GPLL = 0,
+ EMMC_SEL_CPLL,
+ EMMC_SEL_NPLL,
+ EMMC_SEL_24M,
+ EMMC_DIV_SHIFT = 0,
+ EMMC_DIV_MASK = 0xff << EMMC_DIV_SHIFT,
+
+ /* CRU_CLKSEL21_CON */
+ EMMC_CLK_SEL_SHIFT = 15,
+ EMMC_CLK_SEL_MASK = 1 << EMMC_CLK_SEL_SHIFT,
+ EMMC_CLK_SEL_EMMC = 0,
+ EMMC_CLK_SEL_EMMC_DIV50,
+ EMMC_DIV50_SHIFT = 0,
+ EMMC_DIV50_MASK = 0xff << EMMC_DIV_SHIFT,
+
+ /* CRU_CLKSEL22_CON */
+ GMAC_PLL_SEL_SHIFT = 14,
+ GMAC_PLL_SEL_MASK = 3 << GMAC_PLL_SEL_SHIFT,
+ GMAC_PLL_SEL_GPLL = 0,
+ GMAC_PLL_SEL_CPLL,
+ GMAC_PLL_SEL_NPLL,
+ CLK_GMAC_DIV_SHIFT = 8,
+ CLK_GMAC_DIV_MASK = 0x1f << CLK_GMAC_DIV_SHIFT,
+ SFC_PLL_SEL_SHIFT = 7,
+ SFC_PLL_SEL_MASK = 1 << SFC_PLL_SEL_SHIFT,
+ SFC_DIV_CON_SHIFT = 0,
+ SFC_DIV_CON_MASK = 0x7f,
+
+ /* CRU_CLK_SEL23_CON */
+ BUS_PLL_SEL_SHIFT = 15,
+ BUS_PLL_SEL_MASK = 1 << BUS_PLL_SEL_SHIFT,
+ BUS_PLL_SEL_GPLL = 0,
+ BUS_PLL_SEL_CPLL,
+ BUS_ACLK_DIV_SHIFT = 8,
+ BUS_ACLK_DIV_MASK = 0x1f << BUS_ACLK_DIV_SHIFT,
+ RMII_CLK_SEL_SHIFT = 7,
+ RMII_CLK_SEL_MASK = 1 << RMII_CLK_SEL_SHIFT,
+ RMII_CLK_SEL_10M = 0,
+ RMII_CLK_SEL_100M,
+ RMII_EXTCLK_SEL_SHIFT = 6,
+ RMII_EXTCLK_SEL_MASK = 1 << RMII_EXTCLK_SEL_SHIFT,
+ RMII_EXTCLK_SEL_INT = 0,
+ RMII_EXTCLK_SEL_EXT,
+ PCLK_GMAC_DIV_SHIFT = 0,
+ PCLK_GMAC_DIV_MASK = 0x0f << PCLK_GMAC_DIV_SHIFT,
+
+ /* CRU_CLK_SEL24_CON */
+ BUS_PCLK_DIV_SHIFT = 8,
+ BUS_PCLK_DIV_MASK = 3 << BUS_PCLK_DIV_SHIFT,
+ BUS_HCLK_DIV_SHIFT = 0,
+ BUS_HCLK_DIV_MASK = 0x1f << BUS_HCLK_DIV_SHIFT,
+
+ /* CRU_CLK_SEL25_CON */
+ CRYPTO_APK_SEL_SHIFT = 14,
+ CRYPTO_APK_PLL_SEL_MASK = 3 << CRYPTO_APK_SEL_SHIFT,
+ CRYPTO_PLL_SEL_GPLL = 0,
+ CRYPTO_PLL_SEL_CPLL,
+ CRYPTO_PLL_SEL_NPLL = 0,
+ CRYPTO_APK_DIV_SHIFT = 8,
+ CRYPTO_APK_DIV_MASK = 0x1f << CRYPTO_APK_DIV_SHIFT,
+ CRYPTO_PLL_SEL_SHIFT = 6,
+ CRYPTO_PLL_SEL_MASK = 3 << CRYPTO_PLL_SEL_SHIFT,
+ CRYPTO_DIV_SHIFT = 0,
+ CRYPTO_DIV_MASK = 0x1f << CRYPTO_DIV_SHIFT,
+
+ /* CRU_CLK_SEL30_CON */
+ CLK_I2S1_DIV_CON_MASK = 0x7f,
+ CLK_I2S1_PLL_SEL_MASK = 0X1 << 8,
+ CLK_I2S1_PLL_SEL_GPLL = 0X0 << 8,
+ CLK_I2S1_PLL_SEL_NPLL = 0X1 << 8,
+ CLK_I2S1_SEL_MASK = 0x3 << 10,
+ CLK_I2S1_SEL_I2S1 = 0x0 << 10,
+ CLK_I2S1_SEL_FRAC = 0x1 << 10,
+ CLK_I2S1_SEL_MCLK_IN = 0x2 << 10,
+ CLK_I2S1_SEL_OSC = 0x3 << 10,
+ CLK_I2S1_OUT_SEL_MASK = 0x1 << 15,
+ CLK_I2S1_OUT_SEL_I2S1 = 0x0 << 15,
+ CLK_I2S1_OUT_SEL_OSC = 0x1 << 15,
+
+ /* CRU_CLK_SEL31_CON */
+ CLK_I2S1_FRAC_NUMERATOR_SHIFT = 16,
+ CLK_I2S1_FRAC_NUMERATOR_MASK = 0xffff << 16,
+ CLK_I2S1_FRAC_DENOMINATOR_SHIFT = 0,
+ CLK_I2S1_FRAC_DENOMINATOR_MASK = 0xffff,
+
+ /* CRU_CLK_SEL34_CON */
+ UART1_PLL_SEL_SHIFT = 14,
+ UART1_PLL_SEL_MASK = 3 << UART1_PLL_SEL_SHIFT,
+ UART1_PLL_SEL_GPLL = 0,
+ UART1_PLL_SEL_24M,
+ UART1_PLL_SEL_480M,
+ UART1_PLL_SEL_NPLL,
+ UART1_DIV_CON_SHIFT = 0,
+ UART1_DIV_CON_MASK = 0x1f << UART1_DIV_CON_SHIFT,
+
+ /* CRU_CLK_SEL35_CON */
+ UART1_CLK_SEL_SHIFT = 14,
+ UART1_CLK_SEL_MASK = 3 << UART1_PLL_SEL_SHIFT,
+ UART1_CLK_SEL_UART1 = 0,
+ UART1_CLK_SEL_UART1_NP5,
+ UART1_CLK_SEL_UART1_FRAC,
+ UART1_DIVNP5_SHIFT = 0,
+ UART1_DIVNP5_MASK = 0x1f << UART1_DIVNP5_SHIFT,
+
+ /* CRU_CLK_SEL37_CON */
+ UART2_PLL_SEL_SHIFT = 14,
+ UART2_PLL_SEL_MASK = 3 << UART2_PLL_SEL_SHIFT,
+ UART2_PLL_SEL_GPLL = 0,
+ UART2_PLL_SEL_24M,
+ UART2_PLL_SEL_480M,
+ UART2_PLL_SEL_NPLL,
+ UART2_DIV_CON_SHIFT = 0,
+ UART2_DIV_CON_MASK = 0x1f << UART2_DIV_CON_SHIFT,
+
+ /* CRU_CLK_SEL38_CON */
+ UART2_CLK_SEL_SHIFT = 14,
+ UART2_CLK_SEL_MASK = 3 << UART2_PLL_SEL_SHIFT,
+ UART2_CLK_SEL_UART2 = 0,
+ UART2_CLK_SEL_UART2_NP5,
+ UART2_CLK_SEL_UART2_FRAC,
+ UART2_DIVNP5_SHIFT = 0,
+ UART2_DIVNP5_MASK = 0x1f << UART2_DIVNP5_SHIFT,
+
+ /* CRU_CLK_SEL46_CON */
+ UART5_PLL_SEL_SHIFT = 14,
+ UART5_PLL_SEL_MASK = 3 << UART5_PLL_SEL_SHIFT,
+ UART5_PLL_SEL_GPLL = 0,
+ UART5_PLL_SEL_24M,
+ UART5_PLL_SEL_480M,
+ UART5_PLL_SEL_NPLL,
+ UART5_DIV_CON_SHIFT = 0,
+ UART5_DIV_CON_MASK = 0x1f << UART5_DIV_CON_SHIFT,
+
+ /* CRU_CLK_SEL47_CON */
+ UART5_CLK_SEL_SHIFT = 14,
+ UART5_CLK_SEL_MASK = 3 << UART5_PLL_SEL_SHIFT,
+ UART5_CLK_SEL_UART5 = 0,
+ UART5_CLK_SEL_UART5_NP5,
+ UART5_CLK_SEL_UART5_FRAC,
+ UART5_DIVNP5_SHIFT = 0,
+ UART5_DIVNP5_MASK = 0x1f << UART5_DIVNP5_SHIFT,
+
+ /* CRU_CLK_SEL49_CON */
+ CLK_I2C_PLL_SEL_GPLL = 0,
+ CLK_I2C_PLL_SEL_24M,
+ CLK_I2C_DIV_CON_MASK = 0x7f,
+ CLK_I2C_PLL_SEL_MASK = 1,
+ CLK_I2C1_PLL_SEL_SHIFT = 15,
+ CLK_I2C1_DIV_CON_SHIFT = 8,
+ CLK_I2C0_PLL_SEL_SHIFT = 7,
+ CLK_I2C0_DIV_CON_SHIFT = 0,
+
+ /* CRU_CLK_SEL50_CON */
+ CLK_I2C3_PLL_SEL_SHIFT = 15,
+ CLK_I2C3_DIV_CON_SHIFT = 8,
+ CLK_I2C2_PLL_SEL_SHIFT = 7,
+ CLK_I2C2_DIV_CON_SHIFT = 0,
+
+ /* CRU_CLK_SEL52_CON */
+ CLK_PWM_PLL_SEL_GPLL = 0,
+ CLK_PWM_PLL_SEL_24M,
+ CLK_PWM_DIV_CON_MASK = 0x7f,
+ CLK_PWM_PLL_SEL_MASK = 1,
+ CLK_PWM1_PLL_SEL_SHIFT = 15,
+ CLK_PWM1_DIV_CON_SHIFT = 8,
+ CLK_PWM0_PLL_SEL_SHIFT = 7,
+ CLK_PWM0_DIV_CON_SHIFT = 0,
+
+ /* CRU_CLK_SEL53_CON */
+ CLK_SPI_PLL_SEL_GPLL = 0,
+ CLK_SPI_PLL_SEL_24M,
+ CLK_SPI_DIV_CON_MASK = 0x7f,
+ CLK_SPI_PLL_SEL_MASK = 1,
+ CLK_SPI1_PLL_SEL_SHIFT = 15,
+ CLK_SPI1_DIV_CON_SHIFT = 8,
+ CLK_SPI0_PLL_SEL_SHIFT = 7,
+ CLK_SPI0_DIV_CON_SHIFT = 0,
+
+ /* CRU_CLK_SEL55_CON */
+ CLK_SARADC_DIV_CON_SHIFT = 0,
+ CLK_SARADC_DIV_CON_MASK = 0x7ff,
+
+ /* CRU_CLK_GATE10_CON */
+ CLK_I2S1_OUT_MCLK_PAD_MASK = 0x1 << 9,
+ CLK_I2S1_OUT_MCLK_PAD_ENABLE = 0x1 << 9,
+ CLK_I2S1_OUT_MCLK_PAD_DISABLE = 0x0 << 9,
+
+ /* CRU_PMU_MODE */
+ GPLL_MODE_SHIFT = 0,
+ GPLL_MODE_MASK = 3 << GPLL_MODE_SHIFT,
+
+ /* CRU_PMU_CLK_SEL0_CON */
+ CLK_PMU_PCLK_DIV_SHIFT = 0,
+ CLK_PMU_PCLK_DIV_MASK = 0x1f << CLK_PMU_PCLK_DIV_SHIFT,
+};
+#endif
------------------------ drivers/clk/rockchip/Makefile -------------------------
index 41cfb7ad3f..f9134fd51f 100644
@@ -3,6 +3,7 @@
# Copyright (c) 2017 Rockchip Electronics Co., Ltd
#
+obj-$(CONFIG_ROCKCHIP_PX30) += clk_px30.o
obj-$(CONFIG_ROCKCHIP_RK3036) += clk_rk3036.o
obj-$(CONFIG_ROCKCHIP_RK3128) += clk_rk3128.o
obj-$(CONFIG_ROCKCHIP_RK3188) += clk_rk3188.o
----------------------- drivers/clk/rockchip/clk_px30.c ------------------------
new file mode 100644
index 0000000000..36764c128b
@@ -0,0 +1,1630 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * (C) Copyright 2017 Rockchip Electronics Co., Ltd
+ */
+
+#include <common.h>
+#include <bitfield.h>
+#include <clk-uclass.h>
+#include <dm.h>
+#include <errno.h>
+#include <syscon.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_px30.h>
+#include <asm/arch-rockchip/hardware.h>
+#include <asm/io.h>
+#include <dm/lists.h>
+#include <dt-bindings/clock/px30-cru.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+ VCO_MAX_HZ = 3200U * 1000000,
+ VCO_MIN_HZ = 800 * 1000000,
+ OUTPUT_MAX_HZ = 3200U * 1000000,
+ OUTPUT_MIN_HZ = 24 * 1000000,
+};
+
+#define PX30_VOP_PLL_LIMIT 600000000
+
+#define PX30_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \
+ _postdiv2, _dsmpd, _frac) \
+{ \
+ .rate = _rate##U, \
+ .fbdiv = _fbdiv, \
+ .postdiv1 = _postdiv1, \
+ .refdiv = _refdiv, \
+ .postdiv2 = _postdiv2, \
+ .dsmpd = _dsmpd, \
+ .frac = _frac, \
+}
+
+#define PX30_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \
+{ \
+ .rate = _rate##U, \
+ .aclk_div = _aclk_div, \
+ .pclk_div = _pclk_div, \
+}
+
+#define DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1))
+
+#define PX30_CLK_DUMP(_id, _name, _iscru) \
+{ \
+ .id = _id, \
+ .name = _name, \
+ .is_cru = _iscru, \
+}
+
+static struct pll_rate_table px30_pll_rates[] = {
+ /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
+ PX30_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
+ PX30_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
+ PX30_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
+ PX30_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
+ PX30_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
+ PX30_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0),
+ PX30_PLL_RATE(600000000, 1, 75, 3, 1, 1, 0),
+};
+
+static struct cpu_rate_table px30_cpu_rates[] = {
+ PX30_CPUCLK_RATE(1200000000, 1, 5),
+ PX30_CPUCLK_RATE(1008000000, 1, 5),
+ PX30_CPUCLK_RATE(816000000, 1, 3),
+ PX30_CPUCLK_RATE(600000000, 1, 3),
+ PX30_CPUCLK_RATE(408000000, 1, 1),
+};
+
+static u8 pll_mode_shift[PLL_COUNT] = {
+ APLL_MODE_SHIFT, DPLL_MODE_SHIFT, CPLL_MODE_SHIFT,
+ NPLL_MODE_SHIFT, GPLL_MODE_SHIFT
+};
+
+static u32 pll_mode_mask[PLL_COUNT] = {
+ APLL_MODE_MASK, DPLL_MODE_MASK, CPLL_MODE_MASK,
+ NPLL_MODE_MASK, GPLL_MODE_MASK
+};
+
+static struct pll_rate_table auto_table;
+
+static ulong px30_clk_get_pll_rate(struct px30_clk_priv *priv,
+ enum px30_pll_id pll_id);
+
+static struct pll_rate_table *pll_clk_set_by_auto(u32 drate)
+{
+ struct pll_rate_table *rate = &auto_table;
+ u32 ref_khz = OSC_HZ / KHz, refdiv, fbdiv = 0;
+ u32 postdiv1, postdiv2 = 1;
+ u32 fref_khz;
+ u32 diff_khz, best_diff_khz;
+ const u32 max_refdiv = 63, max_fbdiv = 3200, min_fbdiv = 16;
+ const u32 max_postdiv1 = 7, max_postdiv2 = 7;
+ u32 vco_khz;
+ u32 rate_khz = drate / KHz;
+
+ if (!drate) {
+ printf("%s: the frequency can't be 0 Hz\n", __func__);
+ return NULL;
+ }
+
+ postdiv1 = DIV_ROUND_UP(VCO_MIN_HZ / 1000, rate_khz);
+ if (postdiv1 > max_postdiv1) {
+ postdiv2 = DIV_ROUND_UP(postdiv1, max_postdiv1);
+ postdiv1 = DIV_ROUND_UP(postdiv1, postdiv2);
+ }
+
+ vco_khz = rate_khz * postdiv1 * postdiv2;
+
+ if (vco_khz < (VCO_MIN_HZ / KHz) || vco_khz > (VCO_MAX_HZ / KHz) ||
+ postdiv2 > max_postdiv2) {
+ printf("%s: Cannot find out a supported VCO for Freq (%uHz)\n",
+ __func__, rate_khz);
+ return NULL;
+ }
+
+ rate->postdiv1 = postdiv1;
+ rate->postdiv2 = postdiv2;
+
+ best_diff_khz = vco_khz;
+ for (refdiv = 1; refdiv < max_refdiv && best_diff_khz; refdiv++) {
+ fref_khz = ref_khz / refdiv;
+
+ fbdiv = vco_khz / fref_khz;
+ if (fbdiv >= max_fbdiv || fbdiv <= min_fbdiv)
+ continue;
+
+ diff_khz = vco_khz - fbdiv * fref_khz;
+ if (fbdiv + 1 < max_fbdiv && diff_khz > fref_khz / 2) {
+ fbdiv++;
+ diff_khz = fref_khz - diff_khz;
+ }
+
+ if (diff_khz >= best_diff_khz)
+ continue;
+
+ best_diff_khz = diff_khz;
+ rate->refdiv = refdiv;
+ rate->fbdiv = fbdiv;
+ }
+
+ if (best_diff_khz > 4 * (MHz / KHz)) {
+ printf("%s: Failed to match output frequency %u bestis %u Hz\n",
+ __func__, rate_khz,
+ best_diff_khz * KHz);
+ return NULL;
+ }
+
+ return rate;
+}
+
+static const struct pll_rate_table *get_pll_settings(unsigned long rate)
+{
+ unsigned int rate_count = ARRAY_SIZE(px30_pll_rates);
+ int i;
+
+ for (i = 0; i < rate_count; i++) {
+ if (rate == px30_pll_rates[i].rate)
+ return &px30_pll_rates[i];
+ }
+
+ return pll_clk_set_by_auto(rate);
+}
+
+static const struct cpu_rate_table *get_cpu_settings(unsigned long rate)
+{
+ unsigned int rate_count = ARRAY_SIZE(px30_cpu_rates);
+ int i;
+
+ for (i = 0; i < rate_count; i++) {
+ if (rate == px30_cpu_rates[i].rate)
+ return &px30_cpu_rates[i];
+ }
+
+ return NULL;
+}
+
+/*
+ * How to calculate the PLL(from TRM V0.3 Part 1 Page 63):
+ * Formulas also embedded within the Fractional PLL Verilog model:
+ * If DSMPD = 1 (DSM is disabled, "integer mode")
+ * FOUTVCO = FREF / REFDIV * FBDIV
+ * FOUTPOSTDIV = FOUTVCO / POSTDIV1 / POSTDIV2
+ * Where:
+ * FOUTVCO = Fractional PLL non-divided output frequency
+ * FOUTPOSTDIV = Fractional PLL divided output frequency
+ * (output of second post divider)
+ * FREF = Fractional PLL input reference frequency, (the OSC_HZ 24MHz input)
+ * REFDIV = Fractional PLL input reference clock divider
+ * FBDIV = Integer value programmed into feedback divide
+ *
+ */
+static int rkclk_set_pll(struct px30_pll *pll, unsigned int *mode,
+ enum px30_pll_id pll_id,
+ unsigned long drate)
+{
+ const struct pll_rate_table *rate;
+ uint vco_hz, output_hz;
+
+ rate = get_pll_settings(drate);
+ if (!rate) {
+ printf("%s unsupport rate\n", __func__);
+ return -EINVAL;
+ }
+
+ /* All PLLs have same VCO and output frequency range restrictions. */
+ vco_hz = OSC_HZ / 1000 * rate->fbdiv / rate->refdiv * 1000;
+ output_hz = vco_hz / rate->postdiv1 / rate->postdiv2;
+
+ debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
+ pll, rate->fbdiv, rate->refdiv, rate->postdiv1,
+ rate->postdiv2, vco_hz, output_hz);
+ assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
+ output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);
+
+ /*
+ * When power on or changing PLL setting,
+ * we must force PLL into slow mode to ensure output stable clock.
+ */
+ rk_clrsetreg(mode, pll_mode_mask[pll_id],
+ PLLMUX_FROM_XIN24M << pll_mode_shift[pll_id]);
+
+ /* use integer mode */
+ rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT);
+ /* Power down */
+ rk_setreg(&pll->con1, 1 << PLL_PD_SHIFT);
+
+ rk_clrsetreg(&pll->con0,
+ PLL_POSTDIV1_MASK | PLL_FBDIV_MASK,
+ (rate->postdiv1 << PLL_POSTDIV1_SHIFT) | rate->fbdiv);
+ rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
+ (rate->postdiv2 << PLL_POSTDIV2_SHIFT |
+ rate->refdiv << PLL_REFDIV_SHIFT));
+
+ /* Power Up */
+ rk_clrreg(&pll->con1, 1 << PLL_PD_SHIFT);
+
+ /* waiting for pll lock */
+ while (!(readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT)))
+ udelay(1);
+
+ rk_clrsetreg(mode, pll_mode_mask[pll_id],
+ PLLMUX_FROM_PLL << pll_mode_shift[pll_id]);
+
+ return 0;
+}
+
+static uint32_t rkclk_pll_get_rate(struct px30_pll *pll, unsigned int *mode,
+ enum px30_pll_id pll_id)
+{
+ u32 refdiv, fbdiv, postdiv1, postdiv2;
+ u32 con, shift, mask;
+
+ con = readl(mode);
+ shift = pll_mode_shift[pll_id];
+ mask = pll_mode_mask[pll_id];
+
+ switch ((con & mask) >> shift) {
+ case PLLMUX_FROM_XIN24M:
+ return OSC_HZ;
+ case PLLMUX_FROM_PLL:
+ /* normal mode */
+ con = readl(&pll->con0);
+ postdiv1 = (con & PLL_POSTDIV1_MASK) >> PLL_POSTDIV1_SHIFT;
+ fbdiv = (con & PLL_FBDIV_MASK) >> PLL_FBDIV_SHIFT;
+ con = readl(&pll->con1);
+ postdiv2 = (con & PLL_POSTDIV2_MASK) >> PLL_POSTDIV2_SHIFT;
+ refdiv = (con & PLL_REFDIV_MASK) >> PLL_REFDIV_SHIFT;
+ return (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
+ case PLLMUX_FROM_RTC32K:
+ default:
+ return 32768;
+ }
+}
+
+static ulong px30_i2c_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 div, con;
+
+ switch (clk_id) {
+ case SCLK_I2C0:
+ con = readl(&cru->clksel_con[49]);
+ div = con >> CLK_I2C0_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
+ break;
+ case SCLK_I2C1:
+ con = readl(&cru->clksel_con[49]);
+ div = con >> CLK_I2C1_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
+ break;
+ case SCLK_I2C2:
+ con = readl(&cru->clksel_con[50]);
+ div = con >> CLK_I2C2_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
+ break;
+ case SCLK_I2C3:
+ con = readl(&cru->clksel_con[50]);
+ div = con >> CLK_I2C3_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK;
+ break;
+ default:
+ printf("do not support this i2c bus\n");
+ return -EINVAL;
+ }
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong px30_i2c_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
+{
+ struct px30_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+ assert(src_clk_div - 1 <= 127);
+
+ switch (clk_id) {
+ case SCLK_I2C0:
+ rk_clrsetreg(&cru->clksel_con[49],
+ CLK_I2C_DIV_CON_MASK << CLK_I2C0_DIV_CON_SHIFT |
+ CLK_I2C_PLL_SEL_MASK << CLK_I2C0_PLL_SEL_SHIFT,
+ (src_clk_div - 1) << CLK_I2C0_DIV_CON_SHIFT |
+ CLK_I2C_PLL_SEL_GPLL << CLK_I2C0_PLL_SEL_SHIFT);
+ break;
+ case SCLK_I2C1:
+ rk_clrsetreg(&cru->clksel_con[49],
+ CLK_I2C_DIV_CON_MASK << CLK_I2C1_DIV_CON_SHIFT |
+ CLK_I2C_PLL_SEL_MASK << CLK_I2C1_PLL_SEL_SHIFT,
+ (src_clk_div - 1) << CLK_I2C1_DIV_CON_SHIFT |
+ CLK_I2C_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT);
+ break;
+ case SCLK_I2C2:
+ rk_clrsetreg(&cru->clksel_con[50],
+ CLK_I2C_DIV_CON_MASK << CLK_I2C2_DIV_CON_SHIFT |
+ CLK_I2C_PLL_SEL_MASK << CLK_I2C2_PLL_SEL_SHIFT,
+ (src_clk_div - 1) << CLK_I2C2_DIV_CON_SHIFT |
+ CLK_I2C_PLL_SEL_GPLL << CLK_I2C2_PLL_SEL_SHIFT);
+ break;
+ case SCLK_I2C3:
+ rk_clrsetreg(&cru->clksel_con[50],
+ CLK_I2C_DIV_CON_MASK << CLK_I2C3_DIV_CON_SHIFT |
+ CLK_I2C_PLL_SEL_MASK << CLK_I2C3_PLL_SEL_SHIFT,
+ (src_clk_div - 1) << CLK_I2C3_DIV_CON_SHIFT |
+ CLK_I2C_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT);
+ break;
+ default:
+ printf("do not support this i2c bus\n");
+ return -EINVAL;
+ }
+
+ return px30_i2c_get_clk(priv, clk_id);
+}
+
+/*
+ * calculate best rational approximation for a given fraction
+ * taking into account restricted register size, e.g. to find
+ * appropriate values for a pll with 5 bit denominator and
+ * 8 bit numerator register fields, trying to set up with a
+ * frequency ratio of 3.1415, one would say:
+ *
+ * rational_best_approximation(31415, 10000,
+ * (1 << 8) - 1, (1 << 5) - 1, &n, &d);
+ *
+ * you may look at given_numerator as a fixed point number,
+ * with the fractional part size described in given_denominator.
+ *
+ * for theoretical background, see:
+ * http://en.wikipedia.org/wiki/Continued_fraction
+ */
+static void rational_best_approximation(unsigned long given_numerator,
+ unsigned long given_denominator,
+ unsigned long max_numerator,
+ unsigned long max_denominator,
+ unsigned long *best_numerator,
+ unsigned long *best_denominator)
+{
+ unsigned long n, d, n0, d0, n1, d1;
+
+ n = given_numerator;
+ d = given_denominator;
+ n0 = 0;
+ d1 = 0;
+ n1 = 1;
+ d0 = 1;
+ for (;;) {
+ unsigned long t, a;
+
+ if (n1 > max_numerator || d1 > max_denominator) {
+ n1 = n0;
+ d1 = d0;
+ break;
+ }
+ if (d == 0)
+ break;
+ t = d;
+ a = n / d;
+ d = n % d;
+ n = t;
+ t = n0 + a * n1;
+ n0 = n1;
+ n1 = t;
+ t = d0 + a * d1;
+ d0 = d1;
+ d1 = t;
+ }
+ *best_numerator = n1;
+ *best_denominator = d1;
+}
+
+static ulong px30_i2s_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+ u32 con, fracdiv, gate;
+ u32 clk_src = priv->gpll_hz / 2;
+ unsigned long m, n;
+ struct px30_cru *cru = priv->cru;
+
+ switch (clk_id) {
+ case SCLK_I2S1:
+ con = readl(&cru->clksel_con[30]);
+ fracdiv = readl(&cru->clksel_con[31]);
+ gate = readl(&cru->clkgate_con[10]);
+ m = fracdiv & CLK_I2S1_FRAC_NUMERATOR_MASK;
+ m >>= CLK_I2S1_FRAC_NUMERATOR_SHIFT;
+ n = fracdiv & CLK_I2S1_FRAC_DENOMINATOR_MASK;
+ n >>= CLK_I2S1_FRAC_DENOMINATOR_SHIFT;
+ debug("con30: 0x%x, gate: 0x%x, frac: 0x%x\n",
+ con, gate, fracdiv);
+ break;
+ default:
+ printf("do not support this i2s bus\n");
+ return -EINVAL;
+ }
+
+ return clk_src * n / m;
+}
+
+static ulong px30_i2s_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
+{
+ u32 clk_src;
+ unsigned long m, n, val;
+ struct px30_cru *cru = priv->cru;
+
+ clk_src = priv->gpll_hz / 2;
+ rational_best_approximation(hz, clk_src,
+ GENMASK(16 - 1, 0),
+ GENMASK(16 - 1, 0),
+ &m, &n);
+ switch (clk_id) {
+ case SCLK_I2S1:
+ rk_clrsetreg(&cru->clksel_con[30],
+ CLK_I2S1_PLL_SEL_MASK, CLK_I2S1_PLL_SEL_GPLL);
+ rk_clrsetreg(&cru->clksel_con[30],
+ CLK_I2S1_DIV_CON_MASK, 0x1);
+ rk_clrsetreg(&cru->clksel_con[30],
+ CLK_I2S1_SEL_MASK, CLK_I2S1_SEL_FRAC);
+ val = m << CLK_I2S1_FRAC_NUMERATOR_SHIFT | n;
+ writel(val, &cru->clksel_con[31]);
+ rk_clrsetreg(&cru->clkgate_con[10],
+ CLK_I2S1_OUT_MCLK_PAD_MASK,
+ CLK_I2S1_OUT_MCLK_PAD_ENABLE);
+ break;
+ default:
+ printf("do not support this i2s bus\n");
+ return -EINVAL;
+ }
+
+ return px30_i2s_get_clk(priv, clk_id);
+}
+
+static ulong px30_nandc_get_clk(struct px30_clk_priv *priv)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 div, con;
+
+ con = readl(&cru->clksel_con[15]);
+ div = (con & NANDC_DIV_MASK) >> NANDC_DIV_SHIFT;
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong px30_nandc_set_clk(struct px30_clk_priv *priv,
+ ulong set_rate)
+{
+ struct px30_cru *cru = priv->cru;
+ int src_clk_div;
+
+ /* Select nandc source from GPLL by default */
+ /* nandc clock defaulg div 2 internal, need provide double in cru */
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, set_rate);
+ assert(src_clk_div - 1 <= 31);
+
+ rk_clrsetreg(&cru->clksel_con[15],
+ NANDC_CLK_SEL_MASK | NANDC_PLL_MASK |
+ NANDC_DIV_MASK,
+ NANDC_CLK_SEL_NANDC << NANDC_CLK_SEL_SHIFT |
+ NANDC_SEL_GPLL << NANDC_PLL_SHIFT |
+ (src_clk_div - 1) << NANDC_DIV_SHIFT);
+
+ return px30_nandc_get_clk(priv);
+}
+
+static ulong px30_mmc_get_clk(struct px30_clk_priv *priv, uint clk_id)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 div, con, con_id;
+
+ switch (clk_id) {
+ case HCLK_SDMMC:
+ case SCLK_SDMMC:
+ con_id = 16;
+ break;
+ case HCLK_EMMC:
+ case SCLK_EMMC:
+ case SCLK_EMMC_SAMPLE:
+ con_id = 20;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ con = readl(&cru->clksel_con[con_id]);
+ div = (con & EMMC_DIV_MASK) >> EMMC_DIV_SHIFT;
+
+ if ((con & EMMC_PLL_MASK) >> EMMC_PLL_SHIFT
+ == EMMC_SEL_24M)
+ return DIV_TO_RATE(OSC_HZ, div) / 2;
+ else
+ return DIV_TO_RATE(priv->gpll_hz, div) / 2;
+}
+
+static ulong px30_mmc_set_clk(struct px30_clk_priv *priv,
+ ulong clk_id, ulong set_rate)
+{
+ struct px30_cru *cru = priv->cru;
+ int src_clk_div;
+ u32 con_id;
+
+ switch (clk_id) {
+ case HCLK_SDMMC:
+ case SCLK_SDMMC:
+ con_id = 16;
+ break;
+ case HCLK_EMMC:
+ case SCLK_EMMC:
+ con_id = 20;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Select clk_sdmmc/emmc source from GPLL by default */
+ /* mmc clock defaulg div 2 internal, need provide double in cru */
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz / 2, set_rate);
+
+ if (src_clk_div > 127) {
+ /* use 24MHz source for 400KHz clock */
+ src_clk_div = DIV_ROUND_UP(OSC_HZ / 2, set_rate);
+ rk_clrsetreg(&cru->clksel_con[con_id],
+ EMMC_PLL_MASK | EMMC_DIV_MASK,
+ EMMC_SEL_24M << EMMC_PLL_SHIFT |
+ (src_clk_div - 1) << EMMC_DIV_SHIFT);
+ } else {
+ rk_clrsetreg(&cru->clksel_con[con_id],
+ EMMC_PLL_MASK | EMMC_DIV_MASK,
+ EMMC_SEL_GPLL << EMMC_PLL_SHIFT |
+ (src_clk_div - 1) << EMMC_DIV_SHIFT);
+ }
+ rk_clrsetreg(&cru->clksel_con[con_id + 1], EMMC_CLK_SEL_MASK,
+ EMMC_CLK_SEL_EMMC);
+
+ return px30_mmc_get_clk(priv, clk_id);
+}
+
+static ulong px30_pwm_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 div, con;
+
+ switch (clk_id) {
+ case SCLK_PWM0:
+ con = readl(&cru->clksel_con[52]);
+ div = con >> CLK_PWM0_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
+ break;
+ case SCLK_PWM1:
+ con = readl(&cru->clksel_con[52]);
+ div = con >> CLK_PWM1_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK;
+ break;
+ default:
+ printf("do not support this pwm bus\n");
+ return -EINVAL;
+ }
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong px30_pwm_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
+{
+ struct px30_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+ assert(src_clk_div - 1 <= 127);
+
+ switch (clk_id) {
+ case SCLK_PWM0:
+ rk_clrsetreg(&cru->clksel_con[52],
+ CLK_PWM_DIV_CON_MASK << CLK_PWM0_DIV_CON_SHIFT |
+ CLK_PWM_PLL_SEL_MASK << CLK_PWM0_PLL_SEL_SHIFT,
+ (src_clk_div - 1) << CLK_PWM0_DIV_CON_SHIFT |
+ CLK_PWM_PLL_SEL_GPLL << CLK_PWM0_PLL_SEL_SHIFT);
+ break;
+ case SCLK_PWM1:
+ rk_clrsetreg(&cru->clksel_con[52],
+ CLK_PWM_DIV_CON_MASK << CLK_PWM1_DIV_CON_SHIFT |
+ CLK_PWM_PLL_SEL_MASK << CLK_PWM1_PLL_SEL_SHIFT,
+ (src_clk_div - 1) << CLK_PWM1_DIV_CON_SHIFT |
+ CLK_PWM_PLL_SEL_GPLL << CLK_PWM1_PLL_SEL_SHIFT);
+ break;
+ default:
+ printf("do not support this pwm bus\n");
+ return -EINVAL;
+ }
+
+ return px30_pwm_get_clk(priv, clk_id);
+}
+
+static ulong px30_saradc_get_clk(struct px30_clk_priv *priv)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 div, con;
+
+ con = readl(&cru->clksel_con[55]);
+ div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
+
+ return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong px30_saradc_set_clk(struct px30_clk_priv *priv, uint hz)
+{
+ struct px30_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
+ assert(src_clk_div - 1 <= 2047);
+
+ rk_clrsetreg(&cru->clksel_con[55],
+ CLK_SARADC_DIV_CON_MASK,
+ (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
+
+ return px30_saradc_get_clk(priv);
+}
+
+static ulong px30_tsadc_get_clk(struct px30_clk_priv *priv)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 div, con;
+
+ con = readl(&cru->clksel_con[54]);
+ div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK;
+
+ return DIV_TO_RATE(OSC_HZ, div);
+}
+
+static ulong px30_tsadc_set_clk(struct px30_clk_priv *priv, uint hz)
+{
+ struct px30_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(OSC_HZ, hz);
+ assert(src_clk_div - 1 <= 2047);
+
+ rk_clrsetreg(&cru->clksel_con[54],
+ CLK_SARADC_DIV_CON_MASK,
+ (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT);
+
+ return px30_tsadc_get_clk(priv);
+}
+
+static ulong px30_spi_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 div, con;
+
+ switch (clk_id) {
+ case SCLK_SPI0:
+ con = readl(&cru->clksel_con[53]);
+ div = con >> CLK_SPI0_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
+ break;
+ case SCLK_SPI1:
+ con = readl(&cru->clksel_con[53]);
+ div = con >> CLK_SPI1_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK;
+ break;
+ default:
+ printf("do not support this pwm bus\n");
+ return -EINVAL;
+ }
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong px30_spi_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
+{
+ struct px30_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+ assert(src_clk_div - 1 <= 127);
+
+ switch (clk_id) {
+ case SCLK_SPI0:
+ rk_clrsetreg(&cru->clksel_con[53],
+ CLK_SPI_DIV_CON_MASK << CLK_SPI0_DIV_CON_SHIFT |
+ CLK_SPI_PLL_SEL_MASK << CLK_SPI0_PLL_SEL_SHIFT,
+ (src_clk_div - 1) << CLK_SPI0_DIV_CON_SHIFT |
+ CLK_SPI_PLL_SEL_GPLL << CLK_SPI0_PLL_SEL_SHIFT);
+ break;
+ case SCLK_SPI1:
+ rk_clrsetreg(&cru->clksel_con[53],
+ CLK_SPI_DIV_CON_MASK << CLK_SPI1_DIV_CON_SHIFT |
+ CLK_SPI_PLL_SEL_MASK << CLK_SPI1_PLL_SEL_SHIFT,
+ (src_clk_div - 1) << CLK_SPI1_DIV_CON_SHIFT |
+ CLK_SPI_PLL_SEL_GPLL << CLK_SPI1_PLL_SEL_SHIFT);
+ break;
+ default:
+ printf("do not support this pwm bus\n");
+ return -EINVAL;
+ }
+
+ return px30_spi_get_clk(priv, clk_id);
+}
+
+static ulong px30_vop_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 div, con, parent;
+
+ switch (clk_id) {
+ case ACLK_VOPB:
+ case ACLK_VOPL:
+ con = readl(&cru->clksel_con[3]);
+ div = con & ACLK_VO_DIV_MASK;
+ parent = priv->gpll_hz;
+ break;
+ case DCLK_VOPB:
+ con = readl(&cru->clksel_con[5]);
+ div = con & DCLK_VOPB_DIV_MASK;
+ parent = rkclk_pll_get_rate(&cru->pll[CPLL], &cru->mode, CPLL);
+ break;
+ case DCLK_VOPL:
+ con = readl(&cru->clksel_con[8]);
+ div = con & DCLK_VOPL_DIV_MASK;
+ parent = rkclk_pll_get_rate(&cru->pll[NPLL], &cru->mode, NPLL);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong px30_vop_set_clk(struct px30_clk_priv *priv, ulong clk_id, uint hz)
+{
+ struct px30_cru *cru = priv->cru;
+ ulong npll_hz;
+ int src_clk_div;
+
+ switch (clk_id) {
+ case ACLK_VOPB:
+ case ACLK_VOPL:
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[3],
+ ACLK_VO_PLL_MASK | ACLK_VO_DIV_MASK,
+ ACLK_VO_SEL_GPLL << ACLK_VO_PLL_SHIFT |
+ (src_clk_div - 1) << ACLK_VO_DIV_SHIFT);
+ break;
+ case DCLK_VOPB:
+ if (hz < PX30_VOP_PLL_LIMIT) {
+ src_clk_div = DIV_ROUND_UP(PX30_VOP_PLL_LIMIT, hz);
+ if (src_clk_div % 2)
+ src_clk_div = src_clk_div - 1;
+ } else {
+ src_clk_div = 1;
+ }
+ assert(src_clk_div - 1 <= 255);
+ rkclk_set_pll(&cru->pll[CPLL], &cru->mode,
+ CPLL, hz * src_clk_div);
+ rk_clrsetreg(&cru->clksel_con[5],
+ DCLK_VOPB_SEL_MASK | DCLK_VOPB_PLL_SEL_MASK |
+ DCLK_VOPB_DIV_MASK,
+ DCLK_VOPB_SEL_DIVOUT << DCLK_VOPB_SEL_SHIFT |
+ DCLK_VOPB_PLL_SEL_CPLL << DCLK_VOPB_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << DCLK_VOPB_DIV_SHIFT);
+ break;
+ case DCLK_VOPL:
+ npll_hz = px30_clk_get_pll_rate(priv, NPLL);
+ if (npll_hz >= PX30_VOP_PLL_LIMIT && npll_hz >= hz &&
+ npll_hz % hz == 0) {
+ src_clk_div = npll_hz / hz;
+ assert(src_clk_div - 1 <= 255);
+ } else {
+ if (hz < PX30_VOP_PLL_LIMIT) {
+ src_clk_div = DIV_ROUND_UP(PX30_VOP_PLL_LIMIT,
+ hz);
+ if (src_clk_div % 2)
+ src_clk_div = src_clk_div - 1;
+ } else {
+ src_clk_div = 1;
+ }
+ assert(src_clk_div - 1 <= 255);
+ rkclk_set_pll(&cru->pll[NPLL], &cru->mode, NPLL,
+ hz * src_clk_div);
+ }
+ rk_clrsetreg(&cru->clksel_con[8],
+ DCLK_VOPL_SEL_MASK | DCLK_VOPL_PLL_SEL_MASK |
+ DCLK_VOPL_DIV_MASK,
+ DCLK_VOPL_SEL_DIVOUT << DCLK_VOPL_SEL_SHIFT |
+ DCLK_VOPL_PLL_SEL_NPLL << DCLK_VOPL_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << DCLK_VOPL_DIV_SHIFT);
+ break;
+ default:
+ printf("do not support this vop freq\n");
+ return -EINVAL;
+ }
+
+ return px30_vop_get_clk(priv, clk_id);
+}
+
+static ulong px30_bus_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 div, con, parent;
+
+ switch (clk_id) {
+ case ACLK_BUS_PRE:
+ con = readl(&cru->clksel_con[23]);
+ div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT;
+ parent = priv->gpll_hz;
+ break;
+ case HCLK_BUS_PRE:
+ con = readl(&cru->clksel_con[24]);
+ div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT;
+ parent = priv->gpll_hz;
+ break;
+ case PCLK_BUS_PRE:
+ case PCLK_WDT_NS:
+ parent = px30_bus_get_clk(priv, ACLK_BUS_PRE);
+ con = readl(&cru->clksel_con[24]);
+ div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong px30_bus_set_clk(struct px30_clk_priv *priv, ulong clk_id,
+ ulong hz)
+{
+ struct px30_cru *cru = priv->cru;
+ int src_clk_div;
+
+ /*
+ * select gpll as pd_bus bus clock source and
+ * set up dependent divisors for PCLK/HCLK and ACLK clocks.
+ */
+ switch (clk_id) {
+ case ACLK_BUS_PRE:
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[23],
+ BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK,
+ BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT);
+ break;
+ case HCLK_BUS_PRE:
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+ assert(src_clk_div - 1 <= 31);
+ rk_clrsetreg(&cru->clksel_con[24],
+ BUS_PLL_SEL_MASK | BUS_HCLK_DIV_MASK,
+ BUS_PLL_SEL_GPLL << BUS_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT);
+ break;
+ case PCLK_BUS_PRE:
+ src_clk_div =
+ DIV_ROUND_UP(px30_bus_get_clk(priv, ACLK_BUS_PRE), hz);
+ assert(src_clk_div - 1 <= 3);
+ rk_clrsetreg(&cru->clksel_con[24],
+ BUS_PCLK_DIV_MASK,
+ (src_clk_div - 1) << BUS_PCLK_DIV_SHIFT);
+ break;
+ default:
+ printf("do not support this bus freq\n");
+ return -EINVAL;
+ }
+
+ return px30_bus_get_clk(priv, clk_id);
+}
+
+static ulong px30_peri_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 div, con, parent;
+
+ switch (clk_id) {
+ case ACLK_PERI_PRE:
+ con = readl(&cru->clksel_con[14]);
+ div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT;
+ parent = priv->gpll_hz;
+ break;
+ case HCLK_PERI_PRE:
+ con = readl(&cru->clksel_con[14]);
+ div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT;
+ parent = priv->gpll_hz;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong px30_peri_set_clk(struct px30_clk_priv *priv, ulong clk_id,
+ ulong hz)
+{
+ struct px30_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+ assert(src_clk_div - 1 <= 31);
+
+ /*
+ * select gpll as pd_peri bus clock source and
+ * set up dependent divisors for HCLK and ACLK clocks.
+ */
+ switch (clk_id) {
+ case ACLK_PERI_PRE:
+ rk_clrsetreg(&cru->clksel_con[14],
+ PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK,
+ PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT);
+ break;
+ case HCLK_PERI_PRE:
+ rk_clrsetreg(&cru->clksel_con[14],
+ PERI_PLL_SEL_MASK | PERI_HCLK_DIV_MASK,
+ PERI_PLL_GPLL << PERI_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT);
+ break;
+ default:
+ printf("do not support this peri freq\n");
+ return -EINVAL;
+ }
+
+ return px30_peri_get_clk(priv, clk_id);
+}
+
+#ifndef CONFIG_SPL_BUILD
+static ulong px30_crypto_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 div, con, parent;
+
+ switch (clk_id) {
+ case SCLK_CRYPTO:
+ con = readl(&cru->clksel_con[25]);
+ div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT;
+ parent = priv->gpll_hz;
+ break;
+ case SCLK_CRYPTO_APK:
+ con = readl(&cru->clksel_con[25]);
+ div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT;
+ parent = priv->gpll_hz;
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return DIV_TO_RATE(parent, div);
+}
+
+static ulong px30_crypto_set_clk(struct px30_clk_priv *priv, ulong clk_id,
+ ulong hz)
+{
+ struct px30_cru *cru = priv->cru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+ assert(src_clk_div - 1 <= 31);
+
+ /*
+ * select gpll as crypto clock source and
+ * set up dependent divisors for crypto clocks.
+ */
+ switch (clk_id) {
+ case SCLK_CRYPTO:
+ rk_clrsetreg(&cru->clksel_con[25],
+ CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK,
+ CRYPTO_PLL_SEL_GPLL << CRYPTO_PLL_SEL_SHIFT |
+ (src_clk_div - 1) << CRYPTO_DIV_SHIFT);
+ break;
+ case SCLK_CRYPTO_APK:
+ rk_clrsetreg(&cru->clksel_con[25],
+ CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK,
+ CRYPTO_PLL_SEL_GPLL << CRYPTO_APK_SEL_SHIFT |
+ (src_clk_div - 1) << CRYPTO_APK_DIV_SHIFT);
+ break;
+ default:
+ printf("do not support this peri freq\n");
+ return -EINVAL;
+ }
+
+ return px30_crypto_get_clk(priv, clk_id);
+}
+
+static ulong px30_i2s1_mclk_get_clk(struct px30_clk_priv *priv, ulong clk_id)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 con;
+
+ con = readl(&cru->clksel_con[30]);
+
+ if (!(con & CLK_I2S1_OUT_SEL_MASK))
+ return -ENOENT;
+
+ return 12000000;
+}
+
+static ulong px30_i2s1_mclk_set_clk(struct px30_clk_priv *priv, ulong clk_id,
+ ulong hz)
+{
+ struct px30_cru *cru = priv->cru;
+
+ if (hz != 12000000) {
+ printf("do not support this i2s1_mclk freq\n");
+ return -EINVAL;
+ }
+
+ rk_clrsetreg(&cru->clksel_con[30], CLK_I2S1_OUT_SEL_MASK,
+ CLK_I2S1_OUT_SEL_OSC);
+ rk_clrsetreg(&cru->clkgate_con[10], CLK_I2S1_OUT_MCLK_PAD_MASK,
+ CLK_I2S1_OUT_MCLK_PAD_ENABLE);
+
+ return px30_i2s1_mclk_get_clk(priv, clk_id);
+}
+
+static ulong px30_mac_set_clk(struct px30_clk_priv *priv, uint hz)
+{
+ struct px30_cru *cru = priv->cru;
+ u32 con = readl(&cru->clksel_con[22]);
+ ulong pll_rate;
+ u8 div;
+
+ if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_CPLL)
+ pll_rate = px30_clk_get_pll_rate(priv, CPLL);
+ else if ((con >> GMAC_PLL_SEL_SHIFT) & GMAC_PLL_SEL_NPLL)
+ pll_rate = px30_clk_get_pll_rate(priv, NPLL);
+ else
+ pll_rate = priv->gpll_hz;
+
+ /*default set 50MHZ for gmac*/
+ if (!hz)
+ hz = 50000000;
+
+ div = DIV_ROUND_UP(pll_rate, hz) - 1;
+ assert(div < 32);
+ rk_clrsetreg(&cru->clksel_con[22], CLK_GMAC_DIV_MASK,
+ div << CLK_GMAC_DIV_SHIFT);
+
+ return DIV_TO_RATE(pll_rate, div);
+}
+
+static int px30_mac_set_speed_clk(struct px30_clk_priv *priv, uint hz)
+{
+ struct px30_cru *cru = priv->cru;
+
+ if (hz != 2500000 && hz != 25000000) {
+ debug("Unsupported mac speed:%d\n", hz);
+ return -EINVAL;
+ }
+
+ rk_clrsetreg(&cru->clksel_con[23], RMII_CLK_SEL_MASK,
+ ((hz == 2500000) ? 0 : 1) << RMII_CLK_SEL_SHIFT);
+
+ return 0;
+}
+
+#endif
+
+static ulong px30_clk_get_pll_rate(struct px30_clk_priv *priv,
+ enum px30_pll_id pll_id)
+{
+ struct px30_cru *cru = priv->cru;
+
+ return rkclk_pll_get_rate(&cru->pll[pll_id], &cru->mode, pll_id);
+}
+
+static ulong px30_clk_set_pll_rate(struct px30_clk_priv *priv,
+ enum px30_pll_id pll_id, ulong hz)
+{
+ struct px30_cru *cru = priv->cru;
+
+ if (rkclk_set_pll(&cru->pll[pll_id], &cru->mode, pll_id, hz))
+ return -EINVAL;
+ return rkclk_pll_get_rate(&cru->pll[pll_id], &cru->mode, pll_id);
+}
+
+static ulong px30_armclk_set_clk(struct px30_clk_priv *priv, ulong hz)
+{
+ struct px30_cru *cru = priv->cru;
+ const struct cpu_rate_table *rate;
+ ulong old_rate;
+
+ rate = get_cpu_settings(hz);
+ if (!rate) {
+ printf("%s unsupport rate\n", __func__);
+ return -EINVAL;
+ }
+
+ /*
+ * select apll as cpu/core clock pll source and
+ * set up dependent divisors for PERI and ACLK clocks.
+ * core hz : apll = 1:1
+ */
+ old_rate = px30_clk_get_pll_rate(priv, APLL);
+ if (old_rate > hz) {
+ if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz))
+ return -EINVAL;
+ rk_clrsetreg(&cru->clksel_con[0],
+ CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
+ CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
+ rate->aclk_div << CORE_ACLK_DIV_SHIFT |
+ rate->pclk_div << CORE_DBG_DIV_SHIFT |
+ CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
+ 0 << CORE_DIV_CON_SHIFT);
+ } else if (old_rate < hz) {
+ rk_clrsetreg(&cru->clksel_con[0],
+ CORE_CLK_PLL_SEL_MASK | CORE_DIV_CON_MASK |
+ CORE_ACLK_DIV_MASK | CORE_DBG_DIV_MASK,
+ rate->aclk_div << CORE_ACLK_DIV_SHIFT |
+ rate->pclk_div << CORE_DBG_DIV_SHIFT |
+ CORE_CLK_PLL_SEL_APLL << CORE_CLK_PLL_SEL_SHIFT |
+ 0 << CORE_DIV_CON_SHIFT);
+ if (rkclk_set_pll(&cru->pll[APLL], &cru->mode, APLL, hz))
+ return -EINVAL;
+ }
+
+ return px30_clk_get_pll_rate(priv, APLL);
+}
+
+static ulong px30_clk_get_rate(struct clk *clk)
+{
+ struct px30_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong rate = 0;
+
+ if (!priv->gpll_hz && clk->id > ARMCLK) {
+ printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+ return -ENOENT;
+ }
+
+ debug("%s %ld\n", __func__, clk->id);
+ switch (clk->id) {
+ case PLL_APLL:
+ rate = px30_clk_get_pll_rate(priv, APLL);
+ break;
+ case PLL_DPLL:
+ rate = px30_clk_get_pll_rate(priv, DPLL);
+ break;
+ case PLL_CPLL:
+ rate = px30_clk_get_pll_rate(priv, CPLL);
+ break;
+ case PLL_NPLL:
+ rate = px30_clk_get_pll_rate(priv, NPLL);
+ break;
+ case ARMCLK:
+ rate = px30_clk_get_pll_rate(priv, APLL);
+ break;
+ case HCLK_SDMMC:
+ case HCLK_EMMC:
+ case SCLK_SDMMC:
+ case SCLK_EMMC:
+ case SCLK_EMMC_SAMPLE:
+ rate = px30_mmc_get_clk(priv, clk->id);
+ break;
+ case SCLK_I2C0:
+ case SCLK_I2C1:
+ case SCLK_I2C2:
+ case SCLK_I2C3:
+ rate = px30_i2c_get_clk(priv, clk->id);
+ break;
+ case SCLK_I2S1:
+ rate = px30_i2s_get_clk(priv, clk->id);
+ break;
+ case SCLK_NANDC:
+ rate = px30_nandc_get_clk(priv);
+ break;
+ case SCLK_PWM0:
+ case SCLK_PWM1:
+ rate = px30_pwm_get_clk(priv, clk->id);
+ break;
+ case SCLK_SARADC:
+ rate = px30_saradc_get_clk(priv);
+ break;
+ case SCLK_TSADC:
+ rate = px30_tsadc_get_clk(priv);
+ break;
+ case SCLK_SPI0:
+ case SCLK_SPI1:
+ rate = px30_spi_get_clk(priv, clk->id);
+ break;
+ case ACLK_VOPB:
+ case ACLK_VOPL:
+ case DCLK_VOPB:
+ case DCLK_VOPL:
+ rate = px30_vop_get_clk(priv, clk->id);
+ break;
+ case ACLK_BUS_PRE:
+ case HCLK_BUS_PRE:
+ case PCLK_BUS_PRE:
+ case PCLK_WDT_NS:
+ rate = px30_bus_get_clk(priv, clk->id);
+ break;
+ case ACLK_PERI_PRE:
+ case HCLK_PERI_PRE:
+ rate = px30_peri_get_clk(priv, clk->id);
+ break;
+#ifndef CONFIG_SPL_BUILD
+ case SCLK_CRYPTO:
+ case SCLK_CRYPTO_APK:
+ rate = px30_crypto_get_clk(priv, clk->id);
+ break;
+#endif
+ default:
+ return -ENOENT;
+ }
+
+ return rate;
+}
+
+static ulong px30_clk_set_rate(struct clk *clk, ulong rate)
+{
+ struct px30_clk_priv *priv = dev_get_priv(clk->dev);
+ ulong ret = 0;
+
+ if (!priv->gpll_hz && clk->id > ARMCLK) {
+ printf("%s gpll=%lu\n", __func__, priv->gpll_hz);
+ return -ENOENT;
+ }
+
+ debug("%s %ld %ld\n", __func__, clk->id, rate);
+ switch (clk->id) {
+ case PLL_NPLL:
+ ret = px30_clk_set_pll_rate(priv, NPLL, rate);
+ break;
+ case ARMCLK:
+ ret = px30_armclk_set_clk(priv, rate);
+ break;
+ case HCLK_SDMMC:
+ case HCLK_EMMC:
+ case SCLK_SDMMC:
+ case SCLK_EMMC:
+ ret = px30_mmc_set_clk(priv, clk->id, rate);
+ break;
+ case SCLK_I2C0:
+ case SCLK_I2C1:
+ case SCLK_I2C2:
+ case SCLK_I2C3:
+ ret = px30_i2c_set_clk(priv, clk->id, rate);
+ break;
+ case SCLK_I2S1:
+ ret = px30_i2s_set_clk(priv, clk->id, rate);
+ break;
+ case SCLK_NANDC:
+ ret = px30_nandc_set_clk(priv, rate);
+ break;
+ case SCLK_PWM0:
+ case SCLK_PWM1:
+ ret = px30_pwm_set_clk(priv, clk->id, rate);
+ break;
+ case SCLK_SARADC:
+ ret = px30_saradc_set_clk(priv, rate);
+ break;
+ case SCLK_TSADC:
+ ret = px30_tsadc_set_clk(priv, rate);
+ break;
+ case SCLK_SPI0:
+ case SCLK_SPI1:
+ ret = px30_spi_set_clk(priv, clk->id, rate);
+ break;
+ case ACLK_VOPB:
+ case ACLK_VOPL:
+ case DCLK_VOPB:
+ case DCLK_VOPL:
+ ret = px30_vop_set_clk(priv, clk->id, rate);
+ break;
+ case ACLK_BUS_PRE:
+ case HCLK_BUS_PRE:
+ case PCLK_BUS_PRE:
+ ret = px30_bus_set_clk(priv, clk->id, rate);
+ break;
+ case ACLK_PERI_PRE:
+ case HCLK_PERI_PRE:
+ ret = px30_peri_set_clk(priv, clk->id, rate);
+ break;
+#ifndef CONFIG_SPL_BUILD
+ case SCLK_CRYPTO:
+ case SCLK_CRYPTO_APK:
+ ret = px30_crypto_set_clk(priv, clk->id, rate);
+ break;
+ case SCLK_I2S1_OUT:
+ ret = px30_i2s1_mclk_set_clk(priv, clk->id, rate);
+ break;
+ case SCLK_GMAC:
+ case SCLK_GMAC_SRC:
+ ret = px30_mac_set_clk(priv, rate);
+ break;
+ case SCLK_GMAC_RMII:
+ ret = px30_mac_set_speed_clk(priv, rate);
+ break;
+#endif
+ default:
+ return -ENOENT;
+ }
+
+ return ret;
+}
+
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+static int px30_gmac_set_parent(struct clk *clk, struct clk *parent)
+{
+ struct px30_clk_priv *priv = dev_get_priv(clk->dev);
+ struct px30_cru *cru = priv->cru;
+
+ if (parent->id == SCLK_GMAC_SRC) {
+ debug("%s: switching GAMC to SCLK_GMAC_SRC\n", __func__);
+ rk_clrsetreg(&cru->clksel_con[23], RMII_EXTCLK_SEL_MASK,
+ RMII_EXTCLK_SEL_INT << RMII_EXTCLK_SEL_SHIFT);
+ } else {
+ debug("%s: switching GMAC to external clock\n", __func__);
+ rk_clrsetreg(&cru->clksel_con[23], RMII_EXTCLK_SEL_MASK,
+ RMII_EXTCLK_SEL_EXT << RMII_EXTCLK_SEL_SHIFT);
+ }
+ return 0;
+}
+
+static int px30_clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ switch (clk->id) {
+ case SCLK_GMAC:
+ return px30_gmac_set_parent(clk, parent);
+ default:
+ return -ENOENT;
+ }
+}
+#endif
+
+static int px30_clk_enable(struct clk *clk)
+{
+ switch (clk->id) {
+ case HCLK_HOST:
+ case SCLK_GMAC:
+ case SCLK_GMAC_RX_TX:
+ case SCLK_MAC_REF:
+ case SCLK_MAC_REFOUT:
+ case ACLK_GMAC:
+ case PCLK_GMAC:
+ case SCLK_GMAC_RMII:
+ /* Required to successfully probe the Designware GMAC driver */
+ return 0;
+ }
+
+ debug("%s: unsupported clk %ld\n", __func__, clk->id);
+ return -ENOENT;
+}
+
+static struct clk_ops px30_clk_ops = {
+ .get_rate = px30_clk_get_rate,
+ .set_rate = px30_clk_set_rate,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+ .set_parent = px30_clk_set_parent,
+#endif
+ .enable = px30_clk_enable,
+};
+
+static void px30_clk_init(struct px30_clk_priv *priv)
+{
+ ulong npll_hz;
+ int ret;
+
+ npll_hz = px30_clk_get_pll_rate(priv, NPLL);
+ if (npll_hz != NPLL_HZ) {
+ ret = px30_clk_set_pll_rate(priv, NPLL, NPLL_HZ);
+ if (ret < 0)
+ printf("%s failed to set npll rate\n", __func__);
+ }
+
+ px30_bus_set_clk(priv, ACLK_BUS_PRE, ACLK_BUS_HZ);
+ px30_bus_set_clk(priv, HCLK_BUS_PRE, HCLK_BUS_HZ);
+ px30_bus_set_clk(priv, PCLK_BUS_PRE, PCLK_BUS_HZ);
+ px30_peri_set_clk(priv, ACLK_PERI_PRE, ACLK_PERI_HZ);
+ px30_peri_set_clk(priv, HCLK_PERI_PRE, HCLK_PERI_HZ);
+}
+
+static int px30_clk_probe(struct udevice *dev)
+{
+ struct px30_clk_priv *priv = dev_get_priv(dev);
+ struct clk clk_gpll;
+ int ret;
+
+ if (px30_clk_get_pll_rate(priv, APLL) != APLL_HZ)
+ px30_armclk_set_clk(priv, APLL_HZ);
+
+ /* get the GPLL rate from the pmucru */
+ ret = clk_get_by_name(dev, "gpll", &clk_gpll);
+ if (ret) {
+ printf("%s: failed to get gpll clk from pmucru\n", __func__);
+ return ret;
+ }
+
+ priv->gpll_hz = clk_get_rate(&clk_gpll);
+
+ px30_clk_init(priv);
+
+ return 0;
+}
+
+static int px30_clk_ofdata_to_platdata(struct udevice *dev)
+{
+ struct px30_clk_priv *priv = dev_get_priv(dev);
+
+ priv->cru = dev_read_addr_ptr(dev);
+
+ return 0;
+}
+
+static int px30_clk_bind(struct udevice *dev)
+{
+ int ret;
+ struct udevice *sys_child;
+ struct sysreset_reg *priv;
+
+ /* The reset driver does not have a device node, so bind it here */
+ ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
+ &sys_child);
+ if (ret) {
+ debug("Warning: No sysreset driver: ret=%d\n", ret);
+ } else {
+ priv = malloc(sizeof(struct sysreset_reg));
+ priv->glb_srst_fst_value = offsetof(struct px30_cru,
+ glb_srst_fst);
+ priv->glb_srst_snd_value = offsetof(struct px30_cru,
+ glb_srst_snd);
+ sys_child->priv = priv;
+ }
+
+#if CONFIG_IS_ENABLED(RESET_ROCKCHIP)
+ ret = offsetof(struct px30_cru, softrst_con[0]);
+ ret = rockchip_reset_bind(dev, ret, 12);
+ if (ret)
+ debug("Warning: software reset driver bind faile\n");
+#endif
+
+ return 0;
+}
+
+static const struct udevice_id px30_clk_ids[] = {
+ { .compatible = "rockchip,px30-cru" },
+ { }
+};
+
+U_BOOT_DRIVER(rockchip_px30_cru) = {
+ .name = "rockchip_px30_cru",
+ .id = UCLASS_CLK,
+ .of_match = px30_clk_ids,
+ .priv_auto_alloc_size = sizeof(struct px30_clk_priv),
+ .ofdata_to_platdata = px30_clk_ofdata_to_platdata,
+ .ops = &px30_clk_ops,
+ .bind = px30_clk_bind,
+ .probe = px30_clk_probe,
+};
+
+static ulong px30_pclk_pmu_get_pmuclk(struct px30_pmuclk_priv *priv)
+{
+ struct px30_pmucru *pmucru = priv->pmucru;
+ u32 div, con;
+
+ con = readl(&pmucru->pmu_clksel_con[0]);
+ div = (con & CLK_PMU_PCLK_DIV_MASK) >> CLK_PMU_PCLK_DIV_SHIFT;
+
+ return DIV_TO_RATE(priv->gpll_hz, div);
+}
+
+static ulong px30_pclk_pmu_set_pmuclk(struct px30_pmuclk_priv *priv, ulong hz)
+{
+ struct px30_pmucru *pmucru = priv->pmucru;
+ int src_clk_div;
+
+ src_clk_div = DIV_ROUND_UP(priv->gpll_hz, hz);
+ assert(src_clk_div - 1 <= 31);
+
+ rk_clrsetreg(&pmucru->pmu_clksel_con[0],
+ CLK_PMU_PCLK_DIV_MASK,
+ (src_clk_div - 1) << CLK_PMU_PCLK_DIV_SHIFT);
+
+ return px30_pclk_pmu_get_pmuclk(priv);
+}
+
+static ulong px30_pmuclk_get_gpll_rate(struct px30_pmuclk_priv *priv)
+{
+ struct px30_pmucru *pmucru = priv->pmucru;
+
+ return rkclk_pll_get_rate(&pmucru->pll, &pmucru->pmu_mode, GPLL);
+}
+
+static ulong px30_pmuclk_set_gpll_rate(struct px30_pmuclk_priv *priv, ulong hz)
+{
+ struct px30_pmucru *pmucru = priv->pmucru;
+ ulong pclk_pmu_rate;
+ u32 div;
+
+ if (priv->gpll_hz == hz)
+ return priv->gpll_hz;
+
+ div = DIV_ROUND_UP(hz, priv->gpll_hz);
+
+ /* save clock rate */
+ pclk_pmu_rate = px30_pclk_pmu_get_pmuclk(priv);
+
+ /* avoid rate too large, reduce rate first */
+ px30_pclk_pmu_set_pmuclk(priv, pclk_pmu_rate / div);
+
+ /* change gpll rate */
+ rkclk_set_pll(&pmucru->pll, &pmucru->pmu_mode, GPLL, hz);
+ priv->gpll_hz = px30_pmuclk_get_gpll_rate(priv);
+
+ /* restore clock rate */
+ px30_pclk_pmu_set_pmuclk(priv, pclk_pmu_rate);
+
+ return priv->gpll_hz;
+}
+
+static ulong px30_pmuclk_get_rate(struct clk *clk)
+{
+ struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev);
+ ulong rate = 0;
+
+ debug("%s %ld\n", __func__, clk->id);
+ switch (clk->id) {
+ case PLL_GPLL:
+ rate = px30_pmuclk_get_gpll_rate(priv);
+ break;
+ case PCLK_PMU_PRE:
+ rate = px30_pclk_pmu_get_pmuclk(priv);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return rate;
+}
+
+static ulong px30_pmuclk_set_rate(struct clk *clk, ulong rate)
+{
+ struct px30_pmuclk_priv *priv = dev_get_priv(clk->dev);
+ ulong ret = 0;
+
+ debug("%s %ld %ld\n", __func__, clk->id, rate);
+ switch (clk->id) {
+ case PLL_GPLL:
+ ret = px30_pmuclk_set_gpll_rate(priv, rate);
+ break;
+ case PCLK_PMU_PRE:
+ ret = px30_pclk_pmu_set_pmuclk(priv, rate);
+ break;
+ default:
+ return -ENOENT;
+ }
+
+ return ret;
+}
+
+static struct clk_ops px30_pmuclk_ops = {
+ .get_rate = px30_pmuclk_get_rate,
+ .set_rate = px30_pmuclk_set_rate,
+};
+
+static void px30_pmuclk_init(struct px30_pmuclk_priv *priv)
+{
+ priv->gpll_hz = px30_pmuclk_get_gpll_rate(priv);
+ px30_pmuclk_set_gpll_rate(priv, GPLL_HZ);
+
+ px30_pclk_pmu_set_pmuclk(priv, PCLK_PMU_HZ);
+}
+
+static int px30_pmuclk_probe(struct udevice *dev)
+{
+ struct px30_pmuclk_priv *priv = dev_get_priv(dev);
+
+ px30_pmuclk_init(priv);
+
+ return 0;
+}
+
+static int px30_pmuclk_ofdata_to_platdata(struct udevice *dev)
+{
+ struct px30_pmuclk_priv *priv = dev_get_priv(dev);
+
+ priv->pmucru = dev_read_addr_ptr(dev);
+
+ return 0;
+}
+
+static const struct udevice_id px30_pmuclk_ids[] = {
+ { .compatible = "rockchip,px30-pmucru" },
+ { }
+};
+
+U_BOOT_DRIVER(rockchip_px30_pmucru) = {
+ .name = "rockchip_px30_pmucru",
+ .id = UCLASS_CLK,
+ .of_match = px30_pmuclk_ids,
+ .priv_auto_alloc_size = sizeof(struct px30_pmuclk_priv),
+ .ofdata_to_platdata = px30_pmuclk_ofdata_to_platdata,
+ .ops = &px30_pmuclk_ops,
+ .probe = px30_pmuclk_probe,
+};
--------------------- include/dt-bindings/clock/px30-cru.h ---------------------
new file mode 100644
index 0000000000..e5e59690b5
@@ -0,0 +1,389 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017 Rockchip Electronics Co. Ltd.
+ * Author: Elaine <zhangqing@rock-chips.com>
+ */
+
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_PX30_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_PX30_H
+
+/* core clocks */
+#define PLL_APLL 1
+#define PLL_DPLL 2
+#define PLL_CPLL 3
+#define PLL_NPLL 4
+#define APLL_BOOST_H 5
+#define APLL_BOOST_L 6
+#define ARMCLK 7
+
+/* sclk gates (special clocks) */
+#define USB480M 14
+#define SCLK_PDM 15
+#define SCLK_I2S0_TX 16
+#define SCLK_I2S0_TX_OUT 17
+#define SCLK_I2S0_RX 18
+#define SCLK_I2S0_RX_OUT 19
+#define SCLK_I2S1 20
+#define SCLK_I2S1_OUT 21
+#define SCLK_I2S2 22
+#define SCLK_I2S2_OUT 23
+#define SCLK_UART1 24
+#define SCLK_UART2 25
+#define SCLK_UART3 26
+#define SCLK_UART4 27
+#define SCLK_UART5 28
+#define SCLK_I2C0 29
+#define SCLK_I2C1 30
+#define SCLK_I2C2 31
+#define SCLK_I2C3 32
+#define SCLK_I2C4 33
+#define SCLK_PWM0 34
+#define SCLK_PWM1 35
+#define SCLK_SPI0 36
+#define SCLK_SPI1 37
+#define SCLK_TIMER0 38
+#define SCLK_TIMER1 39
+#define SCLK_TIMER2 40
+#define SCLK_TIMER3 41
+#define SCLK_TIMER4 42
+#define SCLK_TIMER5 43
+#define SCLK_TSADC 44
+#define SCLK_SARADC 45
+#define SCLK_OTP 46
+#define SCLK_OTP_USR 47
+#define SCLK_CRYPTO 48
+#define SCLK_CRYPTO_APK 49
+#define SCLK_DDRC 50
+#define SCLK_ISP 51
+#define SCLK_CIF_OUT 52
+#define SCLK_RGA_CORE 53
+#define SCLK_VOPB_PWM 54
+#define SCLK_NANDC 55
+#define SCLK_SDIO 56
+#define SCLK_EMMC 57
+#define SCLK_SFC 58
+#define SCLK_SDMMC 59
+#define SCLK_OTG_ADP 60
+#define SCLK_GMAC_SRC 61
+#define SCLK_GMAC 62
+#define SCLK_GMAC_RX_TX 63
+#define SCLK_MAC_REF 64
+#define SCLK_MAC_REFOUT 65
+#define SCLK_MAC_OUT 66
+#define SCLK_SDMMC_DRV 67
+#define SCLK_SDMMC_SAMPLE 68
+#define SCLK_SDIO_DRV 69
+#define SCLK_SDIO_SAMPLE 70
+#define SCLK_EMMC_DRV 71
+#define SCLK_EMMC_SAMPLE 72
+#define SCLK_GPU 73
+#define SCLK_PVTM 74
+#define SCLK_CORE_VPU 75
+#define SCLK_GMAC_RMII 76
+#define SCLK_UART2_SRC 77
+#define SCLK_NANDC_DIV 78
+#define SCLK_NANDC_DIV50 79
+#define SCLK_SDIO_DIV 80
+#define SCLK_SDIO_DIV50 81
+#define SCLK_EMMC_DIV 82
+#define SCLK_EMMC_DIV50 83
+
+/* dclk gates */
+#define DCLK_VOPB 150
+#define DCLK_VOPL 151
+
+/* aclk gates */
+#define ACLK_GPU 170
+#define ACLK_BUS_PRE 171
+#define ACLK_CRYPTO 172
+#define ACLK_VI_PRE 173
+#define ACLK_VO_PRE 174
+#define ACLK_VPU 175
+#define ACLK_PERI_PRE 176
+#define ACLK_GMAC 178
+#define ACLK_CIF 179
+#define ACLK_ISP 180
+#define ACLK_VOPB 181
+#define ACLK_VOPL 182
+#define ACLK_RGA 183
+#define ACLK_GIC 184
+#define ACLK_DCF 186
+#define ACLK_DMAC 187
+
+/* hclk gates */
+#define HCLK_BUS_PRE 240
+#define HCLK_CRYPTO 241
+#define HCLK_VI_PRE 242
+#define HCLK_VO_PRE 243
+#define HCLK_VPU 244
+#define HCLK_PERI_PRE 245
+#define HCLK_MMC_NAND 246
+#define HCLK_SDMMC 247
+#define HCLK_USB 248
+#define HCLK_CIF 249
+#define HCLK_ISP 250
+#define HCLK_VOPB 251
+#define HCLK_VOPL 252
+#define HCLK_RGA 253
+#define HCLK_NANDC 254
+#define HCLK_SDIO 255
+#define HCLK_EMMC 256
+#define HCLK_SFC 257
+#define HCLK_OTG 258
+#define HCLK_HOST 259
+#define HCLK_HOST_ARB 260
+#define HCLK_PDM 261
+#define HCLK_I2S0 262
+#define HCLK_I2S1 263
+#define HCLK_I2S2 264
+
+/* pclk gates */
+#define PCLK_BUS_PRE 320
+#define PCLK_DDR 321
+#define PCLK_VO_PRE 322
+#define PCLK_GMAC 323
+#define PCLK_MIPI_DSI 324
+#define PCLK_MIPIDSIPHY 325
+#define PCLK_MIPICSIPHY 326
+#define PCLK_USB_GRF 327
+#define PCLK_DCF 328
+#define PCLK_UART1 329
+#define PCLK_UART2 330
+#define PCLK_UART3 331
+#define PCLK_UART4 332
+#define PCLK_UART5 333
+#define PCLK_I2C0 334
+#define PCLK_I2C1 335
+#define PCLK_I2C2 336
+#define PCLK_I2C3 337
+#define PCLK_I2C4 338
+#define PCLK_PWM0 339
+#define PCLK_PWM1 340
+#define PCLK_SPI0 341
+#define PCLK_SPI1 342
+#define PCLK_SARADC 343
+#define PCLK_TSADC 344
+#define PCLK_TIMER 345
+#define PCLK_OTP_NS 346
+#define PCLK_WDT_NS 347
+#define PCLK_GPIO1 348
+#define PCLK_GPIO2 349
+#define PCLK_GPIO3 350
+#define PCLK_ISP 351
+#define PCLK_CIF 352
+#define PCLK_OTP_PHY 353
+
+#define CLK_NR_CLKS (PCLK_OTP_PHY + 1)
+
+/* pmu-clocks indices */
+
+#define PLL_GPLL 1
+
+#define SCLK_RTC32K_PMU 4
+#define SCLK_WIFI_PMU 5
+#define SCLK_UART0_PMU 6
+#define SCLK_PVTM_PMU 7
+#define PCLK_PMU_PRE 8
+#define SCLK_REF24M_PMU 9
+#define SCLK_USBPHY_REF 10
+#define SCLK_MIPIDSIPHY_REF 11
+
+#define XIN24M_DIV 12
+
+#define PCLK_GPIO0_PMU 20
+#define PCLK_UART0_PMU 21
+
+#define CLKPMU_NR_CLKS (PCLK_UART0_PMU + 1)
+
+/* soft-reset indices */
+#define SRST_CORE0_PO 0
+#define SRST_CORE1_PO 1
+#define SRST_CORE2_PO 2
+#define SRST_CORE3_PO 3
+#define SRST_CORE0 4
+#define SRST_CORE1 5
+#define SRST_CORE2 6
+#define SRST_CORE3 7
+#define SRST_CORE0_DBG 8
+#define SRST_CORE1_DBG 9
+#define SRST_CORE2_DBG 10
+#define SRST_CORE3_DBG 11
+#define SRST_TOPDBG 12
+#define SRST_CORE_NOC 13
+#define SRST_STRC_A 14
+#define SRST_L2C 15
+
+#define SRST_DAP 16
+#define SRST_CORE_PVTM 17
+#define SRST_GPU 18
+#define SRST_GPU_NIU 19
+#define SRST_UPCTL2 20
+#define SRST_UPCTL2_A 21
+#define SRST_UPCTL2_P 22
+#define SRST_MSCH 23
+#define SRST_MSCH_P 24
+#define SRST_DDRMON_P 25
+#define SRST_DDRSTDBY_P 26
+#define SRST_DDRSTDBY 27
+#define SRST_DDRGRF_p 28
+#define SRST_AXI_SPLIT_A 29
+#define SRST_AXI_CMD_A 30
+#define SRST_AXI_CMD_P 31
+
+#define SRST_DDRPHY 32
+#define SRST_DDRPHYDIV 33
+#define SRST_DDRPHY_P 34
+#define SRST_VPU_A 36
+#define SRST_VPU_NIU_A 37
+#define SRST_VPU_H 38
+#define SRST_VPU_NIU_H 39
+#define SRST_VI_NIU_A 40
+#define SRST_VI_NIU_H 41
+#define SRST_ISP_H 42
+#define SRST_ISP 43
+#define SRST_CIF_A 44
+#define SRST_CIF_H 45
+#define SRST_CIF_PCLKIN 46
+#define SRST_MIPICSIPHY_P 47
+
+#define SRST_VO_NIU_A 48
+#define SRST_VO_NIU_H 49
+#define SRST_VO_NIU_P 50
+#define SRST_VOPB_A 51
+#define SRST_VOPB_H 52
+#define SRST_VOPB 53
+#define SRST_PWM_VOPB 54
+#define SRST_VOPL_A 55
+#define SRST_VOPL_H 56
+#define SRST_VOPL 57
+#define SRST_RGA_A 58
+#define SRST_RGA_H 59
+#define SRST_RGA 60
+#define SRST_MIPIDSI_HOST_P 61
+#define SRST_MIPIDSIPHY_P 62
+#define SRST_VPU_CORE 63
+
+#define SRST_PERI_NIU_A 64
+#define SRST_USB_NIU_H 65
+#define SRST_USB2OTG_H 66
+#define SRST_USB2OTG 67
+#define SRST_USB2OTG_ADP 68
+#define SRST_USB2HOST_H 69
+#define SRST_USB2HOST_ARB_H 70
+#define SRST_USB2HOST_AUX_H 71
+#define SRST_USB2HOST_EHCI 72
+#define SRST_USB2HOST 73
+#define SRST_USBPHYPOR 74
+#define SRST_USBPHY_OTG_PORT 75
+#define SRST_USBPHY_HOST_PORT 76
+#define SRST_USBPHY_GRF 77
+#define SRST_CPU_BOOST_P 78
+#define SRST_CPU_BOOST 79
+
+#define SRST_MMC_NAND_NIU_H 80
+#define SRST_SDIO_H 81
+#define SRST_EMMC_H 82
+#define SRST_SFC_H 83
+#define SRST_SFC 84
+#define SRST_SDCARD_NIU_H 85
+#define SRST_SDMMC_H 86
+#define SRST_NANDC_H 89
+#define SRST_NANDC 90
+#define SRST_GMAC_NIU_A 92
+#define SRST_GMAC_NIU_P 93
+#define SRST_GMAC_A 94
+
+#define SRST_PMU_NIU_P 96
+#define SRST_PMU_SGRF_P 97
+#define SRST_PMU_GRF_P 98
+#define SRST_PMU 99
+#define SRST_PMU_MEM_P 100
+#define SRST_PMU_GPIO0_P 101
+#define SRST_PMU_UART0_P 102
+#define SRST_PMU_CRU_P 103
+#define SRST_PMU_PVTM 104
+#define SRST_PMU_UART 105
+#define SRST_PMU_NIU_H 106
+#define SRST_PMU_DDR_FAIL_SAVE 107
+#define SRST_PMU_CORE_PERF_A 108
+#define SRST_PMU_CORE_GRF_P 109
+#define SRST_PMU_GPU_PERF_A 110
+#define SRST_PMU_GPU_GRF_P 111
+
+#define SRST_CRYPTO_NIU_A 112
+#define SRST_CRYPTO_NIU_H 113
+#define SRST_CRYPTO_A 114
+#define SRST_CRYPTO_H 115
+#define SRST_CRYPTO 116
+#define SRST_CRYPTO_APK 117
+#define SRST_BUS_NIU_H 120
+#define SRST_USB_NIU_P 121
+#define SRST_BUS_TOP_NIU_P 122
+#define SRST_INTMEM_A 123
+#define SRST_GIC_A 124
+#define SRST_ROM_H 126
+#define SRST_DCF_A 127
+
+#define SRST_DCF_P 128
+#define SRST_PDM_H 129
+#define SRST_PDM 130
+#define SRST_I2S0_H 131
+#define SRST_I2S0_TX 132
+#define SRST_I2S1_H 133
+#define SRST_I2S1 134
+#define SRST_I2S2_H 135
+#define SRST_I2S2 136
+#define SRST_UART1_P 137
+#define SRST_UART1 138
+#define SRST_UART2_P 139
+#define SRST_UART2 140
+#define SRST_UART3_P 141
+#define SRST_UART3 142
+#define SRST_UART4_P 143
+
+#define SRST_UART4 144
+#define SRST_UART5_P 145
+#define SRST_UART5 146
+#define SRST_I2C0_P 147
+#define SRST_I2C0 148
+#define SRST_I2C1_P 149
+#define SRST_I2C1 150
+#define SRST_I2C2_P 151
+#define SRST_I2C2 152
+#define SRST_I2C3_P 153
+#define SRST_I2C3 154
+#define SRST_PWM0_P 157
+#define SRST_PWM0 158
+#define SRST_PWM1_P 159
+
+#define SRST_PWM1 160
+#define SRST_SPI0_P 161
+#define SRST_SPI0 162
+#define SRST_SPI1_P 163
+#define SRST_SPI1 164
+#define SRST_SARADC_P 165
+#define SRST_SARADC 166
+#define SRST_TSADC_P 167
+#define SRST_TSADC 168
+#define SRST_TIMER_P 169
+#define SRST_TIMER0 170
+#define SRST_TIMER1 171
+#define SRST_TIMER2 172
+#define SRST_TIMER3 173
+#define SRST_TIMER4 174
+#define SRST_TIMER5 175
+
+#define SRST_OTP_NS_P 176
+#define SRST_OTP_NS_SBPI 177
+#define SRST_OTP_NS_USR 178
+#define SRST_OTP_PHY_P 179
+#define SRST_OTP_PHY 180
+#define SRST_WDT_NS_P 181
+#define SRST_GPIO1_P 182
+#define SRST_GPIO2_P 183
+#define SRST_GPIO3_P 184
+#define SRST_SGRF_P 185
+#define SRST_GRF_P 186
+#define SRST_I2S0_RX 191
+
+#endif
 
 

Recent Patches

About Us

Sed lacus. Donec lectus. Nullam pretium nibh ut turpis. Nam bibendum. In nulla tortor, elementum vel, tempor at, varius non, purus. Mauris vitae nisl nec metus placerat consectetuer.

Read More...