Improvements:

- RK3188 USB-UART functionality
 - errors triggering a hard-stop in SPL on the RK3399 are reported
 - Rockchip RV1108 (SoC) support
 - MicroCrystal RV3029 (RTC) DM driver
 
 Fixes:
 - RK3188 early UART setup
 - limit SD-card frequency to 40MHz on the RK3399-Q7
 - MIPI fixes
 - RK3399 CPUB clock initialisation
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJcAab4AAoJECaAFcEOcohNx8gH/0OuW443gsA8Ty0rXpCvbzSi
 UejfBfqljX4tYcUrgABVdMd2WdUyQ6rSoVgnX6mvfToCxd51L2CQiimrTJRQp/ZQ
 yCrwC8iFYwgmyM/0UnnjRa03WJvYBi3McWWIxQy7ZywQcZkdIuyn6t5AbcRppGMF
 67G0ft9KRwB+dMcgdRuikDThZRhAWZ30MdY4LFZvyGWupuv/mdpyYhjHYyv05CVf
 BvaUqRFkt86GBAW7Hq+OahH1t/xuZBcPJdt8GC40Blgfmle2uvZOIpoSEezVwFXm
 qKSj5FSSVQ9XtMeWwWvHLUxKSua0pIX5d7HmK9WqcsUIePDbzth8i+/BdA+5AD4=
 =EYJx
 -----END PGP SIGNATURE-----

Merge tag 'for-master-20181130' of git://git.denx.de/u-boot-rockchip

Improvements:
- RK3188 USB-UART functionality
- errors triggering a hard-stop in SPL on the RK3399 are reported
- Rockchip RV1108 (SoC) support
- MicroCrystal RV3029 (RTC) DM driver

Fixes:
- RK3188 early UART setup
- limit SD-card frequency to 40MHz on the RK3399-Q7
- MIPI fixes
- RK3399 CPUB clock initialisation
This commit is contained in:
Tom Rini 2018-12-01 14:17:27 -05:00
commit c1d6e0bbfd
21 changed files with 1549 additions and 207 deletions

View file

