From patchwork Tue Feb 3 06:25:52 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neelesh Gupta X-Patchwork-Id: 435710 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id BFF011401DE for ; Tue, 3 Feb 2015 17:28:06 +1100 (AEDT) Received: from ozlabs.org (ozlabs.org [103.22.144.67]) by lists.ozlabs.org (Postfix) with ESMTP id AEAD31A0D89 for ; Tue, 3 Feb 2015 17:28:06 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from e28smtp08.in.ibm.com (e28smtp08.in.ibm.com [122.248.162.8]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 1A8531A0D6A for ; Tue, 3 Feb 2015 17:28:02 +1100 (AEDT) Received: from /spool/local by e28smtp08.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 3 Feb 2015 11:58:00 +0530 Received: from d28dlp01.in.ibm.com (9.184.220.126) by e28smtp08.in.ibm.com (192.168.1.138) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 3 Feb 2015 11:57:59 +0530 Received: from d28relay01.in.ibm.com (d28relay01.in.ibm.com [9.184.220.58]) by d28dlp01.in.ibm.com (Postfix) with ESMTP id 8AAC8E0045 for ; Tue, 3 Feb 2015 11:59:24 +0530 (IST) Received: from d28av03.in.ibm.com (d28av03.in.ibm.com [9.184.220.65]) by d28relay01.in.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t136RuQ243384844 for ; Tue, 3 Feb 2015 11:57:57 +0530 Received: from d28av03.in.ibm.com (localhost [127.0.0.1]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t136RuBc030005 for ; Tue, 3 Feb 2015 11:57:56 +0530 Received: from localhost.localdomain ([9.124.35.239]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t136Rt7o029963 for ; Tue, 3 Feb 2015 11:57:55 +0530 To: skiboot@lists.ozlabs.org From: Neelesh Gupta Date: Tue, 03 Feb 2015 11:55:52 +0530 Message-ID: <20150203062507.1646.53253.stgit@localhost.localdomain> User-Agent: StGit/0.16 MIME-Version: 1.0 X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15020306-0029-0000-0000-0000044C95DD Subject: [Skiboot] [PATCH v2] p8/i2c: Add OPAL properties in the i2c bus nodes X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" 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 --- 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); } }