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
This commit is contained in:
Tom Rini 2020-01-29 09:34:13 -05:00
commit e7ab1cb3f0
25 changed files with 454 additions and 164 deletions

View File

@ -0,0 +1,73 @@
* Synopsys DesignWare I2C
Required properties :
- compatible : should be "snps,designware-i2c"
or "mscc,ocelot-i2c" with "snps,designware-i2c" for fallback
- reg : Offset and length of the register set for the device
- interrupts : <IRQ> where IRQ is the interrupt number.
- clocks : phandles for the clocks, see the description of clock-names below.
The phandle for the "ic_clk" clock is required. The phandle for the "pclk"
clock is optional. If a single clock is specified but no clock-name, it is
the "ic_clk" clock. If both clocks are listed, the "ic_clk" must be first.
Recommended properties :
- clock-frequency : desired I2C bus clock frequency in Hz.
Optional properties :
- clock-names : Contains the names of the clocks:
"ic_clk", for the core clock used to generate the external I2C clock.
"pclk", the interface clock, required for register access.
- reg : for "mscc,ocelot-i2c", a second register set to configure the SDA hold
time, named ICPU_CFG:TWI_DELAY in the datasheet.
- i2c-sda-hold-time-ns : should contain the SDA hold time in nanoseconds.
This option is only supported in hardware blocks version 1.11a or newer and
on Microsemi SoCs ("mscc,ocelot-i2c" compatible).
- i2c-scl-falling-time-ns : should contain the SCL falling time in nanoseconds.
This value which is by default 300ns is used to compute the tLOW period.
- i2c-sda-falling-time-ns : should contain the SDA falling time in nanoseconds.
This value which is by default 300ns is used to compute the tHIGH period.
Examples :
i2c@f0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,designware-i2c";
reg = <0xf0000 0x1000>;
interrupts = <11>;
clock-frequency = <400000>;
};
i2c@1120000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,designware-i2c";
reg = <0x1120000 0x1000>;
interrupt-parent = <&ictl>;
interrupts = <12 1>;
clock-frequency = <400000>;
i2c-sda-hold-time-ns = <300>;
i2c-sda-falling-time-ns = <300>;
i2c-scl-falling-time-ns = <300>;
};x
i2c@1120000 {
#address-cells = <1>;
#size-cells = <0>;
reg = <0x2000 0x100>;
clock-frequency = <400000>;
clocks = <&i2cclk>;
interrupts = <0>;
eeprom@64 {
compatible = "linux,slave-24c02";
reg = <0x40000064>;
};
};

View File

@ -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

View File

@ -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_ */

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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)

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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 = {

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -89,9 +89,6 @@ typedef struct global_data {
#endif
#if defined(CONFIG_SYS_I2C)
int cur_i2c_bus; /* current used i2c bus */
#endif
#ifdef CONFIG_SYS_I2C_MXC
void *srdata[10];
#endif
unsigned int timebase_h;
unsigned int timebase_l;

View File

@ -30,6 +30,32 @@ enum dm_i2c_chip_flags {
DM_I2C_CHIP_WR_ADDRESS = 1 << 2, /* Send address for each write byte */
};
/** enum i2c_speed_mode - standard I2C speed modes */
enum i2c_speed_mode {
IC_SPEED_MODE_STANDARD,
IC_SPEED_MODE_FAST,
IC_SPEED_MODE_FAST_PLUS,
IC_SPEED_MODE_HIGH,
IC_SPEED_MODE_FAST_ULTRA,
IC_SPEED_MODE_COUNT,
};
/** enum i2c_speed_rate - standard I2C speeds in Hz */
enum i2c_speed_rate {
I2C_SPEED_STANDARD_RATE = 100000,
I2C_SPEED_FAST_RATE = 400000,
I2C_SPEED_FAST_PLUS_RATE = 1000000,
I2C_SPEED_HIGH_RATE = 3400000,
I2C_SPEED_FAST_ULTRA_RATE = 5000000,
};
/** enum i2c_address_mode - available address modes */
enum i2c_address_mode {
I2C_MODE_7_BIT,
I2C_MODE_10_BIT
};
struct udevice;
/**
* struct dm_i2c_chip - information about an i2c chip