All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup
@ 2020-01-23 18:48 Simon Glass
  2020-01-23 18:48 ` [PATCH v3 01/23] i2c: designware_i2c: Add more registers Simon Glass
                   ` (23 more replies)
  0 siblings, 24 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

This series updates the Designware I2C driver to support reading its
timing from the device tree and handling it in units of nanoseconds
instead of clock cycles.

A new function converts from nanoseconds to the units used by the I2C
controller and makes sure that the requested bus speed is not exceeded.
This is more accurate than the existing method.

The series includes a few smaller clean-ups in the same driver.

In addition the v2 series adds enums for i2c speed and updates drivers to
use them.

There is currently an existing configuration method used just for a few
x86 boards (Baytrail). This method is retained but it should be removed in
favour of using the device tree. I have not done this in this series since
I am not sure of the timings to use.

Changes in v3:
- Fix the address of comp_param1 by adding a gap
- Drop note about moving to driver model
- Use ARRAY_SIZE() for i2c_specs bounds check
- Add new patch with support for fast-plus speed
- Add new patch to move dw_i2c_speed_config to header
- Add new patch to separate out the speed calculation
- Add new patch to do more in the probe() method

Changes in v2:
- Fix 'previde' typo
- Add a few more clean-up patches for i2c

Simon Glass (23):
  i2c: designware_i2c: Add more registers
  i2c: designware_i2c: Don't allow changing IC_CLK
  i2c: designware_i2c: Include clk.h in the header file
  i2c: designware_i2c: Rename 'max' speed to 'high' speed
  i2c: designware_i2c: Use an enum for selected speed mode
  i2c: designware_i2c: Use an accurate bus clock instead of MHz
  i2c: designware_i2c: Bring in the binding file
  i2c: designware_i2c: Read device-tree properties
  i2c: designware_i2c: Drop scl_sda_cfg parameter
  i2c: designware_i2c: Put hold config in a struct
  i2c: designware_i2c: Rewrite timing calculation
  i2c: designware_i2c: Add spike supression
  i2c: Add enums for i2c speed and address size
  i2c: ast_i2c: Update to use standard enums for speed
  i2c: designware_i2c: Update to use standard enums for speed
  i2c: kona_i2c: Update to use standard enums for speed
  i2c: omap: Update to use standard enums for speed
  i2c: stm32: Update to use standard enums for speed
  i2c: Update drivers to use enum for speed
  i2c: designware_i2c: Add support for fast-plus speed
  i2c: designware_i2c: Move dw_i2c_speed_config to header
  i2c: designware_i2c: Separate out the speed calculation
  i2c: designware_i2c: Do more in the probe() method

 .../i2c/i2c-designware.txt                    |  73 +++++
 drivers/i2c/ast_i2c.c                         |   2 +-
 drivers/i2c/ast_i2c.h                         |   2 -
 drivers/i2c/designware_i2c.c                  | 300 ++++++++++++++----
 drivers/i2c/designware_i2c.h                  |  73 ++++-
 drivers/i2c/designware_i2c_pci.c              |   4 +-
 drivers/i2c/exynos_hs_i2c.c                   |   5 +-
 drivers/i2c/fsl_i2c.c                         |   3 +-
 drivers/i2c/i2c-cdns.c                        |   2 +-
 drivers/i2c/i2c-uclass.c                      |  12 +-
 drivers/i2c/i2c-uniphier-f.c                  |   2 +-
 drivers/i2c/i2c-uniphier.c                    |   2 +-
 drivers/i2c/imx_lpi2c.c                       |   8 +-
 drivers/i2c/kona_i2c.c                        |  28 +-
 drivers/i2c/mv_i2c.c                          |   4 +-
 drivers/i2c/mvtwsi.c                          |   5 +-
 drivers/i2c/omap24xx_i2c.c                    |   5 +-
 drivers/i2c/omap24xx_i2c.h                    |   4 -
 drivers/i2c/rcar_i2c.c                        |   2 +-
 drivers/i2c/rcar_iic.c                        |   2 +-
 drivers/i2c/s3c24x0_i2c.c                     |   5 +-
 drivers/i2c/sandbox_i2c.c                     |   3 +-
 drivers/i2c/stm32f7_i2c.c                     |  43 +--
 include/i2c.h                                 |  26 ++
 24 files changed, 454 insertions(+), 161 deletions(-)
 create mode 100644 doc/device-tree-bindings/i2c/i2c-designware.txt

