From 4fbafc8575f5fef993538f66e12e02b431ae8c41 Mon Sep 17 00:00:00 2001 From: Christoph Muellner Date: Fri, 24 Feb 2017 13:47:52 +0100 Subject: 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 --- plat/sun50iw1p1/sunxi_rsb.c | 19 +++++++++++++++++-- 1 file 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 #include #include +#include #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; } -- cgit v1.2.3