diff mbox

[v2] p8/i2c: Add OPAL properties in the i2c bus nodes

Message ID 20150203062507.1646.53253.stgit@localhost.localdomain
State Changes Requested
Headers show

Commit Message

Neelesh Gupta Feb. 3, 2015, 6:25 a.m. UTC
We are getting the i2c device tree data from the hostboot and it
shows i2cm nodes compatible to multiple chips like p8 and centaur.
The patch further adds the OPAL properties to the i2c bus nodes
required by the kernel.

Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
---
 hw/p8-i2c.c |  263 +++++++++++++++++++++++++++++++++++------------------------
 1 file changed, 157 insertions(+), 106 deletions(-)

Comments

Neelesh Gupta Feb. 3, 2015, 6:47 a.m. UTC | #1
On 02/03/2015 11:55 AM, Neelesh Gupta wrote:
> We are getting the i2c device tree data from the hostboot and it
> shows i2cm nodes compatible to multiple chips like p8 and centaur.
> The patch further adds the OPAL properties to the i2c bus nodes
> required by the kernel.
>
> Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
> ---
>   hw/p8-i2c.c |  263 +++++++++++++++++++++++++++++++++++------------------------
>   1 file changed, 157 insertions(+), 106 deletions(-)
>
> diff --git a/hw/p8-i2c.c b/hw/p8-i2c.c
> index 3e5334c..7042b50 100644
> --- a/hw/p8-i2c.c
> +++ b/hw/p8-i2c.c
> @@ -1105,6 +1105,50 @@ void p8_i2c_interrupt(uint32_t chip_id)
>   	}
>   }
>   
> +enum i2c_host {
> +	I2C_POWER8,
> +	I2C_CENTAUR,
> +	MAX_I2C_HOSTS,
> +};
> +
> +static const char *compat[] = {
> +	"ibm,power8-i2cm",
> +	"ibm,centaur-i2cm"
> +};
> +
> +static void p8_i2c_add_bus_prop(enum i2c_host chip, struct dt_node *i2cm_port,
> +				struct p8_i2c_master_port *port)
> +{
> +	const struct dt_property *c, *p;
> +	char name[32];
> +
> +	c = dt_find_property(i2cm_port, "compatible");
> +	p = dt_find_property(i2cm_port, "ibm,port-name");

i) These are OPAL properties and should actually be added by skiboot driver
*only* so I guess it is needless to check if they exist already or not. But,
at the moment, it might have been added by PLAT code or from HB (Dan
told me he is adding 'ibm,port-name' in HB to avoid crash with current
op-build pointing to..)
     So, putting a check to avoid duplication of these properties.

ii) Not updating the "status" property for the i2c devices as I'm not sure
     which we are reserving and which one not.

Neelesh.

> +
> +	if (!c) {
> +		if (chip == I2C_POWER8)
> +			dt_add_property_strings(i2cm_port, "compatible",
> +						"ibm,power8-i2c-port",
> +						"ibm,opal-i2c");
> +		else if (chip == I2C_CENTAUR)
> +			dt_add_property_strings(i2cm_port, "compatible",
> +						"ibm,centaur-i2c-port",
> +						"ibm,opal-i2c");
> +	}
> +
> +	if (!p) {
> +		if (chip == I2C_POWER8)
> +			snprintf(name, sizeof(name), "p8_%08x_e%dp%d",
> +				 port->master->chip_id, port->master->engine_id,
> +				 port->port_num);
> +		else if (chip == I2C_CENTAUR)
> +			snprintf(name, sizeof(name), "cen_%08x_e%dp%d",
> +				 port->master->chip_id, port->master->engine_id,
> +				 port->port_num);
> +
> +		dt_add_property_string(i2cm_port, "ibm,port-name", name);
> +	}
> +}
>
Stewart Smith Feb. 4, 2015, 3:03 a.m. UTC | #2
Neelesh Gupta <neelegup@linux.vnet.ibm.com> writes:
> We are getting the i2c device tree data from the hostboot and it
> shows i2cm nodes compatible to multiple chips like p8 and centaur.
> The patch further adds the OPAL properties to the i2c bus nodes
> required by the kernel.

