From patchwork Mon Oct 12 02:53:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver O'Halloran X-Patchwork-Id: 1380603 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [203.11.71.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4C8jzr4KGdz9s0b for ; Mon, 12 Oct 2020 13:58:32 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=n8MA7RTC; dkim-atps=neutral Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 4C8jzr1ySfzDqhC for ; Mon, 12 Oct 2020 13:58:32 +1100 (AEDT) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gmail.com (client-ip=2607:f8b0:4864:20::42e; helo=mail-pf1-x42e.google.com; envelope-from=oohall@gmail.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=n8MA7RTC; dkim-atps=neutral Received: from mail-pf1-x42e.google.com (mail-pf1-x42e.google.com [IPv6:2607:f8b0:4864:20::42e]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4C8jtW0yfDzDqhC for ; Mon, 12 Oct 2020 13:53:54 +1100 (AEDT) Received: by mail-pf1-x42e.google.com with SMTP id b26so12234064pff.3 for ; Sun, 11 Oct 2020 19:53:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bYVPqvNSIetxORTIC5HjZxPhYiweI7R+pR8YgdXpOhU=; b=n8MA7RTC1esGXH2AbjGs+MweyMjBB+CIxt52cqNBrlFe60GzUzAgZFPtDZaj5HhggX 7MndDTWg4BiTbEeliLsjJieYqHOHc8s2CdI/WzyLoM6y7DJzPF8LIh2jGS3vwnOGtTaF 2JgO/y2Iy9YHEax+NBGVvSpIhv+oYS4v++2QPvvas4JZWysbV7UQyEeKXFUaAo18Y4WZ YqAIZ2PiUBeeWTE7bybbhlXBsSPj+sd9ZzySOB1eSg7IAZOJrKRRG0aTSWrcLr0vNLKT rWpbDjaewEMFtqTzvW155KyIXW1uvJqNEsXEEo7JHul/QY+5vtFhoPQgKjwuCyr3ubyZ 9NCQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bYVPqvNSIetxORTIC5HjZxPhYiweI7R+pR8YgdXpOhU=; b=W2YNIwBIChTLTGF46azD7DyGj4iqH/ymYplaY/xWGohZexubgEiNTDEf6pPd9SI1Nb 0jqnLthveJt6kiGirplju1BVB/7t+KenyZNI/quFree2abMlIKVmVCxu6N7zUUj+K3Gm 2nwiZCqMd0BHLJzXxPU6RrcLRb53aJvIgSHyNkG639Lsq69PYYb5Sy5CakXb+Gy4h4yk nchT/k4xHaJ5ZhU0iwHtwFrWGhXhzXdyaCIUFOZs5CB14Anlxji+dla4dJinIwqdq4Yd Nxh1ACZaMJ/4Sqg4iWU/b/PEYnuhEpGw/bZcQqohqkX7oZWV5miRGulCIcMz4PGA8M1z W6Tg== X-Gm-Message-State: AOAM533HGjPTIQxU5sAVoY6f+EBVFl8op1gzQr372arP0fM69qZusUIE 5t6EanDYmEBGxJhfkdonpFDCdSweff9lcg== X-Google-Smtp-Source: ABdhPJw7Ngv3oRJFH19WyqYVXiZwtMwyZjWuDcMvaNnuG6O8I/dbyWY6IkeKmOjfqOH09jWgKX4Hvw== X-Received: by 2002:a17:90a:3984:: with SMTP id z4mr17097173pjb.131.1602471232119; Sun, 11 Oct 2020 19:53:52 -0700 (PDT) Received: from localhost.ibm.com (14-200-206-90.tpgi.com.au. [14.200.206.90]) by smtp.gmail.com with ESMTPSA id g4sm17909258pgg.75.2020.10.11.19.53.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 11 Oct 2020 19:53:51 -0700 (PDT) From: Oliver O'Halloran To: skiboot@lists.ozlabs.org Date: Mon, 12 Oct 2020 13:53:14 +1100 Message-Id: <20201012025314.1070230-10-oohall@gmail.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201012025314.1070230-1-oohall@gmail.com> References: <20201012025314.1070230-1-oohall@gmail.com> MIME-Version: 1.0 Subject: [Skiboot] [PATCH 10/10] hw/p8-i2c: Add buses at runtime X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 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" When booting skiboot we initialise any I2C masters after probing the platform, but before initialising the platform (or NVRAM). Due to this we need to ensure that all the I2C masters we might want to use are in the DT before the platform is initialised. This causes problems since we might want to add another master (e.g. on witherspoon we might need to add a port for the I2C OpenCAPI I2C bus). It's possible to hack around this by adding a new node in the probe function, but the probe function runs very early before many essential services are initialised (e.g. LPC). We might want to add another I2C bus after learning that we have a riser card installed and it's not possible to do that until later in boot. To accommodate those use cases we can add support for adding a new bus at runtime. Signed-off-by: Oliver O'Halloran --- hw/p8-i2c.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++----- include/i2c.h | 3 ++ 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/hw/p8-i2c.c b/hw/p8-i2c.c index 4abbad8673b4..59f85b1dfc14 100644 --- a/hw/p8-i2c.c +++ b/hw/p8-i2c.c @@ -196,6 +196,7 @@ enum p8_i2c_master_type { }; struct p8_i2c_master { + struct dt_node *dt_node; struct lock lock; /* Lock to guard the members */ enum p8_i2c_master_type type; /* P8 vs. Centaur */ uint64_t start_time; /* Request start time */ @@ -1441,10 +1442,10 @@ static void p8_i2c_add_bus_prop(struct p8_i2c_master_port *port) } static struct p8_i2c_master_port *p8_i2c_init_one_port(struct p8_i2c_master *m, - struct dt_node *n, uint64_t lb_freq) + struct dt_node *n) { struct p8_i2c_master_port *port; - uint64_t def_timeout; + uint64_t def_timeout, lb_freq; uint32_t speed, div; port = zalloc(sizeof(*port)); @@ -1453,6 +1454,7 @@ static struct p8_i2c_master_port *p8_i2c_init_one_port(struct p8_i2c_master *m, def_timeout = m->irq_ok ? I2C_TIMEOUT_IRQ_MS : I2C_TIMEOUT_POLL_MS; + lb_freq = dt_prop_get_u32_def(m->dt_node, "clock-frequency", 150000000); speed = dt_prop_get_u32_def(n, "bus-frequency", 100000); div = p8_i2c_get_bit_rate_divisor(lb_freq, speed); @@ -1479,7 +1481,8 @@ static struct p8_i2c_master_port *p8_i2c_init_one_port(struct p8_i2c_master *m, return port; } -static void p8_i2c_init_one(struct dt_node *i2cm, enum p8_i2c_master_type type) +static struct p8_i2c_master *p8_i2c_init_one(struct dt_node *i2cm, + enum p8_i2c_master_type type) { struct p8_i2c_master *master; struct list_head *chip_list; @@ -1493,7 +1496,7 @@ static void p8_i2c_init_one(struct dt_node *i2cm, enum p8_i2c_master_type type) log_simple_error(&e_info(OPAL_RC_I2C_INIT), "I2C: Failed to allocate master " "structure\n"); - return; + return NULL; } master->type = type; @@ -1505,6 +1508,7 @@ static void p8_i2c_init_one(struct dt_node *i2cm, enum p8_i2c_master_type type) 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); + master->dt_node = i2cm; if (master->type == I2C_CENTAUR) { struct centaur_chip *centaur = get_centaur(master->chip_id); if (centaur == NULL) { @@ -1512,7 +1516,7 @@ static void p8_i2c_init_one(struct dt_node *i2cm, enum p8_i2c_master_type type) "I2C: Failed to get centaur 0x%x ", master->chip_id); free(master); - return; + return NULL; } chip_list = ¢aur->i2cms; @@ -1522,7 +1526,7 @@ static void p8_i2c_init_one(struct dt_node *i2cm, enum p8_i2c_master_type type) if (master->engine_id > 0) { prlog(PR_ERR, "I2C: Skipping Centaur Master #1\n"); free(master); - return; + return NULL; } } else { struct proc_chip *chip = get_chip(master->chip_id); @@ -1560,7 +1564,7 @@ static void p8_i2c_init_one(struct dt_node *i2cm, enum p8_i2c_master_type type) centaur_enable_sensor_cache(master->chip_id); free(master); - return; + return NULL; } master->fifo_size = GETFIELD(I2C_EXTD_STAT_FIFO_SIZE, ex_stat); @@ -1576,7 +1580,9 @@ static void p8_i2c_init_one(struct dt_node *i2cm, enum p8_i2c_master_type type) /* initialise ports */ dt_for_each_child(i2cm, i2cm_port) - p8_i2c_init_one_port(master, i2cm_port, lb_freq); + p8_i2c_init_one_port(master, i2cm_port); + + return master; } void p8_i2c_init(void) @@ -1615,3 +1621,64 @@ struct i2c_bus *p8_i2c_find_bus_by_port(uint32_t chip_id, int eng, int port_num) return NULL; } + +/* Adds a new i2c port to the DT and initialises it */ +struct i2c_bus *p8_i2c_add_bus(uint32_t chip_id, int eng_id, int port_id, + uint32_t bus_speed) +{ + struct proc_chip *c = get_chip(chip_id); + struct p8_i2c_master *m, *master = NULL; + struct p8_i2c_master_port *port; + struct dt_node *pn; + + if (!c) { + prerror("I2C: Unable to add i2c bus: c%de%dp%d: chip doesn't exist\n", + chip_id, eng_id, port_id); + return NULL; + } + + list_for_each(&c->i2cms, m, link) { + if (m->engine_id == eng_id) { + master = m; + break; + } + } + + if (!master) { + struct dt_node *mn; + + mn = p8_i2c_add_master_node(c->devnode, eng_id); + if (!mn) { + prerror("I2C: Unable to add DT node for I2CM c%xe%d\n", + chip_id, eng_id); + return NULL; + } + + master = p8_i2c_init_one(mn, I2C_POWER8); + if (!master) { + prerror("I2C: Unable to initialise I2CM c%xe%d\n", + chip_id, eng_id); + return NULL; + } + } + + list_for_each(&master->ports, port, link) + if (port->port_num == port_id) + return &port->bus; + + pn = __p8_i2c_add_port_node(master->dt_node, port_id, bus_speed); + if (!pn) { + prerror("I2C: Unable to add dt node for bus c%xe%dp%d\n", + chip_id, eng_id, port_id); + return NULL; + } + + port = p8_i2c_init_one_port(master, pn); + if (!port) { + prerror("I2C: Unable to init bus c%xe%dp%d\n", + chip_id, eng_id, port_id); + return NULL; + } + + return &port->bus; +} diff --git a/include/i2c.h b/include/i2c.h index 9ad307b3f445..a644bd427ce1 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -69,6 +69,9 @@ struct dt_node *__p8_i2c_add_port_node(struct dt_node *master, int port_id, struct dt_node *p8_i2c_add_port_node(struct dt_node *xscom, int eng_id, int port_id, uint32_t bus_freq); +struct i2c_bus *p8_i2c_add_bus(uint32_t chip_id, int eng_id, int port_id, + uint32_t bus_speed); + int64_t i2c_queue_req(struct i2c_request *req); static inline uint64_t i2c_run_req(struct i2c_request *req)