mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 00/10] i2c: i.MX more cleanup, early driver
@ 2019-03-04  9:18 Sascha Hauer
  2019-03-04  9:18 ` [PATCH 01/10] i2c: i.MX: remove unnecesary define Sascha Hauer
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Sascha Hauer @ 2019-03-04  9:18 UTC (permalink / raw)
  To: Barebox List

These are more cleanups to the i.MX i2c driver. As the last patch an
early i2c driver for use in PBL is added. This is needed for reading
the SPD data for upcoming Layerscape support.

Sascha

Sascha Hauer (10):
  i2c: i.MX: remove unnecesary define
  i2c: i.MX: remove unnecessary ifdef
  i2c: i.MX: Fix FSL_I2C_DFSRR register offset
  i2c: i.MX: remove unnecessary ifdef
  i2c: i.MX: Consolidate status polling loops
  i2c: i.MX: stop after read only in last transfer of a message
  i2c: i.MX: remove unused define
  i2c: i.MX: Read clock-frequency from device tree
  i2c: i.MX: Create header file for register defines
  i2c: i.MX: Add early driver for use in PBL

 drivers/i2c/Kconfig                |   3 +
 drivers/i2c/busses/Makefile        |   1 +
 drivers/i2c/busses/i2c-imx-early.c | 310 +++++++++++++++++++++++++++++
 drivers/i2c/busses/i2c-imx.c       | 157 ++++-----------
 drivers/i2c/busses/i2c-imx.h       |  52 +++++
 include/i2c/i2c-early.h            |  10 +
 6 files changed, 419 insertions(+), 114 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-imx-early.c
 create mode 100644 drivers/i2c/busses/i2c-imx.h
 create mode 100644 include/i2c/i2c-early.h

-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 01/10] i2c: i.MX: remove unnecesary define
  2019-03-04  9:18 [PATCH 00/10] i2c: i.MX more cleanup, early driver Sascha Hauer
@ 2019-03-04  9:18 ` Sascha Hauer
  2019-03-04  9:18 ` [PATCH 02/10] i2c: i.MX: remove unnecessary ifdef Sascha Hauer
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2019-03-04  9:18 UTC (permalink / raw)
  To: Barebox List

No need for a define which is used only once.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/busses/i2c-imx.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index f5fc65b06e..508ec1d273 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -49,9 +49,6 @@
 #include <i2c/i2c.h>
 #include <mach/clock.h>
 
-/* This will be the driver name */
-#define DRIVER_NAME "i2c-fsl"
-
 /* Default value */
 #define FSL_I2C_BIT_RATE	100000	/* 100kHz */
 
@@ -724,7 +721,7 @@ static __maybe_unused struct of_device_id imx_i2c_dt_ids[] = {
 
 static struct driver_d i2c_fsl_driver = {
 	.probe	= i2c_fsl_probe,
-	.name	= DRIVER_NAME,
+	.name	= "i2c-fsl",
 #ifndef CONFIG_PPC
 	.of_compatible = DRV_OF_COMPAT(imx_i2c_dt_ids),
 #endif
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 02/10] i2c: i.MX: remove unnecessary ifdef
  2019-03-04  9:18 [PATCH 00/10] i2c: i.MX more cleanup, early driver Sascha Hauer
  2019-03-04  9:18 ` [PATCH 01/10] i2c: i.MX: remove unnecesary define Sascha Hauer
@ 2019-03-04  9:18 ` Sascha Hauer
  2019-03-04  9:18 ` [PATCH 03/10] i2c: i.MX: Fix FSL_I2C_DFSRR register offset Sascha Hauer
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2019-03-04  9:18 UTC (permalink / raw)
  To: Barebox List

No need to put the of_compatible field into ifdefs, remove them.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/busses/i2c-imx.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 508ec1d273..3323f2ccce 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -722,8 +722,6 @@ static __maybe_unused struct of_device_id imx_i2c_dt_ids[] = {
 static struct driver_d i2c_fsl_driver = {
 	.probe	= i2c_fsl_probe,
 	.name	= "i2c-fsl",
-#ifndef CONFIG_PPC
 	.of_compatible = DRV_OF_COMPAT(imx_i2c_dt_ids),
-#endif
 };
 coredevice_platform_driver(i2c_fsl_driver);
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 03/10] i2c: i.MX: Fix FSL_I2C_DFSRR register offset
  2019-03-04  9:18 [PATCH 00/10] i2c: i.MX more cleanup, early driver Sascha Hauer
  2019-03-04  9:18 ` [PATCH 01/10] i2c: i.MX: remove unnecesary define Sascha Hauer
  2019-03-04  9:18 ` [PATCH 02/10] i2c: i.MX: remove unnecessary ifdef Sascha Hauer
@ 2019-03-04  9:18 ` Sascha Hauer
  2019-03-04  9:18 ` [PATCH 04/10] i2c: i.MX: remove unnecessary ifdef Sascha Hauer
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2019-03-04  9:18 UTC (permalink / raw)
  To: Barebox List

