aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Ungerer <gerg@linux-m68k.org>2018-03-30 09:40:31 -0400
committerGreg Ungerer <gerg@linux-m68k.org>2018-05-27 19:45:26 -0400
commit4d53037876277fbba10f47de7b90d3a873c5d12b (patch)
treee79703184ec4066f0034c47b988cc8fb2aff3afe
parentdf8f77dec74319794eff9a93d68ada7998b0d510 (diff)
m68k: fix read/write multi-byte IO for PCI on ColdFire
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 PCI 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 <gerg@linux-m68k.org> Tested-by: Angelo Dureghello <angelo@sysam.it>
-rw-r--r--arch/m68k/include/asm/io_no.h99
1 files changed, 84 insertions, 15 deletions
diff --git a/arch/m68k/include/asm/io_no.h b/arch/m68k/include/asm/io_no.h
index 42d61d4f4b86..ccb8c31faf49 100644
--- a/arch/m68k/include/asm/io_no.h
+++ b/arch/m68k/include/asm/io_no.h
@@ -18,16 +18,95 @@
18#define __raw_writew(b, addr) (void)((*(volatile unsigned short *) (addr)) = (b)) 18#define __raw_writew(b, addr) (void)((*(volatile unsigned short *) (addr)) = (b))
19#define __raw_writel(b, addr) (void)((*(volatile unsigned int *) (addr)) = (b)) 19#define __raw_writel(b, addr) (void)((*(volatile unsigned int *) (addr)) = (b))
20 20
21#if defined(CONFIG_PCI) && defined(CONFIG_COLDFIRE) 21#if defined(CONFIG_COLDFIRE)
22/* 22/*
23 * Support for PCI bus access uses the asm-generic access functions. 23 * For ColdFire platforms we may need to do some extra checks for what
24 * We need to supply the base address and masks for the normal memory 24 * type of address range we are accessing. Include the ColdFire platform
25 * and IO address space mappings. 25 * definitions so we can figure out if need to do something special.
26 */ 26 */
27#include <asm/byteorder.h> 27#include <asm/byteorder.h>
28#include <asm/coldfire.h> 28#include <asm/coldfire.h>
29#include <asm/mcfsim.h> 29#include <asm/mcfsim.h>
30#endif /* CONFIG_COLDFIRE */
31
32#if defined(IOMEMBASE)
33/*
34 * The ColdFire SoC internal peripherals are mapped into virtual address
35 * space using the ACR registers of the cache control unit. This means we
36 * are using a 1:1 physical:virtual mapping for them. We can quickly
37 * determine if we are accessing an internal peripheral device given the
38 * physical or vitrual address using the same range check. This check logic
39 * applies just the same of there is no MMU but something like a PCI bus
40 * is present.
41 */
42static int __cf_internalio(unsigned long addr)
43{
44 return (addr >= IOMEMBASE) && (addr <= IOMEMBASE + IOMEMSIZE - 1);
45}
46
47static int cf_internalio(const volatile void __iomem *addr)
48{
49 return __cf_internalio((unsigned long) addr);
50}
51
52/*
53 * We need to treat built-in peripherals and bus based address ranges
54 * differently. Local built-in peripherals (and the ColdFire SoC parts
55 * have quite a lot of them) are always native endian - which is big
56 * endian on m68k/ColdFire. Bus based address ranges, like the PCI bus,
57 * are accessed little endian - so we need to byte swap those.
58 */
59#define readw readw
60static inline u16 readw(const volatile void __iomem *addr)
61{
62 if (cf_internalio(addr))
63 return __raw_readw(addr);
64 return __le16_to_cpu(__raw_readw(addr));
65}
66
67#define readl readl
68static inline u32 readl(const volatile void __iomem *addr)
69{
70 if (cf_internalio(addr))
71 return __raw_readl(addr);
72 return __le32_to_cpu(__raw_readl(addr));
73}
74
75#define writew writew
76static inline void writew(u16 value, volatile void __iomem *addr)
77{
78 if (cf_internalio(addr))
79 __raw_writew(value, addr);
80 else
81 __raw_writew(__cpu_to_le16(value), addr);
82}
83
84#define writel writel
85static inline void writel(u32 value, volatile void __iomem *addr)
86{
87 if (cf_internalio(addr))
88 __raw_writel(value, addr);
89 else
90 __raw_writel(__cpu_to_le32(value), addr);
91}
92
93#else
94
95#define readb __raw_readb
96#define readw __raw_readw
97#define readl __raw_readl
98#define writeb __raw_writeb
99#define writew __raw_writew
100#define writel __raw_writel
30 101
102#endif /* IOMEMBASE */
103
104#if defined(CONFIG_PCI)
105/*
106 * Support for PCI bus access uses the asm-generic access functions.
107 * We need to supply the base address and masks for the normal memory
108 * and IO address space mappings.
109 */
31#define PCI_MEM_PA 0xf0000000 /* Host physical address */ 110#define PCI_MEM_PA 0xf0000000 /* Host physical address */
32#define PCI_MEM_BA 0xf0000000 /* Bus physical address */ 111#define PCI_MEM_BA 0xf0000000 /* Bus physical address */
33#define PCI_MEM_SIZE 0x08000000 /* 128 MB */ 112#define PCI_MEM_SIZE 0x08000000 /* 128 MB */
@@ -44,17 +123,7 @@
44#define PIO_RESERVED 0x10000 123#define PIO_RESERVED 0x10000
45#define PCI_IOBASE ((void __iomem *) PCI_IO_PA) 124#define PCI_IOBASE ((void __iomem *) PCI_IO_PA)
46#define PCI_SPACE_LIMIT PCI_IO_MASK 125#define PCI_SPACE_LIMIT PCI_IO_MASK
47 126#endif /* CONFIG_PCI */
48#else
49
50#define readb __raw_readb
51#define readw __raw_readw
52#define readl __raw_readl
53#define writeb __raw_writeb
54#define writew __raw_writew
55#define writel __raw_writel
56
57#endif /* CONFIG_PCI && CONFIG_COLDFIRE */
58 127
59/* 128/*
60 * These are defined in kmap.h as static inline functions. To maintain 129 * These are defined in kmap.h as static inline functions. To maintain