summaryrefslogtreecommitdiff
path: root/src/soc/rockchip/rk3288/i2c.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc/rockchip/rk3288/i2c.c')
-rw-r--r--src/soc/rockchip/rk3288/i2c.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/soc/rockchip/rk3288/i2c.c b/src/soc/rockchip/rk3288/i2c.c
index 9348b6cf89..142ec4a489 100644
--- a/src/soc/rockchip/rk3288/i2c.c
+++ b/src/soc/rockchip/rk3288/i2c.c
@@ -30,6 +30,9 @@
#include "addressmap.h"
#include "grf.h"
#include "soc.h"
+#include "i2c.h"
+#include "clock.h"
+
#define RETRY_COUNT 3
/* 100000us = 100ms */
#define I2C_TIMEOUT_US 100000
@@ -275,3 +278,39 @@ int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int seg_count)
}
return res;
}
+
+void i2c_init(unsigned int bus, unsigned int hz)
+{
+ unsigned int clk_div;
+ unsigned int divl;
+ unsigned int divh;
+ unsigned int i2c_src_clk;
+ struct rk3288_i2c_regs *regs = i2c_bus[bus];
+
+ /*i2c0,i2c2 src clk from pd_bus_pclk
+ other i2c src clk from peri_pclk
+ */
+ switch (bus) {
+ case 0:
+ case 2:
+ i2c_src_clk = PD_BUS_PCLK_HZ;
+ break;
+ case 1:
+ case 3:
+ case 4:
+ case 5:
+ i2c_src_clk = PERI_PCLK_HZ;
+ break;
+ default:
+ break;
+ }
+
+ /*SCL Divisor = 8*(CLKDIVL + 1 + CLKDIVH + 1)
+ SCL = PCLK/ SCLK Divisor
+ */
+ clk_div = div_round_up(i2c_src_clk, hz * 8) - 2;
+ divh = clk_div / 2;
+ divl = ALIGN_UP(clk_div, 2) / 2;
+ assert((divh < 65536) && (divl < 65536));
+ writel((divh << 16) | (divl << 0), &regs->i2c_clkdiv);
+}