i2c: designware_i2c: Add spike supression
authorSimon Glass <sjg@chromium.org>
Thu, 23 Jan 2020 18:48:15 +0000 (11:48 -0700)
committerHeiko Schocher <hs@denx.de>
Mon, 27 Jan 2020 06:22:01 +0000 (07:22 +0100)
Some versions of this peripheral include a spike-suppression phase of the
bus. Add support for this.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
drivers/i2c/designware_i2c.c
drivers/i2c/designware_i2c.h
drivers/i2c/designware_i2c_pci.c

index 00696021032bb35255129f7337f4313b95946957..4aee25c5438049fa4558d6900ef5a78d20037238 100644 (file)
@@ -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);
index f32dc0f85429538eb69ac1e53d3be2e1f1ef59e6..8789c7d8cec277a8d5520f701acaa4439266d293 100644 (file)
@@ -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
index 2b974a07c3334d57f3e5f46a2a66751a4bb1a85e..50f03e3d90555f78a6c5a81fcc893a7781f4fb72 100644 (file)
@@ -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);
 }