// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2009
- * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com.
+ * Vipin Kumar, STMicroelectronics, vipin.kumar@st.com.
*/
#include <common.h>
*/
#define DW_I2C_COMP_TYPE 0x44570140
-#ifdef CONFIG_SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
-static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
-{
- u32 ena = enable ? IC_ENABLE_0B : 0;
-
- writel(ena, &i2c_base->ic_enable);
-
- return 0;
-}
-#else
static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
{
u32 ena = enable ? IC_ENABLE_0B : 0;
return -ETIMEDOUT;
}
-#endif
/* High and low times in different speed modes (in ns) */
enum {
*
* @ic_clk: Input clock in Hz
* @period_ns: Period to represent, in ns
- * @return calculated count
+ * Return: calculated count
*/
static uint calc_counts(uint ic_clk, uint period_ns)
{
* @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
+ * 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,
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);
+ debug("dw_i2c: mode %d, ic_clk %d, speed %d, period %d rise %d fall %d tlow %d thigh %d spk %d\n",
+ mode, ic_clk, info->speed, 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:
if (hcnt < 0 || lcnt < 0) {
debug("dw_i2c: bad counts. hcnt = %d lcnt = %d\n", hcnt, lcnt);
- return -EINVAL;
+ return log_msg_ret("counts", -EINVAL);
}
/*
* @speed: Required i2c speed in Hz
* @bus_clk: Input clock to the I2C controller in Hz (e.g. IC_CLK)
* @config: Returns the config to use for this speed
- * @return 0 if OK, -ve on error
+ * Return: 0 if OK, -ve on error
*/
static int calc_bus_speed(struct dw_i2c *priv, struct i2c_regs *regs, int speed,
ulong bus_clk, struct dw_i2c_speed_config *config)
* @i2c_base: Registers for the I2C controller
* @speed: Required i2c speed in Hz
* @bus_clk: Input clock to the I2C controller in Hz (e.g. IC_CLK)
- * @return 0 if OK, -ve on error
+ * Return: 0 if OK, -ve on error
*/
static int _dw_i2c_set_bus_speed(struct dw_i2c *priv, struct i2c_regs *i2c_base,
unsigned int speed, unsigned int bus_clk)
/* Restore back i2c now speed set */
if (ena == IC_ENABLE_0B)
dw_i2c_enable(i2c_base, true);
+ if (priv)
+ priv->config = config;
+
+ return 0;
+}
+
+int dw_i2c_gen_speed_config(const struct udevice *dev, int speed_hz,
+ struct dw_i2c_speed_config *config)
+{
+ struct dw_i2c *priv = dev_get_priv(dev);
+ ulong rate;
+ int ret;
+
+#if CONFIG_IS_ENABLED(CLK)
+ rate = clk_get_rate(&priv->clk);
+ if (IS_ERR_VALUE(rate))
+ return log_msg_ret("clk", -EINVAL);
+#else
+ rate = IC_CLK;
+#endif
+
+ ret = calc_bus_speed(priv, priv->regs, speed_hz, rate, config);
+ if (ret)
+ printf("%s: ret=%d\n", __func__, ret);
+ if (ret)
+ return log_msg_ret("calc_bus_speed", ret);
return 0;
}
writel(IC_RX_TL, &i2c_base->ic_rx_tl);
writel(IC_TX_TL, &i2c_base->ic_tx_tl);
writel(IC_STOP_DET, &i2c_base->ic_intr_mask);
-#ifndef CONFIG_DM_I2C
+#if !CONFIG_IS_ENABLED(DM_I2C)
_dw_i2c_set_bus_speed(NULL, i2c_base, speed, IC_CLK);
writel(slaveaddr, &i2c_base->ic_sar);
#endif
return 0;
}
-#ifndef CONFIG_DM_I2C
+#if !CONFIG_IS_ENABLED(DM_I2C)
/*
* The legacy I2C functions. These need to get removed once
* all users of this driver are converted to DM.
dw_i2c_write, dw_i2c_set_bus_speed,
CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE, 0)
-#if CONFIG_SYS_I2C_BUS_MAX >= 2
-U_BOOT_I2C_ADAP_COMPLETE(dw_1, dw_i2c_init, dw_i2c_probe, dw_i2c_read,
- dw_i2c_write, dw_i2c_set_bus_speed,
- CONFIG_SYS_I2C_SPEED1, CONFIG_SYS_I2C_SLAVE1, 1)
-#endif
-
-#if CONFIG_SYS_I2C_BUS_MAX >= 3
-U_BOOT_I2C_ADAP_COMPLETE(dw_2, dw_i2c_init, dw_i2c_probe, dw_i2c_read,
- dw_i2c_write, dw_i2c_set_bus_speed,
- CONFIG_SYS_I2C_SPEED2, CONFIG_SYS_I2C_SLAVE2, 2)
-#endif
-
-#if CONFIG_SYS_I2C_BUS_MAX >= 4
-U_BOOT_I2C_ADAP_COMPLETE(dw_3, dw_i2c_init, dw_i2c_probe, dw_i2c_read,
- dw_i2c_write, dw_i2c_set_bus_speed,
- CONFIG_SYS_I2C_SPEED3, CONFIG_SYS_I2C_SLAVE3, 3)
-#endif
-
#else /* CONFIG_DM_I2C */
/* The DM I2C functions */
#if CONFIG_IS_ENABLED(CLK)
rate = clk_get_rate(&i2c->clk);
if (IS_ERR_VALUE(rate))
- return -EINVAL;
+ return log_ret(-EINVAL);
#else
rate = IC_CLK;
#endif
return ret;
}
-int designware_i2c_ofdata_to_platdata(struct udevice *bus)
+int designware_i2c_of_to_plat(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);
+ priv->regs = dev_read_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);
- else
+ if (ret) {
+ if (ret != -ENOTSUPP)
+ dev_warn(bus, "Can't get reset: %d\n", ret);
+ } else {
reset_deassert_bulk(&priv->resets);
+ }
#if CONFIG_IS_ENABLED(CLK)
ret = clk_get_by_index(bus, 0, &priv->clk);
return -ENXIO;
}
- log_info("I2C bus %s version %#x\n", bus->name,
- readl(&priv->regs->comp_version));
+ log_debug("I2C bus %s version %#x\n", bus->name,
+ readl(&priv->regs->comp_version));
return __dw_i2c_init(priv->regs, 0, 0);
}
.name = "i2c_designware",
.id = UCLASS_I2C,
.of_match = designware_i2c_ids,
- .ofdata_to_platdata = designware_i2c_ofdata_to_platdata,
+ .of_to_plat = designware_i2c_of_to_plat,
.probe = designware_i2c_probe,
- .priv_auto_alloc_size = sizeof(struct dw_i2c),
+ .priv_auto = sizeof(struct dw_i2c),
.remove = designware_i2c_remove,
.flags = DM_FLAG_OS_PREPARE,
.ops = &designware_i2c_ops,