Skip to contentSkip to conversation

i2c: fsi: Create busses for all ports

PATCH Applied Oliver O'Halloran 3 participants 3 messages Jun 6, 2019 – Jun 7, 2019

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 i2c: fsi: Create busses for all ports

Currently we only create an I2C bus for the ports listed in the device-tree for that master. There's no real reason for this since we can discover the number of ports the master supports by looking at the port_max field of the status register.

This patch re-works the bus add logic so that we always create buses for each port, unless the bus is marked as unavailable in the DT. This is useful since it ensures that all the buses provided by the CFAM I2C master are accessible to debug tools.

---
v2: Fixed off-by-one when calulating the number of ports.
Compile fixes.

---
 drivers/i2c/busses/i2c-fsi.c | 32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)
drivers/i2c/busses/i2c-fsi.c +27 -5
index 1e2be2219a60..da5eb3960def 100644
@@ -658,13 +658,29 @@ static const struct i2c_algorithm fsi_i2c_algorithm = {
 	.functionality = fsi_i2c_functionality,
 };
 
+static struct device_node *fsi_i2c_find_port_of_node(struct device_node *fsi,
+						     int port)
+{
+	struct device_node *np;
+	u32 port_no;
+	int rc;
+
+	for_each_child_of_node(fsi, np) {
+		rc = of_property_read_u32(np, "reg", &port_no);
+		if (!rc && port_no == port)
+			return np;
+	}
+
+	return NULL;
+}
+
 static int fsi_i2c_probe(struct device *dev)
 {
 	struct fsi_i2c_master *i2c;
 	struct fsi_i2c_port *port;
 	struct device_node *np;
+	u32 port_no, ports, stat;
 	int rc;
-	u32 port_no;
 
 	i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
 	if (!i2c)
@@ -678,10 +694,16 @@ static int fsi_i2c_probe(struct device *dev)
 	if (rc)
 		return rc;
 
-	/* Add adapter for each i2c port of the master. */
-	for_each_available_child_of_node(dev->of_node, np) {
-		rc = of_property_read_u32(np, "reg", &port_no);
-		if (rc || port_no > USHRT_MAX)
+	rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat);
+	if (rc)
+		return rc;
+
+	ports = FIELD_GET(I2C_STAT_MAX_PORT, stat) + 1;
+	dev_dbg(dev, "I2C master has %d ports\n", ports);
+
+	for (port_no = 0; port_no < ports; port_no++) {
+		np = fsi_i2c_find_port_of_node(dev->of_node, port_no);
+		if (np && !of_device_is_available(np))
 			continue;
 
 		port = kzalloc(sizeof(*port), GFP_KERNEL);
Signature · 1 line
2.21.0
maintainer Reviewed-by on v2 1/1
#1 lore raw
Quoted 9 lines · Oliver O'Halloran

Currently we only create an I2C bus for the ports listed in the device-tree for that master. There's no real reason for this since we can discover the number of ports the master supports by looking at the port_max field of the status register.

This patch re-works the bus add logic so that we always create buses for each port, unless the bus is marked as unavailable in the DT. This is useful since it ensures that all the buses provided by the CFAM I2C master are accessible to debug tools.

Thanks Oliver.

Quoted 66 lines

---
v2: Fixed off-by-one when calulating the number of ports.
Compile fixes.

---
  drivers/i2c/busses/i2c-fsi.c | 32 +++++++++++++++++++++++++++-----
  1 file changed, 27 insertions(+), 5 deletions(-)
drivers/i2c/busses/i2c-fsi.c +27 -5
index 1e2be2219a60..da5eb3960def 100644
@@ -658,13 +658,29 @@ static const struct i2c_algorithm fsi_i2c_algorithm = {
  	.functionality = fsi_i2c_functionality,
  };
 
+static struct device_node *fsi_i2c_find_port_of_node(struct device_node *fsi,
+						     int port)
+{
+	struct device_node *np;
+	u32 port_no;
+	int rc;
+
+	for_each_child_of_node(fsi, np) {
+		rc = of_property_read_u32(np, "reg", &port_no);
+		if (!rc && port_no == port)
+			return np;
+	}
+
+	return NULL;
+}
+
  static int fsi_i2c_probe(struct device *dev)
  {
  	struct fsi_i2c_master *i2c;
  	struct fsi_i2c_port *port;
  	struct device_node *np;
+	u32 port_no, ports, stat;
  	int rc;
-	u32 port_no;
 
  	i2c = devm_kzalloc(dev, sizeof(*i2c), GFP_KERNEL);
  	if (!i2c)
@@ -678,10 +694,16 @@ static int fsi_i2c_probe(struct device *dev)
  	if (rc)
  		return rc;
 
-	/* Add adapter for each i2c port of the master. */
-	for_each_available_child_of_node(dev->of_node, np) {
-		rc = of_property_read_u32(np, "reg", &port_no);
-		if (rc || port_no > USHRT_MAX)
+	rc = fsi_i2c_read_reg(i2c->fsi, I2C_FSI_STAT, &stat);
+	if (rc)
+		return rc;
+
+	ports = FIELD_GET(I2C_STAT_MAX_PORT, stat) + 1;
+	dev_dbg(dev, "I2C master has %d ports\n", ports);
+
+	for (port_no = 0; port_no < ports; port_no++) {
+		np = fsi_i2c_find_port_of_node(dev->of_node, port_no);
+		if (np && !of_device_is_available(np))
  			continue;
 
  		port = kzalloc(sizeof(*port), GFP_KERNEL);
Applied
#2 lore raw
In reply to Oliver O'Halloran
Quoted 5 lines · Oliver O'Halloran

Currently we only create an I2C bus for the ports listed in the device-tree for that master. There's no real reason for this since we can discover the number of ports the master supports by looking at the port_max field of the status register.

Quoted 7 lines

This patch re-works the bus add logic so that we always create buses for each port, unless the bus is marked as unavailable in the DT. This is useful since it ensures that all the buses provided by the CFAM I2C master are accessible to debug tools.

Applied to for-next, thanks!