diff mbox series

[v3,22/23] i2c: designware_i2c: Separate out the speed calculation

Message ID 20200123114556.v3.22.I2e3d0961f7331632b382aaf38787ff8911e21149@changeid
State Accepted
Commit 23ad52ebb1e5b322e22c5c6b9d1a06b36fdc97c0
Headers show
Series i2c: designware_ic2: Improvements to timing and general cleanup | expand

Commit Message

Simon Glass Jan. 23, 2020, 6:48 p.m. UTC
We want to be able to calculate the speed separately from actually setting
the speed, so we can generate the required ACPI tables. Split out the
calculation into its own function.

Drop the double underscore on __dw_i2c_set_bus_speed while we are here.
That is reserved for compiler internals.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v3:
- Add new patch to separate out the speed calculation

Changes in v2: None

 drivers/i2c/designware_i2c.c | 78 +++++++++++++++++++++---------------
 drivers/i2c/designware_i2c.h |  3 ++
 2 files changed, 48 insertions(+), 33 deletions(-)
diff mbox series

Patch

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 6be98ee43b..39af25af9a 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -194,22 +194,12 @@  static int dw_i2c_calc_timing(struct dw_i2c *priv, enum i2c_speed_mode mode,
 	return 0;
 }
 
-/*
- * i2c_set_bus_speed - Set the i2c speed
- * @speed:	required i2c speed
- *
- * Set the i2c speed.
- */
-static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
-					   struct i2c_regs *i2c_base,
-					   unsigned int speed,
-					   unsigned int bus_clk)
+static int calc_bus_speed(struct dw_i2c *priv, int speed, ulong bus_clk,
+			  struct dw_i2c_speed_config *config)
 {
 	const struct dw_scl_sda_cfg *scl_sda_cfg = NULL;
-	struct dw_i2c_speed_config config;
+	struct i2c_regs *regs = priv->regs;
 	enum i2c_speed_mode i2c_spd;
-	unsigned int cntl;
-	unsigned int ena;
 	int spk_cnt;
 	int ret;
 
@@ -226,38 +216,60 @@  static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
 	else
 		i2c_spd = IC_SPEED_MODE_STANDARD;
 
-	/* Get enable setting for restore later */
-	ena = readl(&i2c_base->ic_enable) & IC_ENABLE_0B;
-
-	/* to set speed cltr must be disabled */
-	dw_i2c_enable(i2c_base, false);
-
-	cntl = (readl(&i2c_base->ic_con) & (~IC_CON_SPD_MSK));
-
 	/* Get the proper spike-suppression count based on target speed */
 	if (!priv || !priv->has_spk_cnt)
 		spk_cnt = 0;
 	else if (i2c_spd >= IC_SPEED_MODE_HIGH)
-		spk_cnt = readl(&i2c_base->hs_spklen);
+		spk_cnt = readl(&regs->hs_spklen);
 	else
-		spk_cnt = readl(&i2c_base->fs_spklen);
+		spk_cnt = readl(&regs->fs_spklen);
 	if (scl_sda_cfg) {
-		config.sda_hold = scl_sda_cfg->sda_hold;
+		config->sda_hold = scl_sda_cfg->sda_hold;
 		if (i2c_spd == IC_SPEED_MODE_STANDARD) {
-			config.scl_hcnt = scl_sda_cfg->ss_hcnt;
-			config.scl_lcnt = scl_sda_cfg->ss_lcnt;
+			config->scl_hcnt = scl_sda_cfg->ss_hcnt;
+			config->scl_lcnt = scl_sda_cfg->ss_lcnt;
 		} else {
-			config.scl_hcnt = scl_sda_cfg->fs_hcnt;
-			config.scl_lcnt = scl_sda_cfg->fs_lcnt;
+			config->scl_hcnt = scl_sda_cfg->fs_hcnt;
+			config->scl_lcnt = scl_sda_cfg->fs_lcnt;
 		}
 	} else {
 		ret = dw_i2c_calc_timing(priv, i2c_spd, bus_clk, spk_cnt,
-					 &config);
+					 config);
 		if (ret)
 			return log_msg_ret("gen_confg", ret);
 	}
+	config->speed_mode = i2c_spd;
+
+	return 0;
+}
+
+/*
+ * _dw_i2c_set_bus_speed - Set the i2c speed
+ * @speed:	required i2c speed
+ *
+ * Set the i2c speed.
+ */
+static int _dw_i2c_set_bus_speed(struct dw_i2c *priv, struct i2c_regs *i2c_base,
+				 unsigned int speed, unsigned int bus_clk)
+{
+	struct dw_i2c_speed_config config;
+	unsigned int cntl;
+	unsigned int ena;
+	int ret;
+
+	ret = calc_bus_speed(priv, speed, bus_clk, &config);
+	if (ret)
+		return ret;
+
+	/* Get enable setting for restore later */
+	ena = readl(&i2c_base->ic_enable) & IC_ENABLE_0B;
+
+	/* to set speed cltr must be disabled */
+	dw_i2c_enable(i2c_base, false);
+
+	cntl = (readl(&i2c_base->ic_con) & (~IC_CON_SPD_MSK));
 
-	switch (i2c_spd) {
+	switch (config.speed_mode) {
 	case IC_SPEED_MODE_HIGH:
 		cntl |= IC_CON_SPD_SS;
 		writel(config.scl_hcnt, &i2c_base->ic_hs_scl_hcnt);
@@ -526,7 +538,7 @@  static int __dw_i2c_init(struct i2c_regs *i2c_base, int speed, int slaveaddr)
 	writel(IC_TX_TL, &i2c_base->ic_tx_tl);
 	writel(IC_STOP_DET, &i2c_base->ic_intr_mask);
 #ifndef CONFIG_DM_I2C
-	__dw_i2c_set_bus_speed(NULL, i2c_base, speed, IC_CLK);
+	_dw_i2c_set_bus_speed(NULL, i2c_base, speed, IC_CLK);
 	writel(slaveaddr, &i2c_base->ic_sar);
 #endif
 
@@ -571,7 +583,7 @@  static unsigned int dw_i2c_set_bus_speed(struct i2c_adapter *adap,
 					 unsigned int speed)
 {
 	adap->speed = speed;
-	return __dw_i2c_set_bus_speed(NULL, i2c_get_base(adap), speed, IC_CLK);
+	return _dw_i2c_set_bus_speed(NULL, i2c_get_base(adap), speed, IC_CLK);
 }
 
 static void dw_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr)
@@ -670,7 +682,7 @@  static int designware_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
 #else
 	rate = IC_CLK;
 #endif
-	return __dw_i2c_set_bus_speed(i2c, i2c->regs, speed, rate);
+	return _dw_i2c_set_bus_speed(i2c, i2c->regs, speed, rate);
 }
 
 static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 2027a91add..61a882cb65 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -8,6 +8,7 @@ 
 #define __DW_I2C_H_
 
 #include <clk.h>
+#include <i2c.h>
 #include <reset.h>
 
 struct i2c_regs {
@@ -165,12 +166,14 @@  struct dw_scl_sda_cfg {
  * @scl_lcnt: Low count value for SCL
  * @scl_hcnt: High count value for SCL
  * @sda_hold: Data hold count
+ * @speed_mode: Speed mode being used
  */
 struct dw_i2c_speed_config {
 	/* SCL high and low period count */
 	u16 scl_lcnt;
 	u16 scl_hcnt;
 	u32 sda_hold;
+	enum i2c_speed_mode speed_mode;
 };
 
 /**