summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorGuo Ren <ren_guo@c-sky.com>2019-01-08 15:17:49 +0300
committerGuo Ren <ren_guo@c-sky.com>2019-01-08 18:42:42 +0300
commit96354ad79e2e59f9d620669c8e1ac2452440c260 (patch)
treef2cb1c8aeb4839c1a9de1c6c41672a2dc01ea0fe /arch
parentf553aa1c13cbc29aaf420349a28fc33ca98440e5 (diff)
downloadlinux-96354ad79e2e59f9d620669c8e1ac2452440c260.tar.xz
csky: fixup CACHEV1 store instruction fast retire
For I/O access, 810/807 store instruction fast retire will cause wrong primitive. For example: stw (clear interrupt source) stw (unmask interrupt controller) enable interrupt stw is fast retire instruction. When PC is run at enable interrupt stage, the clear interrupt source hasn't finished. It will cause another wrong irq-enter. So use mb() to prevent above. Signed-off-by: Guo Ren <ren_guo@c-sky.com> Cc: Lu Baoquan <lu.baoquan@intellif.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/csky/include/asm/io.h25
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/csky/include/asm/io.h b/arch/csky/include/asm/io.h
index ecae6b358f95..c1dfa9c10e36 100644
--- a/arch/csky/include/asm/io.h
+++ b/arch/csky/include/asm/io.h
@@ -15,6 +15,31 @@ extern void iounmap(void *addr);
extern int remap_area_pages(unsigned long address, phys_addr_t phys_addr,
size_t size, unsigned long flags);
+/*
+ * I/O memory access primitives. Reads are ordered relative to any
+ * following Normal memory access. Writes are ordered relative to any prior
+ * Normal memory access.
+ *
+ * For CACHEV1 (807, 810), store instruction could fast retire, so we need
+ * another mb() to prevent st fast retire.
+ *
+ * For CACHEV2 (860), store instruction with PAGE_ATTR_NO_BUFFERABLE won't
+ * fast retire.
+ */
+#define readb(c) ({ u8 __v = readb_relaxed(c); rmb(); __v; })
+#define readw(c) ({ u16 __v = readw_relaxed(c); rmb(); __v; })
+#define readl(c) ({ u32 __v = readl_relaxed(c); rmb(); __v; })
+
+#ifdef CONFIG_CPU_HAS_CACHEV2
+#define writeb(v,c) ({ wmb(); writeb_relaxed((v),(c)); })
+#define writew(v,c) ({ wmb(); writew_relaxed((v),(c)); })
+#define writel(v,c) ({ wmb(); writel_relaxed((v),(c)); })
+#else
+#define writeb(v,c) ({ wmb(); writeb_relaxed((v),(c)); mb(); })
+#define writew(v,c) ({ wmb(); writew_relaxed((v),(c)); mb(); })
+#define writel(v,c) ({ wmb(); writel_relaxed((v),(c)); mb(); })
+#endif
+
#define ioremap_nocache(phy, sz) ioremap(phy, sz)
#define ioremap_wc ioremap_nocache
#define ioremap_wt ioremap_nocache