summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2020-01-23 11:48:13 -0700
committerHeiko Schocher <hs@denx.de>2020-01-27 07:21:36 +0100
commit31adb873e7a8680f8aac8ba259717b3f2265872e (patch)
tree6a993a1b6a0720051f772e9af4127561a26ecb5b /drivers
parentd22409e2dc7adfaf99c1a5a02902a425f98fd15a (diff)
i2c: designware_i2c: Put hold config in a struct
Create a struct to hold the three timing parameters. This will make it easier to move these calculations into a separate function in a later patch. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Heiko Schocher <hs@denx.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/designware_i2c.c82
1 files changed, 55 insertions, 27 deletions
diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 6e5545cd0c..e50987a717 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -13,6 +13,23 @@
#include <asm/io.h>
#include "designware_i2c.h"
+/**
+ * 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
+ */
+struct dw_i2c_speed_config {
+ /* SCL high and low period count */
+ uint scl_lcnt;
+ uint scl_hcnt;
+ uint sda_hold;
+};
+
#ifdef CONFIG_SYS_I2C_DW_ENABLE_STATUS_UNSUPPORTED
static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
{
@@ -58,10 +75,10 @@ static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
unsigned int bus_clk)
{
const struct dw_scl_sda_cfg *scl_sda_cfg = NULL;
+ struct dw_i2c_speed_config config;
ulong bus_khz = bus_clk / 1000;
enum i2c_speed_mode i2c_spd;
unsigned int cntl;
- unsigned int hcnt, lcnt;
unsigned int ena;
if (priv)
@@ -83,53 +100,64 @@ static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
cntl = (readl(&i2c_base->ic_con) & (~IC_CON_SPD_MSK));
+ config.scl_hcnt = 0;
+ config.scl_lcnt = 0;
+ config.sda_hold = 0;
+ 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;
+ }
+ }
+
switch (i2c_spd) {
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_khz * MIN_HS_SCL_HIGHTIME) / NANO_TO_KILO;
- lcnt = (bus_khz * MIN_HS_SCL_LOWTIME) / NANO_TO_KILO;
+ if (!scl_sda_cfg) {
+ config.scl_hcnt = (bus_khz * MIN_HS_SCL_HIGHTIME) /
+ NANO_TO_KILO;
+ config.scl_lcnt = (bus_khz * MIN_HS_SCL_LOWTIME) /
+ NANO_TO_KILO;
}
- 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_khz * MIN_SS_SCL_HIGHTIME) / NANO_TO_KILO;
- lcnt = (bus_khz * MIN_SS_SCL_LOWTIME) / NANO_TO_KILO;
+ if (!scl_sda_cfg) {
+ config.scl_hcnt = (bus_khz * MIN_SS_SCL_HIGHTIME) /
+ NANO_TO_KILO;
+ config.scl_lcnt = (bus_khz * MIN_SS_SCL_LOWTIME) /
+ NANO_TO_KILO;
}
- 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:
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_khz * MIN_FS_SCL_HIGHTIME) / NANO_TO_KILO;
- lcnt = (bus_khz * MIN_FS_SCL_LOWTIME) / NANO_TO_KILO;
+ if (!scl_sda_cfg) {
+ config.scl_hcnt = (bus_khz * MIN_FS_SCL_HIGHTIME) /
+ NANO_TO_KILO;
+ config.scl_lcnt = (bus_khz * MIN_FS_SCL_LOWTIME) /
+ NANO_TO_KILO;
}
- 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)