OSDN Git Service

ARM: 7500/1: io: avoid writeback addressing modes for __raw_ accessors
[uclinux-h8/linux.git] / arch / arm / include / asm / io.h
index 815c669..09c4628 100644 (file)
@@ -47,13 +47,68 @@ extern void __raw_readsb(const void __iomem *addr, void *data, int bytelen);
 extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
 extern void __raw_readsl(const void __iomem *addr, void *data, int longlen);
 
-#define __raw_writeb(v,a)      ((void)(__chk_io_ptr(a), *(volatile unsigned char __force  *)(a) = (v)))
-#define __raw_writew(v,a)      ((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)))
-#define __raw_writel(v,a)      ((void)(__chk_io_ptr(a), *(volatile unsigned int __force   *)(a) = (v)))
+#if __LINUX_ARM_ARCH__ < 6
+/*
+ * Half-word accesses are problematic with RiscPC due to limitations of
+ * the bus. Rather than special-case the machine, just let the compiler
+ * generate the access for CPUs prior to ARMv6.
+ */
+#define __raw_readw(a)         (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
+#define __raw_writew(v,a)      ((void)(__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)))
+#else
+/*
+ * When running under a hypervisor, we want to avoid I/O accesses with
+ * writeback addressing modes as these incur a significant performance
+ * overhead (the address generation must be emulated in software).
+ */
+static inline void __raw_writew(u16 val, volatile void __iomem *addr)
+{
+       asm volatile("strh %1, %0"
+                    : "+Qo" (*(volatile u16 __force *)addr)
+                    : "r" (val));
+}
+
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+       u16 val;
+       asm volatile("ldrh %1, %0"
+                    : "+Qo" (*(volatile u16 __force *)addr),
+                      "=r" (val));
+       return val;
+}
+#endif
 
-#define __raw_readb(a)         (__chk_io_ptr(a), *(volatile unsigned char __force  *)(a))
-#define __raw_readw(a)         (__chk_io_ptr(a), *(volatile unsigned short __force *)(a))
-#define __raw_readl(a)         (__chk_io_ptr(a), *(volatile unsigned int __force   *)(a))
+static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
+{
+       asm volatile("strb %1, %0"
+                    : "+Qo" (*(volatile u8 __force *)addr)
+                    : "r" (val));
+}
+
+static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+{
+       asm volatile("str %1, %0"
+                    : "+Qo" (*(volatile u32 __force *)addr)
+                    : "r" (val));
+}
+
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+       u8 val;
+       asm volatile("ldrb %1, %0"
+                    : "+Qo" (*(volatile u8 __force *)addr),
+                      "=r" (val));
+       return val;
+}
+
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+       u32 val;
+       asm volatile("ldr %1, %0"
+                    : "+Qo" (*(volatile u32 __force *)addr),
+                      "=r" (val));
+       return val;
+}
 
 /*
  * Architecture ioremap implementation.