From 46281a76bee3fdb18f75b4c71405ac5cacf1a64e Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 16 Jul 2019 22:17:13 +0200 Subject: rockchip: add core px30 headers Add headers needed by the upcoming px30 support, including two new dt-binding headers taken from the Linux kernel. Signed-off-by: Heiko Stuebner Reviewed-by: Kever Yang --- include/configs/px30_common.h | 62 ++++++++++++++++++++++++++++ include/dt-bindings/power/px30-power.h | 27 ++++++++++++ include/dt-bindings/soc/rockchip,boot-mode.h | 16 +++++++ 3 files changed, 105 insertions(+) create mode 100644 include/configs/px30_common.h create mode 100644 include/dt-bindings/power/px30-power.h create mode 100644 include/dt-bindings/soc/rockchip,boot-mode.h (limited to 'include') diff --git a/include/configs/px30_common.h b/include/configs/px30_common.h new file mode 100644 index 00000000000..d6c70601dd0 --- /dev/null +++ b/include/configs/px30_common.h @@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2017 Rockchip Electronics Co., Ltd + */ + +#ifndef __CONFIG_PX30_COMMON_H +#define __CONFIG_PX30_COMMON_H + +#include "rockchip-common.h" + +#define CONFIG_SYS_CBSIZE 1024 +#define CONFIG_SKIP_LOWLEVEL_INIT + +#define CONFIG_SYS_NS16550_MEM32 + +#define CONFIG_ROCKCHIP_STIMER_BASE 0xff220020 +#define COUNTER_FREQUENCY 24000000 + +/* FIXME: ff020000 is pmu_mem (10k), while ff0e0000 is regular int_mem */ +#define CONFIG_IRAM_BASE 0xff020000 + +#define CONFIG_SYS_INIT_SP_ADDR 0x00400000 +#define CONFIG_SYS_LOAD_ADDR 0x00800800 +#define CONFIG_SPL_STACK 0x00400000 +#define CONFIG_SPL_MAX_SIZE 0x20000 +#define CONFIG_SPL_BSS_START_ADDR 0x4000000 +#define CONFIG_SPL_BSS_MAX_SIZE 0x4000 +#define CONFIG_SYS_BOOTM_LEN (64 << 20) /* 64M */ + +#define GICD_BASE 0xff131000 +#define GICC_BASE 0xff132000 + +#define CONFIG_SYS_BOOTM_LEN (64 << 20) /* 64M */ + +/* MMC/SD IP block */ +//#define CONFIG_BOUNCE_BUFFER + +#define CONFIG_SYS_SDRAM_BASE 0 +#define SDRAM_MAX_SIZE 0xff000000 +#define SDRAM_BANK_SIZE (2UL << 30) + +#ifndef CONFIG_SPL_BUILD + +#define ENV_MEM_LAYOUT_SETTINGS \ + "scriptaddr=0x00500000\0" \ + "pxefile_addr_r=0x00600000\0" \ + "fdt_addr_r=0x08300000\0" \ + "kernel_addr_r=0x00280000\0" \ + "kernel_addr_c=0x03e80000\0" \ + "ramdisk_addr_r=0x0a200000\0" + +#include +#define CONFIG_EXTRA_ENV_SETTINGS \ + ENV_MEM_LAYOUT_SETTINGS \ + "fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \ + "partitions=" PARTS_DEFAULT \ + ROCKCHIP_DEVICE_SETTINGS \ + BOOTENV + +#endif + +#endif diff --git a/include/dt-bindings/power/px30-power.h b/include/dt-bindings/power/px30-power.h new file mode 100644 index 00000000000..30917a99ad2 --- /dev/null +++ b/include/dt-bindings/power/px30-power.h @@ -0,0 +1,27 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __DT_BINDINGS_POWER_PX30_POWER_H__ +#define __DT_BINDINGS_POWER_PX30_POWER_H__ + +/* VD_CORE */ +#define PX30_PD_A35_0 0 +#define PX30_PD_A35_1 1 +#define PX30_PD_A35_2 2 +#define PX30_PD_A35_3 3 +#define PX30_PD_SCU 4 + +/* VD_LOGIC */ +#define PX30_PD_USB 5 +#define PX30_PD_DDR 6 +#define PX30_PD_SDCARD 7 +#define PX30_PD_CRYPTO 8 +#define PX30_PD_GMAC 9 +#define PX30_PD_MMC_NAND 10 +#define PX30_PD_VPU 11 +#define PX30_PD_VO 12 +#define PX30_PD_VI 13 +#define PX30_PD_GPU 14 + +/* VD_PMU */ +#define PX30_PD_PMU 15 + +#endif diff --git a/include/dt-bindings/soc/rockchip,boot-mode.h b/include/dt-bindings/soc/rockchip,boot-mode.h new file mode 100644 index 00000000000..4b0914c0989 --- /dev/null +++ b/include/dt-bindings/soc/rockchip,boot-mode.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __ROCKCHIP_BOOT_MODE_H +#define __ROCKCHIP_BOOT_MODE_H + +/*high 24 bits is tag, low 8 bits is type*/ +#define REBOOT_FLAG 0x5242C300 +/* normal boot */ +#define BOOT_NORMAL (REBOOT_FLAG + 0) +/* enter bootloader rockusb mode */ +#define BOOT_BL_DOWNLOAD (REBOOT_FLAG + 1) +/* enter recovery */ +#define BOOT_RECOVERY (REBOOT_FLAG + 3) + /* enter fastboot mode */ +#define BOOT_FASTBOOT (REBOOT_FLAG + 9) + +#endif -- cgit v1.3.1 From d49a526750754cc93ffaa1182cfdf7ffa723e4b6 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Thu, 11 Jul 2019 10:42:16 +0200 Subject: rockchip: clk: add px30 clock driver The px30 contains 2 separate clock controllers, pmucru and cru. Add drivers for them. Signed-off-by: Kever Yang Signed-off-by: Heiko Stuebner Reviewed-by: Kever Yang --- 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 (limited to 'include') diff --git a/arch/arm/include/asm/arch-rockchip/cru_px30.h b/arch/arm/include/asm/arch-rockchip/cru_px30.h new file mode 100644 index 00000000000..7d9fd181aca --- /dev/null +++ b/arch/arm/include/asm/arch-rockchip/cru_px30.h @@ -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 + +#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 diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 41cfb7ad3fd..f9134fd51f1 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -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 diff --git a/drivers/clk/rockchip/clk_px30.c b/drivers/clk/rockchip/clk_px30.c new file mode 100644 index 00000000000..36764c128b0 --- /dev/null +++ b/drivers/clk/rockchip/clk_px30.c @@ -0,0 +1,1630 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2017 Rockchip Electronics Co., Ltd + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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, +}; diff --git a/include/dt-bindings/clock/px30-cru.h b/include/dt-bindings/clock/px30-cru.h new file mode 100644 index 00000000000..e5e59690b5f --- /dev/null +++ b/include/dt-bindings/clock/px30-cru.h @@ -0,0 +1,389 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2017 Rockchip Electronics Co. Ltd. + * Author: Elaine + */ + +#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 -- cgit v1.3.1 From deebba82d95a0cb43f02629651b66d539b0bf0cb Mon Sep 17 00:00:00 2001 From: Heiko Stuebner Date: Tue, 16 Jul 2019 22:19:43 +0200 Subject: rockchip: add px30-evb board The px30 evb is an evaluation board for the px30 together with a dsi- connected display. This adds board and config files for it. Signed-off-by: Heiko Stuebner Reviewed-by: Kever Yang --- board/rockchip/evb_px30/Kconfig | 15 +++++ board/rockchip/evb_px30/MAINTAINERS | 6 ++ board/rockchip/evb_px30/Makefile | 7 +++ board/rockchip/evb_px30/evb_px30.c | 4 ++ configs/evb-px30_defconfig | 111 ++++++++++++++++++++++++++++++++++++ include/configs/evb_px30.h | 19 ++++++ 6 files changed, 162 insertions(+) create mode 100644 board/rockchip/evb_px30/Kconfig create mode 100644 board/rockchip/evb_px30/MAINTAINERS create mode 100644 board/rockchip/evb_px30/Makefile create mode 100644 board/rockchip/evb_px30/evb_px30.c create mode 100644 configs/evb-px30_defconfig create mode 100644 include/configs/evb_px30.h (limited to 'include') diff --git a/board/rockchip/evb_px30/Kconfig b/board/rockchip/evb_px30/Kconfig new file mode 100644 index 00000000000..0042c8e4db1 --- /dev/null +++ b/board/rockchip/evb_px30/Kconfig @@ -0,0 +1,15 @@ +if TARGET_EVB_PX30 + +config SYS_BOARD + default "evb_px30" + +config SYS_VENDOR + default "rockchip" + +config SYS_CONFIG_NAME + default "evb_px30" + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + +endif diff --git a/board/rockchip/evb_px30/MAINTAINERS b/board/rockchip/evb_px30/MAINTAINERS new file mode 100644 index 00000000000..cf13f2419ea --- /dev/null +++ b/board/rockchip/evb_px30/MAINTAINERS @@ -0,0 +1,6 @@ +EVB-PX30 +M: Kever Yang +S: Maintained +F: board/rockchip/evb_px30 +F: include/configs/evb_px30.h +F: configs/evb-px30_defconfig diff --git a/board/rockchip/evb_px30/Makefile b/board/rockchip/evb_px30/Makefile new file mode 100644 index 00000000000..74b0b9f44fa --- /dev/null +++ b/board/rockchip/evb_px30/Makefile @@ -0,0 +1,7 @@ +# +# (C) Copyright 2017 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += evb_px30.o diff --git a/board/rockchip/evb_px30/evb_px30.c b/board/rockchip/evb_px30/evb_px30.c new file mode 100644 index 00000000000..29464ae63ec --- /dev/null +++ b/board/rockchip/evb_px30/evb_px30.c @@ -0,0 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2019 Rockchip Electronics Co., Ltd + */ diff --git a/configs/evb-px30_defconfig b/configs/evb-px30_defconfig new file mode 100644 index 00000000000..36fba600c09 --- /dev/null +++ b/configs/evb-px30_defconfig @@ -0,0 +1,111 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SYS_TEXT_BASE=0x00200000 +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_ROCKCHIP_PX30=y +CONFIG_TARGET_EVB_PX30=y +CONFIG_TPL_LIBGENERIC_SUPPORT=y +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_SPL_STACK_R_ADDR=0x600000 +CONFIG_NR_DRAM_BANKS=1 +CONFIG_DEBUG_UART_BASE=0xFF160000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART=y +CONFIG_SPL_TEXT_BASE=0x00000000 +CONFIG_TPL_SYS_MALLOC_F_LEN=0x600 +# CONFIG_ANDROID_BOOT_IMAGE is not set +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_SPL_LOAD_FIT=y +# CONFIG_CONSOLE_MUX is not set +CONFIG_DEFAULT_FDT_FILE="rockchip/px30-evb.dtb" +CONFIG_MISC_INIT_R=y +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_SPL_BOOTROM_SUPPORT=y +# CONFIG_SPL_RAW_IMAGE_SUPPORT is not set +CONFIG_SPL_STACK_R=y +# CONFIG_TPL_BANNER_PRINT is not set +CONFIG_SPL_CRC32_SUPPORT=y +CONFIG_SPL_ATF=y +# CONFIG_TPL_FRAMEWORK is not set +# CONFIG_CMD_BOOTD is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_LZMADEC is not set +# CONFIG_CMD_UNZIP is not set +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPT=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +# CONFIG_CMD_ITEST is not set +# CONFIG_CMD_SETEXPR is not set +# CONFIG_CMD_MISC is not set +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_ISO_PARTITION is not set +CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64 +CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_LIVE=y +CONFIG_DEFAULT_DEVICE_TREE="px30-evb" +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_ENV_IS_IN_MMC=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_FASTBOOT_BUF_ADDR=0x800800 +CONFIG_FASTBOOT_BUF_SIZE=0x04000000 +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_ROCKCHIP_GPIO=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_MISC=y +CONFIG_ROCKCHIP_OTP=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_PHY_REALTEK=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_PINCTRL=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_RK8XX=y +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_REGULATOR_RK8XX=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_TPL_RAM=y +CONFIG_ROCKCHIP_SDRAM_COMMON=y +CONFIG_DM_RESET=y +# CONFIG_SPECIFY_CONSOLE_INDEX is not set +# CONFIG_TPL_DM_SERIAL is not set +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_SKIP_INIT=y +CONFIG_SOUND=y +CONFIG_SYSRESET=y +CONFIG_OPTEE=y +CONFIG_DM_THERMAL=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DWC2_OTG=y +CONFIG_DM_VIDEO=y +CONFIG_DISPLAY=y +CONFIG_LCD=y +CONFIG_SPL_TINY_MEMSET=y +CONFIG_TPL_TINY_MEMSET=y +CONFIG_LZ4=y +CONFIG_LZO=y +CONFIG_ERRNO_STR=y +# CONFIG_EFI_LOADER is not set diff --git a/include/configs/evb_px30.h b/include/configs/evb_px30.h new file mode 100644 index 00000000000..e761c7c5196 --- /dev/null +++ b/include/configs/evb_px30.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2017 Rockchip Electronics Co., Ltd + */ + +#ifndef __EVB_PX30_H +#define __EVB_PX30_H + +#include + +#define CONFIG_SYS_MMC_ENV_DEV 0 + +#define ROCKCHIP_DEVICE_SETTINGS \ + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0" + +#define CONFIG_SUPPORT_EMMC_RPMB + +#endif -- cgit v1.3.1 From e76943ca6fe690bce5386105a8b671db12c6a736 Mon Sep 17 00:00:00 2001 From: Kever Yang Date: Wed, 16 Oct 2019 17:13:31 +0800 Subject: rockchip: usb: Migrate to use ofnode Migrate to use ofnode_* instead of fdt_* so that we may able to use live dt for usb udc driver. Signed-off-by: Kever Yang --- arch/arm/mach-rockchip/board.c | 14 ++++++-------- drivers/usb/phy/rockchip_usb2_phy.c | 5 ++--- include/usb/dwc2_udc.h | 4 +++- 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c index 8ca34637315..c4b0b9dfe2c 100644 --- a/arch/arm/mach-rockchip/board.c +++ b/arch/arm/mach-rockchip/board.c @@ -61,28 +61,26 @@ static struct dwc2_plat_otg_data otg_data = { int board_usb_init(int index, enum usb_init_type init) { - int node; + ofnode node; const char *mode; bool matched = false; - const void *blob = gd->fdt_blob; /* find the usb_otg node */ - node = fdt_node_offset_by_compatible(blob, -1, "snps,dwc2"); - - while (node > 0) { - mode = fdt_getprop(blob, node, "dr_mode", NULL); + node = ofnode_by_compatible(ofnode_null(), "snps,dwc2"); + while (ofnode_valid(node)) { + mode = ofnode_read_string(node, "dr_mode"); if (mode && strcmp(mode, "otg") == 0) { matched = true; break; } - node = fdt_node_offset_by_compatible(blob, node, "snps,dwc2"); + node = ofnode_by_compatible(node, "snps,dwc2"); } if (!matched) { debug("Not found usb_otg device\n"); return -ENODEV; } - otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg"); + otg_data.regs_otg = ofnode_get_addr(node); return dwc2_udc_probe(&otg_data); } diff --git a/drivers/usb/phy/rockchip_usb2_phy.c b/drivers/usb/phy/rockchip_usb2_phy.c index 16e899954a3..69e408b6c1b 100644 --- a/drivers/usb/phy/rockchip_usb2_phy.c +++ b/drivers/usb/phy/rockchip_usb2_phy.c @@ -5,7 +5,6 @@ #include #include -#include #include "../gadget/dwc2_udc_otg_priv.h" @@ -71,8 +70,8 @@ void otg_phy_init(struct dwc2_udc *dev) for (i = 0; i < ARRAY_SIZE(rockchip_usb2_phy_dt_ids); i++) { of_id = &rockchip_usb2_phy_dt_ids[i]; - if (fdt_node_check_compatible(gd->fdt_blob, pdata->phy_of_node, - of_id->compatible) == 0) { + if (ofnode_device_is_compatible(pdata->phy_of_node, + of_id->compatible)){ phy_cfg = (struct rockchip_usb2_phy_cfg *)of_id->data; break; } diff --git a/include/usb/dwc2_udc.h b/include/usb/dwc2_udc.h index a6c12212a9b..a2af381a667 100644 --- a/include/usb/dwc2_udc.h +++ b/include/usb/dwc2_udc.h @@ -8,12 +8,14 @@ #ifndef __DWC2_USB_GADGET #define __DWC2_USB_GADGET +#include + #define PHY0_SLEEP (1 << 5) #define DWC2_MAX_HW_ENDPOINTS 16 struct dwc2_plat_otg_data { void *priv; - int phy_of_node; + ofnode phy_of_node; int (*phy_control)(int on); uintptr_t regs_phy; uintptr_t regs_otg; -- cgit v1.3.1 From de43ca7e3ee4b71793880b540bb3b958a02e6c04 Mon Sep 17 00:00:00 2001 From: Vasily Khoruzhick Date: Sat, 9 Nov 2019 11:24:50 -0800 Subject: rockchip: rk3399: split rockpro64 out of evb_rk3399 rockpro64 needs to setup I/O domains in order for USB to work in u-boot. Since we currently don't have a driver to do that, split it into its own board file and initialize I/O domains here. Signed-off-by: Vasily Khoruzhick Reviewed-by: Kever Yang --- arch/arm/mach-rockchip/rk3399/Kconfig | 20 +++++++++ board/pine64/rockpro64_rk3399/Kconfig | 15 +++++++ board/pine64/rockpro64_rk3399/MAINTAINERS | 8 ++++ board/pine64/rockpro64_rk3399/Makefile | 7 +++ board/pine64/rockpro64_rk3399/rockpro64-rk3399.c | 55 ++++++++++++++++++++++++ board/rockchip/evb_rk3399/MAINTAINERS | 7 --- configs/rockpro64-rk3399_defconfig | 1 + include/configs/rockpro64_rk3399.h | 15 +++++++ 8 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 board/pine64/rockpro64_rk3399/Kconfig create mode 100644 board/pine64/rockpro64_rk3399/MAINTAINERS create mode 100644 board/pine64/rockpro64_rk3399/Makefile create mode 100644 board/pine64/rockpro64_rk3399/rockpro64-rk3399.c create mode 100644 include/configs/rockpro64_rk3399.h (limited to 'include') diff --git a/arch/arm/mach-rockchip/rk3399/Kconfig b/arch/arm/mach-rockchip/rk3399/Kconfig index f781eacd163..01af3f1464c 100644 --- a/arch/arm/mach-rockchip/rk3399/Kconfig +++ b/arch/arm/mach-rockchip/rk3399/Kconfig @@ -62,6 +62,25 @@ config TARGET_CHROMEBOOK_BOB display. It includes a Chrome OS EC (Cortex-M3) to provide access to the keyboard and battery functions. +config TARGET_ROCKPRO64_RK3399 + bool "Pine64 Rockpro64 board" + help + Rockro64 is SBC produced by Pine64. Key features: + + * Rockchip RK3399 + * 2/4GB Dual-Channel LPDDR3 + * SD card slot + * eMMC socket + * 128Mb SPI Flash + * Gigabit ethernet + * PCIe 4X slot + * WiFI/BT module socket + * HDMI In/Out, DP, MIPI DSI/CSI, eDP + * USB 3.0, 2.0 + * USB Type C power and data + * GPIO expansion ports + * DC 12V/2A + endchoice config ROCKCHIP_BOOT_MODE_REG @@ -98,5 +117,6 @@ source "board/rockchip/evb_rk3399/Kconfig" source "board/theobroma-systems/puma_rk3399/Kconfig" source "board/vamrs/rock960_rk3399/Kconfig" source "board/google/gru/Kconfig" +source "board/pine64/rockpro64_rk3399/Kconfig" endif diff --git a/board/pine64/rockpro64_rk3399/Kconfig b/board/pine64/rockpro64_rk3399/Kconfig new file mode 100644 index 00000000000..3353f1fd095 --- /dev/null +++ b/board/pine64/rockpro64_rk3399/Kconfig @@ -0,0 +1,15 @@ +if TARGET_ROCKPRO64_RK3399 + +config SYS_BOARD + default "rockpro64_rk3399" + +config SYS_VENDOR + default "pine64" + +config SYS_CONFIG_NAME + default "rockpro64_rk3399" + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + +endif diff --git a/board/pine64/rockpro64_rk3399/MAINTAINERS b/board/pine64/rockpro64_rk3399/MAINTAINERS new file mode 100644 index 00000000000..303db144aab --- /dev/null +++ b/board/pine64/rockpro64_rk3399/MAINTAINERS @@ -0,0 +1,8 @@ +ROCKPRO64 +M: Akash Gajjar +M: Jagan Teki +S: Maintained +F: board/pine64/rockpro64_rk3399 +F: include/configs/rockpro64_rk3399.h +F: arch/arm/dts/rk3399-rockpro64-u-boot.dtsi +F: configs/rockpro64-rk3399_defconfig diff --git a/board/pine64/rockpro64_rk3399/Makefile b/board/pine64/rockpro64_rk3399/Makefile new file mode 100644 index 00000000000..b015c47e6fa --- /dev/null +++ b/board/pine64/rockpro64_rk3399/Makefile @@ -0,0 +1,7 @@ +# +# (C) Copyright 2019 Vasily Khoruzhick +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += rockpro64-rk3399.o diff --git a/board/pine64/rockpro64_rk3399/rockpro64-rk3399.c b/board/pine64/rockpro64_rk3399/rockpro64-rk3399.c new file mode 100644 index 00000000000..3f602357713 --- /dev/null +++ b/board/pine64/rockpro64_rk3399/rockpro64-rk3399.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2019 Vasily Khoruzhick + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define GRF_IO_VSEL_BT565_SHIFT 0 +#define PMUGRF_CON0_VSEL_SHIFT 8 + +#ifdef CONFIG_MISC_INIT_R +static void setup_iodomain(void) +{ + struct rk3399_grf_regs *grf = + syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + struct rk3399_pmugrf_regs *pmugrf = + syscon_get_first_range(ROCKCHIP_SYSCON_PMUGRF); + + /* BT565 is in 1.8v domain */ + rk_setreg(&grf->io_vsel, 1 << GRF_IO_VSEL_BT565_SHIFT); + + /* Set GPIO1 1.8v/3.0v source select to PMU1830_VOL */ + rk_setreg(&pmugrf->soc_con0, 1 << PMUGRF_CON0_VSEL_SHIFT); +} + +int misc_init_r(void) +{ + const u32 cpuid_offset = 0x7; + const u32 cpuid_length = 0x10; + u8 cpuid[cpuid_length]; + int ret; + + setup_iodomain(); + + ret = rockchip_cpuid_from_efuse(cpuid_offset, cpuid_length, cpuid); + if (ret) + return ret; + + ret = rockchip_cpuid_set(cpuid, cpuid_length); + if (ret) + return ret; + + ret = rockchip_setup_macaddr(); + + return ret; +} + +#endif diff --git a/board/rockchip/evb_rk3399/MAINTAINERS b/board/rockchip/evb_rk3399/MAINTAINERS index 1c508e5d5b9..eab4c4c5259 100644 --- a/board/rockchip/evb_rk3399/MAINTAINERS +++ b/board/rockchip/evb_rk3399/MAINTAINERS @@ -67,10 +67,3 @@ M: Jagan Teki S: Maintained F: configs/rock-pi-4-rk3399_defconfig F: arch/arm/dts/rk3399-rock-pi-4-u-boot.dtsi - -ROCKPRO64 -M: Akash Gajjar -M: Jagan Teki -S: Maintained -F: configs/rockpro64-rk3399_defconfig -F: arch/arm/dts/rk3399-rockpro64-u-boot.dtsi diff --git a/configs/rockpro64-rk3399_defconfig b/configs/rockpro64-rk3399_defconfig index 423148b1a56..94279ed842b 100644 --- a/configs/rockpro64-rk3399_defconfig +++ b/configs/rockpro64-rk3399_defconfig @@ -2,6 +2,7 @@ CONFIG_ARM=y CONFIG_ARCH_ROCKCHIP=y CONFIG_SYS_TEXT_BASE=0x00200000 CONFIG_ROCKCHIP_RK3399=y +CONFIG_TARGET_ROCKPRO64_RK3399=y CONFIG_NR_DRAM_BANKS=1 CONFIG_DEBUG_UART_BASE=0xFF1A0000 CONFIG_DEBUG_UART_CLOCK=24000000 diff --git a/include/configs/rockpro64_rk3399.h b/include/configs/rockpro64_rk3399.h new file mode 100644 index 00000000000..5f52c1e4f60 --- /dev/null +++ b/include/configs/rockpro64_rk3399.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2019 Vasily Khoruzhick + */ + +#ifndef __ROCKPRO64_RK3399_H +#define __ROCKPRO64_RK3399_H + +#include + +#define CONFIG_SYS_MMC_ENV_DEV 0 + +#define SDRAM_BANK_SIZE (2UL << 30) + +#endif -- cgit v1.3.1 From f1a225229a64168fa489b5f8c82264f1857f6b60 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Thu, 14 Nov 2019 11:21:12 +0800 Subject: arm: rockchip: Add RK3308 SOC support RK3308 is a quad Cortex A35 based SOC with rich audio interfaces(I2S/PCM/TDM/PDM/SPDIF/VAD/HDMI ARC), which designed for intelligent voice interaction and audio input/output processing. Signed-off-by: Andy Yan Reviewed-by: Kever Yang --- arch/arm/include/asm/arch-rk3308/boot0.h | 11 + arch/arm/include/asm/arch-rk3308/cru_rk3308.h | 290 ++++++++++++++++++++++++++ arch/arm/include/asm/arch-rk3308/gpio.h | 11 + arch/arm/include/asm/arch-rk3308/grf_rk3308.h | 197 +++++++++++++++++ arch/arm/mach-rockchip/Kconfig | 24 +++ arch/arm/mach-rockchip/Makefile | 1 + arch/arm/mach-rockchip/rk3308/Kconfig | 14 ++ arch/arm/mach-rockchip/rk3308/Makefile | 9 + arch/arm/mach-rockchip/rk3308/clk_rk3308.c | 31 +++ arch/arm/mach-rockchip/rk3308/rk3308.c | 175 ++++++++++++++++ arch/arm/mach-rockchip/rk3308/syscon_rk3308.c | 20 ++ include/configs/rk3308_common.h | 58 ++++++ 12 files changed, 841 insertions(+) create mode 100644 arch/arm/include/asm/arch-rk3308/boot0.h create mode 100644 arch/arm/include/asm/arch-rk3308/cru_rk3308.h create mode 100644 arch/arm/include/asm/arch-rk3308/gpio.h create mode 100644 arch/arm/include/asm/arch-rk3308/grf_rk3308.h create mode 100644 arch/arm/mach-rockchip/rk3308/Kconfig create mode 100644 arch/arm/mach-rockchip/rk3308/Makefile create mode 100644 arch/arm/mach-rockchip/rk3308/clk_rk3308.c create mode 100644 arch/arm/mach-rockchip/rk3308/rk3308.c create mode 100644 arch/arm/mach-rockchip/rk3308/syscon_rk3308.c create mode 100644 include/configs/rk3308_common.h (limited to 'include') diff --git a/arch/arm/include/asm/arch-rk3308/boot0.h b/arch/arm/include/asm/arch-rk3308/boot0.h new file mode 100644 index 00000000000..2e78b074ade --- /dev/null +++ b/arch/arm/include/asm/arch-rk3308/boot0.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2019 Rockchip Electronics Co., Ltd + */ + +#ifndef __ASM_ARCH_BOOT0_H__ +#define __ASM_ARCH_BOOT0_H__ + +#include + +#endif diff --git a/arch/arm/include/asm/arch-rk3308/cru_rk3308.h b/arch/arm/include/asm/arch-rk3308/cru_rk3308.h new file mode 100644 index 00000000000..a14b64cdb3e --- /dev/null +++ b/arch/arm/include/asm/arch-rk3308/cru_rk3308.h @@ -0,0 +1,290 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2018 Rockchip Electronics Co., Ltd. + */ +#ifndef _ASM_ARCH_CRU_RK3308_H +#define _ASM_ARCH_CRU_RK3308_H + +#include + +#define MHz 1000000 +#define OSC_HZ (24 * MHz) + +#define APLL_HZ (816 * MHz) + +#define CORE_ACLK_HZ 408000000 +#define CORE_DBG_HZ 204000000 + +#define BUS_ACLK_HZ 200000000 +#define BUS_HCLK_HZ 100000000 +#define BUS_PCLK_HZ 100000000 + +#define PERI_ACLK_HZ 200000000 +#define PERI_HCLK_HZ 100000000 +#define PERI_PCLK_HZ 100000000 + +#define AUDIO_HCLK_HZ 100000000 +#define AUDIO_PCLK_HZ 100000000 + +#define RK3308_PLL_CON(x) ((x) * 0x4) +#define RK3308_MODE_CON 0xa0 + +/* RK3308 pll id */ +enum rk3308_pll_id { + APLL, + DPLL, + VPLL0, + VPLL1, + PLL_COUNT, +}; + +struct rk3308_clk_info { + unsigned long id; + char *name; +}; + +/* Private data for the clock driver - used by rockchip_get_cru() */ +struct rk3308_clk_priv { + struct rk3308_cru *cru; + ulong armclk_hz; + ulong dpll_hz; + ulong vpll0_hz; + ulong vpll1_hz; +}; + +struct rk3308_cru { + struct rk3308_pll { + unsigned int con0; + unsigned int con1; + unsigned int con2; + unsigned int con3; + unsigned int con4; + unsigned int reserved0[3]; + } 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 pll_lock; + unsigned int reserved3[6]; + 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[74]; + unsigned int reserved6[54]; + unsigned int clkgate_con[15]; + unsigned int reserved7[(0x380 - 0x338) / 4 - 1]; + unsigned int ssgtbl[32]; + unsigned int softrst_con[10]; + unsigned int reserved8[(0x480 - 0x424) / 4 - 1]; + unsigned int sdmmc_con[2]; + unsigned int sdio_con[2]; + unsigned int emmc_con[2]; +}; + +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, + VPLL1_MODE_SHIFT = 6, + VPLL1_MODE_MASK = 3 << VPLL1_MODE_SHIFT, + VPLL0_MODE_SHIFT = 4, + VPLL0_MODE_MASK = 3 << VPLL0_MODE_SHIFT, + DPLL_MODE_SHIFT = 2, + DPLL_MODE_MASK = 3 << DPLL_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 = 0x7 << CORE_ACLK_DIV_SHIFT, + CORE_DBG_DIV_SHIFT = 8, + CORE_DBG_DIV_MASK = 0xf << CORE_DBG_DIV_SHIFT, + CORE_CLK_PLL_SEL_SHIFT = 6, + CORE_CLK_PLL_SEL_MASK = 0x3 << CORE_CLK_PLL_SEL_SHIFT, + CORE_CLK_PLL_SEL_APLL = 0, + CORE_CLK_PLL_SEL_VPLL0, + CORE_CLK_PLL_SEL_VPLL1, + CORE_DIV_CON_SHIFT = 0, + CORE_DIV_CON_MASK = 0x0f << CORE_DIV_CON_SHIFT, + + /* CRU_CLK_SEL5_CON */ + BUS_PLL_SEL_SHIFT = 6, + BUS_PLL_SEL_MASK = 0x3 << BUS_PLL_SEL_SHIFT, + BUS_PLL_SEL_DPLL = 0, + BUS_PLL_SEL_VPLL0, + BUS_PLL_SEL_VPLL1, + BUS_ACLK_DIV_SHIFT = 0, + BUS_ACLK_DIV_MASK = 0x1f << BUS_ACLK_DIV_SHIFT, + + /* CRU_CLK_SEL6_CON */ + BUS_PCLK_DIV_SHIFT = 8, + BUS_PCLK_DIV_MASK = 0x1f << BUS_PCLK_DIV_SHIFT, + BUS_HCLK_DIV_SHIFT = 0, + BUS_HCLK_DIV_MASK = 0x1f << BUS_HCLK_DIV_SHIFT, + + /* CRU_CLK_SEL7_CON */ + CRYPTO_APK_SEL_SHIFT = 14, + CRYPTO_APK_PLL_SEL_MASK = 3 << CRYPTO_APK_SEL_SHIFT, + CRYPTO_PLL_SEL_DPLL = 0, + CRYPTO_PLL_SEL_VPLL0, + CRYPTO_PLL_SEL_VPLL1 = 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_SEL8_CON */ + DCLK_VOP_SEL_SHIFT = 14, + DCLK_VOP_SEL_MASK = 0x3 << DCLK_VOP_SEL_SHIFT, + DCLK_VOP_SEL_DIVOUT = 0, + DCLK_VOP_SEL_FRACOUT, + DCLK_VOP_SEL_24M, + DCLK_VOP_PLL_SEL_SHIFT = 10, + DCLK_VOP_PLL_SEL_MASK = 0x3 << DCLK_VOP_PLL_SEL_SHIFT, + DCLK_VOP_PLL_SEL_DPLL = 0, + DCLK_VOP_PLL_SEL_VPLL0, + DCLK_VOP_PLL_SEL_VPLL1, + DCLK_VOP_DIV_SHIFT = 0, + DCLK_VOP_DIV_MASK = 0xff, + + /* CRU_CLK_SEL25_CON */ + /* CRU_CLK_SEL26_CON */ + /* CRU_CLK_SEL27_CON */ + /* CRU_CLK_SEL28_CON */ + CLK_I2C_PLL_SEL_SHIFT = 14, + CLK_I2C_PLL_SEL_MASK = 0x3 << CLK_I2C_PLL_SEL_SHIFT, + CLK_I2C_PLL_SEL_DPLL = 0, + CLK_I2C_PLL_SEL_VPLL0, + CLK_I2C_PLL_SEL_24M, + CLK_I2C_DIV_CON_SHIFT = 0, + CLK_I2C_DIV_CON_MASK = 0x7f << CLK_I2C_DIV_CON_SHIFT, + + /* CRU_CLK_SEL29_CON */ + CLK_PWM_PLL_SEL_SHIFT = 14, + CLK_PWM_PLL_SEL_MASK = 0x3 << CLK_PWM_PLL_SEL_SHIFT, + CLK_PWM_PLL_SEL_DPLL = 0, + CLK_PWM_PLL_SEL_VPLL0, + CLK_PWM_PLL_SEL_24M, + CLK_PWM_DIV_CON_SHIFT = 0, + CLK_PWM_DIV_CON_MASK = 0x7f << CLK_PWM_DIV_CON_SHIFT, + + /* CRU_CLK_SEL30_CON */ + /* CRU_CLK_SEL31_CON */ + /* CRU_CLK_SEL32_CON */ + CLK_SPI_PLL_SEL_SHIFT = 14, + CLK_SPI_PLL_SEL_MASK = 0x3 << CLK_SPI_PLL_SEL_SHIFT, + CLK_SPI_PLL_SEL_DPLL = 0, + CLK_SPI_PLL_SEL_VPLL0, + CLK_SPI_PLL_SEL_24M, + CLK_SPI_DIV_CON_SHIFT = 0, + CLK_SPI_DIV_CON_MASK = 0x7f << CLK_SPI_DIV_CON_SHIFT, + + /* CRU_CLK_SEL34_CON */ + CLK_SARADC_DIV_CON_SHIFT = 0, + CLK_SARADC_DIV_CON_MASK = 0x7ff << CLK_SARADC_DIV_CON_SHIFT, + + /* CRU_CLK_SEL36_CON */ + PERI_PLL_SEL_SHIFT = 6, + PERI_PLL_SEL_MASK = 0x3 << PERI_PLL_SEL_SHIFT, + PERI_PLL_DPLL = 0, + PERI_PLL_VPLL0, + PERI_PLL_VPLL1, + PERI_ACLK_DIV_SHIFT = 0, + PERI_ACLK_DIV_MASK = 0x1f << PERI_ACLK_DIV_SHIFT, + + /* CRU_CLK_SEL37_CON */ + PERI_PCLK_DIV_SHIFT = 8, + PERI_PCLK_DIV_MASK = 0x1f << PERI_PCLK_DIV_SHIFT, + PERI_HCLK_DIV_SHIFT = 0, + PERI_HCLK_DIV_MASK = 0x1f << PERI_HCLK_DIV_SHIFT, + + /* CRU_CLKSEL41_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_PLL_SHIFT = 8, + EMMC_PLL_MASK = 0x3 << EMMC_PLL_SHIFT, + EMMC_SEL_DPLL = 0, + EMMC_SEL_VPLL0, + EMMC_SEL_VPLL1, + EMMC_SEL_24M, + EMMC_DIV_SHIFT = 0, + EMMC_DIV_MASK = 0xff << EMMC_DIV_SHIFT, + + /* CRU_CLKSEL43_CON */ + MAC_CLK_SPEED_SEL_SHIFT = 15, + MAC_CLK_SPEED_SEL_MASK = 1 << MAC_CLK_SPEED_SEL_SHIFT, + MAC_CLK_SPEED_SEL_10M = 0, + MAC_CLK_SPEED_SEL_100M, + MAC_CLK_SOURCE_SEL_SHIFT = 14, + MAC_CLK_SOURCE_SEL_MASK = 1 << MAC_CLK_SOURCE_SEL_SHIFT, + MAC_CLK_SOURCE_SEL_INTERNAL = 0, + MAC_CLK_SOURCE_SEL_EXTERNAL, + MAC_PLL_SHIFT = 6, + MAC_PLL_MASK = 0x3 << MAC_PLL_SHIFT, + MAC_SEL_DPLL = 0, + MAC_SEL_VPLL0, + MAC_SEL_VPLL1, + MAC_DIV_SHIFT = 0, + MAC_DIV_MASK = 0x1f << MAC_DIV_SHIFT, + + /* CRU_CLK_SEL45_CON */ + AUDIO_PCLK_DIV_SHIFT = 8, + AUDIO_PCLK_DIV_MASK = 0x1f << AUDIO_PCLK_DIV_SHIFT, + AUDIO_PLL_SEL_SHIFT = 6, + AUDIO_PLL_SEL_MASK = 0x3 << AUDIO_PLL_SEL_SHIFT, + AUDIO_PLL_VPLL0 = 0, + AUDIO_PLL_VPLL1, + AUDIO_PLL_24M, + AUDIO_HCLK_DIV_SHIFT = 0, + AUDIO_HCLK_DIV_MASK = 0x1f << AUDIO_HCLK_DIV_SHIFT, +}; + +check_member(rk3308_cru, emmc_con[1], 0x494); + +#endif diff --git a/arch/arm/include/asm/arch-rk3308/gpio.h b/arch/arm/include/asm/arch-rk3308/gpio.h new file mode 100644 index 00000000000..eca79d51594 --- /dev/null +++ b/arch/arm/include/asm/arch-rk3308/gpio.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2019 Rockchip Electronics Co., Ltd + */ + +#ifndef __ASM_ARCH_GPIO_H__ +#define __ASM_ARCH_GPIO_H__ + +#include + +#endif diff --git a/arch/arm/include/asm/arch-rk3308/grf_rk3308.h b/arch/arm/include/asm/arch-rk3308/grf_rk3308.h new file mode 100644 index 00000000000..3e68626d3e9 --- /dev/null +++ b/arch/arm/include/asm/arch-rk3308/grf_rk3308.h @@ -0,0 +1,197 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + *Copyright 2019 Rockchip Electronics Co., Ltd. + */ +#ifndef _ASM_ARCH_GRF_rk3308_H +#define _ASM_ARCH_GRF_rk3308_H + +#include + +struct rk3308_grf { + unsigned int gpio0a_iomux; + unsigned int reserved0; + unsigned int gpio0b_iomux; + unsigned int reserved1; + unsigned int gpio0c_iomux; + unsigned int reserved2[3]; + unsigned int gpio1a_iomux; + unsigned int reserved3; + unsigned int gpio1bl_iomux; + unsigned int gpio1bh_iomux; + unsigned int gpio1cl_iomux; + unsigned int gpio1ch_iomux; + unsigned int gpio1d_iomux; + unsigned int reserved4; + unsigned int gpio2a_iomux; + unsigned int reserved5; + unsigned int gpio2b_iomux; + unsigned int reserved6; + unsigned int gpio2c_iomux; + unsigned int reserved7[3]; + unsigned int gpio3a_iomux; + unsigned int reserved8; + unsigned int gpio3b_iomux; + unsigned int reserved9[5]; + unsigned int gpio4a_iomux; + unsigned int reserved33; + unsigned int gpio4b_iomux; + unsigned int reserved10; + unsigned int gpio4c_iomux; + unsigned int reserved11; + unsigned int gpio4d_iomux; + unsigned int reserved34; + unsigned int gpio0a_p; + unsigned int gpio0b_p; + unsigned int gpio0c_p; + unsigned int reserved12; + unsigned int gpio1a_p; + unsigned int gpio1b_p; + unsigned int gpio1c_p; + unsigned int gpio1d_p; + unsigned int gpio2a_p; + unsigned int gpio2b_p; + unsigned int gpio2c_p; + unsigned int reserved13; + unsigned int gpio3a_p; + unsigned int gpio3b_p; + unsigned int reserved14[2]; + unsigned int gpio4a_p; + unsigned int gpio4b_p; + unsigned int gpio4c_p; + unsigned int gpio4d_p; + unsigned int reserved15[(0x100 - 0xec) / 4 - 1]; + unsigned int gpio0a_e; + unsigned int gpio0b_e; + unsigned int gpio0c_e; + unsigned int reserved16; + unsigned int gpio1a_e; + unsigned int gpio1b_e; + unsigned int gpio1c_e; + unsigned int gpio1d_e; + unsigned int gpio2a_e; + unsigned int gpio2b_e; + unsigned int gpio2c_e; + unsigned int reserved17; + unsigned int gpio3a_e; + unsigned int gpio3b_e; + unsigned int reserved18[2]; + unsigned int gpio4a_e; + unsigned int gpio4b_e; + unsigned int gpio4c_e; + unsigned int gpio4d_e; + unsigned int gpio0a_sr; + unsigned int gpio0b_sr; + unsigned int gpio0c_sr; + unsigned int reserved19; + unsigned int gpio1a_sr; + unsigned int gpio1b_sr; + unsigned int gpio1c_sr; + unsigned int gpio1d_sr; + unsigned int gpio2a_sr; + unsigned int gpio2b_sr; + unsigned int gpio2c_sr; + unsigned int reserved20; + unsigned int gpio3a_sr; + unsigned int gpio3b_sr; + unsigned int reserved21[2]; + unsigned int gpio4a_sr; + unsigned int gpio4b_sr; + unsigned int gpio4c_sr; + unsigned int gpio4d_sr; + unsigned int gpio0a_smt; + unsigned int gpio0b_smt; + unsigned int gpio0c_smt; + unsigned int reserved22; + unsigned int gpio1a_smt; + unsigned int gpio1b_smt; + unsigned int gpio1c_smt; + unsigned int gpio1d_smt; + unsigned int gpio2a_smt; + unsigned int gpio2b_smt; + unsigned int gpio2c_smt; + unsigned int reserved23; + unsigned int gpio3a_smt; + unsigned int gpio3b_smt; + unsigned int reserved35[2]; + unsigned int gpio4a_smt; + unsigned int gpio4b_smt; + unsigned int gpio4c_smt; + unsigned int gpio4d_smt; + unsigned int reserved24[(0x300 - 0x1EC) / 4 - 1]; + unsigned int soc_con0; + unsigned int soc_con1; + unsigned int soc_con2; + unsigned int soc_con3; + unsigned int soc_con4; + unsigned int soc_con5; + unsigned int soc_con6; + unsigned int soc_con7; + unsigned int soc_con8; + unsigned int soc_con9; + unsigned int soc_con10; + unsigned int reserved25[(0x380 - 0x328) / 4 - 1]; + unsigned int soc_status0; + unsigned int reserved26[(0x400 - 0x380) / 4 - 1]; + unsigned int cpu_con0; + unsigned int cpu_con1; + unsigned int cpu_con2; + unsigned int reserved27[(0x420 - 0x408) / 4 - 1]; + unsigned int cpu_status0; + unsigned int cpu_status1; + unsigned int reserved28[(0x440 - 0x424) / 4 - 1]; + unsigned int pvtm_con0; + unsigned int pvtm_con1; + unsigned int pvtm_status0; + unsigned int pvtm_status1; + unsigned int reserved29[(0x460 - 0x44C) / 4 - 1]; + unsigned int tsadc_tbl; + unsigned int tsadc_tbh; + unsigned int reserved30[(0x480 - 0x464) / 4 - 1]; + unsigned int host0_con0; + unsigned int host0_con1; + unsigned int otg_con0; + unsigned int host0_status0; + unsigned int reserved31[(0x4a0 - 0x48C) / 4 - 1]; + unsigned int mac_con0; + unsigned int upctrl_con0; + unsigned int upctrl_status0; + unsigned int reserved32[(0x500 - 0x4A8) / 4 - 1]; + unsigned int os_reg0; + unsigned int os_reg1; + unsigned int os_reg2; + unsigned int os_reg3; + unsigned int os_reg4; + unsigned int os_reg5; + unsigned int os_reg6; + unsigned int os_reg7; + unsigned int os_reg8; + unsigned int os_reg9; + unsigned int os_reg10; + unsigned int os_reg11; + unsigned int reserved38[(0x600 - 0x52c) / 4 - 1]; + unsigned int soc_con12; + unsigned int reserved39; + unsigned int soc_con13; + unsigned int soc_con14; + unsigned int soc_con15; + unsigned int reserved40[(0x800 - 0x610) / 4 - 1]; + unsigned int chip_id; +}; +check_member(rk3308_grf, gpio0a_p, 0xa0); + +struct rk3308_sgrf { + unsigned int soc_con0; + unsigned int soc_con1; + unsigned int con_tzma_r0size; + unsigned int con_secure0; + unsigned int reserved0; + unsigned int clk_timer_en; + unsigned int clkgat_con; + unsigned int fastboot_addr; + unsigned int fastboot_en; + unsigned int reserved1[(0x30 - 0x24) / 4]; + unsigned int srst_con; +}; +check_member(rk3308_sgrf, fastboot_en, 0x20); + +#endif diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig index 3cb934a3f33..493699472c7 100644 --- a/arch/arm/mach-rockchip/Kconfig +++ b/arch/arm/mach-rockchip/Kconfig @@ -127,6 +127,29 @@ config ROCKCHIP_RK3288 and video codec support. Peripherals include Gigabit Ethernet, USB2 host and OTG, SDIO, I2S, UARTs, SPI, I2C and PWMs. +config ROCKCHIP_RK3308 + bool "Support Rockchip RK3308" + select ARM64 + select DEBUG_UART_BOARD_INIT + select SUPPORT_SPL + select SUPPORT_TPL + select SPL + select SPL_ATF + select SPL_ATF_NO_PLATFORM_PARAM + select SPL_LOAD_FIT + imply ROCKCHIP_COMMON_BOARD + imply SPL_ROCKCHIP_COMMON_BOARD + imply SPL_CLK + imply SPL_REGMAP + imply SPL_SYSCON + imply SPL_RAM + imply SPL_SERIAL_SUPPORT + imply TPL_SERIAL_SUPPORT + imply SPL_SEPARATE_BSS + help + The Rockchip RK3308 is a ARM-based Soc which embedded with quad + Cortex-A35 and highly integrated audio interfaces. + config ROCKCHIP_RK3328 bool "Support Rockchip RK3328" select ARM64 @@ -345,6 +368,7 @@ source "arch/arm/mach-rockchip/rk3128/Kconfig" source "arch/arm/mach-rockchip/rk3188/Kconfig" source "arch/arm/mach-rockchip/rk322x/Kconfig" source "arch/arm/mach-rockchip/rk3288/Kconfig" +source "arch/arm/mach-rockchip/rk3308/Kconfig" source "arch/arm/mach-rockchip/rk3328/Kconfig" source "arch/arm/mach-rockchip/rk3368/Kconfig" source "arch/arm/mach-rockchip/rk3399/Kconfig" diff --git a/arch/arm/mach-rockchip/Makefile b/arch/arm/mach-rockchip/Makefile index 3b58158ff9d..a728acda24a 100644 --- a/arch/arm/mach-rockchip/Makefile +++ b/arch/arm/mach-rockchip/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_ROCKCHIP_RK3128) += rk3128/ obj-$(CONFIG_ROCKCHIP_RK3188) += rk3188/ obj-$(CONFIG_ROCKCHIP_RK322X) += rk322x/ obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288/ +obj-$(CONFIG_ROCKCHIP_RK3308) += rk3308/ obj-$(CONFIG_ROCKCHIP_RK3328) += rk3328/ obj-$(CONFIG_ROCKCHIP_RK3368) += rk3368/ obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399/ diff --git a/arch/arm/mach-rockchip/rk3308/Kconfig b/arch/arm/mach-rockchip/rk3308/Kconfig new file mode 100644 index 00000000000..9c096615953 --- /dev/null +++ b/arch/arm/mach-rockchip/rk3308/Kconfig @@ -0,0 +1,14 @@ +if ROCKCHIP_RK3308 + +config SYS_SOC + default "rk3308" + +config SYS_MALLOC_F_LEN + default 0x400 + +config SPL_SERIAL_SUPPORT + default y + +config ROCKCHIP_BOOT_MODE_REG + default 0xff000500 +endif diff --git a/arch/arm/mach-rockchip/rk3308/Makefile b/arch/arm/mach-rockchip/rk3308/Makefile new file mode 100644 index 00000000000..ce4d44bb346 --- /dev/null +++ b/arch/arm/mach-rockchip/rk3308/Makefile @@ -0,0 +1,9 @@ +# +# (C) Copyright 2018 Rockchip Electronics Co., Ltd. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += syscon_rk3308.o +obj-y += rk3308.o +obj-y += clk_rk3308.o diff --git a/arch/arm/mach-rockchip/rk3308/clk_rk3308.c b/arch/arm/mach-rockchip/rk3308/clk_rk3308.c new file mode 100644 index 00000000000..51b43153e86 --- /dev/null +++ b/arch/arm/mach-rockchip/rk3308/clk_rk3308.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd + */ + +#include +#include +#include +#include +#include + +int rockchip_get_clk(struct udevice **devp) +{ + return uclass_get_device_by_driver(UCLASS_CLK, + DM_GET_DRIVER(rockchip_rk3308_cru), devp); +} + +void *rockchip_get_cru(void) +{ + struct rk3308_clk_priv *priv; + struct udevice *dev; + int ret; + + ret = rockchip_get_clk(&dev); + if (ret) + return ERR_PTR(ret); + + priv = dev_get_priv(dev); + + return priv->cru; +} diff --git a/arch/arm/mach-rockchip/rk3308/rk3308.c b/arch/arm/mach-rockchip/rk3308/rk3308.c new file mode 100644 index 00000000000..f27f9e8c0b2 --- /dev/null +++ b/arch/arm/mach-rockchip/rk3308/rk3308.c @@ -0,0 +1,175 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + *Copyright (c) 2018 Rockchip Electronics Co., Ltd + */ +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#include +static struct mm_region rk3308_mem_map[] = { + { + .virt = 0x0UL, + .phys = 0x0UL, + .size = 0xff000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + .virt = 0xff000000UL, + .phys = 0xff000000UL, + .size = 0x01000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* List terminator */ + 0, + } +}; + +struct mm_region *mem_map = rk3308_mem_map; + +#define GRF_BASE 0xff000000 +#define SGRF_BASE 0xff2b0000 + +enum { + GPIO1C7_SHIFT = 8, + GPIO1C7_MASK = GENMASK(11, 8), + GPIO1C7_GPIO = 0, + GPIO1C7_UART1_RTSN, + GPIO1C7_UART2_TX_M0, + GPIO1C7_SPI2_MOSI, + GPIO1C7_JTAG_TMS, + + GPIO1C6_SHIFT = 4, + GPIO1C6_MASK = GENMASK(7, 4), + GPIO1C6_GPIO = 0, + GPIO1C6_UART1_CTSN, + GPIO1C6_UART2_RX_M0, + GPIO1C6_SPI2_MISO, + GPIO1C6_JTAG_TCLK, + + GPIO4D3_SHIFT = 6, + GPIO4D3_MASK = GENMASK(7, 6), + GPIO4D3_GPIO = 0, + GPIO4D3_SDMMC_D3, + GPIO4D3_UART2_TX_M1, + + GPIO4D2_SHIFT = 4, + GPIO4D2_MASK = GENMASK(5, 4), + GPIO4D2_GPIO = 0, + GPIO4D2_SDMMC_D2, + GPIO4D2_UART2_RX_M1, + + UART2_IO_SEL_SHIFT = 2, + UART2_IO_SEL_MASK = GENMASK(3, 2), + UART2_IO_SEL_M0 = 0, + UART2_IO_SEL_M1, + UART2_IO_SEL_USB, + + GPIO3B3_SEL_SRC_CTRL_SHIFT = 7, + GPIO3B3_SEL_SRC_CTRL_MASK = BIT(7), + GPIO3B3_SEL_SRC_CTRL_IOMUX = 0, + GPIO3B3_SEL_SRC_CTRL_SEL_PLUS, + + GPIO3B3_SEL_PLUS_SHIFT = 4, + GPIO3B3_SEL_PLUS_MASK = GENMASK(6, 4), + GPIO3B3_SEL_PLUS_GPIO3_B3 = 0, + GPIO3B3_SEL_PLUS_FLASH_ALE, + GPIO3B3_SEL_PLUS_EMMC_PWREN, + GPIO3B3_SEL_PLUS_SPI1_CLK, + GPIO3B3_SEL_PLUS_LCDC_D23_M1, + + GPIO3B2_SEL_SRC_CTRL_SHIFT = 3, + GPIO3B2_SEL_SRC_CTRL_MASK = BIT(3), + GPIO3B2_SEL_SRC_CTRL_IOMUX = 0, + GPIO3B2_SEL_SRC_CTRL_SEL_PLUS, + + GPIO3B2_SEL_PLUS_SHIFT = 0, + GPIO3B2_SEL_PLUS_MASK = GENMASK(2, 0), + GPIO3B2_SEL_PLUS_GPIO3_B2 = 0, + GPIO3B2_SEL_PLUS_FLASH_RDN, + GPIO3B2_SEL_PLUS_EMMC_RSTN, + GPIO3B2_SEL_PLUS_SPI1_MISO, + GPIO3B2_SEL_PLUS_LCDC_D22_M1, +}; + +enum { + IOVSEL3_CTRL_SHIFT = 8, + IOVSEL3_CTRL_MASK = BIT(8), + VCCIO3_SEL_BY_GPIO = 0, + VCCIO3_SEL_BY_IOVSEL3, + + IOVSEL3_SHIFT = 3, + IOVSEL3_MASK = BIT(3), + VCCIO3_3V3 = 0, + VCCIO3_1V8, +}; + +/* + * The voltage of VCCIO3(which is the voltage domain of emmc/flash/sfc + * interface) can indicated by GPIO0_A4 or io_vsel3. The SOC defaults + * use GPIO0_A4 to indicate power supply voltage for VCCIO3 by hardware, + * then we can switch to io_vsel3 after system power on, and release GPIO0_A4 + * for other usage. + */ + +#define GPIO0_A4 4 + +int rk_board_init(void) +{ + static struct rk3308_grf * const grf = (void *)GRF_BASE; + u32 val; + int ret; + + ret = gpio_request(GPIO0_A4, "gpio0_a4"); + if (ret < 0) { + printf("request for gpio0_a4 failed:%d\n", ret); + return 0; + } + + gpio_direction_input(GPIO0_A4); + + if (gpio_get_value(GPIO0_A4)) + val = VCCIO3_SEL_BY_IOVSEL3 << IOVSEL3_CTRL_SHIFT | + VCCIO3_1V8 << IOVSEL3_SHIFT; + else + val = VCCIO3_SEL_BY_IOVSEL3 << IOVSEL3_CTRL_SHIFT | + VCCIO3_3V3 << IOVSEL3_SHIFT; + rk_clrsetreg(&grf->soc_con0, IOVSEL3_CTRL_MASK | IOVSEL3_MASK, val); + + gpio_free(GPIO0_A4); + return 0; +} + +#if defined(CONFIG_DEBUG_UART) +__weak void board_debug_uart_init(void) +{ + static struct rk3308_grf * const grf = (void *)GRF_BASE; + + /* Enable early UART2 channel m1 on the rk3308 */ + rk_clrsetreg(&grf->soc_con5, UART2_IO_SEL_MASK, + UART2_IO_SEL_M1 << UART2_IO_SEL_SHIFT); + rk_clrsetreg(&grf->gpio4d_iomux, + GPIO4D3_MASK | GPIO4D2_MASK, + GPIO4D2_UART2_RX_M1 << GPIO4D2_SHIFT | + GPIO4D3_UART2_TX_M1 << GPIO4D3_SHIFT); +} +#endif + +#if defined(CONFIG_SPL_BUILD) +int arch_cpu_init(void) +{ + static struct rk3308_sgrf * const sgrf = (void *)SGRF_BASE; + + /* Set CRYPTO SDMMC EMMC NAND SFC USB master bus to be secure access */ + rk_clrreg(&sgrf->con_secure0, 0x2b83); + + return 0; +} +#endif diff --git a/arch/arm/mach-rockchip/rk3308/syscon_rk3308.c b/arch/arm/mach-rockchip/rk3308/syscon_rk3308.c new file mode 100644 index 00000000000..b380ff57233 --- /dev/null +++ b/arch/arm/mach-rockchip/rk3308/syscon_rk3308.c @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 Rockchip Electronics Co., Ltd + */ + +#include +#include +#include +#include + +static const struct udevice_id rk3308_syscon_ids[] = { + { .compatible = "rockchip,rk3308-grf", .data = ROCKCHIP_SYSCON_GRF }, + { } +}; + +U_BOOT_DRIVER(syscon_rk3308) = { + .name = "rk3308_syscon", + .id = UCLASS_SYSCON, + .of_match = rk3308_syscon_ids, +}; diff --git a/include/configs/rk3308_common.h b/include/configs/rk3308_common.h new file mode 100644 index 00000000000..a67d3d7d1b7 --- /dev/null +++ b/include/configs/rk3308_common.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2017 Rockchip Electronics Co., Ltd + */ + +#ifndef __CONFIG_RK3308_COMMON_H +#define __CONFIG_RK3308_COMMON_H + +#include "rockchip-common.h" + +#define CONFIG_SYS_CBSIZE 1024 +#define CONFIG_SKIP_LOWLEVEL_INIT +#define CONFIG_SYS_MAX_NAND_DEVICE 1 +#define CONFIG_SYS_NAND_ONFI_DETECTION +#define CONFIG_SYS_NAND_PAGE_SIZE 2048 +#define CONFIG_SYS_NAND_PAGE_COUNT 64 +#define CONFIG_SYS_NAND_SIZE (256 * 1024 * 1024) +#define CONFIG_SPL_MAX_SIZE 0x20000 +#define CONFIG_SPL_BSS_START_ADDR 0x00400000 +#define CONFIG_SPL_BSS_MAX_SIZE 0x2000 +#define CONFIG_SYS_SPI_U_BOOT_OFFS 0x8000 + +#define CONFIG_SYS_NS16550_MEM32 + +#define CONFIG_ROCKCHIP_STIMER_BASE 0xff1b00a0 +#define CONFIG_IRAM_BASE 0xfff80000 +#define CONFIG_SYS_INIT_SP_ADDR 0x00800000 +#define CONFIG_SYS_LOAD_ADDR 0x00C00800 +#define CONFIG_SPL_STACK 0x00400000 +#define CONFIG_SYS_BOOTM_LEN (64 << 20) /* 64M */ + +#define COUNTER_FREQUENCY 24000000 + +#define CONFIG_SYS_BOOTM_LEN (64 << 20) /* 64M */ + +#define CONFIG_SYS_SDRAM_BASE 0 +#define SDRAM_MAX_SIZE 0xff000000 +#define SDRAM_BANK_SIZE (2UL << 30) + +#ifndef CONFIG_SPL_BUILD + +#define ENV_MEM_LAYOUT_SETTINGS \ + "scriptaddr=0x00500000\0" \ + "pxefile_addr_r=0x00600000\0" \ + "fdt_addr_r=0x01f00000\0" \ + "kernel_addr_r=0x00680000\0" \ + "ramdisk_addr_r=0x04000000\0" + +#include +#define CONFIG_EXTRA_ENV_SETTINGS \ + ENV_MEM_LAYOUT_SETTINGS \ + "partitions=" PARTS_DEFAULT \ + ROCKCHIP_DEVICE_SETTINGS \ + BOOTENV + +#endif + +#endif -- cgit v1.3.1 From fe9efbca7b99fd9303b25cf33cbd720603c88f27 Mon Sep 17 00:00:00 2001 From: Finley Xiao Date: Thu, 14 Nov 2019 11:21:13 +0800 Subject: rockchip: clk: Add clk driver for rk3308 Add clk controller driver for RK3308 SOC. This patch depends on Elaine's pll patch[0]. [0]http://patchwork.ozlabs.org/patch/1183718/ Signed-off-by: Andy Yan Reviewed-by: Kever Yang --- drivers/clk/rockchip/Makefile | 1 + drivers/clk/rockchip/clk_rk3308.c | 1072 ++++++++++++++++++++++++++++++++ include/dt-bindings/clock/rk3308-cru.h | 387 ++++++++++++ 3 files changed, 1460 insertions(+) create mode 100644 drivers/clk/rockchip/clk_rk3308.c create mode 100644 include/dt-bindings/clock/rk3308-cru.h (limited to 'include') diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 8035b26136f..4cfcf833092 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_ROCKCHIP_RK3128) += clk_rk3128.o obj-$(CONFIG_ROCKCHIP_RK3188) += clk_rk3188.o obj-$(CONFIG_ROCKCHIP_RK322X) += clk_rk322x.o obj-$(CONFIG_ROCKCHIP_RK3288) += clk_rk3288.o +obj-$(CONFIG_ROCKCHIP_RK3308) += clk_rk3308.o obj-$(CONFIG_ROCKCHIP_RK3328) += clk_rk3328.o obj-$(CONFIG_ROCKCHIP_RK3368) += clk_rk3368.o obj-$(CONFIG_ROCKCHIP_RK3399) += clk_rk3399.o diff --git a/drivers/clk/rockchip/clk_rk3308.c b/drivers/clk/rockchip/clk_rk3308.c new file mode 100644 index 00000000000..f212c5ffc2c --- /dev/null +++ b/drivers/clk/rockchip/clk_rk3308.c @@ -0,0 +1,1072 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2017-2019 Rockchip Electronics Co., Ltd + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 DIV_TO_RATE(input_rate, div) ((input_rate) / ((div) + 1)) + +#define RK3308_CPUCLK_RATE(_rate, _aclk_div, _pclk_div) \ +{ \ + .rate = _rate##U, \ + .aclk_div = _aclk_div, \ + .pclk_div = _pclk_div, \ +} + +static struct rockchip_pll_rate_table rk3308_pll_rates[] = { + /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */ + RK3036_PLL_RATE(1300000000, 6, 325, 1, 1, 1, 0), + RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0), + RK3036_PLL_RATE(816000000, 1, 68, 2, 1, 1, 0), + RK3036_PLL_RATE(748000000, 2, 187, 3, 1, 1, 0), +}; + +static struct rockchip_cpu_rate_table rk3308_cpu_rates[] = { + RK3308_CPUCLK_RATE(1200000000, 1, 5), + RK3308_CPUCLK_RATE(1008000000, 1, 5), + RK3308_CPUCLK_RATE(816000000, 1, 3), + RK3308_CPUCLK_RATE(600000000, 1, 3), + RK3308_CPUCLK_RATE(408000000, 1, 1), +}; + +static struct rockchip_pll_clock rk3308_pll_clks[] = { + [APLL] = PLL(pll_rk3328, PLL_APLL, RK3308_PLL_CON(0), + RK3308_MODE_CON, 0, 10, 0, rk3308_pll_rates), + [DPLL] = PLL(pll_rk3328, PLL_DPLL, RK3308_PLL_CON(8), + RK3308_MODE_CON, 2, 10, 0, NULL), + [VPLL0] = PLL(pll_rk3328, PLL_VPLL0, RK3308_PLL_CON(16), + RK3308_MODE_CON, 4, 10, 0, NULL), + [VPLL1] = PLL(pll_rk3328, PLL_VPLL1, RK3308_PLL_CON(24), + RK3308_MODE_CON, 6, 10, 0, NULL), +}; + +static ulong rk3308_armclk_set_clk(struct rk3308_clk_priv *priv, ulong hz) +{ + struct rk3308_cru *cru = priv->cru; + const struct rockchip_cpu_rate_table *rate; + ulong old_rate; + + rate = rockchip_get_cpu_settings(rk3308_cpu_rates, 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 = rockchip_pll_get_rate(&rk3308_pll_clks[APLL], + priv->cru, APLL); + if (old_rate > hz) { + if (rockchip_pll_set_rate(&rk3308_pll_clks[APLL], + priv->cru, 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 (rockchip_pll_set_rate(&rk3308_pll_clks[APLL], + priv->cru, APLL, hz)) + return -EINVAL; + } + + return rockchip_pll_get_rate(&rk3308_pll_clks[APLL], priv->cru, APLL); +} + +static void rk3308_clk_get_pll_rate(struct rk3308_clk_priv *priv) +{ + if (!priv->dpll_hz) + priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], + priv->cru, DPLL); + if (!priv->vpll0_hz) + priv->vpll0_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0], + priv->cru, VPLL0); + if (!priv->vpll1_hz) + priv->vpll1_hz = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1], + priv->cru, VPLL1); +} + +static ulong rk3308_i2c_get_clk(struct clk *clk) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + u32 div, con, con_id; + + switch (clk->id) { + case SCLK_I2C0: + con_id = 25; + break; + case SCLK_I2C1: + con_id = 26; + break; + case SCLK_I2C2: + con_id = 27; + break; + case SCLK_I2C3: + con_id = 28; + break; + default: + printf("do not support this i2c bus\n"); + return -EINVAL; + } + + con = readl(&cru->clksel_con[con_id]); + div = con >> CLK_I2C_DIV_CON_SHIFT & CLK_I2C_DIV_CON_MASK; + + return DIV_TO_RATE(priv->dpll_hz, div); +} + +static ulong rk3308_i2c_set_clk(struct clk *clk, uint hz) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + u32 src_clk_div, con_id; + + src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); + assert(src_clk_div - 1 <= 127); + + switch (clk->id) { + case SCLK_I2C0: + con_id = 25; + break; + case SCLK_I2C1: + con_id = 26; + break; + case SCLK_I2C2: + con_id = 27; + break; + case SCLK_I2C3: + con_id = 28; + break; + default: + printf("do not support this i2c bus\n"); + return -EINVAL; + } + rk_clrsetreg(&cru->clksel_con[con_id], + CLK_I2C_PLL_SEL_MASK | CLK_I2C_DIV_CON_MASK, + CLK_I2C_PLL_SEL_DPLL << CLK_I2C_PLL_SEL_SHIFT | + (src_clk_div - 1) << CLK_I2C_DIV_CON_SHIFT); + + return rk3308_i2c_get_clk(clk); +} + +static ulong rk3308_mac_set_clk(struct clk *clk, uint hz) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + u32 con = readl(&cru->clksel_con[43]); + ulong pll_rate; + u8 div; + + if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL0) + pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0], + priv->cru, VPLL0); + else if ((con >> MAC_PLL_SHIFT) & MAC_SEL_VPLL1) + pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1], + priv->cru, VPLL1); + else + pll_rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], + priv->cru, DPLL); + + /*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[43], MAC_DIV_MASK, + div << MAC_DIV_SHIFT); + + return DIV_TO_RATE(pll_rate, div); +} + +static int rk3308_mac_set_speed_clk(struct clk *clk, uint hz) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + + if (hz != 2500000 && hz != 25000000) { + debug("Unsupported mac speed:%d\n", hz); + return -EINVAL; + } + + rk_clrsetreg(&cru->clksel_con[43], MAC_CLK_SPEED_SEL_MASK, + ((hz == 2500000) ? 0 : 1) << MAC_CLK_SPEED_SEL_SHIFT); + + return 0; +} + +static ulong rk3308_mmc_get_clk(struct clk *clk) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + u32 div, con, con_id; + + switch (clk->id) { + case HCLK_SDMMC: + case SCLK_SDMMC: + con_id = 39; + break; + case HCLK_EMMC: + case SCLK_EMMC: + case SCLK_EMMC_SAMPLE: + con_id = 41; + 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->vpll0_hz, div) / 2; +} + +static ulong rk3308_mmc_set_clk(struct clk *clk, ulong set_rate) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + int src_clk_div; + u32 con_id; + + switch (clk->id) { + case HCLK_SDMMC: + case SCLK_SDMMC: + con_id = 39; + break; + case HCLK_EMMC: + case SCLK_EMMC: + con_id = 41; + break; + default: + return -EINVAL; + } + /* Select clk_sdmmc/emmc source from VPLL0 by default */ + /* mmc clock defaulg div 2 internal, need provide double in cru */ + src_clk_div = DIV_ROUND_UP(priv->vpll0_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_CLK_SEL_MASK, + EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT | + 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_CLK_SEL_MASK, + EMMC_CLK_SEL_EMMC << EMMC_CLK_SEL_SHIFT | + EMMC_SEL_VPLL0 << EMMC_PLL_SHIFT | + (src_clk_div - 1) << EMMC_DIV_SHIFT); + } + + return rk3308_mmc_get_clk(clk); +} + +static ulong rk3308_saradc_get_clk(struct clk *clk) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + u32 div, con; + + con = readl(&cru->clksel_con[34]); + div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK; + + return DIV_TO_RATE(OSC_HZ, div); +} + +static ulong rk3308_saradc_set_clk(struct clk *clk, uint hz) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_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[34], + CLK_SARADC_DIV_CON_MASK, + (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT); + + return rk3308_saradc_get_clk(clk); +} + +static ulong rk3308_tsadc_get_clk(struct clk *clk) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + u32 div, con; + + con = readl(&cru->clksel_con[33]); + div = con >> CLK_SARADC_DIV_CON_SHIFT & CLK_SARADC_DIV_CON_MASK; + + return DIV_TO_RATE(OSC_HZ, div); +} + +static ulong rk3308_tsadc_set_clk(struct clk *clk, uint hz) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_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[33], + CLK_SARADC_DIV_CON_MASK, + (src_clk_div - 1) << CLK_SARADC_DIV_CON_SHIFT); + + return rk3308_tsadc_get_clk(clk); +} + +static ulong rk3308_spi_get_clk(struct clk *clk) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + u32 div, con, con_id; + + switch (clk->id) { + case SCLK_SPI0: + con_id = 30; + break; + case SCLK_SPI1: + con_id = 31; + break; + case SCLK_SPI2: + con_id = 32; + break; + default: + printf("do not support this spi bus\n"); + return -EINVAL; + } + + con = readl(&cru->clksel_con[con_id]); + div = con >> CLK_SPI_DIV_CON_SHIFT & CLK_SPI_DIV_CON_MASK; + + return DIV_TO_RATE(priv->dpll_hz, div); +} + +static ulong rk3308_spi_set_clk(struct clk *clk, uint hz) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + u32 src_clk_div, con_id; + + src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); + assert(src_clk_div - 1 <= 127); + + switch (clk->id) { + case SCLK_SPI0: + con_id = 30; + break; + case SCLK_SPI1: + con_id = 31; + break; + case SCLK_SPI2: + con_id = 32; + break; + default: + printf("do not support this spi bus\n"); + return -EINVAL; + } + + rk_clrsetreg(&cru->clksel_con[con_id], + CLK_SPI_PLL_SEL_MASK | CLK_SPI_DIV_CON_MASK, + CLK_SPI_PLL_SEL_DPLL << CLK_SPI_PLL_SEL_SHIFT | + (src_clk_div - 1) << CLK_SPI_DIV_CON_SHIFT); + + return rk3308_spi_get_clk(clk); +} + +static ulong rk3308_pwm_get_clk(struct clk *clk) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + u32 div, con; + + con = readl(&cru->clksel_con[29]); + div = con >> CLK_PWM_DIV_CON_SHIFT & CLK_PWM_DIV_CON_MASK; + + return DIV_TO_RATE(priv->dpll_hz, div); +} + +static ulong rk3308_pwm_set_clk(struct clk *clk, uint hz) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + int src_clk_div; + + src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); + assert(src_clk_div - 1 <= 127); + + rk_clrsetreg(&cru->clksel_con[29], + CLK_PWM_PLL_SEL_MASK | CLK_PWM_DIV_CON_MASK, + CLK_PWM_PLL_SEL_DPLL << CLK_PWM_PLL_SEL_SHIFT | + (src_clk_div - 1) << CLK_PWM_DIV_CON_SHIFT); + + return rk3308_pwm_get_clk(clk); +} + +static ulong rk3308_vop_get_clk(struct clk *clk) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + u32 div, pll_sel, vol_sel, con, parent; + + con = readl(&cru->clksel_con[8]); + vol_sel = (con & DCLK_VOP_SEL_MASK) >> DCLK_VOP_SEL_SHIFT; + pll_sel = (con & DCLK_VOP_PLL_SEL_MASK) >> DCLK_VOP_PLL_SEL_SHIFT; + div = con & DCLK_VOP_DIV_MASK; + + if (vol_sel == DCLK_VOP_SEL_24M) { + parent = OSC_HZ; + } else if (vol_sel == DCLK_VOP_SEL_DIVOUT) { + switch (pll_sel) { + case DCLK_VOP_PLL_SEL_DPLL: + parent = priv->dpll_hz; + break; + case DCLK_VOP_PLL_SEL_VPLL0: + parent = priv->vpll0_hz; + break; + case DCLK_VOP_PLL_SEL_VPLL1: + parent = priv->vpll0_hz; + break; + default: + printf("do not support this vop pll sel\n"); + return -EINVAL; + } + } else { + printf("do not support this vop sel\n"); + return -EINVAL; + } + + return DIV_TO_RATE(parent, div); +} + +static ulong rk3308_vop_set_clk(struct clk *clk, ulong hz) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3308_cru *cru = priv->cru; + ulong pll_rate, now, best_rate = 0; + u32 i, div, best_div = 0, best_sel = 0; + + for (i = 0; i <= DCLK_VOP_PLL_SEL_VPLL1; i++) { + switch (i) { + case DCLK_VOP_PLL_SEL_DPLL: + pll_rate = priv->dpll_hz; + break; + case DCLK_VOP_PLL_SEL_VPLL0: + pll_rate = priv->vpll0_hz; + break; + case DCLK_VOP_PLL_SEL_VPLL1: + pll_rate = priv->vpll1_hz; + break; + default: + printf("do not support this vop pll sel\n"); + return -EINVAL; + } + + div = DIV_ROUND_UP(pll_rate, hz); + if (div > 255) + continue; + now = pll_rate / div; + if (abs(hz - now) < abs(hz - best_rate)) { + best_rate = now; + best_div = div; + best_sel = i; + } + debug("pll_rate=%lu, best_rate=%lu, best_div=%u, best_sel=%u\n", + pll_rate, best_rate, best_div, best_sel); + } + + if (best_rate != hz && hz == OSC_HZ) { + rk_clrsetreg(&cru->clksel_con[8], + DCLK_VOP_SEL_MASK, + DCLK_VOP_SEL_24M << DCLK_VOP_SEL_SHIFT); + } else if (best_rate) { + rk_clrsetreg(&cru->clksel_con[8], + DCLK_VOP_SEL_MASK | DCLK_VOP_PLL_SEL_MASK | + DCLK_VOP_DIV_MASK, + DCLK_VOP_SEL_DIVOUT << DCLK_VOP_SEL_SHIFT | + best_sel << DCLK_VOP_PLL_SEL_SHIFT | + (best_div - 1) << DCLK_VOP_DIV_SHIFT); + } else { + printf("do not support this vop freq\n"); + return -EINVAL; + } + + return rk3308_vop_get_clk(clk); +} + +static ulong rk3308_bus_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) +{ + struct rk3308_cru *cru = priv->cru; + u32 div, con, parent = priv->dpll_hz; + + switch (clk_id) { + case ACLK_BUS: + con = readl(&cru->clksel_con[5]); + div = (con & BUS_ACLK_DIV_MASK) >> BUS_ACLK_DIV_SHIFT; + break; + case HCLK_BUS: + con = readl(&cru->clksel_con[6]); + div = (con & BUS_HCLK_DIV_MASK) >> BUS_HCLK_DIV_SHIFT; + break; + case PCLK_BUS: + case PCLK_WDT: + con = readl(&cru->clksel_con[6]); + div = (con & BUS_PCLK_DIV_MASK) >> BUS_PCLK_DIV_SHIFT; + break; + default: + return -ENOENT; + } + + return DIV_TO_RATE(parent, div); +} + +static ulong rk3308_bus_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, + ulong hz) +{ + struct rk3308_cru *cru = priv->cru; + int src_clk_div; + + src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); + assert(src_clk_div - 1 <= 31); + + /* + * select dpll as pd_bus bus clock source and + * set up dependent divisors for PCLK/HCLK and ACLK clocks. + */ + switch (clk_id) { + case ACLK_BUS: + rk_clrsetreg(&cru->clksel_con[5], + BUS_PLL_SEL_MASK | BUS_ACLK_DIV_MASK, + BUS_PLL_SEL_DPLL << BUS_PLL_SEL_SHIFT | + (src_clk_div - 1) << BUS_ACLK_DIV_SHIFT); + break; + case HCLK_BUS: + rk_clrsetreg(&cru->clksel_con[6], + BUS_HCLK_DIV_MASK, + (src_clk_div - 1) << BUS_HCLK_DIV_SHIFT); + break; + case PCLK_BUS: + rk_clrsetreg(&cru->clksel_con[6], + 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 rk3308_bus_get_clk(priv, clk_id); +} + +static ulong rk3308_peri_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) +{ + struct rk3308_cru *cru = priv->cru; + u32 div, con, parent = priv->dpll_hz; + + switch (clk_id) { + case ACLK_PERI: + con = readl(&cru->clksel_con[36]); + div = (con & PERI_ACLK_DIV_MASK) >> PERI_ACLK_DIV_SHIFT; + break; + case HCLK_PERI: + con = readl(&cru->clksel_con[37]); + div = (con & PERI_HCLK_DIV_MASK) >> PERI_HCLK_DIV_SHIFT; + break; + case PCLK_PERI: + con = readl(&cru->clksel_con[37]); + div = (con & PERI_PCLK_DIV_MASK) >> PERI_PCLK_DIV_SHIFT; + break; + default: + return -ENOENT; + } + + return DIV_TO_RATE(parent, div); +} + +static ulong rk3308_peri_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, + ulong hz) +{ + struct rk3308_cru *cru = priv->cru; + int src_clk_div; + + src_clk_div = DIV_ROUND_UP(priv->dpll_hz, hz); + assert(src_clk_div - 1 <= 31); + + /* + * select dpll as pd_peri bus clock source and + * set up dependent divisors for PCLK/HCLK and ACLK clocks. + */ + switch (clk_id) { + case ACLK_PERI: + rk_clrsetreg(&cru->clksel_con[36], + PERI_PLL_SEL_MASK | PERI_ACLK_DIV_MASK, + PERI_PLL_DPLL << PERI_PLL_SEL_SHIFT | + (src_clk_div - 1) << PERI_ACLK_DIV_SHIFT); + break; + case HCLK_PERI: + rk_clrsetreg(&cru->clksel_con[37], + PERI_HCLK_DIV_MASK, + (src_clk_div - 1) << PERI_HCLK_DIV_SHIFT); + break; + case PCLK_PERI: + rk_clrsetreg(&cru->clksel_con[37], + PERI_PCLK_DIV_MASK, + (src_clk_div - 1) << PERI_PCLK_DIV_SHIFT); + break; + default: + printf("do not support this peri freq\n"); + return -EINVAL; + } + + return rk3308_peri_get_clk(priv, clk_id); +} + +static ulong rk3308_audio_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) +{ + struct rk3308_cru *cru = priv->cru; + u32 div, con, parent = priv->vpll0_hz; + + switch (clk_id) { + case HCLK_AUDIO: + con = readl(&cru->clksel_con[45]); + div = (con & AUDIO_HCLK_DIV_MASK) >> AUDIO_HCLK_DIV_SHIFT; + break; + case PCLK_AUDIO: + con = readl(&cru->clksel_con[45]); + div = (con & AUDIO_PCLK_DIV_MASK) >> AUDIO_PCLK_DIV_SHIFT; + break; + default: + return -ENOENT; + } + + return DIV_TO_RATE(parent, div); +} + +static ulong rk3308_audio_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, + ulong hz) +{ + struct rk3308_cru *cru = priv->cru; + int src_clk_div; + + src_clk_div = DIV_ROUND_UP(priv->vpll0_hz, hz); + assert(src_clk_div - 1 <= 31); + + /* + * select vpll0 as audio bus clock source and + * set up dependent divisors for HCLK and PCLK clocks. + */ + switch (clk_id) { + case HCLK_AUDIO: + rk_clrsetreg(&cru->clksel_con[45], + AUDIO_PLL_SEL_MASK | AUDIO_HCLK_DIV_MASK, + AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT | + (src_clk_div - 1) << AUDIO_HCLK_DIV_SHIFT); + break; + case PCLK_AUDIO: + rk_clrsetreg(&cru->clksel_con[45], + AUDIO_PLL_SEL_MASK | AUDIO_PCLK_DIV_MASK, + AUDIO_PLL_VPLL0 << AUDIO_PLL_SEL_SHIFT | + (src_clk_div - 1) << AUDIO_PCLK_DIV_SHIFT); + break; + default: + printf("do not support this audio freq\n"); + return -EINVAL; + } + + return rk3308_peri_get_clk(priv, clk_id); +} + +static ulong rk3308_crypto_get_clk(struct rk3308_clk_priv *priv, ulong clk_id) +{ + struct rk3308_cru *cru = priv->cru; + u32 div, con, parent; + + switch (clk_id) { + case SCLK_CRYPTO: + con = readl(&cru->clksel_con[7]); + div = (con & CRYPTO_DIV_MASK) >> CRYPTO_DIV_SHIFT; + parent = priv->vpll0_hz; + break; + case SCLK_CRYPTO_APK: + con = readl(&cru->clksel_con[7]); + div = (con & CRYPTO_APK_DIV_MASK) >> CRYPTO_APK_DIV_SHIFT; + parent = priv->vpll0_hz; + break; + default: + return -ENOENT; + } + + return DIV_TO_RATE(parent, div); +} + +static ulong rk3308_crypto_set_clk(struct rk3308_clk_priv *priv, ulong clk_id, + ulong hz) +{ + struct rk3308_cru *cru = priv->cru; + int src_clk_div; + + src_clk_div = DIV_ROUND_UP(priv->vpll0_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[7], + CRYPTO_PLL_SEL_MASK | CRYPTO_DIV_MASK, + CRYPTO_PLL_SEL_VPLL0 << CRYPTO_PLL_SEL_SHIFT | + (src_clk_div - 1) << CRYPTO_DIV_SHIFT); + break; + case SCLK_CRYPTO_APK: + rk_clrsetreg(&cru->clksel_con[7], + CRYPTO_APK_PLL_SEL_MASK | CRYPTO_APK_DIV_MASK, + CRYPTO_PLL_SEL_VPLL0 << 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 rk3308_crypto_get_clk(priv, clk_id); +} + +static ulong rk3308_clk_get_rate(struct clk *clk) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + ulong rate = 0; + + debug("%s id:%ld\n", __func__, clk->id); + + switch (clk->id) { + case PLL_APLL: + case ARMCLK: + rate = rockchip_pll_get_rate(&rk3308_pll_clks[APLL], + priv->cru, APLL); + break; + case PLL_DPLL: + rate = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], + priv->cru, DPLL); + break; + case PLL_VPLL0: + rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL0], + priv->cru, VPLL0); + break; + case PLL_VPLL1: + rate = rockchip_pll_get_rate(&rk3308_pll_clks[VPLL1], + priv->cru, VPLL1); + break; + case HCLK_SDMMC: + case HCLK_EMMC: + case SCLK_SDMMC: + case SCLK_EMMC: + case SCLK_EMMC_SAMPLE: + rate = rk3308_mmc_get_clk(clk); + break; + case SCLK_I2C0: + case SCLK_I2C1: + case SCLK_I2C2: + case SCLK_I2C3: + rate = rk3308_i2c_get_clk(clk); + break; + case SCLK_SARADC: + rate = rk3308_saradc_get_clk(clk); + break; + case SCLK_TSADC: + rate = rk3308_tsadc_get_clk(clk); + break; + case SCLK_SPI0: + case SCLK_SPI1: + rate = rk3308_spi_get_clk(clk); + break; + case SCLK_PWM0: + rate = rk3308_pwm_get_clk(clk); + break; + case DCLK_VOP: + rate = rk3308_vop_get_clk(clk); + break; + case ACLK_BUS: + case HCLK_BUS: + case PCLK_BUS: + case PCLK_WDT: + rate = rk3308_bus_get_clk(priv, clk->id); + break; + case ACLK_PERI: + case HCLK_PERI: + case PCLK_PERI: + rate = rk3308_peri_get_clk(priv, clk->id); + break; + case HCLK_AUDIO: + case PCLK_AUDIO: + rate = rk3308_audio_get_clk(priv, clk->id); + break; + case SCLK_CRYPTO: + case SCLK_CRYPTO_APK: + rate = rk3308_crypto_get_clk(priv, clk->id); + break; + default: + return -ENOENT; + } + + return rate; +} + +static ulong rk3308_clk_set_rate(struct clk *clk, ulong rate) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + ulong ret = 0; + + debug("%s %ld %ld\n", __func__, clk->id, rate); + + switch (clk->id) { + case PLL_DPLL: + ret = rockchip_pll_set_rate(&rk3308_pll_clks[DPLL], priv->cru, + DPLL, rate); + priv->dpll_hz = rockchip_pll_get_rate(&rk3308_pll_clks[DPLL], + priv->cru, DPLL); + break; + case ARMCLK: + if (priv->armclk_hz) + rk3308_armclk_set_clk(priv, rate); + priv->armclk_hz = rate; + break; + case HCLK_SDMMC: + case HCLK_EMMC: + case SCLK_SDMMC: + case SCLK_EMMC: + ret = rk3308_mmc_set_clk(clk, rate); + break; + case SCLK_I2C0: + case SCLK_I2C1: + case SCLK_I2C2: + case SCLK_I2C3: + ret = rk3308_i2c_set_clk(clk, rate); + break; + case SCLK_MAC: + ret = rk3308_mac_set_clk(clk, rate); + break; + case SCLK_MAC_RMII: + ret = rk3308_mac_set_speed_clk(clk, rate); + break; + case SCLK_SARADC: + ret = rk3308_saradc_set_clk(clk, rate); + break; + case SCLK_TSADC: + ret = rk3308_tsadc_set_clk(clk, rate); + break; + case SCLK_SPI0: + case SCLK_SPI1: + ret = rk3308_spi_set_clk(clk, rate); + break; + case SCLK_PWM0: + ret = rk3308_pwm_set_clk(clk, rate); + break; + case DCLK_VOP: + ret = rk3308_vop_set_clk(clk, rate); + break; + case ACLK_BUS: + case HCLK_BUS: + case PCLK_BUS: + rate = rk3308_bus_set_clk(priv, clk->id, rate); + break; + case ACLK_PERI: + case HCLK_PERI: + case PCLK_PERI: + rate = rk3308_peri_set_clk(priv, clk->id, rate); + break; + case HCLK_AUDIO: + case PCLK_AUDIO: + rate = rk3308_audio_set_clk(priv, clk->id, rate); + break; + case SCLK_CRYPTO: + case SCLK_CRYPTO_APK: + ret = rk3308_crypto_set_clk(priv, clk->id, rate); + break; + default: + return -ENOENT; + } + + return ret; +} + +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) +static int __maybe_unused rk3308_mac_set_parent(struct clk *clk, struct clk *parent) +{ + struct rk3308_clk_priv *priv = dev_get_priv(clk->dev); + + /* + * If the requested parent is in the same clock-controller and + * the id is SCLK_MAC_SRC, switch to the internal clock. + */ + if (parent->id == SCLK_MAC_SRC) { + debug("%s: switching RMII to SCLK_MAC\n", __func__); + rk_clrreg(&priv->cru->clksel_con[43], BIT(14)); + } else { + debug("%s: switching RMII to CLKIN\n", __func__); + rk_setreg(&priv->cru->clksel_con[43], BIT(14)); + } + + return 0; +} + +static int __maybe_unused rk3308_clk_set_parent(struct clk *clk, struct clk *parent) +{ + switch (clk->id) { + case SCLK_MAC: + return rk3308_mac_set_parent(clk, parent); + default: + break; + } + + debug("%s: unsupported clk %ld\n", __func__, clk->id); + return -ENOENT; +} +#endif + +static struct clk_ops rk3308_clk_ops = { + .get_rate = rk3308_clk_get_rate, + .set_rate = rk3308_clk_set_rate, +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) + .set_parent = rk3308_clk_set_parent, +#endif +}; + +static void rk3308_clk_init(struct udevice *dev) +{ + struct rk3308_clk_priv *priv = dev_get_priv(dev); + int ret; + + if (rockchip_pll_get_rate(&rk3308_pll_clks[APLL], + priv->cru, APLL) != APLL_HZ) { + ret = rk3308_armclk_set_clk(priv, APLL_HZ); + if (ret < 0) + printf("%s failed to set armclk rate\n", __func__); + } + + rk3308_clk_get_pll_rate(priv); + + rk3308_bus_set_clk(priv, ACLK_BUS, BUS_ACLK_HZ); + rk3308_bus_set_clk(priv, HCLK_BUS, BUS_HCLK_HZ); + rk3308_bus_set_clk(priv, PCLK_BUS, BUS_PCLK_HZ); + + rk3308_peri_set_clk(priv, ACLK_PERI, PERI_ACLK_HZ); + rk3308_peri_set_clk(priv, HCLK_PERI, PERI_HCLK_HZ); + rk3308_peri_set_clk(priv, PCLK_PERI, PERI_PCLK_HZ); + + rk3308_audio_set_clk(priv, HCLK_AUDIO, AUDIO_HCLK_HZ); + rk3308_audio_set_clk(priv, PCLK_AUDIO, AUDIO_PCLK_HZ); +} + +static int rk3308_clk_probe(struct udevice *dev) +{ + int ret; + + rk3308_clk_init(dev); + + /* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */ + ret = clk_set_defaults(dev, 1); + if (ret) + debug("%s clk_set_defaults failed %d\n", __func__, ret); + + return ret; +} + +static int rk3308_clk_ofdata_to_platdata(struct udevice *dev) +{ + struct rk3308_clk_priv *priv = dev_get_priv(dev); + + priv->cru = dev_read_addr_ptr(dev); + + return 0; +} + +static int rk3308_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 rk3308_cru, + glb_srst_fst); + priv->glb_srst_snd_value = offsetof(struct rk3308_cru, + glb_srst_snd); + sys_child->priv = priv; + } + +#if CONFIG_IS_ENABLED(RESET_ROCKCHIP) + ret = offsetof(struct rk3308_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 rk3308_clk_ids[] = { + { .compatible = "rockchip,rk3308-cru" }, + { } +}; + +U_BOOT_DRIVER(rockchip_rk3308_cru) = { + .name = "rockchip_rk3308_cru", + .id = UCLASS_CLK, + .of_match = rk3308_clk_ids, + .priv_auto_alloc_size = sizeof(struct rk3308_clk_priv), + .ofdata_to_platdata = rk3308_clk_ofdata_to_platdata, + .ops = &rk3308_clk_ops, + .bind = rk3308_clk_bind, + .probe = rk3308_clk_probe, +}; diff --git a/include/dt-bindings/clock/rk3308-cru.h b/include/dt-bindings/clock/rk3308-cru.h new file mode 100644 index 00000000000..d97840f9ee2 --- /dev/null +++ b/include/dt-bindings/clock/rk3308-cru.h @@ -0,0 +1,387 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2019 Rockchip Electronics Co. Ltd. + * Author: Finley Xiao + */ + +#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK3308_H +#define _DT_BINDINGS_CLK_ROCKCHIP_RK3308_H + +/* core clocks */ +#define PLL_APLL 1 +#define PLL_DPLL 2 +#define PLL_VPLL0 3 +#define PLL_VPLL1 4 +#define ARMCLK 5 + +/* sclk (special clocks) */ +#define USB480M 14 +#define SCLK_RTC32K 15 +#define SCLK_PVTM_CORE 16 +#define SCLK_UART0 17 +#define SCLK_UART1 18 +#define SCLK_UART2 19 +#define SCLK_UART3 20 +#define SCLK_UART4 21 +#define SCLK_I2C0 22 +#define SCLK_I2C1 23 +#define SCLK_I2C2 24 +#define SCLK_I2C3 25 +#define SCLK_PWM0 26 +#define SCLK_SPI0 27 +#define SCLK_SPI1 28 +#define SCLK_SPI2 29 +#define SCLK_TIMER0 30 +#define SCLK_TIMER1 31 +#define SCLK_TIMER2 32 +#define SCLK_TIMER3 33 +#define SCLK_TIMER4 34 +#define SCLK_TIMER5 35 +#define SCLK_TSADC 36 +#define SCLK_SARADC 37 +#define SCLK_OTP 38 +#define SCLK_OTP_USR 39 +#define SCLK_CPU_BOOST 40 +#define SCLK_CRYPTO 41 +#define SCLK_CRYPTO_APK 42 +#define SCLK_NANDC_DIV 43 +#define SCLK_NANDC_DIV50 44 +#define SCLK_NANDC 45 +#define SCLK_SDMMC_DIV 46 +#define SCLK_SDMMC_DIV50 47 +#define SCLK_SDMMC 48 +#define SCLK_SDMMC_DRV 49 +#define SCLK_SDMMC_SAMPLE 50 +#define SCLK_SDIO_DIV 51 +#define SCLK_SDIO_DIV50 52 +#define SCLK_SDIO 53 +#define SCLK_SDIO_DRV 54 +#define SCLK_SDIO_SAMPLE 55 +#define SCLK_EMMC_DIV 56 +#define SCLK_EMMC_DIV50 57 +#define SCLK_EMMC 58 +#define SCLK_EMMC_DRV 59 +#define SCLK_EMMC_SAMPLE 60 +#define SCLK_SFC 61 +#define SCLK_OTG_ADP 62 +#define SCLK_MAC_SRC 63 +#define SCLK_MAC 64 +#define SCLK_MAC_REF 65 +#define SCLK_MAC_RX_TX 66 +#define SCLK_MAC_RMII 67 +#define SCLK_DDR_MON_TIMER 68 +#define SCLK_DDR_MON 69 +#define SCLK_DDRCLK 70 +#define SCLK_PMU 71 +#define SCLK_USBPHY_REF 72 +#define SCLK_WIFI 73 +#define SCLK_PVTM_PMU 74 +#define SCLK_PDM 75 +#define SCLK_I2S0_8CH_TX 76 +#define SCLK_I2S0_8CH_TX_OUT 77 +#define SCLK_I2S0_8CH_RX 78 +#define SCLK_I2S0_8CH_RX_OUT 79 +#define SCLK_I2S1_8CH_TX 80 +#define SCLK_I2S1_8CH_TX_OUT 81 +#define SCLK_I2S1_8CH_RX 82 +#define SCLK_I2S1_8CH_RX_OUT 83 +#define SCLK_I2S2_8CH_TX 84 +#define SCLK_I2S2_8CH_TX_OUT 85 +#define SCLK_I2S2_8CH_RX 86 +#define SCLK_I2S2_8CH_RX_OUT 87 +#define SCLK_I2S3_8CH_TX 88 +#define SCLK_I2S3_8CH_TX_OUT 89 +#define SCLK_I2S3_8CH_RX 90 +#define SCLK_I2S3_8CH_RX_OUT 91 +#define SCLK_I2S0_2CH 92 +#define SCLK_I2S0_2CH_OUT 93 +#define SCLK_I2S1_2CH 94 +#define SCLK_I2S1_2CH_OUT 95 +#define SCLK_SPDIF_TX_DIV 96 +#define SCLK_SPDIF_TX_DIV50 97 +#define SCLK_SPDIF_TX 98 +#define SCLK_SPDIF_RX_DIV 99 +#define SCLK_SPDIF_RX_DIV50 100 +#define SCLK_SPDIF_RX 101 +#define SCLK_I2S0_8CH_TX_MUX 102 +#define SCLK_I2S0_8CH_RX_MUX 103 +#define SCLK_I2S1_8CH_TX_MUX 104 +#define SCLK_I2S1_8CH_RX_MUX 105 +#define SCLK_I2S2_8CH_TX_MUX 106 +#define SCLK_I2S2_8CH_RX_MUX 107 +#define SCLK_I2S3_8CH_TX_MUX 108 +#define SCLK_I2S3_8CH_RX_MUX 109 +#define SCLK_I2S0_8CH_TX_SRC 110 +#define SCLK_I2S0_8CH_RX_SRC 111 +#define SCLK_I2S1_8CH_TX_SRC 112 +#define SCLK_I2S1_8CH_RX_SRC 113 +#define SCLK_I2S2_8CH_TX_SRC 114 +#define SCLK_I2S2_8CH_RX_SRC 115 +#define SCLK_I2S3_8CH_TX_SRC 116 +#define SCLK_I2S3_8CH_RX_SRC 117 +#define SCLK_I2S0_2CH_SRC 118 +#define SCLK_I2S1_2CH_SRC 119 +#define SCLK_PWM1 120 +#define SCLK_PWM2 121 +#define SCLK_OWIRE 122 + +/* dclk */ +#define DCLK_VOP 125 + +/* aclk */ +#define ACLK_BUS_SRC 130 +#define ACLK_BUS 131 +#define ACLK_PERI_SRC 132 +#define ACLK_PERI 133 +#define ACLK_MAC 134 +#define ACLK_CRYPTO 135 +#define ACLK_VOP 136 +#define ACLK_GIC 137 +#define ACLK_DMAC0 138 +#define ACLK_DMAC1 139 + +/* hclk */ +#define HCLK_BUS 150 +#define HCLK_PERI 151 +#define HCLK_AUDIO 152 +#define HCLK_NANDC 153 +#define HCLK_SDMMC 154 +#define HCLK_SDIO 155 +#define HCLK_EMMC 156 +#define HCLK_SFC 157 +#define HCLK_OTG 158 +#define HCLK_HOST 159 +#define HCLK_HOST_ARB 160 +#define HCLK_PDM 161 +#define HCLK_SPDIFTX 162 +#define HCLK_SPDIFRX 163 +#define HCLK_I2S0_8CH 164 +#define HCLK_I2S1_8CH 165 +#define HCLK_I2S2_8CH 166 +#define HCLK_I2S3_8CH 167 +#define HCLK_I2S0_2CH 168 +#define HCLK_I2S1_2CH 169 +#define HCLK_VAD 170 +#define HCLK_CRYPTO 171 +#define HCLK_VOP 172 + +/* pclk */ +#define PCLK_BUS 190 +#define PCLK_DDR 191 +#define PCLK_PERI 192 +#define PCLK_PMU 193 +#define PCLK_AUDIO 194 +#define PCLK_MAC 195 +#define PCLK_ACODEC 196 +#define PCLK_UART0 197 +#define PCLK_UART1 198 +#define PCLK_UART2 199 +#define PCLK_UART3 200 +#define PCLK_UART4 201 +#define PCLK_I2C0 202 +#define PCLK_I2C1 203 +#define PCLK_I2C2 204 +#define PCLK_I2C3 205 +#define PCLK_PWM0 206 +#define PCLK_SPI0 207 +#define PCLK_SPI1 208 +#define PCLK_SPI2 209 +#define PCLK_SARADC 210 +#define PCLK_TSADC 211 +#define PCLK_TIMER 212 +#define PCLK_OTP_NS 213 +#define PCLK_WDT 214 +#define PCLK_GPIO0 215 +#define PCLK_GPIO1 216 +#define PCLK_GPIO2 217 +#define PCLK_GPIO3 218 +#define PCLK_GPIO4 219 +#define PCLK_SGRF 220 +#define PCLK_GRF 221 +#define PCLK_USBSD_DET 222 +#define PCLK_DDR_UPCTL 223 +#define PCLK_DDR_MON 224 +#define PCLK_DDRPHY 225 +#define PCLK_DDR_STDBY 226 +#define PCLK_USB_GRF 227 +#define PCLK_CRU 228 +#define PCLK_OTP_PHY 229 +#define PCLK_CPU_BOOST 230 +#define PCLK_PWM1 231 +#define PCLK_PWM2 232 +#define PCLK_CAN 233 +#define PCLK_OWIRE 234 + +#define CLK_NR_CLKS (PCLK_OWIRE + 1) + +/* soft-reset indices */ + +/* cru_softrst_con0 */ +#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 + +/* cru_softrst_con1 */ +#define SRST_DAP 16 +#define SRST_CORE_PVTM 17 +#define SRST_CORE_PRF 18 +#define SRST_CORE_GRF 19 +#define SRST_DDRUPCTL 20 +#define SRST_DDRUPCTL_P 22 +#define SRST_MSCH 23 +#define SRST_DDRMON_P 25 +#define SRST_DDRSTDBY_P 26 +#define SRST_DDRSTDBY 27 +#define SRST_DDRPHY 28 +#define SRST_DDRPHY_DIV 29 +#define SRST_DDRPHY_P 30 + +/* cru_softrst_con2 */ +#define SRST_BUS_NIU_H 32 +#define SRST_USB_NIU_P 33 +#define SRST_CRYPTO_A 34 +#define SRST_CRYPTO_H 35 +#define SRST_CRYPTO 36 +#define SRST_CRYPTO_APK 37 +#define SRST_VOP_A 38 +#define SRST_VOP_H 39 +#define SRST_VOP_D 40 +#define SRST_INTMEM_A 41 +#define SRST_ROM_H 42 +#define SRST_GIC_A 43 +#define SRST_UART0_P 44 +#define SRST_UART0 45 +#define SRST_UART1_P 46 +#define SRST_UART1 47 + +/* cru_softrst_con3 */ +#define SRST_UART2_P 48 +#define SRST_UART2 49 +#define SRST_UART3_P 50 +#define SRST_UART3 51 +#define SRST_UART4_P 52 +#define SRST_UART4 53 +#define SRST_I2C0_P 54 +#define SRST_I2C0 55 +#define SRST_I2C1_P 56 +#define SRST_I2C1 57 +#define SRST_I2C2_P 58 +#define SRST_I2C2 59 +#define SRST_I2C3_P 60 +#define SRST_I2C3 61 +#define SRST_PWM0_P 62 +#define SRST_PWM0 63 + +/* cru_softrst_con4 */ +#define SRST_SPI0_P 64 +#define SRST_SPI0 65 +#define SRST_SPI1_P 66 +#define SRST_SPI1 67 +#define SRST_SPI2_P 68 +#define SRST_SPI2 69 +#define SRST_SARADC_P 70 +#define SRST_TSADC_P 71 +#define SRST_TSADC 72 +#define SRST_TIMER0_P 73 +#define SRST_TIMER0 74 +#define SRST_TIMER1 75 +#define SRST_TIMER2 76 +#define SRST_TIMER3 77 +#define SRST_TIMER4 78 +#define SRST_TIMER5 79 + +/* cru_softrst_con5 */ +#define SRST_OTP_NS_P 80 +#define SRST_OTP_NS_SBPI 81 +#define SRST_OTP_NS_USR 82 +#define SRST_OTP_PHY_P 83 +#define SRST_OTP_PHY 84 +#define SRST_GPIO0_P 86 +#define SRST_GPIO1_P 87 +#define SRST_GPIO2_P 88 +#define SRST_GPIO3_P 89 +#define SRST_GPIO4_P 90 +#define SRST_GRF_P 91 +#define SRST_USBSD_DET_P 92 +#define SRST_PMU 93 +#define SRST_PMU_PVTM 94 +#define SRST_USB_GRF_P 95 + +/* cru_softrst_con6 */ +#define SRST_CPU_BOOST 96 +#define SRST_CPU_BOOST_P 97 +#define SRST_PWM1_P 98 +#define SRST_PWM1 99 +#define SRST_PWM2_P 100 +#define SRST_PWM2 101 +#define SRST_PERI_NIU_A 104 +#define SRST_PERI_NIU_H 105 +#define SRST_PERI_NIU_p 106 +#define SRST_USB2OTG_H 107 +#define SRST_USB2OTG 108 +#define SRST_USB2OTG_ADP 109 +#define SRST_USB2HOST_H 110 +#define SRST_USB2HOST_ARB_H 111 + +/* cru_softrst_con7 */ +#define SRST_USB2HOST_AUX_H 112 +#define SRST_USB2HOST_EHCI 113 +#define SRST_USB2HOST 114 +#define SRST_USBPHYPOR 115 +#define SRST_UTMI0 116 +#define SRST_UTMI1 117 +#define SRST_SDIO_H 118 +#define SRST_EMMC_H 119 +#define SRST_SFC_H 120 +#define SRST_SFC 121 +#define SRST_SD_H 122 +#define SRST_NANDC_H 123 +#define SRST_NANDC_N 124 +#define SRST_MAC_A 125 +#define SRST_CAN_P 126 +#define SRST_OWIRE_P 127 + +/* cru_softrst_con8 */ +#define SRST_AUDIO_NIU_H 128 +#define SRST_AUDIO_NIU_P 129 +#define SRST_PDM_H 130 +#define SRST_PDM_M 131 +#define SRST_SPDIFTX_H 132 +#define SRST_SPDIFTX_M 133 +#define SRST_SPDIFRX_H 134 +#define SRST_SPDIFRX_M 135 +#define SRST_I2S0_8CH_H 136 +#define SRST_I2S0_8CH_TX_M 137 +#define SRST_I2S0_8CH_RX_M 138 +#define SRST_I2S1_8CH_H 139 +#define SRST_I2S1_8CH_TX_M 140 +#define SRST_I2S1_8CH_RX_M 141 +#define SRST_I2S2_8CH_H 142 +#define SRST_I2S2_8CH_TX_M 143 + +/* cru_softrst_con9 */ +#define SRST_I2S2_8CH_RX_M 144 +#define SRST_I2S3_8CH_H 145 +#define SRST_I2S3_8CH_TX_M 146 +#define SRST_I2S3_8CH_RX_M 147 +#define SRST_I2S0_2CH_H 148 +#define SRST_I2S0_2CH_M 149 +#define SRST_I2S1_2CH_H 150 +#define SRST_I2S1_2CH_M 151 +#define SRST_VAD_H 152 +#define SRST_ACODEC_P 153 + +#endif -- cgit v1.3.1 From 9e3de722e4967100306cb5e074e3984a03539ee9 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Thu, 14 Nov 2019 11:21:15 +0800 Subject: board: rockchip: Add rk3308 evb support Add support for rk3308 evaluation board. Signed-off-by: Andy Yan Reviewed-by: Kever Yang --- arch/arm/mach-rockchip/rk3308/Kconfig | 8 ++++ board/rockchip/evb_rk3308/Kconfig | 15 +++++++ board/rockchip/evb_rk3308/MAINTAINERS | 6 +++ board/rockchip/evb_rk3308/Makefile | 7 ++++ board/rockchip/evb_rk3308/evb_rk3308.c | 44 +++++++++++++++++++ configs/evb-rk3308_defconfig | 77 ++++++++++++++++++++++++++++++++++ include/configs/evb_rk3308.h | 20 +++++++++ 7 files changed, 177 insertions(+) create mode 100644 board/rockchip/evb_rk3308/Kconfig create mode 100644 board/rockchip/evb_rk3308/MAINTAINERS create mode 100644 board/rockchip/evb_rk3308/Makefile create mode 100644 board/rockchip/evb_rk3308/evb_rk3308.c create mode 100644 configs/evb-rk3308_defconfig create mode 100644 include/configs/evb_rk3308.h (limited to 'include') diff --git a/arch/arm/mach-rockchip/rk3308/Kconfig b/arch/arm/mach-rockchip/rk3308/Kconfig index 9c096615953..c74d1fc7f11 100644 --- a/arch/arm/mach-rockchip/rk3308/Kconfig +++ b/arch/arm/mach-rockchip/rk3308/Kconfig @@ -1,5 +1,9 @@ if ROCKCHIP_RK3308 +config TARGET_EVB_RK3308 + bool "EVB_RK3308" + select BOARD_LATE_INIT + config SYS_SOC default "rk3308" @@ -11,4 +15,8 @@ config SPL_SERIAL_SUPPORT config ROCKCHIP_BOOT_MODE_REG default 0xff000500 + + +source "board/rockchip/evb_rk3308/Kconfig" + endif diff --git a/board/rockchip/evb_rk3308/Kconfig b/board/rockchip/evb_rk3308/Kconfig new file mode 100644 index 00000000000..0074429cb6d --- /dev/null +++ b/board/rockchip/evb_rk3308/Kconfig @@ -0,0 +1,15 @@ +if TARGET_EVB_RK3308 + +config SYS_BOARD + default "evb_rk3308" + +config SYS_VENDOR + default "rockchip" + +config SYS_CONFIG_NAME + default "evb_rk3308" + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + +endif diff --git a/board/rockchip/evb_rk3308/MAINTAINERS b/board/rockchip/evb_rk3308/MAINTAINERS new file mode 100644 index 00000000000..0af119ae0aa --- /dev/null +++ b/board/rockchip/evb_rk3308/MAINTAINERS @@ -0,0 +1,6 @@ +EVB-RK3308 +M: Andy Yan +S: Maintained +F: board/rockchip/evb_rk3308 +F: include/configs/evb_rk3308.h +F: configs/evb-rk3308_defconfig diff --git a/board/rockchip/evb_rk3308/Makefile b/board/rockchip/evb_rk3308/Makefile new file mode 100644 index 00000000000..05de5560f14 --- /dev/null +++ b/board/rockchip/evb_rk3308/Makefile @@ -0,0 +1,7 @@ +# +# (C) Copyright 2018 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += evb_rk3308.o diff --git a/board/rockchip/evb_rk3308/evb_rk3308.c b/board/rockchip/evb_rk3308/evb_rk3308.c new file mode 100644 index 00000000000..180f1fe4f00 --- /dev/null +++ b/board/rockchip/evb_rk3308/evb_rk3308.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2018 Rockchip Electronics Co., Ltd + */ + +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define KEY_DOWN_MIN_VAL 0 +#define KEY_DOWN_MAX_VAL 30 + +/* + * Two board variants whith adc channel 3 is for board id + * v10: 1024, v11: 512 + * v10: adc channel 0 for dnl key + * v11: adc channel 1 for dnl key + */ +int rockchip_dnl_key_pressed(void) +{ + unsigned int key_val, id_val; + int key_ch; + + if (adc_channel_single_shot("saradc", 3, &id_val)) { + printf("%s read board id failed\n", __func__); + return false; + } + + if (abs(id_val - 1024) <= 30) + key_ch = 0; + else + key_ch = 1; + + if (adc_channel_single_shot("saradc", key_ch, &key_val)) { + printf("%s read adc key val failed\n", __func__); + return false; + } + + if (key_val >= KEY_DOWN_MIN_VAL && key_val <= KEY_DOWN_MAX_VAL) + return true; + else + return false; +} diff --git a/configs/evb-rk3308_defconfig b/configs/evb-rk3308_defconfig new file mode 100644 index 00000000000..36d30dfa805 --- /dev/null +++ b/configs/evb-rk3308_defconfig @@ -0,0 +1,77 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SYS_TEXT_BASE=0x00600000 +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_ROCKCHIP_RK3308=y +CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0 +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_TARGET_EVB_RK3308=y +CONFIG_SPL_STACK_R_ADDR=0xc00000 +CONFIG_DEBUG_UART_BASE=0xFF0C0000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART=y +CONFIG_ANDROID_BOOT_IMAGE=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_BOOTDELAY=0 +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_SPL_STACK_R=y +# CONFIG_CMD_BDI is not set +# CONFIG_CMD_CONSOLE is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPT=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +# CONFIG_CMD_ITEST is not set +# CONFIG_CMD_SETEXPR is not set +# CONFIG_CMD_MISC is not set +# CONFIG_DOS_PARTITION is not set +# CONFIG_ISO_PARTITION is not set +CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64 +CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_LIVE=y +CONFIG_DEFAULT_DEVICE_TREE="rk3308-evb" +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_REGMAP=y +CONFIG_SYSCON=y +CONFIG_CLK=y +# CONFIG_USB_FUNCTION_FASTBOOT is not set +CONFIG_ROCKCHIP_GPIO=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_PHY=y +CONFIG_PINCTRL=y +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_DM_RESET=y +CONFIG_BAUDRATE=1500000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_SKIP_INIT=y +CONFIG_SYSRESET=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_DWC2=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DWC2_OTG=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_SPL_TINY_MEMSET=y +CONFIG_LZ4=y +CONFIG_LZO=y +CONFIG_ERRNO_STR=y +# CONFIG_EFI_LOADER is not set diff --git a/include/configs/evb_rk3308.h b/include/configs/evb_rk3308.h new file mode 100644 index 00000000000..4d40606e4bd --- /dev/null +++ b/include/configs/evb_rk3308.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * (C) Copyright 2018 Rockchip Electronics Co., Ltd + */ + +#ifndef __EVB_RK3308_H +#define __EVB_RK3308_H + +#include + +#define CONFIG_SUPPORT_EMMC_RPMB +#define CONFIG_SYS_MMC_ENV_DEV 0 + +#define ROCKCHIP_DEVICE_SETTINGS \ + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0" +#undef CONFIG_CONSOLE_SCROLL_LINES +#define CONFIG_CONSOLE_SCROLL_LINES 10 + +#endif -- cgit v1.3.1 From 208b8cd646a7c3be64a45dfb154e4e2dd2b39ad0 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Thu, 14 Nov 2019 11:23:02 +0800 Subject: rockchip: rk3308: Add support for ROC-RK3308-CC board ROC-RK3308-CC is a rk3308 based board designed by Firelfy, with eMMC and 256MB DDR3 and RTL8188 Wifi on board. Signed-off-by: Andy Yan Reviewed-by: Kever Yang --- arch/arm/mach-rockchip/rk3308/Kconfig | 5 ++ board/firefly/firefly-rk3308/Kconfig | 15 ++++++ board/firefly/firefly-rk3308/MAINTAINERS | 5 ++ board/firefly/firefly-rk3308/Makefile | 7 +++ board/firefly/firefly-rk3308/roc_cc_rk3308.c | 81 ++++++++++++++++++++++++++++ configs/roc-cc-rk3308_defconfig | 77 ++++++++++++++++++++++++++ include/configs/firefly_rk3308.h | 20 +++++++ 7 files changed, 210 insertions(+) create mode 100644 board/firefly/firefly-rk3308/Kconfig create mode 100644 board/firefly/firefly-rk3308/MAINTAINERS create mode 100644 board/firefly/firefly-rk3308/Makefile create mode 100644 board/firefly/firefly-rk3308/roc_cc_rk3308.c create mode 100644 configs/roc-cc-rk3308_defconfig create mode 100644 include/configs/firefly_rk3308.h (limited to 'include') diff --git a/arch/arm/mach-rockchip/rk3308/Kconfig b/arch/arm/mach-rockchip/rk3308/Kconfig index c74d1fc7f11..b9fdfe2e950 100644 --- a/arch/arm/mach-rockchip/rk3308/Kconfig +++ b/arch/arm/mach-rockchip/rk3308/Kconfig @@ -4,6 +4,10 @@ config TARGET_EVB_RK3308 bool "EVB_RK3308" select BOARD_LATE_INIT +config TARGET_ROC_RK3308_CC + bool "Firefly roc-rk3308-cc" + select BOARD_LATE_INIT + config SYS_SOC default "rk3308" @@ -18,5 +22,6 @@ config ROCKCHIP_BOOT_MODE_REG source "board/rockchip/evb_rk3308/Kconfig" +source "board/firefly/firefly-rk3308/Kconfig" endif diff --git a/board/firefly/firefly-rk3308/Kconfig b/board/firefly/firefly-rk3308/Kconfig new file mode 100644 index 00000000000..80b1ad85a2e --- /dev/null +++ b/board/firefly/firefly-rk3308/Kconfig @@ -0,0 +1,15 @@ +if TARGET_ROC_RK3308_CC + +config SYS_BOARD + default "firefly-rk3308" + +config SYS_VENDOR + default "firefly" + +config SYS_CONFIG_NAME + default "firefly_rk3308" + +config BOARD_SPECIFIC_OPTIONS # dummy + def_bool y + +endif diff --git a/board/firefly/firefly-rk3308/MAINTAINERS b/board/firefly/firefly-rk3308/MAINTAINERS new file mode 100644 index 00000000000..199079717e7 --- /dev/null +++ b/board/firefly/firefly-rk3308/MAINTAINERS @@ -0,0 +1,5 @@ +ROC-RK3308-CC +M: Andy Yan +S: Maintained +F: board/firefly/firefly-rk3308/roc_cc_rk3308.c +F: configs/roc-cc-rk3308_defconfig diff --git a/board/firefly/firefly-rk3308/Makefile b/board/firefly/firefly-rk3308/Makefile new file mode 100644 index 00000000000..4c50b26ea9b --- /dev/null +++ b/board/firefly/firefly-rk3308/Makefile @@ -0,0 +1,7 @@ +# +# (C) Copyright 2018 Rockchip Electronics Co., Ltd +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += roc_cc_rk3308.o diff --git a/board/firefly/firefly-rk3308/roc_cc_rk3308.c b/board/firefly/firefly-rk3308/roc_cc_rk3308.c new file mode 100644 index 00000000000..5f0a6594b67 --- /dev/null +++ b/board/firefly/firefly-rk3308/roc_cc_rk3308.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2019 Rockchip Electronics Co., Ltd + */ + +#include +#include +#include +#include +#include + +#if defined(CONFIG_DEBUG_UART) +#define GRF_BASE 0xff000000 + +enum { + GPIO1C7_SHIFT = 8, + GPIO1C7_MASK = GENMASK(11, 8), + GPIO1C7_GPIO = 0, + GPIO1C7_UART1_RTSN, + GPIO1C7_UART2_TX_M0, + GPIO1C7_SPI2_MOSI, + GPIO1C7_JTAG_TMS, + + GPIO1C6_SHIFT = 4, + GPIO1C6_MASK = GENMASK(7, 4), + GPIO1C6_GPIO = 0, + GPIO1C6_UART1_CTSN, + GPIO1C6_UART2_RX_M0, + GPIO1C6_SPI2_MISO, + GPIO1C6_JTAG_TCLK, + + GPIO4D3_SHIFT = 6, + GPIO4D3_MASK = GENMASK(7, 6), + GPIO4D3_GPIO = 0, + GPIO4D3_SDMMC_D3, + GPIO4D3_UART2_TX_M1, + + GPIO4D2_SHIFT = 4, + GPIO4D2_MASK = GENMASK(5, 4), + GPIO4D2_GPIO = 0, + GPIO4D2_SDMMC_D2, + GPIO4D2_UART2_RX_M1, + + UART2_IO_SEL_SHIFT = 2, + UART2_IO_SEL_MASK = GENMASK(3, 2), + UART2_IO_SEL_M0 = 0, + UART2_IO_SEL_M1, + UART2_IO_SEL_USB, +}; + +void board_debug_uart_init(void) +{ + static struct rk3308_grf * const grf = (void *)GRF_BASE; + + /* Enable early UART2 channel m0 on the rk3308 */ + rk_clrsetreg(&grf->soc_con5, UART2_IO_SEL_MASK, + UART2_IO_SEL_M0 << UART2_IO_SEL_SHIFT); + rk_clrsetreg(&grf->gpio1ch_iomux, + GPIO1C6_MASK | GPIO1C7_MASK, + GPIO1C6_UART2_RX_M0 << GPIO1C6_SHIFT | + GPIO1C7_UART2_TX_M0 << GPIO1C7_SHIFT); +} +#endif + +#define KEY_DOWN_MIN_VAL 0 +#define KEY_DOWN_MAX_VAL 30 + +int rockchip_dnl_key_pressed(void) +{ + unsigned int val; + + if (adc_channel_single_shot("saradc", 1, &val)) { + printf("%s read adc key val failed\n", __func__); + return false; + } + + if (val >= KEY_DOWN_MIN_VAL && val <= KEY_DOWN_MAX_VAL) + return true; + else + return false; +} diff --git a/configs/roc-cc-rk3308_defconfig b/configs/roc-cc-rk3308_defconfig new file mode 100644 index 00000000000..82ebe6a786e --- /dev/null +++ b/configs/roc-cc-rk3308_defconfig @@ -0,0 +1,77 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SYS_TEXT_BASE=0x00600000 +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_ROCKCHIP_RK3308=y +CONFIG_ROCKCHIP_SPL_RESERVE_IRAM=0x0 +CONFIG_SPL_DRIVERS_MISC_SUPPORT=y +CONFIG_TARGET_ROC_RK3308_CC=y +CONFIG_SPL_STACK_R_ADDR=0xc00000 +CONFIG_DEBUG_UART_BASE=0xFF0C0000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART=y +CONFIG_ANDROID_BOOT_IMAGE=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_BOOTDELAY=0 +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_SPL_STACK_R=y +# CONFIG_CMD_BDI is not set +# CONFIG_CMD_CONSOLE is not set +# CONFIG_CMD_ELF is not set +# CONFIG_CMD_IMI is not set +# CONFIG_CMD_XIMG is not set +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPT=y +# CONFIG_CMD_LOADB is not set +# CONFIG_CMD_LOADS is not set +CONFIG_CMD_MMC=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +# CONFIG_CMD_ITEST is not set +# CONFIG_CMD_SETEXPR is not set +# CONFIG_CMD_MISC is not set +# CONFIG_DOS_PARTITION is not set +# CONFIG_ISO_PARTITION is not set +CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=64 +CONFIG_SPL_OF_CONTROL=y +CONFIG_OF_LIVE=y +CONFIG_DEFAULT_DEVICE_TREE="rk3308-roc-cc" +CONFIG_OF_SPL_REMOVE_PROPS="pinctrl-0 pinctrl-names clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_REGMAP=y +CONFIG_SYSCON=y +CONFIG_CLK=y +# CONFIG_USB_FUNCTION_FASTBOOT is not set +CONFIG_ROCKCHIP_GPIO=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_PHY=y +CONFIG_PINCTRL=y +CONFIG_REGULATOR_PWM=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_DM_RESET=y +CONFIG_BAUDRATE=1500000 +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_SKIP_INIT=y +CONFIG_SYSRESET=y +CONFIG_USB=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_GENERIC=y +CONFIG_USB_DWC2=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_DWC2_OTG=y +CONFIG_USB_GADGET_DOWNLOAD=y +CONFIG_SPL_TINY_MEMSET=y +CONFIG_LZ4=y +CONFIG_LZO=y +CONFIG_ERRNO_STR=y +# CONFIG_EFI_LOADER is not set diff --git a/include/configs/firefly_rk3308.h b/include/configs/firefly_rk3308.h new file mode 100644 index 00000000000..2cc7b4a153f --- /dev/null +++ b/include/configs/firefly_rk3308.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2019 Rockchip Electronics Co., Ltd + */ + +#ifndef __FIREFLY_RK3308_H +#define __FIREFLY_RK3308_H + +#include + +#define CONFIG_SUPPORT_EMMC_RPMB +#define CONFIG_SYS_MMC_ENV_DEV 0 + +#define ROCKCHIP_DEVICE_SETTINGS \ + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0" +#undef CONFIG_CONSOLE_SCROLL_LINES +#define CONFIG_CONSOLE_SCROLL_LINES 10 + +#endif -- cgit v1.3.1 From 59b01eb7a17a7c0915fd8aff8f818699b4624137 Mon Sep 17 00:00:00 2001 From: Michael Trimarchi Date: Fri, 15 Nov 2019 22:07:24 +0100 Subject: rockchip: dts: tinker: Add tinker-s board support Support tinker-s board. The board is equivalent of tinker board except of emmc. TODO: - support of usb current burst when the board is powered from pc Signed-off-by: Michael Trimarchi Reviewed-by: Kever Yang --- arch/arm/dts/Makefile | 1 + arch/arm/dts/rk3288-tinker-s-u-boot.dtsi | 34 ++++++++++ arch/arm/dts/rk3288-tinker-s.dts | 29 ++++++++ board/rockchip/tinker_rk3288/MAINTAINERS | 7 ++ board/rockchip/tinker_rk3288/tinker-rk3288.c | 12 ++++ configs/tinker-s-rk3288_defconfig | 99 ++++++++++++++++++++++++++++ include/configs/tinker_rk3288.h | 1 + 7 files changed, 183 insertions(+) create mode 100644 arch/arm/dts/rk3288-tinker-s-u-boot.dtsi create mode 100644 arch/arm/dts/rk3288-tinker-s.dts create mode 100644 configs/tinker-s-rk3288_defconfig (limited to 'include') diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index c22fbaf2255..d8846df1bdd 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -90,6 +90,7 @@ dtb-$(CONFIG_ROCKCHIP_RK3288) += \ rk3288-popmetal.dtb \ rk3288-rock2-square.dtb \ rk3288-tinker.dtb \ + rk3288-tinker-s.dtb \ rk3288-veyron-jerry.dtb \ rk3288-veyron-mickey.dtb \ rk3288-veyron-minnie.dtb \ diff --git a/arch/arm/dts/rk3288-tinker-s-u-boot.dtsi b/arch/arm/dts/rk3288-tinker-s-u-boot.dtsi new file mode 100644 index 00000000000..a177fca73a5 --- /dev/null +++ b/arch/arm/dts/rk3288-tinker-s-u-boot.dtsi @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Amarula Solutions SRO + */ + +#include "rk3288-u-boot.dtsi" +#include "rk3288-tinker-u-boot.dtsi" + +/ { + chosen { + u-boot,spl-boot-order = \ + "same-as-spl", &sdmmc, &emmc; + }; +}; + +&emmc { + u-boot,dm-spl; +}; + +&emmc_clk { + u-boot,dm-spl; +}; + +&emmc_cmd { + u-boot,dm-spl; +}; + +&emmc_pwr { + u-boot,dm-spl; +}; + +&emmc_bus8 { + u-boot,dm-spl; +}; diff --git a/arch/arm/dts/rk3288-tinker-s.dts b/arch/arm/dts/rk3288-tinker-s.dts new file mode 100644 index 00000000000..cc7ac5f8811 --- /dev/null +++ b/arch/arm/dts/rk3288-tinker-s.dts @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd. + */ + +/dts-v1/; + +#include "rk3288-tinker.dtsi" + +/ { + model = "Rockchip RK3288 Asus Tinker Board S"; + compatible = "asus,rk3288-tinker-s", "rockchip,rk3288"; + + chosen { + stdout-path = &uart2; + }; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>; + max-frequency = <150000000>; + mmc-hs200-1_8v; + mmc-ddr-1_8v; + status = "okay"; +}; diff --git a/board/rockchip/tinker_rk3288/MAINTAINERS b/board/rockchip/tinker_rk3288/MAINTAINERS index cddceafb6e9..ed5de682c97 100644 --- a/board/rockchip/tinker_rk3288/MAINTAINERS +++ b/board/rockchip/tinker_rk3288/MAINTAINERS @@ -4,3 +4,10 @@ S: Maintained F: board/rockchip/tinker_rk3288 F: include/configs/tinker_rk3288.h F: configs/tinker-rk3288_defconfig + +TINKER-S-RK3288 +M: Michael Trimarchi +S: Maintained +F: board/rockchip/tinker_rk3288 +F: include/configs/tinker_rk3288.h +F: configs/tinker-s-rk3288_defconfig diff --git a/board/rockchip/tinker_rk3288/tinker-rk3288.c b/board/rockchip/tinker_rk3288/tinker-rk3288.c index 6c76c3c25c4..7a0c3c997d9 100644 --- a/board/rockchip/tinker_rk3288/tinker-rk3288.c +++ b/board/rockchip/tinker_rk3288/tinker-rk3288.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include static int get_ethaddr_from_eeprom(u8 *addr) { @@ -33,3 +35,13 @@ int rk3288_board_late_init(void) return 0; } + +int mmc_get_env_dev(void) +{ + u32 bootdevice_brom_id = readl(BROM_BOOTSOURCE_ID_ADDR); + + if (bootdevice_brom_id == BROM_BOOTSOURCE_EMMC) + return 0; + + return 1; +} diff --git a/configs/tinker-s-rk3288_defconfig b/configs/tinker-s-rk3288_defconfig new file mode 100644 index 00000000000..c851a93f312 --- /dev/null +++ b/configs/tinker-s-rk3288_defconfig @@ -0,0 +1,99 @@ +CONFIG_ARM=y +CONFIG_ARCH_ROCKCHIP=y +CONFIG_SYS_TEXT_BASE=0x01000000 +CONFIG_SPL_GPIO_SUPPORT=y +CONFIG_ROCKCHIP_RK3288=y +CONFIG_TARGET_TINKER_RK3288=y +CONFIG_NR_DRAM_BANKS=1 +CONFIG_SPL_SIZE_LIMIT=307200 +CONFIG_SPL_STACK_R_ADDR=0x800000 +CONFIG_DEBUG_UART_BASE=0xff690000 +CONFIG_DEBUG_UART_CLOCK=24000000 +CONFIG_DEBUG_UART=y +CONFIG_TPL_SYS_MALLOC_F_LEN=0x4000 +CONFIG_SPL_SYS_MALLOC_F_LEN=0x4000 +CONFIG_SYS_MALLOC_F_LEN=0x4000 +# CONFIG_ANDROID_BOOT_IMAGE is not set +CONFIG_USE_PREBOOT=y +CONFIG_SILENT_CONSOLE=y +CONFIG_CONSOLE_MUX=y +CONFIG_DEFAULT_FDT_FILE="rk3288-tinker-s.dtb" +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_SPL_STACK_R=y +CONFIG_SPL_STACK_R_MALLOC_SIMPLE_LEN=0x300000 +CONFIG_SPL_I2C_SUPPORT=y +CONFIG_SPL_POWER_SUPPORT=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_GPT=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +CONFIG_CMD_USB_MASS_STORAGE=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_BMP=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_PMIC=y +CONFIG_CMD_REGULATOR=y +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set +CONFIG_SPL_PARTITION_UUIDS=y +CONFIG_SPL_OF_CONTROL=y +CONFIG_DEFAULT_DEVICE_TREE="rk3288-tinker-s" +CONFIG_OF_SPL_REMOVE_PROPS="clock-names interrupt-parent assigned-clocks assigned-clock-rates assigned-clock-parents" +CONFIG_ENV_IS_IN_MMC=y +CONFIG_REGMAP=y +CONFIG_SPL_REGMAP=y +CONFIG_SYSCON=y +CONFIG_SPL_SYSCON=y +# CONFIG_SPL_SIMPLE_BUS is not set +CONFIG_CLK=y +CONFIG_SPL_CLK=y +CONFIG_FASTBOOT_FLASH=y +CONFIG_FASTBOOT_FLASH_MMC_DEV=0 +CONFIG_FASTBOOT_CMD_OEM_FORMAT=y +CONFIG_ROCKCHIP_GPIO=y +CONFIG_SYS_I2C_ROCKCHIP=y +CONFIG_MISC=y +CONFIG_I2C_EEPROM=y +CONFIG_MMC_DW=y +CONFIG_MMC_DW_ROCKCHIP=y +CONFIG_SPI_FLASH=y +CONFIG_SF_DEFAULT_SPEED=20000000 +CONFIG_DM_ETH=y +CONFIG_ETH_DESIGNWARE=y +CONFIG_GMAC_ROCKCHIP=y +CONFIG_PINCTRL=y +CONFIG_SPL_PINCTRL=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_RK8XX=y +CONFIG_SPL_DM_REGULATOR=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_SPL_DM_REGULATOR_FIXED=y +CONFIG_REGULATOR_RK8XX=y +CONFIG_PWM_ROCKCHIP=y +CONFIG_RAM=y +CONFIG_SPL_RAM=y +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_SYSRESET=y +CONFIG_USB=y +CONFIG_USB_DWC2=y +CONFIG_ROCKCHIP_USB2_PHY=y +CONFIG_USB_GADGET=y +CONFIG_USB_GADGET_MANUFACTURER="Rockchip" +CONFIG_USB_GADGET_VENDOR_NUM=0x2207 +CONFIG_USB_GADGET_PRODUCT_NUM=0x320a +CONFIG_USB_GADGET_DWC2_OTG=y +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y +CONFIG_USB_ETHER_SMSC95XX=y +CONFIG_CMD_DHRYSTONE=y +CONFIG_ERRNO_STR=y +CONFIG_DM_VIDEO=y +CONFIG_DISPLAY=y +CONFIG_VIDEO_ROCKCHIP=y +CONFIG_DISPLAY_ROCKCHIP_HDMI=y +CONFIG_CONSOLE_SCROLL_LINES=10 diff --git a/include/configs/tinker_rk3288.h b/include/configs/tinker_rk3288.h index 5adae68c91b..f8a55a2cec6 100644 --- a/include/configs/tinker_rk3288.h +++ b/include/configs/tinker_rk3288.h @@ -12,6 +12,7 @@ #undef BOOT_TARGET_DEVICES #define BOOT_TARGET_DEVICES(func) \ + func(MMC, mmc, 0) \ func(MMC, mmc, 1) \ func(USB, usb, 0) \ func(PXE, pxe, na) \ -- cgit v1.3.1