Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758588AbcJYILb (ORCPT ); Tue, 25 Oct 2016 04:11:31 -0400 Received: from mail-de.keymile.com ([195.8.104.250]:42664 "EHLO mail-de.keymile.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750765AbcJYIL1 (ORCPT ); Tue, 25 Oct 2016 04:11:27 -0400 From: Valentin Longchamp To: lee.jones@linaro.org, linux-kernel@vger.kernel.org Cc: Valentin Longchamp Subject: [PATCH v2] mfd: do not assign already already assigned compatible of_nodes Date: Tue, 25 Oct 2016 10:11:13 +0200 Message-Id: <1477383073-26135-1-git-send-email-valentin.longchamp@keymile.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <20161024100805.GH14477@dell> References: <20161024100805.GH14477@dell> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1957 Lines: 67 If 2 similar cells have the same of_compatible (2 instances of the same functionality), they both are assigned the first found of_node with this compatible. In the below example, the pdev of both cells get the child@0 of_node. parent@0 { /* MFD devices with 2 cells reg = <0>; child@0 { reg = <0>; compatible = "child-driver"; }; child@1 { reg = <1>; compatible = "child-driver"; }; }; To avoid this, the found of_nodes are checked to see if they are already assigned in the children of the parent dev and are only assigned if still "available" (not assigned to a child). This allows the 2nd cell's pdev to get the child@1 of_node. Signed-off-by: Valentin Longchamp --- drivers/mfd/mfd-core.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 3ac486a..a684ce5 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -137,6 +137,19 @@ static inline void mfd_acpi_add_device(const struct mfd_cell *cell, } #endif +static inline int mfd_check_node_callback(struct device *dev, void *data) +{ + struct device_node *np = data; + + return dev->of_node == np; +} + +static inline int mfd_is_node_allocated_to_dev(struct device *dev, + struct device_node *node) +{ + return device_for_each_child(dev, node, mfd_check_node_callback); +} + static int mfd_add_device(struct device *parent, int id, const struct mfd_cell *cell, atomic_t *usage_count, struct resource *mem_base, @@ -178,8 +191,10 @@ static int mfd_add_device(struct device *parent, int id, if (parent->of_node && cell->of_compatible) { for_each_child_of_node(parent->of_node, np) { if (of_device_is_compatible(np, cell->of_compatible)) { - pdev->dev.of_node = np; - break; + if (!mfd_is_node_allocated_to_dev(parent, np)) { + pdev->dev.of_node = np; + break; + } } } } -- 1.8.3.1