-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH v3 01/23] i2c: designware_i2c: Add more registers
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 02/23] i2c: designware_i2c: Don't allow changing IC_CLK Simon Glass
                   ` (22 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Some versions of this peripherals provide more control of the bus
behaviour. Add definitions for these registers.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Ley Foon Tan <ley.foon.tan@intel.com>
Reviewed-by: Jun Chen <ptchentw@gmail.com>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3:
- Fix the address of comp_param1 by adding a gap

Changes in v2:
- Fix 'previde' typo

 drivers/i2c/designware_i2c.h | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 48766d0806..3b407d2bed 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -43,8 +43,20 @@ 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)
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 02/23] i2c: designware_i2c: Don't allow changing IC_CLK
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
  2020-01-23 18:48 ` [PATCH v3 01/23] i2c: designware_i2c: Add more registers Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 03/23] i2c: designware_i2c: Include clk.h in the header file Simon Glass
                   ` (21 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

If a different input clock is required then the correct way to do this is
with a clock driver. Don't allow boards to override IC_CLK.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/designware_i2c.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 3b407d2bed..10fb7d7d3e 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -59,9 +59,7 @@ struct i2c_regs {
 	u32 comp_type;
 };
 
-#if !defined(IC_CLK)
 #define IC_CLK			166
-#endif
 #define NANO_TO_MICRO		1000
 
 /* High and low times in different speed modes (in ns) */
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 03/23] i2c: designware_i2c: Include clk.h in the header file
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
  2020-01-23 18:48 ` [PATCH v3 01/23] i2c: designware_i2c: Add more registers Simon Glass
  2020-01-23 18:48 ` [PATCH v3 02/23] i2c: designware_i2c: Don't allow changing IC_CLK Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 04/23] i2c: designware_i2c: Rename 'max' speed to 'high' speed Simon Glass
                   ` (20 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

We use struct clk here so really should include this header file to avoid
build errors. Also switch the order of clk.h in the C file to match the
required code style.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Ley Foon Tan <ley.foon.tan@intel.com>
Reviewed-by: Jun Chen <ptchentw@gmail.com>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/designware_i2c.c | 2 +-
 drivers/i2c/designware_i2c.h | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index b8cdd1c661..138fc72561 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -4,8 +4,8 @@
  * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.com.
  */
 
-#include <clk.h>
 #include <common.h>
+#include <clk.h>
 #include <dm.h>
 #include <i2c.h>
 #include <pci.h>
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 10fb7d7d3e..aade5c2da0 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -7,6 +7,7 @@
 #ifndef __DW_I2C_H_
 #define __DW_I2C_H_
 
+#include <clk.h>
 #include <reset.h>
 
 struct i2c_regs {
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 04/23] i2c: designware_i2c: Rename 'max' speed to 'high' speed
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (2 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 03/23] i2c: designware_i2c: Include clk.h in the header file Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 05/23] i2c: designware_i2c: Use an enum for selected speed mode Simon Glass
                   ` (19 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Some SoCs support a higher speed than what is currently called 'max' in
this driver. Rename it to 'high' speed, which is the official name of the
3.4MHz speed.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Jun Chen <ptchentw@gmail.com>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/designware_i2c.c | 10 +++++-----
 drivers/i2c/designware_i2c.h |  8 ++++----
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 138fc72561..dd1cc0b823 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -62,10 +62,10 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
 	unsigned int ena;
 	int i2c_spd;
 
-	/* 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;
+	/* Allow high speed if there is no config, or the config allows it */
+	if (speed >= I2C_HIGH_SPEED &&
+	    (!scl_sda_cfg || scl_sda_cfg->has_high_speed))
+		i2c_spd = IC_SPEED_MODE_HIGH;
 	else if (speed >= I2C_FAST_SPEED)
 		i2c_spd = IC_SPEED_MODE_FAST;
 	else
@@ -80,7 +80,7 @@ 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:
+	case IC_SPEED_MODE_HIGH:
 		cntl |= IC_CON_SPD_SS;
 		if (scl_sda_cfg) {
 			hcnt = scl_sda_cfg->fs_hcnt;
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index aade5c2da0..d4c1ca0cc3 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -138,16 +138,16 @@ struct i2c_regs {
 /* Speed Selection */
 #define IC_SPEED_MODE_STANDARD	1
 #define IC_SPEED_MODE_FAST	2
-#define IC_SPEED_MODE_MAX	3
+#define IC_SPEED_MODE_HIGH	3
 
-#define I2C_MAX_SPEED		3400000
+#define I2C_HIGH_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
@@ -155,7 +155,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;
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 05/23] i2c: designware_i2c: Use an enum for selected speed mode
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (3 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 04/23] i2c: designware_i2c: Rename 'max' speed to 'high' speed Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 06/23] i2c: designware_i2c: Use an accurate bus clock instead of MHz Simon Glass
                   ` (18 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Group these #defines into an enum to make it easier to understand the
relationship between them.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Jun Chen <ptchentw@gmail.com>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/designware_i2c.c |  2 +-
 drivers/i2c/designware_i2c.h | 10 +++++++---
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index dd1cc0b823..2416ef32f9 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -57,10 +57,10 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
 					   unsigned int speed,
 					   unsigned int bus_mhz)
 {
+	enum i2c_speed_mode i2c_spd;
 	unsigned int cntl;
 	unsigned int hcnt, lcnt;
 	unsigned int ena;
-	int i2c_spd;
 
 	/* Allow high speed if there is no config, or the config allows it */
 	if (speed >= I2C_HIGH_SPEED &&
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index d4c1ca0cc3..569cab6fd3 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -136,9 +136,13 @@ struct i2c_regs {
 #define IC_STATUS_ACT		0x0001
 
 /* Speed Selection */
-#define IC_SPEED_MODE_STANDARD	1
-#define IC_SPEED_MODE_FAST	2
-#define IC_SPEED_MODE_HIGH	3
+enum i2c_speed_mode {
+	IC_SPEED_MODE_STANDARD,
+	IC_SPEED_MODE_FAST,
+	IC_SPEED_MODE_HIGH,
+
+	IC_SPEED_MODE_COUNT,
+};
 
 #define I2C_HIGH_SPEED		3400000
 #define I2C_FAST_SPEED		400000
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 06/23] i2c: designware_i2c: Use an accurate bus clock instead of MHz
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (4 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 05/23] i2c: designware_i2c: Use an enum for selected speed mode Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 07/23] i2c: designware_i2c: Bring in the binding file Simon Glass
                   ` (17 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

At present the driver uses an approximation for the bus clock, e.g. 166MHz
instead of 166 2/3 MHz.

This can result in small errors in the resulting I2C speed, perhaps 0.5%
or so.

Adjust the existing code to start from the accurate figure, even if later
rounding reduces this accuracy.

Update the bus speed code to work in KHz instead of MHz, which removes
most of the error.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/designware_i2c.c | 18 ++++++++----------
 drivers/i2c/designware_i2c.h |  4 ++--
 2 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 2416ef32f9..0a1df8015f 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -55,8 +55,9 @@ static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
 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)
+					   unsigned int bus_clk)
 {
+	ulong bus_khz = bus_clk / 1000;
 	enum i2c_speed_mode i2c_spd;
 	unsigned int cntl;
 	unsigned int hcnt, lcnt;
@@ -86,8 +87,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
 			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;
+			hcnt = (bus_khz * MIN_HS_SCL_HIGHTIME) / NANO_TO_KILO;
+			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);
@@ -99,8 +100,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
 			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;
+			hcnt = (bus_khz * MIN_SS_SCL_HIGHTIME) / NANO_TO_KILO;
+			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);
@@ -113,8 +114,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct i2c_regs *i2c_base,
 			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;
+			hcnt = (bus_khz * MIN_FS_SCL_HIGHTIME) / NANO_TO_KILO;
+			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);
@@ -511,9 +512,6 @@ 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
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 569cab6fd3..5b477830d4 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -60,8 +60,8 @@ struct i2c_regs {
 	u32 comp_type;
 };
 
-#define IC_CLK			166
-#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
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 07/23] i2c: designware_i2c: Bring in the binding file
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (5 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 06/23] i2c: designware_i2c: Use an accurate bus clock instead of MHz Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 08/23] i2c: designware_i2c: Read device-tree properties Simon Glass
                   ` (16 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Bring in this file from Linux v5.4.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 .../i2c/i2c-designware.txt                    | 73 +++++++++++++++++++
 1 file changed, 73 insertions(+)
 create mode 100644 doc/device-tree-bindings/i2c/i2c-designware.txt

diff --git a/doc/device-tree-bindings/i2c/i2c-designware.txt b/doc/device-tree-bindings/i2c/i2c-designware.txt
new file mode 100644
index 0000000000..be766be812
--- /dev/null
+++ b/doc/device-tree-bindings/i2c/i2c-designware.txt
@@ -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 at f0000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "snps,designware-i2c";
+		reg = <0xf0000 0x1000>;
+		interrupts = <11>;
+		clock-frequency = <400000>;
+	};
+
+	i2c at 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 at 1120000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg = <0x2000 0x100>;
+		clock-frequency = <400000>;
+		clocks = <&i2cclk>;
+		interrupts = <0>;
+
+		eeprom at 64 {
+			compatible = "linux,slave-24c02";
+			reg = <0x40000064>;
+		};
+	};
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 08/23] i2c: designware_i2c: Read device-tree properties
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (6 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 07/23] i2c: designware_i2c: Bring in the binding file Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 09/23] i2c: designware_i2c: Drop scl_sda_cfg parameter Simon Glass
                   ` (15 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

The i2c controller defines a few timing properties. Read these in and
store them for use by the driver.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/designware_i2c.c     |  8 ++++++--
 drivers/i2c/designware_i2c.h     | 15 +++++++++++++++
 drivers/i2c/designware_i2c_pci.c |  2 +-
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 0a1df8015f..34b6816545 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -535,11 +535,15 @@ static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
 	return ret;
 }
 
-static int designware_i2c_ofdata_to_platdata(struct udevice *bus)
+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);
+	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);
 
 	return 0;
 }
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 5b477830d4..f32dc0f854 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -167,10 +167,24 @@ struct dw_scl_sda_cfg {
 	u32 sda_hold;
 };
 
+/**
+ * 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
+ * @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;
 #if CONFIG_IS_ENABLED(CLK)
 	struct clk clk;
 #endif
@@ -180,5 +194,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..2b974a07c3 100644
--- a/drivers/i2c/designware_i2c_pci.c
+++ b/drivers/i2c/designware_i2c_pci.c
@@ -63,7 +63,7 @@ static int designware_i2c_pci_ofdata_to_platdata(struct udevice *dev)
 		/* Use BayTrail specific timing values */
 		priv->scl_sda_cfg = &byt_config;
 
-	return 0;
+	return designware_i2c_ofdata_to_platdata(dev);
 }
 
 static int designware_i2c_pci_probe(struct udevice *dev)
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 09/23] i2c: designware_i2c: Drop scl_sda_cfg parameter
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (7 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 08/23] i2c: designware_i2c: Read device-tree properties Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 10/23] i2c: designware_i2c: Put hold config in a struct Simon Glass
                   ` (14 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Instead of passing this parameter into __dw_i2c_set_bus_speed(), pass in
the driver's private data, from which the function can obtain that
information. This allows the function to have access to the full state of
the driver.

Signed-off-by: Sicomp_param1mon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/designware_i2c.c | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 34b6816545..6e5545cd0c 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -52,17 +52,20 @@ static int dw_i2c_enable(struct i2c_regs *i2c_base, bool enable)
  *
  * 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,
+static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
+					   struct i2c_regs *i2c_base,
 					   unsigned int speed,
 					   unsigned int bus_clk)
 {
+	const struct dw_scl_sda_cfg *scl_sda_cfg = NULL;
 	ulong bus_khz = bus_clk / 1000;
 	enum i2c_speed_mode i2c_spd;
 	unsigned int cntl;
 	unsigned int hcnt, lcnt;
 	unsigned int ena;
 
+	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_HIGH_SPEED &&
 	    (!scl_sda_cfg || scl_sda_cfg->has_high_speed))
