diff options
author | Christoph Muellner <christoph.muellner@theobroma-systems.com> | 2017-02-24 13:47:52 +0100 |
---|---|---|
committer | Christoph Muellner <christoph.muellner@theobroma-systems.com> | 2017-03-08 14:18:39 +0100 |
commit | 4fbafc8575f5fef993538f66e12e02b431ae8c41 (patch) | |
tree | 212462bd084615e28762ea75a2a7d62175fb91ae /plat | |
parent | ecd8b1df9648376e9c334345c5c014004825893d (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>
Diffstat (limited to 'plat')
-rw-r--r-- | plat/sun50iw1p1/sunxi_rsb.c | 19 |
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; } |