diff mbox series

[v3,12/23] i2c: designware_i2c: Add spike supression

Message ID 20200123114556.v3.12.I8edeb1d807ab73060bd6a5d028f7af8537cbf2f2@changeid
State Accepted
Commit 96fe11c3dace9038e2df0e7c4625d1c3e330425f
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
Some versions of this peripheral include a spike-suppression phase of the
bus. Add support for this.

Signed-off-by: Simon Glass <sjg at chromium.org>
Reviewed-by: Heiko Schocher <hs at denx.de>

---

Changes in v3: None
Changes in v2:
- Add a few more clean-up patches for i2c

 drivers/i2c/designware_i2c.c     | 10 +++++++++-
 drivers/i2c/designware_i2c.h     |  2 ++
 drivers/i2c/designware_i2c_pci.c |  2 ++
 3 files changed, 13 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 0069602103..4aee25c543 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -220,6 +220,7 @@  static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
 	enum i2c_speed_mode i2c_spd;
 	unsigned int cntl;
 	unsigned int ena;
+	int spk_cnt;
 	int ret;
 
 	if (priv)
@@ -241,6 +242,13 @@  static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
 
 	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);
+	else
+		spk_cnt = readl(&i2c_base->fs_spklen);
 	if (scl_sda_cfg) {
 		config.sda_hold = scl_sda_cfg->sda_hold;
 		if (i2c_spd == IC_SPEED_MODE_STANDARD) {
@@ -251,7 +259,7 @@  static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
 			config.scl_lcnt = scl_sda_cfg->fs_lcnt;
 		}
 	} else {
-		ret = dw_i2c_calc_timing(priv, i2c_spd, bus_clk, 0,
+		ret = dw_i2c_calc_timing(priv, i2c_spd, bus_clk, spk_cnt,
 					 &config);
 		if (ret)
 			return log_msg_ret("gen_confg", ret);
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index f32dc0f854..8789c7d8ce 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -176,6 +176,7 @@  struct dw_scl_sda_cfg {
  * @scl_rise_time_ns: Configured SCL rise time in nanoseconds
  * @scl_fall_time_ns: Configured SCL fall time in nanoseconds
  * @sda_hold_time_ns: Configured SDA hold time in nanoseconds
+ * @has_spk_cnt: true if the spike-count register is present
  * @clk: Clock input to the I2C controller
  */
 struct dw_i2c {
@@ -185,6 +186,7 @@  struct dw_i2c {
 	u32 scl_rise_time_ns;
 	u32 scl_fall_time_ns;
 	u32 sda_hold_time_ns;
+	bool has_spk_cnt;
 #if CONFIG_IS_ENABLED(CLK)
 	struct clk clk;
 #endif
diff --git a/drivers/i2c/designware_i2c_pci.c b/drivers/i2c/designware_i2c_pci.c
index 2b974a07c3..50f03e3d90 100644
--- a/drivers/i2c/designware_i2c_pci.c
+++ b/drivers/i2c/designware_i2c_pci.c
@@ -62,6 +62,8 @@  static int designware_i2c_pci_ofdata_to_platdata(struct udevice *dev)
 	if (IS_ENABLED(CONFIG_INTEL_BAYTRAIL))
 		/* Use BayTrail specific timing values */
 		priv->scl_sda_cfg = &byt_config;
+	if (dev_get_driver_data(dev) == INTEL_APL)
+		priv->has_spk_cnt = true;
 
 	return designware_i2c_ofdata_to_platdata(dev);
 }