@@ -371,7 +374,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
 
@@ -416,7 +419,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)
@@ -515,8 +518,7 @@ static int designware_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
 #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,
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 10/23] i2c: designware_i2c: Put hold config in a struct
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (8 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 09/23] i2c: designware_i2c: Drop scl_sda_cfg parameter Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 11/23] i2c: designware_i2c: Rewrite timing calculation Simon Glass
                   ` (13 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

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

Changes in v3: None
Changes in v2: None

 drivers/i2c/designware_i2c.c | 82 ++++++++++++++++++++++++------------
 1 file 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)
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 11/23] i2c: designware_i2c: Rewrite timing calculation
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (9 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 10/23] i2c: designware_i2c: Put hold config in a struct Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 12/23] i2c: designware_i2c: Add spike supression Simon Glass
                   ` (12 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

At present the driver can end up with timing parameters which are slightly
faster than those expected. It is possible to optimise the parameters to
get the best possible result.

Create a new function to handle the timing calculation. This uses a table
of defaults for each speed mode rather than writing it in code.

The function works by calculating the 'period' of each bit on the bus in
terms of the input clock to the controller (IC_CLK). It makes sure that
the constraints are met and that the different components of that period
add up correctly.

This code was taken from coreboot which has ended up with this same
driver, but now in a much-different form.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/designware_i2c.c | 169 ++++++++++++++++++++++++++++++-----
 1 file changed, 147 insertions(+), 22 deletions(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index e50987a717..0069602103 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -63,6 +63,147 @@ 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_STANDARD_SPEED,
+		MIN_SS_SCL_HIGHTIME,
+		MIN_SS_SCL_LOWTIME,
+		1000,
+		300,
+	},
+	[IC_SPEED_MODE_FAST] = {
+		I2C_FAST_SPEED,
+		MIN_FS_SCL_HIGHTIME,
+		MIN_FS_SCL_LOWTIME,
+		300,
+		300,
+	},
+	[IC_SPEED_MODE_HIGH] = {
+		I2C_HIGH_SPEED,
+		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;
+}
+
 /*
  * i2c_set_bus_speed - Set the i2c speed
  * @speed:	required i2c speed
@@ -76,10 +217,10 @@ static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
 {
 	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 ena;
+	int ret;
 
 	if (priv)
 		scl_sda_cfg = priv->scl_sda_cfg;
@@ -100,9 +241,6 @@ 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) {
@@ -112,29 +250,22 @@ static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
 			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, 0,
+					 &config);
+		if (ret)
+			return log_msg_ret("gen_confg", ret);
 	}
 
 	switch (i2c_spd) {
 	case IC_SPEED_MODE_HIGH:
 		cntl |= IC_CON_SPD_SS;
-		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(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) {
-			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(config.scl_hcnt, &i2c_base->ic_ss_scl_hcnt);
 		writel(config.scl_lcnt, &i2c_base->ic_ss_scl_lcnt);
 		break;
@@ -142,12 +273,6 @@ static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
 	case IC_SPEED_MODE_FAST:
 	default:
 		cntl |= IC_CON_SPD_FS;
-		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(config.scl_hcnt, &i2c_base->ic_fs_scl_hcnt);
 		writel(config.scl_lcnt, &i2c_base->ic_fs_scl_lcnt);
 		break;
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 12/23] i2c: designware_i2c: Add spike supression
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (10 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 11/23] i2c: designware_i2c: Rewrite timing calculation Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 13/23] i2c: Add enums for i2c speed and address size Simon Glass
                   ` (11 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

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>

---

Changes in v3: None
Changes in v2:
- Add a few more clean-up patches for i2c

 drivers/i2c/designware_i2c.c     | 10 +++++++++-
 drivers/i2c/designware_i2c.h     |  2 ++
 drivers/i2c/designware_i2c_pci.c |  2 ++
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 0069602103..4aee25c543 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -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);
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index f32dc0f854..8789c7d8ce 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -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
diff --git a/drivers/i2c/designware_i2c_pci.c b/drivers/i2c/designware_i2c_pci.c
index 2b974a07c3..50f03e3d90 100644
--- a/drivers/i2c/designware_i2c_pci.c
+++ b/drivers/i2c/designware_i2c_pci.c
@@ -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);
 }
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 13/23] i2c: Add enums for i2c speed and address size
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (11 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 12/23] i2c: designware_i2c: Add spike supression Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 14/23] i2c: ast_i2c: Update to use standard enums for speed Simon Glass
                   ` (10 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Some drivers define their own speed enums and use their own constants for
speed. It makes sense to have a unified defition of the different speeds.

Since many controllers have to do different things for fast/high speed, it
is a good idea to have an enum for the mode.

Add these as well as an enum for the address mode.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 include/i2c.h | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/include/i2c.h b/include/i2c.h
index 72e2e8e426..0faf8542e2 100644
--- a/include/i2c.h
+++ b/include/i2c.h
@@ -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
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 14/23] i2c: ast_i2c: Update to use standard enums for speed
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (12 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 13/23] i2c: Add enums for i2c speed and address size Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 15/23] i2c: designware_i2c: " Simon Glass
                   ` (9 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Update this driver to use the new standard enums for speed.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/ast_i2c.c | 2 +-
 drivers/i2c/ast_i2c.h | 2 --
 2 files changed, 1 insertion(+), 3 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_ */
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 15/23] i2c: designware_i2c: Update to use standard enums for speed
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (13 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 14/23] i2c: ast_i2c: Update to use standard enums for speed Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 16/23] i2c: kona_i2c: " Simon Glass
                   ` (8 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Update this driver to use the new standard enums for speed.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/designware_i2c.c | 10 +++++-----
 drivers/i2c/designware_i2c.h | 13 -------------
 2 files changed, 5 insertions(+), 18 deletions(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 4aee25c543..1f41e3eae0 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -103,21 +103,21 @@ struct i2c_mode_info {
 
 static const struct i2c_mode_info info_for_mode[] = {
 	[IC_SPEED_MODE_STANDARD] = {
-		I2C_STANDARD_SPEED,
+		I2C_SPEED_STANDARD_RATE,
 		MIN_SS_SCL_HIGHTIME,
 		MIN_SS_SCL_LOWTIME,
 		1000,
 		300,
 	},
 	[IC_SPEED_MODE_FAST] = {
-		I2C_FAST_SPEED,
+		I2C_SPEED_FAST_RATE,
 		MIN_FS_SCL_HIGHTIME,
 		MIN_FS_SCL_LOWTIME,
 		300,
 		300,
 	},
 	[IC_SPEED_MODE_HIGH] = {
-		I2C_HIGH_SPEED,
+		I2C_SPEED_HIGH_RATE,
 		MIN_HS_SCL_HIGHTIME,
 		MIN_HS_SCL_LOWTIME,
 		120,
@@ -226,10 +226,10 @@ static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
 	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_HIGH_SPEED &&
+	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_FAST_SPEED)
+	else if (speed >= I2C_SPEED_FAST_RATE)
 		i2c_spd = IC_SPEED_MODE_FAST;
 	else
 		i2c_spd = IC_SPEED_MODE_STANDARD;
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 8789c7d8ce..5289ab0683 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -135,19 +135,6 @@ struct i2c_regs {
 #define IC_STATUS_TFNF		0x0002
 #define IC_STATUS_ACT		0x0001
 
-/* Speed Selection */
-enum i2c_speed_mode {
-	IC_SPEED_MODE_STANDARD,
-	IC_SPEED_MODE_FAST,
-	IC_SPEED_MODE_HIGH,
-
-	IC_SPEED_MODE_COUNT,
-};
-
-#define I2C_HIGH_SPEED		3400000
-#define I2C_FAST_SPEED		400000
-#define I2C_STANDARD_SPEED	100000
-
 /**
  * struct dw_scl_sda_cfg - I2C timing configuration
  *
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 16/23] i2c: kona_i2c: Update to use standard enums for speed
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (14 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 15/23] i2c: designware_i2c: " Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 17/23] i2c: omap: " Simon Glass
                   ` (7 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Update this driver to use the new standard enums for speed.

Note: This driver needs to move to driver model.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/kona_i2c.c | 28 +++++++++++-----------------
 1 file changed, 11 insertions(+), 17 deletions(-)

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);
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 17/23] i2c: omap: Update to use standard enums for speed
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (15 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 16/23] i2c: kona_i2c: " Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-24  3:21   ` Lokesh Vutla
  2020-01-23 18:48 ` [PATCH v3 18/23] i2c: stm32: " Simon Glass
                   ` (6 subsequent siblings)
  23 siblings, 1 reply; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Update this driver to use the new standard enums for speed.

