From patchwork Thu Feb 13 09:57:09 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean-Jacques Hiblot X-Patchwork-Id: 3644591 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 7C1609F390 for ; Thu, 13 Feb 2014 10:06:24 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6EB5A20158 for ; Thu, 13 Feb 2014 10:06:23 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 32B7120154 for ; Thu, 13 Feb 2014 10:06:22 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WDtAy-0001zv-ME; Thu, 13 Feb 2014 10:05:48 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WDt66-0000SK-7H; Thu, 13 Feb 2014 10:00:46 +0000 Received: from mail-wi0-f182.google.com ([209.85.212.182]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WDt62-0000RV-Oi for linux-arm-kernel@lists.infradead.org; Thu, 13 Feb 2014 10:00:43 +0000 Received: by mail-wi0-f182.google.com with SMTP id f8so8275619wiw.3 for ; Thu, 13 Feb 2014 02:00:19 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=from:to:cc:subject:date:message-id; bh=HwG4i1XJKcy4BWqp640afKJJqDsYtYTG7Fz01/Uw6eQ=; b=XE1kX4/MR0ey8dJ5m4CRpEWkKOApzh5ewJwjFImcpFSaowSUkE0vqwC+rh3FdR15Qy yj8atZpsSaHs2oqRIoykUIIZhIxE8gb5qacctMnhULo0bhcxufUR8Gf1rpW6xz3Ksm8Y 6ryybPPc3kelnDYtv2Ym6tUmRyTr9SSsCHT5JwujQso9PzWFP3uGesiW2SZLx+Kjj1/b tDw+JsRay5+XbG3318lNxvhAHkeMvY7gGZCnUflia1XDsuWmUkDT5PVVVhDN8DYdfU+T f7KGBOr9nexfgISHxdNZIeIIA2bGmMMxkFHYV0XWAFSD/UZdhpIg7WwfqoyfVYv1WBZi R0yA== X-Received: by 10.180.93.133 with SMTP id cu5mr1839852wib.32.1392285619826; Thu, 13 Feb 2014 02:00:19 -0800 (PST) Received: from stedf17-labo202.ds.jdsu.net. (4-161.80-90.static-ip.oleane.fr. [90.80.161.4]) by mx.google.com with ESMTPSA id ff9sm12693820wib.11.2014.02.13.02.00.18 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 13 Feb 2014 02:00:18 -0800 (PST) From: Jean-Jacques Hiblot To: gregkh@linuxfoundation.org, grant.likely@linaro.org, robh+dt@kernel.org Subject: [PATCH] dt: platform driver: Fill the resources before probe and defer if needed Date: Thu, 13 Feb 2014 10:57:09 +0100 Message-Id: <1392285429-9325-1-git-send-email-jjhiblot@traphandler.com> X-Mailer: git-send-email 1.8.5.3 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140213_050042_918494_78392913 X-CRM114-Status: GOOD ( 19.98 ) X-Spam-Score: -2.6 (--) Cc: gregory.clement@free-electrons.com, devicetree@vger.kernel.org, Jean-Jacques Hiblot , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The goal of this patch is to allow drivers to be probed even if at the time of the DT parsing some of their ressources are not available yet. In the current situation, the resource of a platform device are filled from the DT at the time the device is created (of_device_alloc()). The drawbackof this is that a device sitting close to the top of the DT (ahb for example) but depending on ressources that are initialized later (IRQ domain dynamically created for example) will fail to probe because the ressources don't exist at this time. This patch fills the resource structure only before the device is probed and will defer the probe if the resource are not available yet. Signed-off-by: Jean-Jacques Hiblot Reviewed-by: Gregory CLEMENT --- drivers/base/platform.c | 6 ++++ drivers/of/platform.c | 71 +++++++++++++++++++++++++++++---------------- include/linux/of_platform.h | 10 +++++++ 3 files changed, 62 insertions(+), 25 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index bc78848..8e37d8b 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -481,6 +481,12 @@ static int platform_drv_probe(struct device *_dev) struct platform_device *dev = to_platform_device(_dev); int ret; + if (_dev->of_node) { + ret = of_platform_device_populate_resources(dev); + if (ret < 0) + return drv->prevent_deferred_probe ? ret : -EPROBE_DEFER; + } + if (ACPI_HANDLE(_dev)) acpi_dev_pm_attach(_dev, true); diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 404d1da..64a8eb8 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -141,36 +141,11 @@ struct platform_device *of_device_alloc(struct device_node *np, struct device *parent) { struct platform_device *dev; - int rc, i, num_reg = 0, num_irq; - struct resource *res, temp_res; dev = platform_device_alloc("", -1); if (!dev) return NULL; - /* count the io and irq resources */ - if (of_can_translate_address(np)) - while (of_address_to_resource(np, num_reg, &temp_res) == 0) - num_reg++; - num_irq = of_irq_count(np); - - /* Populate the resource table */ - if (num_irq || num_reg) { - res = kzalloc(sizeof(*res) * (num_irq + num_reg), GFP_KERNEL); - if (!res) { - platform_device_put(dev); - return NULL; - } - - dev->num_resources = num_reg + num_irq; - dev->resource = res; - for (i = 0; i < num_reg; i++, res++) { - rc = of_address_to_resource(np, i, res); - WARN_ON(rc); - } - WARN_ON(of_irq_to_resource_table(np, res, num_irq) != num_irq); - } - dev->dev.of_node = of_node_get(np); #if defined(CONFIG_MICROBLAZE) dev->dev.dma_mask = &dev->archdata.dma_mask; @@ -233,6 +208,52 @@ static struct platform_device *of_platform_device_create_pdata( return dev; } +int of_platform_device_populate_resources(struct platform_device *dev) +{ + struct device_node *np; + int rc = 0, i, nreg = 0, nirq; + + np = dev->dev.of_node; + + /* count the io and irq resources */ + if (of_can_translate_address(np)) { + struct resource temp_res; + while (of_address_to_resource(np, nreg, &temp_res) == 0) + nreg++; + } + nirq = of_irq_count(np); + + /* Populate the resource table */ + if (nirq || nreg) { + struct resource *res; + + res = krealloc(dev->resource, sizeof(*res) * (nirq + nreg), + GFP_KERNEL); + if (!res) { + kfree(dev->resource); + dev->resource = NULL; + return -ENOMEM; + } + memset(res, 0, sizeof(*res) * (nirq + nreg)); + dev->resource = res; + dev->num_resources = nreg + nirq; + + for (i = 0; i < nreg; i++, res++) { + rc = of_address_to_resource(np, i, res); + WARN_ON(rc); + if (rc) + break; + } + + if (!rc && of_irq_to_resource_table(np, res, nirq) != nirq) { + rc = -ENOENT; + WARN_ON(rc); + } + } + return rc; +} +EXPORT_SYMBOL(of_platform_device_populate_resources); + /** * of_platform_device_create - Alloc, initialize and register an of_device * @np: pointer to node to create device for diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index 05cb4a9..315e1e3 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h @@ -53,6 +53,16 @@ struct of_dev_auxdata { extern const struct of_device_id of_default_bus_match_table[]; +/* Populate the resource for a platform device */ +#ifdef CONFIG_OF +int of_platform_device_populate_resources(struct platform_device *dev); +#else +static inline int of_platform_device_populate_resources( + struct platform_device *) +{ + return -ENOSYS; +} +#endif /* Platform drivers register/unregister */ extern struct platform_device *of_device_alloc(struct device_node *np, const char *bus_id,