@ -503,7 +503,7 @@
&sdmmc {
u-boot,dm-pre-reloc;
clock-frequency = <150000000>;
clock-freq-min-max = <100000 150000000>;
max-frequency = <40000000>;
supports-sd;
bus-width = <4>;
cap-mmc-highspeed;

View file

@ -121,8 +121,35 @@
};
grf: syscon@10300000 {
compatible = "rockchip,rv1108-grf", "syscon";
compatible = "rockchip,rv1108-grf", "syscon", "simple-mfd";
reg = <0x10300000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
u2phy: usb2-phy@100 {
compatible = "rockchip,rv1108-usb2phy";
reg = <0x100 0x0c>;
clocks = <&cru SCLK_USBPHY>;
clock-names = "phyclk";
#clock-cells = <0>;
clock-output-names = "usbphy";
rockchip,usbgrf = <&usbgrf>;
status = "disabled";
u2phy_otg: otg-port {
interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "otg-mux";
#phy-cells = <0>;
status = "disabled";
};
u2phy_host: host-port {
interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "linestate";
#phy-cells = <0>;
status = "disabled";
};
};
};
saradc: saradc@1038c000 {
@ -141,6 +168,11 @@
reg = <0x20060000 0x1000>;
};
usbgrf: syscon@202a0000 {
compatible = "rockchip,rv1108-usbgrf", "syscon";
reg = <0x202a0000 0x1000>;
};
cru: clock-controller@20200000 {
compatible = "rockchip,rv1108-cru";
reg = <0x20200000 0x1000>;
@ -200,12 +232,19 @@
};
usb20_otg: usb@30180000 {
compatible = "rockchip,rv1108-usb", "rockchip,rk3288-usb",
compatible = "rockchip,rv1108-usb", "rockchip,rk3066-usb",
"snps,dwc2";
reg = <0x30180000 0x40000>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
hnp-srp-disable;
clocks = <&cru HCLK_OTG>;
clock-names = "otg";
dr_mode = "otg";
g-np-tx-fifo-size = <16>;
g-rx-fifo-size = <280>;
g-tx-fifo-size = <256 128 128 64 32 16>;
g-use-dma;
phys = <&u2phy_otg>;
phy-names = "usb2-phy";
status = "disabled";
};
@ -427,6 +466,35 @@
};
};
emmc {
emmc_clk: emmc-clk {
rockchip,pins = <2 RK_PB6 RK_FUNC_1 &pcfg_pull_none_drv_8ma>;
};
emmc_cmd: emmc-cmd {
rockchip,pins = <2 RK_PB4 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
};
emmc_pwren: emmc-pwren {
rockchip,pins = <2 RK_PC2 RK_FUNC_2 &pcfg_pull_none>;
};
emmc_bus1: emmc-bus1 {
rockchip,pins = <2 RK_PA0 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
};
emmc_bus8: emmc-bus8 {
rockchip,pins = <2 RK_PA0 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
<2 RK_PA1 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
<2 RK_PA2 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
<2 RK_PA3 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
<2 RK_PA4 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
<2 RK_PA5 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
<2 RK_PA6 RK_FUNC_2 &pcfg_pull_up_drv_8ma>,
<2 RK_PA7 RK_FUNC_2 &pcfg_pull_up_drv_8ma>;
};
};
sdmmc {
sdmmc_clk: sdmmc-clk {
rockchip,pins = <3 RK_PC4 RK_FUNC_1 &pcfg_pull_none_drv_4ma>;

View file

@ -43,6 +43,12 @@ struct sysreset_reg {
unsigned int glb_srst_snd_value;
};
struct softreset_reg {
void __iomem *base;
unsigned int sf_reset_offset;
unsigned int sf_reset_num;
};
/**
* clk_get_divisor() - Calculate the required clock divisior
*

View file

@ -69,16 +69,21 @@ check_member(rk3399_cru, sdio1_con[1], 0x594);
#define MHz 1000000
#define KHz 1000
#define OSC_HZ (24*MHz)
#define APLL_HZ (600*MHz)
#define LPLL_HZ (600*MHz)
#define BPLL_HZ (600*MHz)
#define GPLL_HZ (594*MHz)
#define CPLL_HZ (384*MHz)
#define PPLL_HZ (676*MHz)
#define PMU_PCLK_HZ (48*MHz)
#define ACLKM_CORE_HZ (300*MHz)
#define ATCLK_CORE_HZ (300*MHz)
#define PCLK_DBG_HZ (100*MHz)
#define ACLKM_CORE_L_HZ (300*MHz)
#define ATCLK_CORE_L_HZ (300*MHz)
#define PCLK_DBG_L_HZ (100*MHz)
#define ACLKM_CORE_B_HZ (300*MHz)
#define ATCLK_CORE_B_HZ (300*MHz)
#define PCLK_DBG_B_HZ (100*MHz)
#define PERIHP_ACLK_HZ (148500*KHz)
#define PERIHP_HCLK_HZ (148500*KHz)
@ -98,4 +103,13 @@ enum apll_l_frequencies {
APLL_L_600_MHZ,
};
enum apll_b_frequencies {
APLL_B_600_MHZ,
};
void rk3399_configure_cpu_l(struct rk3399_cru *cru,
enum apll_l_frequencies apll_l_freq);
void rk3399_configure_cpu_b(struct rk3399_cru *cru,
enum apll_b_frequencies apll_b_freq);
#endif /* __ASM_ARCH_CRU_RK3399_H_ */

View file

@ -11,7 +11,11 @@
#define OSC_HZ (24 * 1000 * 1000)
#define APLL_HZ (600 * 1000000)
#define GPLL_HZ (594 * 1000000)
#define GPLL_HZ (1188 * 1000000)
#define ACLK_PERI_HZ (148500000)
#define HCLK_PERI_HZ (148500000)
#define PCLK_PERI_HZ (74250000)
#define ACLK_BUS_HZ (148500000)
struct rv1108_clk_priv {
struct rv1108_cru *cru;
@ -80,6 +84,11 @@ enum {
WORK_MODE_NORMAL = 1,
DSMPD_SHIFT = 3,
DSMPD_MASK = 1 << DSMPD_SHIFT,
INTEGER_MODE = 1,
GLOBAL_POWER_DOWN_SHIFT = 0,
GLOBAL_POWER_DOWN_MASK = 1 << GLOBAL_POWER_DOWN_SHIFT,
GLOBAL_POWER_DOWN = 1,
GLOBAL_POWER_UP = 0,
/* CLKSEL0_CON */
CORE_PLL_SEL_SHIFT = 8,
@ -90,11 +99,77 @@ enum {
CORE_CLK_DIV_SHIFT = 0,
CORE_CLK_DIV_MASK = 0x1f << CORE_CLK_DIV_SHIFT,
/* CLKSEL_CON1 */
PCLK_DBG_DIV_CON_SHIFT = 4,
PCLK_DBG_DIV_CON_MASK = 0xf << PCLK_DBG_DIV_CON_SHIFT,
ACLK_CORE_DIV_CON_SHIFT = 0,
ACLK_CORE_DIV_CON_MASK = 7 << ACLK_CORE_DIV_CON_SHIFT,
/* CLKSEL_CON2 */
ACLK_BUS_PLL_SEL_SHIFT = 8,
ACLK_BUS_PLL_SEL_MASK = 3 << ACLK_BUS_PLL_SEL_SHIFT,
ACLK_BUS_PLL_SEL_GPLL = 0,
ACLK_BUS_PLL_SEL_APLL = 1,
ACLK_BUS_PLL_SEL_DPLL = 2,
ACLK_BUS_DIV_CON_SHIFT = 0,
ACLK_BUS_DIV_CON_MASK = 0x1f << ACLK_BUS_DIV_CON_SHIFT,
ACLK_BUS_DIV_CON_WIDTH = 5,
/* CLKSEL_CON3 */
PCLK_BUS_DIV_CON_SHIFT = 8,
PCLK_BUS_DIV_CON_MASK = 0x1f << PCLK_BUS_DIV_CON_SHIFT,
HCLK_BUS_DIV_CON_SHIFT = 0,
HCLK_BUS_DIV_CON_MASK = 0x1f,
/* CLKSEL_CON4 */
CLK_DDR_PLL_SEL_SHIFT = 8,
CLK_DDR_PLL_SEL_MASK = 0x3 << CLK_DDR_PLL_SEL_SHIFT,
CLK_DDR_DIV_CON_SHIFT = 0,
CLK_DDR_DIV_CON_MASK = 0x3 << CLK_DDR_DIV_CON_SHIFT,
/* CLKSEL_CON19 */
CLK_I2C1_PLL_SEL_SHIFT = 15,
CLK_I2C1_PLL_SEL_MASK = 1 << CLK_I2C1_PLL_SEL_SHIFT,
CLK_I2C1_PLL_SEL_DPLL = 0,
CLK_I2C1_PLL_SEL_GPLL = 1,
CLK_I2C1_DIV_CON_SHIFT = 8,
CLK_I2C1_DIV_CON_MASK = 0x7f << CLK_I2C1_DIV_CON_SHIFT,
CLK_I2C0_PLL_SEL_SHIFT = 7,
CLK_I2C0_PLL_SEL_MASK = 1 << CLK_I2C0_PLL_SEL_SHIFT,
CLK_I2C0_DIV_CON_SHIFT = 0,
CLK_I2C0_DIV_CON_MASK = 0x7f,
I2C_DIV_CON_WIDTH = 7,
/* CLKSEL_CON20 */
CLK_I2C3_PLL_SEL_SHIFT = 15,
CLK_I2C3_PLL_SEL_MASK = 1 << CLK_I2C3_PLL_SEL_SHIFT,
CLK_I2C3_PLL_SEL_DPLL = 0,
CLK_I2C3_PLL_SEL_GPLL = 1,
CLK_I2C3_DIV_CON_SHIFT = 8,
CLK_I2C3_DIV_CON_MASK = 0x7f << CLK_I2C3_DIV_CON_SHIFT,
CLK_I2C2_PLL_SEL_SHIFT = 7,
CLK_I2C2_PLL_SEL_MASK = 1 << CLK_I2C2_PLL_SEL_SHIFT,
CLK_I2C2_DIV_CON_SHIFT = 0,
CLK_I2C2_DIV_CON_MASK = 0x7f,
/* CLKSEL_CON22 */
CLK_SARADC_DIV_CON_SHIFT= 0,
CLK_SARADC_DIV_CON_MASK = GENMASK(9, 0),
CLK_SARADC_DIV_CON_WIDTH= 10,
/* CLKSEL_CON23 */
ACLK_PERI_PLL_SEL_SHIFT = 15,
ACLK_PERI_PLL_SEL_MASK = 1 << ACLK_PERI_PLL_SEL_SHIFT,
ACLK_PERI_PLL_SEL_GPLL = 0,
ACLK_PERI_PLL_SEL_DPLL = 1,
PCLK_PERI_DIV_CON_SHIFT = 10,
PCLK_PERI_DIV_CON_MASK = 0x1f << PCLK_PERI_DIV_CON_SHIFT,
HCLK_PERI_DIV_CON_SHIFT = 5,
HCLK_PERI_DIV_CON_MASK = 0x1f << HCLK_PERI_DIV_CON_SHIFT,
ACLK_PERI_DIV_CON_SHIFT = 0,
ACLK_PERI_DIV_CON_MASK = 0x1f,
PERI_DIV_CON_WIDTH = 5,
/* CLKSEL24_CON */
MAC_PLL_SEL_SHIFT = 12,
MAC_PLL_SEL_MASK = 1 << MAC_PLL_SEL_SHIFT,
@ -105,6 +180,17 @@ enum {
MAC_CLK_DIV_MASK = 0x1f,
MAC_CLK_DIV_SHIFT = 0,
/* CLKSEL25_CON */
EMMC_PLL_SEL_SHIFT = 12,
EMMC_PLL_SEL_MASK = 3 << EMMC_PLL_SEL_SHIFT,
EMMC_PLL_SEL_DPLL = 0,
EMMC_PLL_SEL_GPLL,
EMMC_PLL_SEL_OSC,
/* CLKSEL26_CON */
EMMC_CLK_DIV_SHIFT = 8,
EMMC_CLK_DIV_MASK = 0xff << EMMC_CLK_DIV_SHIFT,
/* CLKSEL27_CON */
SFC_PLL_SEL_SHIFT = 7,
SFC_PLL_SEL_MASK = 1 << SFC_PLL_SEL_SHIFT,
@ -112,5 +198,61 @@ enum {
SFC_PLL_SEL_GPLL = 1,
SFC_CLK_DIV_SHIFT = 0,
SFC_CLK_DIV_MASK = 0x3f << SFC_CLK_DIV_SHIFT,
/* CLKSEL28_CON */
ACLK_VIO1_PLL_SEL_SHIFT = 14,
ACLK_VIO1_PLL_SEL_MASK = 3 << ACLK_VIO1_PLL_SEL_SHIFT,
VIO_PLL_SEL_DPLL = 0,
VIO_PLL_SEL_GPLL = 1,
ACLK_VIO1_CLK_DIV_SHIFT = 8,
ACLK_VIO1_CLK_DIV_MASK = 0x1f << ACLK_VIO1_CLK_DIV_SHIFT,
CLK_VIO_DIV_CON_WIDTH = 5,
ACLK_VIO0_PLL_SEL_SHIFT = 6,
ACLK_VIO0_PLL_SEL_MASK = 3 << ACLK_VIO0_PLL_SEL_SHIFT,
ACLK_VIO0_CLK_DIV_SHIFT = 0,
ACLK_VIO0_CLK_DIV_MASK = 0x1f << ACLK_VIO0_CLK_DIV_SHIFT,
/* CLKSEL29_CON */
PCLK_VIO_CLK_DIV_SHIFT = 8,
PCLK_VIO_CLK_DIV_MASK = 0x1f << PCLK_VIO_CLK_DIV_SHIFT,
HCLK_VIO_CLK_DIV_SHIFT = 0,
HCLK_VIO_CLK_DIV_MASK = 0x1f << HCLK_VIO_CLK_DIV_SHIFT,
/* CLKSEL32_CON */
DCLK_VOP_SEL_SHIFT = 7,
DCLK_VOP_SEL_MASK = 1 << DCLK_VOP_SEL_SHIFT,
DCLK_VOP_SEL_HDMI = 0,
DCLK_VOP_SEL_PLL = 1,
DCLK_VOP_PLL_SEL_SHIFT = 6,
DCLK_VOP_PLL_SEL_MASK = 1 << DCLK_VOP_PLL_SEL_SHIFT,
DCLK_VOP_PLL_SEL_GPLL = 0,
DCLK_VOP_PLL_SEL_DPLL = 1,
DCLK_VOP_CLK_DIV_SHIFT = 0,
DCLK_VOP_CLK_DIV_MASK = 0x3f << DCLK_VOP_CLK_DIV_SHIFT,
DCLK_VOP_DIV_CON_WIDTH = 6,
/* SOFTRST1_CON*/
DDRPHY_SRSTN_CLKDIV_REQ_SHIFT = 0,
DDRPHY_SRSTN_CLKDIV_REQ = 1,
DDRPHY_SRSTN_CLKDIV_DIS = 0,
DDRPHY_SRSTN_CLKDIV_REQ_MASK = 1 << DDRPHY_SRSTN_CLKDIV_REQ_SHIFT,
DDRPHY_SRSTN_REQ_SHIFT = 1,
DDRPHY_SRSTN_REQ = 1,
DDRPHY_SRSTN_DIS = 0,
DDRPHY_SRSTN_REQ_MASK = 1 << DDRPHY_SRSTN_REQ_SHIFT,
DDRPHY_PSRSTN_REQ_SHIFT = 2,
DDRPHY_PSRSTN_REQ = 1,
DDRPHY_PSRSTN_DIS = 0,
DDRPHY_PSRSTN_REQ_MASK = 1 << DDRPHY_PSRSTN_REQ_SHIFT,
/* SOFTRST2_CON*/
DDRUPCTL_PSRSTN_REQ_SHIFT = 0,
DDRUPCTL_PSRSTN_REQ = 1,
DDRUPCTL_PSRSTN_DIS = 0,
DDRUPCTL_PSRSTN_REQ_MASK = 1 << DDRUPCTL_PSRSTN_REQ_SHIFT,
DDRUPCTL_NSRSTN_REQ_SHIFT = 1,
DDRUPCTL_NSRSTN_REQ = 1,
DDRUPCTL_NSRSTN_DIS = 0,
DDRUPCTL_NSRSTN_REQ_MASK = 1 << DDRUPCTL_NSRSTN_REQ_SHIFT,
};
#endif

View file

@ -205,4 +205,46 @@ enum {
ATO_AE_SHIFT = 0,
ATO_AE_MASK = 1,
};
/* GRF_UOC_CON0 */
enum {
SIDDQ_SHIFT = 13,
SIDDQ_MASK = 1 << SIDDQ_SHIFT,
BYPASSSEL_SHIFT = 9,
BYPASSSEL_MASK = 1 << BYPASSSEL_SHIFT,
BYPASSDMEN_SHIFT = 8,
BYPASSDMEN_MASK = 1 << BYPASSDMEN_SHIFT,
UOC_DISABLE_SHIFT = 4,
UOC_DISABLE_MASK = 1 << UOC_DISABLE_SHIFT,
COMMON_ON_N_SHIFT = 0,
COMMON_ON_N_MASK = 1 << COMMON_ON_N_SHIFT,
};
/* GRF_UOC_CON2 */
enum {
SOFT_CON_SEL_SHIFT = 2,
SOFT_CON_SEL_MASK = 1 << SOFT_CON_SEL_SHIFT,
};
/* GRF_UOC0_CON3 */
enum {
TERMSEL_FULLSPEED_SHIFT = 5,
TERMSEL_FULLSPEED_MASK = 1 << TERMSEL_FULLSPEED_SHIFT,
XCVRSELECT_SHIFT = 3,
XCVRSELECT_FSTRANSC = 1,
XCVRSELECT_MASK = 3 << XCVRSELECT_SHIFT,
OPMODE_SHIFT = 1,
OPMODE_NODRIVING = 1,
OPMODE_MASK = 3 << OPMODE_SHIFT,
SUSPENDN_SHIFT = 0,
SUSPENDN_MASK = 1 << SUSPENDN_SHIFT,
};
#endif

View file

@ -35,6 +35,7 @@ config ROCKCHIP_RK3188
select SPL_RAM
select SPL_DRIVERS_MISC_SUPPORT
select SPL_ROCKCHIP_EARLYRETURN_TO_BROM
select DEBUG_UART_BOARD_INIT
select BOARD_LATE_INIT
select ROCKCHIP_BROM_HELPER
help
@ -156,6 +157,14 @@ config ROCKCHIP_RV1108
The Rockchip RV1108 is a ARM-based SoC with a single-core Cortex-A7
and a DSP.
config ROCKCHIP_USB_UART
bool "Route uart output to usb pins"
help
Rockchip SoCs have the ability to route the signals of the debug
uart through the d+ and d- pins of a specific usb phy to enable
some form of closed-case debugging. With this option supported
SoCs will enable this routing as a debug measure.
config SPL_ROCKCHIP_BACK_TO_BROM
bool "SPL returns to bootrom"
default y if ROCKCHIP_RK3036

View file

@ -33,6 +33,7 @@ obj-$(CONFIG_ROCKCHIP_RK322X) += rk322x-board.o
obj-$(CONFIG_ROCKCHIP_RK3288) += rk3288-board.o
obj-$(CONFIG_ROCKCHIP_RK3036) += rk3036-board.o
obj-$(CONFIG_ROCKCHIP_RK3399) += rk3399-board.o
obj-$(CONFIG_ROCKCHIP_RV1108) += rv1108-board.o
endif
obj-$(CONFIG_$(SPL_TPL_)RAM) += sdram_common.o

View file

@ -16,6 +16,7 @@
#include <asm/io.h>
#include <asm/arch/bootrom.h>
#include <asm/arch/clock.h>
#include <asm/arch/grf_rk3188.h>
#include <asm/arch/hardware.h>
#include <asm/arch/periph.h>
#include <asm/arch/pmu_rk3188.h>
@ -92,23 +93,38 @@ static int setup_arm_clock(void)
return ret;
}
void board_init_f(ulong dummy)
void board_debug_uart_init(void)
{
struct udevice *pinctrl, *dev;
int ret;
/* Example code showing how to enable the debug UART on RK3188 */
#ifdef EARLY_UART
#include <asm/arch/grf_rk3188.h>
/* Enable early UART on the RK3188 */
#define GRF_BASE 0x20008000
struct rk3188_grf * const grf = (void *)GRF_BASE;
enum {
GPIO1B1_SHIFT = 2,
GPIO1B1_MASK = 3,
GPIO1B1_GPIO = 0,
GPIO1B1_UART2_SOUT,
GPIO1B0_SHIFT = 0,
GPIO1B0_MASK = 3,
GPIO1B0_GPIO = 0,
GPIO1B0_UART2_SIN,
};
/* Enable early UART on the RK3188 */
rk_clrsetreg(&grf->gpio1b_iomux,
GPIO1B1_MASK << GPIO1B1_SHIFT |
GPIO1B0_MASK << GPIO1B0_SHIFT,
GPIO1B1_UART2_SOUT << GPIO1B1_SHIFT |
GPIO1B0_UART2_SIN << GPIO1B0_SHIFT);
}
void board_init_f(ulong dummy)
{
struct udevice *pinctrl, *dev;
int ret;
#define EARLY_UART
#ifdef EARLY_UART
/*
* Debug UART can be used from here if required:
*
@ -124,6 +140,25 @@ void board_init_f(ulong dummy)
printch('\n');
#endif
#ifdef CONFIG_ROCKCHIP_USB_UART
rk_clrsetreg(&grf->uoc0_con[0],
SIDDQ_MASK | UOC_DISABLE_MASK | COMMON_ON_N_MASK,
1 << SIDDQ_SHIFT | 1 << UOC_DISABLE_SHIFT |
1 << COMMON_ON_N_SHIFT);
rk_clrsetreg(&grf->uoc0_con[2],
SOFT_CON_SEL_MASK, 1 << SOFT_CON_SEL_SHIFT);
rk_clrsetreg(&grf->uoc0_con[3],
OPMODE_MASK | XCVRSELECT_MASK |
TERMSEL_FULLSPEED_MASK | SUSPENDN_MASK,
OPMODE_NODRIVING << OPMODE_SHIFT |
XCVRSELECT_FSTRANSC << XCVRSELECT_SHIFT |
1 << TERMSEL_FULLSPEED_SHIFT |
1 << SUSPENDN_SHIFT);
rk_clrsetreg(&grf->uoc0_con[0],
BYPASSSEL_MASK | BYPASSDMEN_MASK,
1 << BYPASSSEL_SHIFT | 1 << BYPASSDMEN_SHIFT);
#endif
ret = spl_early_init();
if (ret) {
debug("spl_early_init() failed: %d\n", ret);

View file

@ -202,13 +202,13 @@ void board_init_f(ulong dummy)
ret = uclass_get_device(UCLASS_PINCTRL, 0, &pinctrl);
if (ret) {
debug("Pinctrl init failed: %d\n", ret);
pr_err("Pinctrl init failed: %d\n", ret);
return;
}
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret) {
debug("DRAM init failed: %d\n", ret);
pr_err("DRAM init failed: %d\n", ret);
return;
}
}

View file

@ -0,0 +1,81 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2015 Google, Inc
*/
#include <common.h>
DECLARE_GLOBAL_DATA_PTR;
#if defined(CONFIG_USB_GADGET) && defined(CONFIG_USB_GADGET_DWC2_OTG)
#include <usb.h>
#include <usb/dwc2_udc.h>
static struct dwc2_plat_otg_data rv1108_otg_data = {
.rx_fifo_sz = 512,
.np_tx_fifo_sz = 16,
.tx_fifo_sz = 128,
};
int board_usb_init(int index, enum usb_init_type init)
{
const void *blob = gd->fdt_blob;
bool matched = false;
int node, phy_node;
u32 grf_phy_offset;
const char *mode;
/* find the usb_otg node */
node = fdt_node_offset_by_compatible(blob, -1, "rockchip,rk3066-usb");
while (node > 0) {
mode = fdt_getprop(blob, node, "dr_mode", NULL);
if (mode && strcmp(mode, "otg") == 0) {
matched = true;
break;
}
node = fdt_node_offset_by_compatible(blob, node,
"rockchip,rk3066-usb");
}
if (!matched) {
debug("usb_otg device not found\n");
return -ENODEV;
}
rv1108_otg_data.regs_otg = fdtdec_get_addr(blob, node, "reg");
node = fdtdec_lookup_phandle(blob, node, "phys");
if (node <= 0) {
debug("phys node not found\n");
return -ENODEV;
}
phy_node = fdt_parent_offset(blob, node);
if (phy_node <= 0) {
debug("usb phy node not found\n");
return -ENODEV;
}
rv1108_otg_data.phy_of_node = phy_node;
grf_phy_offset = fdtdec_get_addr(blob, node, "reg");
/* find the grf node */
node = fdt_node_offset_by_compatible(blob, -1,
"rockchip,rv1108-grf");
if (node <= 0) {
debug("grf node not found\n");
return -ENODEV;
}
rv1108_otg_data.regs_phy = grf_phy_offset + fdtdec_get_addr(blob, node,
"reg");
return dwc2_udc_probe(&rv1108_otg_data);
}
int board_usb_cleanup(int index, enum usb_init_type init)
{
return 0;
}
#endif

View file

@ -56,6 +56,5 @@ CONFIG_ROCKCHIP_TIMER=y
CONFIG_USB=y
CONFIG_ROCKCHIP_USB2_PHY=y
CONFIG_SPL_TINY_MEMSET=y
CONFIG_TPL_TINY_MEMSET=y
CONFIG_CMD_DHRYSTONE=y
CONFIG_ERRNO_STR=y

View file

@ -61,6 +61,11 @@ static const struct pll_div *apll_l_cfgs[] = {
[APLL_L_600_MHZ] = &apll_l_600_cfg,
};
static const struct pll_div apll_b_600_cfg = PLL_DIVISORS(600*MHz, 1, 2, 1);
static const struct pll_div *apll_b_cfgs[] = {
[APLL_B_600_MHZ] = &apll_b_600_cfg,
};
enum {
/* PLL_CON0 */
PLL_FBDIV_MASK = 0xfff,
@ -128,6 +133,24 @@ enum {
ATCLK_CORE_L_DIV_SHIFT = 0,
ATCLK_CORE_L_DIV_MASK = 0x1f << ATCLK_CORE_L_DIV_SHIFT,
/* CLKSEL_CON2 */
ACLKM_CORE_B_DIV_CON_SHIFT = 8,
ACLKM_CORE_B_DIV_CON_MASK = 0x1f << ACLKM_CORE_B_DIV_CON_SHIFT,
CLK_CORE_B_PLL_SEL_SHIFT = 6,
CLK_CORE_B_PLL_SEL_MASK = 3 << CLK_CORE_B_PLL_SEL_SHIFT,
CLK_CORE_B_PLL_SEL_ALPLL = 0x0,
CLK_CORE_B_PLL_SEL_ABPLL = 0x1,
CLK_CORE_B_PLL_SEL_DPLL = 0x10,
CLK_CORE_B_PLL_SEL_GPLL = 0x11,
CLK_CORE_B_DIV_MASK = 0x1f,
CLK_CORE_B_DIV_SHIFT = 0,
/* CLKSEL_CON3 */
PCLK_DBG_B_DIV_SHIFT = 0x8,
PCLK_DBG_B_DIV_MASK = 0x1f << PCLK_DBG_B_DIV_SHIFT,
ATCLK_CORE_B_DIV_SHIFT = 0,
ATCLK_CORE_B_DIV_MASK = 0x1f << ATCLK_CORE_B_DIV_SHIFT,
/* CLKSEL_CON14 */
PCLK_PERIHP_DIV_CON_SHIFT = 12,
PCLK_PERIHP_DIV_CON_MASK = 0x7 << PCLK_PERIHP_DIV_CON_SHIFT,
@ -395,25 +418,26 @@ static int pll_para_config(u32 freq_hz, struct pll_div *div)
return 0;
}
void rk3399_configure_cpu(struct rk3399_cru *cru,
enum apll_l_frequencies apll_l_freq)
void rk3399_configure_cpu_l(struct rk3399_cru *cru,
enum apll_l_frequencies apll_l_freq)
{
u32 aclkm_div;
u32 pclk_dbg_div;
u32 atclk_div;
/* Setup cluster L */
rkclk_set_pll(&cru->apll_l_con[0], apll_l_cfgs[apll_l_freq]);
aclkm_div = APLL_HZ / ACLKM_CORE_HZ - 1;
assert((aclkm_div + 1) * ACLKM_CORE_HZ == APLL_HZ &&
aclkm_div = LPLL_HZ / ACLKM_CORE_L_HZ - 1;
assert((aclkm_div + 1) * ACLKM_CORE_L_HZ == LPLL_HZ &&
aclkm_div < 0x1f);
pclk_dbg_div = APLL_HZ / PCLK_DBG_HZ - 1;
assert((pclk_dbg_div + 1) * PCLK_DBG_HZ == APLL_HZ &&
pclk_dbg_div = LPLL_HZ / PCLK_DBG_L_HZ - 1;
assert((pclk_dbg_div + 1) * PCLK_DBG_L_HZ == LPLL_HZ &&
pclk_dbg_div < 0x1f);
atclk_div = APLL_HZ / ATCLK_CORE_HZ - 1;
assert((atclk_div + 1) * ATCLK_CORE_HZ == APLL_HZ &&
atclk_div = LPLL_HZ / ATCLK_CORE_L_HZ - 1;
assert((atclk_div + 1) * ATCLK_CORE_L_HZ == LPLL_HZ &&
atclk_div < 0x1f);
rk_clrsetreg(&cru->clksel_con[0],
@ -428,6 +452,42 @@ void rk3399_configure_cpu(struct rk3399_cru *cru,
pclk_dbg_div << PCLK_DBG_L_DIV_SHIFT |
atclk_div << ATCLK_CORE_L_DIV_SHIFT);
}
void rk3399_configure_cpu_b(struct rk3399_cru *cru,
enum apll_b_frequencies apll_b_freq)
{
u32 aclkm_div;
u32 pclk_dbg_div;
u32 atclk_div;
/* Setup cluster B */
rkclk_set_pll(&cru->apll_b_con[0], apll_b_cfgs[apll_b_freq]);
aclkm_div = BPLL_HZ / ACLKM_CORE_B_HZ - 1;
assert((aclkm_div + 1) * ACLKM_CORE_B_HZ == BPLL_HZ &&
aclkm_div < 0x1f);
pclk_dbg_div = BPLL_HZ / PCLK_DBG_B_HZ - 1;
assert((pclk_dbg_div + 1) * PCLK_DBG_B_HZ == BPLL_HZ &&
pclk_dbg_div < 0x1f);
atclk_div = BPLL_HZ / ATCLK_CORE_B_HZ - 1;
assert((atclk_div + 1) * ATCLK_CORE_B_HZ == BPLL_HZ &&
atclk_div < 0x1f);
rk_clrsetreg(&cru->clksel_con[2],
ACLKM_CORE_B_DIV_CON_MASK | CLK_CORE_B_PLL_SEL_MASK |
CLK_CORE_B_DIV_MASK,
aclkm_div << ACLKM_CORE_B_DIV_CON_SHIFT |
CLK_CORE_B_PLL_SEL_ABPLL << CLK_CORE_B_PLL_SEL_SHIFT |
0 << CLK_CORE_B_DIV_SHIFT);
rk_clrsetreg(&cru->clksel_con[3],
PCLK_DBG_B_DIV_MASK | ATCLK_CORE_B_DIV_MASK,
pclk_dbg_div << PCLK_DBG_B_DIV_SHIFT |
atclk_div << ATCLK_CORE_B_DIV_SHIFT);
}
#define I2C_CLK_REG_MASK(bus) \
(I2C_DIV_CON_MASK << \
CLK_I2C ##bus## _DIV_CON_SHIFT | \
@ -1026,7 +1086,8 @@ static void rkclk_init(struct rk3399_cru *cru)
u32 hclk_div;
u32 pclk_div;
rk3399_configure_cpu(cru, APLL_L_600_MHZ);
rk3399_configure_cpu_l(cru, APLL_L_600_MHZ);
rk3399_configure_cpu_b(cru, APLL_B_600_MHZ);
/*
* some cru registers changed by bootrom, we'd better reset them to
* reset/default values described in TRM to avoid confusion in kernel.

View file

@ -17,6 +17,8 @@
#include <dm/lists.h>
#include <dt-bindings/clock/rv1108-cru.h>
DECLARE_GLOBAL_DATA_PTR;
enum {
VCO_MAX_HZ = 2400U * 1000000,
VCO_MIN_HZ = 600 * 1000000,
@ -35,6 +37,9 @@ enum {
#hz "Hz cannot be hit with PLL "\
"divisors on line " __stringify(__LINE__));
static const struct pll_div apll_init_cfg = PLL_DIVISORS(APLL_HZ, 1, 3, 1);
static const struct pll_div gpll_init_cfg = PLL_DIVISORS(GPLL_HZ, 2, 2, 1);
/* use integer mode */
static inline int rv1108_pll_id(enum rk_clk_id clk_id)
{
@ -57,6 +62,58 @@ static inline int rv1108_pll_id(enum rk_clk_id clk_id)
return id;
}
static int rkclk_set_pll(struct rv1108_cru *cru, enum rk_clk_id clk_id,
const struct pll_div *div)
{
int pll_id = rv1108_pll_id(clk_id);
struct rv1108_pll *pll = &cru->pll[pll_id];
/* All PLLs have same VCO and output frequency range restrictions. */
uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;
debug("PLL at %p: fb=%d, ref=%d, pst1=%d, pst2=%d, vco=%u Hz, output=%u Hz\n",
pll, div->fbdiv, div->refdiv, div->postdiv1,
div->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(&pll->con3, WORK_MODE_MASK,
WORK_MODE_SLOW << WORK_MODE_SHIFT);
/* use integer mode */
rk_setreg(&pll->con3, 1 << DSMPD_SHIFT);
/* Power down */
rk_setreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
rk_clrsetreg(&pll->con0, FBDIV_MASK, div->fbdiv << FBDIV_SHIFT);
rk_clrsetreg(&pll->con1, POSTDIV1_MASK | POSTDIV2_MASK | REFDIV_MASK,
(div->postdiv1 << POSTDIV1_SHIFT |
div->postdiv2 << POSTDIV2_SHIFT |
div->refdiv << REFDIV_SHIFT));
rk_clrsetreg(&pll->con2, FRACDIV_MASK,
(div->refdiv << REFDIV_SHIFT));
/* Power Up */
rk_clrreg(&pll->con3, 1 << GLOBAL_POWER_DOWN_SHIFT);
/* waiting for pll lock */
while (readl(&pll->con2) & (1 << LOCK_STA_SHIFT))
udelay(1);
/*
* set PLL into normal mode.
*/
rk_clrsetreg(&pll->con3, WORK_MODE_MASK,
WORK_MODE_NORMAL << WORK_MODE_SHIFT);
return 0;
}
static uint32_t rkclk_pll_get_rate(struct rv1108_cru *cru,
enum rk_clk_id clk_id)
{
@ -74,7 +131,7 @@ static uint32_t rkclk_pll_get_rate(struct rv1108_cru *cru,
fbdiv = (con0 >> FBDIV_SHIFT) & FBDIV_MASK;
postdiv1 = (con1 & POSTDIV1_MASK) >> POSTDIV1_SHIFT;
postdiv2 = (con1 & POSTDIV2_MASK) >> POSTDIV2_SHIFT;
refdiv = (con1 & REFDIV_MASK) >> REFDIV_SHIFT;
refdiv = (con1 >> REFDIV_SHIFT) & REFDIV_MASK;
freq = (24 * fbdiv / (refdiv * postdiv1 * postdiv2)) * 1000000;
} else {
freq = OSC_HZ;
@ -154,6 +211,326 @@ static ulong rv1108_saradc_set_clk(struct rv1108_cru *cru, uint hz)
return rv1108_saradc_get_clk(cru);
}
static ulong rv1108_aclk_vio1_get_clk(struct rv1108_cru *cru)
{
u32 div, val;
val = readl(&cru->clksel_con[28]);
div = bitfield_extract(val, ACLK_VIO1_CLK_DIV_SHIFT,
CLK_VIO_DIV_CON_WIDTH);
return DIV_TO_RATE(GPLL_HZ, div);
}
static ulong rv1108_aclk_vio1_set_clk(struct rv1108_cru *cru, uint hz)
{
int src_clk_div;
src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
assert(src_clk_div < 32);
rk_clrsetreg(&cru->clksel_con[28],
ACLK_VIO1_CLK_DIV_MASK | ACLK_VIO1_PLL_SEL_MASK,
(src_clk_div << ACLK_VIO1_CLK_DIV_SHIFT) |
(VIO_PLL_SEL_GPLL << ACLK_VIO1_PLL_SEL_SHIFT));
return rv1108_aclk_vio1_get_clk(cru);
}
static ulong rv1108_aclk_vio0_get_clk(struct rv1108_cru *cru)
{
u32 div, val;
val = readl(&cru->clksel_con[28]);
div = bitfield_extract(val, ACLK_VIO0_CLK_DIV_SHIFT,
CLK_VIO_DIV_CON_WIDTH);
return DIV_TO_RATE(GPLL_HZ, div);
}
static ulong rv1108_aclk_vio0_set_clk(struct rv1108_cru *cru, uint hz)
{
int src_clk_div;
src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
assert(src_clk_div < 32);
rk_clrsetreg(&cru->clksel_con[28],
ACLK_VIO0_CLK_DIV_MASK | ACLK_VIO0_PLL_SEL_MASK,
(src_clk_div << ACLK_VIO0_CLK_DIV_SHIFT) |
(VIO_PLL_SEL_GPLL << ACLK_VIO0_PLL_SEL_SHIFT));
/*HCLK_VIO default div = 4*/
rk_clrsetreg(&cru->clksel_con[29],
HCLK_VIO_CLK_DIV_MASK,
3 << HCLK_VIO_CLK_DIV_SHIFT);
/*PCLK_VIO default div = 4*/
rk_clrsetreg(&cru->clksel_con[29],
PCLK_VIO_CLK_DIV_MASK,
3 << PCLK_VIO_CLK_DIV_SHIFT);
return rv1108_aclk_vio0_get_clk(cru);
}
static ulong rv1108_dclk_vop_get_clk(struct rv1108_cru *cru)
{
u32 div, val;
val = readl(&cru->clksel_con[32]);
div = bitfield_extract(val, DCLK_VOP_CLK_DIV_SHIFT,
DCLK_VOP_DIV_CON_WIDTH);
return DIV_TO_RATE(GPLL_HZ, div);
}
static ulong rv1108_dclk_vop_set_clk(struct rv1108_cru *cru, uint hz)
{
int src_clk_div;
src_clk_div = DIV_ROUND_UP(GPLL_HZ, hz) - 1;
assert(src_clk_div < 64);
rk_clrsetreg(&cru->clksel_con[32],
DCLK_VOP_CLK_DIV_MASK | DCLK_VOP_PLL_SEL_MASK |
DCLK_VOP_SEL_SHIFT,
(src_clk_div << DCLK_VOP_CLK_DIV_SHIFT) |
(DCLK_VOP_PLL_SEL_GPLL << DCLK_VOP_PLL_SEL_SHIFT) |
(DCLK_VOP_SEL_PLL << DCLK_VOP_SEL_SHIFT));
return rv1108_dclk_vop_get_clk(cru);
}
static ulong rv1108_aclk_bus_get_clk(struct rv1108_cru *cru)
{
u32 div, val;
ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
val = readl(&cru->clksel_con[2]);
div = bitfield_extract(val, ACLK_BUS_DIV_CON_SHIFT,
ACLK_BUS_DIV_CON_WIDTH);
return DIV_TO_RATE(parent_rate, div);
}
static ulong rv1108_aclk_bus_set_clk(struct rv1108_cru *cru, uint hz)
{
int src_clk_div;
ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
assert(src_clk_div < 32);
rk_clrsetreg(&cru->clksel_con[2],
ACLK_BUS_DIV_CON_MASK | ACLK_BUS_PLL_SEL_MASK,
(src_clk_div << ACLK_BUS_DIV_CON_SHIFT) |
(ACLK_BUS_PLL_SEL_GPLL << ACLK_BUS_PLL_SEL_SHIFT));
return rv1108_aclk_bus_get_clk(cru);
}
static ulong rv1108_aclk_peri_get_clk(struct rv1108_cru *cru)
{
u32 div, val;
ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
val = readl(&cru->clksel_con[23]);
div = bitfield_extract(val, ACLK_PERI_DIV_CON_SHIFT,
PERI_DIV_CON_WIDTH);
return DIV_TO_RATE(parent_rate, div);
}
static ulong rv1108_hclk_peri_get_clk(struct rv1108_cru *cru)
{
u32 div, val;
ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
val = readl(&cru->clksel_con[23]);
div = bitfield_extract(val, HCLK_PERI_DIV_CON_SHIFT,
PERI_DIV_CON_WIDTH);
return DIV_TO_RATE(parent_rate, div);
}
static ulong rv1108_pclk_peri_get_clk(struct rv1108_cru *cru)
{
u32 div, val;
ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
val = readl(&cru->clksel_con[23]);
div = bitfield_extract(val, PCLK_PERI_DIV_CON_SHIFT,
PERI_DIV_CON_WIDTH);
return DIV_TO_RATE(parent_rate, div);
}
static ulong rv1108_aclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
{
int src_clk_div;
ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
assert(src_clk_div < 32);
rk_clrsetreg(&cru->clksel_con[23],
ACLK_PERI_DIV_CON_MASK | ACLK_PERI_PLL_SEL_MASK,
(src_clk_div << ACLK_PERI_DIV_CON_SHIFT) |
(ACLK_PERI_PLL_SEL_GPLL << ACLK_PERI_PLL_SEL_SHIFT));
return rv1108_aclk_peri_get_clk(cru);
}
static ulong rv1108_hclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
{
int src_clk_div;
ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
assert(src_clk_div < 32);
rk_clrsetreg(&cru->clksel_con[23],
HCLK_PERI_DIV_CON_MASK,
(src_clk_div << HCLK_PERI_DIV_CON_SHIFT));
return rv1108_hclk_peri_get_clk(cru);
}
static ulong rv1108_pclk_peri_set_clk(struct rv1108_cru *cru, uint hz)
{
int src_clk_div;
ulong parent_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
src_clk_div = DIV_ROUND_UP(parent_rate, hz) - 1;
assert(src_clk_div < 32);
rk_clrsetreg(&cru->clksel_con[23],
PCLK_PERI_DIV_CON_MASK,
(src_clk_div << PCLK_PERI_DIV_CON_SHIFT));
return rv1108_pclk_peri_get_clk(cru);
}
static ulong rv1108_i2c_get_clk(struct rv1108_cru *cru, ulong clk_id)
{
u32 div, con;
switch (clk_id) {
case SCLK_I2C0_PMU:
con = readl(&cru->clksel_con[19]);
div = bitfield_extract(con, CLK_I2C0_DIV_CON_SHIFT,
I2C_DIV_CON_WIDTH);
break;
case SCLK_I2C1:
con = readl(&cru->clksel_con[19]);
div = bitfield_extract(con, CLK_I2C1_DIV_CON_SHIFT,
I2C_DIV_CON_WIDTH);
break;
case SCLK_I2C2:
con = readl(&cru->clksel_con[20]);
div = bitfield_extract(con, CLK_I2C2_DIV_CON_SHIFT,
I2C_DIV_CON_WIDTH);
break;
case SCLK_I2C3:
con = readl(&cru->clksel_con[20]);
div = bitfield_extract(con, CLK_I2C3_DIV_CON_SHIFT,
I2C_DIV_CON_WIDTH);
break;
default:
printf("do not support this i2c bus\n");
return -EINVAL;
}
return DIV_TO_RATE(GPLL_HZ, div);
}
static ulong rv1108_i2c_set_clk(struct rv1108_cru *cru, ulong clk_id, uint hz)
{
int src_clk_div;
/* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
src_clk_div = GPLL_HZ / hz;
assert(src_clk_div - 1 <= 127);
switch (clk_id) {
case SCLK_I2C0_PMU:
rk_clrsetreg(&cru->clksel_con[19],
CLK_I2C0_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
(src_clk_div << CLK_I2C0_DIV_CON_SHIFT) |
(CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
break;
case SCLK_I2C1:
rk_clrsetreg(&cru->clksel_con[19],
CLK_I2C1_DIV_CON_MASK | CLK_I2C1_PLL_SEL_MASK,
(src_clk_div << CLK_I2C1_DIV_CON_SHIFT) |
(CLK_I2C1_PLL_SEL_GPLL << CLK_I2C1_PLL_SEL_SHIFT));
break;
case SCLK_I2C2:
rk_clrsetreg(&cru->clksel_con[20],
CLK_I2C2_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
(src_clk_div << CLK_I2C2_DIV_CON_SHIFT) |
(CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
break;
case SCLK_I2C3:
rk_clrsetreg(&cru->clksel_con[20],
CLK_I2C3_DIV_CON_MASK | CLK_I2C3_PLL_SEL_MASK,
(src_clk_div << CLK_I2C3_DIV_CON_SHIFT) |
(CLK_I2C3_PLL_SEL_GPLL << CLK_I2C3_PLL_SEL_SHIFT));
break;
default:
printf("do not support this i2c bus\n");
return -EINVAL;
}
return rv1108_i2c_get_clk(cru, clk_id);
}
static ulong rv1108_mmc_get_clk(struct rv1108_cru *cru)
{
u32 div, con;
ulong mmc_clk;
con = readl(&cru->clksel_con[26]);
div = bitfield_extract(con, EMMC_CLK_DIV_SHIFT, 8);
con = readl(&cru->clksel_con[25]);
if ((con & EMMC_PLL_SEL_MASK) >> EMMC_PLL_SEL_SHIFT == EMMC_PLL_SEL_OSC)
mmc_clk = DIV_TO_RATE(OSC_HZ, div) / 2;
else
mmc_clk = DIV_TO_RATE(GPLL_HZ, div) / 2;
debug("%s div %d get_clk %ld\n", __func__, div, mmc_clk);
return mmc_clk;
}
static ulong rv1108_mmc_set_clk(struct rv1108_cru *cru, ulong rate)
{
int div;
u32 pll_rate;
div = DIV_ROUND_UP(rkclk_pll_get_rate(cru, CLK_GENERAL), rate);
if (div < 127) {
debug("%s source gpll\n", __func__);
rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
(EMMC_PLL_SEL_GPLL << EMMC_PLL_SEL_SHIFT));
pll_rate = rkclk_pll_get_rate(cru, CLK_GENERAL);
} else {
debug("%s source 24m\n", __func__);
rk_clrsetreg(&cru->clksel_con[25], EMMC_PLL_SEL_MASK,
(EMMC_PLL_SEL_OSC << EMMC_PLL_SEL_SHIFT));
pll_rate = OSC_HZ;
}
div = DIV_ROUND_UP(pll_rate / 2, rate);
rk_clrsetreg(&cru->clksel_con[26], EMMC_CLK_DIV_MASK,
((div - 1) << EMMC_CLK_DIV_SHIFT));
debug("%s set_rate %ld div %d\n", __func__, rate, div);
return DIV_TO_RATE(pll_rate, div);
}
static ulong rv1108_clk_get_rate(struct clk *clk)
{
struct rv1108_clk_priv *priv = dev_get_priv(clk->dev);
@ -163,6 +540,29 @@ static ulong rv1108_clk_get_rate(struct clk *clk)
return rkclk_pll_get_rate(priv->cru, clk->id);
case SCLK_SARADC:
return rv1108_saradc_get_clk(priv->cru);
case ACLK_VIO0:
return rv1108_aclk_vio0_get_clk(priv->cru);
case ACLK_VIO1:
return rv1108_aclk_vio1_get_clk(priv->cru);
case DCLK_VOP:
return rv1108_dclk_vop_get_clk(priv->cru);
case ACLK_PRE:
return rv1108_aclk_bus_get_clk(priv->cru);
case ACLK_PERI:
return rv1108_aclk_peri_get_clk(priv->cru);
case HCLK_PERI:
return rv1108_hclk_peri_get_clk(priv->cru);
case PCLK_PERI:
return rv1108_pclk_peri_get_clk(priv->cru);
case SCLK_I2C0_PMU:
case SCLK_I2C1:
case SCLK_I2C2:
case SCLK_I2C3:
return rv1108_i2c_get_clk(priv->cru, clk->id);
case HCLK_EMMC:
case SCLK_EMMC:
case SCLK_EMMC_SAMPLE:
return rv1108_mmc_get_clk(priv->cru);
default:
return -ENOENT;
}
@ -183,6 +583,37 @@ static ulong rv1108_clk_set_rate(struct clk *clk, ulong rate)
case SCLK_SARADC:
new_rate = rv1108_saradc_set_clk(priv->cru, rate);
break;
case ACLK_VIO0:
new_rate = rv1108_aclk_vio0_set_clk(priv->cru, rate);
break;
case ACLK_VIO1:
new_rate = rv1108_aclk_vio1_set_clk(priv->cru, rate);
break;
case DCLK_VOP:
new_rate = rv1108_dclk_vop_set_clk(priv->cru, rate);
break;
case ACLK_PRE:
new_rate = rv1108_aclk_bus_set_clk(priv->cru, rate);
break;
case ACLK_PERI:
new_rate = rv1108_aclk_peri_set_clk(priv->cru, rate);
break;
case HCLK_PERI:
new_rate = rv1108_hclk_peri_set_clk(priv->cru, rate);
break;
case PCLK_PERI:
new_rate = rv1108_pclk_peri_set_clk(priv->cru, rate);
break;
case SCLK_I2C0_PMU:
case SCLK_I2C1:
case SCLK_I2C2:
case SCLK_I2C3:
new_rate = rv1108_i2c_set_clk(priv->cru, clk->id, rate);
break;
case HCLK_EMMC:
case SCLK_EMMC:
new_rate = rv1108_mmc_set_clk(priv->cru, rate);
break;
default:
return -ENOENT;
}
@ -197,14 +628,34 @@ static const struct clk_ops rv1108_clk_ops = {
static void rkclk_init(struct rv1108_cru *cru)
{
unsigned int apll = rkclk_pll_get_rate(cru, CLK_ARM);
unsigned int dpll = rkclk_pll_get_rate(cru, CLK_DDR);
unsigned int gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
unsigned int apll, dpll, gpll;
unsigned int aclk_bus, aclk_peri, hclk_peri, pclk_peri;
aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ / 2);
aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ / 2);
hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ / 2);
pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ / 2);
rv1108_aclk_vio0_set_clk(cru, 297000000);
rv1108_aclk_vio1_set_clk(cru, 297000000);
/* configure apll */
rkclk_set_pll(cru, CLK_ARM, &apll_init_cfg);
rkclk_set_pll(cru, CLK_GENERAL, &gpll_init_cfg);
aclk_bus = rv1108_aclk_bus_set_clk(cru, ACLK_BUS_HZ);
aclk_peri = rv1108_aclk_peri_set_clk(cru, ACLK_PERI_HZ);
hclk_peri = rv1108_hclk_peri_set_clk(cru, HCLK_PERI_HZ);
pclk_peri = rv1108_pclk_peri_set_clk(cru, PCLK_PERI_HZ);
apll = rkclk_pll_get_rate(cru, CLK_ARM);
dpll = rkclk_pll_get_rate(cru, CLK_DDR);
gpll = rkclk_pll_get_rate(cru, CLK_GENERAL);
rk_clrsetreg(&cru->clksel_con[0], CORE_CLK_DIV_MASK,
0 << MAC_CLK_DIV_SHIFT);
printf("APLL: %d DPLL:%d GPLL:%d\n", apll, dpll, gpll);
printf("ACLK_BUS: %d ACLK_PERI:%d HCLK_PERI:%d PCLK_PERI:%d\n",
aclk_bus, aclk_peri, hclk_peri, pclk_peri);
}
static int rv1108_clk_ofdata_to_platdata(struct udevice *dev)
@ -228,8 +679,9 @@ static int rv1108_clk_probe(struct udevice *dev)
static int rv1108_clk_bind(struct udevice *dev)
{
int ret;
struct udevice *sys_child;
struct udevice *sys_child, *sf_child;
struct sysreset_reg *priv;
struct softreset_reg *sf_priv;
/* The reset driver does not have a device node, so bind it here */
ret = device_bind_driver(dev, "rockchip_sysreset", "sysreset",
@ -251,6 +703,17 @@ static int rv1108_clk_bind(struct udevice *dev)
if (ret)
debug("Warning: software reset driver bind faile\n");
#endif
ret = device_bind_driver_to_node(dev, "rockchip_reset", "reset",
dev_ofnode(dev), &sf_child);
if (ret) {
debug("Warning: No rockchip reset driver: ret=%d\n", ret);
} else {
sf_priv = malloc(sizeof(struct softreset_reg));
sf_priv->sf_reset_offset = offsetof(struct rv1108_cru,
softrst_con[0]);
sf_priv->sf_reset_num = 13;
sf_child->priv = sf_priv;
}
return 0;
}
@ -265,8 +728,8 @@ U_BOOT_DRIVER(clk_rv1108) = {
.id = UCLASS_CLK,
.of_match = rv1108_clk_ids,
.priv_auto_alloc_size = sizeof(struct rv1108_clk_priv),
.ofdata_to_platdata = rv1108_clk_ofdata_to_platdata,
.ops = &rv1108_clk_ops,
.bind = rv1108_clk_bind,
.ofdata_to_platdata = rv1108_clk_ofdata_to_platdata,
.probe = rv1108_clk_probe,
};

View file

@ -60,6 +60,16 @@ config RTC_ISL1208
This driver supports reading and writing the RTC/calendar and detects
total power failures.
config RTC_RV3029
bool "Enable RV3029 driver"
depends on DM_RTC
help
The MicroCrystal RV3029 is a I2C Real Time Clock (RTC) with 8-byte
battery-backed SRAM.
This driver supports reading and writing the RTC/calendar and the
battery-baced SRAM section.
config RTC_RX8010SJ
bool "Enable RX8010SJ driver"
depends on DM_RTC

View file

@ -1,189 +1,495 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2010
* Heiko Schocher, DENX Software Engineering, hs@denx.de
* (C) Copyright 2018 Theobroma Systems Design und Consulting GmbH
*
* Based on a the Linux rtc-rv3029c2.c driver written by:
* Gregory Hermant <gregory.hermant@calao-systems.com>
* Michael Buesch <m@bues.ch>
*/
#include <common.h>
#include <command.h>
#include <dm.h>
#include <i2c.h>
#include <rtc.h>
#define RTC_RV3029_CTRL1 0x00
#define RTC_RV3029_CTRL1_EERE (1 << 3)
#define RTC_RV3029_PAGE_LEN 7
#define RTC_RV3029_CTRL_STATUS 0x03
#define RTC_RV3029_CTRLS_EEBUSY (1 << 7)
/* control section */
#define RV3029_ONOFF_CTRL 0x00
#define RV3029_ONOFF_CTRL_WE BIT(0)
#define RV3029_ONOFF_CTRL_TE BIT(1)
#define RV3029_ONOFF_CTRL_TAR BIT(2)
#define RV3029_ONOFF_CTRL_EERE BIT(3)
#define RV3029_ONOFF_CTRL_SRON BIT(4)
#define RV3029_ONOFF_CTRL_TD0 BIT(5)
#define RV3029_ONOFF_CTRL_TD1 BIT(6)
#define RV3029_ONOFF_CTRL_CLKINT BIT(7)
#define RV3029_IRQ_CTRL 0x01
#define RV3029_IRQ_CTRL_AIE BIT(0)
#define RV3029_IRQ_CTRL_TIE BIT(1)
#define RV3029_IRQ_CTRL_V1IE BIT(2)
#define RV3029_IRQ_CTRL_V2IE BIT(3)
#define RV3029_IRQ_CTRL_SRIE BIT(4)
#define RV3029_IRQ_FLAGS 0x02
#define RV3029_IRQ_FLAGS_AF BIT(0)
#define RV3029_IRQ_FLAGS_TF BIT(1)
#define RV3029_IRQ_FLAGS_V1IF BIT(2)
#define RV3029_IRQ_FLAGS_V2IF BIT(3)
#define RV3029_IRQ_FLAGS_SRF BIT(4)
#define RV3029_STATUS 0x03
#define RV3029_STATUS_VLOW1 BIT(2)
#define RV3029_STATUS_VLOW2 BIT(3)
#define RV3029_STATUS_SR BIT(4)
#define RV3029_STATUS_PON BIT(5)
#define RV3029_STATUS_EEBUSY BIT(7)
#define RV3029_RST_CTRL 0x04
#define RV3029_RST_CTRL_SYSR BIT(4)
#define RV3029_CONTROL_SECTION_LEN 0x05
#define RTC_RV3029_CTRL_RESET 0x04
#define RTC_RV3029_CTRL_SYS_R (1 << 4)
/* watch section */
#define RV3029_W_SEC 0x08
#define RV3029_W_MINUTES 0x09
#define RV3029_W_HOURS 0x0A
#define RV3029_REG_HR_12_24 BIT(6) /* 24h/12h mode */
#define RV3029_REG_HR_PM BIT(5) /* PM/AM bit in 12h mode */
#define RV3029_W_DATE 0x0B
#define RV3029_W_DAYS 0x0C
#define RV3029_W_MONTHS 0x0D
#define RV3029_W_YEARS 0x0E
#define RTC_RV3029_CLOCK_PAGE 0x08
#define RTC_RV3029_PAGE_LEN 7
/* eeprom control section */
#define RV3029_CONTROL_E2P_EECTRL 0x30
#define RV3029_TRICKLE_1K BIT(4) /* 1.5K resistance */
#define RV3029_TRICKLE_5K BIT(5) /* 5K resistance */
#define RV3029_TRICKLE_20K BIT(6) /* 20K resistance */
#define RV3029_TRICKLE_80K BIT(7) /* 80K resistance */
#define RV3029_TRICKLE_MASK (RV3029_TRICKLE_1K |\
RV3029_TRICKLE_5K |\
RV3029_TRICKLE_20K |\
RV3029_TRICKLE_80K)
#define RV3029_TRICKLE_SHIFT 4
#define RV3029C2_W_SECONDS 0x00
#define RV3029C2_W_MINUTES 0x01
#define RV3029C2_W_HOURS 0x02
#define RV3029C2_W_DATE 0x03
#define RV3029C2_W_DAYS 0x04
#define RV3029C2_W_MONTHS 0x05
#define RV3029C2_W_YEARS 0x06
#define RV3029C2_REG_HR_12_24 (1 << 6) /* 24h/12h mode */
#define RV3029C2_REG_HR_PM (1 << 5) /* PM/AM bit in 12h mode */
#define RTC_RV3029_EEPROM_CTRL 0x30
#define RTC_RV3029_TRICKLE_1K (1 << 4)
#define RTC_RV3029_TRICKLE_5K (1 << 5)
#define RTC_RV3029_TRICKLE_20K (1 << 6)
#define RTC_RV3029_TRICKLE_80K (1 << 7)
int rtc_get( struct rtc_time *tmp )
static int rv3029_rtc_get(struct udevice *dev, struct rtc_time *tm)
{
int ret;
unsigned char buf[RTC_RV3029_PAGE_LEN];
u8 regs[RTC_RV3029_PAGE_LEN];
int ret;
ret = i2c_read(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CLOCK_PAGE, 1, buf, \
RTC_RV3029_PAGE_LEN);
if (ret) {
ret = dm_i2c_read(dev, RV3029_W_SEC, regs, sizeof(regs));
if (ret < 0) {
printf("%s: error reading RTC: %x\n", __func__, ret);
return -1;
return -EIO;
}
tmp->tm_sec = bcd2bin( buf[RV3029C2_W_SECONDS] & 0x7f);
tmp->tm_min = bcd2bin( buf[RV3029C2_W_MINUTES] & 0x7f);
if (buf[RV3029C2_W_HOURS] & RV3029C2_REG_HR_12_24) {
/* 12h format */
tmp->tm_hour = bcd2bin(buf[RV3029C2_W_HOURS] & 0x1f);
if (buf[RV3029C2_W_HOURS] & RV3029C2_REG_HR_PM)
/* PM flag set */
tmp->tm_hour += 12;
} else
tmp->tm_hour = bcd2bin(buf[RV3029C2_W_HOURS] & 0x3f);
tmp->tm_mday = bcd2bin( buf[RV3029C2_W_DATE] & 0x3F );
tmp->tm_mon = bcd2bin( buf[RV3029C2_W_MONTHS] & 0x1F );
tmp->tm_wday = bcd2bin( buf[RV3029C2_W_DAYS] & 0x07 );
tm->tm_sec = bcd2bin(regs[RV3029_W_SEC - RV3029_W_SEC]);
tm->tm_min = bcd2bin(regs[RV3029_W_MINUTES - RV3029_W_SEC]);
/* HR field has a more complex interpretation */
{
const u8 _hr = regs[RV3029_W_HOURS - RV3029_W_SEC];
if (_hr & RV3029_REG_HR_12_24) {
/* 12h format */
tm->tm_hour = bcd2bin(_hr & 0x1f);
if (_hr & RV3029_REG_HR_PM) /* PM flag set */
tm->tm_hour += 12;
} else {
/* 24h format */
tm->tm_hour = bcd2bin(_hr & 0x3f);
}
}
tm->tm_mday = bcd2bin(regs[RV3029_W_DATE - RV3029_W_SEC]);
tm->tm_mon = bcd2bin(regs[RV3029_W_MONTHS - RV3029_W_SEC]) - 1;
/* RTC supports only years > 1999 */
tmp->tm_year = bcd2bin( buf[RV3029C2_W_YEARS]) + 2000;
tmp->tm_yday = 0;
tmp->tm_isdst = 0;
tm->tm_year = bcd2bin(regs[RV3029_W_YEARS - RV3029_W_SEC]) + 2000;
tm->tm_wday = bcd2bin(regs[RV3029_W_DAYS - RV3029_W_SEC]) - 1;
debug( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec );
tm->tm_yday = 0;
tm->tm_isdst = 0;
debug("%s: %4d-%02d-%02d (wday=%d) %2d:%02d:%02d\n",
__func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
return 0;
}
int rtc_set( struct rtc_time *tmp )
static int rv3029_rtc_set(struct udevice *dev, const struct rtc_time *tm)
{
int ret;
unsigned char buf[RTC_RV3029_PAGE_LEN];
u8 regs[RTC_RV3029_PAGE_LEN];
debug( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n",
tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday,
tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
debug("%s: %4d-%02d-%02d (wday=%d( %2d:%02d:%02d\n",
__func__, tm->tm_year, tm->tm_mon, tm->tm_mday,
tm->tm_wday, tm->tm_hour, tm->tm_min, tm->tm_sec);
if (tmp->tm_year < 2000) {
printf("RTC: year %d < 2000 not possible\n", tmp->tm_year);
return -1;
if (tm->tm_year < 2000) {
printf("%s: year %d (before 2000) not supported\n",
__func__, tm->tm_year);
return -EINVAL;
}
buf[RV3029C2_W_SECONDS] = bin2bcd(tmp->tm_sec);
buf[RV3029C2_W_MINUTES] = bin2bcd(tmp->tm_min);
buf[RV3029C2_W_HOURS] = bin2bcd(tmp->tm_hour);
/* set 24h format */
buf[RV3029C2_W_HOURS] &= ~RV3029C2_REG_HR_12_24;
buf[RV3029C2_W_DATE] = bin2bcd(tmp->tm_mday);
buf[RV3029C2_W_DAYS] = bin2bcd(tmp->tm_wday);
buf[RV3029C2_W_MONTHS] = bin2bcd(tmp->tm_mon);
tmp->tm_year -= 2000;
buf[RV3029C2_W_YEARS] = bin2bcd(tmp->tm_year);
ret = i2c_write(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CLOCK_PAGE, 1,
buf, RTC_RV3029_PAGE_LEN);
/* give the RTC some time to update */
udelay(1000);
return ret;
regs[RV3029_W_SEC - RV3029_W_SEC] = bin2bcd(tm->tm_sec);
regs[RV3029_W_MINUTES - RV3029_W_SEC] = bin2bcd(tm->tm_min);
regs[RV3029_W_HOURS - RV3029_W_SEC] = bin2bcd(tm->tm_hour);
regs[RV3029_W_DATE - RV3029_W_SEC] = bin2bcd(tm->tm_mday);
regs[RV3029_W_MONTHS - RV3029_W_SEC] = bin2bcd(tm->tm_mon + 1);
regs[RV3029_W_DAYS - RV3029_W_SEC] = bin2bcd(tm->tm_wday + 1) & 0x7;
regs[RV3029_W_YEARS - RV3029_W_SEC] = bin2bcd(tm->tm_year - 2000);
return dm_i2c_write(dev, RV3029_W_SEC, regs, sizeof(regs));
}
/* sets EERE-Bit (automatic EEPROM refresh) */
static void set_eere_bit(int state)
static int rv3029_rtc_reset(struct udevice *dev)
{
unsigned char reg_ctrl1;
u8 ctrl = RV3029_RST_CTRL_SYSR;
unsigned long start;
const unsigned long timeout_ms = 10000;
int ret;
(void)i2c_read(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CTRL1, 1,
&reg_ctrl1, 1);
/* trigger the system-reset */
ret = dm_i2c_write(dev, RV3029_RST_CTRL, &ctrl, 1);
if (ret < 0)
return -EIO;
if (state)
reg_ctrl1 |= RTC_RV3029_CTRL1_EERE;
else
reg_ctrl1 &= (~RTC_RV3029_CTRL1_EERE);
/* wait for the system-reset to complete */
start = get_timer(0);
do {
if (get_timer(start) > timeout_ms)
return -ETIMEDOUT;
(void)i2c_write(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CTRL1, 1,
&reg_ctrl1, 1);
ret = dm_i2c_read(dev, RV3029_RST_CTRL, &ctrl, 1);
if (ret < 0)
return -EIO;
} while (ctrl & RV3029_RST_CTRL_SYSR);
return 0;
}
/* waits until EEPROM page is no longer busy (times out after 10ms*loops) */
static int wait_eebusy(int loops)
static int rv3029_rtc_read8(struct udevice *dev, unsigned int reg)
{
int i;
unsigned char ctrl_status;
u8 data;
int ret;
for (i = 0; i < loops; i++) {
(void)i2c_read(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CTRL_STATUS,
1, &ctrl_status, 1);
ret = dm_i2c_read(dev, reg, &data, sizeof(data));
return ret < 0 ? ret : data;
}
if ((ctrl_status & RTC_RV3029_CTRLS_EEBUSY) == 0)
static int rv3029_rtc_write8(struct udevice *dev, unsigned int reg, int val)
{
u8 data = val;
return dm_i2c_write(dev, reg, &data, 1);
}
#if defined(OF_CONTROL)
static int rv3029_get_sr(struct udevice *dev, u8 *buf)
{
int ret = dm_i2c_read(dev, RV3029_STATUS, buf, 1);
if (ret < 0)
return -EIO;
dev_dbg(dev, "status = 0x%.2x (%d)\n", buf[0], buf[0]);
return 0;
}
static int rv3029_set_sr(struct udevice *dev, u8 val)
{
int ret;
ret = dm_i2c_read(dev, RV3029_STATUS, &val, 1);
if (ret < 0)
return -EIO;
dev_dbg(dev, "status = 0x%.2x (%d)\n", val, val);
return 0;
}
static int rv3029_eeprom_busywait(struct udevice *dev)
{
int i, ret;
u8 sr;
for (i = 100; i > 0; i--) {
ret = rv3029_get_sr(dev, &sr);
if (ret < 0)
break;
if (!(sr & RV3029_STATUS_EEBUSY))
break;
udelay(10000);
}
return i;
}
void rtc_reset (void)
{
unsigned char buf[RTC_RV3029_PAGE_LEN];
buf[0] = RTC_RV3029_CTRL_SYS_R;
(void)i2c_write(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_CTRL_RESET, 1,
buf, 1);
#if defined(CONFIG_SYS_RV3029_TCR)
/*
* because EEPROM_CTRL register is in EEPROM page it is necessary to
* disable automatic EEPROM refresh and check if EEPROM is busy
* before EEPORM_CTRL register may be accessed
*/
set_eere_bit(0);
wait_eebusy(100);
/* read current trickle charger setting */
(void)i2c_read(CONFIG_SYS_I2C_RTC_ADDR, RTC_RV3029_EEPROM_CTRL,
1, buf, 1);
/* enable automatic EEPROM refresh again */
set_eere_bit(1);
/*
* to minimize EEPROM access write trickle charger setting only if it
* differs from current value
*/
if ((buf[0] & 0xF0) != CONFIG_SYS_RV3029_TCR) {
buf[0] = (buf[0] & 0x0F) | CONFIG_SYS_RV3029_TCR;
/*
* write trickle charger setting (disable autom. EEPROM
* refresh and wait until EEPROM is idle)
*/
set_eere_bit(0);
wait_eebusy(100);
(void)i2c_write(CONFIG_SYS_I2C_RTC_ADDR,
RTC_RV3029_EEPROM_CTRL, 1, buf, 1);
/*
* it is necessary to wait 10ms before EEBUSY-Bit may be read
* (this is not documented in the data sheet yet, but the
* manufacturer recommends it)
*/
udelay(10000);
/* wait until EEPROM write access is finished */
wait_eebusy(100);
set_eere_bit(1);
if (i <= 0) {
dev_err(dev, "EEPROM busy wait timeout.\n");
return -ETIMEDOUT;
}
#endif
return ret;
}
static int rv3029_update_bits(struct udevice *dev, u8 reg, u8 mask, u8 set)
{
u8 buf;
int ret;
ret = dm_i2c_read(dev, reg, &buf, 1);
if (ret < 0)
return ret;
if ((buf & mask) == (set && mask))
return 0;
buf = (buf & ~mask) | (set & mask);
ret = dm_i2c_read(dev, reg, &buf, 1);
if (ret < 0)
return ret;
return 0;
}
static int rv3029_eeprom_exit(struct udevice *dev)
{
/* Re-enable eeprom refresh */
return rv3029_update_bits(dev, RV3029_ONOFF_CTRL,
RV3029_ONOFF_CTRL_EERE,
RV3029_ONOFF_CTRL_EERE);
}
static int rv3029_eeprom_enter(struct udevice *dev)
{
int ret;
u8 sr;
/* Check whether we are in the allowed voltage range. */
ret = rv3029_get_sr(dev, &sr);
if (ret < 0)
return ret;
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
/* We clear the bits and retry once just in case
* we had a brown out in early startup.
*/
sr &= ~RV3029_STATUS_VLOW1;
sr &= ~RV3029_STATUS_VLOW2;
ret = rv3029_set_sr(dev, sr);
if (ret < 0)
return ret;
udelay(10000);
ret = rv3029_get_sr(dev, &sr);
if (ret < 0)
return ret;
if (sr & (RV3029_STATUS_VLOW1 | RV3029_STATUS_VLOW2)) {
dev_err(dev, "Supply voltage is too low to safely access the EEPROM.\n");
return -ENODEV;
}
}
/* Disable eeprom refresh. */
ret = rv3029_update_bits(dev,
RV3029_ONOFF_CTRL, RV3029_ONOFF_CTRL_EERE, 0);
if (ret < 0)
return ret;
/* Wait for any previous eeprom accesses to finish. */
ret = rv3029_eeprom_busywait(dev);
if (ret < 0)
rv3029_eeprom_exit(dev);
return ret;
}
static int rv3029_eeprom_read(struct udevice *dev, u8 reg,
u8 buf[], size_t len)
{
int ret, err;
err = rv3029_eeprom_enter(dev);
if (err < 0)
return err;
ret = dm_i2c_read(dev, reg, buf, len);
err = rv3029_eeprom_exit(dev);
if (err < 0)
return err;
return ret;
}
static int rv3029_eeprom_write(struct udevice *dev, u8 reg,
u8 const buf[], size_t len)
{
int ret;
size_t i;
u8 tmp;
ret = rv3029_eeprom_enter(dev);
if (ret < 0)
return ret;
for (i = 0; i < len; i++, reg++) {
ret = dm_i2c_read(dev, reg, &tmp, 1);
if (ret < 0)
break;
if (tmp != buf[i]) {
ret = dm_i2c_write(dev, reg, &buf[i], 1);
if (ret < 0)
break;
}
ret = rv3029_eeprom_busywait(dev);
if (ret < 0)
break;
}
ret = rv3029_eeprom_exit(dev);
if (ret < 0)
return ret;
return 0;
}
static int rv3029_eeprom_update_bits(struct udevice *dev,
u8 reg, u8 mask, u8 set)
{
u8 buf;
int ret;
ret = rv3029_eeprom_read(dev, reg, &buf, 1);
if (ret < 0)
return ret;
/*
* If the EEPROM already reads the correct bitpattern, we don't need
* to update it.
*/
if ((buf & mask) == (set & mask))
return 0;
buf = (buf & ~mask) | (set & mask);
ret = rv3029_eeprom_write(dev, reg, &buf, 1);
if (ret < 0)
return ret;
return 0;
}
static void rv3029_trickle_config(struct udevice *dev)
{
static const struct rv3029_trickle_tab_elem {
u32 r; /* resistance in ohms */
u8 conf; /* trickle config bits */
} rv3029_trickle_tab[] = {
{
.r = 1076,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
}, {
.r = 1091,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
RV3029_TRICKLE_20K,
}, {
.r = 1137,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K |
RV3029_TRICKLE_80K,
}, {
.r = 1154,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_5K,
}, {
.r = 1371,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_20K |
RV3029_TRICKLE_80K,
}, {
.r = 1395,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_20K,
}, {
.r = 1472,
.conf = RV3029_TRICKLE_1K | RV3029_TRICKLE_80K,
}, {
.r = 1500,
.conf = RV3029_TRICKLE_1K,
}, {
.r = 3810,
.conf = RV3029_TRICKLE_5K | RV3029_TRICKLE_20K |
RV3029_TRICKLE_80K,
}, {
.r = 4000,
.conf = RV3029_TRICKLE_5K | RV3029_TRICKLE_20K,
}, {
.r = 4706,
.conf = RV3029_TRICKLE_5K | RV3029_TRICKLE_80K,
}, {
.r = 5000,
.conf = RV3029_TRICKLE_5K,
}, {
.r = 16000,
.conf = RV3029_TRICKLE_20K | RV3029_TRICKLE_80K,
}, {
.r = 20000,
.conf = RV3029_TRICKLE_20K,
}, {
.r = 80000,
.conf = RV3029_TRICKLE_80K,
},
};
int err;
u32 ohms;
u8 trickle_set_bits = 0;
/* Configure the trickle charger. */
err = dev_read_u32(dev, "trickle-resistor-ohms", &ohms);
if (!err) {
/* Find trickle-charger config */
for (int i = 0; i < ARRAY_SIZE(rv3029_trickle_tab); i++)
if (rv3029_trickle_tab[i].r >= ohms) {
dev_dbg(dev, "trickle charger at %d ohms\n",
rv3029_trickle_tab[i].r);
trickle_set_bits = rv3029_trickle_tab[i].conf;
break;
}
}
dev_dbg(dev, "trickle charger config 0x%x\n", trickle_set_bits);
err = rv3029_eeprom_update_bits(dev, RV3029_CONTROL_E2P_EECTRL,
RV3029_TRICKLE_MASK,
trickle_set_bits);
if (err < 0)
dev_dbg(dev, "failed to update trickle charger\n");
}
#else
static inline void rv3029_trickle_config(struct udevice *dev)
{
}
#endif
static int rv3029_probe(struct udevice *dev)
{
i2c_set_chip_flags(dev, DM_I2C_CHIP_RD_ADDRESS |
DM_I2C_CHIP_WR_ADDRESS);
rv3029_trickle_config(dev);
return 0;
}
static const struct rtc_ops rv3029_rtc_ops = {
.get = rv3029_rtc_get,
.set = rv3029_rtc_set,
.read8 = rv3029_rtc_read8,
.write8 = rv3029_rtc_write8,
.reset = rv3029_rtc_reset,
};
static const struct udevice_id rv3029_rtc_ids[] = {
{ .compatible = "mc,rv3029" },
{ .compatible = "mc,rv3029c2" },
{ }
};
U_BOOT_DRIVER(rtc_rv3029) = {
.name = "rtc-rv3029",
.id = UCLASS_RTC,
.probe = rv3029_probe,
.of_match = rv3029_rtc_ids,
.ops = &rv3029_rtc_ops,
};

View file

@ -106,7 +106,7 @@ int rk_mipi_dsi_enable(struct udevice *dev,
rk_mipi_dsi_write(regs, VSYNC_ACTIVE_LOW, val);
val = (timing->flags & DISPLAY_FLAGS_DE_LOW) ? 1 : 0;
rk_mipi_dsi_write(regs, DISPLAY_FLAGS_DE_LOW, val);
rk_mipi_dsi_write(regs, DATAEN_ACTIVE_LOW, val);
val = (timing->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE) ? 1 : 0;
rk_mipi_dsi_write(regs, COLORM_ACTIVE_LOW, val);
@ -241,7 +241,7 @@ int rk_mipi_phy_enable(struct udevice *dev)
/* select the suitable value for fsfreqrang reg */
for (i = 0; i < ARRAY_SIZE(freq_rang); i++) {
if (ddr_clk / (MHz) >= freq_rang[i][0])
if (ddr_clk / (MHz) <= freq_rang[i][0])
break;
}
if (i == ARRAY_SIZE(freq_rang)) {

View file

@ -11,11 +11,14 @@
/*
* Default environment settings
*/
#undef CONFIG_EXTRA_ENV_SETTINGS
#define CONFIG_EXTRA_ENV_SETTINGS \
"netdev=eth0\0" \
"ipaddr=172.16.12.50\0" \
"serverip=172.16.12.69\0" \
""
#undef CONFIG_BOOTCOMMAND
#define CONFIG_BOOTCOMMAND \
"sf probe;" \
"sf read 0x62000000 0x140800 0x500000;" \

View file

@ -17,6 +17,9 @@
#define CONFIG_SYS_TIMER_BASE 0x10350020
#define CONFIG_SYS_TIMER_COUNTER (CONFIG_SYS_TIMER_BASE + 8)
/* MMC/SD IP block */
#define CONFIG_BOUNCE_BUFFER
#define CONFIG_SYS_SDRAM_BASE 0x60000000
#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + 0x100000)
#define CONFIG_SYS_LOAD_ADDR (CONFIG_SYS_SDRAM_BASE + 0x2000000)
@ -25,3 +28,18 @@
#define CONFIG_USB_OHCI_NEW
#define CONFIG_SYS_USB_OHCI_MAX_ROOT_PORTS 1
#endif
#ifndef CONFIG_SPL_BUILD
#define ENV_MEM_LAYOUT_SETTINGS \
"scriptaddr=0x60000000\0" \
"fdt_addr_r=0x61f00000\0" \
"kernel_addr_r=0x62000000\0" \
"ramdisk_addr_r=0x64000000\0"
#include <config_distro_bootcmd.h>
#define CONFIG_EXTRA_ENV_SETTINGS \
ENV_MEM_LAYOUT_SETTINGS \
"fdtfile=" CONFIG_DEFAULT_FDT_FILE "\0" \
"partitions=" PARTS_DEFAULT \
BOOTENV
#endif

View file

@ -14,7 +14,6 @@
#define ARMCLK 3
/* sclk gates (special clocks) */
#define SCLK_MAC 64
#define SCLK_SPI0 65
#define SCLK_NANDC 67
#define SCLK_SDMMC 68
@ -35,20 +34,77 @@
#define SCLK_SDMMC_SAMPLE 84
#define SCLK_SDIO_SAMPLE 85
#define SCLK_EMMC_SAMPLE 86
#define SCLK_MAC_RX 87
#define SCLK_MAC_TX 88
#define SCLK_MACREF 89
#define SCLK_MACREF_OUT 90
#define SCLK_SARADC 91
#define SCLK_VENC_CORE 87
#define SCLK_HEVC_CORE 88
#define SCLK_HEVC_CABAC 89
#define SCLK_PWM0_PMU 90
#define SCLK_I2C0_PMU 91
#define SCLK_WIFI 92
#define SCLK_CIFOUT 93
#define SCLK_MIPI_CSI_OUT 94
#define SCLK_CIF0 95
#define SCLK_CIF1 96
#define SCLK_CIF2 97
#define SCLK_CIF3 98
#define SCLK_DSP 99
#define SCLK_DSP_IOP 100
#define SCLK_DSP_EPP 101
#define SCLK_DSP_EDP 102
#define SCLK_DSP_EDAP 103
#define SCLK_CVBS_HOST 104
#define SCLK_HDMI_SFR 105
#define SCLK_HDMI_CEC 106
#define SCLK_CRYPTO 107
#define SCLK_SPI 108
#define SCLK_SARADC 109
#define SCLK_TSADC 110
#define SCLK_MAC_PRE 111
#define SCLK_MAC 112
#define SCLK_MAC_RX 113
#define SCLK_MAC_REF 114
#define SCLK_MAC_REFOUT 115
#define SCLK_DSP_PFM 116
#define SCLK_RGA 117
#define SCLK_I2C1 118
#define SCLK_I2C2 119
#define SCLK_I2C3 120
#define SCLK_PWM 121
#define SCLK_ISP 122
#define SCLK_USBPHY 123
#define SCLK_I2S0_SRC 124
#define SCLK_I2S1_SRC 125
#define SCLK_I2S2_SRC 126
#define SCLK_UART0_SRC 127
#define SCLK_UART1_SRC 128
#define SCLK_UART2_SRC 129
#define SCLK_MAC_TX 130
#define SCLK_MACREF 131
#define SCLK_MACREF_OUT 132
#define DCLK_VOP_SRC 185
#define DCLK_HDMIPHY 186
#define DCLK_VOP 187
/* aclk gates */
#define ACLK_DMAC 192
#define ACLK_PRE 193
#define ACLK_CORE 194
#define ACLK_ENMCORE 195
#define ACLK_GMAC 196
#define ACLK_RKVENC 196
#define ACLK_RKVDEC 197
#define ACLK_VPU 198
#define ACLK_CIF0 199
#define ACLK_VIO0 200
#define ACLK_VIO1 201
#define ACLK_VOP 202
#define ACLK_IEP 203
#define ACLK_RGA 204
#define ACLK_ISP 205
#define ACLK_CIF1 206
#define ACLK_CIF2 207
#define ACLK_CIF3 208
#define ACLK_PERI 209
#define ACLK_GMAC 210
/* pclk gates */
#define PCLK_GPIO1 256
@ -67,12 +123,24 @@
#define PCLK_PWM 269
#define PCLK_TIMER 270
#define PCLK_PERI 271
#define PCLK_GMAC 272
#define PCLK_SARADC 273
#define PCLK_GPIO0_PMU 272
#define PCLK_I2C0_PMU 273
#define PCLK_PWM0_PMU 274
#define PCLK_ISP 275
#define PCLK_VIO 276
#define PCLK_MIPI_DSI 277
#define PCLK_HDMI_CTRL 278
#define PCLK_SARADC 279
#define PCLK_DSP_CFG 280
#define PCLK_BUS 281
#define PCLK_EFUSE0 282
#define PCLK_EFUSE1 283
#define PCLK_WDT 284
#define PCLK_GMAC 285
/* hclk gates */
#define HCLK_I2S0_8CH 320
#define HCLK_I2S1_8CH 321
#define HCLK_I2S1_2CH 321
#define HCLK_I2S2_2CH 322
#define HCLK_NANDC 323
#define HCLK_SDMMC 324
@ -80,20 +148,37 @@
#define HCLK_EMMC 326
#define HCLK_PERI 327
#define HCLK_SFC 328
#define HCLK_RKVENC 329
#define HCLK_RKVDEC 330
#define HCLK_CIF0 331
#define HCLK_VIO 332
#define HCLK_VOP 333
#define HCLK_IEP 334
#define HCLK_RGA 335
#define HCLK_ISP 336
#define HCLK_CRYPTO_MST 337
#define HCLK_CRYPTO_SLV 338
#define HCLK_HOST0 339
#define HCLK_OTG 340
#define HCLK_CIF1 341
#define HCLK_CIF2 342
#define HCLK_CIF3 343
#define HCLK_BUS 344
#define HCLK_VPU 345
#define CLK_NR_CLKS (HCLK_SFC + 1)
#define CLK_NR_CLKS (HCLK_VPU + 1)
/* reset id */
#define SRST_CORE_PO_AD 0
#define SRST_CORE_PO_AD 0
#define SRST_CORE_AD 1
#define SRST_L2_AD 2
#define SRST_CPU_NIU_AD 3
#define SRST_CPU_NIU_AD 3
#define SRST_CORE_PO 4
#define SRST_CORE 5
#define SRST_L2 6
#define SRST_L2 6
#define SRST_CORE_DBG 8
#define PRST_DBG 9
#define RST_DAP 10
#define RST_DAP 10
#define PRST_DBG_NIU 11
#define ARST_STRC_SYS_AD 15
@ -160,9 +245,9 @@
#define HRST_SYSBUS 75
#define PRST_USBGRF 76
#define ARST_PERIPH_NIU 80
#define HRST_PERIPH_NIU 81
#define PRST_PERIPH_NIU 82
#define ARST_PERIPH_NIU 80
#define HRST_PERIPH_NIU 81
#define PRST_PERIPH_NIU 82
#define HRST_PERIPH 83
#define HRST_SDMMC 84
#define HRST_SDIO 85
@ -180,7 +265,7 @@
#define HRST_HOST0_AUX 96
#define HRST_HOST0_ARB 97
#define SRST_HOST0_EHCIPHY 98
#define SRST_HOST0_UTMI 99
#define SRST_HOST0_UTMI 99
#define SRST_USBPOR 100
#define SRST_UTMI0 101
#define SRST_UTMI1 102
@ -227,21 +312,21 @@
#define HRST_VPU_NIU 141
#define ARST_VPU 142
#define HRST_VPU 143
#define ARST_RKVDEC_NIU 144
#define HRST_RKVDEC_NIU 145
#define ARST_RKVDEC_NIU 144
#define HRST_RKVDEC_NIU 145
#define ARST_RKVDEC 146
#define HRST_RKVDEC 147
#define SRST_RKVDEC_CABAC 148
#define SRST_RKVDEC_CORE 149
#define ARST_RKVENC_NIU 150
#define HRST_RKVENC_NIU 151
#define ARST_RKVENC_NIU 150
#define HRST_RKVENC_NIU 151
#define ARST_RKVENC 152
#define HRST_RKVENC 153
#define SRST_RKVENC_CORE 154
#define SRST_DSP_CORE 156
#define SRST_DSP_SYS 157
#define SRST_DSP_GLOBAL 158
#define SRST_DSP_GLOBAL 158
#define SRST_DSP_OECM 159
#define PRST_DSP_IOP_NIU 160
#define ARST_DSP_EPP_NIU 161
@ -259,7 +344,7 @@
#define SRST_PMU_I2C0 173
#define PRST_PMU_I2C0 174
#define PRST_PMU_GPIO0 175
#define PRST_PMU_INTMEM 176
#define PRST_PMU_INTMEM 176
#define PRST_PMU_PWM0 177
#define SRST_PMU_PWM0 178
#define PRST_PMU_GRF 179

View file

@ -4054,7 +4054,6 @@ CONFIG_SYS_RTC_CNT
CONFIG_SYS_RTC_OSCILLATOR
CONFIG_SYS_RTC_REG_BASE_ADDR
CONFIG_SYS_RTC_SETUP
CONFIG_SYS_RV3029_TCR
CONFIG_SYS_RX_ETH_BUFFER
CONFIG_SYS_SATA
CONFIG_SYS_SATA1