Note: This driver needs to move to driver model.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/omap24xx_i2c.c | 2 +-
 drivers/i2c/omap24xx_i2c.h | 4 ----
 2 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
index 4b93e02bbe..7e6e3c4f81 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;
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
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 18/23] i2c: stm32: Update to use standard enums for speed
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (16 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 17/23] i2c: omap: " Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 19/23] i2c: Update drivers to use enum " Simon Glass
                   ` (5 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Update this driver to use the new standard enums for speed.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Patrick Delaunay <patrick.delaunay@st.com>
Tested-by: Patrick Delaunay <patrick.delaunay@st.com>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3:
- Drop note about moving to driver model
- Use ARRAY_SIZE() for i2c_specs bounds check

Changes in v2: None

 drivers/i2c/stm32f7_i2c.c | 43 +++++++++++++++------------------------
 1 file changed, 16 insertions(+), 27 deletions(-)

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);
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 19/23] i2c: Update drivers to use enum for speed
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (17 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 18/23] i2c: stm32: " Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 20/23] i2c: designware_i2c: Add support for fast-plus speed Simon Glass
                   ` (4 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Convert the obvious uses of i2c bus speeds to use the enum.

Use livetree access for code changes.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Heiko Schocher <hs@denx.de>
---

Changes in v3: None
Changes in v2: None

 drivers/i2c/exynos_hs_i2c.c  |  5 +++--
 drivers/i2c/fsl_i2c.c        |  3 ++-
 drivers/i2c/i2c-cdns.c       |  2 +-
 drivers/i2c/i2c-uclass.c     | 12 ++++++------
 drivers/i2c/i2c-uniphier-f.c |  2 +-
 drivers/i2c/i2c-uniphier.c   |  2 +-
 drivers/i2c/imx_lpi2c.c      |  8 ++++----
 drivers/i2c/mv_i2c.c         |  4 ++--
 drivers/i2c/mvtwsi.c         |  5 +++--
 drivers/i2c/omap24xx_i2c.c   |  3 ++-
 drivers/i2c/rcar_i2c.c       |  2 +-
 drivers/i2c/rcar_iic.c       |  2 +-
 drivers/i2c/s3c24x0_i2c.c    |  5 +++--
 drivers/i2c/sandbox_i2c.c    |  3 ++-
 14 files changed, 32 insertions(+), 26 deletions(-)

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/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 7e6e3c4f81..6e7d24d727 100644
--- a/drivers/i2c/omap24xx_i2c.c
+++ b/drivers/i2c/omap24xx_i2c.c
@@ -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/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;
 		}
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 20/23] i2c: designware_i2c: Add support for fast-plus speed
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (18 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 19/23] i2c: Update drivers to use enum " Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 21/23] i2c: designware_i2c: Move dw_i2c_speed_config to header Simon Glass
                   ` (3 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Fast-plus runs at 1MHz and is used by some devices. Add support for this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add new patch with support for fast-plus speed

Changes in v2: None

 drivers/i2c/designware_i2c.c | 12 ++++++++++--
 drivers/i2c/designware_i2c.h |  2 ++
 2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 1f41e3eae0..d9e0d81ff0 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -116,6 +116,13 @@ static const struct i2c_mode_info info_for_mode[] = {
 		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,
@@ -230,6 +237,8 @@ static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
 	    (!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;
@@ -271,13 +280,12 @@ static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
 		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;
 		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;
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 5289ab0683..3db63b5f95 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -68,6 +68,8 @@ struct i2c_regs {
 #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
 
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 21/23] i2c: designware_i2c: Move dw_i2c_speed_config to header
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (19 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 20/23] i2c: designware_i2c: Add support for fast-plus speed Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-23 18:48 ` [PATCH v3 22/23] i2c: designware_i2c: Separate out the speed calculation Simon Glass
                   ` (2 subsequent siblings)
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

This is used to store the speed information for a bus. We want to provide
this to ACPI so that it can tell the kernel. Move this struct to the
header file so it can be accessed by the ACPI i2c implementation being
added later.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add new patch to move dw_i2c_speed_config to header

Changes in v2: None

 drivers/i2c/designware_i2c.c | 17 -----------------
 drivers/i2c/designware_i2c.h | 17 +++++++++++++++++
 2 files changed, 17 insertions(+), 17 deletions(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index d9e0d81ff0..6be98ee43b 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -13,23 +13,6 @@
 #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)
 {
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 3db63b5f95..2027a91add 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -156,6 +156,23 @@ 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
+ */
+struct dw_i2c_speed_config {
+	/* SCL high and low period count */
+	u16 scl_lcnt;
+	u16 scl_hcnt;
+	u32 sda_hold;
+};
+
 /**
  * struct dw_i2c - private information for the bus
  *
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 22/23] i2c: designware_i2c: Separate out the speed calculation
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (20 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 21/23] i2c: designware_i2c: Move dw_i2c_speed_config to header Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-04-22  6:43   ` Heinrich Schuchardt
  2020-01-23 18:48 ` [PATCH v3 23/23] i2c: designware_i2c: Do more in the probe() method Simon Glass
  2020-01-29  6:00 ` [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Heiko Schocher
  23 siblings, 1 reply; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

We want to be able to calculate the speed separately from actually setting
the speed, so we can generate the required ACPI tables. Split out the
calculation into its own function.

Drop the double underscore on __dw_i2c_set_bus_speed while we are here.
That is reserved for compiler internals.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add new patch to separate out the speed calculation

Changes in v2: None

 drivers/i2c/designware_i2c.c | 78 +++++++++++++++++++++---------------
 drivers/i2c/designware_i2c.h |  3 ++
 2 files changed, 48 insertions(+), 33 deletions(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 6be98ee43b..39af25af9a 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -194,22 +194,12 @@ static int dw_i2c_calc_timing(struct dw_i2c *priv, enum i2c_speed_mode mode,
 	return 0;
 }
 
-/*
- * 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 dw_i2c *priv,
-					   struct i2c_regs *i2c_base,
-					   unsigned int speed,
-					   unsigned int bus_clk)
+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 dw_i2c_speed_config config;
+	struct i2c_regs *regs = priv->regs;
 	enum i2c_speed_mode i2c_spd;
-	unsigned int cntl;
-	unsigned int ena;
 	int spk_cnt;
 	int ret;
 
@@ -226,38 +216,60 @@ static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
 	else
 		i2c_spd = IC_SPEED_MODE_STANDARD;
 
-	/* Get enable setting for restore later */
-	ena = readl(&i2c_base->ic_enable) & IC_ENABLE_0B;
-
-	/* to set speed cltr must be disabled */
-	dw_i2c_enable(i2c_base, false);
-
-	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);
+		spk_cnt = readl(&regs->hs_spklen);
 	else
-		spk_cnt = readl(&i2c_base->fs_spklen);
+		spk_cnt = readl(&regs->fs_spklen);
 	if (scl_sda_cfg) {
-		config.sda_hold = scl_sda_cfg->sda_hold;
+		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;
+			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;
+			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);
+					 config);
 		if (ret)
 			return log_msg_ret("gen_confg", ret);
 	}
