summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-omap2/hwspinlock.c8
-rw-r--r--drivers/hwspinlock/hwspinlock_core.c2
-rw-r--r--drivers/hwspinlock/omap_hwspinlock.c6
-rw-r--r--include/linux/hwspinlock.h28
4 files changed, 42 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/hwspinlock.c b/arch/arm/mach-omap2/hwspinlock.c
index 06d4a80660a5..eb7e509957db 100644
--- a/arch/arm/mach-omap2/hwspinlock.c
+++ b/arch/arm/mach-omap2/hwspinlock.c
@@ -19,10 +19,15 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
+#include <linux/hwspinlock.h>
#include <plat/omap_hwmod.h>
#include <plat/omap_device.h>
+static struct hwspinlock_pdata omap_hwspinlock_pdata __initdata = {
+ .base_id = 0,
+};
+
struct omap_device_pm_latency omap_spinlock_latency[] = {
{
.deactivate_func = omap_device_idle_hwmods,
@@ -48,7 +53,8 @@ int __init hwspinlocks_init(void)
if (oh == NULL)
return -EINVAL;
- od = omap_device_build(dev_name, 0, oh, NULL, 0,
+ od = omap_device_build(dev_name, 0, oh, &omap_hwspinlock_pdata,
+ sizeof(struct hwspinlock_pdata),
omap_spinlock_latency,
ARRAY_SIZE(omap_spinlock_latency), false);
if (IS_ERR(od)) {
diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c
index af5175c5d5f4..4eb85b4a320e 100644
--- a/drivers/hwspinlock/hwspinlock_core.c
+++ b/drivers/hwspinlock/hwspinlock_core.c
@@ -282,6 +282,8 @@ int hwspin_lock_register(struct hwspinlock *hwlock)
spin_lock(&hwspinlock_tree_lock);
ret = radix_tree_insert(&hwspinlock_tree, hwlock->id, hwlock);
+ if (ret == -EEXIST)
+ pr_err("hwspinlock id %d already exists!\n", hwlock->id);
if (ret)
goto out;
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
index d0583480fe33..2044d181e49d 100644
--- a/drivers/hwspinlock/omap_hwspinlock.c
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -94,12 +94,16 @@ static const struct hwspinlock_ops omap_hwspinlock_ops = {
static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
{
+ struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
struct omap_hwspinlock *omap_lock;
struct omap_hwspinlock_state *state;
struct resource *res;
void __iomem *io_base;
int i, ret;
+ if (!pdata)
+ return -ENODEV;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENODEV;
@@ -141,7 +145,7 @@ static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
omap_lock = &state->lock[i];
omap_lock->lock.dev = &pdev->dev;
- omap_lock->lock.id = i;
+ omap_lock->lock.id = pdata->base_id + i;
omap_lock->lock.ops = &omap_hwspinlock_ops;
omap_lock->addr = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
diff --git a/include/linux/hwspinlock.h b/include/linux/hwspinlock.h
index 8390efc457eb..f85cef5452f2 100644
--- a/include/linux/hwspinlock.h
+++ b/include/linux/hwspinlock.h
@@ -27,6 +27,34 @@
struct hwspinlock;
+/**
+ * struct hwspinlock_pdata - platform data for hwspinlock drivers
+ * @base_id: base id for this hwspinlock device
+ *
+ * hwspinlock devices provide system-wide hardware locks that are used
+ * by remote processors that have no other way to achieve synchronization.
+ *
+ * To achieve that, each physical lock must have a system-wide id number
+ * that is agreed upon, otherwise remote processors can't possibly assume
+ * they're using the same hardware lock.
+ *
+ * Usually boards have a single hwspinlock device, which provides several
+ * hwspinlocks, and in this case, they can be trivially numbered 0 to
+ * (num-of-locks - 1).
+ *
+ * In case boards have several hwspinlocks devices, a different base id
+ * should be used for each hwspinlock device (they can't all use 0 as
+ * a starting id!).
+ *
+ * This platform data structure should be used to provide the base id
+ * for each device (which is trivially 0 when only a single hwspinlock
+ * device exists). It can be shared between different platforms, hence
+ * its location.
+ */
+struct hwspinlock_pdata {
+ int base_id;
+};
+
#if defined(CONFIG_HWSPINLOCK) || defined(CONFIG_HWSPINLOCK_MODULE)
int hwspin_lock_register(struct hwspinlock *lock);