summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Muellner <christoph.muellner@theobroma-systems.com>2017-02-24 13:47:52 +0100
committerChristoph Muellner <christoph.muellner@theobroma-systems.com>2017-03-08 14:18:39 +0100
commit4fbafc8575f5fef993538f66e12e02b431ae8c41 (patch)
tree212462bd084615e28762ea75a2a7d62175fb91ae
parentecd8b1df9648376e9c334345c5c014004825893d (diff)
sun50iw1p1: Make RSB read/write calls MP-safe.
When calling rsb_read() or rsb_write() from different processors at the same time we most likely mess up with the RSB block. This patch adds a spinlock, which guarantees atomic access to the RSB block. Signed-off-by: Christoph Muellner <christoph.muellner@theobroma-systems.com>
-rw-r--r--plat/sun50iw1p1/sunxi_rsb.c19
1 files changed, 17 insertions, 2 deletions
diff --git a/plat/sun50iw1p1/sunxi_rsb.c b/plat/sun50iw1p1/sunxi_rsb.c
index 7d7210e..58ee556 100644
--- a/plat/sun50iw1p1/sunxi_rsb.c
+++ b/plat/sun50iw1p1/sunxi_rsb.c
@@ -32,6 +32,7 @@
#include <plat_config.h>
#include <mmio.h>
#include <sys/errno.h>
+#include <spinlock.h>
#include "sunxi_def.h"
#include "sunxi_private.h"
@@ -103,6 +104,8 @@ static struct rsb_slave rsb_slaves[] = {
{ AXP803_HW_ADDR, RUNTIME_ADDR1 }, /* PMIC */
};
+static struct spinlock lock;
+
static inline void rsb_cmd(uint8_t cmd)
{
uint32_t reg;
@@ -123,6 +126,8 @@ int rsb_read(uint8_t rt_addr, uint8_t addr, uint32_t *val, size_t size)
{
uint32_t reg, cmd, mask;
+ spin_lock(&lock);
+
switch (size) {
case 1:
cmd = RSB_CMD_RD8;
@@ -137,6 +142,7 @@ int rsb_read(uint8_t rt_addr, uint8_t addr, uint32_t *val, size_t size)
mask = 0xffffffff;
break;
default:
+ spin_unlock(&lock);
ERROR("Invalid RSB read size %u", size);
return -1;
}
@@ -150,8 +156,10 @@ int rsb_read(uint8_t rt_addr, uint8_t addr, uint32_t *val, size_t size)
/* Read status */
reg = mmio_read_32(R_RSB_BASE + RSB_INTS);
- if (reg != RSB_INTS_TRAS_OVER)
+ if (reg != RSB_INTS_TRAS_OVER) {
+ spin_unlock(&lock);
return -reg;
+ }
/* Get data */
reg = mmio_read_32(R_RSB_BASE + RSB_DATA);
@@ -159,6 +167,7 @@ int rsb_read(uint8_t rt_addr, uint8_t addr, uint32_t *val, size_t size)
if (val)
*val = reg & mask;
+ spin_unlock(&lock);
return 0;
}
@@ -166,6 +175,8 @@ int rsb_write(uint8_t rt_addr, uint8_t addr, uint32_t val, size_t size)
{
uint32_t reg, cmd;
+ spin_lock(&lock);
+
switch (size) {
case 1:
cmd = RSB_CMD_WR8;
@@ -177,6 +188,7 @@ int rsb_write(uint8_t rt_addr, uint8_t addr, uint32_t val, size_t size)
cmd = RSB_CMD_WR32;
break;
default:
+ spin_unlock(&lock);
ERROR("Invalid RSB read size %u", size);
return -1;
}
@@ -191,9 +203,12 @@ int rsb_write(uint8_t rt_addr, uint8_t addr, uint32_t val, size_t size)
/* Read status */
reg = mmio_read_32(R_RSB_BASE + RSB_INTS);
- if (reg != RSB_INTS_TRAS_OVER)
+ if (reg != RSB_INTS_TRAS_OVER) {
+ spin_unlock(&lock);
return -1;
+ }
+ spin_unlock(&lock);
return 0;
}