We need to treat built-in peripherals and bus based address ranges
differently. Local built-in peripherals (and the ColdFire SoC parts
have quite a lot of them) are always native endian - which is big
endian on m68k/ColdFire. Bus based address ranges, like the PIC bus,
are accessed little endian - so we need to byte swap those.

So implement readw/writew and readl/writel functions to deal with
memory mapped accesses correctly based on the address range being
accessed.

This fixes readw/writew and readl/writel so that they can be used in
drivers for native SoC hardware modules (many of which are shared with
other architectures (ARM in Freescale SoC parts for example). And also
drivers for PCI devices.

Signed-off-by: Greg Ungerer <g...@linux-m68k.org>
---
 arch/m68k/include/asm/io_no.h | 58 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 58 insertions(+)

diff --git a/arch/m68k/include/asm/io_no.h b/arch/m68k/include/asm/io_no.h
index a3d23e8..4fe743f 100644
--- a/arch/m68k/include/asm/io_no.h
+++ b/arch/m68k/include/asm/io_no.h
@@ -45,6 +45,64 @@
 #define PCI_IOBASE     ((void __iomem *) PCI_IO_PA)
 #define PCI_SPACE_LIMIT        PCI_IO_MASK
 
+/*
+ * The ColdFire SoC internal peripherals are mapped into virtual address
+ * space using the ACR registers of the cache control unit. This means we
+ * are using a 1:1 physical:virtual mapping for them. We can quickly
+ * determine if we are accessing an internal peripheral device given the
+ * physical or vitrual address using the same range check.
+ */
+static int __cf_internalio(unsigned long addr)
+{
+       return (addr >= IOMEMBASE) && (addr <= IOMEMBASE + IOMEMSIZE - 1);
+}
+
+static int cf_internalio(const volatile void __iomem *addr)
+{
+       return __cf_internalio((unsigned long) addr);
+}
+
+/*
+ * We need to treat built-in peripherals and bus based address ranges
+ * differently. Local built-in peripherals (and the ColdFire SoC parts
+ * have quite a lot of them) are always native endian - which is big
+ * endian on m68k/ColdFire. Bus based address ranges, like the PIC bus,
+ * are accessed little endian - so we need to byte swap those.
+ */
+#define readw readw
+static inline u16 readw(const volatile void __iomem *addr)
+{
+       if (cf_internalio(addr))
+               return __raw_readw(addr);
+       return __le16_to_cpu(__raw_readw(addr));
+}
+
+#define readl readl
+static inline u32 readl(const volatile void __iomem *addr)
+{
+       if (cf_internalio(addr))
+               return __raw_readl(addr);
+       return __le32_to_cpu(__raw_readl(addr));
+}
+
+#define writew writew
+static inline void writew(u16 value, volatile void __iomem *addr)
+{
+       if (cf_internalio(addr))
+               __raw_writew(value, addr);
+       else
+               __raw_writew(__cpu_to_le16(value), addr);
+}
+
+#define writel writel
+static inline void writel(u32 value, volatile void __iomem *addr)
+{
+       if (cf_internalio(addr))
+               __raw_writel(value, addr);
+       else
+               __raw_writel(__cpu_to_le32(value), addr);
+}
+
 #else
 
 #define readb __raw_readb
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-m68k" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to