summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2020-01-29 09:34:13 -0500
committerTom Rini <trini@konsulko.com>2020-01-29 09:34:13 -0500
commite7ab1cb3f0421ad8e8435a8258790e238c623ea2 (patch)
treefb2e7cce740a30f137dcdce0d2f4b2512ae58498 /drivers
parent3e12744a90241b08788ab7f20b5437381dbc9f68 (diff)
parent2034f6c27fc91407fe8bbd36670714b77d9ef1dc (diff)
Merge tag 'for-v2020.04' of https://gitlab.denx.de/u-boot/custodians/u-boot-i2c
i2c changes for 2020.04 - updates the Designware I2C driver - get timings from device tree - handle units in nanoseconds - make sure that the requested bus speed is not exceeded - few smaller clean-ups - adds enums for i2c speed and update drivers which use them - global_data: remove unused mxc_i2c specific field
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/ast_i2c.c2
-rw-r--r--drivers/i2c/ast_i2c.h2
-rw-r--r--drivers/i2c/designware_i2c.c300
-rw-r--r--drivers/i2c/designware_i2c.h73
-rw-r--r--drivers/i2c/designware_i2c_pci.c4
-rw-r--r--drivers/i2c/exynos_hs_i2c.c5
-rw-r--r--drivers/i2c/fsl_i2c.c3
-rw-r--r--drivers/i2c/i2c-cdns.c2
-rw-r--r--drivers/i2c/i2c-uclass.c12
-rw-r--r--drivers/i2c/i2c-uniphier-f.c2
-rw-r--r--drivers/i2c/i2c-uniphier.c2
-rw-r--r--drivers/i2c/imx_lpi2c.c8
-rw-r--r--drivers/i2c/kona_i2c.c28
-rw-r--r--drivers/i2c/mv_i2c.c4
-rw-r--r--drivers/i2c/mvtwsi.c5
-rw-r--r--drivers/i2c/omap24xx_i2c.c5
-rw-r--r--drivers/i2c/omap24xx_i2c.h4
-rw-r--r--drivers/i2c/rcar_i2c.c2
-rw-r--r--drivers/i2c/rcar_iic.c2
-rw-r--r--drivers/i2c/s3c24x0_i2c.c5
-rw-r--r--drivers/i2c/sandbox_i2c.c3
-rw-r--r--drivers/i2c/stm32f7_i2c.c43
22 files changed, 355 insertions, 161 deletions
diff --git a/drivers/i2c/ast_i2c.c b/drivers/i2c/ast_i2c.c
index 763183d649..35dc234160 100644
--- a/drivers/i2c/ast_i2c.c
+++ b/drivers/i2c/ast_i2c.c
@@ -314,7 +314,7 @@ static int ast_i2c_set_speed(struct udevice *dev, unsigned int speed)
divider = i2c_rate / speed;
priv->speed = speed;
- if (speed > I2C_HIGHSPEED_RATE) {
+ if (speed > I2C_SPEED_FAST_RATE) {
debug("Enable High Speed\n");
setbits_le32(&regs->fcr, I2CD_M_HIGH_SPEED_EN
| I2CD_M_SDA_DRIVE_1T_EN
diff --git a/drivers/i2c/ast_i2c.h b/drivers/i2c/ast_i2c.h
index 401e0970f7..928785989e 100644
--- a/drivers/i2c/ast_i2c.h
+++ b/drivers/i2c/ast_i2c.h
@@ -126,6 +126,4 @@ struct ast_i2c_regs {
#define I2CD_RX_DATA_SHIFT 8
#define I2CD_RX_DATA_MASK (0xff << I2CD_RX_DATA_SHIFT)
-#define I2C_HIGHSPEED_RATE 400000
-
#endif /* __AST_I2C_H_ */
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index b8cdd1c661..c8c5d2c331 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -4,8 +4,8 @@
* Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
*/
-#include <clk.h>
#include <common.h>
+#include <clk.h>
#include <dm.h>
#include <i2c.h>
#include <pci.h>
@@ -46,30 +46,220 @@ static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
}
#endif
+/* High and low times in different speed modes (in ns) */
+enum {
+ /* SDA Hold Time */
+ DEFAULT_SDA_HOLD_TIME = 300,
+};
+
+/**
+ * calc_counts() - Convert a period to a number of IC clk cycles
+ *
+ * @ic_clk: Input clock in Hz
+ * @period_ns: Period to represent, in ns
+ * @return calculated count
+ */
+static uint calc_counts(uint ic_clk, uint period_ns)
+{
+ return DIV_ROUND_UP(ic_clk / 1000 * period_ns, NANO_TO_KILO);
+}
+
+/**
+ * struct i2c_mode_info - Information about an I2C speed mode
+ *
+ * Each speed mode has its own characteristics. This struct holds these to aid
+ * calculations in dw_i2c_calc_timing().
+ *
+ * @speed: Speed in Hz
+ * @min_scl_lowtime_ns: Minimum value for SCL low period in ns
+ * @min_scl_hightime_ns: Minimum value for SCL high period in ns
+ * @def_rise_time_ns: Default rise time in ns
+ * @def_fall_time_ns: Default fall time in ns
+ */
+struct i2c_mode_info {
+ int speed;
+ int min_scl_hightime_ns;
+ int min_scl_lowtime_ns;
+ int def_rise_time_ns;
+ int def_fall_time_ns;
+};
+
+static const struct i2c_mode_info info_for_mode[] = {
+ [IC_SPEED_MODE_STANDARD] = {
+ I2C_SPEED_STANDARD_RATE,
+ MIN_SS_SCL_HIGHTIME,
+ MIN_SS_SCL_LOWTIME,
+ 1000,
+ 300,
+ },
+ [IC_SPEED_MODE_FAST] = {
+ I2C_SPEED_FAST_RATE,
+ MIN_FS_SCL_HIGHTIME,
+ MIN_FS_SCL_LOWTIME,
+ 300,
+ 300,
+ },
+ [IC_SPEED_MODE_FAST_PLUS] = {
+ I2C_SPEED_FAST_PLUS_RATE,
+ MIN_FP_SCL_HIGHTIME,
+ MIN_FP_SCL_LOWTIME,
+ 260,
+ 500,
+ },
+ [IC_SPEED_MODE_HIGH] = {
+ I2C_SPEED_HIGH_RATE,
+ MIN_HS_SCL_HIGHTIME,
+ MIN_HS_SCL_LOWTIME,
+ 120,
+ 120,
+ },
+};
+
+/**
+ * dw_i2c_calc_timing() - Calculate the timings to use for a bus
+ *
+ * @priv: Bus private information (NULL if not using driver model)
+ * @mode: Speed mode to use
+ * @ic_clk: IC clock speed in Hz
+ * @spk_cnt: Spike-suppression count
+ * @config: Returns value to use
+ * @return 0 if OK, -EINVAL if the calculation failed due to invalid data
+ */
+static int dw_i2c_calc_timing(struct dw_i2c *priv, enum i2c_speed_mode mode,
+ int ic_clk, int spk_cnt,
+ struct dw_i2c_speed_config *config)
+{
+ int fall_cnt, rise_cnt, min_tlow_cnt, min_thigh_cnt;
+ int hcnt, lcnt, period_cnt, diff, tot;
+ int sda_hold_time_ns, scl_rise_time_ns, scl_fall_time_ns;
+ const struct i2c_mode_info *info;
+
+ /*
+ * Find the period, rise, fall, min tlow, and min thigh in terms of
+ * counts of the IC clock
+ */
+ info = &info_for_mode[mode];
+ period_cnt = ic_clk / info->speed;
+ scl_rise_time_ns = priv && priv->scl_rise_time_ns ?
+ priv->scl_rise_time_ns : info->def_rise_time_ns;
+ scl_fall_time_ns = priv && priv->scl_fall_time_ns ?
+ priv->scl_fall_time_ns : info->def_fall_time_ns;
+ rise_cnt = calc_counts(ic_clk, scl_rise_time_ns);
+ fall_cnt = calc_counts(ic_clk, scl_fall_time_ns);
+ min_tlow_cnt = calc_counts(ic_clk, info->min_scl_lowtime_ns);
+ min_thigh_cnt = calc_counts(ic_clk, info->min_scl_hightime_ns);
+
+ debug("dw_i2c: period %d rise %d fall %d tlow %d thigh %d spk %d\n",
+ period_cnt, rise_cnt, fall_cnt, min_tlow_cnt, min_thigh_cnt,
+ spk_cnt);
+
+ /*
+ * Back-solve for hcnt and lcnt according to the following equations:
+ * SCL_High_time = [(HCNT + IC_*_SPKLEN + 7) * ic_clk] + SCL_Fall_time
+ * SCL_Low_time = [(LCNT + 1) * ic_clk] - SCL_Fall_time + SCL_Rise_time
+ */
+ hcnt = min_thigh_cnt - fall_cnt - 7 - spk_cnt;
+ lcnt = min_tlow_cnt - rise_cnt + fall_cnt - 1;
+
+ if (hcnt < 0 || lcnt < 0) {
+ debug("dw_i2c: bad counts. hcnt = %d lcnt = %d\n", hcnt, lcnt);
+ return -EINVAL;
+ }
+
+ /*
+ * Now add things back up to ensure the period is hit. If it is off,
+ * split the difference and bias to lcnt for remainder
+ */
+ tot = hcnt + lcnt + 7 + spk_cnt + rise_cnt + 1;
+
+ if (tot < period_cnt) {
+ diff = (period_cnt - tot) / 2;
+ hcnt += diff;
+ lcnt += diff;
+ tot = hcnt + lcnt + 7 + spk_cnt + rise_cnt + 1;
+ lcnt += period_cnt - tot;
+ }
+
+ config->scl_lcnt = lcnt;
+ config->scl_hcnt = hcnt;
+
+ /* Use internal default unless other value is specified */
+ sda_hold_time_ns = priv && priv->sda_hold_time_ns ?
+ priv->sda_hold_time_ns : DEFAULT_SDA_HOLD_TIME;
+ config->sda_hold = calc_counts(ic_clk, sda_hold_time_ns);
+
+ debug("dw_i2c: hcnt = %d lcnt = %d sda hold = %d\n", hcnt, lcnt,
+ config->sda_hold);
+
+ return 0;
+}
+
+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 i2c_regs *regs = priv->regs;
+ enum i2c_speed_mode i2c_spd;
+ int spk_cnt;
+ int ret;
+
+ if (priv)
+ scl_sda_cfg = priv->scl_sda_cfg;
+ /* Allow high speed if there is no config, or the config allows it */
+ if (speed >= I2C_SPEED_HIGH_RATE &&
+ (!scl_sda_cfg || scl_sda_cfg->has_high_speed))
+ i2c_spd = IC_SPEED_MODE_HIGH;
+ else if (speed >= I2C_SPEED_FAST_RATE)
+ i2c_spd = IC_SPEED_MODE_FAST_PLUS;
+ else if (speed >= I2C_SPEED_FAST_PLUS_RATE)
+ i2c_spd = IC_SPEED_MODE_FAST;
+ else
+ i2c_spd = IC_SPEED_MODE_STANDARD;
+
+ /* 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(&regs->hs_spklen);
+ else
+ spk_cnt = readl(&regs->fs_spklen);
+ if (scl_sda_cfg) {
+ 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;
+ } else {
+ 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);
+ if (ret)
+ return log_msg_ret("gen_confg", ret);
+ }
+ config->speed_mode = i2c_spd;
+
+ return 0;
+}
+
/*
- * i2c_set_bus_speed - Set the i2c speed
+ * _dw_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 i2c_regs *i2c_base,
- struct dw_scl_sda_cfg *scl_sda_cfg,
- unsigned int speed,
- unsigned int bus_mhz)
+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 hcnt, lcnt;
unsigned int ena;
- int i2c_spd;
+ int ret;
- /* Allow max speed if there is no config, or the config allows it */
- if (speed >= I2C_MAX_SPEED &&
- (!scl_sda_cfg || scl_sda_cfg->has_max_speed))
- i2c_spd = IC_SPEED_MODE_MAX;
- else if (speed >= I2C_FAST_SPEED)
- i2c_spd = IC_SPEED_MODE_FAST;
- else
- i2c_spd = IC_SPEED_MODE_STANDARD;
+ 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;
@@ -79,53 +269,31 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
cntl = (readl(&i2c_base->ic_con) & (~IC_CON_SPD_MSK));
- switch (i2c_spd) {
- case IC_SPEED_MODE_MAX:
+ switch (config.speed_mode) {
+ case IC_SPEED_MODE_HIGH:
cntl |= IC_CON_SPD_SS;
- if (scl_sda_cfg) {
- hcnt = scl_sda_cfg->fs_hcnt;
- lcnt = scl_sda_cfg->fs_lcnt;
- } else {
- hcnt = (bus_mhz * MIN_HS_SCL_HIGHTIME) / NANO_TO_MICRO;
- lcnt = (bus_mhz * MIN_HS_SCL_LOWTIME) / NANO_TO_MICRO;
- }
- writel(hcnt, &i2c_base->ic_hs_scl_hcnt);
- writel(lcnt, &i2c_base->ic_hs_scl_lcnt);
+ writel(config.scl_hcnt, &i2c_base->ic_hs_scl_hcnt);
+ writel(config.scl_lcnt, &i2c_base->ic_hs_scl_lcnt);
break;
-
case IC_SPEED_MODE_STANDARD:
cntl |= IC_CON_SPD_SS;
- if (scl_sda_cfg) {
- hcnt = scl_sda_cfg->ss_hcnt;
- lcnt = scl_sda_cfg->ss_lcnt;
- } else {
- hcnt = (bus_mhz * MIN_SS_SCL_HIGHTIME) / NANO_TO_MICRO;
- lcnt = (bus_mhz * MIN_SS_SCL_LOWTIME) / NANO_TO_MICRO;
- }
- writel(hcnt, &i2c_base->ic_ss_scl_hcnt);
- writel(lcnt, &i2c_base->ic_ss_scl_lcnt);
+ writel(config.scl_hcnt, &i2c_base->ic_ss_scl_hcnt);
+ writel(config.scl_lcnt, &i2c_base->ic_ss_scl_lcnt);
break;
-
+ case IC_SPEED_MODE_FAST_PLUS:
case IC_SPEED_MODE_FAST:
default:
cntl |= IC_CON_SPD_FS;
- if (scl_sda_cfg) {
- hcnt = scl_sda_cfg->fs_hcnt;
- lcnt = scl_sda_cfg->fs_lcnt;
- } else {
- hcnt = (bus_mhz * MIN_FS_SCL_HIGHTIME) / NANO_TO_MICRO;
- lcnt = (bus_mhz * MIN_FS_SCL_LOWTIME) / NANO_TO_MICRO;
- }
- writel(hcnt, &i2c_base->ic_fs_scl_hcnt);
- writel(lcnt, &i2c_base->ic_fs_scl_lcnt);
+ writel(config.scl_hcnt, &i2c_base->ic_fs_scl_hcnt);
+ writel(config.scl_lcnt, &i2c_base->ic_fs_scl_lcnt);
break;
}
writel(cntl, &i2c_base->ic_con);
/* Configure SDA Hold Time if required */
- if (scl_sda_cfg)
- writel(scl_sda_cfg->sda_hold, &i2c_base->ic_sda_hold);
+ if (config.sda_hold)
+ writel(config.sda_hold, &i2c_base->ic_sda_hold);
/* Restore back i2c now speed set */
if (ena == IC_ENABLE_0B)
@@ -370,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(i2c_base, NULL, speed, IC_CLK);
+ _dw_i2c_set_bus_speed(NULL, i2c_base, speed, IC_CLK);
writel(slaveaddr, &i2c_base->ic_sar);
#endif
@@ -415,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(i2c_get_base(adap), NULL, 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)
@@ -511,14 +679,10 @@ static int designware_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
rate = clk_get_rate(&i2c->clk);
if (IS_ERR_VALUE(rate))
return -EINVAL;
-
- /* Convert to MHz */
- rate /= 1000000;
#else
rate = IC_CLK;
#endif
- return __dw_i2c_set_bus_speed(i2c->regs, i2c->scl_sda_cfg, 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,
@@ -537,20 +701,17 @@ static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
return ret;
}
-static int designware_i2c_ofdata_to_platdata(struct udevice *bus)
-{
- struct dw_i2c *priv = dev_get_priv(bus);
-
- priv->regs = (struct i2c_regs *)devfdt_get_addr_ptr(bus);
-
- return 0;
-}
-
-int designware_i2c_probe(struct udevice *bus)
+int designware_i2c_ofdata_to_platdata(struct udevice *bus)
{
struct dw_i2c *priv = dev_get_priv(bus);
int ret;
+ if (!priv->regs)
+ priv->regs = (struct i2c_regs *)devfdt_get_addr_ptr(bus);
+ dev_read_u32(bus, "i2c-scl-rising-time-ns", &priv->scl_rise_time_ns);
+ dev_read_u32(bus, "i2c-scl-falling-time-ns", &priv->scl_fall_time_ns);
+ dev_read_u32(bus, "i2c-sda-hold-time-ns", &priv->sda_hold_time_ns);
+
ret = reset_get_bulk(bus, &priv->resets);
if (ret)
dev_warn(bus, "Can't get reset: %d\n", ret);
@@ -570,6 +731,13 @@ int designware_i2c_probe(struct udevice *bus)
}
#endif
+ return 0;
+}
+
+int designware_i2c_probe(struct udevice *bus)
+{
+ struct dw_i2c *priv = dev_get_priv(bus);
+
return __dw_i2c_init(priv->regs, 0, 0);
}
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 48766d0806..61a882cb65 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -7,6 +7,8 @@
#ifndef __DW_I2C_H_
#define __DW_I2C_H_
+#include <clk.h>
+#include <i2c.h>
#include <reset.h>
struct i2c_regs {
@@ -43,20 +45,32 @@ struct i2c_regs {
u32 ic_rxflr; /* 0x78 */
u32 ic_sda_hold; /* 0x7c */
u32 ic_tx_abrt_source; /* 0x80 */
- u8 res1[0x18]; /* 0x84 */
+ u32 slv_data_nak_only;
+ u32 dma_cr;
+ u32 dma_tdlr;
+ u32 dma_rdlr;
+ u32 sda_setup;
+ u32 ack_general_call;
u32 ic_enable_status; /* 0x9c */
+ u32 fs_spklen;
+ u32 hs_spklen;
+ u32 clr_restart_det;
+ u8 reserved[0xf4 - 0xac];
+ u32 comp_param1; /* 0xf4 */
+ u32 comp_version;
+ u32 comp_type;
};
-#if !defined(IC_CLK)
-#define IC_CLK 166
-#endif
-#define NANO_TO_MICRO 1000
+#define IC_CLK 166666666
+#define NANO_TO_KILO 1000000
/* High and low times in different speed modes (in ns) */
#define MIN_SS_SCL_HIGHTIME 4000
#define MIN_SS_SCL_LOWTIME 4700
#define MIN_FS_SCL_HIGHTIME 600
#define MIN_FS_SCL_LOWTIME 1300
+#define MIN_FP_SCL_HIGHTIME 260
+#define MIN_FP_SCL_LOWTIME 500
#define MIN_HS_SCL_HIGHTIME 60
#define MIN_HS_SCL_LOWTIME 160
@@ -124,19 +138,10 @@ struct i2c_regs {
#define IC_STATUS_TFNF 0x0002
#define IC_STATUS_ACT 0x0001
-/* Speed Selection */
-#define IC_SPEED_MODE_STANDARD 1
-#define IC_SPEED_MODE_FAST 2
-#define IC_SPEED_MODE_MAX 3
-
-#define I2C_MAX_SPEED 3400000
-#define I2C_FAST_SPEED 400000
-#define I2C_STANDARD_SPEED 100000
-
/**
* struct dw_scl_sda_cfg - I2C timing configuration
*
- * @has_max_speed: Support maximum speed (1Mbps)
+ * @has_high_speed: Support high speed (3.4Mbps)
* @ss_hcnt: Standard speed high time in ns
* @fs_hcnt: Fast speed high time in ns
* @ss_lcnt: Standard speed low time in ns
@@ -144,7 +149,7 @@ struct i2c_regs {
* @sda_hold: SDA hold time
*/
struct dw_scl_sda_cfg {
- bool has_max_speed;
+ bool has_high_speed;
u32 ss_hcnt;
u32 fs_hcnt;
u32 ss_lcnt;
@@ -152,10 +157,45 @@ struct dw_scl_sda_cfg {
u32 sda_hold;
};
+/**
+ * struct dw_i2c_speed_config - timings to use for a particular speed
+ *
+ * This holds calculated values to be written to the I2C controller. Each value
+ * is represented as a number of IC clock cycles.
+ *
+ * @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;
+};
+
+/**
+ * struct dw_i2c - private information for the bus
+ *
+ * @regs: Registers pointer
+ * @scl_sda_cfg: Deprecated information for x86 (should move to device tree)
+ * @resets: Resets for the I2C controller
+ * @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 {
struct i2c_regs *regs;
struct dw_scl_sda_cfg *scl_sda_cfg;
struct reset_ctl_bulk resets;
+ 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
@@ -165,5 +205,6 @@ extern const struct dm_i2c_ops designware_i2c_ops;
int designware_i2c_probe(struct udevice *bus);
int designware_i2c_remove(struct udevice *dev);
+int designware_i2c_ofdata_to_platdata(struct udevice *bus);
#endif /* __DW_I2C_H_ */
diff --git a/drivers/i2c/designware_i2c_pci.c b/drivers/i2c/designware_i2c_pci.c
index 7f0625df66..50f03e3d90 100644
--- a/drivers/i2c/designware_i2c_pci.c
+++ b/drivers/i2c/designware_i2c_pci.c
@@ -62,8 +62,10 @@ 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 0;
+ return designware_i2c_ofdata_to_platdata(dev);
}
static int designware_i2c_pci_probe(struct udevice *dev)
diff --git a/drivers/i2c/exynos_hs_i2c.c b/drivers/i2c/exynos_hs_i2c.c
index a0821c9257..9f201c66d0 100644
--- a/drivers/i2c/exynos_hs_i2c.c
+++ b/drivers/i2c/exynos_hs_i2c.c
@@ -527,8 +527,9 @@ static int s3c_i2c_ofdata_to_platdata(struct udevice *dev)
i2c_bus->id = pinmux_decode_periph_id(blob, node);
- i2c_bus->clock_frequency = fdtdec_get_int(blob, node,
- "clock-frequency", 100000);
+ i2c_bus->clock_frequency =
+ dev_read_u32_default(dev, "clock-frequency",
+ I2C_SPEED_STANDARD_RATE);
i2c_bus->node = node;
i2c_bus->bus_num = dev->seq;
diff --git a/drivers/i2c/fsl_i2c.c b/drivers/i2c/fsl_i2c.c
index bbbd6ef5bf..097c54388f 100644
--- a/drivers/i2c/fsl_i2c.c
+++ b/drivers/i2c/fsl_i2c.c
@@ -584,7 +584,8 @@ static int fsl_i2c_ofdata_to_platdata(struct udevice *bus)
dev->index = dev_read_u32_default(bus, "cell-index", -1);
dev->slaveadd = dev_read_u32_default(bus, "u-boot,i2c-slave-addr",
0x7f);
- dev->speed = dev_read_u32_default(bus, "clock-frequency", 400000);
+ dev->speed = dev_read_u32_default(bus, "clock-frequency",
+ I2C_SPEED_FAST_RATE);
if (!clk_get_by_index(bus, 0, &clock))
dev->i2c_clk = clk_get_rate(&clock);
diff --git a/drivers/i2c/i2c-cdns.c b/drivers/i2c/i2c-cdns.c
index ff3956d8c2..ac15da2c67 100644
--- a/drivers/i2c/i2c-cdns.c
+++ b/drivers/i2c/i2c-cdns.c
@@ -213,7 +213,7 @@ static int cdns_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
unsigned long speed_p = speed;
int ret = 0;
- if (speed > 400000) {
+ if (speed > I2C_SPEED_FAST_RATE) {
debug("%s, failed to set clock speed to %u\n", __func__,
speed);
return -EINVAL;
diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c
index fe77e64619..2aa3efe8aa 100644
--- a/drivers/i2c/i2c-uclass.c
+++ b/drivers/i2c/i2c-uclass.c
@@ -641,7 +641,8 @@ static int i2c_post_probe(struct udevice *dev)
#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
struct dm_i2c_bus *i2c = dev_get_uclass_priv(dev);
- i2c->speed_hz = dev_read_u32_default(dev, "clock-frequency", 100000);
+ i2c->speed_hz = dev_read_u32_default(dev, "clock-frequency",
+ I2C_SPEED_STANDARD_RATE);
return dm_i2c_set_bus_speed(dev, i2c->speed_hz);
#else
@@ -699,11 +700,10 @@ int i2c_uclass_init(struct uclass *class)
return -ENOMEM;
/* Get the last allocated alias. */
-#if CONFIG_IS_ENABLED(OF_CONTROL)
- priv->max_id = dev_read_alias_highest_id("i2c");
-#else
- priv->max_id = -1;
-#endif
+ if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA))
+ priv->max_id = dev_read_alias_highest_id("i2c");
+ else
+ priv->max_id = -1;
debug("%s: highest alias id is %d\n", __func__, priv->max_id);
diff --git a/drivers/i2c/i2c-uniphier-f.c b/drivers/i2c/i2c-uniphier-f.c
index ced606bf36..62acd28e1b 100644
--- a/drivers/i2c/i2c-uniphier-f.c
+++ b/drivers/i2c/i2c-uniphier-f.c
@@ -281,7 +281,7 @@ static int uniphier_fi2c_set_bus_speed(struct udevice *bus, unsigned int speed)
struct uniphier_fi2c_regs __iomem *regs = priv->regs;
/* max supported frequency is 400 kHz */
- if (speed > 400000)
+ if (speed > I2C_SPEED_FAST_RATE)
return -EINVAL;
ret = uniphier_fi2c_check_bus_busy(priv);
diff --git a/drivers/i2c/i2c-uniphier.c b/drivers/i2c/i2c-uniphier.c
index e427415e7e..07a7e03033 100644
--- a/drivers/i2c/i2c-uniphier.c
+++ b/drivers/i2c/i2c-uniphier.c
@@ -177,7 +177,7 @@ static int uniphier_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
struct uniphier_i2c_priv *priv = dev_get_priv(bus);
/* max supported frequency is 400 kHz */
- if (speed > 400000)
+ if (speed > I2C_SPEED_FAST_RATE)
return -EINVAL;
/* bus reset: make sure the bus is idle when change the frequency */
diff --git a/drivers/i2c/imx_lpi2c.c b/drivers/i2c/imx_lpi2c.c
index 2de99d019e..c9d3faa911 100644
--- a/drivers/i2c/imx_lpi2c.c
+++ b/drivers/i2c/imx_lpi2c.c
@@ -169,7 +169,7 @@ static int bus_i2c_start(struct udevice *bus, u8 addr, u8 dir)
debug("i2c: start check busy bus: 0x%x\n", result);
/* Try to init the lpi2c then check the bus busy again */
- bus_i2c_init(bus, 100000);
+ bus_i2c_init(bus, I2C_SPEED_STANDARD_RATE);
result = imx_lpci2c_check_busy_bus(regs);
if (result) {
printf("i2c: Error check busy bus: 0x%x\n", result);
@@ -388,13 +388,13 @@ static int imx_lpi2c_probe_chip(struct udevice *bus, u32 chip,
result = bus_i2c_start(bus, chip, 0);
if (result) {
bus_i2c_stop(bus);
- bus_i2c_init(bus, 100000);
+ bus_i2c_init(bus, I2C_SPEED_STANDARD_RATE);
return result;
}
result = bus_i2c_stop(bus);
if (result)
- bus_i2c_init(bus, 100000);
+ bus_i2c_init(bus, I2C_SPEED_STANDARD_RATE);
return result;
}
@@ -489,7 +489,7 @@ static int imx_lpi2c_probe(struct udevice *bus)
return ret;
}
- ret = bus_i2c_init(bus, 100000);
+ ret = bus_i2c_init(bus, I2C_SPEED_STANDARD_RATE);
if (ret < 0)
return ret;
diff --git a/drivers/i2c/kona_i2c.c b/drivers/i2c/kona_i2c.c
index d13e4deee5..0726b4c956 100644
--- a/drivers/i2c/kona_i2c.c
+++ b/drivers/i2c/kona_i2c.c
@@ -98,12 +98,6 @@ enum bcm_kona_cmd_t {
BCM_CMD_STOP,
};
-enum bus_speed_index {
- BCM_SPD_100K = 0,
- BCM_SPD_400K,
- BCM_SPD_1MHZ,
-};
-
/* Internal divider settings for standard mode, fast mode and fast mode plus */
struct bus_speed_cfg {
uint8_t time_m; /* Number of cycles for setup time */
@@ -115,9 +109,9 @@ struct bus_speed_cfg {
};
static const struct bus_speed_cfg std_cfg_table[] = {
- [BCM_SPD_100K] = {0x01, 0x01, 0x03, 0x06, 0x00, 0x02},
- [BCM_SPD_400K] = {0x05, 0x01, 0x03, 0x05, 0x01, 0x02},
- [BCM_SPD_1MHZ] = {0x01, 0x01, 0x03, 0x01, 0x01, 0x03},
+ [IC_SPEED_MODE_STANDARD] = {0x01, 0x01, 0x03, 0x06, 0x00, 0x02},
+ [IC_SPEED_MODE_FAST] = {0x05, 0x01, 0x03, 0x05, 0x01, 0x02},
+ [IC_SPEED_MODE_FAST_PLUS] = {0x01, 0x01, 0x03, 0x01, 0x01, 0x03},
};
struct bcm_kona_i2c_dev {
@@ -127,8 +121,8 @@ struct bcm_kona_i2c_dev {
};
/* Keep these two defines in sync */
-#define DEF_SPD 100000
-#define DEF_SPD_ENUM BCM_SPD_100K
+#define DEF_SPD I2C_SPEED_STANDARD_RATE
+#define DEF_SPD_ENUM IC_SPEED_MODE_STANDARD
#define DEF_DEVICE(num) \
{(void *)CONFIG_SYS_I2C_BASE##num, DEF_SPD, &std_cfg_table[DEF_SPD_ENUM]}
@@ -560,14 +554,14 @@ static uint bcm_kona_i2c_assign_bus_speed(struct bcm_kona_i2c_dev *dev,
uint speed)
{
switch (speed) {
- case 100000:
- dev->std_cfg = &std_cfg_table[BCM_SPD_100K];
+ case I2C_SPEED_STANDARD_RATE:
+ dev->std_cfg = &std_cfg_table[IC_SPEED_MODE_STANDARD];
break;
- case 400000:
- dev->std_cfg = &std_cfg_table[BCM_SPD_400K];
+ case I2C_SPEED_FAST_RATE:
+ dev->std_cfg = &std_cfg_table[IC_SPEED_MODE_FAST];
break;
- case 1000000:
- dev->std_cfg = &std_cfg_table[BCM_SPD_1MHZ];
+ case I2C_SPEED_FAST_PLUS_RATE:
+ dev->std_cfg = &std_cfg_table[IC_SPEED_MODE_FAST_PLUS];
break;
default:
printf("%d hz bus speed not supported\n", speed);
diff --git a/drivers/i2c/mv_i2c.c b/drivers/i2c/mv_i2c.c
index 8a56ef9a24..63665f0952 100644
--- a/drivers/i2c/mv_i2c.c
+++ b/drivers/i2c/mv_i2c.c
@@ -434,7 +434,7 @@ void i2c_init(int speed, int slaveaddr)
base_glob = (struct mv_i2c *)CONFIG_MV_I2C_REG;
#endif
- if (speed > 100000)
+ if (speed > I2C_SPEED_STANDARD_RATE)
val = ICR_FM;
else
val = ICR_SM;
@@ -565,7 +565,7 @@ static int mv_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
struct mv_i2c_priv *priv = dev_get_priv(bus);
u32 val;
- if (speed > 100000)
+ if (speed > I2C_SPEED_STANDARD_RATE)
val = ICR_FM;
else
val = ICR_SM;
diff --git a/drivers/i2c/mvtwsi.c b/drivers/i2c/mvtwsi.c
index 0a2dafcec6..382cf4b304 100644
--- a/drivers/i2c/mvtwsi.c
+++ b/drivers/i2c/mvtwsi.c
@@ -805,8 +805,9 @@ static int mvtwsi_i2c_ofdata_to_platdata(struct udevice *bus)
"cell-index", -1);
dev->slaveadd = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
"u-boot,i2c-slave-addr", 0x0);
- dev->speed = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
- "clock-frequency", 100000);
+ dev->speed = dev_read_u32_default(bus, "clock-frequency",
+ I2C_SPEED_STANDARD_RATE);
+
return 0;
}
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 4b93e02bbe..6e7d24d727 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -306,7 +306,7 @@ static int __omap24_i2c_setspeed(void __iomem *i2c_base, int ip_rev, uint speed,
int hsscll = 0, hssclh = 0;
u32 scll = 0, sclh = 0;
- if (speed >= OMAP_I2C_HIGH_SPEED) {
+ if (speed >= I2C_SPEED_HIGH_RATE) {
/* High speed */
psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK;
psc -= 1;
@@ -1066,7 +1066,8 @@ static int omap_i2c_ofdata_to_platdata(struct udevice *bus)
struct omap_i2c_platdata *plat = dev_get_platdata(bus);
plat->base = devfdt_get_addr(bus);
- plat->speed = dev_read_u32_default(bus, "clock-frequency", 100000);
+ plat->speed = dev_read_u32_default(bus, "clock-frequency",
+ I2C_SPEED_STANDARD_RATE);
plat->ip_rev = dev_get_driver_data(bus);
return 0;
diff --git a/drivers/i2c/omap24xx_i2c.h b/drivers/i2c/omap24xx_i2c.h
index 3458cf3a7d..6904f2d9ad 100644
--- a/drivers/i2c/omap24xx_i2c.h
+++ b/drivers/i2c/omap24xx_i2c.h
@@ -81,10 +81,6 @@
#define I2C_SCLH_HSSCLH 8
#define I2C_SCLH_HSSCLH_M 0xFF
-#define OMAP_I2C_STANDARD 100000
-#define OMAP_I2C_FAST_MODE 400000
-#define OMAP_I2C_HIGH_SPEED 3400000
-
#define SYSTEM_CLOCK_12 12000000
#define SYSTEM_CLOCK_13 13000000
#define SYSTEM_CLOCK_192 19200000
diff --git a/drivers/i2c/rcar_i2c.c b/drivers/i2c/rcar_i2c.c
index 2ebae349ed..05d0dc6012 100644
--- a/drivers/i2c/rcar_i2c.c
+++ b/drivers/i2c/rcar_i2c.c
@@ -344,7 +344,7 @@ static int rcar_i2c_probe(struct udevice *dev)
writel(0, priv->base + RCAR_I2C_ICMSR);
writel(0, priv->base + RCAR_I2C_ICMAR);
- ret = rcar_i2c_set_speed(dev, 100000);
+ ret = rcar_i2c_set_speed(dev, I2C_SPEED_STANDARD_RATE);
if (ret)
clk_disable(&priv->clk);
diff --git a/drivers/i2c/rcar_iic.c b/drivers/i2c/rcar_iic.c
index 9d45f547d1..2a82eb0b76 100644
--- a/drivers/i2c/rcar_iic.c
+++ b/drivers/i2c/rcar_iic.c
@@ -248,7 +248,7 @@ static int rcar_iic_probe(struct udevice *dev)
rcar_iic_finish(dev);
- return rcar_iic_set_speed(dev, 100000);
+ return rcar_iic_set_speed(dev, I2C_SPEED_STANDARD_RATE);
}
static const struct dm_i2c_ops rcar_iic_ops = {
diff --git a/drivers/i2c/s3c24x0_i2c.c b/drivers/i2c/s3c24x0_i2c.c
index ad0bc69fa3..68bf93b324 100644
--- a/drivers/i2c/s3c24x0_i2c.c
+++ b/drivers/i2c/s3c24x0_i2c.c
@@ -313,8 +313,9 @@ static int s3c_i2c_ofdata_to_platdata(struct udevice *dev)
i2c_bus->id = pinmux_decode_periph_id(blob, node);
- i2c_bus->clock_frequency = fdtdec_get_int(blob, node,
- "clock-frequency", 100000);
+ i2c_bus->clock_frequency =
+ dev_read_u32_default(dev, "clock-frequency",
+ I2C_SPEED_STANDARD_RATE);
i2c_bus->node = node;
i2c_bus->bus_num = dev->seq;
diff --git a/drivers/i2c/sandbox_i2c.c b/drivers/i2c/sandbox_i2c.c
index 0dbbaa0c44..1a4521d5b8 100644
--- a/drivers/i2c/sandbox_i2c.c
+++ b/drivers/i2c/sandbox_i2c.c
@@ -72,7 +72,8 @@ static int sandbox_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
* 400KHz for reads.
*/
is_read = nmsgs > 1;
- if (i2c->speed_hz > (is_read ? 400000 : 100000)) {
+ if (i2c->speed_hz > (is_read ? I2C_SPEED_FAST_RATE :
+ I2C_SPEED_STANDARD_RATE)) {
debug("%s: Max speed exceeded\n", __func__);
return -EINVAL;
}
diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c
index 2b18735fea..21dfa5023b 100644
--- a/drivers/i2c/stm32f7_i2c.c
+++ b/drivers/i2c/stm32f7_i2c.c
@@ -115,17 +115,6 @@ struct stm32_i2c_regs {
#define STM32_NSEC_PER_SEC 1000000000L
-#define STANDARD_RATE 100000
-#define FAST_RATE 400000
-#define FAST_PLUS_RATE 1000000
-
-enum stm32_i2c_speed {
- STM32_I2C_SPEED_STANDARD, /* 100 kHz */
- STM32_I2C_SPEED_FAST, /* 400 kHz */
- STM32_I2C_SPEED_FAST_PLUS, /* 1 MHz */
- STM32_I2C_SPEED_END,
-};
-
/**
* struct stm32_i2c_spec - private i2c specification timing
* @rate: I2C bus speed (Hz)
@@ -164,7 +153,7 @@ struct stm32_i2c_spec {
* @analog_filter: Analog filter delay (On/Off)
*/
struct stm32_i2c_setup {
- enum stm32_i2c_speed speed;
+ enum i2c_speed_mode speed;
u32 speed_freq;
u32 clock_src;
u32 rise_time;
@@ -198,8 +187,8 @@ struct stm32_i2c_priv {
};
static const struct stm32_i2c_spec i2c_specs[] = {
- [STM32_I2C_SPEED_STANDARD] = {
- .rate = STANDARD_RATE,
+ [IC_SPEED_MODE_STANDARD] = {
+ .rate = I2C_SPEED_STANDARD_RATE,
.rate_min = 8000,
.rate_max = 120000,
.fall_max = 300,
@@ -210,8 +199,8 @@ static const struct stm32_i2c_spec i2c_specs[] = {
.l_min = 4700,
.h_min = 4000,
},
- [STM32_I2C_SPEED_FAST] = {
- .rate = FAST_RATE,
+ [IC_SPEED_MODE_FAST] = {
+ .rate = I2C_SPEED_FAST_RATE,
.rate_min = 320000,
.rate_max = 480000,
.fall_max = 300,
@@ -222,8 +211,8 @@ static const struct stm32_i2c_spec i2c_specs[] = {
.l_min = 1300,
.h_min = 600,
},
- [STM32_I2C_SPEED_FAST_PLUS] = {
- .rate = FAST_PLUS_RATE,
+ [IC_SPEED_MODE_FAST_PLUS] = {
+ .rate = I2C_SPEED_FAST_PLUS_RATE,
.rate_min = 800000,
.rate_max = 1200000,
.fall_max = 100,
@@ -648,9 +637,9 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv,
struct list_head solutions;
int ret;
- if (setup->speed >= STM32_I2C_SPEED_END) {
+ if (setup->speed >= ARRAY_SIZE(i2c_specs)) {
pr_err("%s: speed out of bound {%d/%d}\n", __func__,
- setup->speed, STM32_I2C_SPEED_END - 1);
+ setup->speed, ARRAY_SIZE(i2c_specs) - 1);
return -EINVAL;
}
@@ -719,7 +708,7 @@ static int stm32_i2c_setup_timing(struct stm32_i2c_priv *i2c_priv,
if (ret) {
debug("%s: failed to compute I2C timings.\n",
__func__);
- if (i2c_priv->speed > STM32_I2C_SPEED_STANDARD) {
+ if (i2c_priv->speed > IC_SPEED_MODE_STANDARD) {
i2c_priv->speed--;
setup->speed = i2c_priv->speed;
setup->speed_freq =
@@ -784,14 +773,14 @@ static int stm32_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
struct stm32_i2c_priv *i2c_priv = dev_get_priv(bus);
switch (speed) {
- case STANDARD_RATE:
- i2c_priv->speed = STM32_I2C_SPEED_STANDARD;
+ case I2C_SPEED_STANDARD_RATE:
+ i2c_priv->speed = IC_SPEED_MODE_STANDARD;
break;
- case FAST_RATE:
- i2c_priv->speed = STM32_I2C_SPEED_FAST;
+ case I2C_SPEED_FAST_RATE:
+ i2c_priv->speed = IC_SPEED_MODE_FAST;
break;
- case FAST_PLUS_RATE:
- i2c_priv->speed = STM32_I2C_SPEED_FAST_PLUS;
+ case I2C_SPEED_FAST_PLUS_RATE:
+ i2c_priv->speed = IC_SPEED_MODE_FAST_PLUS;
break;
default:
debug("%s: Speed %d not supported\n", __func__, speed);