+	config->speed_mode = i2c_spd;
+
+	return 0;
+}
+
+/*
+ * _dw_i2c_set_bus_speed - Set the i2c speed
+ * @speed:	required i2c speed
+ *
+ * Set the i2c speed.
+ */
+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 ena;
+	int ret;
+
+	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;
+
+	/* to set speed cltr must be disabled */
+	dw_i2c_enable(i2c_base, false);
+
+	cntl = (readl(&i2c_base->ic_con) & (~IC_CON_SPD_MSK));
 
-	switch (i2c_spd) {
+	switch (config.speed_mode) {
 	case IC_SPEED_MODE_HIGH:
 		cntl |= IC_CON_SPD_SS;
 		writel(config.scl_hcnt, &i2c_base->ic_hs_scl_hcnt);
@@ -526,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(NULL, i2c_base, speed, IC_CLK);
+	_dw_i2c_set_bus_speed(NULL, i2c_base, speed, IC_CLK);
 	writel(slaveaddr, &i2c_base->ic_sar);
 #endif
 
@@ -571,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(NULL, i2c_get_base(adap), 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)
@@ -670,7 +682,7 @@ static int designware_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
 #else
 	rate = IC_CLK;
 #endif
-	return __dw_i2c_set_bus_speed(i2c, i2c->regs, 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,
diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
index 2027a91add..61a882cb65 100644
--- a/drivers/i2c/designware_i2c.h
+++ b/drivers/i2c/designware_i2c.h
@@ -8,6 +8,7 @@
 #define __DW_I2C_H_
 
 #include <clk.h>
+#include <i2c.h>
 #include <reset.h>
 
 struct i2c_regs {
@@ -165,12 +166,14 @@ struct dw_scl_sda_cfg {
  * @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;
 };
 
 /**
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 23/23] i2c: designware_i2c: Do more in the probe() method
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (21 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 22/23] i2c: designware_i2c: Separate out the speed calculation Simon Glass
@ 2020-01-23 18:48 ` Simon Glass
  2020-01-29  6:00 ` [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Heiko Schocher
  23 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-01-23 18:48 UTC (permalink / raw)
  To: u-boot

Move some of the code currently in the ofdata_to_platdata() method to
probe() so that it is not executed when generating ACPI tables.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

Changes in v3:
- Add new patch to do more in the probe() method

Changes in v2: None

 drivers/i2c/designware_i2c.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
index 39af25af9a..c8c5d2c331 100644
--- a/drivers/i2c/designware_i2c.c
+++ b/drivers/i2c/designware_i2c.c
@@ -704,6 +704,7 @@ static int designware_i2c_probe_chip(struct udevice *bus, uint chip_addr,
 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);
@@ -711,14 +712,6 @@ int designware_i2c_ofdata_to_platdata(struct udevice *bus)
 	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);
 
-	return 0;
-}
-
-int designware_i2c_probe(struct udevice *bus)
-{
-	struct dw_i2c *priv = dev_get_priv(bus);
-	int ret;
-
 	ret = reset_get_bulk(bus, &priv->resets);
 	if (ret)
 		dev_warn(bus, "Can't get reset: %d\n", ret);
@@ -738,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);
 }
 
-- 
2.25.0.341.g760bfbb309-goog

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH v3 17/23] i2c: omap: Update to use standard enums for speed
  2020-01-23 18:48 ` [PATCH v3 17/23] i2c: omap: " Simon Glass
@ 2020-01-24  3:21   ` Lokesh Vutla
  0 siblings, 0 replies; 28+ messages in thread
From: Lokesh Vutla @ 2020-01-24  3:21 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 24/01/20 12:18 AM, Simon Glass wrote:
> Update this driver to use the new standard enums for speed.
> 
> Note: This driver needs to move to driver model.

omap24xx_i2c is already converted to DM. The following commits has those
changes. Not sure what you meant here.

commit daa69ffe3d4d603ccb7dfca92c33f19d9e1c2313
Author: Mugunthan V N <mugunthanvnm@ti.com>
Date:   Mon Jul 18 15:11:01 2016 +0530

    drivers: i2c: omap24xx_i2c: adopt omap_i2c driver to driver model

    Convert omap i2c driver to adopt i2c driver model

    Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
    Reviewed-by: Simon Glass <sjg@chromium.org>

commit be243e4113b6c3c302ee03050726358714f40ffe
Author: Mugunthan V N <mugunthanvnm@ti.com>
Date:   Mon Jul 18 15:11:00 2016 +0530

    drivers: i2c: omap24xx_i2c: prepare driver for DM conversion

    Prepare the driver for DM conversion.

    Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
    Reviewed-by: Simon Glass <sjg@chromium.org>


Thanks and regards,
Lokesh

> 
> Signed-off-by: Simon Glass <sjg@chromium.org>
> Reviewed-by: Heiko Schocher <hs@denx.de>
> ---
> 
> Changes in v3: None
> Changes in v2: None
> 
>  drivers/i2c/omap24xx_i2c.c | 2 +-
>  drivers/i2c/omap24xx_i2c.h | 4 ----
>  2 files changed, 1 insertion(+), 5 deletions(-)
> 
> diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c
> index 4b93e02bbe..7e6e3c4f81 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;
> 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
> 

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup
  2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
                   ` (22 preceding siblings ...)
  2020-01-23 18:48 ` [PATCH v3 23/23] i2c: designware_i2c: Do more in the probe() method Simon Glass
@ 2020-01-29  6:00 ` Heiko Schocher
  23 siblings, 0 replies; 28+ messages in thread
From: Heiko Schocher @ 2020-01-29  6:00 UTC (permalink / raw)
  To: u-boot

Hello Simon,

Am 23.01.2020 um 19:48 schrieb Simon Glass:
> This series updates the Designware I2C driver to support reading its
> timing from the device tree and handling it in units of nanoseconds
> instead of clock cycles.
> 
> A new function converts from nanoseconds to the units used by the I2C
> controller and makes sure that the requested bus speed is not exceeded.
> This is more accurate than the existing method.
> 
> The series includes a few smaller clean-ups in the same driver.
> 
> In addition the v2 series adds enums for i2c speed and updates drivers to
> use them.
> 
> There is currently an existing configuration method used just for a few
> x86 boards (Baytrail). This method is retained but it should be removed in
> favour of using the device tree. I have not done this in this series since
> I am not sure of the timings to use.
> 
> Changes in v3:
> - Fix the address of comp_param1 by adding a gap
> - Drop note about moving to driver model
> - Use ARRAY_SIZE() for i2c_specs bounds check
> - Add new patch with support for fast-plus speed
> - Add new patch to move dw_i2c_speed_config to header
> - Add new patch to separate out the speed calculation
> - Add new patch to do more in the probe() method
> 
> Changes in v2:
> - Fix 'previde' typo
> - Add a few more clean-up patches for i2c
> 
> Simon Glass (23):
>    i2c: designware_i2c: Add more registers
>    i2c: designware_i2c: Don't allow changing IC_CLK
>    i2c: designware_i2c: Include clk.h in the header file
>    i2c: designware_i2c: Rename 'max' speed to 'high' speed
>    i2c: designware_i2c: Use an enum for selected speed mode
>    i2c: designware_i2c: Use an accurate bus clock instead of MHz
>    i2c: designware_i2c: Bring in the binding file
>    i2c: designware_i2c: Read device-tree properties
>    i2c: designware_i2c: Drop scl_sda_cfg parameter
>    i2c: designware_i2c: Put hold config in a struct
>    i2c: designware_i2c: Rewrite timing calculation
>    i2c: designware_i2c: Add spike supression
>    i2c: Add enums for i2c speed and address size
>    i2c: ast_i2c: Update to use standard enums for speed
>    i2c: designware_i2c: Update to use standard enums for speed
>    i2c: kona_i2c: Update to use standard enums for speed
>    i2c: omap: Update to use standard enums for speed
>    i2c: stm32: Update to use standard enums for speed
>    i2c: Update drivers to use enum for speed
>    i2c: designware_i2c: Add support for fast-plus speed
>    i2c: designware_i2c: Move dw_i2c_speed_config to header
>    i2c: designware_i2c: Separate out the speed calculation
>    i2c: designware_i2c: Do more in the probe() method
> 
>   .../i2c/i2c-designware.txt                    |  73 +++++
>   drivers/i2c/ast_i2c.c                         |   2 +-
>   drivers/i2c/ast_i2c.h                         |   2 -
>   drivers/i2c/designware_i2c.c                  | 300 ++++++++++++++----
>   drivers/i2c/designware_i2c.h                  |  73 ++++-
>   drivers/i2c/designware_i2c_pci.c              |   4 +-
>   drivers/i2c/exynos_hs_i2c.c                   |   5 +-
>   drivers/i2c/fsl_i2c.c                         |   3 +-
>   drivers/i2c/i2c-cdns.c                        |   2 +-
>   drivers/i2c/i2c-uclass.c                      |  12 +-
>   drivers/i2c/i2c-uniphier-f.c                  |   2 +-
>   drivers/i2c/i2c-uniphier.c                    |   2 +-
>   drivers/i2c/imx_lpi2c.c                       |   8 +-
>   drivers/i2c/kona_i2c.c                        |  28 +-
>   drivers/i2c/mv_i2c.c                          |   4 +-
>   drivers/i2c/mvtwsi.c                          |   5 +-
>   drivers/i2c/omap24xx_i2c.c                    |   5 +-
>   drivers/i2c/omap24xx_i2c.h                    |   4 -
>   drivers/i2c/rcar_i2c.c                        |   2 +-
>   drivers/i2c/rcar_iic.c                        |   2 +-
>   drivers/i2c/s3c24x0_i2c.c                     |   5 +-
>   drivers/i2c/sandbox_i2c.c                     |   3 +-
>   drivers/i2c/stm32f7_i2c.c                     |  43 +--
>   include/i2c.h                                 |  26 ++
>   24 files changed, 454 insertions(+), 161 deletions(-)
>   create mode 100644 doc/device-tree-bindings/i2c/i2c-designware.txt

Applied the hole series to u-boot-i2c master.

Thanks!

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-52   Fax: +49-8142-66989-80   Email: hs at denx.de

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH v3 22/23] i2c: designware_i2c: Separate out the speed calculation
  2020-01-23 18:48 ` [PATCH v3 22/23] i2c: designware_i2c: Separate out the speed calculation Simon Glass
@ 2020-04-22  6:43   ` Heinrich Schuchardt
  2020-04-22 16:20     ` Simon Glass
  0 siblings, 1 reply; 28+ messages in thread
From: Heinrich Schuchardt @ 2020-04-22  6:43 UTC (permalink / raw)
  To: u-boot

On 1/23/20 7:48 PM, Simon Glass wrote:
> We want to be able to calculate the speed separately from actually setting
> the speed, so we can generate the required ACPI tables. Split out the
> calculation into its own function.
>
> Drop the double underscore on __dw_i2c_set_bus_speed while we are here.
> That is reserved for compiler internals.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v3:
> - Add new patch to separate out the speed calculation
>
> Changes in v2: None
>
>  drivers/i2c/designware_i2c.c | 78 +++++++++++++++++++++---------------
>  drivers/i2c/designware_i2c.h |  3 ++
>  2 files changed, 48 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
> index 6be98ee43b..39af25af9a 100644
> --- a/drivers/i2c/designware_i2c.c
> +++ b/drivers/i2c/designware_i2c.c
> @@ -194,22 +194,12 @@ static int dw_i2c_calc_timing(struct dw_i2c *priv, enum i2c_speed_mode mode,
>  	return 0;
>  }
>
> -/*
> - * 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 dw_i2c *priv,
> -					   struct i2c_regs *i2c_base,
> -					   unsigned int speed,
> -					   unsigned int bus_clk)
> +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 dw_i2c_speed_config config;
> +	struct i2c_regs *regs = priv->regs;

Later in the code you have 'if (priv)'. Please, do not dereference priv
before the check.

Overall the code is somehow odd:

_dw_i2c_set_bus_speed() is called in multiple places with priv == NULL
and then calls calc_bus_speed(priv, ...).

Then in calc_bus_speed() you have:

comp_param1 = readl(&regs->comp_param1);

where regs == NULL->regs.

comp_param1 is used later on in the code to determine i2c_spd which is
returned in config->speed_mode.

Could you, please, have a close look at the driver.

Best regards

Heinrich

>  	enum i2c_speed_mode i2c_spd;
> -	unsigned int cntl;
> -	unsigned int ena;
>  	int spk_cnt;
>  	int ret;
>
> @@ -226,38 +216,60 @@ static unsigned int __dw_i2c_set_bus_speed(struct dw_i2c *priv,
>  	else
>  		i2c_spd = IC_SPEED_MODE_STANDARD;
>
> -	/* Get enable setting for restore later */
> -	ena = readl(&i2c_base->ic_enable) & IC_ENABLE_0B;
> -
> -	/* to set speed cltr must be disabled */
> -	dw_i2c_enable(i2c_base, false);
> -
> -	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);
> +		spk_cnt = readl(&regs->hs_spklen);
>  	else
> -		spk_cnt = readl(&i2c_base->fs_spklen);
> +		spk_cnt = readl(&regs->fs_spklen);
>  	if (scl_sda_cfg) {
> -		config.sda_hold = scl_sda_cfg->sda_hold;
> +		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;
> +			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;
> +			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);
> +					 config);
>  		if (ret)
>  			return log_msg_ret("gen_confg", ret);
>  	}
> +	config->speed_mode = i2c_spd;
> +
> +	return 0;
> +}
> +
> +/*
> + * _dw_i2c_set_bus_speed - Set the i2c speed
> + * @speed:	required i2c speed
> + *
> + * Set the i2c speed.
> + */
> +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 ena;
> +	int ret;
> +
> +	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;
> +
> +	/* to set speed cltr must be disabled */
> +	dw_i2c_enable(i2c_base, false);
> +
> +	cntl = (readl(&i2c_base->ic_con) & (~IC_CON_SPD_MSK));
>
> -	switch (i2c_spd) {
> +	switch (config.speed_mode) {
>  	case IC_SPEED_MODE_HIGH:
>  		cntl |= IC_CON_SPD_SS;
>  		writel(config.scl_hcnt, &i2c_base->ic_hs_scl_hcnt);
> @@ -526,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(NULL, i2c_base, speed, IC_CLK);
> +	_dw_i2c_set_bus_speed(NULL, i2c_base, speed, IC_CLK);
>  	writel(slaveaddr, &i2c_base->ic_sar);
>  #endif
>
> @@ -571,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(NULL, i2c_get_base(adap), 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)
> @@ -670,7 +682,7 @@ static int designware_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
>  #else
>  	rate = IC_CLK;
>  #endif
> -	return __dw_i2c_set_bus_speed(i2c, i2c->regs, 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,
> diff --git a/drivers/i2c/designware_i2c.h b/drivers/i2c/designware_i2c.h
> index 2027a91add..61a882cb65 100644
> --- a/drivers/i2c/designware_i2c.h
> +++ b/drivers/i2c/designware_i2c.h
> @@ -8,6 +8,7 @@
>  #define __DW_I2C_H_
>
>  #include <clk.h>
> +#include <i2c.h>
>  #include <reset.h>
>
>  struct i2c_regs {
> @@ -165,12 +166,14 @@ struct dw_scl_sda_cfg {
>   * @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;
>  };
>
>  /**
>

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH v3 22/23] i2c: designware_i2c: Separate out the speed calculation
  2020-04-22  6:43   ` Heinrich Schuchardt
@ 2020-04-22 16:20     ` Simon Glass
  0 siblings, 0 replies; 28+ messages in thread
From: Simon Glass @ 2020-04-22 16:20 UTC (permalink / raw)
  To: u-boot

Hi Heinrich,

On Wed, 22 Apr 2020 at 00:43, Heinrich Schuchardt <xypron.glpk@gmx.de> wrote:
>
> On 1/23/20 7:48 PM, Simon Glass wrote:
> > We want to be able to calculate the speed separately from actually setting
> > the speed, so we can generate the required ACPI tables. Split out the
> > calculation into its own function.
> >
> > Drop the double underscore on __dw_i2c_set_bus_speed while we are here.
> > That is reserved for compiler internals.
> >
> > Signed-off-by: Simon Glass <sjg@chromium.org>
> > ---
> >
> > Changes in v3:
> > - Add new patch to separate out the speed calculation
> >
> > Changes in v2: None
> >
> >  drivers/i2c/designware_i2c.c | 78 +++++++++++++++++++++---------------
> >  drivers/i2c/designware_i2c.h |  3 ++
> >  2 files changed, 48 insertions(+), 33 deletions(-)
> >
> > diff --git a/drivers/i2c/designware_i2c.c b/drivers/i2c/designware_i2c.c
> > index 6be98ee43b..39af25af9a 100644
> > --- a/drivers/i2c/designware_i2c.c
> > +++ b/drivers/i2c/designware_i2c.c
> > @@ -194,22 +194,12 @@ static int dw_i2c_calc_timing(struct dw_i2c *priv, enum i2c_speed_mode mode,
> >       return 0;
> >  }
> >
> > -/*
> > - * 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 dw_i2c *priv,
> > -                                        struct i2c_regs *i2c_base,
> > -                                        unsigned int speed,
> > -                                        unsigned int bus_clk)
> > +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 dw_i2c_speed_config config;
> > +     struct i2c_regs *regs = priv->regs;
>
> Later in the code you have 'if (priv)'. Please, do not dereference priv
> before the check.
>
> Overall the code is somehow odd:
>
> _dw_i2c_set_bus_speed() is called in multiple places with priv == NULL
> and then calls calc_bus_speed(priv, ...).
>
> Then in calc_bus_speed() you have:
>
> comp_param1 = readl(&regs->comp_param1);
>
> where regs == NULL->regs.
>
> comp_param1 is used later on in the code to determine i2c_spd which is
> returned in config->speed_mode.

Only for non-DM though I think. Still this is horrible, will send a patch.

What board are you testing with?

>
> Could you, please, have a close look at the driver.
>
> Best regards
>
> Heinrich
>
Regards,
Simon

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2020-04-22 16:20 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-01-23 18:48 [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Simon Glass
2020-01-23 18:48 ` [PATCH v3 01/23] i2c: designware_i2c: Add more registers Simon Glass
2020-01-23 18:48 ` [PATCH v3 02/23] i2c: designware_i2c: Don't allow changing IC_CLK Simon Glass
2020-01-23 18:48 ` [PATCH v3 03/23] i2c: designware_i2c: Include clk.h in the header file Simon Glass
2020-01-23 18:48 ` [PATCH v3 04/23] i2c: designware_i2c: Rename 'max' speed to 'high' speed Simon Glass
2020-01-23 18:48 ` [PATCH v3 05/23] i2c: designware_i2c: Use an enum for selected speed mode Simon Glass
2020-01-23 18:48 ` [PATCH v3 06/23] i2c: designware_i2c: Use an accurate bus clock instead of MHz Simon Glass
2020-01-23 18:48 ` [PATCH v3 07/23] i2c: designware_i2c: Bring in the binding file Simon Glass
2020-01-23 18:48 ` [PATCH v3 08/23] i2c: designware_i2c: Read device-tree properties Simon Glass
2020-01-23 18:48 ` [PATCH v3 09/23] i2c: designware_i2c: Drop scl_sda_cfg parameter Simon Glass
2020-01-23 18:48 ` [PATCH v3 10/23] i2c: designware_i2c: Put hold config in a struct Simon Glass
2020-01-23 18:48 ` [PATCH v3 11/23] i2c: designware_i2c: Rewrite timing calculation Simon Glass
2020-01-23 18:48 ` [PATCH v3 12/23] i2c: designware_i2c: Add spike supression Simon Glass
2020-01-23 18:48 ` [PATCH v3 13/23] i2c: Add enums for i2c speed and address size Simon Glass
2020-01-23 18:48 ` [PATCH v3 14/23] i2c: ast_i2c: Update to use standard enums for speed Simon Glass
2020-01-23 18:48 ` [PATCH v3 15/23] i2c: designware_i2c: " Simon Glass
2020-01-23 18:48 ` [PATCH v3 16/23] i2c: kona_i2c: " Simon Glass
2020-01-23 18:48 ` [PATCH v3 17/23] i2c: omap: " Simon Glass
2020-01-24  3:21   ` Lokesh Vutla
2020-01-23 18:48 ` [PATCH v3 18/23] i2c: stm32: " Simon Glass
2020-01-23 18:48 ` [PATCH v3 19/23] i2c: Update drivers to use enum " Simon Glass
2020-01-23 18:48 ` [PATCH v3 20/23] i2c: designware_i2c: Add support for fast-plus speed Simon Glass
2020-01-23 18:48 ` [PATCH v3 21/23] i2c: designware_i2c: Move dw_i2c_speed_config to header Simon Glass
2020-01-23 18:48 ` [PATCH v3 22/23] i2c: designware_i2c: Separate out the speed calculation Simon Glass
2020-04-22  6:43   ` Heinrich Schuchardt
2020-04-22 16:20     ` Simon Glass
2020-01-23 18:48 ` [PATCH v3 23/23] i2c: designware_i2c: Do more in the probe() method Simon Glass
2020-01-29  6:00 ` [PATCH v3 00/23] i2c: designware_ic2: Improvements to timing and general cleanup Heiko Schocher

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.