From patchwork Mon Oct 12 02:53:13 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: 1380602 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 4C8jzQ2pFGz9s0b for ; Mon, 12 Oct 2020 13:58:10 +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=fslZx/qs; 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 4C8jzQ1lFFzDqs6 for ; Mon, 12 Oct 2020 13:58:10 +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::443; helo=mail-pf1-x443.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=fslZx/qs; dkim-atps=neutral Received: from mail-pf1-x443.google.com (mail-pf1-x443.google.com [IPv6:2607:f8b0:4864:20::443]) (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 4C8jtR6slGzDqhn for ; Mon, 12 Oct 2020 13:53:51 +1100 (AEDT) Received: by mail-pf1-x443.google.com with SMTP id e7so3201107pfn.12 for ; Sun, 11 Oct 2020 19:53:51 -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=zAv19fs6mo9GkhnvGCk8gFTXyqC6WPUWhXvohXsanAw=; b=fslZx/qshhcO4rpR8vL9Jym39YxYCAjdGXE3o37Com+oLMmD1BBqtZOrUqv743Omqm zAMsNslVyCVh+rsUM8uAUK7y7j/FhdwytFxeJGXYH6hiNAMl9SMNaHMUkOCKNL2NPu8I jKQicnbQTSeE39Myl5fa55qSnm4VIImgfXrMgC7BrD1tCQFQOmmCrsK6ZoaNqpLJ+y0I rf+Pt/tooc12D+tjjrbtQdv20PoY7wmOIE50CLPHPzz3trG/ZeS67DhkT6QHa3ymHHr+ +5OYk53SBDk/pti9AWhEBdxuFF83zBj9SrBt3OXYZ0xLyCALKrEHcPLbBnoeHM3GrHBL czBw== 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=zAv19fs6mo9GkhnvGCk8gFTXyqC6WPUWhXvohXsanAw=; b=Et7m0RhG3JdlRq3+ymvpAZ8fNQeEq0g/kYyh8dIGJOVl19i1DrFXQTHf6YZSuBOU3q s9iCSRDhX6umtEhoxiInJQfLiMHWGGrGo5PtXijH3C2i5qOZFI0kftjuPMLLaEUsYFFD AAipbzrXzUbq32Q8/n6nFBz/FRSzwNFCVKAkk0KK3kWuC2mqunFgXZjncyBd82QecIks C5kCXtLhuv219BWT1ChhFAXS2VS2INU0BwoMxBEbcpR89DggHla8HUHoV9EWYpqB6XaU ayC3eFsZipBQs4eds/ER9mZc/uY41lHrM0aBfw9YdH7vHQHpZS8TC26hjxFpPgH+UBC9 MI9A== X-Gm-Message-State: AOAM533N0lLbr3MwNx6gYOY+dZnyYC1UHU2bNAX9lxR+5vPmQCJK9SLv PU2+WT5rpMyiZNq811tkWWaorw3WY9cKXg== X-Google-Smtp-Source: ABdhPJwxTmBYUHtfCfiYzyGuE9XkbiXG7EKR6VIjz/htkNeHD1roq5IaemjJuY84lbjPn+7gpdAJMg== X-Received: by 2002:a17:90b:1496:: with SMTP id js22mr17756499pjb.20.1602471229818; Sun, 11 Oct 2020 19:53:49 -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.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 11 Oct 2020 19:53:49 -0700 (PDT) From: Oliver O'Halloran To: skiboot@lists.ozlabs.org Date: Mon, 12 Oct 2020 13:53:13 +1100 Message-Id: <20201012025314.1070230-9-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 09/10] hdat/i2c: Rework i2c device creation 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" We've got functions to instantiate I2C buses at various places inside of the skiboot code base (in hdat, firenze-pci, and in witherspoon). The HDAT ones are the most generic so re-work those a bit and export the functions used to add DT nodes for I2C masters and the ports below them. Signed-off-by: Oliver O'Halloran --- hdata/i2c.c | 171 ++++++++++++++++++++++++++++++++------------------ include/i2c.h | 5 ++ 2 files changed, 114 insertions(+), 62 deletions(-) diff --git a/hdata/i2c.c b/hdata/i2c.c index a2fe8ac1b994..9f95e6146205 100644 --- a/hdata/i2c.c +++ b/hdata/i2c.c @@ -7,86 +7,128 @@ #include #include #include +#include #include "spira.h" #include "hdata.h" -struct i2c_dev { - uint8_t i2cm_engine; - uint8_t i2cm_port; - __be16 i2c_bus_freq; +/* + * These should probably be in hw/p8-i2c.c. However, that would require the HDAT + * test to #include hw/p8-i2c.c which is probably going to be more trouble than + * it's worth. So these helpers are here instead. + */ +struct dt_node *p8_i2c_add_master_node(struct dt_node *xscom, int eng_id) +{ + uint64_t clk, size, xscom_base; + struct dt_node *i2cm; - /* i2c slave info */ - uint8_t type; - uint8_t dev_addr; - uint8_t dev_port; - uint8_t __reserved; + dt_for_each_compatible(xscom, i2cm, "ibm,power8-i2cm") + if (dt_prop_get_u32(i2cm, "chip-engine#") == eng_id) + return i2cm; - __be32 purpose; - __be32 i2c_link; - __be16 slca_index; -}; + /* XXX: Might need to be updated for new chips */ + if (proc_gen >= proc_gen_p9) + size = 0x1000; + else + size = 0x20; -#define P9_I2CM_XSCOM_SIZE 0x1000 -#define P9_I2CM_XSCOM_BASE 0xa0000 + xscom_base = 0xa0000 + size * eng_id; -static struct dt_node *get_i2cm_node(struct dt_node *xscom, int engine) -{ - uint64_t xscom_base = P9_I2CM_XSCOM_BASE + P9_I2CM_XSCOM_SIZE * (uint64_t)engine; - struct dt_node *i2cm; - uint64_t freq, clock; - - i2cm = dt_find_by_name_addr(xscom, "i2cm", xscom_base); - if (!i2cm) { - i2cm = dt_new_addr(xscom, "i2cm", xscom_base); - dt_add_property_cells(i2cm, "reg", xscom_base, - P9_I2CM_XSCOM_SIZE); - - dt_add_property_strings(i2cm, "compatible", - "ibm,power8-i2cm", "ibm,power9-i2cm"); - - dt_add_property_cells(i2cm, "#size-cells", 0); - dt_add_property_cells(i2cm, "#address-cells", 1); - dt_add_property_cells(i2cm, "chip-engine#", engine); - - freq = dt_prop_get_u64_def(xscom, "bus-frequency", 0); - clock = (u32)(freq / 4); - if (clock) - dt_add_property_cells(i2cm, "clock-frequency", clock); - else - dt_add_property_cells(i2cm, "clock-frequency", 150000000); + i2cm = dt_new_addr(xscom, "i2cm", xscom_base); + if (!i2cm) + return NULL; + + if (proc_gen >= proc_gen_p9) { + dt_add_property_strings(i2cm, "compatible", "ibm,power8-i2cm", + "ibm,power9-i2cm"); + } else { + dt_add_property_strings(i2cm, "compatible", "ibm,power8-i2cm"); } + dt_add_property_cells(i2cm, "reg", xscom_base, size); + dt_add_property_cells(i2cm, "#size-cells", 0); + dt_add_property_cells(i2cm, "#address-cells", 1); + dt_add_property_cells(i2cm, "chip-engine#", eng_id); + + /* + * The i2cm runs at 1/4th the PIB frequency. If we don't know the PIB + * frequency then pick 150MHz which should be in the right ballpark. + */ + clk = dt_prop_get_u64_def(xscom, "bus-frequency", 0); + if (clk) + dt_add_property_cells(i2cm, "clock-frequency", clk / 4); + else + dt_add_property_cells(i2cm, "clock-frequency", 150000000); + return i2cm; } -static struct dt_node *get_bus_node(struct dt_node *i2cm, int port, int freq) +struct dt_node *__p8_i2c_add_port_node(struct dt_node *master, int port_id, + uint32_t bus_speed) { - struct dt_node *bus; + struct dt_node *port; + uint32_t speed; + + dt_for_each_child(master, port) + if (dt_prop_get_u32(port, "reg") == port_id) + goto check_speed; - bus = dt_find_by_name_addr(i2cm, "i2c-bus", port); - if (!bus) { - bus = dt_new_addr(i2cm, "i2c-bus", port); - dt_add_property_cells(bus, "reg", port); - dt_add_property_cells(bus, "#size-cells", 0); - dt_add_property_cells(bus, "#address-cells", 1); + port = dt_new_addr(master, "i2c-bus", port_id); + if (!port) + return NULL; - /* The P9 I2C master is fully compatible with the P8 one */ - dt_add_property_strings(bus, "compatible", "ibm,opal-i2c", + dt_add_property_cells(port, "reg", port_id); + dt_add_property_cells(port, "#size-cells", 0); + dt_add_property_cells(port, "#address-cells", 1); + + /* The P9 I2C master is fully compatible with the P8 one */ + if (proc_gen >= proc_gen_p9) { + dt_add_property_strings(port, "compatible", "ibm,opal-i2c", "ibm,power8-i2c-port", "ibm,power9-i2c-port"); + } else { + dt_add_property_strings(port, "compatible", "ibm,opal-i2c", + "ibm,power8-i2c-port"); + } - /* - * use the clock frequency as the bus frequency until we - * have actual devices on the bus. Adding a device will - * reduce the frequency to something that all devices - * can tolerate. - */ - dt_add_property_cells(bus, "bus-frequency", freq * 1000); +check_speed: + speed = dt_prop_get_u32_def(port, "bus-frequency", 0xffffffff); + if (bus_speed < speed) { + dt_check_del_prop(port, "bus-frequency"); + dt_add_property_cells(port, "bus-frequency", bus_speed); } - return bus; + return port; +} + + +struct dt_node *p8_i2c_add_port_node(struct dt_node *xscom, int eng_id, + int port_id, uint32_t bus_freq) +{ + struct dt_node *i2cm; + + i2cm = p8_i2c_add_master_node(xscom, eng_id); + if (!i2cm) + return NULL; + + return __p8_i2c_add_port_node(i2cm, port_id, bus_freq); } +struct i2c_dev { + uint8_t i2cm_engine; + uint8_t i2cm_port; + __be16 i2c_bus_freq; + + /* i2c slave info */ + uint8_t type; + uint8_t dev_addr; + uint8_t dev_port; + uint8_t __reserved; + + __be32 purpose; + __be32 i2c_link; + __be16 slca_index; +}; + struct hdat_i2c_type { uint32_t id; const char *name; @@ -192,7 +234,7 @@ struct host_i2c_hdr { int parse_i2c_devs(const struct HDIF_common_hdr *hdr, int idata_index, struct dt_node *xscom) { - struct dt_node *i2cm, *bus, *node; + struct dt_node *bus, *node; const struct hdat_i2c_type *type; const struct hdat_i2c_info *info; const struct i2c_dev *dev; @@ -263,9 +305,14 @@ int parse_i2c_devs(const struct HDIF_common_hdr *hdr, int idata_index, (proc_gen == proc_gen_p9 || proc_gen == proc_gen_p10)) continue; - i2cm = get_i2cm_node(xscom, dev->i2cm_engine); - bus = get_bus_node(i2cm, dev->i2cm_port, - be16_to_cpu(dev->i2c_bus_freq)); + bus = p8_i2c_add_port_node(xscom, dev->i2cm_engine, dev->i2cm_port, + be16_to_cpu(dev->i2c_bus_freq) * 1000); + + if (!bus) { + prerror("Unable to add node for e%dp%d under %s\n", + dev->i2cm_engine, dev->i2cm_port, xscom->name); + continue; + } /* * Looks like hostboot gives the address as an 8 bit, left diff --git a/include/i2c.h b/include/i2c.h index 8ec32ad1c6f3..9ad307b3f445 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -63,6 +63,11 @@ extern struct i2c_bus *i2c_find_bus_by_id(uint32_t opal_id); /* not generic, but useful */ struct i2c_bus *p8_i2c_find_bus_by_port(uint32_t chip_id, int eng, int port_id); +struct dt_node *p8_i2c_add_master_node(struct dt_node *xscom, int eng_id); +struct dt_node *__p8_i2c_add_port_node(struct dt_node *master, int port_id, + uint32_t bus_speed); +struct dt_node *p8_i2c_add_port_node(struct dt_node *xscom, int eng_id, + int port_id, uint32_t bus_freq); int64_t i2c_queue_req(struct i2c_request *req);