From 4f17374dfd25db1bbb163c474de6dc6f8a7d9e84 Mon Sep 17 00:00:00 2001 From: huang lin Date: Wed, 2 Mar 2016 18:46:24 +0800 Subject: rockchip: rk3399: add i2c clock driver This patch add i2c clock driver and reuse the common rockchip i2c driver. The i2c0,4,8 src clock from ppll, while i2c1,2,3,5,6,7 from gpll. Please refer to TRM V0.3 Part1 Page 142 for i2c clock setting. BRANCH=none BUG=chrome-os-partner:51537 TEST=emerge-kevin coreboot Change-Id: I91822e483244d71798a1c68f14ba0a84f405a665 Signed-off-by: Patrick Georgi Original-Commit-Id: 270118e44d159f6a27812fa234b34fe7ac54cbe4 Original-Change-Id: Iea5f4a93cf173e1278166dcb04e19a4ef6c4af04 Original-Signed-off-by: huang lin Original-Signed-off-by: Vadim Bendebury Original-Reviewed-on: https://chromium-review.googlesource.com/338948 Reviewed-on: https://review.coreboot.org/14711 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- src/soc/rockchip/rk3399/clock.c | 104 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) (limited to 'src/soc/rockchip/rk3399/clock.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 #include #include +#include #include #include #include @@ -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; +} -- cgit v1.2.3