* [PATCH v4 1/3] i3c: fix i2c and i3c scl rate by bus mode
2019-06-19 18:36 [PATCH v4 0/3] Fix i2c and i3c scl rate according bus mode Vitor Soares
@ 2019-06-19 18:36 ` Vitor Soares
2019-06-19 18:36 ` [PATCH v4 2/3] i3c: add mixed limited " Vitor Soares
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Vitor Soares @ 2019-06-19 18:36 UTC (permalink / raw)
To: linux-i3c, Joao.Pinto; +Cc: Boris Brezillon, linux-kernel, stable, Vitor Soares
Currently the I3C framework limits SCL frequency to FM speed when
dealing with a mixed slow bus, even if all I2C devices are FM+ capable.
The core was also not accounting for I3C speed limitations when
operating in mixed slow mode and was erroneously using FM+ speed as the
max I2C speed when operating in mixed fast mode.
Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure")
Signed-off-by: Vitor Soares <vitor.soares@synopsys.com>
Cc: Boris Brezillon <bbrezillon@kernel.org>
Cc: <stable@vger.kernel.org>
Cc: <linux-kernel@vger.kernel.org>
---
Changes in v4:
Print i2c-scl and i3c-scl unconditionally when in debug mode
Changes in v3:
Change dev_warn() to dev_dbg()
Changes in v2:
Enhance commit message
Add dev_warn() in case user-defined i2c rate doesn't match LVR constraint
Add dev_warn() in case user-defined i3c rate lower than i2c rate
drivers/i3c/master.c | 52 +++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 39 insertions(+), 13 deletions(-)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 5f4bd52..14980db 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -91,6 +91,12 @@ void i3c_bus_normaluse_unlock(struct i3c_bus *bus)
up_read(&bus->lock);
}
+static struct i3c_master_controller *
+i3c_bus_to_i3c_master(struct i3c_bus *i3cbus)
+{
+ return container_of(i3cbus, struct i3c_master_controller, bus);
+}
+
static struct i3c_master_controller *dev_to_i3cmaster(struct device *dev)
{
return container_of(dev, struct i3c_master_controller, dev);
@@ -565,20 +571,39 @@ static const struct device_type i3c_masterdev_type = {
.groups = i3c_masterdev_groups,
};
-int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode)
+int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
+ unsigned long max_i2c_scl_rate)
{
- i3cbus->mode = mode;
- if (!i3cbus->scl_rate.i3c)
- i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
+ struct i3c_master_controller *master = i3c_bus_to_i3c_master(i3cbus);
- if (!i3cbus->scl_rate.i2c) {
- if (i3cbus->mode == I3C_BUS_MODE_MIXED_SLOW)
- i3cbus->scl_rate.i2c = I3C_BUS_I2C_FM_SCL_RATE;
- else
- i3cbus->scl_rate.i2c = I3C_BUS_I2C_FM_PLUS_SCL_RATE;
+ i3cbus->mode = mode;
+
+ switch (i3cbus->mode) {
+ case I3C_BUS_MODE_PURE:
+ if (!i3cbus->scl_rate.i3c)
+ i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
+ break;
+ case I3C_BUS_MODE_MIXED_FAST:
+ if (!i3cbus->scl_rate.i3c)
+ i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
+ if (!i3cbus->scl_rate.i2c)
+ i3cbus->scl_rate.i2c = max_i2c_scl_rate;
+ break;
+ case I3C_BUS_MODE_MIXED_SLOW:
+ if (!i3cbus->scl_rate.i2c)
+ i3cbus->scl_rate.i2c = max_i2c_scl_rate;
+ if (!i3cbus->scl_rate.i3c ||
+ i3cbus->scl_rate.i3c > i3cbus->scl_rate.i2c)
+ i3cbus->scl_rate.i3c = i3cbus->scl_rate.i2c;
+ break;
+ default:
+ return -EINVAL;
}
+ dev_dbg(&master->dev, "i2c-scl = %ld Hz i3c-scl = %ld Hz\n",
+ i3cbus->scl_rate.i2c, i3cbus->scl_rate.i3c);
+
/*
* I3C/I2C frequency may have been overridden, check that user-provided
* values are not exceeding max possible frequency.
@@ -1966,9 +1991,6 @@ of_i3c_master_add_i2c_boardinfo(struct i3c_master_controller *master,
/* LVR is encoded in reg[2]. */
boardinfo->lvr = reg[2];
- if (boardinfo->lvr & I3C_LVR_I2C_FM_MODE)
- master->bus.scl_rate.i2c = I3C_BUS_I2C_FM_SCL_RATE;
-
list_add_tail(&boardinfo->node, &master->boardinfo.i2c);
of_node_get(node);
@@ -2417,6 +2439,7 @@ int i3c_master_register(struct i3c_master_controller *master,
const struct i3c_master_controller_ops *ops,
bool secondary)
{
+ unsigned long i2c_scl_rate = I3C_BUS_I2C_FM_PLUS_SCL_RATE;
struct i3c_bus *i3cbus = i3c_master_get_bus(master);
enum i3c_bus_mode mode = I3C_BUS_MODE_PURE;
struct i2c_dev_boardinfo *i2cbi;
@@ -2466,9 +2489,12 @@ int i3c_master_register(struct i3c_master_controller *master,
ret = -EINVAL;
goto err_put_dev;
}
+
+ if (i2cbi->lvr & I3C_LVR_I2C_FM_MODE)
+ i2c_scl_rate = I3C_BUS_I2C_FM_SCL_RATE;
}
- ret = i3c_bus_set_mode(i3cbus, mode);
+ ret = i3c_bus_set_mode(i3cbus, mode, i2c_scl_rate);
if (ret)
goto err_put_dev;
--
2.7.4
_______________________________________________
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 2/3] i3c: add mixed limited bus mode
2019-06-19 18:36 [PATCH v4 0/3] Fix i2c and i3c scl rate according bus mode Vitor Soares
2019-06-19 18:36 ` [PATCH v4 1/3] i3c: fix i2c and i3c scl rate by " Vitor Soares
@ 2019-06-19 18:36 ` Vitor Soares
2019-06-19 18:36 ` [PATCH v4 3/3] i3c: dw: add limited bus mode support Vitor Soares
2019-06-20 8:56 ` [PATCH v4 0/3] Fix i2c and i3c scl rate according bus mode Boris Brezillon
3 siblings, 0 replies; 5+ messages in thread
From: Vitor Soares @ 2019-06-19 18:36 UTC (permalink / raw)
To: linux-i3c, Joao.Pinto; +Cc: Boris Brezillon, linux-kernel, Vitor Soares
The i3c bus spec defines a bus configuration where i2c devices don't
have a 50ns filter but support SCL running at SDR max rate (12.5MHz).
This patch introduces the limited bus mode so that users can use
a higher speed in presence of i2c devices index 1.
Signed-off-by: Vitor Soares <vitor.soares@synopsys.com>
Cc: Boris Brezillon <bbrezillon@kernel.org>
Cc: <linux-kernel@vger.kernel.org>
---
Changes in v4:
None
Changes in v3:
None
Changes in v2:
Enhance commit message
drivers/i3c/master.c | 5 +++++
include/linux/i3c/master.h | 5 +++++
2 files changed, 10 insertions(+)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 14980db..76549f1 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -470,6 +470,7 @@ static int i3c_bus_init(struct i3c_bus *i3cbus)
static const char * const i3c_bus_mode_strings[] = {
[I3C_BUS_MODE_PURE] = "pure",
[I3C_BUS_MODE_MIXED_FAST] = "mixed-fast",
+ [I3C_BUS_MODE_MIXED_LIMITED] = "mixed-limited",
[I3C_BUS_MODE_MIXED_SLOW] = "mixed-slow",
};
@@ -585,6 +586,7 @@ int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
break;
case I3C_BUS_MODE_MIXED_FAST:
+ case I3C_BUS_MODE_MIXED_LIMITED:
if (!i3cbus->scl_rate.i3c)
i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
if (!i3cbus->scl_rate.i2c)
@@ -2481,6 +2483,9 @@ int i3c_master_register(struct i3c_master_controller *master,
mode = I3C_BUS_MODE_MIXED_FAST;
break;
case I3C_LVR_I2C_INDEX(1):
+ if (mode < I3C_BUS_MODE_MIXED_LIMITED)
+ mode = I3C_BUS_MODE_MIXED_LIMITED;
+ break;
case I3C_LVR_I2C_INDEX(2):
if (mode < I3C_BUS_MODE_MIXED_SLOW)
mode = I3C_BUS_MODE_MIXED_SLOW;
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index f13fd8b..89ea461 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -250,12 +250,17 @@ struct i3c_device {
* the bus. The only impact in this mode is that the
* high SCL pulse has to stay below 50ns to trick I2C
* devices when transmitting I3C frames
+ * @I3C_BUS_MODE_MIXED_LIMITED: I2C devices without 50ns spike filter are
+ * present on the bus. However they allows
+ * compliance up to the maximum SDR SCL clock
+ * frequency.
* @I3C_BUS_MODE_MIXED_SLOW: I2C devices without 50ns spike filter are present
* on the bus
*/
enum i3c_bus_mode {
I3C_BUS_MODE_PURE,
I3C_BUS_MODE_MIXED_FAST,
+ I3C_BUS_MODE_MIXED_LIMITED,
I3C_BUS_MODE_MIXED_SLOW,
};
--
2.7.4
_______________________________________________
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 3/3] i3c: dw: add limited bus mode support
2019-06-19 18:36 [PATCH v4 0/3] Fix i2c and i3c scl rate according bus mode Vitor Soares
2019-06-19 18:36 ` [PATCH v4 1/3] i3c: fix i2c and i3c scl rate by " Vitor Soares
2019-06-19 18:36 ` [PATCH v4 2/3] i3c: add mixed limited " Vitor Soares
@ 2019-06-19 18:36 ` Vitor Soares
2019-06-20 8:56 ` [PATCH v4 0/3] Fix i2c and i3c scl rate according bus mode Boris Brezillon
3 siblings, 0 replies; 5+ messages in thread
From: Vitor Soares @ 2019-06-19 18:36 UTC (permalink / raw)
To: linux-i3c, Joao.Pinto; +Cc: Boris Brezillon, linux-kernel, Vitor Soares
This patch add limited bus mode support for DesignWare i3c master
Signed-off-by: Vitor Soares <vitor.soares@synopsys.com>
Cc: Boris Brezillon <bbrezillon@kernel.org>
Cc: <linux-kernel@vger.kernel.org>
---
Changes in v4:
None
Changes in v3:
None
Changes in v2:
None
drivers/i3c/master/dw-i3c-master.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index 1d83c97..9612d93 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -599,6 +599,7 @@ static int dw_i3c_master_bus_init(struct i3c_master_controller *m)
switch (bus->mode) {
case I3C_BUS_MODE_MIXED_FAST:
+ case I3C_BUS_MODE_MIXED_LIMITED:
ret = dw_i2c_clk_cfg(master);
if (ret)
return ret;
--
2.7.4
_______________________________________________
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v4 0/3] Fix i2c and i3c scl rate according bus mode
2019-06-19 18:36 [PATCH v4 0/3] Fix i2c and i3c scl rate according bus mode Vitor Soares
` (2 preceding siblings ...)
2019-06-19 18:36 ` [PATCH v4 3/3] i3c: dw: add limited bus mode support Vitor Soares
@ 2019-06-20 8:56 ` Boris Brezillon
3 siblings, 0 replies; 5+ messages in thread
From: Boris Brezillon @ 2019-06-20 8:56 UTC (permalink / raw)
To: Vitor Soares; +Cc: linux-i3c, Joao.Pinto
On Wed, 19 Jun 2019 20:36:30 +0200
Vitor Soares <Vitor.Soares@synopsys.com> wrote:
> This patch series fix the i2c and i3c scl rate according the bus mode
> and LVR register. It also introduce the mixed limited bus for the
> cases where i2c devices doesn't have 50 ns filter but allow higher
> clock rate for i3c transfers.
> Please refer table 5 and 10 of i3c bus spec v1.0 for more detail.
>
> Please follow each patch commit message for more details and changes
> made in this version.
>
> Vitor Soares (3):
> i3c: fix i2c and i3c scl rate by bus mode
> i3c: add mixed limited bus mode
> i3c: dw: add limited bus mode support
Queued to i3c/next.
Thanks,
Boris
>
> drivers/i3c/master.c | 57 +++++++++++++++++++++++++++++---------
> drivers/i3c/master/dw-i3c-master.c | 1 +
> include/linux/i3c/master.h | 5 ++++
> 3 files changed, 50 insertions(+), 13 deletions(-)
>
_______________________________________________
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
^ permalink raw reply [flat|nested] 5+ messages in thread