4ed5b77 ("i.MX: i2c: Add Vybrid support") introduced regshifts for the
register offsets, but missed to adjust the register offset for the
FSL_I2C_DFSRR register (which exists only on PowerPC). Fix this.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/busses/i2c-imx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 3323f2ccce..40d8527b7f 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -65,7 +65,7 @@
 #define FSL_I2C_I2CR	0x02	/* i2c control */
 #define FSL_I2C_I2SR	0x03	/* i2c status */
 #define FSL_I2C_I2DR	0x04	/* i2c transfer data */
-#define FSL_I2C_DFSRR	0x14	/* i2c digital filter sampling rate */
+#define FSL_I2C_DFSRR	0x05	/* i2c digital filter sampling rate */
 
 #define IMX_I2C_REGSHIFT	2
 #define VF610_I2C_REGSHIFT	0
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 04/10] i2c: i.MX: remove unnecessary ifdef
  2019-03-04  9:18 [PATCH 00/10] i2c: i.MX more cleanup, early driver Sascha Hauer
                   ` (2 preceding siblings ...)
  2019-03-04  9:18 ` [PATCH 03/10] i2c: i.MX: Fix FSL_I2C_DFSRR register offset Sascha Hauer
@ 2019-03-04  9:18 ` Sascha Hauer
  2019-03-04  9:18 ` [PATCH 05/10] i2c: i.MX: Consolidate status polling loops Sascha Hauer
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2019-03-04  9:18 UTC (permalink / raw)
  To: Barebox List

dev_dbg is a no-op when debugging is disabled, so no need for extra ifdefs.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/busses/i2c-imx.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 40d8527b7f..3d872a87d2 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -187,7 +187,6 @@ static inline unsigned char fsl_i2c_read_reg(struct fsl_i2c_struct *i2c_fsl,
 	return readb(i2c_fsl->base + reg);
 }
 
-#ifdef CONFIG_I2C_DEBUG
 static void i2c_fsl_dump_reg(struct i2c_adapter *adapter)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
@@ -209,13 +208,6 @@ static void i2c_fsl_dump_reg(struct i2c_adapter *adapter)
 		(reg_sr & I2SR_SRW  ? 1 : 0), (reg_sr & I2SR_IIF  ? 1 : 0),
 		(reg_sr & I2SR_RXAK ? 1 : 0));
 }
-#else
-static inline void i2c_fsl_dump_reg(struct i2c_adapter *adapter)
-{
-	return;
-}
-#endif
-
 
 static int i2c_fsl_bus_busy(struct i2c_adapter *adapter, int for_busy)
 {
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 05/10] i2c: i.MX: Consolidate status polling loops
  2019-03-04  9:18 [PATCH 00/10] i2c: i.MX more cleanup, early driver Sascha Hauer
                   ` (3 preceding siblings ...)
  2019-03-04  9:18 ` [PATCH 04/10] i2c: i.MX: remove unnecessary ifdef Sascha Hauer
@ 2019-03-04  9:18 ` Sascha Hauer
  2019-03-04  9:18 ` [PATCH 06/10] i2c: i.MX: stop after read only in last transfer of a message Sascha Hauer
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2019-03-04  9:18 UTC (permalink / raw)
  To: Barebox List

We poll for different bits in the status register in different
functions. Instead of repeating the polling loops each time create
a helper function for it.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/busses/i2c-imx.c | 73 +++++++++++++++---------------------
 1 file changed, 31 insertions(+), 42 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 3d872a87d2..e169feb3fc 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -209,46 +209,50 @@ static void i2c_fsl_dump_reg(struct i2c_adapter *adapter)
 		(reg_sr & I2SR_RXAK ? 1 : 0));
 }
 
-static int i2c_fsl_bus_busy(struct i2c_adapter *adapter, int for_busy)
+static int i2c_fsl_poll_status(struct i2c_adapter *adapter, int timeout_ms,
+			       uint8_t set, uint8_t clear)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
 	uint64_t start;
-	unsigned int temp;
+	uint8_t temp;
 
 	start = get_time_ns();
 	while (1) {
 		temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
-		if (for_busy && (temp & I2SR_IBB))
-			break;
-		if (!for_busy && !(temp & I2SR_IBB))
-			break;
-		if (is_timeout(start, 500 * MSECOND)) {
-			dev_err(&adapter->dev,
-				 "<%s> timeout waiting for I2C bus %s\n",
-				 __func__,for_busy ? "busy" : "not busy");
+		if (temp & set)
+			return 0;
+		if (~temp & clear)
+			return 0;
+
+		if (is_timeout(start, timeout_ms * MSECOND)) {
+			dev_dbg(&adapter->dev,
+				 "timeout waiting for status %s 0x%02x, cur status: 0x%02x\n",
+					set ? "set" : "clear",
+					set ? set : clear,
+					temp);
 			return -EIO;
 		}
 	}
+}
 