I'd love to see an addition to doc/device-tree/ along with this patch!

(as well as a diff as to what DT is generated to explain the change)


> Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
> ---
>  hw/p8-i2c.c |  263 +++++++++++++++++++++++++++++++++++------------------------
>  1 file changed, 157 insertions(+), 106 deletions(-)
>
> diff --git a/hw/p8-i2c.c b/hw/p8-i2c.c
> index 3e5334c..7042b50 100644
> --- a/hw/p8-i2c.c
> +++ b/hw/p8-i2c.c
> @@ -1105,6 +1105,50 @@ void p8_i2c_interrupt(uint32_t chip_id)
>  	}
>  }
>  
> +enum i2c_host {
> +	I2C_POWER8,
> +	I2C_CENTAUR,
> +	MAX_I2C_HOSTS,
> +};
> +
> +static const char *compat[] = {
> +	"ibm,power8-i2cm",
> +	"ibm,centaur-i2cm"
> +};
> +
> +static void p8_i2c_add_bus_prop(enum i2c_host chip, struct dt_node *i2cm_port,
> +				struct p8_i2c_master_port *port)
> +{
> +	const struct dt_property *c, *p;
> +	char name[32];
> +
> +	c = dt_find_property(i2cm_port, "compatible");
> +	p = dt_find_property(i2cm_port, "ibm,port-name");
> +
> +	if (!c) {
> +		if (chip == I2C_POWER8)
> +			dt_add_property_strings(i2cm_port, "compatible",
> +						"ibm,power8-i2c-port",
> +						"ibm,opal-i2c");
> +		else if (chip == I2C_CENTAUR)
> +			dt_add_property_strings(i2cm_port, "compatible",
> +						"ibm,centaur-i2c-port",
> +						"ibm,opal-i2c");
> +	}
> +
> +	if (!p) {
> +		if (chip == I2C_POWER8)
> +			snprintf(name, sizeof(name), "p8_%08x_e%dp%d",
> +				 port->master->chip_id, port->master->engine_id,
> +				 port->port_num);
> +		else if (chip == I2C_CENTAUR)
> +			snprintf(name, sizeof(name), "cen_%08x_e%dp%d",
> +				 port->master->chip_id, port->master->engine_id,
> +				 port->port_num);
> +
> +		dt_add_property_string(i2cm_port, "ibm,port-name", name);
> +	}
> +}
>  void p8_i2c_init(void)
>  {
>  	struct p8_i2c_master_port *port;
> @@ -1114,112 +1158,119 @@ void p8_i2c_init(void)
>  	struct proc_chip *chip;
>  	uint64_t ex_stat;
>  	static bool irq_printed;
> -	int rc;
> -
> -	dt_for_each_compatible(dt_root, i2cm, "ibm,power8-i2cm") {
> -		master = zalloc(sizeof(*master));
> -		if (!master) {
> -			log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: "
> -				     "Failed to allocate master structure\n");
> -			break;
> -		}
> -
> -		/* Local bus speed in Hz */
> -		lb_freq = dt_prop_get_u32(i2cm, "clock-frequency");
> -
> -		/* Initialise the i2c master structure */
> -		master->state = state_idle;
> -		master->chip_id = dt_get_chip_id(i2cm);
> -		master->engine_id = dt_prop_get_u32(i2cm, "chip-engine#");
> -		master->xscom_base = dt_get_address(i2cm, 0, NULL);
> -		chip = get_chip(master->chip_id);
> -		assert(chip);
> -		init_timer(&master->timeout, p8_i2c_timeout, master);
> -		init_timer(&master->poller, p8_i2c_poll, master);
> -
> -		prlog(PR_INFO, "I2C: Chip %08x Eng. %d\n",
> -		      master->chip_id, master->engine_id);
> -
> -		rc = xscom_read(master->chip_id, master->xscom_base +
> -				I2C_EXTD_STAT_REG, &ex_stat);
> -		if (rc) {
> -			log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: "
> -					 "Failed to read EXTD_STAT_REG\n");
> -			free(master);
> -			break;
> -		}
> -
> -		master->fifo_size = GETFIELD(I2C_EXTD_STAT_FIFO_SIZE, ex_stat);
> -		list_head_init(&master->req_list);
> -
> -		/* Check if interrupt is usable */
> -		master->irq_ok = p8_i2c_has_irqs();
> -		if (!irq_printed) {
> -			irq_printed = true;
> -			prlog(PR_INFO, "I2C: Interrupts %sfunctional\n",
> -			      master->irq_ok ? "" : "non-");
> -		}
> -
> -		/* Program the watermark register */
> -		rc = p8_i2c_prog_watermark(master);
> -		if (rc) {
> -			log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: "
> -					 "Failed to program the WATERMARK_REG\n");
> -			free(master);
> -			break;
> -		}
> -
> -		/* Allocate ports driven by this master */
> -		count = 0;
> -		dt_for_each_child(i2cm, i2cm_port)
> -			count++;
> -
> -		port = zalloc(sizeof(*port) * count);
> -		if (!port) {
> -			log_simple_error(&e_info(OPAL_RC_I2C_INIT),
> -					 "I2C: Insufficient memory\n");
> -			free(master);
> -			break;
> +	int rc, i;
> +
> +	for (i = 0; i < MAX_I2C_HOSTS; i++) {
> +		dt_for_each_compatible(dt_root, i2cm, compat[i]) {
> +			master = zalloc(sizeof(*master));
> +			if (!master) {
> +				log_simple_error(&e_info(OPAL_RC_I2C_INIT),
> +					"I2C: Failed to allocate master "
> +					"structure\n");
> +				break;
> +			}
> +
> +			/* Local bus speed in Hz */
> +			lb_freq = dt_prop_get_u32(i2cm, "clock-frequency");
> +
> +			/* Initialise the i2c master structure */
> +			master->state = state_idle;
> +			master->chip_id = dt_get_chip_id(i2cm);
> +			master->engine_id = dt_prop_get_u32(i2cm, "chip-engine#");
> +			master->xscom_base = dt_get_address(i2cm, 0, NULL);
> +			chip = get_chip(master->chip_id);
> +			assert(chip);
> +			init_timer(&master->timeout, p8_i2c_timeout, master);
> +			init_timer(&master->poller, p8_i2c_poll, master);
> +
> +			prlog(PR_INFO, "I2C: Chip %08x Eng. %d\n",
> +			      master->chip_id, master->engine_id);
> +
> +			rc = xscom_read(master->chip_id, master->xscom_base +
> +					I2C_EXTD_STAT_REG, &ex_stat);
> +			if (rc) {
> +				log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: "
> +						 "Failed to read EXTD_STAT_REG\n");
> +				free(master);
> +				break;
> +			}
> +
> +			master->fifo_size = GETFIELD(I2C_EXTD_STAT_FIFO_SIZE,
> +						     ex_stat);
> +			list_head_init(&master->req_list);
> +
> +			/* Check if interrupt is usable */
> +			master->irq_ok = p8_i2c_has_irqs();
> +			if (!irq_printed) {
> +				irq_printed = true;
> +				prlog(PR_INFO, "I2C: Interrupts %sfunctional\n",
> +				      master->irq_ok ? "" : "non-");
> +			}
> +
> +			/* Program the watermark register */
> +			rc = p8_i2c_prog_watermark(master);
> +			if (rc) {
> +				log_simple_error(&e_info(OPAL_RC_I2C_INIT),
> +					"I2C: Failed to program the "
> +					"WATERMARK_REG\n");
> +				free(master);
> +				break;
> +			}
> +
> +			/* Allocate ports driven by this master */
> +			count = 0;
> +			dt_for_each_child(i2cm, i2cm_port)
> +				count++;
> +
> +			port = zalloc(sizeof(*port) * count);
> +			if (!port) {
> +				log_simple_error(&e_info(OPAL_RC_I2C_INIT),
> +						 "I2C: Insufficient memory\n");
> +				free(master);
> +				break;
> +			}
> +
> +			/* Add master to chip's list */
> +			list_add_tail(&chip->i2cms, &master->link);
> +			max_bus_speed = 0;
> +
> +			dt_for_each_child(i2cm, i2cm_port) {
> +				uint32_t speed;
> +
> +				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->bit_rate_div =
> +					p8_i2c_get_bit_rate_divisor(lb_freq, speed);
> +				port->bus.dt_node = i2cm_port;
> +				port->bus.queue_req = p8_i2c_queue_request;
> +				port->bus.alloc_req = p8_i2c_alloc_request;
> +				port->bus.free_req = p8_i2c_free_request;
> +				i2c_add_bus(&port->bus);
> +				/* Add OPAL properties to the bus node */
> +				p8_i2c_add_bus_prop(i, i2cm_port, port);
> +				prlog(PR_INFO, " P%d: <%s> %d kHz\n",
> +				      port->port_num,
> +				      (char *)dt_prop_get(i2cm_port,
> +						  "ibm,port-name"), speed/1000);
> +				port++;
> +			}
> +
> +			/* If we have no interrupt, calculate a poll interval,
> +			 * otherwise just use a TIMER_POLL timer which will tick
> +			 * on OPAL pollers only (which allows us to operate
> +			 * during boot before interrupts are functional etc...
> +			 */
> +			if (master->irq_ok)
> +				master->poll_interval = TIMER_POLL;
> +			else
> +				master->poll_interval =
> +					p8_i2c_get_poll_interval(max_bus_speed);
> +			master->byte_timeout = master->irq_ok ?
> +				msecs_to_tb(I2C_TIMEOUT_IRQ_MS) :
> +				msecs_to_tb(I2C_TIMEOUT_POLL_MS);
>  		}
> -
> -		/* Add master to chip's list */
> -		list_add_tail(&chip->i2cms, &master->link);
> -		max_bus_speed = 0;
> -
> -		dt_for_each_child(i2cm, i2cm_port) {
> -			uint32_t speed;
> -
> -			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->bit_rate_div =
> -				p8_i2c_get_bit_rate_divisor(lb_freq, speed);
> -			port->bus.dt_node = i2cm_port;
> -			port->bus.queue_req = p8_i2c_queue_request;
> -			port->bus.alloc_req = p8_i2c_alloc_request;
> -			port->bus.free_req = p8_i2c_free_request;
> -			i2c_add_bus(&port->bus);
> -			prlog(PR_INFO, " P%d: <%s> %d kHz\n",
> -			      port->port_num,
> -			      (char *)dt_prop_get(i2cm_port, "ibm,port-name"),
> -			      speed/1000);
> -			port++;
> -		}
> -
> -		/* If we have no interrupt, calculate a poll interval, otherwise
> -		 * just use a TIMER_POLL timer which will tick on OPAL pollers
> -		 * only (which allows us to operate during boot before
> -		 * interrupts are functional etc...
> -		 */
> -		if (master->irq_ok)
> -			master->poll_interval = TIMER_POLL;
> -		else
> -			master->poll_interval =
> -				p8_i2c_get_poll_interval(max_bus_speed);
> -		master->byte_timeout = master->irq_ok ?
> -			msecs_to_tb(I2C_TIMEOUT_IRQ_MS) :
> -			msecs_to_tb(I2C_TIMEOUT_POLL_MS);
>  	}
>  }
>
> _______________________________________________
> Skiboot mailing list
> Skiboot@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot
Neelesh Gupta Feb. 4, 2015, 6:42 a.m. UTC | #3
On 02/04/2015 08:33 AM, Stewart Smith wrote:
> Neelesh Gupta <neelegup@linux.vnet.ibm.com> writes:
>> We are getting the i2c device tree data from the hostboot and it
>> shows i2cm nodes compatible to multiple chips like p8 and centaur.
>> The patch further adds the OPAL properties to the i2c bus nodes
>> required by the kernel.
> I'd love to see an addition to doc/device-tree/ along with this patch!

