Blackfin: cleanup sync handling when enabling/disabling cplbs
The handling of updating the [DI]MEM_CONTROL MMRs does not follow proper
sync procedures as laid out in the Blackfin programming manual. So rather
than audit/fix every call location, create helper functions that do the
right things in order to safely update these MMRs. Then convert all call
sites to use these new helper functions.
While we're fixing the code, drop the workaround for anomaly 05000125 as
that anomaly applies to old versions of silicon that we do not support.
Signed-off-by: Yi Li <yi.li@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
diff --git a/arch/blackfin/kernel/cplb-mpu/cacheinit.c b/arch/blackfin/kernel/cplb-mpu/cacheinit.c
index d5a86c3..a082681 100644
--- a/arch/blackfin/kernel/cplb-mpu/cacheinit.c
+++ b/arch/blackfin/kernel/cplb-mpu/cacheinit.c
@@ -30,13 +30,14 @@
unsigned long ctrl;
int i;
- SSYNC();
for (i = 0; i < MAX_CPLBS; i++) {
bfin_write32(ICPLB_ADDR0 + i * 4, icplb_tbl[i].addr);
bfin_write32(ICPLB_DATA0 + i * 4, icplb_tbl[i].data);
}
ctrl = bfin_read_IMEM_CONTROL();
ctrl |= IMC | ENICPLB;
+ /* CSYNC to ensure load store ordering */
+ CSYNC();
bfin_write_IMEM_CONTROL(ctrl);
SSYNC();
}
@@ -48,7 +49,6 @@
unsigned long ctrl;
int i;
- SSYNC();
for (i = 0; i < MAX_CPLBS; i++) {
bfin_write32(DCPLB_ADDR0 + i * 4, dcplb_tbl[i].addr);
bfin_write32(DCPLB_DATA0 + i * 4, dcplb_tbl[i].data);
@@ -63,6 +63,8 @@
* to port B
*/
ctrl |= DMEM_CNTR | PORT_PREF0 | (ANOMALY_05000287 ? PORT_PREF1 : 0);
+ /* CSYNC to ensure load store ordering */
+ CSYNC();
bfin_write_DMEM_CONTROL(ctrl);
SSYNC();
}
diff --git a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
index bcdfe9b..651b127 100644
--- a/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
+++ b/arch/blackfin/kernel/cplb-mpu/cplbmgr.c
@@ -22,6 +22,7 @@
#include <asm/blackfin.h>
#include <asm/cacheflush.h>
+#include <asm/cplb.h>
#include <asm/cplbinit.h>
#include <asm/mmu_context.h>
@@ -41,46 +42,6 @@
int nr_icplb_supv_miss[NR_CPUS], nr_dcplb_prot[NR_CPUS];
int nr_cplb_flush[NR_CPUS];
-static inline void disable_dcplb(void)
-{
- unsigned long ctrl;
- SSYNC();
- ctrl = bfin_read_DMEM_CONTROL();
- ctrl &= ~ENDCPLB;
- bfin_write_DMEM_CONTROL(ctrl);
- SSYNC();
-}
-
-static inline void enable_dcplb(void)
-{
- unsigned long ctrl;
- SSYNC();
- ctrl = bfin_read_DMEM_CONTROL();
- ctrl |= ENDCPLB;
- bfin_write_DMEM_CONTROL(ctrl);
- SSYNC();
-}
-
-static inline void disable_icplb(void)
-{
- unsigned long ctrl;
- SSYNC();
- ctrl = bfin_read_IMEM_CONTROL();
- ctrl &= ~ENICPLB;
- bfin_write_IMEM_CONTROL(ctrl);
- SSYNC();
-}
-
-static inline void enable_icplb(void)
-{
- unsigned long ctrl;
- SSYNC();
- ctrl = bfin_read_IMEM_CONTROL();
- ctrl |= ENICPLB;
- bfin_write_IMEM_CONTROL(ctrl);
- SSYNC();
-}
-
/*
* Given the contents of the status register, return the index of the
* CPLB that caused the fault.
@@ -198,10 +159,10 @@
dcplb_tbl[cpu][idx].addr = addr;
dcplb_tbl[cpu][idx].data = d_data;
- disable_dcplb();
+ _disable_dcplb();
bfin_write32(DCPLB_DATA0 + idx * 4, d_data);
bfin_write32(DCPLB_ADDR0 + idx * 4, addr);
- enable_dcplb();
+ _enable_dcplb();
return 0;
}
@@ -288,10 +249,10 @@
icplb_tbl[cpu][idx].addr = addr;
icplb_tbl[cpu][idx].data = i_data;
- disable_icplb();
+ _disable_icplb();
bfin_write32(ICPLB_DATA0 + idx * 4, i_data);
bfin_write32(ICPLB_ADDR0 + idx * 4, addr);
- enable_icplb();
+ _enable_icplb();
return 0;
}
@@ -340,19 +301,19 @@
nr_cplb_flush[cpu]++;
local_irq_save_hw(flags);
- disable_icplb();
+ _disable_icplb();
for (i = first_switched_icplb; i < MAX_CPLBS; i++) {
icplb_tbl[cpu][i].data = 0;
bfin_write32(ICPLB_DATA0 + i * 4, 0);
}
- enable_icplb();
+ _enable_icplb();
- disable_dcplb();
+ _disable_dcplb();
for (i = first_switched_dcplb; i < MAX_CPLBS; i++) {
dcplb_tbl[cpu][i].data = 0;
bfin_write32(DCPLB_DATA0 + i * 4, 0);
}
- enable_dcplb();
+ _enable_dcplb();
local_irq_restore_hw(flags);
}
@@ -385,7 +346,7 @@
#endif
}
- disable_dcplb();
+ _disable_dcplb();
for (i = first_mask_dcplb; i < first_switched_dcplb; i++) {
dcplb_tbl[cpu][i].addr = addr;
dcplb_tbl[cpu][i].data = d_data;
@@ -393,6 +354,6 @@
bfin_write32(DCPLB_ADDR0 + i * 4, addr);
addr += PAGE_SIZE;
}
- enable_dcplb();
+ _enable_dcplb();
local_irq_restore_hw(flags);
}
diff --git a/arch/blackfin/kernel/cplb-nompu/cacheinit.c b/arch/blackfin/kernel/cplb-nompu/cacheinit.c
index d5a86c3..a082681 100644
--- a/arch/blackfin/kernel/cplb-nompu/cacheinit.c
+++ b/arch/blackfin/kernel/cplb-nompu/cacheinit.c
@@ -30,13 +30,14 @@
unsigned long ctrl;
int i;
- SSYNC();
for (i = 0; i < MAX_CPLBS; i++) {
bfin_write32(ICPLB_ADDR0 + i * 4, icplb_tbl[i].addr);
bfin_write32(ICPLB_DATA0 + i * 4, icplb_tbl[i].data);
}
ctrl = bfin_read_IMEM_CONTROL();
ctrl |= IMC | ENICPLB;
+ /* CSYNC to ensure load store ordering */
+ CSYNC();
bfin_write_IMEM_CONTROL(ctrl);
SSYNC();
}
@@ -48,7 +49,6 @@
unsigned long ctrl;
int i;
- SSYNC();
for (i = 0; i < MAX_CPLBS; i++) {
bfin_write32(DCPLB_ADDR0 + i * 4, dcplb_tbl[i].addr);
bfin_write32(DCPLB_DATA0 + i * 4, dcplb_tbl[i].data);
@@ -63,6 +63,8 @@
* to port B
*/
ctrl |= DMEM_CNTR | PORT_PREF0 | (ANOMALY_05000287 ? PORT_PREF1 : 0);
+ /* CSYNC to ensure load store ordering */
+ CSYNC();
bfin_write_DMEM_CONTROL(ctrl);
SSYNC();
}
diff --git a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c
index 12b0308..aabbb42 100644
--- a/arch/blackfin/kernel/cplb-nompu/cplbmgr.c
+++ b/arch/blackfin/kernel/cplb-nompu/cplbmgr.c
@@ -48,36 +48,13 @@
#define MGR_ATTR
#endif
-/*
- * We're in an exception handler. The normal cli nop nop workaround
- * isn't going to do very much, as the only thing that can interrupt
- * us is an NMI, and the cli isn't going to stop that.
- */
-#define NOWA_SSYNC __asm__ __volatile__ ("ssync;")
-
-/* Anomaly handlers provide SSYNCs, so avoid extra if anomaly is present */
-#if ANOMALY_05000125
-
-#define bfin_write_DMEM_CONTROL_SSYNC(v) bfin_write_DMEM_CONTROL(v)
-#define bfin_write_IMEM_CONTROL_SSYNC(v) bfin_write_IMEM_CONTROL(v)
-
-#else
-
-#define bfin_write_DMEM_CONTROL_SSYNC(v) \
- do { NOWA_SSYNC; bfin_write_DMEM_CONTROL(v); NOWA_SSYNC; } while (0)
-#define bfin_write_IMEM_CONTROL_SSYNC(v) \
- do { NOWA_SSYNC; bfin_write_IMEM_CONTROL(v); NOWA_SSYNC; } while (0)
-
-#endif
-
static inline void write_dcplb_data(int cpu, int idx, unsigned long data,
unsigned long addr)
{
- unsigned long ctrl = bfin_read_DMEM_CONTROL();
- bfin_write_DMEM_CONTROL_SSYNC(ctrl & ~ENDCPLB);
+ _disable_dcplb();
bfin_write32(DCPLB_DATA0 + idx * 4, data);
bfin_write32(DCPLB_ADDR0 + idx * 4, addr);
- bfin_write_DMEM_CONTROL_SSYNC(ctrl);
+ _enable_dcplb();
#ifdef CONFIG_CPLB_INFO
dcplb_tbl[cpu][idx].addr = addr;
@@ -88,12 +65,10 @@
static inline void write_icplb_data(int cpu, int idx, unsigned long data,
unsigned long addr)
{
- unsigned long ctrl = bfin_read_IMEM_CONTROL();
-
- bfin_write_IMEM_CONTROL_SSYNC(ctrl & ~ENICPLB);
+ _disable_icplb();
bfin_write32(ICPLB_DATA0 + idx * 4, data);
bfin_write32(ICPLB_ADDR0 + idx * 4, addr);
- bfin_write_IMEM_CONTROL_SSYNC(ctrl);
+ _enable_icplb();
#ifdef CONFIG_CPLB_INFO
icplb_tbl[cpu][idx].addr = addr;