[Skiboot] [PATCH 07/10] hw/p8-i2c: Set poll interval from the current port

Oliver O'Halloran oohall at gmail.com
Mon Oct 12 13:53:11 AEDT 2020


The rate at which we need to poll the master depends on the speed of the
bus. Faster I2C buses will require more frequent polling so it doesn't
make a whole lot of sense to set this on a per-master basis. This patch
sets the master's polling interval to a per-port setting calculated
from the port speed.

Signed-off-by: Oliver O'Halloran <oohall at gmail.com>
---
 hw/p8-i2c.c | 23 +++++++----------------
 1 file changed, 7 insertions(+), 16 deletions(-)

diff --git a/hw/p8-i2c.c b/hw/p8-i2c.c
index 78f1e7e32932..f01cbe8a0870 100644
--- a/hw/p8-i2c.c
+++ b/hw/p8-i2c.c
@@ -234,6 +234,7 @@ struct p8_i2c_master_port {
 	uint32_t		port_num;
 	uint32_t		bit_rate_div;	/* Divisor to set bus speed*/
 	uint64_t		byte_timeout;	/* Timeout per byte */
+	uint64_t		poll_interval;	/* Polling interval */
 	struct list_node	link;
 };
 
@@ -1017,7 +1018,7 @@ static int p8_i2c_start_request(struct p8_i2c_master *master,
 				struct i2c_request *req)
 {
 	struct p8_i2c_master_port *port;
-	uint64_t cmd, poll_interval;
+	uint64_t cmd;
 	int64_t rc;
 
 	DBG("Starting req %d len=%d addr=%02x (offset=%x)\n",
@@ -1152,10 +1153,10 @@ static int p8_i2c_start_request(struct p8_i2c_master *master,
 	 * cases
 	 */
 	if (!opal_booting() && master->irq_ok)
-		poll_interval = TIMER_POLL;
+		master->poll_interval = TIMER_POLL;
 	else
-		poll_interval = master->poll_interval;
-	schedule_timer(&master->poller, poll_interval);
+		master->poll_interval = port->poll_interval;
+	schedule_timer(&master->poller, master->poll_interval);
 
 	/* If we don't have a user-set timeout then use the master's default */
 	if (!req->timeout)
@@ -1442,7 +1443,7 @@ static void p8_i2c_add_bus_prop(struct p8_i2c_master_port *port)
 static void p8_i2c_init_one(struct dt_node *i2cm, enum p8_i2c_master_type type)
 {
 	struct p8_i2c_master_port *port;
-	uint32_t lb_freq, count, max_bus_speed;
+	uint32_t lb_freq, count;
 	struct dt_node *i2cm_port;
 	struct p8_i2c_master *master;
 	struct list_head *chip_list;
@@ -1547,7 +1548,6 @@ static void p8_i2c_init_one(struct dt_node *i2cm, enum p8_i2c_master_type type)
 
 	/* Add master to chip's list */
 	list_add_tail(chip_list, &master->link);
-	max_bus_speed = 0;
 
 	default_timeout = master->irq_ok ?
 		I2C_TIMEOUT_IRQ_MS :
@@ -1559,8 +1559,7 @@ static void p8_i2c_init_one(struct dt_node *i2cm, enum p8_i2c_master_type type)
 		port->port_num = dt_prop_get_u32(i2cm_port, "reg");
 		port->master = master;
 		speed = dt_prop_get_u32(i2cm_port, "bus-frequency");
-		if (speed > max_bus_speed)
-			max_bus_speed = speed;
+		port->poll_interval = p8_i2c_get_poll_interval(speed);
 		port->bit_rate_div =
 			p8_i2c_get_bit_rate_divisor(lb_freq, speed);
 		port->bus.dt_node = i2cm_port;
@@ -1581,14 +1580,6 @@ static void p8_i2c_init_one(struct dt_node *i2cm, enum p8_i2c_master_type type)
 					  "ibm,port-name"), speed/1000);
 		port++;
 	}
-
-	/* When at runtime and we have the i2c irq, we just use it
-	 * (see p8_i2c_start_request), but in the situation where
-	 * one of those isn't the case (e.g. during boot), we need
-	 * a better poll interval to efficiently crank the i2c machine.
-	 * poll_interval is that interval.
-	 */
-	master->poll_interval = (max_bus_speed) ? p8_i2c_get_poll_interval(max_bus_speed) : TIMER_POLL;
 }
 
 void p8_i2c_init(void)
-- 
2.26.2



More information about the Skiboot mailing list