Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755564AbbLWLAz (ORCPT ); Wed, 23 Dec 2015 06:00:55 -0500 Received: from mailout1.w1.samsung.com ([210.118.77.11]:30008 "EHLO mailout1.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934223AbbLWLAt (ORCPT ); Wed, 23 Dec 2015 06:00:49 -0500 X-AuditID: cbfec7f5-f79b16d000005389-4d-567a7ede2323 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 , Tomeu Vizoso , Greg Kroah-Hartman , Dan Williams , Kukjin Kim , Krzysztof Kozlowski , Bartlomiej Zolnierkiewicz Subject: [PATCH v5 4/5] ARM: amba: Move reading of periphid to amba_match() Date: Wed, 23 Dec 2015 11:59:27 +0100 Message-id: <1450868368-5650-5-git-send-email-m.szyprowski@samsung.com> X-Mailer: git-send-email 1.9.2 In-reply-to: <1450868368-5650-1-git-send-email-m.szyprowski@samsung.com> References: <1450868368-5650-1-git-send-email-m.szyprowski@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFtrHLMWRmVeSWpSXmKPExsVy+t/xq7r36qrCDM6+F7TYOGM9q8X0qRcY LZoXr2ezeP3C0KL/8Wtmi02Pr7FaXN41h81ixvl9TBa3L/NarD1yl92ib+0lNovja8MdeDxa mnvYPHbcXcLosXjPSyaPTas62TzuXNvD5rF/7hp2j81L6j36tqxi9Pi8SS6AM4rLJiU1J7Ms tUjfLoEr48Sz6SwFO7UrLv86xNzA+Eexi5GTQ0LAROLe1t3MELaYxIV769m6GLk4hASWMkoc XLKKFcJpYpI4PvcFC0gVm4ChRNfbLjYQW0QgW2L+3m52kCJmgfnMEg9X9bOCJIQFvCVu3vwH NpZFQFVi24ZLYA28Au4Sjd1vmCDWyUn8f7kCzOYU8JC4s/wVWL0QUE3bwTfMExh5FzAyrGIU TS1NLihOSs810itOzC0uzUvXS87P3cQICdWvOxiXHrM6xCjAwajEw/uiuTJMiDWxrLgy9xCj BAezkghv+jugEG9KYmVValF+fFFpTmrxIUZpDhYlcd6Zu96HCAmkJ5akZqemFqQWwWSZODil GhhFLXTyTsz9VrdGr8tqHlcDN/MHi8zsRJF7xcc/LKlg2H8wZMdWxkglqxu8+kEOzR8aDn28 XrY15N0ax1fP33z9GOb6ZEVHnLl7z5u/YXUTEs6z+exQU5V5x2i35cp3X/UrH64bS6kd+vJ+ mvNC3c4/X1fsenv4HLuaVmDl5qfN5qxCGYbsam5KLMUZiYZazEXFiQDGIamGUQIAAA== Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5591 Lines: 220 From: Tomeu Vizoso Reading the periphid when the Primecell device is registered means that the apb pclk must be available by then or the device won't be registered at all. By reading the periphid in amba_match() we can return -EPROBE_DEFER if the apb pclk isn't there yet and the device will be retried later. Signed-off-by: Tomeu Vizoso [minor code adjustments, removed forward declaration, added missing comment] Signed-off-by: Marek Szyprowski Reviewed-by: Ulf Hansson --- drivers/amba/bus.c | 146 +++++++++++++++++++++++++++-------------------------- 1 file changed, 75 insertions(+), 71 deletions(-) diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index f009936..643127f 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -24,6 +24,71 @@ #define to_amba_driver(d) container_of(d, struct amba_driver, drv) +static int amba_get_enable_pclk(struct amba_device *pcdev) +{ + int ret; + + pcdev->pclk = clk_get(&pcdev->dev, "apb_pclk"); + if (IS_ERR(pcdev->pclk)) + return PTR_ERR(pcdev->pclk); + + ret = clk_prepare_enable(pcdev->pclk); + if (ret) + clk_put(pcdev->pclk); + + return ret; +} + +static void amba_put_disable_pclk(struct amba_device *pcdev) +{ + clk_disable_unprepare(pcdev->pclk); + clk_put(pcdev->pclk); +} + +static int amba_read_periphid(struct amba_device *dev) +{ + u32 size; + void __iomem *tmp; + int i, ret = 0; + + /* + * Dynamically calculate the size of the resource + * and use this for iomap + */ + size = resource_size(&dev->res); + tmp = ioremap(dev->res.start, size); + if (!tmp) + return -ENOMEM; + + ret = amba_get_enable_pclk(dev); + if (ret == 0) { + u32 pid, cid; + + /* + * Read pid and cid based on size of resource + * they are located at end of region + */ + for (pid = 0, i = 0; i < 4; i++) + pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) << + (i * 8); + for (cid = 0, i = 0; i < 4; i++) + cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) << + (i * 8); + + amba_put_disable_pclk(dev); + + if (cid == AMBA_CID || cid == CORESIGHT_CID) + dev->periphid = pid; + + if (!dev->periphid) + ret = -ENODEV; + } + + iounmap(tmp); + + return ret; +} + static const struct amba_id * amba_lookup(const struct amba_id *table, struct amba_device *dev) { @@ -43,11 +108,19 @@ static int amba_match(struct device *dev, struct device_driver *drv) { struct amba_device *pcdev = to_amba_device(dev); struct amba_driver *pcdrv = to_amba_driver(drv); + int ret; /* When driver_override is set, only bind to the matching driver */ if (pcdev->driver_override) return !strcmp(pcdev->driver_override, drv->name); + /* Do plug-n-play if no hard-coded primecell ID has been provided */ + if (!pcdev->periphid) { + ret = amba_read_periphid(pcdev); + if (ret) + return ret; + } + return amba_lookup(pcdrv->id_table, pcdev) != NULL; } @@ -204,27 +277,6 @@ static int __init amba_init(void) postcore_initcall(amba_init); -static int amba_get_enable_pclk(struct amba_device *pcdev) -{ - int ret; - - pcdev->pclk = clk_get(&pcdev->dev, "apb_pclk"); - if (IS_ERR(pcdev->pclk)) - return PTR_ERR(pcdev->pclk); - - ret = clk_prepare_enable(pcdev->pclk); - if (ret) - clk_put(pcdev->pclk); - - return ret; -} - -static void amba_put_disable_pclk(struct amba_device *pcdev) -{ - clk_disable_unprepare(pcdev->pclk); - clk_put(pcdev->pclk); -} - /* * These are the device model conversion veneers; they convert the * device model structures to our more specific structures. @@ -341,15 +393,12 @@ static void amba_device_release(struct device *dev) * @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 + * Claim the resource, and register the AMBA device with the Linux device * manager. */ int amba_device_add(struct amba_device *dev, struct resource *parent) { - u32 size; - void __iomem *tmp; - int i, ret; + int ret; WARN_ON(dev->irq[0] == (unsigned int)-1); WARN_ON(dev->irq[1] == (unsigned int)-1); @@ -358,51 +407,6 @@ int amba_device_add(struct amba_device *dev, struct resource *parent) if (ret) goto err_out; - /* Hard-coded primecell ID instead of plug-n-play */ - if (dev->periphid != 0) - goto skip_probe; - - /* - * Dynamically calculate the size of the resource - * and use this for iomap - */ - size = resource_size(&dev->res); - tmp = ioremap(dev->res.start, size); - if (!tmp) { - ret = -ENOMEM; - goto err_release; - } - - ret = amba_get_enable_pclk(dev); - if (ret == 0) { - u32 pid, cid; - - /* - * Read pid and cid based on size of resource - * they are located at end of region - */ - for (pid = 0, i = 0; i < 4; i++) - pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) << - (i * 8); - for (cid = 0, i = 0; i < 4; i++) - cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) << - (i * 8); - - amba_put_disable_pclk(dev); - - if (cid == AMBA_CID || cid == CORESIGHT_CID) - dev->periphid = pid; - - if (!dev->periphid) - ret = -ENODEV; - } - - iounmap(tmp); - - if (ret) - goto err_release; - - skip_probe: ret = device_add(&dev->dev); if (ret) goto err_release; -- 1.9.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/