summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/rockchip/rk3399/Makefile.inc1
-rw-r--r--src/soc/rockchip/rk3399/clock.c104
-rw-r--r--src/soc/rockchip/rk3399/include/soc/addressmap.h4
-rw-r--r--src/soc/rockchip/rk3399/include/soc/clock.h3
4 files changed, 112 insertions, 0 deletions
diff --git a/src/soc/rockchip/rk3399/Makefile.inc b/src/soc/rockchip/rk3399/Makefile.inc
index 40c652fcf2..bdd9d3eb26 100644
--- a/src/soc/rockchip/rk3399/Makefile.inc
+++ b/src/soc/rockchip/rk3399/Makefile.inc
@@ -51,6 +51,7 @@ ramstage-y += sdram.c
ramstage-y += ../common/spi.c
ramstage-$(CONFIG_DRIVERS_UART) += ../common/uart.c
ramstage-y += clock.c
+ramstage-y += ../common/i2c.c
ramstage-y += soc.c
ramstage-y += timer.c
diff --git a/src/soc/rockchip/rk3399/clock.c b/src/soc/rockchip/rk3399/clock.c
index 8a2b3517f6..d706c9329f 100644
--- a/src/soc/rockchip/rk3399/clock.c
+++ b/src/soc/rockchip/rk3399/clock.c
@@ -19,6 +19,7 @@
#include <soc/addressmap.h>
#include <soc/clock.h>
#include <soc/grf.h>
+#include <soc/i2c.h>
#include <soc/soc.h>
#include <stdint.h>
#include <stdlib.h>
@@ -94,6 +95,14 @@ enum {
SPI3_DIV_CON_MASK = 0x7f,
SPI3_DIV_CON_SHIFT = 0x0,
+ /* PMUCRU_CLKSEL_CON2 */
+ I2C_DIV_CON_MASK = 0x7f,
+ I2C8_DIV_CON_SHIFT = 8,
+ I2C0_DIV_CON_SHIFT = 0,
+
+ /* PMUCRU_CLKSEL_CON3 */
+ I2C4_DIV_CON_SHIFT = 0,
+
/* CLKSEL_CON0 */
ACLKM_CORE_L_DIV_CON_MASK = 0x1f,
ACLKM_CORE_L_DIV_CON_SHIFT = 8,
@@ -166,6 +175,27 @@ enum {
CLK_SPI2_PLL_SEL_SHIFT = 7,
CLK_SPI2_PLL_DIV_CON_SHIFT = 0,
+ /* CLKSEL_CON61 */
+ CLK_I2C_PLL_SEL_MASK = 1,
+ CLK_I2C_PLL_SEL_CPLL = 0,
+ CLK_I2C_PLL_SEL_GPLL = 1,
+ CLK_I2C5_PLL_SEL_SHIFT = 15,
+ CLK_I2C5_DIV_CON_SHIFT = 8,
+ CLK_I2C1_PLL_SEL_SHIFT = 7,
+ CLK_I2C1_DIV_CON_SHIFT = 0,
+
+ /* CLKSEL_CON62 */
+ CLK_I2C6_PLL_SEL_SHIFT = 15,
+ CLK_I2C6_DIV_CON_SHIFT = 8,
+ CLK_I2C2_PLL_SEL_SHIFT = 7,
+ CLK_I2C2_DIV_CON_SHIFT = 0,
+
+ /* CLKSEL_CON63 */
+ CLK_I2C7_PLL_SEL_SHIFT = 15,
+ CLK_I2C7_DIV_CON_SHIFT = 8,
+ CLK_I2C3_PLL_SEL_SHIFT = 7,
+ CLK_I2C3_DIV_CON_SHIFT = 0,
+
/* CRU_SOFTRST_CON4 */
RESETN_DDR0_REQ_MASK = 1,
RESETN_DDR0_REQ_SHIFT = 8,
@@ -471,3 +501,77 @@ void rkclk_configure_spi(unsigned int bus, unsigned int hz)
printk(BIOS_ERR, "do not support this spi bus\n");
}
}
+
+#define I2C_CLK_REG_VALUE(bus, clk_div) \
+ RK_CLRSETBITS(I2C_DIV_CON_MASK << \
+ CLK_I2C ##bus## _DIV_CON_SHIFT | \
+ CLK_I2C_PLL_SEL_MASK << \
+ CLK_I2C ##bus## _PLL_SEL_SHIFT, \
+ (clk_div - 1) << \
+ CLK_I2C ##bus## _DIV_CON_SHIFT | \
+ CLK_I2C_PLL_SEL_GPLL << \
+ CLK_I2C ##bus## _PLL_SEL_SHIFT)
+#define PMU_I2C_CLK_REG_VALUE(bus, clk_div) \
+ RK_CLRSETBITS(I2C_DIV_CON_MASK << I2C ##bus## _DIV_CON_SHIFT, \
+ (clk_div - 1) << I2C ##bus## _DIV_CON_SHIFT)
+
+static void rkclk_configure_i2c(unsigned int bus, unsigned int hz)
+{
+ int src_clk_div;
+ int pll;
+
+ /* i2c0,4,8 src clock from ppll, i2c1,2,3,5,6,7 src clock from gpll*/
+ pll = (bus == 0 || bus == 4 || bus == 8) ? PPLL_HZ : GPLL_HZ;
+ src_clk_div = pll / hz;
+ assert((src_clk_div - 1 < 127) && (src_clk_div * hz == pll));
+
+ switch (bus) {
+ case 0:
+ write32(&pmucru_ptr->pmucru_clksel[2],
+ PMU_I2C_CLK_REG_VALUE(0, src_clk_div));
+ break;
+ case 1:
+ write32(&cru_ptr->clksel_con[61],
+ I2C_CLK_REG_VALUE(1, src_clk_div));
+ break;
+ case 2:
+ write32(&cru_ptr->clksel_con[62],
+ I2C_CLK_REG_VALUE(2, src_clk_div));
+ break;
+ case 3:
+ write32(&cru_ptr->clksel_con[63],
+ I2C_CLK_REG_VALUE(3, src_clk_div));
+ break;
+ case 4:
+ write32(&pmucru_ptr->pmucru_clksel[3],
+ PMU_I2C_CLK_REG_VALUE(4, src_clk_div));
+ break;
+ case 5:
+ write32(&cru_ptr->clksel_con[61],
+ I2C_CLK_REG_VALUE(5, src_clk_div));
+ break;
+ case 6:
+ write32(&cru_ptr->clksel_con[62],
+ I2C_CLK_REG_VALUE(6, src_clk_div));
+ break;
+ case 7:
+ write32(&cru_ptr->clksel_con[63],
+ I2C_CLK_REG_VALUE(7, src_clk_div));
+ break;
+ case 8:
+ write32(&pmucru_ptr->pmucru_clksel[2],
+ PMU_I2C_CLK_REG_VALUE(8, src_clk_div));
+ break;
+ default:
+ printk(BIOS_ERR, "do not support this i2c bus\n");
+ }
+}
+
+uint32_t rkclk_i2c_clock_for_bus(unsigned bus)
+{
+ uint32_t freq = 198 * 1000 * 1000;
+
+ rkclk_configure_i2c(bus, freq);
+
+ return freq;
+}
diff --git a/src/soc/rockchip/rk3399/include/soc/addressmap.h b/src/soc/rockchip/rk3399/include/soc/addressmap.h
index 427122c868..90d1356298 100644
--- a/src/soc/rockchip/rk3399/include/soc/addressmap.h
+++ b/src/soc/rockchip/rk3399/include/soc/addressmap.h
@@ -56,4 +56,8 @@
#define TSADC_BASE 0xff260000
#define SARADC_BASE 0xff100000
+
+#define IC_BASES { I2C0_BASE, I2C1_BASE, I2C2_BASE, I2C3_BASE, \
+ I2C4_BASE, I2C5_BASE, I2C6_BASE, I2C7_BASE, I2C8_BASE }
+
#endif /* __SOC_ROCKCHIP_RK3399_ADDRESSMAP_H__ */
diff --git a/src/soc/rockchip/rk3399/include/soc/clock.h b/src/soc/rockchip/rk3399/include/soc/clock.h
index cb4d32568a..4c5a455a8b 100644
--- a/src/soc/rockchip/rk3399/include/soc/clock.h
+++ b/src/soc/rockchip/rk3399/include/soc/clock.h
@@ -104,4 +104,7 @@ void rkclk_init(void);
void rkclk_configure_cpu(enum apll_l_frequencies apll_l_freq);
void rkclk_configure_ddr(unsigned int hz);
void rkclk_configure_spi(unsigned int bus, unsigned int hz);
+void rkclk_ddr_reset(u32 ch, u32 ctl, u32 phy);
+uint32_t rkclk_i2c_clock_for_bus(unsigned bus);
+
#endif /* __SOC_ROCKCHIP_RK3399_CLOCK_H__ */