ssbi: add remote spinlock support
Remote spinlocks are needed for targets that share the SSBI2 controller
with other processors (i.e. modem). Targets that have the PMIC Arbiter
are not impacted because the hardware handles the arbitration of the
different software masters.
Change-Id: I3ffd41d7d259e0745ff4d03cd99d5c4bdbc94fa6
Signed-off-by: Kenneth Heitke <kheitke@codeaurora.org>
diff --git a/drivers/platform/msm/ssbi.c b/drivers/platform/msm/ssbi.c
index 8a6dbf7..e2554f5 100644
--- a/drivers/platform/msm/ssbi.c
+++ b/drivers/platform/msm/ssbi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
* Copyright (c) 2010, Google Inc.
*
* Original authors: Code Aurora Forum
@@ -25,6 +25,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/msm_ssbi.h>
+#include <linux/remote_spinlock.h>
/* SSBI 2.0 controller registers */
#define SSBI2_CMD 0x0008
@@ -75,7 +76,9 @@
struct device *dev;
struct device *slave;
void __iomem *base;
+ bool use_rlock;
spinlock_t lock;
+ remote_spinlock_t rspin_lock;
enum msm_ssbi_controller_type controller_type;
int (*read)(struct msm_ssbi *, u16 addr, u8 *buf, int len);
int (*write)(struct msm_ssbi *, u16 addr, u8 *buf, int len);
@@ -255,9 +258,15 @@
if (ssbi->dev != dev)
return -ENXIO;
- spin_lock_irqsave(&ssbi->lock, flags);
- ret = ssbi->read(ssbi, addr, buf, len);
- spin_unlock_irqrestore(&ssbi->lock, flags);
+ if (ssbi->use_rlock) {
+ remote_spin_lock_irqsave(&ssbi->rspin_lock, flags);
+ ret = ssbi->read(ssbi, addr, buf, len);
+ remote_spin_unlock_irqrestore(&ssbi->rspin_lock, flags);
+ } else {
+ spin_lock_irqsave(&ssbi->lock, flags);
+ ret = ssbi->read(ssbi, addr, buf, len);
+ spin_unlock_irqrestore(&ssbi->lock, flags);
+ }
return ret;
}
@@ -272,9 +281,15 @@
if (ssbi->dev != dev)
return -ENXIO;
- spin_lock_irqsave(&ssbi->lock, flags);
- ret = ssbi->write(ssbi, addr, buf, len);
- spin_unlock_irqrestore(&ssbi->lock, flags);
+ if (ssbi->use_rlock) {
+ remote_spin_lock_irqsave(&ssbi->rspin_lock, flags);
+ ret = ssbi->write(ssbi, addr, buf, len);
+ remote_spin_unlock_irqrestore(&ssbi->rspin_lock, flags);
+ } else {
+ spin_lock_irqsave(&ssbi->lock, flags);
+ ret = ssbi->write(ssbi, addr, buf, len);
+ spin_unlock_irqrestore(&ssbi->lock, flags);
+ }
return ret;
}
@@ -362,6 +377,15 @@
ssbi->write = msm_ssbi_write_bytes;
}
+ if (pdata->rsl_id) {
+ ret = remote_spin_lock_init(&ssbi->rspin_lock, pdata->rsl_id);
+ if (ret) {
+ dev_err(&pdev->dev, "remote spinlock init failed\n");
+ goto err_ssbi_add_slave;
+ }
+ ssbi->use_rlock = 1;
+ }
+
spin_lock_init(&ssbi->lock);
ret = msm_ssbi_add_slave(ssbi, &pdata->slave);
diff --git a/include/linux/msm_ssbi.h b/include/linux/msm_ssbi.h
index e90398a..647bc06 100644
--- a/include/linux/msm_ssbi.h
+++ b/include/linux/msm_ssbi.h
@@ -1,5 +1,5 @@
/* Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
* Author: Dima Zavin <dima@android.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -30,6 +30,7 @@
};
struct msm_ssbi_platform_data {
+ const char *rsl_id;
struct msm_ssbi_slave_info slave;
enum msm_ssbi_controller_type controller_type;
};