From patchwork Wed Sep 4 09:00:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790225 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B9406CA0ED3 for ; Wed, 4 Sep 2024 09:33:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=URewZP1CjuEapcOrKzsC3z8bnfBtBnJFc+7fenwYvsw=; b=jtadvqHS2SjivlIuA3sPmlY+tD AXXONGQpnh4RlJiqH5pL4bcaCj/cvLPy5WfA/MmFxJ5gqQ4rc1ipdACI1YI2k4X9PyE+av0923Wdm XxSANWtcSw+FBbiLO7IGLSZK7UjwRPRo7UluHQzmyN3MpI9CvKY/e7SoheXArcECYBMhUycnUE0RP qbBWWeBTjybD80vCUUtqFXGaeq3sjyxXcg37vJYfKlwivSxUgWT0qxvmqNRIyHhSoHLEHafG0kZiX p/Y/N3J8EDhlUNKmV9u9YXn12qMdzWK1G0s4rwXFse5e58dZpOGBix3Q2y4G4aykFHEyBK7D0nJAl BfgTqfZg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmOP-00000003hQc-0Wtm; Wed, 04 Sep 2024 09:33:37 +0000 Received: from mail-pf1-x42a.google.com ([2607:f8b0:4864:20::42a]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsK-00000003YlY-3gSm for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:00:30 +0000 Received: by mail-pf1-x42a.google.com with SMTP id d2e1a72fcca58-7141d7b270dso5096506b3a.2 for ; Wed, 04 Sep 2024 02:00:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440427; x=1726045227; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=URewZP1CjuEapcOrKzsC3z8bnfBtBnJFc+7fenwYvsw=; b=aWWjiwj4dQVX4Oe6pfaUk4ZZla53uWsFDnzvAEgxSJhasttd2puWlpkUXDjtCtSnWk f85EnPlp+FvqmfGvAk/VhJ0W8jLX4wHSWYij4LNSaLe7s8+Q/L7LGqOTvUQEpmvBrzGe pbIsyMuoNMGgs5HVdp6GNAu7jxfZbHHfeYLk0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440427; x=1726045227; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=URewZP1CjuEapcOrKzsC3z8bnfBtBnJFc+7fenwYvsw=; b=oCrsoLukR4k3Ni4RzFFmWNdOT0jMHmf2Fj2BaFOkjQ+rQxAHxfEUTcToXrB7g+PzIx 9s5AjbO37rKoeEV6brPDuEtxSe79vNI6V3AthKqchlojfQhk9DiBmIMiSOz3hzbXrU7d mgvvQsTqei+LPZtNcfAzLzcjtCLlVVWk8YS2M+XrcRPUEZ/p3v+ws9sJGmBvY+ffvd2d LyrorKPuMgXsOkH64BlXzTH9DatcVaJV0BYk/m9of1eXXuGX4C9wNQ29nWjtYUX9ncG0 FpR9Fx1vGF9nW46W8qLht7ORk1BJQxvFACSJJjqo891s8Re9po7R7E0mHjZjLomo32PD I0uQ== X-Forwarded-Encrypted: i=1; AJvYcCVfbVVd7Jk1xxz2o0/NTc39xXhvO+97TKTP/AmuaD36Pd1t+oF06rc7Brq55AdDLIvf6M3kaZfW1Ss/t0K3QA==@lists.infradead.org X-Gm-Message-State: AOJu0YxYp8TuL0fQPbBTqmOZyT+KJ5LeQ5GPc33vWEG1yyzmirxMmAqc 8xRFbg6obv83w2n6Lo7bTBnVSGyKNB4yht+Tnt+9H3nFZZqIk/jgojzUxdVm6g== X-Google-Smtp-Source: AGHT+IHf+4oWltICBIad0flKpZyWzPtxz5hqcWd60IFNv00gyZa3rQlflgcNL2YbqnsGxF7j26kYgg== X-Received: by 2002:a05:6a00:2d05:b0:70a:f65e:b13d with SMTP id d2e1a72fcca58-717449c6427mr11999072b3a.27.1725440426991; Wed, 04 Sep 2024 02:00:26 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.00.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:00:26 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 01/12] of: dynamic: Add of_changeset_update_prop_string Date: Wed, 4 Sep 2024 17:00:03 +0800 Message-ID: <20240904090016.2841572-2-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020028_927730_0995864E X-CRM114-Status: GOOD ( 16.85 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Add a helper function to add string property updates to an OF changeset. This is similar to of_changeset_add_prop_string(), but instead of adding the property (and failing if it exists), it will update the property. This shall be used later in the DT hardware prober. Signed-off-by: Chen-Yu Tsai Reviewed-by: Rob Herring (Arm) --- Changes since v5: - Collected Rob's tag Changes since v4: - Use modern designated initializer for |prop| Changes since v3: - Use new __of_prop_free() helper - Add new line before header declaration Changes since v2: - New patch added in v3 --- drivers/of/dynamic.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/of.h | 4 ++++ 2 files changed, 48 insertions(+) diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c index 110104a936d9..daa69d160a78 100644 --- a/drivers/of/dynamic.c +++ b/drivers/of/dynamic.c @@ -1072,3 +1072,47 @@ int of_changeset_add_prop_bool(struct of_changeset *ocs, struct device_node *np, return of_changeset_add_prop_helper(ocs, np, &prop); } EXPORT_SYMBOL_GPL(of_changeset_add_prop_bool); + +static int of_changeset_update_prop_helper(struct of_changeset *ocs, + struct device_node *np, + const struct property *pp) +{ + struct property *new_pp; + int ret; + + new_pp = __of_prop_dup(pp, GFP_KERNEL); + if (!new_pp) + return -ENOMEM; + + ret = of_changeset_update_property(ocs, np, new_pp); + if (ret) + __of_prop_free(new_pp); + + return ret; +} + +/** + * of_changeset_update_prop_string - Add a string property update to a changeset + * + * @ocs: changeset pointer + * @np: device node pointer + * @prop_name: name of the property to be updated + * @str: pointer to null terminated string + * + * Create a string property to be updated and add it to a changeset. + * + * Return: 0 on success, a negative error value in case of an error. + */ +int of_changeset_update_prop_string(struct of_changeset *ocs, + struct device_node *np, + const char *prop_name, const char *str) +{ + struct property prop = { + .name = (char *)prop_name, + .length = strlen(str) + 1, + .value = (void *)str, + }; + + return of_changeset_update_prop_helper(ocs, np, &prop); +} +EXPORT_SYMBOL_GPL(of_changeset_update_prop_string); diff --git a/include/linux/of.h b/include/linux/of.h index 85b60ac9eec5..046283be1cd3 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -1651,6 +1651,10 @@ static inline int of_changeset_add_prop_u32(struct of_changeset *ocs, return of_changeset_add_prop_u32_array(ocs, np, prop_name, &val, 1); } +int of_changeset_update_prop_string(struct of_changeset *ocs, + struct device_node *np, + const char *prop_name, const char *str); + int of_changeset_add_prop_bool(struct of_changeset *ocs, struct device_node *np, const char *prop_name); From patchwork Wed Sep 4 09:00:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790226 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3793ACA0ED3 for ; Wed, 4 Sep 2024 09:35:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=2M921d4gJ85snm6ehV18l9ZU1Po4pieq34BYMUnhsNU=; b=vzSmSBd+fTw49RkgIINWvaeiGl 5OVtRPxBRyYDkjtVeCrayPcjfKvRGkfWLmCDNBXJI1yyim/Nx7s7z0QOYPkhynKvNeGv8Nd2XbAdU A0D3+BK32nvjiOXKyaFBTzm0tFgh3oUMT6SR7uHQanUIf8AHvG6dC/8pd1izGrD9fK/6NvCsWX2Dy lx8CVR1OBxjdgZw2DcYwPIOUBUwFCDkwc7u5I2ZuQbza7Sfcx6+TcbkW69MWCpp7Ac+LhQcY1Z3zb gvUtztCwnlXh4UqjTDo3IepgO++GlkKx1J67Kbyr7h1Sn75qAFN5hnHaVyOuJbM3tRV5ACLNj2HWC r37qaDpA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmQB-00000003hpH-3lTp; Wed, 04 Sep 2024 09:35:27 +0000 Received: from mail-pf1-x433.google.com ([2607:f8b0:4864:20::433]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsP-00000003Yn5-1pkD for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:00:35 +0000 Received: by mail-pf1-x433.google.com with SMTP id d2e1a72fcca58-715e64ea7d1so5352793b3a.0 for ; Wed, 04 Sep 2024 02:00:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440432; x=1726045232; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2M921d4gJ85snm6ehV18l9ZU1Po4pieq34BYMUnhsNU=; b=OsfIL8BXKldKg5tH0b0xTjjjuAlw1z9T7JKqJsFRnakOfo05Z1B75dZk48ffomOeAy g+ctfI8vU3NFknzzUn68VMVyx/bS//pcr6XJKFBzfmO0jgmsKTS+/OWd7D56EC/IFnay eKkvx67/wFamC3x7hvSFUIGcDxz7hG9ap+RHk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440432; x=1726045232; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2M921d4gJ85snm6ehV18l9ZU1Po4pieq34BYMUnhsNU=; b=gOkCd1LLuxcJ+HKL3kcp3YmQ5A/RdOtCyUm8xOVOU+2ZPWJptckGjiSLA5vZz125Qs SEUL678tYLYwv6aBCz1b1FYNkdPGNKAMaI1BdeYhZs1h4KhwpLBs4L0B41xUte+kkhN1 3tUhjZpTD5tLzV8rGuC5PeUWZiEPdbzwEm882EQRia2ytUpiT1ZgAMjtCjaJDTnQXg5R PTjdNj/e20QWcsn7O9Yw8AbeR5uq8QncGnPGbux7L5F5C2YRdwq743C7iL7XE7k37yDd Gpwl/sZzBfvbhmu2NvZVsCRoHuDK7WnABxvsofxGnLqHc5e1/djugOUPEH+YlXxRsVpC Bitw== X-Forwarded-Encrypted: i=1; AJvYcCVffkvCVpSa5CxCSugg9gstbqhZBYMTvYRx2T7pAW+TCu0XADC40QOE2AEISehRBxLrppkQdDBE9l/0K6LGag==@lists.infradead.org X-Gm-Message-State: AOJu0YyBKhR2+ysB56R8us/t3pIYCA/4Aif8oLAPnCF9Ypav3xY7GDLO cZo7EXmBrWMcYkMevVskgr830VrhKGaacDqh/OrE+0z3e3kkLUXiftysqdRTIQ== X-Google-Smtp-Source: AGHT+IF/MVW4wrOQrl8cYkGW2jFbuYY69p3WFoLB5FjxApHmcb1+fCtPnl3w/uoQeTGzo0ajB2S9PQ== X-Received: by 2002:a05:6a00:66d9:b0:710:e4db:a6fc with SMTP id d2e1a72fcca58-7173b6b63demr14365184b3a.27.1725440430497; Wed, 04 Sep 2024 02:00:30 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.00.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:00:30 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 02/12] of: base: Add for_each_child_of_node_with_prefix_scoped() Date: Wed, 4 Sep 2024 17:00:04 +0800 Message-ID: <20240904090016.2841572-3-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020033_508841_26B7EFA1 X-CRM114-Status: GOOD ( 15.69 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org There are cases where drivers would go through child device nodes and operate on only the ones whose node name starts with a given prefix. Provide a helper for these users. This will mainly be used in a subsequent patch that implements a hardware component prober for I2C busses. Signed-off-by: Chen-Yu Tsai --- Changes since v5: - New patch --- drivers/of/base.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/of.h | 9 +++++++++ 2 files changed, 44 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index 20603d3c9931..d3c123b3261a 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -628,6 +628,41 @@ struct device_node *of_get_next_child(const struct device_node *node, } EXPORT_SYMBOL(of_get_next_child); +/** + * of_get_next_child_with_prefix - Find the next child node with prefix + * @node: parent node + * @prev: previous child of the parent node, or NULL to get first + * + * This function is like of_get_next_child(), except that it automatically + * skips any nodes whose name doesn't have the given prefix. + * + * Return: A node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_get_next_child_with_prefix(const struct device_node *node, + struct device_node *prev, + const char *prefix) +{ + struct device_node *next; + unsigned long flags; + + if (!node) + return NULL; + + raw_spin_lock_irqsave(&devtree_lock, flags); + next = prev ? prev->sibling : node->child; + for (; next; next = next->sibling) { + if (!of_node_name_prefix(next, prefix)) + continue; + if (of_node_get(next)) + break; + } + of_node_put(prev); + raw_spin_unlock_irqrestore(&devtree_lock, flags); + return next; +} +EXPORT_SYMBOL(of_get_next_child_with_prefix); + static struct device_node *of_get_next_status_child(const struct device_node *node, struct device_node *prev, bool (*checker)(const struct device_node *)) diff --git a/include/linux/of.h b/include/linux/of.h index 046283be1cd3..acc0d5b98417 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -289,6 +289,9 @@ extern struct device_node *of_get_parent(const struct device_node *node); extern struct device_node *of_get_next_parent(struct device_node *node); extern struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev); +extern struct device_node *of_get_next_child_with_prefix(const struct device_node *node, + struct device_node *prev, + const char *prefix); extern struct device_node *of_get_next_available_child( const struct device_node *node, struct device_node *prev); extern struct device_node *of_get_next_reserved_child( @@ -1468,6 +1471,12 @@ static inline int of_property_read_s32(const struct device_node *np, child != NULL; \ child = of_get_next_child(parent, child)) +#define for_each_child_of_node_with_prefix_scoped(parent, child, prefix) \ + for (struct device_node *child __free(device_node) = \ + of_get_next_child_with_prefix(parent, NULL, prefix); \ + child != NULL; \ + child = of_get_next_child_with_prefix(parent, child, prefix)) + #define for_each_available_child_of_node(parent, child) \ for (child = of_get_next_available_child(parent, NULL); child != NULL; \ child = of_get_next_available_child(parent, child)) From patchwork Wed Sep 4 09:00:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790233 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DCF29CD3431 for ; Wed, 4 Sep 2024 09:36:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=il2QfOTiET8rjOcFBiZisnVGS1vYYZiPRBoWVegvz3I=; b=Q90pw+QbcyNZhaQe5lGsvGsePJ 9jO6YME5vhViEc8sDtSFepi1ss+JxCOjpx0yX3X6dNZWiORh3mqKjCBUwZohHGUYTkqdAgNK6NgB4 YE6J0fWcCs6eobqmDlCNq2tFuOMhUS7Y/pVt0qmcZ/n/u9CRjkD+tvewI72DX9V1/Wkm2Q5vvNhDP kdtYxPX/Tctx23fhH07iZtJreokcO+OEKLSEld/gSFjC/akHkm0e4NJ6nCU4UzUN2m7lzLagWEKBa Mc5U0WPVkX7BL48tY8/1fZZsjAduJzzVARxUTHiXONA95GO3xOWzhJoAY3JLB90X7piywkhzGnKhB ktfcTnsA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmR5-00000003i2D-2XUs; Wed, 04 Sep 2024 09:36:23 +0000 Received: from mail-ot1-x333.google.com ([2607:f8b0:4864:20::333]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsR-00000003Yok-3zrT for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:00:38 +0000 Received: by mail-ot1-x333.google.com with SMTP id 46e09a7af769-70f60d73436so3534496a34.1 for ; Wed, 04 Sep 2024 02:00:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440434; x=1726045234; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=il2QfOTiET8rjOcFBiZisnVGS1vYYZiPRBoWVegvz3I=; b=M6Yob2l9ollYk1o39Y+nyM4dlzDqxBwOqWvIdvNEmvrkaHf7kHoaEB9lmensKnrfI8 H5JS8tFuhp6TEEpI8C2BWdCb3atxIAQ4MNcZMklnp3KSiKYdHGIb8uDtr24JiMWVvAdv atXpY44SfxZAX2BPdxmJ6kDj+6CAMc7oKr9Nw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440434; x=1726045234; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=il2QfOTiET8rjOcFBiZisnVGS1vYYZiPRBoWVegvz3I=; b=RQe/VWOKvgn6+KROXKxSG2Xw03PIgznSIfyH5UAAFGXa8Zs9so+my+9Z9rB+IVzxNS lrhM7eUarZi7yzlMgoKoEVE7CbGnzCpPouPGv2ZNQ5WW9204YyeRpYm+fc6MFD4PgZAL fSk8tpjQRvg2OQ5g/hcLgCjfdXYpvVsDRr+DCrBa7RIDiDB6IQCYK990vvKc86sjCP3V dktAbVP8/+V9eBxK4VZR547vkgQ2JDVL9yYUkf2z/oCscLnH0Tg9MrHrkb5E6kECytaE nanxn7s/p66vvrPe9myTjFBgT+mbAmnC6kGwZXj1LnY7U//GtoDaudlr/HxzM8LlxigV XeIw== X-Forwarded-Encrypted: i=1; AJvYcCVE+0jTJ5D+bjtROeSKbK9b8fPaN+K488XQq34USYxtOB//lBLg6iUddM5aIkJAU3E9aUlitiaY67QTgo+qOg==@lists.infradead.org X-Gm-Message-State: AOJu0YxAlidEueVCSxQD0hOuksUJp3I9bEtWKHVARXKTikmymvxSMP/D MiiQM9LeS9ErLTR/zanTmPfUa9dlE/d3OSi00HFnEZEjoBz/LVY9BaVtj/9vuQ== X-Google-Smtp-Source: AGHT+IFjPAH4gu4wNsG/hc91RRvJC5dzdd5l+iIjQEyefCsJA13TtrMy0WEpFbhOCDltsCruxjjIJA== X-Received: by 2002:a05:6358:5e1b:b0:1b1:ac2e:af69 with SMTP id e5c5f4694b2df-1b603c48228mr2349782555d.17.1725440434102; Wed, 04 Sep 2024 02:00:34 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.00.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:00:33 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 03/12] regulator: Move OF-specific regulator lookup code to of_regulator.c Date: Wed, 4 Sep 2024 17:00:05 +0800 Message-ID: <20240904090016.2841572-4-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020036_188300_C9B04715 X-CRM114-Status: GOOD ( 26.49 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org There's still a bit of OF-specific code in the regulator device lookup function. Move those bits of code over to of_regulator.c, and create a new function of_regulator_dev_lookup() to encapsulate the code moved out of regulator_dev_lookup(). Also mark of_find_regulator_by_node() as static, since there are no other users in other compile units. There are no functional changes. A line alignment was also fixed. Signed-off-by: Chen-Yu Tsai --- Changes since v5: - Fix kerneldoc format of of_regulator_dev_lookup() - Fix stub compile error for !CONFIG_OF in drivers/regulator/internal.h Changes since v4: - New patch --- drivers/regulator/core.c | 87 ++---------------------- drivers/regulator/internal.h | 9 +-- drivers/regulator/of_regulator.c | 110 ++++++++++++++++++++++++++++++- 3 files changed, 119 insertions(+), 87 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index c1d11924d892..835a5531d045 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -421,74 +421,6 @@ static void regulator_lock_dependent(struct regulator_dev *rdev, mutex_unlock(®ulator_list_mutex); } -/** - * of_get_child_regulator - get a child regulator device node - * based on supply name - * @parent: Parent device node - * @prop_name: Combination regulator supply name and "-supply" - * - * Traverse all child nodes. - * Extract the child regulator device node corresponding to the supply name. - * - * Return: Pointer to the &struct device_node corresponding to the regulator - * if found, or %NULL if not found. - */ -static struct device_node *of_get_child_regulator(struct device_node *parent, - const char *prop_name) -{ - struct device_node *regnode = NULL; - struct device_node *child = NULL; - - for_each_child_of_node(parent, child) { - regnode = of_parse_phandle(child, prop_name, 0); - - if (!regnode) { - regnode = of_get_child_regulator(child, prop_name); - if (regnode) - goto err_node_put; - } else { - goto err_node_put; - } - } - return NULL; - -err_node_put: - of_node_put(child); - return regnode; -} - -/** - * of_get_regulator - get a regulator device node based on supply name - * @dev: Device pointer for the consumer (of regulator) device - * @supply: regulator supply name - * - * Extract the regulator device node corresponding to the supply name. - * - * Return: Pointer to the &struct device_node corresponding to the regulator - * if found, or %NULL if not found. - */ -static struct device_node *of_get_regulator(struct device *dev, const char *supply) -{ - struct device_node *regnode = NULL; - char prop_name[64]; /* 64 is max size of property name */ - - dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); - - snprintf(prop_name, 64, "%s-supply", supply); - regnode = of_parse_phandle(dev->of_node, prop_name, 0); - - if (!regnode) { - regnode = of_get_child_regulator(dev->of_node, prop_name); - if (regnode) - return regnode; - - dev_dbg(dev, "Looking up %s property in node %pOF failed\n", - prop_name, dev->of_node); - return NULL; - } - return regnode; -} - /* Platform voltage constraint check */ int regulator_check_voltage(struct regulator_dev *rdev, int *min_uV, int *max_uV) @@ -2021,7 +1953,6 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, const char *supply) { struct regulator_dev *r = NULL; - struct device_node *node; struct regulator_map *map; const char *devname = NULL; @@ -2029,19 +1960,11 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, /* first do a dt based lookup */ if (dev && dev->of_node) { - node = of_get_regulator(dev, supply); - if (node) { - r = of_find_regulator_by_node(node); - of_node_put(node); - if (r) - return r; - - /* - * We have a node, but there is no device. - * assume it has not registered yet. - */ - return ERR_PTR(-EPROBE_DEFER); - } + r = of_regulator_dev_lookup(dev, supply); + if (!IS_ERR(r)) + return r; + if (PTR_ERR(r) == -EPROBE_DEFER) + return r; } /* if not found, try doing it non-dt way */ diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index 77a502141089..8e5506c5ee94 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h @@ -66,7 +66,8 @@ static inline struct regulator_dev *dev_to_rdev(struct device *dev) } #ifdef CONFIG_OF -struct regulator_dev *of_find_regulator_by_node(struct device_node *np); +struct regulator_dev *of_regulator_dev_lookup(struct device *dev, + const char *supply); struct regulator_init_data *regulator_of_get_init_data(struct device *dev, const struct regulator_desc *desc, struct regulator_config *config, @@ -80,10 +81,10 @@ int of_get_n_coupled(struct regulator_dev *rdev); bool of_check_coupling_data(struct regulator_dev *rdev); #else -static inline struct regulator_dev * -of_find_regulator_by_node(struct device_node *np) +static inline struct regulator_dev *of_regulator_dev_lookup(struct device *dev, + const char *supply) { - return NULL; + return ERR_PTR(-ENODEV); } static inline struct regulator_init_data * diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index cec8c3647a00..d5dd7a9e577b 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -552,7 +552,75 @@ struct regulator_init_data *regulator_of_get_init_data(struct device *dev, return NULL; } -struct regulator_dev *of_find_regulator_by_node(struct device_node *np) +/** + * of_get_child_regulator - get a child regulator device node + * based on supply name + * @parent: Parent device node + * @prop_name: Combination regulator supply name and "-supply" + * + * Traverse all child nodes. + * Extract the child regulator device node corresponding to the supply name. + * + * Return: Pointer to the &struct device_node corresponding to the regulator + * if found, or %NULL if not found. + */ +static struct device_node *of_get_child_regulator(struct device_node *parent, + const char *prop_name) +{ + struct device_node *regnode = NULL; + struct device_node *child = NULL; + + for_each_child_of_node(parent, child) { + regnode = of_parse_phandle(child, prop_name, 0); + + if (!regnode) { + regnode = of_get_child_regulator(child, prop_name); + if (regnode) + goto err_node_put; + } else { + goto err_node_put; + } + } + return NULL; + +err_node_put: + of_node_put(child); + return regnode; +} + +/** + * of_get_regulator - get a regulator device node based on supply name + * @dev: Device pointer for the consumer (of regulator) device + * @supply: regulator supply name + * + * Extract the regulator device node corresponding to the supply name. + * + * Return: Pointer to the &struct device_node corresponding to the regulator + * if found, or %NULL if not found. + */ +static struct device_node *of_get_regulator(struct device *dev, const char *supply) +{ + struct device_node *regnode = NULL; + char prop_name[64]; /* 64 is max size of property name */ + + dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); + + snprintf(prop_name, 64, "%s-supply", supply); + regnode = of_parse_phandle(dev->of_node, prop_name, 0); + + if (!regnode) { + regnode = of_get_child_regulator(dev->of_node, prop_name); + if (regnode) + return regnode; + + dev_dbg(dev, "Looking up %s property in node %pOF failed\n", + prop_name, dev->of_node); + return NULL; + } + return regnode; +} + +static struct regulator_dev *of_find_regulator_by_node(struct device_node *np) { struct device *dev; @@ -561,6 +629,46 @@ struct regulator_dev *of_find_regulator_by_node(struct device_node *np) return dev ? dev_to_rdev(dev) : NULL; } +/** + * of_regulator_dev_lookup - lookup a regulator device with device tree only + * @dev: Device pointer for regulator supply lookup. + * @supply: Supply name or regulator ID. + * + * Return: Pointer to the &struct regulator_dev on success, or ERR_PTR() + * encoded value on error. + * + * If successful, returns a pointer to the &struct regulator_dev that + * corresponds to the name @supply and with the embedded &struct device + * refcount incremented by one. The refcount must be dropped by calling + * put_device(). + * + * On failure one of the following ERR_PTR() encoded values is returned: + * * -%ENODEV if lookup fails permanently. + * * -%EPROBE_DEFER if lookup could succeed in the future. + */ +struct regulator_dev *of_regulator_dev_lookup(struct device *dev, + const char *supply) +{ + struct regulator_dev *r; + struct device_node *node; + + node = of_get_regulator(dev, supply); + if (node) { + r = of_find_regulator_by_node(node); + of_node_put(node); + if (r) + return r; + + /* + * We have a node, but there is no device. + * assume it has not registered yet. + */ + return ERR_PTR(-EPROBE_DEFER); + } + + return ERR_PTR(-ENODEV); +} + /* * Returns number of regulators coupled with rdev. */ From patchwork Wed Sep 4 09:00:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790232 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 69BA0CA0ED3 for ; Wed, 4 Sep 2024 09:36:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=b0sbG/jw58dFVSs3/2Q1ZWzAnnopRuiveILCTgaftSY=; b=Qh0PCiu72kGuvj4jzfUKROye7Q HTJcADmHdLaOiD5h+3JbpG6DSpzwdCuA4GFV394XdpWBsJ+CCXpikpJUyxkzU94hJwCLhEYzuyc2Y uLA0Yfu5qDh4t888ZXTfhHZqGqkLOGGtHmslJ+Kb3tBZz4sqO9yuzOZAh4xJblt8j9UwLfH9J5XlC eV0dSmqCMH3lr0AZiLecFRIsbharBUpMQ7lFFbArscteVlbP3JqqGgyA1Cot3qa5mT3NpsQIKVFfv UJ9kmNa+veJim1NBs2T3nd80Lzh2D39QhY6VILxEaEE51G33dGKCCXw2StBVOolQ71Kr/z7wlwili hEPRQ79w==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmR5-00000003i2Z-3wCB; Wed, 04 Sep 2024 09:36:23 +0000 Received: from mail-pf1-x42f.google.com ([2607:f8b0:4864:20::42f]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsU-00000003YqN-1SDx for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:00:39 +0000 Received: by mail-pf1-x42f.google.com with SMTP id d2e1a72fcca58-7141d7b270dso5096641b3a.2 for ; Wed, 04 Sep 2024 02:00:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440438; x=1726045238; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=b0sbG/jw58dFVSs3/2Q1ZWzAnnopRuiveILCTgaftSY=; b=Bgg7aklHzDmGJ78sORANIVyRKaR/AeodGek+Qbwway/IG32tVvbiH5LoJpFI66h/f0 KqH1R+BGshhDRolGI3fBPt5NyYBRGqjWTOAu3V0ipr+yZq6QVWk2vS6eYCqQWJPJ848m erbBPxRkRT0cxYafTfIUD7mliAmQAJV0ef3m4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440438; x=1726045238; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=b0sbG/jw58dFVSs3/2Q1ZWzAnnopRuiveILCTgaftSY=; b=UsqUW2eXwC15uFxmjFcSi7KGt9s5pTcDSgyxN8kGDkiNDyqHNU6r0MwYpdCZIb/mGv 6w0/QZ5W+6G2nEcioOni0oABus1JIFnJQj5yoXAHVanlzdex1EfhDuYlEHWfFspY39k7 LWuQ7wSSTr9dqZ1KQLc3OA7bTtHy1O6QtuiTcrvG2kqB5TzjkcPH5cTJccQUKGqvgrsZ E2J18LWybDQpvbaubEPsNmXnPJ/rxfvf18KQD17nN+CgL1pwSICB3drE3SleT6/zTQO+ nAdekUgDjF7tGuJc4gGWm6wi6mEOi2zpcvmdUQqx15k2gylz7hOZC5/WJ4kXoi0vhUrl tDrQ== X-Forwarded-Encrypted: i=1; AJvYcCUAN7ZGWFzMWix3LMh7E+nC0H6+Xdo/wSNql5BUwAL9zd6+7Bf3nCAAKvgLPf7a/3LvgXadR5vBc4noP40bgw==@lists.infradead.org X-Gm-Message-State: AOJu0YwTxRFoS0XQLaYa3u1aa4hHeolpEZtbh7C7iVydnd2IwFTuX60L +WtrgixwG8uOhSZQnu/ZxY2ExugUEvoozu7cwStISD/CZ/x/cN5/koydmKH1XA== X-Google-Smtp-Source: AGHT+IFJnhX8EeVHE/Pb/2Pe1cdA+zN3kwfbn5THcKUWQl9Uebvww0bAh3IhVagxcNqMcqnK8VZyqg== X-Received: by 2002:a05:6a21:6e4b:b0:1c6:ac08:8dd2 with SMTP id adf61e73a8af0-1ced6087aaemr11569081637.15.1725440437588; Wed, 04 Sep 2024 02:00:37 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.00.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:00:37 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 04/12] regulator: Split up _regulator_get() Date: Wed, 4 Sep 2024 17:00:06 +0800 Message-ID: <20240904090016.2841572-5-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020038_411995_998BC664 X-CRM114-Status: GOOD ( 18.83 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org _regulator_get() contains a lot of common code doing checks prior to the regulator lookup and housekeeping work after the lookup. Almost all the code could be shared with a OF-specific variant of _regulator_get(). Split out the common parts so that they can be reused. The OF-specific version of _regulator_get() will be added in a subsequent patch. No functional changes were made. Signed-off-by: Chen-Yu Tsai --- Changes since v5: - Fixed kerneldoc "Return" section format for _regulator_get_common() - Slightly reworded return value description Changes since v4: - New patch --- drivers/regulator/core.c | 54 ++++++++++++++++++++++++++++-------- drivers/regulator/internal.h | 4 +++ 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 835a5531d045..d60c86477ac2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -2103,26 +2103,43 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) return ret; } -/* Internal regulator request function */ -struct regulator *_regulator_get(struct device *dev, const char *id, - enum regulator_get_type get_type) +/* common pre-checks for regulator requests */ +int _regulator_get_common_check(struct device *dev, const char *id, + enum regulator_get_type get_type) { - struct regulator_dev *rdev; - struct regulator *regulator; - struct device_link *link; - int ret; - if (get_type >= MAX_GET_TYPE) { dev_err(dev, "invalid type %d in %s\n", get_type, __func__); - return ERR_PTR(-EINVAL); + return -EINVAL; } if (id == NULL) { dev_err(dev, "regulator request with no identifier\n"); - return ERR_PTR(-EINVAL); + return -EINVAL; } - rdev = regulator_dev_lookup(dev, id); + return 0; +} + +/** + * _regulator_get_common - Common code for regulator requests + * @rdev: regulator device pointer as returned by *regulator_dev_lookup() + * Its reference count is expected to have been incremented. + * @dev: device used for dev_printk messages + * @id: Supply name or regulator ID + * @get_type: enum regulator_get_type value corresponding to type of request + * + * Returns: pointer to struct regulator corresponding to @rdev, or ERR_PTR() + * encoded error. + * + * This function should be chained with *regulator_dev_lookup() functions. + */ +struct regulator *_regulator_get_common(struct regulator_dev *rdev, struct device *dev, + const char *id, enum regulator_get_type get_type) +{ + struct regulator *regulator; + struct device_link *link; + int ret; + if (IS_ERR(rdev)) { ret = PTR_ERR(rdev); @@ -2238,6 +2255,21 @@ struct regulator *_regulator_get(struct device *dev, const char *id, return regulator; } +/* Internal regulator request function */ +struct regulator *_regulator_get(struct device *dev, const char *id, + enum regulator_get_type get_type) +{ + struct regulator_dev *rdev; + int ret; + + ret = _regulator_get_common_check(dev, id, get_type); + if (ret) + return ERR_PTR(ret); + + rdev = regulator_dev_lookup(dev, id); + return _regulator_get_common(rdev, dev, id, get_type); +} + /** * regulator_get - lookup and obtain a reference to a regulator. * @dev: device for regulator "consumer" diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index 8e5506c5ee94..5b43f802468d 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h @@ -121,6 +121,10 @@ enum regulator_get_type { MAX_GET_TYPE }; +int _regulator_get_common_check(struct device *dev, const char *id, + enum regulator_get_type get_type); +struct regulator *_regulator_get_common(struct regulator_dev *rdev, struct device *dev, + const char *id, enum regulator_get_type get_type); struct regulator *_regulator_get(struct device *dev, const char *id, enum regulator_get_type get_type); int _regulator_bulk_get(struct device *dev, int num_consumers, From patchwork Wed Sep 4 09:00:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790234 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D1782CD3431 for ; Wed, 4 Sep 2024 09:37:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=zqurBuTzBG79QZ78UIum29OxfBzXy96OhjTo0P9FefQ=; b=UGKoEjY5C2Sxf0v7aazAbl1CD4 7ETcgZmzRCbq4a5Fo9hYEBXfvDZjHvaJGUgCO3wL6Dfu18uvXxD3ygMuDAHPhg0xEm4UOrHMZLsVy 8vWOt6Qpts20eV8CMPMP2FhHqrwga9Wsptjkqobn9HtuUmHpw7pPt3Faic+EgFMS0ndetJg3OWfvr bYubIoLkWQJ9o/n5VqKChE2mQLkptx6snHAJFN+cwydHjiCD/DLdmTv0dT/nbI6gTsrnwQGABKLC4 0RjbrbZD6xvNa8XpLeKXwUDd4DpQEQx6yEG9JHzrvcDTTaElkMYnTJh7kutFlDt3CDKClFCZqL+MA gf/k/K9g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmS0-00000003iMe-1HKN; Wed, 04 Sep 2024 09:37:20 +0000 Received: from mail-pf1-x432.google.com ([2607:f8b0:4864:20::432]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsY-00000003YrW-0eed for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:00:44 +0000 Received: by mail-pf1-x432.google.com with SMTP id d2e1a72fcca58-71456acebe8so490204b3a.3 for ; Wed, 04 Sep 2024 02:00:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440441; x=1726045241; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zqurBuTzBG79QZ78UIum29OxfBzXy96OhjTo0P9FefQ=; b=DpKFnp28JKeRmEuwDQAy7ZzHx4QHiM5y5YQ06aJY9xKBciXPbMtn6lcqn1Yy+Q7eKa 74IeByFS2EANY/JKjvbFSgoRPLEuOcwFx3s0UxTW0b0zQAVqBITz5dmRadCUO/+8l0LA 5iYH0ahOORsOMO/4xVznTdqOoca/ofRVd/pd8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440441; x=1726045241; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zqurBuTzBG79QZ78UIum29OxfBzXy96OhjTo0P9FefQ=; b=o3dh05CRjF2TSnudpt8NGUlqK+5ZASEaN2dHuv0faSLHgVMjOa7YVJD1wKyL90xGUz rHda5TJxbUJffQMEEmN2EiFWXkHU9rUExAmcxiutNe3ddJvjIrLuQt9pcBwYED6k8BXa bLjZUgPRQizTjl8Yn6VFjloSScMmXmYd8eBVdB69G7RVTq0CldYg/IXqbeBr5vZssG+F iCi1Z/rBOe/HmI+3BlOrW4mAQjoukbIFwHV42aomS/knH8xF3tj30QhQJDifnRA5eADW 7L8e5amJlgtIX73vqZ6/1ClEF6nQKxSOv9Ur2D/TkVUSgGydFYtbz/4kqmbnFSIwYvAH eCDA== X-Forwarded-Encrypted: i=1; AJvYcCW253D44Vs8wLrf7yeXCQK+wLQd5S4+4/mp8dyVn6jVwEbnORcxcbDUChzolfpsENU4/5OLYZdY9vF9IbdTrw==@lists.infradead.org X-Gm-Message-State: AOJu0YwInZWAg6V4ama//AVNutiO98pxM05zOkvmzMFved5ZxC/EePTx 4Jtu5WAneAoVJvEV4cXFWzHCJW7cGFfubmW2KI0GfLiHlfPdm6zAu83YnPMARA== X-Google-Smtp-Source: AGHT+IHe1ov6SAHeqdTpaMdmXEE49/kdY3WIDfrYRS2QYo2M/zJW5BO+zQ6dWos4RcZpLJnxA2k6Yg== X-Received: by 2002:a05:6a00:3d11:b0:714:20d1:944e with SMTP id d2e1a72fcca58-715dfaeaea3mr22059815b3a.2.1725440441161; Wed, 04 Sep 2024 02:00:41 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.00.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:00:40 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 05/12] regulator: Do pure DT regulator lookup in of_regulator_bulk_get_all() Date: Wed, 4 Sep 2024 17:00:07 +0800 Message-ID: <20240904090016.2841572-6-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020042_497099_0EEB940E X-CRM114-Status: GOOD ( 26.06 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org The to-be-introduced I2C component prober needs to enable regulator supplies (and toggle GPIO pins) for the various components it intends to probe. To support this, a new "pure DT lookup" method for getting regulator supplies is needed, since the device normally requesting the supply won't get created until after the component is probed to be available. Convert the existing of_regulator_bulk_get_all() for this purpose. This function has no in-tree users, as the original patch [1] that used it was never landed. This patch changes the function ABI, but it is straightforward to convert users. The underlying code that supports the existing regulator_get*() functions has been reworked in previous patches to support this specific case. An internal OF-specific version of regulator_get(), of_regulator_get_optional(), is added for this. Also convert an existing usage of "dev && dev->of_node" to "dev_of_node(dev)". [1] https://lore.kernel.org/all/20231220203537.83479-2-jernej.skrabec@gmail.com/ Signed-off-by: Chen-Yu Tsai --- Changes since v5: - Used "dev_of_node(dev)" instead of "dev->of_node" - Replaced "dev_printk" with "dev_printk()" in kerneldoc mentions - Fixed kerneldoc "Return" section format for of_regulator_get_optional() - Fix @np parameter name in of_regulator_dev_lookup() kerneldoc Changes since v4: - Restore platform-agnostic regulator consumer code to original state - Move OF-specific regulator code to of_regulator.c (separate patch) - Split _regulator_get() into three parts for reuse (separate patch) - Add OF-specific _of_regulator_get() function - Rename regulator_of_get_optional() to of_regulator_get_optional() for consistency - Make of_regulator_get_optional static, as it is only used internally - Convert of_regulator_bulk_get_all() Changes since v3: - New patch --- drivers/regulator/core.c | 4 +-- drivers/regulator/internal.h | 2 ++ drivers/regulator/of_regulator.c | 52 +++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index d60c86477ac2..f94a06ac2109 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1959,8 +1959,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, regulator_supply_alias(&dev, &supply); /* first do a dt based lookup */ - if (dev && dev->of_node) { - r = of_regulator_dev_lookup(dev, supply); + if (dev_of_node(dev)) { + r = of_regulator_dev_lookup(dev, dev_of_node(dev), supply); if (!IS_ERR(r)) return r; if (PTR_ERR(r) == -EPROBE_DEFER) diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index 5b43f802468d..f62cacbbc729 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h @@ -67,6 +67,7 @@ static inline struct regulator_dev *dev_to_rdev(struct device *dev) #ifdef CONFIG_OF struct regulator_dev *of_regulator_dev_lookup(struct device *dev, + struct device_node *np, const char *supply); struct regulator_init_data *regulator_of_get_init_data(struct device *dev, const struct regulator_desc *desc, @@ -82,6 +83,7 @@ bool of_check_coupling_data(struct regulator_dev *rdev); #else static inline struct regulator_dev *of_regulator_dev_lookup(struct device *dev, + struct device_node *np, const char *supply) { return ERR_PTR(-ENODEV); diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index d5dd7a9e577b..b00172176d0c 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c @@ -590,7 +590,8 @@ static struct device_node *of_get_child_regulator(struct device_node *parent, /** * of_get_regulator - get a regulator device node based on supply name - * @dev: Device pointer for the consumer (of regulator) device + * @dev: Device pointer for dev_printk() messages + * @node: Device node pointer for supply property lookup * @supply: regulator supply name * * Extract the regulator device node corresponding to the supply name. @@ -598,15 +599,16 @@ static struct device_node *of_get_child_regulator(struct device_node *parent, * Return: Pointer to the &struct device_node corresponding to the regulator * if found, or %NULL if not found. */ -static struct device_node *of_get_regulator(struct device *dev, const char *supply) +static struct device_node *of_get_regulator(struct device *dev, struct device_node *node, + const char *supply) { struct device_node *regnode = NULL; char prop_name[64]; /* 64 is max size of property name */ - dev_dbg(dev, "Looking up %s-supply from device tree\n", supply); + dev_dbg(dev, "Looking up %s-supply from device node %pOF\n", supply, node); snprintf(prop_name, 64, "%s-supply", supply); - regnode = of_parse_phandle(dev->of_node, prop_name, 0); + regnode = of_parse_phandle(node, prop_name, 0); if (!regnode) { regnode = of_get_child_regulator(dev->of_node, prop_name); @@ -632,6 +634,7 @@ static struct regulator_dev *of_find_regulator_by_node(struct device_node *np) /** * of_regulator_dev_lookup - lookup a regulator device with device tree only * @dev: Device pointer for regulator supply lookup. + * @np: Device node pointer for regulator supply lookup. * @supply: Supply name or regulator ID. * * Return: Pointer to the &struct regulator_dev on success, or ERR_PTR() @@ -646,13 +649,13 @@ static struct regulator_dev *of_find_regulator_by_node(struct device_node *np) * * -%ENODEV if lookup fails permanently. * * -%EPROBE_DEFER if lookup could succeed in the future. */ -struct regulator_dev *of_regulator_dev_lookup(struct device *dev, +struct regulator_dev *of_regulator_dev_lookup(struct device *dev, struct device_node *np, const char *supply) { struct regulator_dev *r; struct device_node *node; - node = of_get_regulator(dev, supply); + node = of_get_regulator(dev, np, supply); if (node) { r = of_find_regulator_by_node(node); of_node_put(node); @@ -669,6 +672,41 @@ struct regulator_dev *of_regulator_dev_lookup(struct device *dev, return ERR_PTR(-ENODEV); } +static struct regulator *_of_regulator_get(struct device *dev, struct device_node *node, + const char *id, enum regulator_get_type get_type) +{ + struct regulator_dev *r; + int ret; + + ret = _regulator_get_common_check(dev, id, get_type); + if (ret) + return ERR_PTR(ret); + + r = of_regulator_dev_lookup(dev, node, id); + return _regulator_get_common(r, dev, id, get_type); +} + +/** + * of_regulator_get_optional - get optional regulator via device tree lookup + * @dev: device used for dev_printk() messages + * @node: device node for regulator "consumer" + * @id: Supply name + * + * Return: pointer to struct regulator corresponding to the regulator producer, + * or PTR_ERR() encoded error number. + * + * This is intended for use by consumers that want to get a regulator + * supply directly from a device node, and can and want to deal with + * absence of such supplies. This will _not_ consider supply aliases. + * See regulator_dev_lookup(). + */ +static struct regulator *of_regulator_get_optional(struct device *dev, + struct device_node *node, + const char *id) +{ + return _of_regulator_get(NULL, node, id, OPTIONAL_GET); +} + /* * Returns number of regulators coupled with rdev. */ @@ -886,7 +924,7 @@ int of_regulator_bulk_get_all(struct device *dev, struct device_node *np, } else { memcpy(name, prop->name, i); name[i] = '\0'; - tmp = regulator_get(dev, name); + tmp = of_regulator_get_optional(dev, np, name); if (IS_ERR(tmp)) { ret = PTR_ERR(tmp); goto error; From patchwork Wed Sep 4 09:00:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790235 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 49B4ACD3431 for ; Wed, 4 Sep 2024 09:39:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=oXe0bTAdK4fzeVHk0iwWr+4YgaeXrtwwmT3G1fAlM0c=; b=KfLvWFJ+tNyAK5nb/TZmEIDA+m WvAUK1HF+m6LZ+MYzuiMUr/TUfO0KjYResj36uMpgoPeei4+hQD/FMdxmbN3wrZyfqBnJUVKi3ESY xFbVGmRuykk57DdD/k6m5QvLB5sUjAcEm+BG6PwpysdjROOGBe+tBCnPQqShbnPv2hHUm50UE0SXq dyRv86JKRZb0tVUFCMigTWk1ugnZD42dd5z55BYCFNwIRdb0Lj66SlcC8wutyT/LNn5g/Heuy0H2a Q4LKqyDsUzScuEGpawXPMTa5QfVEEpJz5tdXipXT0l+jrVNum6F2OHPmCKi32waeT+sXZjJRi3zIF rx2QIhQA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmTp-00000003iru-03Kc; Wed, 04 Sep 2024 09:39:13 +0000 Received: from mail-pf1-x429.google.com ([2607:f8b0:4864:20::429]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsb-00000003YtK-1pC6 for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:00:46 +0000 Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-70cec4aa1e4so4530549b3a.1 for ; Wed, 04 Sep 2024 02:00:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440445; x=1726045245; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=oXe0bTAdK4fzeVHk0iwWr+4YgaeXrtwwmT3G1fAlM0c=; b=XQdfrNjutGUIBe2/XwPDYvEn+AP0z8AsthSaC5lHzJqyN82N6+4bMzA/IRyTAjvzuw Nj/ZdEJ7bAtlyz54SQ4ewsOJVOGHlDapx44X/0PrGn49Wp2m3O3nIeKJUWaB+rIqfKEB cjQA4gyBPs4od8BL86m5p2dIcmAvqML6SYhLc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440445; x=1726045245; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=oXe0bTAdK4fzeVHk0iwWr+4YgaeXrtwwmT3G1fAlM0c=; b=Eu5WF2RP7JmtUWJftSYBxCLfDdZudYzg5POfPSlCxC9ecqc1HXPZq18WAYi9SflsdH kChmhLk6jrniZ9q5GowBcpB7GLEGgJsPEmaU6MOFmEyW8pMdbtL9+MeKzJXKAABcUAbe cGC/AqXsys3+Arj6eMNyenjFTmXHC76dVcf9w2l6DAgQiZQbPUbNOqKmQ0HI6h8ekicc g/UGgWdlWfGj5Sr04GPLsorjVtM7vgav0lccb+anX5yDQzFJoMNYz5xHB3DG8WDg5tYQ 0qSppvZcgIUtoC6zcp4KCwZtR7HtQ7wKefbrQzZt0JIUCt1AU0C+DkOl76h0W8Y5iyRA qkWQ== X-Forwarded-Encrypted: i=1; AJvYcCU7DnwUvD6Rlw7JhVH5HPrCHDNwLfbe0Tvkq0CXAlNXADzEAsGLRr73sS9kR4VEOpVeq6gWreFtpEeohJ+xQA==@lists.infradead.org X-Gm-Message-State: AOJu0YxkwoXi6O9LgRR537mlPvglFRC+Z7Y7CKxAYiE7/jmlCbR6NNKJ feNgb5KZZw+zZxkFfbTFL6CEMO99fT5F4tH4Gb7fr5Lj9jXyaUJMK2gtj4C4Hw== X-Google-Smtp-Source: AGHT+IGxijmAvO+pYlgJ7hjMKsPERsrObcLBwxYEKhBRWkHQTmof+srMssUjYemzBoLP7fiuqVV5Ew== X-Received: by 2002:a05:6a20:d48c:b0:1be:c929:e269 with SMTP id adf61e73a8af0-1cce10ab242mr24768495637.34.1725440444657; Wed, 04 Sep 2024 02:00:44 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.00.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:00:44 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 06/12] gpiolib: Add gpio_get_property_name_length() Date: Wed, 4 Sep 2024 17:00:08 +0800 Message-ID: <20240904090016.2841572-7-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020045_511054_E0B200AC X-CRM114-Status: GOOD ( 19.78 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org The I2C device tree component prober needs to get and toggle GPIO lines for the components it intends to probe. These components may not use the same name for their GPIO lines, so the prober must go through the device tree, check each property to see it is a GPIO property, and get the GPIO line. Instead of duplicating the GPIO suffixes, or exporting them to the prober to do pattern matching, simply add and export a new function that does the pattern matching and returns the length of the GPIO name. The caller can then use that to copy out the name if it needs to. Andy suggested a much shorter implementation. Suggested-by: Andy Shevchenko Signed-off-by: Chen-Yu Tsai --- Changes since v5: - Changed function name to "gpio_get_property_name_length()" - Changed argument name to "propname" - Clarified return value for "*-" case - Reworked according to Andy's suggestion - Added stub function Changes since v4: - new patch --- drivers/gpio/gpiolib.c | 25 +++++++++++++++++++++++++ include/linux/gpio/consumer.h | 7 +++++++ 2 files changed, 32 insertions(+) diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 3903d0a75304..86527cc7991b 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -4295,6 +4295,31 @@ struct gpio_desc *fwnode_gpiod_get_index(struct fwnode_handle *fwnode, } EXPORT_SYMBOL_GPL(fwnode_gpiod_get_index); +/** + * gpio_get_property_name_length - Returns the GPIO name length from a property name + * @propname: name of the property to check + * + * This function checks if the given property name matches the GPIO property + * patterns, and returns the length of the name of the GPIO. The pattern is + * "*-" or just "". + * + * Returns: + * The length of the string before '-' if it matches + * "*-", or 0 if no name part, just the suffix, or + * -EINVAL if the string doesn't match the pattern. + */ +int gpio_get_property_name_length(const char *propname) +{ + const char *dash = strrchr(propname, '-'); + + for (const char *const *p = gpio_suffixes; *p; p++) + if (!strcmp(dash ? dash + 1 : propname, *p)) + return dash ? dash - propname : 0; + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(gpio_get_property_name_length); + /** * gpiod_count - return the number of GPIOs associated with a device / function * or -ENOENT if no GPIO has been assigned to the requested function diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h index db2dfbae8edb..494dde33ca44 100644 --- a/include/linux/gpio/consumer.h +++ b/include/linux/gpio/consumer.h @@ -56,6 +56,8 @@ enum gpiod_flags { #ifdef CONFIG_GPIOLIB +int gpio_get_property_name_length(const char *propname); + /* Return the number of GPIOs associated with a device / function */ int gpiod_count(struct device *dev, const char *con_id); @@ -188,6 +190,11 @@ struct gpio_desc *devm_fwnode_gpiod_get_index(struct device *dev, #include +static inline int gpio_get_property_name_length(const char *propname) +{ + return ERR_PTR(-ENOSYS); +} + static inline int gpiod_count(struct device *dev, const char *con_id) { return 0; From patchwork Wed Sep 4 09:00:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790236 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 18FC7CA0ED3 for ; Wed, 4 Sep 2024 09:40:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=1lx3yQsWkTb9x7LagKbuMm4vpMCf33yZ7BqsG5IeSJA=; b=bECIwOP8v+qJbsny84qEQ0LZ/c nyHKKE2/aeTE+seSlzgWN2y8ZsptOrnXUmChJRf0Td4O8AQqnLmIs0FzuajgQM4wKcxD8vDi6UK8o 8/XTfVg1yPFZN3NvHeMQm1ZTIH718MYjOSOH0LWTmpkJC6ZyYqfdo71htSw0+BC1QC27NelWy2cAZ yBEca8/QsaYD86c2XU5KkUvmY2ew7QFJBxlBaD/v4j6aXzMCOw2adjnU3bsi5JUJM+NdZH9q/6jV/ KmWw6ox0VqLhRnlLLmomuvdRlBUOQGnsVwkD4lfkWhVURS/0ON564JkyNY5cW9IFZFeCkMEPW6Ltt hiTjIBsQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmUi-00000003j6R-3KLs; Wed, 04 Sep 2024 09:40:08 +0000 Received: from mail-pf1-x429.google.com ([2607:f8b0:4864:20::429]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsf-00000003Yvh-0WkW for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:00:51 +0000 Received: by mail-pf1-x429.google.com with SMTP id d2e1a72fcca58-7176645e440so368567b3a.1 for ; Wed, 04 Sep 2024 02:00:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440448; x=1726045248; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=1lx3yQsWkTb9x7LagKbuMm4vpMCf33yZ7BqsG5IeSJA=; b=cSH3S+V7TT3X2JYOSRfMfTppqszYgpAZx22dDnp8yG82K2ict/GrZqlLG2INjx8u2W hDM75Th3aOhZWGq6dGSsSDtKxQ16i48ZqzU8SgjIQYaMlZXQHGAGdXVWDyAfquFNvdQT /2ROLBtt2uZSJKX/DfZ+ZfdxYk1++vsN+LOx4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440448; x=1726045248; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=1lx3yQsWkTb9x7LagKbuMm4vpMCf33yZ7BqsG5IeSJA=; b=E8uALIBOo+4goad2zlSXGfDhcGSRXKM2cked4k6xm8mWJj90Tyw0QwCUeQPDDEw4HN TTtiKHeFbMGmELF+OgNy/MWrX3xobyoHL3wwAIyusAUwaxDYodPyDWFjhWd8SpPPPJII skkXnmZv7irBtOfCz/klHXVO8LXA1ErGLkEAxf9pjGvxpirwP5vi/hNmSAtLbYOZFdSl HgRznZrdeTUkyj5h5crkbywMQ0S34sHt1PQNodRQMqBw2yC4Z0BTztcFY6dWESXyHxt4 WRd7eSmg/HhbazME0REuRNABtNdsOfk2+ahnywXapZOh5M2sHb2QyqEJvVkQpwWI6Sj5 dXUQ== X-Forwarded-Encrypted: i=1; AJvYcCXFUil3AaT99v2nHoUc25b//8vyQanHLfOtLvXhKm5YnAz/EDvWa6pBidz8tvXYOiwPxChGZY7BFUZd6eV0dQ==@lists.infradead.org X-Gm-Message-State: AOJu0YyjvTmTB8jpyCnVy1wcyRjpqQ8/U77BG4qm2tlF8HLEQIfDbK8L T2pljHWHAfbBk+rEr6cXlyOu2dcoXXmgDUfKwWZnQTM32RFeww1GysWd5Q2dbg== X-Google-Smtp-Source: AGHT+IFljw5CEOubKFgJs6Qw/4fe2qNKJQ/lUogumRK/GAi7DQzBwRnb7bCkK8F5ANHCSTOzSxDq3Q== X-Received: by 2002:a05:6a00:2e08:b0:714:228d:e9f2 with SMTP id d2e1a72fcca58-7177a92187bmr2450461b3a.3.1725440448446; Wed, 04 Sep 2024 02:00:48 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.00.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:00:48 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 07/12] i2c: core: Remove extra space in Makefile Date: Wed, 4 Sep 2024 17:00:09 +0800 Message-ID: <20240904090016.2841572-8-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020049_209566_953F54D7 X-CRM114-Status: GOOD ( 11.46 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Some lines in the Makefile have a space before tabs. Remove those. Reported-by: Andy Shevchenko Closes: https://lore.kernel.org/all/ZsdE0PxKnGRjzChl@smile.fi.intel.com/ Signed-off-by: Chen-Yu Tsai Reviewed-by: Andy Shevchenko --- Changes since v5: - new patch --- drivers/i2c/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 3f71ce4711e3..f12d6b10a85e 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -5,10 +5,10 @@ obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o obj-$(CONFIG_I2C) += i2c-core.o -i2c-core-objs := i2c-core-base.o i2c-core-smbus.o +i2c-core-objs := i2c-core-base.o i2c-core-smbus.o i2c-core-$(CONFIG_ACPI) += i2c-core-acpi.o -i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o -i2c-core-$(CONFIG_OF) += i2c-core-of.o +i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o +i2c-core-$(CONFIG_OF) += i2c-core-of.o obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o From patchwork Wed Sep 4 09:00:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790247 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1D0D1CA0ED3 for ; Wed, 4 Sep 2024 09:41:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=3ed6jqfoQQgVNg3s8z2id6R5BmVDPgmpZejNIbOkDt8=; b=ESoLUW7GxGTDy5chcQ1rg/1qMi 5pHz40JQWAkM6K/nEHxVsPAFXusLQNfu0Rqx5BP7h+htMv8UYjOh2R4iVKTJxaE8ifNtJ8Q8OT+HI eGnNW7F3iEq3Kc3SPl3cGcCqF75qKAZwxyS8Ik4Wy5GW78/Dz5J9QsSFJUczG600w9bWtDJ+vF6lw mootsL2WadGniz5AghobomR8qAWtJJJC3qjZ7WBxyOromvmHvH0gD7cZgnrCTN37taA4xM6U8EVwl EAh7RBLOo9/BQHqMXd8AO76OXzvHi6GN/PhrzL79ExsIArQWR/NO+fqtWDslTd33j/FRPOF2DClbd HptXhRJw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmVd-00000003jLK-3SYD; Wed, 04 Sep 2024 09:41:05 +0000 Received: from mail-pf1-x42b.google.com ([2607:f8b0:4864:20::42b]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsj-00000003Yxk-1ZLF for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:00:55 +0000 Received: by mail-pf1-x42b.google.com with SMTP id d2e1a72fcca58-7176645e4daso1905436b3a.3 for ; Wed, 04 Sep 2024 02:00:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440452; x=1726045252; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3ed6jqfoQQgVNg3s8z2id6R5BmVDPgmpZejNIbOkDt8=; b=bn1/WIpIYODIWQ/6kDNY+2kxUYB8/ituCbC7/Puuy6R0hZBxhYOPRJHiRy/Z01kg9v 0bs5+DH3MdQ9B3OaaQArD7XVb4qFYWNJzxuKMBugoiKFqKB7bvBR9crcsiFOigFmiHCp WxGZwQRM/8XUdGYvLrLraq1HnlJAwsRZe+Ry0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440452; x=1726045252; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3ed6jqfoQQgVNg3s8z2id6R5BmVDPgmpZejNIbOkDt8=; b=GzEs5netLmqZ6syJS5SZdIrFEg1iEkr72JKldtRAe7d045MWtoIhvnbxGcbjeItPO9 QxokEorKT+7X0ZhILtuA5gAI8yp+SY5XXIOLC1SSjvBvLF+1RqxXZKgQ7RESzfHdXbDE eL+e8bPVueN4bw4JtlMCHuSiZ1v+lIOBY+e5XA7sGmETyXhM9hQQVdnDiu+fY8MiEZro 1s9Q8nIqICYhwoFGdRPf8I6c7laqEyMWB0NQeWsdrqL6cegmNtfmGiAEXG0W9lMp6xKp kkp2AKynLzUW8jwznUndFuRxNiloK97mgGsebeyjs6KQBtLW4AU4SUNa4/izdNDZrmuO ycsg== X-Forwarded-Encrypted: i=1; AJvYcCWuDt9Z+wh08tqZj5k2Vc/5zb0zIGXmKQKlrbfqTlYna0g2FJWMqZG4tUqx6C3F507n8Jm67JGtp+tNpgNDgw==@lists.infradead.org X-Gm-Message-State: AOJu0YzK7bNv2n/ZK3YDyju7kmeJ/2QeWhZEIRrcCPDx90gJUpzYCeke 7S16D4a5Wff5gzHSKtdX31RigbjNKMQyhkPkg8L9mixIRsrNFmv0gN2wX16sBQ== X-Google-Smtp-Source: AGHT+IHgy+GLE/Elk7AlgRjkOzPzYZQvWSrVWrXb8ZopFFo9Tqw+tlmxWy6NqFA6LVTclmTWOYnewQ== X-Received: by 2002:a05:6a00:2da8:b0:70e:8070:f9d0 with SMTP id d2e1a72fcca58-7173fa40bcfmr10345406b3a.9.1725440452151; Wed, 04 Sep 2024 02:00:52 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.00.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:00:51 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 08/12] i2c: Introduce OF component probe function Date: Wed, 4 Sep 2024 17:00:10 +0800 Message-ID: <20240904090016.2841572-9-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020053_467421_F56435F9 X-CRM114-Status: GOOD ( 40.94 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Some devices are designed and manufactured with some components having multiple drop-in replacement options. These components are often connected to the mainboard via ribbon cables, having the same signals and pin assignments across all options. These may include the display panel and touchscreen on laptops and tablets, and the trackpad on laptops. Sometimes which component option is used in a particular device can be detected by some firmware provided identifier, other times that information is not available, and the kernel has to try to probe each device. This change attempts to make the "probe each device" case cleaner. The current approach is to have all options added and enabled in the device tree. The kernel would then bind each device and run each driver's probe function. This works, but has been broken before due to the introduction of asynchronous probing, causing multiple instances requesting "shared" resources, such as pinmuxes, GPIO pins, interrupt lines, at the same time, with only one instance succeeding. Work arounds for these include moving the pinmux to the parent I2C controller, using GPIO hogs or pinmux settings to keep the GPIO pins in some fixed configuration, and requesting the interrupt line very late. Such configurations can be seen on the MT8183 Krane Chromebook tablets, and the Qualcomm sc8280xp-based Lenovo Thinkpad 13S. Instead of this delicate dance between drivers and device tree quirks, this change introduces a simple I2C component probe. function For a given class of devices on the same I2C bus, it will go through all of them, doing a simple I2C read transfer and see which one of them responds. It will then enable the device that responds. This requires some minor modifications in the existing device tree. The status for all the device nodes for the component options must be set to "failed-needs-probe". This makes it clear that some mechanism is needed to enable one of them, and also prevents the prober and device drivers running at the same time. Signed-off-by: Chen-Yu Tsai --- Changes since v5: - Fixed indent in Makefile - Split regulator and GPIO TODO items - Reversed final conditional in i2c_of_probe_enable_node() Changes since v4: - Split code into helper functions - Use scoped helpers and __free() to reduce error path Changes since v3: - Complete kernel-doc - Return different error if I2C controller is disabled - Expand comment to explain assumptions and constraints - Split for-loop finding target node and operations on target node - Add missing i2c_put_adapter() - Move prober code to separate file Rob also asked why there was a limitation of "exactly one touchscreen will be enabled across the whole tree". The use case this prober currently targets is a component on consumer electronics (tablet or laptop) being swapped out due to cost or supply reasons. Designs with multiple components of the same type are pretty rare. The way the next patch is written also assumes this for efficiency reasons. Changes since v2: - New patch split out from "of: Introduce hardware prober driver" - Addressed Rob's comments - Move i2c prober to i2c subsystem - Use of_node_is_available() to check if node is enabled. - Use OF changeset API to update status property - Addressed Andy's comments - Probe function now accepts "struct device *dev" instead to reduce line length and dereferences - Move "ret = 0" to just before for_each_child_of_node(i2c_node, node) --- drivers/i2c/Makefile | 1 + drivers/i2c/i2c-core-of-prober.c | 158 +++++++++++++++++++++++++++++++ include/linux/i2c.h | 4 + 3 files changed, 163 insertions(+) create mode 100644 drivers/i2c/i2c-core-of-prober.c diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index f12d6b10a85e..c539cdc1e305 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -9,6 +9,7 @@ i2c-core-objs := i2c-core-base.o i2c-core-smbus.o i2c-core-$(CONFIG_ACPI) += i2c-core-acpi.o i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o i2c-core-$(CONFIG_OF) += i2c-core-of.o +i2c-core-$(CONFIG_OF_DYNAMIC) += i2c-core-of-prober.o obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o diff --git a/drivers/i2c/i2c-core-of-prober.c b/drivers/i2c/i2c-core-of-prober.c new file mode 100644 index 000000000000..64d7631f4885 --- /dev/null +++ b/drivers/i2c/i2c-core-of-prober.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Linux I2C core OF component prober code + * + * Copyright (C) 2024 Google LLC + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Some devices, such as Google Hana Chromebooks, are produced by multiple + * vendors each using their preferred components. Such components are all + * in the device tree. Instead of having all of them enabled and having each + * driver separately try and probe its device while fighting over shared + * resources, they can be marked as "fail-needs-probe" and have a prober + * figure out which one is actually used beforehand. + * + * This prober assumes such drop-in parts are on the same I2C bus, have + * non-conflicting addresses, and can be directly probed by seeing which + * address responds. + * + * TODO: + * - Support handling common regulators. + * - Support handling common GPIOs. + * - Support I2C muxes + */ + +static struct device_node *i2c_of_probe_get_i2c_node(struct device *dev, const char *type) +{ + struct device_node *node __free(device_node) = of_find_node_by_name(NULL, type); + if (!node) + return dev_err_ptr_probe(dev, -ENODEV, "Could not find %s device node\n", type); + + struct device_node *i2c_node __free(device_node) = of_get_parent(node); + if (!of_node_name_eq(i2c_node, "i2c")) + return dev_err_ptr_probe(dev, -EINVAL, "%s device isn't on I2C bus\n", type); + + if (!of_device_is_available(i2c_node)) + return dev_err_ptr_probe(dev, -ENODEV, "I2C controller not available\n"); + + return no_free_ptr(i2c_node); +} + +static int i2c_of_probe_enable_node(struct device *dev, struct device_node *node) +{ + int ret; + + dev_info(dev, "Enabling %pOF\n", node); + + struct of_changeset *ocs __free(kfree) = kzalloc(sizeof(*ocs), GFP_KERNEL); + if (!ocs) + return -ENOMEM; + + of_changeset_init(ocs); + ret = of_changeset_update_prop_string(ocs, node, "status", "okay"); + if (ret) + return ret; + + ret = of_changeset_apply(ocs); + if (ret) { + /* ocs needs to be explicitly cleaned up before being freed. */ + of_changeset_destroy(ocs); + } else { + /* + * ocs is intentionally kept around as it needs to + * exist as long as the change is applied. + */ + void *ptr __always_unused = no_free_ptr(ocs); + } + + return ret; +} + +/** + * i2c_of_probe_component() - probe for devices of "type" on the same i2c bus + * @dev: &struct device of the caller, only used for dev_* printk messages + * @type: a string to match the device node name prefix to probe for + * + * Probe for possible I2C components of the same "type" on the same I2C bus + * that have their status marked as "fail". + * + * Assumes that across the entire device tree the only instances of nodes + * prefixed with "type" are the ones that need handling for second source + * components. In other words, if type is "touchscreen", then all device + * nodes named "touchscreen*" are the ones that need probing. There cannot + * be another "touchscreen" node that is already enabled. + * + * Assumes that for each "type" of component, only one actually exists. In + * other words, only one matching and existing device will be enabled. + * + * Context: Process context only. Does non-atomic I2C transfers. + * Should only be used from a driver probe function, as the function + * can return -EPROBE_DEFER if the I2C adapter is unavailable. + * Return: 0 on success or no-op, error code otherwise. + * A no-op can happen when it seems like the device tree already + * has components of the type to be probed already enabled. This + * can happen when the device tree had not been updated to mark + * the status of the to-be-probed components as "fail". Or this + * function was already run with the same parameters and succeeded + * in enabling a component. The latter could happen if the user + * had multiple types of components to probe, and one of them down + * the list caused a deferred probe. This is expected behavior. + */ +int i2c_of_probe_component(struct device *dev, const char *type) +{ + struct i2c_adapter *i2c; + int ret; + + struct device_node *i2c_node __free(device_node) = i2c_of_probe_get_i2c_node(dev, type); + if (IS_ERR(i2c_node)) + return PTR_ERR(i2c_node); + + for_each_child_of_node_scoped(i2c_node, node) { + if (!of_node_name_prefix(node, type)) + continue; + if (!of_device_is_available(node)) + continue; + + /* + * Device tree has component already enabled. Either the + * device tree isn't supported or we already probed once. + */ + return 0; + } + + i2c = of_get_i2c_adapter_by_node(i2c_node); + if (!i2c) + return dev_err_probe(dev, -EPROBE_DEFER, "Couldn't get I2C adapter\n"); + + ret = 0; + for_each_child_of_node_scoped(i2c_node, node) { + union i2c_smbus_data data; + u32 addr; + + if (!of_node_name_prefix(node, type)) + continue; + if (of_property_read_u32(node, "reg", &addr)) + continue; + if (i2c_smbus_xfer(i2c, addr, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data) < 0) + continue; + + /* Found a device that is responding */ + ret = i2c_of_probe_enable_node(dev, node); + break; + } + + i2c_put_adapter(i2c); + + return ret; +} +EXPORT_SYMBOL_GPL(i2c_of_probe_component); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 388ce71a29a9..c6c16731243d 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -1033,6 +1033,10 @@ const struct of_device_id int of_i2c_get_board_info(struct device *dev, struct device_node *node, struct i2c_board_info *info); +#if IS_ENABLED(CONFIG_OF_DYNAMIC) +int i2c_of_probe_component(struct device *dev, const char *type); +#endif + #else static inline struct i2c_client *of_find_i2c_device_by_node(struct device_node *node) From patchwork Wed Sep 4 09:00:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790248 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 385FFCD3431 for ; Wed, 4 Sep 2024 09:42:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=qLn/XE+uDzMxmMKZJAijY6Hl5jp5DWcTMHCPptQeycc=; b=IB/Po+pJ50N9BUEOGyvcij0vHy SQA0/EmPQ8f/9SGdQ2H+iSJsL/Ud8TTUdm4f9i/Rzg5jCfLfVL95HiPzDzsz0ZOIgdqSOgdIaiwnf DNer7lWtuGhMh76cf9oA0jGY5SK42pAmqgL0FHmoGelr0a7tx/Ftz0w5ZubLORmt2pN5e9AZ9A9DC rfANJ3w5W0fhI3b5mxDUz6+5V3FTKUP2ns3E5CRSkPTTLS80OuUSX5+X6+dt1pand9mT1QAPirkWN LuKt20Nt4YaHuW3wJprXkJH+wAPmzQYp/QqGooTeGgZiDd77AvOMNf+/wAcClRnd6KcQCJ2T5KYVj MwIi3PjA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmXQ-00000003jpL-2jAK; Wed, 04 Sep 2024 09:42:56 +0000 Received: from mail-oo1-xc32.google.com ([2607:f8b0:4864:20::c32]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsn-00000003Yzf-1NTh for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:00:58 +0000 Received: by mail-oo1-xc32.google.com with SMTP id 006d021491bc7-5dca9cc71b2so375347eaf.2 for ; Wed, 04 Sep 2024 02:00:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440456; x=1726045256; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qLn/XE+uDzMxmMKZJAijY6Hl5jp5DWcTMHCPptQeycc=; b=fstfpRde66oLtMa3jcIppzwB080rXQbI/UsUVdJnR1r1+kQNmumN/EXzpCQZwwEBtj HoG0KXbulty6G6QtFbXeQjXQtCgAo5ZhI74k/kjfnv9SI/jLAEhgHpX/ZJ+8r31ckFZ3 gzFU7fC/j+AuJ4bt2V1XiRpld4mNOuA/xxanQ= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440456; x=1726045256; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qLn/XE+uDzMxmMKZJAijY6Hl5jp5DWcTMHCPptQeycc=; b=R6pv3lGrlhNBUYyI9tjmOon7Gsn6hKeOReXkVTevM82AD3D1KmDX+XKGwZyaX3ITyd sZZSg+osi20K7JUGiTb3UCQoi28rxfAl50W7sly6YmFdRII+ga2BXvBdgnAfL/Ao0X92 nZOJD/g2YbsvQgeH17YLZ/W9LqCWd+S03CPQBAlIYk3jKDXnz8vdrSWVhVYKvEuvEB0p mco6+JSFPL6uxIkXMd95RvGFmjs7zBs+E2FQkOer0nDkBFTPJMwSEpQexQG8nH8PjtWY GaVc6YuWU6yRIDlztfMhtAMefwKd/ryRf36ficNH+1OE6+p4rthgwvql++I/UKlG5S0w a4rA== X-Forwarded-Encrypted: i=1; AJvYcCXPSTOOnQe3Rk305yxPEWwfHW/uz6Vat1i9yCB+dVSIAnmBHD9bq6fAd7JRaZew2oIOunnj+QTKDb7As9V8hA==@lists.infradead.org X-Gm-Message-State: AOJu0YzOzV5HJlnbDfs+eDnhs3w9GWgmI5Lm+HO2lYGIHlThlcqdjT9w uVQMFBvS4UDoTZUAwPngJ+egkxe/qE6oWZvUxtePo7D5ecm2rFHh7MMAe3TUiQ== X-Google-Smtp-Source: AGHT+IHzx1FZvOZD6BTlnZiQsDYe4dTxexfmSKVGQ4N7JYcwoXKnticdmTrNQBjnjLU8yqjr9ZcwRA== X-Received: by 2002:a05:6870:64a9:b0:277:e512:f27a with SMTP id 586e51a60fabf-277e512f84emr11125014fac.16.1725440455782; Wed, 04 Sep 2024 02:00:55 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.00.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:00:55 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 09/12] i2c: of-prober: Add regulator support Date: Wed, 4 Sep 2024 17:00:11 +0800 Message-ID: <20240904090016.2841572-10-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020057_380783_D9B6DF79 X-CRM114-Status: GOOD ( 33.18 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org This adds regulator management to the I2C OF component prober. Components that the prober intends to probe likely require their regulator supplies be enabled, and GPIOs be toggled to enable them or bring them out of reset before they will respond to probe attempts. GPIOs will be handled in the next patch. Without specific knowledge of each component's resource names or power sequencing requirements, the prober can only enable the regulator supplies all at once, and toggle the GPIOs all at once. Luckily, reset pins tend to be active low, while enable pins tend to be active high, so setting the raw status of all GPIO pins to high should work. The wait time before and after resources are enabled are collected from existing drivers and device trees. The prober collects resources from all possible components and enables them together, instead of enabling resources and probing each component one by one. The latter approach does not provide any boot time benefits over simply enabling each component and letting each driver probe sequentially. The prober will also deduplicate the resources, since on a component swap out or co-layout design, the resources are always the same. While duplicate regulator supplies won't cause much issue, shared GPIOs don't work reliably, especially with other drivers. For the same reason, the prober will release the GPIOs before the successfully probed component is actually enabled. Signed-off-by: Chen-Yu Tsai --- Changes since v5: - Split of_regulator_bulk_get_all() return value check and explain "ret == 0" case - Switched to of_get_next_child_with_prefix_scoped() where applicable - Used krealloc_array() instead of directly calculating size - copy whole regulator array in one memcpy() call - Drop "0" from struct zeroing initializer - Split out regulator helper from i2c_of_probe_enable_res() to keep code cleaner when combined with the next patch - Added options for customizing power sequencing delay - Rename i2c_of_probe_get_regulator() to i2c_of_probe_get_regulators() - Add i2c_of_probe_free_regulator() helper Changes since v4: - Split out GPIO handling to separate patch - Rewrote using of_regulator_bulk_get_all() - Replaced "regulators" with "regulator supplies" in debug messages Changes since v3: - New patch This change is kept as a separate patch for now since the changes are quite numerous. --- drivers/i2c/i2c-core-of-prober.c | 154 +++++++++++++++++++++++++++++-- include/linux/i2c.h | 10 +- 2 files changed, 155 insertions(+), 9 deletions(-) diff --git a/drivers/i2c/i2c-core-of-prober.c b/drivers/i2c/i2c-core-of-prober.c index 64d7631f4885..56b06ad7aa64 100644 --- a/drivers/i2c/i2c-core-of-prober.c +++ b/drivers/i2c/i2c-core-of-prober.c @@ -6,12 +6,14 @@ */ #include +#include #include #include #include #include #include #include +#include #include /* @@ -27,11 +29,119 @@ * address responds. * * TODO: - * - Support handling common regulators. * - Support handling common GPIOs. * - Support I2C muxes */ +struct i2c_of_probe_data { + const struct i2c_of_probe_opts *opts; + struct regulator_bulk_data *regulators; + unsigned int regulators_num; +}; + +/* Returns number of regulator supplies found for node, or error. */ +static int i2c_of_probe_get_regulators(struct device *dev, struct device_node *node, + struct i2c_of_probe_data *data) +{ + struct regulator_bulk_data *tmp, *new_regulators; + int ret; + + ret = of_regulator_bulk_get_all(dev, node, &tmp); + if (ret < 0) { + return ret; + } else if (ret == 0) { + /* + * It's entirely possible for a device node to not have + * regulator supplies. While it doesn't make sense from + * a hardware perspective, the supplies could be always + * on or otherwise not modeled in the device tree, but + * the device would still work. + */ + return ret; + } + + if (!data->regulators) { + data->regulators = tmp; + data->regulators_num = ret; + return ret; + }; + + new_regulators = krealloc_array(data->regulators, (data->regulators_num + ret), + sizeof(*tmp), GFP_KERNEL); + if (!new_regulators) { + regulator_bulk_free(ret, tmp); + return -ENOMEM; + } + + data->regulators = new_regulators; + memcpy(&data->regulators[data->regulators_num], tmp, sizeof(*tmp) * ret); + data->regulators_num += ret; + + return ret; +} + +static void i2c_of_probe_free_regulators(struct i2c_of_probe_data *data) +{ + regulator_bulk_free(data->regulators_num, data->regulators); + data->regulators_num = 0; + data->regulators = NULL; +} + +static void i2c_of_probe_free_res(struct i2c_of_probe_data *data) +{ + i2c_of_probe_free_regulators(data); +} + +static int i2c_of_probe_get_res(struct device *dev, struct device_node *node, + struct i2c_of_probe_data *data) +{ + struct property *prop; + int ret; + + ret = i2c_of_probe_get_regulators(dev, node, data); + if (ret < 0) { + dev_err_probe(dev, ret, "Failed to get regulator supplies from %pOF\n", node); + goto err_cleanup; + } + + return 0; + +err_cleanup: + i2c_of_probe_free_res(data); + return ret; +} + +static int i2c_of_probe_enable_regulators(struct device *dev, struct i2c_of_probe_data *data) +{ + int ret; + + dev_dbg(dev, "Enabling regulator supplies\n"); + + ret = regulator_bulk_enable(data->regulators_num, data->regulators); + if (ret) + return ret; + + msleep(data->opts->post_power_on_delay_ms); + + return 0; +} + +static void i2c_of_probe_disable_regulators(struct i2c_of_probe_data *data) +{ + regulator_bulk_disable(data->regulators_num, data->regulators); +} + +static int i2c_of_probe_enable_res(struct device *dev, struct i2c_of_probe_data *data) +{ + int ret; + + ret = i2c_of_probe_enable_regulators(dev, data); + if (ret) + return ret; + + return 0; +} + static struct device_node *i2c_of_probe_get_i2c_node(struct device *dev, const char *type) { struct device_node *node __free(device_node) = of_find_node_by_name(NULL, type); @@ -78,10 +188,17 @@ static int i2c_of_probe_enable_node(struct device *dev, struct device_node *node return ret; } +static const struct i2c_of_probe_opts i2c_of_probe_opts_default = { + /* largest post-power-on pre-reset-deassert delay seen among drivers */ + .post_power_on_delay_ms = 500, +}; + /** * i2c_of_probe_component() - probe for devices of "type" on the same i2c bus * @dev: &struct device of the caller, only used for dev_* printk messages * @type: a string to match the device node name prefix to probe for + * @opts: &struct i2c_of_probe_data containing tweakable options for the prober. + * Defaults are used if this is %NULL. * * Probe for possible I2C components of the same "type" on the same I2C bus * that have their status marked as "fail". @@ -108,8 +225,9 @@ static int i2c_of_probe_enable_node(struct device *dev, struct device_node *node * had multiple types of components to probe, and one of them down * the list caused a deferred probe. This is expected behavior. */ -int i2c_of_probe_component(struct device *dev, const char *type) +int i2c_of_probe_component(struct device *dev, const char *type, const struct i2c_of_probe_opts *opts) { + struct i2c_of_probe_data probe_data = { .opts = opts ?: &i2c_of_probe_opts_default }; struct i2c_adapter *i2c; int ret; @@ -117,9 +235,7 @@ int i2c_of_probe_component(struct device *dev, const char *type) if (IS_ERR(i2c_node)) return PTR_ERR(i2c_node); - for_each_child_of_node_scoped(i2c_node, node) { - if (!of_node_name_prefix(node, type)) - continue; + for_each_child_of_node_with_prefix_scoped(i2c_node, node, type) { if (!of_device_is_available(node)) continue; @@ -134,13 +250,33 @@ int i2c_of_probe_component(struct device *dev, const char *type) if (!i2c) return dev_err_probe(dev, -EPROBE_DEFER, "Couldn't get I2C adapter\n"); + /* Grab resources */ + for_each_child_of_node_with_prefix_scoped(i2c_node, node, type) { + u32 addr; + + if (of_property_read_u32(node, "reg", &addr)) + continue; + + dev_dbg(dev, "Requesting resources for %pOF\n", node); + ret = i2c_of_probe_get_res(dev, node, &probe_data); + if (ret) + return ret; + } + + dev_dbg(dev, "Resources: # of regulator supplies = %d\n", probe_data.regulators_num); + + /* Enable resources */ + ret = i2c_of_probe_enable_res(dev, &probe_data); + if (ret) { + i2c_of_probe_free_res(&probe_data); + return dev_err_probe(dev, ret, "Failed to enable resources\n"); + } + ret = 0; - for_each_child_of_node_scoped(i2c_node, node) { + for_each_child_of_node_with_prefix_scoped(i2c_node, node, type) { union i2c_smbus_data data; u32 addr; - if (!of_node_name_prefix(node, type)) - continue; if (of_property_read_u32(node, "reg", &addr)) continue; if (i2c_smbus_xfer(i2c, addr, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data) < 0) @@ -151,6 +287,8 @@ int i2c_of_probe_component(struct device *dev, const char *type) break; } + i2c_of_probe_disable_regulators(&probe_data); + i2c_of_probe_free_res(&probe_data); i2c_put_adapter(i2c); return ret; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index c6c16731243d..dbcdb8edbf6f 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -1034,7 +1034,15 @@ int of_i2c_get_board_info(struct device *dev, struct device_node *node, struct i2c_board_info *info); #if IS_ENABLED(CONFIG_OF_DYNAMIC) -int i2c_of_probe_component(struct device *dev, const char *type); +/** + * i2c_of_probe_opts - I2C OF component prober customization options + * @post_power_on_delay_us: Delay in ms after regulators are powered on. Passed to msleep(). + */ +struct i2c_of_probe_opts { + unsigned int post_power_on_delay_ms; +}; + +int i2c_of_probe_component(struct device *dev, const char *type, const struct i2c_of_probe_opts *opts); #endif #else From patchwork Wed Sep 4 09:00:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790249 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 91E1CCA0ED3 for ; Wed, 4 Sep 2024 09:42:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=DwAJluv0Exq9EadYfBSyNeJ8D4Ka/sU/iYmJbm5J4eo=; b=KR+oq+ku3T9+yjIGNb0C9A02+6 oGSZkd8yDVgVNoUqA5d11FW19OkX31/lLZE32OJEyldMku+GA/YVnkrw4vIZni8M3zlJFvm6ieYOI 6GnilveYzmzv+2xk80GvP7QX/J35z/jwLDy/7NcFrQkaqIP3MMvJCNUZ7ZE7zrF+VcxZjeYRzH6MK FdrP070dy4hNLEqzRLelzQb0eBv/wzwE12BPjjzcny3c0+vT9ofA3CVjGNxaMmvMm8PA7jAlzx08X NdN99lEeZyCBAjXzC8j67CoQEpAjwfHxeY9nXC9NV7dU/TTXcz6Cajm41jvDupU5ncNPVKHXp+3ad A98KjgrQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmXQ-00000003jpg-43dS; Wed, 04 Sep 2024 09:42:56 +0000 Received: from mail-pg1-x52d.google.com ([2607:f8b0:4864:20::52d]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsq-00000003Z1I-1zEj for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:01:04 +0000 Received: by mail-pg1-x52d.google.com with SMTP id 41be03b00d2f7-7cd9e634ea9so4246150a12.0 for ; Wed, 04 Sep 2024 02:01:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440459; x=1726045259; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=DwAJluv0Exq9EadYfBSyNeJ8D4Ka/sU/iYmJbm5J4eo=; b=HN9lcGD8K79UBtI0kNYMK9wbHIRVQ6rE7ECNkFVro2Tvdup3scINZBFXy/soSNa8xL Dy+sU05nafY43echRHmlmbhlexM4RVyTsLvdEHDN4P4f4KB7aIo3+J/1xeBv/WYKQn8P JrwHw4n7vjt+p+V8YdmYg+kuElouUDMnwvG1A= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440459; x=1726045259; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=DwAJluv0Exq9EadYfBSyNeJ8D4Ka/sU/iYmJbm5J4eo=; b=i58y0GZyH2eP86WPISfM+h8spqICXi7DYTUDuk/HPaAYseRok+r/av3S1C4j3n6/q+ BvRG+I2tUAWKIih7JuwDgqkDCcsh5qFT2ntwfpK7q9A13ocwA0PgFGBnP3KpmINRk/CD q/07fmUe5J5z9/jlEAMeEvoWGy1qKR86bEVuZbJRpSdc22koNfK1aKrejvSb5UTsJQtJ JoI2LF2HwAh/DC0yz7PCk7nk60COJPxvZl1bKFNmYx9JnuWfIxZSwh4NxVqGdllecMoo GLxm9taXj/8C8hjbyK2e/x/tDRotYJiDP1WA0URF6m1ceYMmhWjljil7B9xO9kL+fGBa XyQQ== X-Forwarded-Encrypted: i=1; AJvYcCU1pLNEkjkR2j3h4kIpqstt7XISBe1cwOzjUdiAdeai8PoZFWf7D4/NbhOej0ccH849Kyyvtq2/vjySdM5MFg==@lists.infradead.org X-Gm-Message-State: AOJu0YyW3bfgGYphdhPjOYZLno3r2hZv7USGfMxRf/awnQT7FTeHojNo iVqd0EuG9q8hZaL8+KgqVPwLc050SChuIWl9zfGMzcM4+aaVHRxoDuUBR2lW5A== X-Google-Smtp-Source: AGHT+IFFqCnmeBWZ9aXSqOpUywkoxinPfwTNU43tOQwWBlrfj1Rm3kLKZ4eIZFoE+WAsIUVUCM7mHQ== X-Received: by 2002:a05:6a21:1813:b0:1cd:f065:4ef7 with SMTP id adf61e73a8af0-1ced0469052mr12363435637.19.1725440459454; Wed, 04 Sep 2024 02:00:59 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.00.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:00:59 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 10/12] i2c: of-prober: Add GPIO support Date: Wed, 4 Sep 2024 17:00:12 +0800 Message-ID: <20240904090016.2841572-11-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020100_545676_545BCF93 X-CRM114-Status: GOOD ( 34.55 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org This adds GPIO management to the I2C OF component prober. Components that the prober intends to probe likely require their regulator supplies be enabled, and GPIOs be toggled to enable them or bring them out of reset before they will respond to probe attempts. regulator support was added in the previous patch. Without specific knowledge of each component's resource names or power sequencing requirements, the prober can only enable the regulator supplies all at once, and toggle the GPIOs all at once. Luckily, reset pins tend to be active low, while enable pins tend to be active high, so setting the raw status of all GPIO pins to high should work. The wait time before and after resources are enabled are collected from existing drivers and device trees. The prober collects resources from all possible components and enables them together, instead of enabling resources and probing each component one by one. The latter approach does not provide any boot time benefits over simply enabling each component and letting each driver probe sequentially. The prober will also deduplicate the resources, since on a component swap out or co-layout design, the resources are always the same. While duplicate regulator supplies won't cause much issue, shared GPIOs don't work reliably, especially with other drivers. For the same reason, the prober will release the GPIOs before the successfully probed component is actually enabled. Signed-off-by: Chen-Yu Tsai --- Changes since v5: - Renamed "con" to "propname" in i2c_of_probe_get_gpiod() - Copy string first and check return value of strscpy() for overflow in i2c_of_probe_get_gpiod() - Add parenthesis around "enable" and "reset" GPIO names in comments - Split resource count debug message into two separate lines - Split out GPIO helper from i2c_of_probe_enable_res() to keep code cleaner following the previous patch - Adopted options for customizing power sequencing delay following previous patch Changes since v4: - Split out from previous patch - Moved GPIO property name check to common function in gpiolib.c in new patch - Moved i2c_of_probe_free_gpios() into for_each_child_of_node_scoped() - Rewrote in gpiod_*_array-esque fashion --- drivers/i2c/i2c-core-of-prober.c | 143 ++++++++++++++++++++++++++++++- include/linux/i2c.h | 2 + 2 files changed, 144 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/i2c-core-of-prober.c b/drivers/i2c/i2c-core-of-prober.c index 56b06ad7aa64..04242ff86e69 100644 --- a/drivers/i2c/i2c-core-of-prober.c +++ b/drivers/i2c/i2c-core-of-prober.c @@ -5,16 +5,19 @@ * Copyright (C) 2024 Google LLC */ +#include #include #include #include #include #include +#include #include #include #include #include #include +#include /* * Some devices, such as Google Hana Chromebooks, are produced by multiple @@ -29,12 +32,14 @@ * address responds. * * TODO: - * - Support handling common GPIOs. + * - Support inverted polarity GPIOs, such as electrical high to "disable". + * Seen on some OmniVision camera sensors. * - Support I2C muxes */ struct i2c_of_probe_data { const struct i2c_of_probe_opts *opts; + struct gpio_descs *gpiods; struct regulator_bulk_data *regulators; unsigned int regulators_num; }; @@ -85,10 +90,90 @@ static void i2c_of_probe_free_regulators(struct i2c_of_probe_data *data) regulator_bulk_free(data->regulators_num, data->regulators); data->regulators_num = 0; data->regulators = NULL; +}; + +/* + * Returns 1 if property is GPIO and GPIO successfully requested, + * 0 if not a GPIO property, or error if request for GPIO failed. + */ +static int i2c_of_probe_get_gpiod(struct device_node *node, struct property *prop, + struct i2c_of_probe_data *data) +{ + struct fwnode_handle *fwnode = of_fwnode_handle(node); + struct gpio_descs *gpiods; + struct gpio_desc *gpiod; + char propname[32]; /* 32 is max size of property name */ + char *con_id = NULL; + size_t new_size; + int len, ret; + + len = gpio_get_property_name_length(prop->name); + if (len < 0) + return 0; + + ret = strscpy(propname, prop->name); + if (ret < 0) { + pr_err("%pOF: length of GPIO name \"%s\" exceeds current limit\n", + node, prop->name); + return -EINVAL; + } + + if (len > 0) { + /* "len < ARRAY_SIZE(propname)" guaranteed by strscpy() above */ + propname[len] = '\0'; + con_id = propname; + } + + /* + * GPIO descriptors are not reference counted. GPIOD_FLAGS_BIT_NONEXCLUSIVE + * can't differentiate between GPIOs shared between devices to be probed and + * other devices (which is incorrect). If the initial request fails with + * -EBUSY, retry with GPIOD_FLAGS_BIT_NONEXCLUSIVE and see if it matches + * any existing ones. + */ + gpiod = fwnode_gpiod_get_index(fwnode, con_id, 0, GPIOD_ASIS, "i2c-of-prober"); + if (IS_ERR(gpiod)) { + if (PTR_ERR(gpiod) != -EBUSY || !data->gpiods) + return PTR_ERR(gpiod); + + gpiod = fwnode_gpiod_get_index(fwnode, con_id, 0, + GPIOD_ASIS | GPIOD_FLAGS_BIT_NONEXCLUSIVE, + "i2c-of-prober"); + for (unsigned int i = 0; i < data->gpiods->ndescs; i++) + if (gpiod == data->gpiods->desc[i]) + return 1; + + return -EBUSY; + } + + new_size = struct_size(gpiods, desc, data->gpiods ? data->gpiods->ndescs + 1 : 1); + gpiods = krealloc(data->gpiods, new_size, GFP_KERNEL); + if (!gpiods) { + gpiod_put(gpiod); + return -ENOMEM; + } + + data->gpiods = gpiods; + data->gpiods->desc[data->gpiods->ndescs++] = gpiod; + + return 1; +} + +/* + * This is split into two functions because in the normal flow the GPIOs + * have to be released before the actual driver probes so that the latter + * can acquire them. + */ +static void i2c_of_probe_free_gpios(struct i2c_of_probe_data *data) +{ + if (data->gpiods) + gpiod_put_array(data->gpiods); + data->gpiods = NULL; } static void i2c_of_probe_free_res(struct i2c_of_probe_data *data) { + i2c_of_probe_free_gpios(data); i2c_of_probe_free_regulators(data); } @@ -104,6 +189,18 @@ static int i2c_of_probe_get_res(struct device *dev, struct device_node *node, goto err_cleanup; } + for_each_property_of_node(node, prop) { + dev_dbg(dev, "Trying property %pOF/%s\n", node, prop->name); + + /* GPIOs */ + ret = i2c_of_probe_get_gpiod(node, prop, data); + if (ret < 0) { + dev_err_probe(dev, ret, "Failed to get GPIO from %pOF/%s\n", + node, prop->name); + goto err_cleanup; + } + } + return 0; err_cleanup: @@ -131,6 +228,37 @@ static void i2c_of_probe_disable_regulators(struct i2c_of_probe_data *data) regulator_bulk_disable(data->regulators_num, data->regulators); } +static int i2c_of_probe_set_gpios(struct device *dev, struct i2c_of_probe_data *data) +{ + int ret; + int gpio_i; + + if (!data->gpiods) + return 0; + + for (gpio_i = 0; gpio_i < data->gpiods->ndescs; gpio_i++) { + /* + * "reset" GPIOs normally have opposite polarity compared to + * "enable" GPIOs. Instead of parsing the flags again, simply + * set the raw value to high. + */ + dev_dbg(dev, "Setting GPIO %d\n", gpio_i); + ret = gpiod_direction_output_raw(data->gpiods->desc[gpio_i], 1); + if (ret) + goto disable_gpios; + } + + msleep(data->opts->post_reset_deassert_delay_ms); + + return 0; + +disable_gpios: + for (gpio_i--; gpio_i >= 0; gpio_i--) + gpiod_set_raw_value_cansleep(data->gpiods->desc[gpio_i], 0); + + return ret; +} + static int i2c_of_probe_enable_res(struct device *dev, struct i2c_of_probe_data *data) { int ret; @@ -139,7 +267,15 @@ static int i2c_of_probe_enable_res(struct device *dev, struct i2c_of_probe_data if (ret) return ret; + ret = i2c_of_probe_set_gpios(dev, data); + if (ret) + goto err_disable_regulators; + return 0; + +err_disable_regulators: + i2c_of_probe_disable_regulators(data); + return ret; } static struct device_node *i2c_of_probe_get_i2c_node(struct device *dev, const char *type) @@ -191,6 +327,8 @@ static int i2c_of_probe_enable_node(struct device *dev, struct device_node *node static const struct i2c_of_probe_opts i2c_of_probe_opts_default = { /* largest post-power-on pre-reset-deassert delay seen among drivers */ .post_power_on_delay_ms = 500, + /* largest post-reset-deassert delay seen in tree for Elan I2C HID */ + .post_reset_deassert_delay_ms = 300, }; /** @@ -264,6 +402,8 @@ int i2c_of_probe_component(struct device *dev, const char *type, const struct i2 } dev_dbg(dev, "Resources: # of regulator supplies = %d\n", probe_data.regulators_num); + dev_dbg(dev, "Resources: # of GPIOs = %d\n", + probe_data.gpiods ? probe_data.gpiods->ndescs : 0); /* Enable resources */ ret = i2c_of_probe_enable_res(dev, &probe_data); @@ -283,6 +423,7 @@ int i2c_of_probe_component(struct device *dev, const char *type, const struct i2 continue; /* Found a device that is responding */ + i2c_of_probe_free_gpios(&probe_data); ret = i2c_of_probe_enable_node(dev, node); break; } diff --git a/include/linux/i2c.h b/include/linux/i2c.h index dbcdb8edbf6f..0da1edddb5a2 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -1037,9 +1037,11 @@ int of_i2c_get_board_info(struct device *dev, struct device_node *node, /** * i2c_of_probe_opts - I2C OF component prober customization options * @post_power_on_delay_us: Delay in ms after regulators are powered on. Passed to msleep(). + * @post_reset_deassert_delay_ms: Delay in ms after GPIOs are set. Passed to msleep(). */ struct i2c_of_probe_opts { unsigned int post_power_on_delay_ms; + unsigned int post_reset_deassert_delay_ms; }; int i2c_of_probe_component(struct device *dev, const char *type, const struct i2c_of_probe_opts *opts); From patchwork Wed Sep 4 09:00:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790250 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 03A37CD3431 for ; Wed, 4 Sep 2024 09:43:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=LH0ODR77CMPhaoeIe1+Kc3EgHt+dqRx4jM2dm2TUXS4=; b=vmJupZZnsdCprRSNC/NLd7jEZP s+DyCGr7FAitGhHmXsjZVbPJ1X4tJHBREHavWr/fvNkmLEwm7VxQaxYX6k4369gplU+OpK0o38DV3 /csKiGED2zYvlwWvst6DstrY0R2Xc+iiiw1Mjc1VXpaB+VtmanOpMPWiG5CueDQIMoHkasdVRlJ2a fA/S04GT2THiN4YaPstl3aX5dsOvtpB1L4ympVjl+1KKw5gy3O1+JIejv2YR/RjpGz3MBRceeqiJF E5MSizRqW7u86zt70/4uVuZC5iJSlih99PYkFtq+smngIL3StmNEE3EhMWEsQOtmbbBMRlnRiRtGL TwGN2H3A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmYM-00000003k9i-30FF; Wed, 04 Sep 2024 09:43:54 +0000 Received: from mail-pg1-x536.google.com ([2607:f8b0:4864:20::536]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsu-00000003Z2G-1btB for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:01:06 +0000 Received: by mail-pg1-x536.google.com with SMTP id 41be03b00d2f7-7cf5e179b68so355286a12.1 for ; Wed, 04 Sep 2024 02:01:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440463; x=1726045263; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=LH0ODR77CMPhaoeIe1+Kc3EgHt+dqRx4jM2dm2TUXS4=; b=bz/A6WkriyYua1WFzpvQEsdxZuerIHugjGtKVxynNCBkgFno60zfurMUJ5IEQWEkak KbIc40rUJ6x5EjbdUREtNr39A2eOJfjVbKybxW0JRUNkGL4BXOLDEMAse1ddn6WH/OHS zgPdisjWIXxaGZA4mWmEXrfoMnigbkXrkjsgI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440463; x=1726045263; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=LH0ODR77CMPhaoeIe1+Kc3EgHt+dqRx4jM2dm2TUXS4=; b=F8sPCqr//wQk4FyV7t9Qia5FSSi3BVs5aO9mOjO2TyeuuyCziSWav5bmABGYrphY7a rbgQtqGPNw24qnxKjSFpPTXcKTOMRIaoWj1cS8MmxPKQm8KjJg7LLSQ4G/QHNzeaybY+ XFE3YWa2WJGg/TGddIOJnzeT/XKlDvTIpM6HxPoiY+7+KqXM0oh9HDwMmRvmH4A0us3A cV5Liqj5QiiC7/VmpL9ywqsQDYvtq50OX9vQYr7WgD3ZdzlWjT3HSlBcDdSTdzG9FfYt 0iXQQiuctNzbGVN6A65p2on0mo/puw4OITNSy/dkPf3tzc7D+DWkuCNnDiIUs3njVJzt 1/+w== X-Forwarded-Encrypted: i=1; AJvYcCWvu5ssMfAG+BbKM4JwTPqkWc3AVGPUOthowrYkUVndGmmilcf+UOrk+Cenqadjc4dmd9xpj/+XuXkkeSPJ1w==@lists.infradead.org X-Gm-Message-State: AOJu0Yz7S2Lh2KaCXWZiEX/B58FklLjJCb0xeY3z31AajxeWQLCVH2QJ SWwVBclxGkLAJALe8usgrg876/VHt9LKwJGfcPfol3BKy4KO71HCeAPF9GY4Wg== X-Google-Smtp-Source: AGHT+IGOU8buTd7JELJzOfZ6Jk+nZTRBNBcLcVAojTU5x9IVaH5+dcYqoe907unghNVIfUBxa7r5Mg== X-Received: by 2002:a05:6a21:3408:b0:1ce:f6dc:2ba8 with SMTP id adf61e73a8af0-1cf081e2f3emr2560968637.24.1725440463059; Wed, 04 Sep 2024 02:01:03 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.00.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:01:02 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 11/12] platform/chrome: Introduce device tree hardware prober Date: Wed, 4 Sep 2024 17:00:13 +0800 Message-ID: <20240904090016.2841572-12-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020104_512429_677F1EC3 X-CRM114-Status: GOOD ( 39.22 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Some devices are designed and manufactured with some components having multiple drop-in replacement options. These components are often connected to the mainboard via ribbon cables, having the same signals and pin assignments across all options. These may include the display panel and touchscreen on laptops and tablets, and the trackpad on laptops. Sometimes which component option is used in a particular device can be detected by some firmware provided identifier, other times that information is not available, and the kernel has to try to probe each device. This change attempts to make the "probe each device" case cleaner. The current approach is to have all options added and enabled in the device tree. The kernel would then bind each device and run each driver's probe function. This works, but has been broken before due to the introduction of asynchronous probing, causing multiple instances requesting "shared" resources, such as pinmuxes, GPIO pins, interrupt lines, at the same time, with only one instance succeeding. Work arounds for these include moving the pinmux to the parent I2C controller, using GPIO hogs or pinmux settings to keep the GPIO pins in some fixed configuration, and requesting the interrupt line very late. Such configurations can be seen on the MT8183 Krane Chromebook tablets, and the Qualcomm sc8280xp-based Lenovo Thinkpad 13S. Instead of this delicate dance between drivers and device tree quirks, this change introduces a simple I2C component prober. For any given class of devices on the same I2C bus, it will go through all of them, doing a simple I2C read transfer and see which one of them responds. It will then enable the device that responds. This requires some minor modifications in the existing device tree. The status for all the device nodes for the component options must be set to "failed-needs-probe". This makes it clear that some mechanism is needed to enable one of them, and also prevents the prober and device drivers running at the same time. Signed-off-by: Chen-Yu Tsai Acked-by: Tzung-Bi Shih --- Changes since v5: - Adapt to new i2c_of_probe_component() parameters Changes since v4: - Fix Kconfig dependency - Update copyright year - Drop "linux/of.h" header - Include "linux/errno.h" - Move |int ret| declaration to top of block - Return -ENODEV on no match instead of 0 - Unregister platform driver and device unconditionally after previous change Changes since v3: - Include linux/init.h - Rewrite for loop in driver probe function as suggested by Andy - Make prober driver buildable as module - Ignore prober errors other than probe deferral Changes since v2: - Addressed Rob's comments - Move remaining driver code to drivers/platform/chrome/ - Depend on rather than select CONFIG_I2C - Copy machine check to driver init function - Addressed Andy's comments - Explicitly mention "device tree" or OF in driver name, description and Kconfig symbol - Drop filename from inside the file - Switch to passing "struct device *" to shorten lines - Move "ret = 0" to just before for_each_child_of_node(i2c_node, node) - Make loop variable size_t (instead of unsigned int as Andy asked) - Use PLATFORM_DEVID_NONE instead of raw -1 - Use standard goto error path pattern in hw_prober_driver_init() - Changes since v1: - New patch --- drivers/platform/chrome/Kconfig | 11 ++ drivers/platform/chrome/Makefile | 1 + .../platform/chrome/chromeos_of_hw_prober.c | 104 ++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 drivers/platform/chrome/chromeos_of_hw_prober.c diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig index 7dbeb786352a..b7dbaf77b6db 100644 --- a/drivers/platform/chrome/Kconfig +++ b/drivers/platform/chrome/Kconfig @@ -61,6 +61,17 @@ config CHROMEOS_TBMC To compile this driver as a module, choose M here: the module will be called chromeos_tbmc. +config CHROMEOS_OF_HW_PROBER + tristate "ChromeOS Device Tree Hardware Prober" + depends on OF + depends on I2C + select OF_DYNAMIC + default OF + help + This option enables the device tree hardware prober for ChromeOS + devices. The driver will probe the correct component variant in + devices that have multiple drop-in options for one component. + config CROS_EC tristate "ChromeOS Embedded Controller" select CROS_EC_PROTO diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile index 2dcc6ccc2302..21a9d5047053 100644 --- a/drivers/platform/chrome/Makefile +++ b/drivers/platform/chrome/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_CHROMEOS_ACPI) += chromeos_acpi.o obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o obj-$(CONFIG_CHROMEOS_PRIVACY_SCREEN) += chromeos_privacy_screen.o obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o +obj-$(CONFIG_CHROMEOS_OF_HW_PROBER) += chromeos_of_hw_prober.o obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o obj-$(CONFIG_CROS_EC) += cros_ec.o obj-$(CONFIG_CROS_EC_I2C) += cros_ec_i2c.o diff --git a/drivers/platform/chrome/chromeos_of_hw_prober.c b/drivers/platform/chrome/chromeos_of_hw_prober.c new file mode 100644 index 000000000000..90fc1de16788 --- /dev/null +++ b/drivers/platform/chrome/chromeos_of_hw_prober.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * ChromeOS Device Tree Hardware Prober + * + * Copyright (c) 2024 Google LLC + */ + +#include +#include +#include +#include +#include + +#define DRV_NAME "chromeos_of_hw_prober" + +/** + * struct hw_prober_entry - Holds an entry for the hardware prober + * + * @compatible: compatible string to match against the machine + * @prober: prober function to call when machine matches + * @data: extra data for the prober function + */ +struct hw_prober_entry { + const char *compatible; + int (*prober)(struct device *dev, const void *data); + const void *data; +}; + +static int chromeos_i2c_component_prober(struct device *dev, const void *data) +{ + const char *type = data; + + return i2c_of_probe_component(dev, type, NULL); +} + +static const struct hw_prober_entry hw_prober_platforms[] = { + { .compatible = "google,hana", .prober = chromeos_i2c_component_prober, .data = "touchscreen" }, + { .compatible = "google,hana", .prober = chromeos_i2c_component_prober, .data = "trackpad" }, +}; + +static int chromeos_of_hw_prober_probe(struct platform_device *pdev) +{ + for (size_t i = 0; i < ARRAY_SIZE(hw_prober_platforms); i++) { + int ret; + + if (!of_machine_is_compatible(hw_prober_platforms[i].compatible)) + continue; + + ret = hw_prober_platforms[i].prober(&pdev->dev, hw_prober_platforms[i].data); + /* Ignore unrecoverable errors and keep going through other probers */ + if (ret == -EPROBE_DEFER) + return ret; + } + + return 0; +} + +static struct platform_driver chromeos_of_hw_prober_driver = { + .probe = chromeos_of_hw_prober_probe, + .driver = { + .name = DRV_NAME, + }, +}; + +static struct platform_device *chromeos_of_hw_prober_pdev; + +static int chromeos_of_hw_prober_driver_init(void) +{ + size_t i; + int ret; + + for (i = 0; i < ARRAY_SIZE(hw_prober_platforms); i++) + if (of_machine_is_compatible(hw_prober_platforms[i].compatible)) + break; + if (i == ARRAY_SIZE(hw_prober_platforms)) + return -ENODEV; + + ret = platform_driver_register(&chromeos_of_hw_prober_driver); + if (ret) + return ret; + + chromeos_of_hw_prober_pdev = + platform_device_register_simple(DRV_NAME, PLATFORM_DEVID_NONE, NULL, 0); + if (IS_ERR(chromeos_of_hw_prober_pdev)) + goto err; + + return 0; + +err: + platform_driver_unregister(&chromeos_of_hw_prober_driver); + + return PTR_ERR(chromeos_of_hw_prober_pdev); +} +module_init(chromeos_of_hw_prober_driver_init); + +static void chromeos_of_hw_prober_driver_exit(void) +{ + platform_device_unregister(chromeos_of_hw_prober_pdev); + platform_driver_unregister(&chromeos_of_hw_prober_driver); +} +module_exit(chromeos_of_hw_prober_driver_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ChromeOS device tree hardware prober"); From patchwork Wed Sep 4 09:00:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chen-Yu Tsai X-Patchwork-Id: 13790251 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3D805CA0ED3 for ; Wed, 4 Sep 2024 09:44:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Transfer-Encoding: MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From: Reply-To:Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Owner; bh=uBItDi4n14IYuM9iuwfGhl3IjynLmMqAt1J2tlAZIYM=; b=aglcChOTX8NG1y0e6JW7eBTXOi Hw/12FUxaaDmkVyrc1cqevfwetFTqQVkbLnMYHqbWV2DOkTypzhuRypnUApDv6i4RHTr7lzFy3yCV dY0I1W3gO/Pl3f3X8s6MXJhusrqa0kQOM9gz67cFxYeqN3K21+g5K0lWUzqWZdfRv7gUFLcLomEnY RkSqq4+sq3Nk2JaFBs35P7r0MGOKX+Bwirs66yZJjOw1YrB45lzTnlUDkLIvznG9qVw5CWyGY3Cu+ Mgb08ZFacw2tAccAuB64E9sAPluc8nyCtKCi3bt1l1qG8g+ZCitwNco2BFVdcVzKE260WL025P0Tk +frVxg7A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.97.1 #2 (Red Hat Linux)) id 1slmZG-00000003kOj-3oBU; Wed, 04 Sep 2024 09:44:50 +0000 Received: from mail-pf1-x430.google.com ([2607:f8b0:4864:20::430]) by bombadil.infradead.org with esmtps (Exim 4.97.1 #2 (Red Hat Linux)) id 1sllsx-00000003Z55-1nqq for linux-mediatek@lists.infradead.org; Wed, 04 Sep 2024 09:01:08 +0000 Received: by mail-pf1-x430.google.com with SMTP id d2e1a72fcca58-714114be925so5110962b3a.2 for ; Wed, 04 Sep 2024 02:01:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1725440467; x=1726045267; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=uBItDi4n14IYuM9iuwfGhl3IjynLmMqAt1J2tlAZIYM=; b=dSTrO0eLBcazH6p2JU+/Hhvgy8pf+2zPZ3+WfXpCDMyaEZ/yUqJHBh6bCobWM3/D99 QdFFvol0+Ru+MkkXSnf6Vcqyp5lJVcpInaVOCzDn1oWtS2RI5zdCmIxgtiaj7hvhBtzL RNYc0fU+o56yAcfuEvYnA0VdiFKxt6UTiK1PY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725440467; x=1726045267; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uBItDi4n14IYuM9iuwfGhl3IjynLmMqAt1J2tlAZIYM=; b=ozWt1OTz69xgOi8wnk+tR2rH2CN50tPid6JJ3BQU8/10QdUnqt/eDwto+lfaqL4X21 rrIs/kwYlHCfqyuwMr+7zaxfYS4xlZrYvQFwc8VjNZ/yV2VkMULaxOoBqHKAhws1DFEn qZFgSaeXkKQx2YvCyihFQojFXNOZf8cgi2HXF/0LorhU7CKNw3t4z3OSByA3Czc9Kt0e CYosiRBqjRrq1lzs4q17TLQaoSeDUEB7mU2LN2Lm3X151w8wLrBWYuCq93ek00CBygMW xq1XiI9/mlfyGGmqog1LDNBqaWZgAgcr143COaSy8sk3dqlxgl7BBT9HDKHjcHJYF9jt +lcg== X-Forwarded-Encrypted: i=1; AJvYcCUdzocNI9PJlH2GXVYLkXb5A6XS09lLEAEoPYKj6NtLcU/uPzTSOgUH3kuJz9uUNCXarEvFPpRKK5lS1ip0Nw==@lists.infradead.org X-Gm-Message-State: AOJu0YxvXD6hJ/YvyVbQXVIM+ohbXv1JP1x/W5Nn6MwOL6p03pBiWLHJ Z+8eN4OW3yTbQgHgl5U/SOeCojss8bj4ikvQWPfmYOcaOMe6aYuZQlZprd5ydQ== X-Google-Smtp-Source: AGHT+IH2qucxlwAjWUMwLjsKdIgEfhg67bYq6GG+aNowoHtwaNabhMzLvVoNZUyf17AzUzRmQ7DIlg== X-Received: by 2002:a05:6a00:9282:b0:704:2563:5079 with SMTP id d2e1a72fcca58-7173d0069b0mr16668781b3a.27.1725440466605; Wed, 04 Sep 2024 02:01:06 -0700 (PDT) Received: from wenstp920.tpe.corp.google.com ([2401:fa00:1:10:83fc:5c8e:13bd:d165]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-717785b5183sm1153279b3a.197.2024.09.04.02.01.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 04 Sep 2024 02:01:06 -0700 (PDT) From: Chen-Yu Tsai To: Rob Herring , Saravana Kannan , Matthias Brugger , AngeloGioacchino Del Regno , Wolfram Sang , Benson Leung , Tzung-Bi Shih , Mark Brown , Liam Girdwood Cc: Chen-Yu Tsai , chrome-platform@lists.linux.dev, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org, Douglas Anderson , Johan Hovold , Jiri Kosina , Andy Shevchenko , linux-i2c@vger.kernel.org Subject: [PATCH v6 12/12] arm64: dts: mediatek: mt8173-elm-hana: Mark touchscreens and trackpads as fail Date: Wed, 4 Sep 2024 17:00:14 +0800 Message-ID: <20240904090016.2841572-13-wenst@chromium.org> X-Mailer: git-send-email 2.46.0.469.g59c65b2a67-goog In-Reply-To: <20240904090016.2841572-1-wenst@chromium.org> References: <20240904090016.2841572-1-wenst@chromium.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20240904_020107_550265_BA04CDD8 X-CRM114-Status: GOOD ( 14.29 ) X-BeenThere: linux-mediatek@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "Linux-mediatek" Errors-To: linux-mediatek-bounces+linux-mediatek=archiver.kernel.org@lists.infradead.org Instead of having them all available, mark them all as "fail-needs-probe" and have the implementation try to probe which one is present. Also remove the shared resource workaround by moving the pinctrl entry for the trackpad interrupt line back into the individual trackpad nodes. Signed-off-by: Chen-Yu Tsai --- Changes since v4: - Rebased Changes since v3: - Also remove second source workaround, i.e. move the interrupt line pinctrl entry from the i2c node back to the components. Changes since v2: - Drop class from status --- arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi | 13 +++++++++++++ arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi index 8d1cbc92bce3..251e084bf7de 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi @@ -14,6 +14,7 @@ touchscreen2: touchscreen@34 { compatible = "melfas,mip4_ts"; reg = <0x34>; interrupts-extended = <&pio 88 IRQ_TYPE_LEVEL_LOW>; + status = "fail-needs-probe"; }; /* @@ -26,6 +27,7 @@ touchscreen3: touchscreen@20 { reg = <0x20>; hid-descr-addr = <0x0020>; interrupts-extended = <&pio 88 IRQ_TYPE_LEVEL_LOW>; + status = "fail-needs-probe"; }; /* Lenovo Ideapad C330 uses G2Touch touchscreen as a 2nd source touchscreen */ @@ -47,9 +49,12 @@ &i2c4 { trackpad2: trackpad@2c { compatible = "hid-over-i2c"; interrupts-extended = <&pio 117 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&trackpad_irq>; reg = <0x2c>; hid-descr-addr = <0x0020>; wakeup-source; + status = "fail-needs-probe"; }; }; @@ -74,3 +79,11 @@ pins_wp { }; }; }; + +&touchscreen { + status = "fail-needs-probe"; +}; + +&trackpad { + status = "fail-needs-probe"; +}; diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi index b4d85147b77b..eee64461421f 100644 --- a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi @@ -358,12 +358,12 @@ touchscreen: touchscreen@10 { &i2c4 { clock-frequency = <400000>; status = "okay"; - pinctrl-names = "default"; - pinctrl-0 = <&trackpad_irq>; trackpad: trackpad@15 { compatible = "elan,ekth3000"; interrupts-extended = <&pio 117 IRQ_TYPE_LEVEL_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&trackpad_irq>; reg = <0x15>; vcc-supply = <&mt6397_vgp6_reg>; wakeup-source;