diff options
author | Jeffrey Deans <jeffrey.deans@imgtec.com> | 2014-07-17 12:20:59 +0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-08-02 02:06:41 +0400 |
commit | c55b2851f901215fbfa46e4ea9cc04761c776815 (patch) | |
tree | a743802f48557f7915c727abf59a451e083732a0 /arch/mips | |
parent | 1c772b5664d9efa8d8d25b69b4ea8ae8996d6153 (diff) | |
download | linux-c55b2851f901215fbfa46e4ea9cc04761c776815.tar.xz |
MIPS: GIC: Fix GICBIS macro
The GICBIS macro could update the GIC registers incorrectly, depending
on the data value passed in:
* Bits were only OR'd into the register data, so register fields could
not be cleared.
* Bits were OR'd into the register data without masking the data to the
correct field width, corrupting adjacent bits.
Signed-off-by: Jeffrey Deans <jeffrey.deans@imgtec.com>
Signed-off-by: Markos Chandras <markos.chandras@imgtec.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/7378/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/include/asm/gic.h | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/arch/mips/include/asm/gic.h b/arch/mips/include/asm/gic.h index 8b30befd99d6..3f20b2111d56 100644 --- a/arch/mips/include/asm/gic.h +++ b/arch/mips/include/asm/gic.h @@ -43,18 +43,17 @@ #ifdef GICISBYTELITTLEENDIAN #define GICREAD(reg, data) ((data) = (reg), (data) = le32_to_cpu(data)) #define GICWRITE(reg, data) ((reg) = cpu_to_le32(data)) -#define GICBIS(reg, bits) \ - ({unsigned int data; \ - GICREAD(reg, data); \ - data |= bits; \ - GICWRITE(reg, data); \ - }) - #else #define GICREAD(reg, data) ((data) = (reg)) #define GICWRITE(reg, data) ((reg) = (data)) -#define GICBIS(reg, bits) ((reg) |= (bits)) #endif +#define GICBIS(reg, mask, bits) \ + do { u32 data; \ + GICREAD((reg), data); \ + data &= ~(mask); \ + data |= ((bits) & (mask)); \ + GICWRITE((reg), data); \ + } while (0) /* GIC Address Space */ @@ -170,13 +169,15 @@ #define GIC_SH_SET_POLARITY_OFS 0x0100 #define GIC_SET_POLARITY(intr, pol) \ GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_POLARITY_OFS + \ - GIC_INTR_OFS(intr)), (pol) << GIC_INTR_BIT(intr)) + GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \ + (pol) << GIC_INTR_BIT(intr)) /* Triggering : Reset Value is always 0 */ #define GIC_SH_SET_TRIGGER_OFS 0x0180 #define GIC_SET_TRIGGER(intr, trig) \ GICBIS(GIC_REG_ADDR(SHARED, GIC_SH_SET_TRIGGER_OFS + \ - GIC_INTR_OFS(intr)), (trig) << GIC_INTR_BIT(intr)) + GIC_INTR_OFS(intr)), (1 << GIC_INTR_BIT(intr)), \ + (trig) << GIC_INTR_BIT(intr)) /* Mask manipulation */ #define GIC_SH_SMASK_OFS 0x0380 |