-	return 0;
+static int i2c_fsl_bus_busy(struct i2c_adapter *adapter)
+{
+	return i2c_fsl_poll_status(adapter, 500, I2SR_IBB, 0);
+}
+
+static int i2c_fsl_bus_idle(struct i2c_adapter *adapter)
+{
+	return i2c_fsl_poll_status(adapter, 500, 0, I2SR_IBB);
 }
 
 static int i2c_fsl_trx_complete(struct i2c_adapter *adapter)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	uint64_t start;
-
-	start = get_time_ns();
-	while (1) {
-		unsigned int reg = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
-		if (reg & I2SR_IIF)
-			break;
+	int ret;
 
-		if (is_timeout(start, 100 * MSECOND)) {
-			dev_err(&adapter->dev, "<%s> TXR timeout\n", __func__);
-			return -EIO;
-		}
-	}
+	ret = i2c_fsl_poll_status(adapter, 100, I2SR_IIF, 0);
+	if (ret)
+		return ret;
 
 	fsl_i2c_write_reg(i2c_fsl->hwdata->i2sr_clr_opcode,
 			  i2c_fsl, FSL_I2C_I2SR);
@@ -258,22 +262,7 @@ static int i2c_fsl_trx_complete(struct i2c_adapter *adapter)
 
 static int i2c_fsl_acked(struct i2c_adapter *adapter)
 {
-	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
-	uint64_t start;
-
-	start = get_time_ns();
-	while (1) {
-		unsigned int reg = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2SR);
-		if (!(reg & I2SR_RXAK))
-			break;
-
-		if (is_timeout(start, MSECOND)) {
-			dev_dbg(&adapter->dev, "<%s> No ACK\n", __func__);
-			return -EIO;
-		}
-	}
-
-	return 0;
+	return i2c_fsl_poll_status(adapter, 1, 0, I2SR_RXAK);
 }
 
 static int i2c_fsl_start(struct i2c_adapter *adapter)
@@ -302,7 +291,7 @@ static int i2c_fsl_start(struct i2c_adapter *adapter)
 	temp |= I2CR_MSTA;
 	fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
-	result = i2c_fsl_bus_busy(adapter, 1);
+	result = i2c_fsl_bus_busy(adapter);
 	if (result) {
 		result = i2c_recover_bus(&i2c_fsl->adapter);
 		if (result)
@@ -334,7 +323,7 @@ static void i2c_fsl_stop(struct i2c_adapter *adapter)
 	/* adding this delay helps on low bitrates */
 	udelay(i2c_fsl->disable_delay);
 
-	i2c_fsl_bus_busy(adapter, 0);
+	i2c_fsl_bus_idle(adapter);
 }
 
 #ifdef CONFIG_PPC
@@ -550,7 +539,7 @@ static int i2c_fsl_xfer(struct i2c_adapter *adapter,
 			temp |= I2CR_RSTA;
 			fsl_i2c_write_reg(temp, i2c_fsl, FSL_I2C_I2CR);
 
-			result = i2c_fsl_bus_busy(adapter, 1);
+			result = i2c_fsl_bus_busy(adapter);
 			if (result)
 				goto fail0;
 		}
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 06/10] i2c: i.MX: stop after read only in last transfer of a message
  2019-03-04  9:18 [PATCH 00/10] i2c: i.MX more cleanup, early driver Sascha Hauer
                   ` (4 preceding siblings ...)
  2019-03-04  9:18 ` [PATCH 05/10] i2c: i.MX: Consolidate status polling loops Sascha Hauer
@ 2019-03-04  9:18 ` Sascha Hauer
  2019-03-04  9:18 ` [PATCH 07/10] i2c: i.MX: remove unused define Sascha Hauer
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2019-03-04  9:18 UTC (permalink / raw)
  To: Barebox List

Following the Linux driver the controller should be stopped in the
read transfer path only after the last transfer of a message, but
not when other transfers of the same message are following. Implement
this behaviour for the barebox driver aswell.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/busses/i2c-imx.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index e169feb3fc..c903d8dfd1 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -469,7 +469,8 @@ static int i2c_fsl_write(struct i2c_adapter *adapter, struct i2c_msg *msg)
 	return 0;
 }
 
