Received: by 10.213.65.68 with SMTP id h4csp255338imn; Fri, 23 Mar 2018 04:03:14 -0700 (PDT) X-Google-Smtp-Source: AG47ELv2/4CtEkj7qqLgIW5GFpqNyJvtRqId0nJt3/byaHI6GqdJZEkjF/FT2+2WSDnwT/XtQt/L X-Received: by 10.99.95.78 with SMTP id t75mr20735043pgb.330.1521802994825; Fri, 23 Mar 2018 04:03:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521802994; cv=none; d=google.com; s=arc-20160816; b=NKPb7Mzhx4tQyKFFcnJyCyCd/MoEre7Kj2jBFd0TMKi8NNFk/ovtnoCD3gqTIsGwFJ WiV5NVkd1krcDrU+ALA5jwgbPmZkdYNq+lwBsofwXsDYpfq4gTs8rERnIKazYBuFhA7T Xy0rUhA/l8ClTz5cvRJcAunjpQt/mvuqGDhPliy4kkvIbUBGXfc0RGZ7gIeUEHg89KHI 78hoozZYokQUaCErkekSFHLXxhXJWIG7jLsAvoaorgpZGZ8G/qIZftqnBwk7i5Q5KpZs aSyNmdiZViYTqgXdYoA9aFWE+2NwQYNqSn8mx4qxKsRUNKjIVB7v7uAWsnCAb0HGkhSv snTA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=ejG7u/xFM2zgpsgeaqXC0cUXojSx80+cy9RsyCeo+98=; b=ALke2JnslxJNDO5VN+kdayn80MQ/sw5AQsaegMfKmG/RcexHtzn1iXOUEXaRyLcMJy 3tNDkKDhzDxi64XzIxc1cNUASzt5lDzhLl7K7218+OgywG8NEsYKqk9jBy7Me30R54En ug+hx9kIFI0rCiBdivTFEm+ui58sXmnYLi9NnDXgTlEF2s42FMitHs0KojtlDmmNxLrk 700tKV+7jVt3TBoKaUsBYMnlKuHp8XSeJTVKQXFKFd4ZpRiF9M14Hb1hzB+ZzpHMD9Oy JokBiGgl7jLpdRXQasWB9R94mkyK1vDyXeXuAh3CKERmb6MF9YPLevcmWdiRI6GqZh/Y 0Fvw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a34-v6si8416102pld.8.2018.03.23.04.03.00; Fri, 23 Mar 2018 04:03:14 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755936AbeCWLAm (ORCPT + 99 others); Fri, 23 Mar 2018 07:00:42 -0400 Received: from mail.bootlin.com ([62.4.15.54]:43837 "EHLO mail.bootlin.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753331AbeCWLAg (ORCPT ); Fri, 23 Mar 2018 07:00:36 -0400 Received: by mail.bootlin.com (Postfix, from userid 110) id 9EDAF208B0; Fri, 23 Mar 2018 12:00:33 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.bootlin.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.bootlin.com (Postfix) with ESMTPSA id ADCB1206FB; Fri, 23 Mar 2018 12:00:22 +0100 (CET) From: Boris Brezillon To: Wolfram Sang , linux-i2c@vger.kernel.org, Jonathan Corbet , linux-doc@vger.kernel.org, Greg Kroah-Hartman , Arnd Bergmann Cc: Przemyslaw Sroka , Arkadiusz Golec , Alan Douglas , Bartosz Folta , Damian Kos , Alicja Jurasik-Urbaniak , Cyprian Wronka , Suresh Punnoose , Rafal Ciepiela , Thomas Petazzoni , Nishanth Menon , Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, Vitor Soares , Geert Uytterhoeven , Linus Walleij , Xiang Lin , linux-gpio@vger.kernel.org, Boris Brezillon Subject: [PATCH v3 01/11] i2c: Export of_i2c_get_board_info() Date: Fri, 23 Mar 2018 12:00:10 +0100 Message-Id: <20180323110020.19080-2-boris.brezillon@bootlin.com> X-Mailer: git-send-email 2.14.1 In-Reply-To: <20180323110020.19080-1-boris.brezillon@bootlin.com> References: <20180323110020.19080-1-boris.brezillon@bootlin.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Boris Brezillon I3C busses have to know about all I2C devices connected on the I3C bus to properly initialize the I3C master, and I2C frames can't be sent on the bus until this initialization is done. We can't let the I2C core parse the DT and instantiate I2C devices as part of its i2c_add_adapter() procedure because, when done this way, I2C devices are directly registered to the device-model and might be attached to drivers which could in turn start sending frames on the bus, which won't work since, as said above, the bus is not yet initialized. Export of_i2c_register_device() in order to let the I3C core parse the I2C device nodes by itself and initialize the bus. Signed-off-by: Boris Brezillon --- Changes in v2: - fix memset() call - rebase on v4.15-rc1 --- drivers/i2c/i2c-core-base.c | 2 +- drivers/i2c/i2c-core-of.c | 66 ++++++++++++++++++++++++++------------------- include/linux/i2c.h | 10 +++++++ 3 files changed, 49 insertions(+), 29 deletions(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 5a00bf443d06..e57715f5064c 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -736,7 +736,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) client->dev.parent = &client->adapter->dev; client->dev.bus = &i2c_bus_type; client->dev.type = &i2c_client_type; - client->dev.of_node = info->of_node; + client->dev.of_node = of_node_get(info->of_node); client->dev.fwnode = info->fwnode; i2c_dev_set_name(adap, client, info); diff --git a/drivers/i2c/i2c-core-of.c b/drivers/i2c/i2c-core-of.c index 8d474bb1dc15..7470bc418a3b 100644 --- a/drivers/i2c/i2c-core-of.c +++ b/drivers/i2c/i2c-core-of.c @@ -22,56 +22,66 @@ #include "i2c-core.h" -static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, - struct device_node *node) +int of_i2c_get_board_info(struct device *dev, struct device_node *node, + struct i2c_board_info *info) { - struct i2c_client *result; - struct i2c_board_info info = {}; - struct dev_archdata dev_ad = {}; - const __be32 *addr_be; u32 addr; - int len; + int ret; - dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node); + memset(info, 0, sizeof(*info)); - if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { - dev_err(&adap->dev, "of_i2c: modalias failure on %pOF\n", - node); - return ERR_PTR(-EINVAL); + if (of_modalias_node(node, info->type, sizeof(info->type)) < 0) { + dev_err(dev, "of_i2c: modalias failure on %pOF\n", node); + return -EINVAL; } - addr_be = of_get_property(node, "reg", &len); - if (!addr_be || (len < sizeof(*addr_be))) { - dev_err(&adap->dev, "of_i2c: invalid reg on %pOF\n", node); - return ERR_PTR(-EINVAL); + ret = of_property_read_u32(node, "reg", &addr); + if (ret) { + dev_err(dev, "of_i2c: invalid reg on %pOF\n", node); + return ret; } - addr = be32_to_cpup(addr_be); if (addr & I2C_TEN_BIT_ADDRESS) { addr &= ~I2C_TEN_BIT_ADDRESS; - info.flags |= I2C_CLIENT_TEN; + info->flags |= I2C_CLIENT_TEN; } if (addr & I2C_OWN_SLAVE_ADDRESS) { addr &= ~I2C_OWN_SLAVE_ADDRESS; - info.flags |= I2C_CLIENT_SLAVE; + info->flags |= I2C_CLIENT_SLAVE; } - if (i2c_check_addr_validity(addr, info.flags)) { - dev_err(&adap->dev, "of_i2c: invalid addr=%x on %pOF\n", - addr, node); - return ERR_PTR(-EINVAL); + ret = i2c_check_addr_validity(addr, info->flags); + if (ret) { + dev_err(dev, "of_i2c: invalid addr=%x on %pOF\n", addr, node); + return ret; } - info.addr = addr; - info.of_node = of_node_get(node); - info.archdata = &dev_ad; + info->addr = addr; + info->of_node = node; if (of_property_read_bool(node, "host-notify")) - info.flags |= I2C_CLIENT_HOST_NOTIFY; + info->flags |= I2C_CLIENT_HOST_NOTIFY; if (of_get_property(node, "wakeup-source", NULL)) - info.flags |= I2C_CLIENT_WAKE; + info->flags |= I2C_CLIENT_WAKE; + + return 0; +} +EXPORT_SYMBOL_GPL(of_i2c_get_board_info); + +static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap, + struct device_node *node) +{ + struct i2c_client *result; + struct i2c_board_info info; + int ret; + + dev_dbg(&adap->dev, "of_i2c: register %pOF\n", node); + + ret = of_i2c_get_board_info(&adap->dev, node, &info); + if (ret) + return ERR_PTR(ret); result = i2c_new_device(adap, &info); if (result == NULL) { diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 419a38e7c315..3e38c10748e3 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -873,6 +873,9 @@ extern const struct of_device_id *i2c_of_match_device(const struct of_device_id *matches, struct i2c_client *client); +int of_i2c_get_board_info(struct device *dev, struct device_node *node, + struct i2c_board_info *info); + #else static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) @@ -897,6 +900,13 @@ static inline const struct of_device_id return NULL; } +static inline int of_i2c_get_board_info(struct device *dev, + struct device_node *node, + struct i2c_board_info *info) +{ + return -ENOTSUPP; +} + #endif /* CONFIG_OF */ #if IS_ENABLED(CONFIG_ACPI) -- 2.14.1