From patchwork Tue Apr 12 14:09:53 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marek Szyprowski X-Patchwork-Id: 8810831 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B99199F39A for ; Tue, 12 Apr 2016 14:10:15 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id C73BF20357 for ; Tue, 12 Apr 2016 14:10:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A19732028D for ; Tue, 12 Apr 2016 14:10:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933589AbcDLOKM (ORCPT ); Tue, 12 Apr 2016 10:10:12 -0400 Received: from mailout4.w1.samsung.com ([210.118.77.14]:17677 "EHLO mailout4.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932855AbcDLOKL (ORCPT ); Tue, 12 Apr 2016 10:10:11 -0400 Received: from eucpsbgm1.samsung.com (unknown [203.254.199.244]) by mailout4.w1.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0O5I00JN8Y0WVO70@mailout4.w1.samsung.com>; Tue, 12 Apr 2016 15:10:08 +0100 (BST) X-AuditID: cbfec7f4-f796c6d000001486-e4-570d01bf25bf Received: from eusync4.samsung.com ( [203.254.199.214]) by eucpsbgm1.samsung.com (EUCPMTA) with SMTP id A6.0B.05254.FB10D075; Tue, 12 Apr 2016 15:10:07 +0100 (BST) Received: from amdc1339.digital.local ([106.116.147.30]) by eusync4.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0O5I00I7JY0R6J10@eusync4.samsung.com>; Tue, 12 Apr 2016 15:10:07 +0100 (BST) From: Marek Szyprowski To: linux-samsung-soc@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Cc: Marek Szyprowski , Russell King - ARM Linux , Ulf Hansson , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz Subject: [PATCH v6] drivers: amba: properly handle devices with power domains Date: Tue, 12 Apr 2016 16:09:53 +0200 Message-id: <1460470193-24928-1-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <570D017E.7060105@samsung.com> References: <570D017E.7060105@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprGLMWRmVeSWpSXmKPExsVy+t/xa7r7GXnDDdr+mlpsnLGe1eL1C0OL TY+vsVpc3jWHzWLG+X1MFrcv81qsPXKX3eL42nAHDo+W5h42jzvX9rB5bF5S79G3ZRWjx+dN cgGsUVw2Kak5mWWpRfp2CVwZT293sRX8Uqho7VnI3MD4QKqLkZNDQsBE4uqDRjYIW0ziwr31 QDYXh5DAUkaJyxfOs0A4TUwSu1r6warYBAwlut52gdkiAtkS8/d2s4MUMQt8ZZRYencXO0hC WMBX4kPPNrAiFgFViWuzH4HFeQU8JBp2nmSGWCcn8f/lCiYQm1NAW+Lkh6WsILaQgJbEmiMP mScw8i5gZFjFKJpamlxQnJSea6hXnJhbXJqXrpecn7uJERJaX3YwLj5mdYhRgINRiYf3gTNP uBBrYllxZe4hRgkOZiUR3hQG3nAh3pTEyqrUovz4otKc1OJDjNIcLErivHN3vQ8REkhPLEnN Tk0tSC2CyTJxcEo1MEZezqt9YbvJvvPaqvORcruXHD3l+npqSpPGjMWK3zr+XbNafXGS5qpd zft4A7Y3P1lyYYLq/BWzZOTnlweJfsr49OO4y0av8Ghe5bz8nbYO3bnB0Wm54XcNPHjK2kum mv/60y3kq/MlhM1upbH6x9P6qjsi7BvTXl9KzORLnS20N+XDkTnmd5VYijMSDbWYi4oTAQGq rLEpAgAA Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-7.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, 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 To read pid/cid registers, the probed device need to be properly turned on. When it is inside a power domain, the bus code should ensure that the given power domain is enabled before trying to access device's registers. However in some cases power domain (or clocks) might not be yet available. Returning EPROBE_DEFER is not a solution in such case, because callers don't handle this special error code. Instead such devices are added to the special list and their registration is retried in late_initcall, when hopefully all resources are available. Signed-off-by: Marek Szyprowski --- drivers/amba/bus.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index f0099360039e..f0b711bb0372 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -336,16 +336,7 @@ static void amba_device_release(struct device *dev) kfree(d); } -/** - * amba_device_add - add a previously allocated AMBA device structure - * @dev: AMBA device allocated by amba_device_alloc - * @parent: resource parent for this devices resources - * - * Claim the resource, and read the device cell ID if not already - * initialized. Register the AMBA device with the Linux device - * manager. - */ -int amba_device_add(struct amba_device *dev, struct resource *parent) +static int amba_device_try_add(struct amba_device *dev, struct resource *parent) { u32 size; void __iomem *tmp; @@ -373,6 +364,12 @@ int amba_device_add(struct amba_device *dev, struct resource *parent) goto err_release; } + ret = dev_pm_domain_attach(&dev->dev, true); + if (ret == -EPROBE_DEFER) { + iounmap(tmp); + goto err_release; + } + ret = amba_get_enable_pclk(dev); if (ret == 0) { u32 pid, cid; @@ -398,6 +395,7 @@ int amba_device_add(struct amba_device *dev, struct resource *parent) } iounmap(tmp); + dev_pm_domain_detach(&dev->dev, true); if (ret) goto err_release; @@ -421,8 +419,68 @@ int amba_device_add(struct amba_device *dev, struct resource *parent) err_out: return ret; } + +/* + * Registration of AMBA device require reading its pid and cid registers. + * To do this, the device must be turned on (if it is a part of power domain) + * and have clocks enabled. However in some cases those resources might not be + * yet available. Returning EPROBE_DEFER is not a solution in such case, + * because callers don't handle this special error code. Instead such devices + * are added to the special list and their registration is retried in + * late_initcall, when hopefully all resources are available. + */ +struct deferred_device { + struct amba_device *dev; + struct resource *parent; + struct list_head node; +}; + +static LIST_HEAD(deferred_devices); + +/** + * amba_device_add - add a previously allocated AMBA device structure + * @dev: AMBA device allocated by amba_device_alloc + * @parent: resource parent for this devices resources + * + * Claim the resource, and read the device cell ID if not already + * initialized. Register the AMBA device with the Linux device + * manager. + */ +int amba_device_add(struct amba_device *dev, struct resource *parent) +{ + int ret = amba_device_try_add(dev, parent); + + if (ret == -EPROBE_DEFER) { + struct deferred_device *ddev; + + ddev = kmalloc(sizeof(*ddev), GFP_KERNEL); + ddev->dev = dev; + ddev->parent = parent; + list_add_tail(&ddev->node, &deferred_devices); + ret = 0; + } + return ret; +} EXPORT_SYMBOL_GPL(amba_device_add); +static int __init amba_deferred_device_init(void) +{ + struct deferred_device *ddev, *tmp; + + list_for_each_entry_safe(ddev, tmp, &deferred_devices, node) { + int ret = amba_device_try_add(ddev->dev, ddev->parent); + + if (ret == -EPROBE_DEFER) + continue; + + list_del_init(&ddev->node); + kfree(ddev); + } + + return 0; +} +late_initcall(amba_deferred_device_init); + static struct amba_device * amba_aphb_device_add(struct device *parent, const char *name, resource_size_t base, size_t size, int irq1, int irq2,