I will add one.
>
> (as well as a diff as to what DT is generated to explain the change)

Have not received the hostboot changes yet. So, in a way it is not tested.

Neelesh.

>
>
>> Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
>> ---
>>   hw/p8-i2c.c |  263 +++++++++++++++++++++++++++++++++++------------------------
>>   1 file changed, 157 insertions(+), 106 deletions(-)
>>
>> diff --git a/hw/p8-i2c.c b/hw/p8-i2c.c
>> index 3e5334c..7042b50 100644
>> --- a/hw/p8-i2c.c
>> +++ b/hw/p8-i2c.c
>> @@ -1105,6 +1105,50 @@ void p8_i2c_interrupt(uint32_t chip_id)
>>   	}
>>   }
>>   
>>
diff mbox

Patch

diff --git a/hw/p8-i2c.c b/hw/p8-i2c.c
index 3e5334c..7042b50 100644
--- a/hw/p8-i2c.c
+++ b/hw/p8-i2c.c
@@ -1105,6 +1105,50 @@  void p8_i2c_interrupt(uint32_t chip_id)
 	}
 }
 
+enum i2c_host {
+	I2C_POWER8,
+	I2C_CENTAUR,
+	MAX_I2C_HOSTS,
+};
+
+static const char *compat[] = {
+	"ibm,power8-i2cm",
+	"ibm,centaur-i2cm"
+};
+
+static void p8_i2c_add_bus_prop(enum i2c_host chip, struct dt_node *i2cm_port,
+				struct p8_i2c_master_port *port)
+{
+	const struct dt_property *c, *p;
+	char name[32];
+
+	c = dt_find_property(i2cm_port, "compatible");
+	p = dt_find_property(i2cm_port, "ibm,port-name");
+
+	if (!c) {
+		if (chip == I2C_POWER8)
+			dt_add_property_strings(i2cm_port, "compatible",
+						"ibm,power8-i2c-port",
+						"ibm,opal-i2c");
+		else if (chip == I2C_CENTAUR)
+			dt_add_property_strings(i2cm_port, "compatible",
+						"ibm,centaur-i2c-port",
+						"ibm,opal-i2c");
+	}
+
+	if (!p) {
+		if (chip == I2C_POWER8)
+			snprintf(name, sizeof(name), "p8_%08x_e%dp%d",
+				 port->master->chip_id, port->master->engine_id,
+				 port->port_num);
+		else if (chip == I2C_CENTAUR)
+			snprintf(name, sizeof(name), "cen_%08x_e%dp%d",
+				 port->master->chip_id, port->master->engine_id,
+				 port->port_num);
+
+		dt_add_property_string(i2cm_port, "ibm,port-name", name);
+	}
+}
 void p8_i2c_init(void)
 {
 	struct p8_i2c_master_port *port;
@@ -1114,112 +1158,119 @@  void p8_i2c_init(void)
 	struct proc_chip *chip;
 	uint64_t ex_stat;
 	static bool irq_printed;
-	int rc;
-
-	dt_for_each_compatible(dt_root, i2cm, "ibm,power8-i2cm") {
-		master = zalloc(sizeof(*master));
-		if (!master) {
-			log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: "
-				     "Failed to allocate master structure\n");
-			break;
-		}
-
-		/* Local bus speed in Hz */
-		lb_freq = dt_prop_get_u32(i2cm, "clock-frequency");
-
-		/* Initialise the i2c master structure */
-		master->state = state_idle;
-		master->chip_id = dt_get_chip_id(i2cm);
-		master->engine_id = dt_prop_get_u32(i2cm, "chip-engine#");
-		master->xscom_base = dt_get_address(i2cm, 0, NULL);
-		chip = get_chip(master->chip_id);
-		assert(chip);
-		init_timer(&master->timeout, p8_i2c_timeout, master);
-		init_timer(&master->poller, p8_i2c_poll, master);
-
-		prlog(PR_INFO, "I2C: Chip %08x Eng. %d\n",
-		      master->chip_id, master->engine_id);
-
-		rc = xscom_read(master->chip_id, master->xscom_base +
-				I2C_EXTD_STAT_REG, &ex_stat);
-		if (rc) {
-			log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: "
-					 "Failed to read EXTD_STAT_REG\n");
-			free(master);
-			break;
-		}
-
-		master->fifo_size = GETFIELD(I2C_EXTD_STAT_FIFO_SIZE, ex_stat);
-		list_head_init(&master->req_list);
-
-		/* Check if interrupt is usable */
-		master->irq_ok = p8_i2c_has_irqs();
-		if (!irq_printed) {
-			irq_printed = true;
-			prlog(PR_INFO, "I2C: Interrupts %sfunctional\n",
-			      master->irq_ok ? "" : "non-");
-		}
-
-		/* Program the watermark register */
-		rc = p8_i2c_prog_watermark(master);
-		if (rc) {
-			log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: "
-					 "Failed to program the WATERMARK_REG\n");
-			free(master);
-			break;
-		}
-
-		/* Allocate ports driven by this master */
-		count = 0;
-		dt_for_each_child(i2cm, i2cm_port)
-			count++;
-
-		port = zalloc(sizeof(*port) * count);
-		if (!port) {
-			log_simple_error(&e_info(OPAL_RC_I2C_INIT),
-					 "I2C: Insufficient memory\n");
-			free(master);
-			break;
+	int rc, i;
+
+	for (i = 0; i < MAX_I2C_HOSTS; i++) {
+		dt_for_each_compatible(dt_root, i2cm, compat[i]) {
+			master = zalloc(sizeof(*master));
+			if (!master) {
+				log_simple_error(&e_info(OPAL_RC_I2C_INIT),
+					"I2C: Failed to allocate master "
+					"structure\n");
+				break;
+			}
+
+			/* Local bus speed in Hz */
+			lb_freq = dt_prop_get_u32(i2cm, "clock-frequency");
+
+			/* Initialise the i2c master structure */
+			master->state = state_idle;
+			master->chip_id = dt_get_chip_id(i2cm);
+			master->engine_id = dt_prop_get_u32(i2cm, "chip-engine#");
+			master->xscom_base = dt_get_address(i2cm, 0, NULL);
+			chip = get_chip(master->chip_id);
+			assert(chip);
+			init_timer(&master->timeout, p8_i2c_timeout, master);
+			init_timer(&master->poller, p8_i2c_poll, master);
+
+			prlog(PR_INFO, "I2C: Chip %08x Eng. %d\n",
+			      master->chip_id, master->engine_id);
+
+			rc = xscom_read(master->chip_id, master->xscom_base +
+					I2C_EXTD_STAT_REG, &ex_stat);
+			if (rc) {
+				log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: "
+						 "Failed to read EXTD_STAT_REG\n");
+				free(master);
+				break;
+			}
+
+			master->fifo_size = GETFIELD(I2C_EXTD_STAT_FIFO_SIZE,
+						     ex_stat);
+			list_head_init(&master->req_list);
+
+			/* Check if interrupt is usable */
+			master->irq_ok = p8_i2c_has_irqs();
+			if (!irq_printed) {
+				irq_printed = true;
+				prlog(PR_INFO, "I2C: Interrupts %sfunctional\n",
+				      master->irq_ok ? "" : "non-");
+			}
+
+			/* Program the watermark register */
+			rc = p8_i2c_prog_watermark(master);
+			if (rc) {
+				log_simple_error(&e_info(OPAL_RC_I2C_INIT),
+					"I2C: Failed to program the "
+					"WATERMARK_REG\n");
+				free(master);
+				break;
+			}
+
+			/* Allocate ports driven by this master */
+			count = 0;
+			dt_for_each_child(i2cm, i2cm_port)
+				count++;
+
+			port = zalloc(sizeof(*port) * count);
+			if (!port) {
+				log_simple_error(&e_info(OPAL_RC_I2C_INIT),
+						 "I2C: Insufficient memory\n");
+				free(master);
+				break;
+			}
+
+			/* Add master to chip's list */
+			list_add_tail(&chip->i2cms, &master->link);
+			max_bus_speed = 0;
+
+			dt_for_each_child(i2cm, i2cm_port) {
+				uint32_t speed;
+
+				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->bit_rate_div =
+					p8_i2c_get_bit_rate_divisor(lb_freq, speed);
+				port->bus.dt_node = i2cm_port;
+				port->bus.queue_req = p8_i2c_queue_request;
+				port->bus.alloc_req = p8_i2c_alloc_request;
+				port->bus.free_req = p8_i2c_free_request;
+				i2c_add_bus(&port->bus);
+				/* Add OPAL properties to the bus node */
+				p8_i2c_add_bus_prop(i, i2cm_port, port);
+				prlog(PR_INFO, " P%d: <%s> %d kHz\n",
+				      port->port_num,
+				      (char *)dt_prop_get(i2cm_port,
+						  "ibm,port-name"), speed/1000);
+				port++;
+			}
+
+			/* If we have no interrupt, calculate a poll interval,
+			 * otherwise just use a TIMER_POLL timer which will tick
+			 * on OPAL pollers only (which allows us to operate
+			 * during boot before interrupts are functional etc...
+			 */
+			if (master->irq_ok)
+				master->poll_interval = TIMER_POLL;
+			else
+				master->poll_interval =
+					p8_i2c_get_poll_interval(max_bus_speed);
+			master->byte_timeout = master->irq_ok ?
+				msecs_to_tb(I2C_TIMEOUT_IRQ_MS) :
+				msecs_to_tb(I2C_TIMEOUT_POLL_MS);
 		}
-
-		/* Add master to chip's list */
-		list_add_tail(&chip->i2cms, &master->link);
-		max_bus_speed = 0;
-
-		dt_for_each_child(i2cm, i2cm_port) {
-			uint32_t speed;
-
-			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->bit_rate_div =
-				p8_i2c_get_bit_rate_divisor(lb_freq, speed);
-			port->bus.dt_node = i2cm_port;
-			port->bus.queue_req = p8_i2c_queue_request;
-			port->bus.alloc_req = p8_i2c_alloc_request;
-			port->bus.free_req = p8_i2c_free_request;
-			i2c_add_bus(&port->bus);
-			prlog(PR_INFO, " P%d: <%s> %d kHz\n",
-			      port->port_num,
-			      (char *)dt_prop_get(i2cm_port, "ibm,port-name"),
-			      speed/1000);
-			port++;
-		}
-
-		/* If we have no interrupt, calculate a poll interval, otherwise
-		 * just use a TIMER_POLL timer which will tick on OPAL pollers
-		 * only (which allows us to operate during boot before
-		 * interrupts are functional etc...
-		 */
-		if (master->irq_ok)
-			master->poll_interval = TIMER_POLL;
-		else
-			master->poll_interval =
-				p8_i2c_get_poll_interval(max_bus_speed);
-		master->byte_timeout = master->irq_ok ?
-			msecs_to_tb(I2C_TIMEOUT_IRQ_MS) :
-			msecs_to_tb(I2C_TIMEOUT_POLL_MS);
 	}
 }