From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757472Ab3JJVQs (ORCPT ); Thu, 10 Oct 2013 17:16:48 -0400 Received: from comal.ext.ti.com ([198.47.26.152]:60906 "EHLO comal.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755263Ab3JJVQo (ORCPT ); Thu, 10 Oct 2013 17:16:44 -0400 From: Suman Anna To: Ohad Ben-Cohen , Mark Rutland CC: Tony Lindgren , Benoit Cousson , Kumar Gala , Paul Walmsley , , , , Suman Anna Subject: [PATCHv3 4/8] hwspinlock/omap: enable module before reading SYSSTATUS register Date: Thu, 10 Oct 2013 16:15:31 -0500 Message-ID: <1381439735-52888-5-git-send-email-s-anna@ti.com> X-Mailer: git-send-email 1.8.4 In-Reply-To: <1381439735-52888-1-git-send-email-s-anna@ti.com> References: <1381439735-52888-1-git-send-email-s-anna@ti.com> MIME-Version: 1.0 Content-Type: text/plain Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The number of hwspinlocks are determined based on the value read from the IP block's SYSSTATUS register. However, the module may not be enabled and clocked, and the read may result in a bus error. This particular issue is seen rather easily on AM33XX, since the module wakeup is software controlled, and it is disabled out of reset. Make sure the module is enabled and clocked before reading the SYSSTATUS register. Signed-off-by: Suman Anna --- drivers/hwspinlock/omap_hwspinlock.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c index 349c5aa..9495d76 100644 --- a/drivers/hwspinlock/omap_hwspinlock.c +++ b/drivers/hwspinlock/omap_hwspinlock.c @@ -100,10 +100,23 @@ static int omap_hwspinlock_probe(struct platform_device *pdev) if (!io_base) return -ENOMEM; + /* + * make sure the module is enabled and clocked before reading + * the module SYSSTATUS register + */ + pm_runtime_enable(&pdev->dev); + pm_runtime_get_sync(&pdev->dev); + /* Determine number of locks */ i = readl(io_base + SYSSTATUS_OFFSET); i >>= SPINLOCK_NUMLOCKS_BIT_OFFSET; + /* + * runtime PM will make sure the clock of this module is + * enabled again iff at least one lock is requested + */ + pm_runtime_put(&pdev->dev); + /* one of the four lsb's must be set, and nothing else */ if (hweight_long(i & 0xf) != 1 || i > 8) { ret = -EINVAL; @@ -123,12 +136,6 @@ static int omap_hwspinlock_probe(struct platform_device *pdev) for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++) hwlock->priv = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i; - /* - * runtime PM will make sure the clock of this module is - * enabled iff at least one lock is requested - */ - pm_runtime_enable(&pdev->dev); - ret = hwspin_lock_register(bank, &pdev->dev, &omap_hwspinlock_ops, base_id, num_locks); if (ret) @@ -137,9 +144,9 @@ static int omap_hwspinlock_probe(struct platform_device *pdev) return 0; reg_fail: - pm_runtime_disable(&pdev->dev); kfree(bank); iounmap_base: + pm_runtime_disable(&pdev->dev); iounmap(io_base); return ret; } -- 1.8.4