From nobody Mon Feb 9 11:09:15 2026 Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 47DA419EEC2 for ; Wed, 8 Jan 2025 01:28:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736299734; cv=none; b=kqT9kavpBP+vdNZgCCraYh5kN/bJjigisU4z8SSttHLojV1jIgPTjJXz7j09X9t51+m5Ph7nsnceIpifHy5BWXipvO2H2Jsnf8YPNvjmJ9Y/AiNbLmOZfTD0l0sTga3LMXl0NMCgX2awUxBAIDkX+t/a3vLHN4G4KCWRjynjlD4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1736299734; c=relaxed/simple; bh=t7arDmLNv1I8472tLkuO20WVqQ6j2EmCM9HKMORooEM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=sq7fNzsgR4ge8xBVzBSmdVK/GnIobv2sy8CA2zIgDVI/GhWEloPsLUbLmiyMn7HndcVCafOaiKWNkElPIlZDzoGRf8bvoLTYbfpz4FaD//Mtd1l2za+ZFkiOSiUHXa7w1LqgzLEKdEjVE847Yk8QkTemE6PUmpKDa8mKMRoQJk4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org; spf=pass smtp.mailfrom=chromium.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b=Q/6l7dEb; arc=none smtp.client-ip=209.85.214.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chromium.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chromium.org header.i=@chromium.org header.b="Q/6l7dEb" Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-2162c0f6a39so6711215ad.0 for ; Tue, 07 Jan 2025 17:28:51 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1736299731; x=1736904531; darn=vger.kernel.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=NtmiACSjJT3F9PAWPO6E+GzjG0s112mCP5ZFxh4lNAM=; b=Q/6l7dEbCoDEtJf+P6hdEcO29HBCnEmWr1MQefTl7/dD4DfPBci2jWJapqXIju5hhC ktkMFgvoFenJpgZ8VbWwKXaIR8dTLurgTUICOZKcvpDnZBw7+TSuUFS2ZjOsP3F31Y/m NAIeTGnDKjBS0zcJw1QyUw83Jn0Ti61uNjOF4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1736299731; x=1736904531; 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=NtmiACSjJT3F9PAWPO6E+GzjG0s112mCP5ZFxh4lNAM=; b=vzGK0ExD/vXu2vfnguDr/ShLQsTv5hmWg8ptSwGE0cnlstmEJllosqoW9wvZ6eRvXX 1yaPKSX3X+0zs0V/7t8CTDnM35lwjl1GIxHtD54NeRCM08qrXiZJToPFD6Qt8dNyAA/b A7bcQE0Qv30gw1ss10GfUjQLvkRv2vaj/H3yTQwUoedyaoaZo5NaSwSZXgZf7Fq7xSsR kE3t5NdhFHI4isrB7JmxtnhGM8xnmRY2FSegcDxYGoO4zgdC3n1HZIm7w1s+R5wL3wa7 +wxfIQQ8JRXqbZUQMh1her5Zh3tZzFc9B8pQ+08Irt11B+mo0JInOWmuEtzTyFHPYNaZ Bu1Q== X-Gm-Message-State: AOJu0Yy8999p892SFKh8UNc29TmTvHHBx5tGwbTG6E9zPvit000F1GbA GQbARFNYOVmcwOnkIGTZyf/PdqyozI/2bIkpi4ILJZFtJ77Dkkv/aoCbQaZ8Lg== X-Gm-Gg: ASbGncvDqA0JAhoBa7MWw37QFjxTk6XmYTz57Er4dw49MBGKhDptzC3yITPDCTitzfM ZVzVXONTVpV66u4+pKzsO4VWnyIsfuKXSLvO6uKsf3KckgYtiBkwFU9Jx1BR7U1/Bu0KrvNNq5z bltGDLAsW1trXh3D4saDdQxAnjpn9WTsSJBf0xMsL/K7h/KFVzHBEktAXvBMgXrbFRuTeR7gLMn Qct9cyQO3W3gqVUUAd3Zf4XkEbV7VNSs96gPlO+PgIoDk5sXCfUVGiY7LgJ30wNgjlxTFFt6UN1 sGqJAsdv86Fm6APr285v X-Google-Smtp-Source: AGHT+IECb87WVTKnPoq5klH18qVel9WHdGx/7ugyROn+iCaeZnJB4oA6NAnKgGI+EaTULuxAe5Qexw== X-Received: by 2002:a05:6a20:3943:b0:1e5:f8c6:203 with SMTP id adf61e73a8af0-1e745cb45damr6802792637.14.1736299730635; Tue, 07 Jan 2025 17:28:50 -0800 (PST) Received: from localhost (129.135.125.34.bc.googleusercontent.com. [34.125.135.129]) by smtp.gmail.com with UTF8SMTPSA id d2e1a72fcca58-72aad90b90asm34097987b3a.177.2025.01.07.17.28.49 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 07 Jan 2025 17:28:50 -0800 (PST) From: Stephen Boyd To: Bjorn Andersson , Konrad Dybcio Cc: linux-kernel@vger.kernel.org, patches@lists.linux.dev, devicetree@vger.kernel.org, Dmitry Baryshkov , Krzysztof Kozlowski , Rob Herring , linux-arm-msm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Arnd Bergmann , Conor Dooley , Saravana Kannan , =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Subject: [RFC PATCH 1/6] bus: Extract simple-bus into self-contained driver Date: Tue, 7 Jan 2025 17:28:38 -0800 Message-ID: <20250108012846.3275443-2-swboyd@chromium.org> X-Mailer: git-send-email 2.47.1.613.gc27f4b7a9f-goog In-Reply-To: <20250108012846.3275443-1-swboyd@chromium.org> References: <20250108012846.3275443-1-swboyd@chromium.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Extract the simple bus into a self contained driver so that devices are still populated when a node has two (or more) compatibles with the least specific one being the generic "simple-bus". Allow the driver to be a module so that in a fully modular build a driver module for the more specific compatible will be loaded first before trying to match this driver. Cc: Rob Herring Cc: Saravana Kannan Cc: Cc: Arnd Bergmann Cc: "Uwe Kleine-K=C3=B6nig" Cc: Bjorn Andersson Cc: Konrad Dybcio Cc: Signed-off-by: Stephen Boyd --- drivers/bus/Kconfig | 23 +++++++++++ drivers/bus/Makefile | 3 ++ drivers/bus/simple-bus.c | 79 +++++++++++++++++++++++++++++++++++++ drivers/bus/simple-pm-bus.c | 2 + drivers/of/platform.c | 50 +++++++++++++++++++++++ 5 files changed, 157 insertions(+) create mode 100644 drivers/bus/simple-bus.c diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index ff669a8ccad9..7c2aa1350578 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -261,6 +261,29 @@ config DA8XX_MSTPRI configuration. Allows to adjust the priorities of all master peripherals. =20 +config ALLOW_SIMPLE_BUS_OVERRIDE + bool "Allow simple-bus compatible OF nodes to match other drivers" + depends on OF + help + Allow nodes with the "simple-bus" compatible to use a more specific + driver which populates child devices itself. + +config OF_SIMPLE_BUS + tristate "OF Simple Bus Driver" + depends on ALLOW_SIMPLE_BUS_OVERRIDE || COMPILE_TEST + default ALLOW_SIMPLE_BUS_OVERRIDE + help + Driver for the "simple-bus" compatible nodes in DeviceTree. Child + nodes are usually automatically populated on the platform bus when a + node is compatible with "simple-bus". This driver maintains that + feature but it fails probe to allow other drivers to try to probe + with a more specific compatible if possible. + + Those other drivers depend on this kconfig symbol so that they match + the builtin or modular status of this driver. Don't disable this + symbol if ALLOW_SIMPLE_BUS_OVERRIDE is set and there isn't another + driver for the simple-bus compatible. + source "drivers/bus/fsl-mc/Kconfig" source "drivers/bus/mhi/Kconfig" =20 diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index cddd4984d6af..f3968221d704 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -40,5 +40,8 @@ obj-$(CONFIG_VEXPRESS_CONFIG) +=3D vexpress-config.o =20 obj-$(CONFIG_DA8XX_MSTPRI) +=3D da8xx-mstpri.o =20 +# Must be last for driver registration ordering +obj-$(CONFIG_OF_SIMPLE_BUS) +=3D simple-bus.o + # MHI obj-y +=3D mhi/ diff --git a/drivers/bus/simple-bus.c b/drivers/bus/simple-bus.c new file mode 100644 index 000000000000..3e39b9818566 --- /dev/null +++ b/drivers/bus/simple-bus.c @@ -0,0 +1,79 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Simple Bus Driver + */ + +#include +#include +#include +#include +#include +#include + +static struct platform_driver simple_bus_driver; + +static int has_specific_simple_bus_drv(struct device_driver *drv, void *de= v) +{ + /* Skip if it's this simple bus driver */ + if (drv =3D=3D &simple_bus_driver.driver) + return 0; + + if (of_driver_match_device(dev, drv)) { + dev_dbg(dev, "Allowing '%s' to probe more specifically\n", drv->name); + return 1; + } + + return 0; +} + +static int simple_bus_probe(struct platform_device *pdev) +{ + struct device *dev =3D &pdev->dev; + const struct of_dev_auxdata *lookup =3D dev_get_platdata(dev); + struct device_node *np =3D dev->of_node; + + /* + * If any other driver wants the device, leave the device to the other + * driver. Only check drivers that come after this driver so that if an + * earlier driver failed to probe we don't populate any devices, and + * only check if there's a more specific compatible. + */ + if (of_property_match_string(np, "compatible", "simple-bus") !=3D 0 && + bus_for_each_drv(&platform_bus_type, &simple_bus_driver.driver, dev, + has_specific_simple_bus_drv)) + return -ENODEV; + + if (np) + of_platform_populate(np, NULL, lookup, dev); + + return 0; +} + +static const struct of_device_id simple_bus_of_match[] =3D { + { .compatible =3D "simple-bus", }, + { } +}; +MODULE_DEVICE_TABLE(of, simple_bus_of_match); + +static struct platform_driver simple_bus_driver =3D { + .probe =3D simple_bus_probe, + .driver =3D { + .name =3D "simple-bus", + .of_match_table =3D simple_bus_of_match, + }, +}; + +static int __init simple_bus_driver_init(void) +{ + return platform_driver_register(&simple_bus_driver); +} +arch_initcall(simple_bus_driver_init); + +static void __exit simple_bus_driver_exit(void) +{ + platform_driver_unregister(&simple_bus_driver); +} +module_exit(simple_bus_driver_exit); + +MODULE_DESCRIPTION("Simple Bus Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/bus/simple-pm-bus.c b/drivers/bus/simple-pm-bus.c index 5dea31769f9a..be9879aa80c1 100644 --- a/drivers/bus/simple-pm-bus.c +++ b/drivers/bus/simple-pm-bus.c @@ -118,7 +118,9 @@ static const struct dev_pm_ops simple_pm_bus_pm_ops =3D= { =20 static const struct of_device_id simple_pm_bus_of_match[] =3D { { .compatible =3D "simple-pm-bus", }, +#ifndef CONFIG_ALLOW_SIMPLE_BUS_OVERRIDE { .compatible =3D "simple-bus", .data =3D ONLY_BUS }, +#endif { .compatible =3D "simple-mfd", .data =3D ONLY_BUS }, { .compatible =3D "isa", .data =3D ONLY_BUS }, { .compatible =3D "arm,amba-bus", .data =3D ONLY_BUS }, diff --git a/drivers/of/platform.c b/drivers/of/platform.c index c6d8afb284e8..63a80c30d515 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -311,6 +311,54 @@ static const struct of_dev_auxdata *of_dev_lookup(cons= t struct of_dev_auxdata *l return NULL; } =20 +/** + * of_platform_should_populate_children() - Should child nodes be populate= d for a bus + * @bus: device node of the bus to populate children for + * @matches: match table for bus nodes + * + * This function is used to determine if child nodes should be populated as + * devices for a bus. That is usually the case, unless + * CONFIG_ALLOW_SIMPLE_BUS_OVERRIDE=3Dy, in which case the simple-bus driv= er + * (CONFIG_OF_SIMPLE_BUS) will populate them. + * + * Return: True if child nodes should be populated as devices, false other= wise. + */ +static bool of_platform_should_populate_children(const struct of_device_id= *matches, + struct device_node *bus) +{ + /* Not configured to allow simple-bus to be overridden. Skip. */ + if (!IS_ENABLED(CONFIG_ALLOW_SIMPLE_BUS_OVERRIDE)) + return true; + + /* The simple-bus driver will handle it. */ + if (IS_ENABLED(CONFIG_OF_SIMPLE_BUS)) + return false; + + if (!matches) + return true; + + /* + * Always populate if the matches aren't populating a "simple-bus" + * compatible node. + */ + for (; matches->name[0] || matches->type[0] || matches->compatible[0]; ma= tches++) { + if (!strncmp(matches->compatible, "simple-bus", + ARRAY_SIZE(matches->compatible))) { + /* + * Always populate if "simple-bus" is the first + * compatible, so that CONFIG_OF_SIMPLE_BUS can be + * disabled while CONFIG_ALLOW_SIMPLE_BUS_OVERRIDE can + * be enabled. + */ + if (of_property_match_string(bus, "compatible", "simple-bus") !=3D 0) + return false; + break; + } + } + + return true; +} + /** * of_platform_bus_create() - Create a device for a node and its children. * @bus: device node of the bus to instantiate @@ -370,6 +418,8 @@ static int of_platform_bus_create(struct device_node *b= us, dev =3D of_platform_device_create_pdata(bus, bus_id, platform_data, paren= t); if (!dev || !of_match_node(matches, bus)) return 0; + if (!of_platform_should_populate_children(matches, bus)) + return 0; =20 for_each_child_of_node_scoped(bus, child) { pr_debug(" create child: %pOF\n", child); --=20 https://chromeos.dev