-static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msg)
+static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msg,
+			bool is_last)
 {
 	struct fsl_i2c_struct *i2c_fsl = to_fsl_i2c_struct(adapter);
 	int i, result;
@@ -500,7 +501,7 @@ static int i2c_fsl_read(struct i2c_adapter *adapter, struct i2c_msg *msg)
 		if (result)
 			return result;
 
-		if (i == (msg->len - 1)) {
+		if (is_last && i == msg->len - 1) {
 			i2c_fsl_stop(adapter);
 		} else if (i == (msg->len - 2)) {
 			temp = fsl_i2c_read_reg(i2c_fsl, FSL_I2C_I2CR);
@@ -547,7 +548,7 @@ static int i2c_fsl_xfer(struct i2c_adapter *adapter,
 
 		/* write/read data */
 		if (msgs[i].flags & I2C_M_RD)
-			result = i2c_fsl_read(adapter, &msgs[i]);
+			result = i2c_fsl_read(adapter, &msgs[i], i == num - 1);
 		else
 			result = i2c_fsl_write(adapter, &msgs[i]);
 		if (result)
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 07/10] i2c: i.MX: remove unused define
  2019-03-04  9:18 [PATCH 00/10] i2c: i.MX more cleanup, early driver Sascha Hauer
                   ` (5 preceding siblings ...)
  2019-03-04  9:18 ` [PATCH 06/10] i2c: i.MX: stop after read only in last transfer of a message Sascha Hauer
@ 2019-03-04  9:18 ` Sascha Hauer
  2019-03-04  9:18 ` [PATCH 08/10] i2c: i.MX: Read clock-frequency from device tree Sascha Hauer
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2019-03-04  9:18 UTC (permalink / raw)
  To: Barebox List

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/busses/i2c-imx.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index c903d8dfd1..9ce6bb7533 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -99,9 +99,6 @@
 #define I2CR_IEN_OPCODE_0	0x0
 #define I2CR_IEN_OPCODE_1	I2CR_IEN
 
-#define I2C_PM_TIMEOUT		10 /* ms */
-
-
 /*
  * sorted list of clock divider, register value pairs
  * taken from table 26-5, p.26-9, Freescale i.MX
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 08/10] i2c: i.MX: Read clock-frequency from device tree
  2019-03-04  9:18 [PATCH 00/10] i2c: i.MX more cleanup, early driver Sascha Hauer
                   ` (6 preceding siblings ...)
  2019-03-04  9:18 ` [PATCH 07/10] i2c: i.MX: remove unused define Sascha Hauer
@ 2019-03-04  9:18 ` Sascha Hauer
  2019-03-04  9:18 ` [PATCH 09/10] i2c: i.MX: Create header file for register defines Sascha Hauer
  2019-03-04  9:18 ` [PATCH 10/10] i2c: i.MX: Add early driver for use in PBL Sascha Hauer
  9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2019-03-04  9:18 UTC (permalink / raw)
  To: Barebox List

We speed up the clock frequency only if probed via platform_data.
Additionally honour the "clock-frequency" property.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/busses/i2c-imx.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 9ce6bb7533..409c178e6a 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -49,9 +49,6 @@
 #include <i2c/i2c.h>
 #include <mach/clock.h>
 
-/* Default value */
-#define FSL_I2C_BIT_RATE	100000	/* 100kHz */
-
 /* IMX I2C registers:
  * the I2C register offset is different between SoCs,
  * to provid support for all these chips, split the
@@ -611,6 +608,7 @@ static int __init i2c_fsl_probe(struct device_d *pdev)
 	struct fsl_i2c_struct *i2c_fsl;
 	struct i2c_platform_data *pdata;
 	int ret;
+	int bitrate;
 
 	pdata = pdev->platform_data;
 
@@ -652,10 +650,12 @@ static int __init i2c_fsl_probe(struct device_d *pdev)
 	i2c_fsl->dfsrr = -1;
 
 	/* Set up clock divider */
+	bitrate = 100000;
+	of_property_read_u32(pdev->device_node, "clock-frequency", &bitrate);
 	if (pdata && pdata->bitrate)
-		i2c_fsl_set_clk(i2c_fsl, pdata->bitrate);
-	else
-		i2c_fsl_set_clk(i2c_fsl, FSL_I2C_BIT_RATE);
+		bitrate = pdata->bitrate;
+
+	i2c_fsl_set_clk(i2c_fsl, bitrate);
 
 	/* Set up chip registers to defaults */
 	fsl_i2c_write_reg(i2c_fsl->hwdata->i2cr_ien_opcode ^ I2CR_IEN,
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 09/10] i2c: i.MX: Create header file for register defines
  2019-03-04  9:18 [PATCH 00/10] i2c: i.MX more cleanup, early driver Sascha Hauer
                   ` (7 preceding siblings ...)
  2019-03-04  9:18 ` [PATCH 08/10] i2c: i.MX: Read clock-frequency from device tree Sascha Hauer
@ 2019-03-04  9:18 ` Sascha Hauer
  2019-03-04  9:18 ` [PATCH 10/10] i2c: i.MX: Add early driver for use in PBL Sascha Hauer
  9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2019-03-04  9:18 UTC (permalink / raw)
  To: Barebox List

We'll add a stripped down driver variant for use in PBL. To share the
register defines add a header file for them.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/busses/i2c-imx.c | 47 +-------------------------------
 drivers/i2c/busses/i2c-imx.h | 52 ++++++++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 46 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-imx.h

diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 409c178e6a..4c7346063c 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -49,52 +49,7 @@
 #include <i2c/i2c.h>
 #include <mach/clock.h>
 
-/* IMX I2C registers:
- * the I2C register offset is different between SoCs,
- * to provid support for all these chips, split the
- * register offset into a fixed base address and a
- * variable shift value, then the full register offset
- * will be calculated by
- * reg_off = ( reg_base_addr << reg_shift)
- */
-#define FSL_I2C_IADR	0x00	/* i2c slave address */
-#define FSL_I2C_IFDR	0x01	/* i2c frequency divider */
-#define FSL_I2C_I2CR	0x02	/* i2c control */
-#define FSL_I2C_I2SR	0x03	/* i2c status */
-#define FSL_I2C_I2DR	0x04	/* i2c transfer data */
-#define FSL_I2C_DFSRR	0x05	/* i2c digital filter sampling rate */
-
-#define IMX_I2C_REGSHIFT	2
-#define VF610_I2C_REGSHIFT	0
-
-
-/* Bits of FSL I2C registers */
-#define I2SR_RXAK	0x01
-#define I2SR_IIF	0x02
-#define I2SR_SRW	0x04
-#define I2SR_IAL	0x10
-#define I2SR_IBB	0x20
-#define I2SR_IAAS	0x40
-#define I2SR_ICF	0x80
-#define I2CR_RSTA	0x04
-#define I2CR_TXAK	0x08
-#define I2CR_MTX	0x10
-#define I2CR_MSTA	0x20
-#define I2CR_IIEN	0x40
-#define I2CR_IEN	0x80
-
-/* register bits different operating codes definition:
- * 1) I2SR: Interrupt flags clear operation differ between SoCs:
- * - write zero to clear(w0c) INT flag on i.MX,
- * - but write one to clear(w1c) INT flag on Vybrid.
- * 2) I2CR: I2C module enable operation also differ between SoCs:
- * - set I2CR_IEN bit enable the module on i.MX,
- * - but clear I2CR_IEN bit enable the module on Vybrid.
- */
-#define I2SR_CLR_OPCODE_W0C	0x0
-#define I2SR_CLR_OPCODE_W1C	(I2SR_IAL | I2SR_IIF)
-#define I2CR_IEN_OPCODE_0	0x0
-#define I2CR_IEN_OPCODE_1	I2CR_IEN
+#include "i2c-imx.h"
 
 /*
  * sorted list of clock divider, register value pairs
diff --git a/drivers/i2c/busses/i2c-imx.h b/drivers/i2c/busses/i2c-imx.h
new file mode 100644
index 0000000000..3e3e1317f2
--- /dev/null
+++ b/drivers/i2c/busses/i2c-imx.h
@@ -0,0 +1,52 @@
+#ifndef I2C_IMX_H
+#define I2C_IMX_H
+
+/*
+ * IMX I2C registers:
+ * the I2C register offset is different between SoCs, to provide support for
+ * all these chips, split the register offset into a fixed base address and a
+ * variable shift value, then the full register offset will be calculated by:
+ * reg_off = reg_base_addr << reg_shift
+ */
+#define FSL_I2C_IADR	0x00	/* i2c slave address */
+#define FSL_I2C_IFDR	0x01	/* i2c frequency divider */
+#define FSL_I2C_I2CR	0x02	/* i2c control */
+#define FSL_I2C_I2SR	0x03	/* i2c status */
+#define FSL_I2C_I2DR	0x04	/* i2c transfer data */
+#define FSL_I2C_DFSRR	0x05	/* i2c digital filter sampling rate */
+
+#define IMX_I2C_REGSHIFT	2
+#define VF610_I2C_REGSHIFT	0
+
+/* Bits of FSL I2C registers */
+#define I2SR_RXAK	0x01
+#define I2SR_IIF	0x02
+#define I2SR_SRW	0x04
+#define I2SR_IAL	0x10
+#define I2SR_IBB	0x20
+#define I2SR_IAAS	0x40
+#define I2SR_ICF	0x80
+#define I2CR_RSTA	0x04
+#define I2CR_TXAK	0x08
+#define I2CR_MTX	0x10
+#define I2CR_MSTA	0x20
+#define I2CR_IIEN	0x40
+#define I2CR_IEN	0x80
+
+/*
+ * register bits different operating codes definition:
+ *
+ * 1) I2SR: Interrupt flags clear operation differ between SoCs:
+ * - write zero to clear(w0c) INT flag on i.MX,
+ * - but write one to clear(w1c) INT flag on Vybrid.
+ *
+ * 2) I2CR: I2C module enable operation also differ between SoCs:
+ * - set I2CR_IEN bit enable the module on i.MX,
+ * - but clear I2CR_IEN bit enable the module on Vybrid.
+ */
+#define I2SR_CLR_OPCODE_W0C	0x0
+#define I2SR_CLR_OPCODE_W1C	(I2SR_IAL | I2SR_IIF)
+#define I2CR_IEN_OPCODE_0	0x0
+#define I2CR_IEN_OPCODE_1	I2CR_IEN
+
+#endif /* I2C_IMX_H */
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

* [PATCH 10/10] i2c: i.MX: Add early driver for use in PBL
  2019-03-04  9:18 [PATCH 00/10] i2c: i.MX more cleanup, early driver Sascha Hauer
                   ` (8 preceding siblings ...)
  2019-03-04  9:18 ` [PATCH 09/10] i2c: i.MX: Create header file for register defines Sascha Hauer
@ 2019-03-04  9:18 ` Sascha Hauer
  9 siblings, 0 replies; 11+ messages in thread
From: Sascha Hauer @ 2019-03-04  9:18 UTC (permalink / raw)
  To: Barebox List

i2c is used in SPD EEPROMs and thus needed very early before barebox is
up. This patch adds a i.MX i2c driver variant for use in PBL.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/i2c/Kconfig                |   3 +
 drivers/i2c/busses/Makefile        |   1 +
 drivers/i2c/busses/i2c-imx-early.c | 310 +++++++++++++++++++++++++++++
 include/i2c/i2c-early.h            |  10 +
 4 files changed, 324 insertions(+)
 create mode 100644 drivers/i2c/busses/i2c-imx-early.c
 create mode 100644 include/i2c/i2c-early.h

diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 56259d82d4..fc314ec9c6 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -16,3 +16,6 @@ config I2C_MUX
 source drivers/i2c/muxes/Kconfig
 
 endif
+
+config I2C_IMX_EARLY
+	bool
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 8dccc38379..61d7c86e76 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -1,6 +1,7 @@
 obj-$(CONFIG_I2C_AT91)		+= i2c-at91.o
 obj-$(CONFIG_I2C_GPIO)		+= i2c-gpio.o
 obj-$(CONFIG_I2C_IMX)		+= i2c-imx.o
+lwl-$(CONFIG_I2C_IMX_EARLY)	+= i2c-imx-early.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
 obj-$(CONFIG_I2C_OMAP)		+= i2c-omap.o
 obj-$(CONFIG_I2C_TEGRA)		+= i2c-tegra.o
diff --git a/drivers/i2c/busses/i2c-imx-early.c b/drivers/i2c/busses/i2c-imx-early.c
new file mode 100644
index 0000000000..d67226441e
--- /dev/null
+++ b/drivers/i2c/busses/i2c-imx-early.c
@@ -0,0 +1,310 @@
+/*
+ * Copyright 2013 GE Intelligent Platforms, Inc
+ * Copyright 2006,2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Early I2C support functions to read SPD data or board
+ * information.
+ * Based on U-Boot drivers/i2c/fsl_i2c.c
+ */
+#include <common.h>
+#include <i2c/i2c.h>
+#include <i2c/i2c-early.h>
+
+#include "i2c-imx.h"
+
+struct fsl_i2c {
+	void __iomem *regs;
+	unsigned int i2cr_ien_opcode;
+	unsigned int i2sr_clr_opcode;
+	unsigned int ifdr;
+	unsigned int regshift;
+};
+
+static inline void fsl_i2c_write_reg(unsigned int val,
+				     struct fsl_i2c *fsl_i2c,
+				     unsigned int reg)
+{
+	reg <<= fsl_i2c->regshift;
+
+	writeb(val, fsl_i2c->regs + reg);
+}
+
+static inline unsigned char fsl_i2c_read_reg(struct fsl_i2c *fsl_i2c,
+					     unsigned int reg)
+{
+	reg <<= fsl_i2c->regshift;
+
+	return readb(fsl_i2c->regs + reg);
+}
+
+static int i2c_fsl_poll_status(struct fsl_i2c *fsl_i2c, uint8_t set, uint8_t clear)
+{
+	int timeout = 1000000;
+	uint8_t temp;
+
+	while (1) {
+		temp = fsl_i2c_read_reg(fsl_i2c, FSL_I2C_I2SR);
+		if (temp & set)
+			return 0;
+		if (~temp & clear)
+			return 0;
+
+		if (!--timeout) {
+			pr_debug("timeout waiting for status %s 0x%02x, cur status: 0x%02x\n",
+					set ? "set" : "clear",
+					set ? set : clear,
+					temp);
+			return -EIO;
+		}
+	}
+}
+
+static int i2c_fsl_bus_busy(struct fsl_i2c *fsl_i2c)
+{
+	return i2c_fsl_poll_status(fsl_i2c, I2SR_IBB, 0);
+}
+
+static int i2c_fsl_bus_idle(struct fsl_i2c *fsl_i2c)
+{
+	return i2c_fsl_poll_status(fsl_i2c, 0, I2SR_IBB);
+}
+
+static int i2c_fsl_trx_complete(struct fsl_i2c *fsl_i2c)
+{
+	int ret;
+
+	ret = i2c_fsl_poll_status(fsl_i2c, I2SR_IIF, 0);
+	if (ret)
+		return ret;
+
+	fsl_i2c_write_reg(fsl_i2c->i2sr_clr_opcode,
+			  fsl_i2c, FSL_I2C_I2SR);
+
+	return 0;
+}
+
+static int i2c_fsl_acked(struct fsl_i2c *fsl_i2c)
+{
+	return i2c_fsl_poll_status(fsl_i2c, 0, I2SR_RXAK);
+}
+
+static int i2c_fsl_start(struct fsl_i2c *fsl_i2c)
+{
+	unsigned int temp = 0;
+	int ret;
+
+	fsl_i2c_write_reg(fsl_i2c->ifdr, fsl_i2c, FSL_I2C_IFDR);
+
+	/* Enable I2C controller */
+	fsl_i2c_write_reg(fsl_i2c->i2sr_clr_opcode,
+			  fsl_i2c, FSL_I2C_I2SR);
+	fsl_i2c_write_reg(fsl_i2c->i2cr_ien_opcode,
+			  fsl_i2c, FSL_I2C_I2CR);
+
+	/* Wait controller to be stable */
+	udelay(100);
+
+	/* Start I2C transaction */
+	temp = fsl_i2c_read_reg(fsl_i2c, FSL_I2C_I2CR);
+	temp |= I2CR_MSTA;
+	fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+
+	ret = i2c_fsl_bus_busy(fsl_i2c);
+	if (ret)
+		return -EAGAIN;
+
+	temp |= I2CR_MTX | I2CR_TXAK;
+	fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+
+	return ret;
+}
+
+static void i2c_fsl_stop(struct fsl_i2c *fsl_i2c)
+{
+	unsigned int temp = 0;
+
+	/* Stop I2C transaction */
+	temp = fsl_i2c_read_reg(fsl_i2c, FSL_I2C_I2CR);
+	temp &= ~(I2CR_MSTA | I2CR_MTX);
+	fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+	/* wait for the stop condition to be send, otherwise the i2c
+	 * controller is disabled before the STOP is sent completely */
+
+	i2c_fsl_bus_idle(fsl_i2c);
+}
+
+static int i2c_fsl_send(struct fsl_i2c *fsl_i2c, uint8_t data)
+{
+	int ret;
+
+	pr_debug("%s send 0x%02x\n", __func__, data);
+
+	fsl_i2c_write_reg(data, fsl_i2c, FSL_I2C_I2DR);
+
+	ret = i2c_fsl_trx_complete(fsl_i2c);
+	if (ret) {
+		pr_debug("%s timeout 1\n", __func__);
+		return ret;
+	}
+
+	ret = i2c_fsl_acked(fsl_i2c);
+	if (ret) {
+		pr_debug("%s timeout 2\n", __func__);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int i2c_fsl_write(struct fsl_i2c *fsl_i2c, struct i2c_msg *msg)
+{
+	int i, ret;
+
+	if (!(msg->flags & I2C_M_DATA_ONLY)) {
+		ret = i2c_fsl_send(fsl_i2c, msg->addr << 1);
+		if (ret)
+			return ret;
+	}
+
+	/* write data */
+	for (i = 0; i < msg->len; i++) {
+		ret = i2c_fsl_send(fsl_i2c, msg->buf[i]);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int i2c_fsl_read(struct fsl_i2c *fsl_i2c, struct i2c_msg *msg)
+{
+	int i, ret;
+	unsigned int temp;
+
+	/* clear IIF */
+	fsl_i2c_write_reg(fsl_i2c->i2sr_clr_opcode,
+			  fsl_i2c, FSL_I2C_I2SR);
+
+	if (!(msg->flags & I2C_M_DATA_ONLY)) {
+		ret = i2c_fsl_send(fsl_i2c, (msg->addr << 1) | 1);
+		if (ret)
+			return ret;
+	}
+
+	/* setup bus to read data */
+	temp = fsl_i2c_read_reg(fsl_i2c, FSL_I2C_I2CR);
+	temp &= ~I2CR_MTX;
+	if (msg->len - 1)
+		temp &= ~I2CR_TXAK;
+	fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+
+	fsl_i2c_read_reg(fsl_i2c, FSL_I2C_I2DR); /* dummy read */
+
+	/* read data */
+	for (i = 0; i < msg->len; i++) {
+		ret = i2c_fsl_trx_complete(fsl_i2c);
+		if (ret)
+			return ret;
+
+		if (i == (msg->len - 1)) {
+			i2c_fsl_stop(fsl_i2c);
+		} else if (i == (msg->len - 2)) {
+			temp = fsl_i2c_read_reg(fsl_i2c, FSL_I2C_I2CR);
+			temp |= I2CR_TXAK;
+			fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+		}
+		msg->buf[i] = fsl_i2c_read_reg(fsl_i2c, FSL_I2C_I2DR);
+	}
+	return 0;
+}
+
+/**
+ * i2c_fsl_xfer - transfer I2C messages on i.MX compatible I2C controllers
+ * @ctx: driver context pointer
+ * @msgs: pointer to I2C messages
+ * @num: number of messages to transfer
+ *
+ * This function transfers I2C messages on i.MX and compatible I2C controllers.
+ * If successful returns the number of messages transferred, otherwise a negative
+ * error code is returned.
+ */
+int i2c_fsl_xfer(void *ctx, struct i2c_msg *msgs, int num)
+{
+	struct fsl_i2c *fsl_i2c = ctx;
+	unsigned int i, temp;
+	int ret;
+
+	pr_debug("%s enter\n", __func__);
+
+	/* Start I2C transfer */
+	for (i = 0; i < 3; i++) {
+		ret = i2c_fsl_start(fsl_i2c);
+		if (!ret)
+			break;
+		if (ret == -EAGAIN)
+			continue;
+		return ret;
+	}
+
+	/* read/write data */
+	for (i = 0; i < num; i++) {
+		if (i && !(msgs[i].flags & I2C_M_DATA_ONLY)) {
+			temp = fsl_i2c_read_reg(fsl_i2c, FSL_I2C_I2CR);
+			temp |= I2CR_RSTA;
+			fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+
+			ret = i2c_fsl_bus_busy(fsl_i2c);
+			if (ret)
+				goto fail0;
+		}
+
+		/* write/read data */
+		if (msgs[i].flags & I2C_M_RD)
+			ret = i2c_fsl_read(fsl_i2c, &msgs[i]);
+		else
+			ret = i2c_fsl_write(fsl_i2c, &msgs[i]);
+		if (ret)
+			goto fail0;
+	}
+
+fail0:
+	/* Stop I2C transfer */
+	i2c_fsl_stop(fsl_i2c);
+
+	/* Disable I2C controller, and force our state to stopped */
+	temp = fsl_i2c->i2cr_ien_opcode ^ I2CR_IEN,
+	fsl_i2c_write_reg(temp, fsl_i2c, FSL_I2C_I2CR);
+
+	return (ret < 0) ? ret : num;
+}
+
+static struct fsl_i2c fsl_i2c;
+
+/**
+ * ls1046_i2c_init - Return a context pointer for accessing I2C on LS1046a
+ * @regs: The base address of the I2C controller to access
+ *
+ * This function returns a context pointer suitable to transfer I2C messages
+ * using i2c_fsl_xfer.
+ */
+void *ls1046_i2c_init(void __iomem *regs)
+{
+	fsl_i2c.regs = regs;
+	fsl_i2c.regshift = 0;
+	fsl_i2c.i2cr_ien_opcode = I2CR_IEN_OPCODE_0;
+	fsl_i2c.i2sr_clr_opcode = I2SR_CLR_OPCODE_W1C;
+	/* Divider for ~100kHz when coming from the ROM */
+	fsl_i2c.ifdr = 0x3e;
+
+	return &fsl_i2c;
+}
diff --git a/include/i2c/i2c-early.h b/include/i2c/i2c-early.h
new file mode 100644
index 0000000000..27efd25109
--- /dev/null
+++ b/include/i2c/i2c-early.h
@@ -0,0 +1,10 @@
+#ifndef __I2C_EARLY_H
+#define __I2C_EARLY_H
+
+#include <i2c/i2c.h>
+
+int i2c_fsl_xfer(void *ctx, struct i2c_msg *msgs, int num);
+
+void *ls1046_i2c_init(void __iomem *regs);
+
+#endif /* __I2C_EARLY_H */
-- 
2.20.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

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

end of thread, other threads:[~2019-03-04  9:19 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-04  9:18 [PATCH 00/10] i2c: i.MX more cleanup, early driver Sascha Hauer
2019-03-04  9:18 ` [PATCH 01/10] i2c: i.MX: remove unnecesary define Sascha Hauer
2019-03-04  9:18 ` [PATCH 02/10] i2c: i.MX: remove unnecessary ifdef Sascha Hauer
2019-03-04  9:18 ` [PATCH 03/10] i2c: i.MX: Fix FSL_I2C_DFSRR register offset Sascha Hauer
2019-03-04  9:18 ` [PATCH 04/10] i2c: i.MX: remove unnecessary ifdef Sascha Hauer
2019-03-04  9:18 ` [PATCH 05/10] i2c: i.MX: Consolidate status polling loops Sascha Hauer
2019-03-04  9:18 ` [PATCH 06/10] i2c: i.MX: stop after read only in last transfer of a message Sascha Hauer
2019-03-04  9:18 ` [PATCH 07/10] i2c: i.MX: remove unused define Sascha Hauer
2019-03-04  9:18 ` [PATCH 08/10] i2c: i.MX: Read clock-frequency from device tree Sascha Hauer
2019-03-04  9:18 ` [PATCH 09/10] i2c: i.MX: Create header file for register defines Sascha Hauer
2019-03-04  9:18 ` [PATCH 10/10] i2c: i.MX: Add early driver for use in PBL Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox