diff options
| author | Chris Metcalf <cmetcalf@tilera.com> | 2012-04-06 13:52:07 -0400 |
|---|---|---|
| committer | Chris Metcalf <cmetcalf@tilera.com> | 2012-07-11 16:04:53 -0400 |
| commit | 44e56967100f22a21abade38821018ba03d0a39f (patch) | |
| tree | 534e37f68b7c91fae16b3e297fb6fbe42626aece | |
| parent | 37b82b5de77083ada0202da9001ecec9affe4b10 (diff) | |
arch/tile: support MMIO-based readb/writeb etc.
Add support for MMIO read/write on tilegx to support GXIO IORPC access.
Similar to the asm-generic version, but we include memory fences on
the writes to be conservative.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
| -rw-r--r-- | arch/tile/include/asm/io.h | 144 |
1 files changed, 116 insertions, 28 deletions
diff --git a/arch/tile/include/asm/io.h b/arch/tile/include/asm/io.h index d2152deb1f3c..2a9b293fece6 100644 --- a/arch/tile/include/asm/io.h +++ b/arch/tile/include/asm/io.h | |||
| @@ -62,6 +62,92 @@ extern void iounmap(volatile void __iomem *addr); | |||
| 62 | #define mm_ptov(addr) ((void *)phys_to_virt(addr)) | 62 | #define mm_ptov(addr) ((void *)phys_to_virt(addr)) |
| 63 | #define mm_vtop(addr) ((unsigned long)virt_to_phys(addr)) | 63 | #define mm_vtop(addr) ((unsigned long)virt_to_phys(addr)) |
| 64 | 64 | ||
| 65 | #if CHIP_HAS_MMIO() | ||
| 66 | |||
| 67 | /* | ||
| 68 | * We use inline assembly to guarantee that the compiler does not | ||
| 69 | * split an access into multiple byte-sized accesses as it might | ||
| 70 | * sometimes do if a register data structure is marked "packed". | ||
| 71 | * Obviously on tile we can't tolerate such an access being | ||
| 72 | * actually unaligned, but we want to avoid the case where the | ||
| 73 | * compiler conservatively would generate multiple accesses even | ||
| 74 | * for an aligned read or write. | ||
| 75 | */ | ||
| 76 | |||
| 77 | static inline u8 __raw_readb(const volatile void __iomem *addr) | ||
| 78 | { | ||
| 79 | return *(const volatile u8 __force *)addr; | ||
| 80 | } | ||
| 81 | |||
| 82 | static inline u16 __raw_readw(const volatile void __iomem *addr) | ||
| 83 | { | ||
| 84 | u16 ret; | ||
| 85 | asm volatile("ld2u %0, %1" : "=r" (ret) : "r" (addr)); | ||
| 86 | barrier(); | ||
| 87 | return le16_to_cpu(ret); | ||
| 88 | } | ||
| 89 | |||
| 90 | static inline u32 __raw_readl(const volatile void __iomem *addr) | ||
| 91 | { | ||
| 92 | u32 ret; | ||
| 93 | /* Sign-extend to conform to u32 ABI sign-extension convention. */ | ||
| 94 | asm volatile("ld4s %0, %1" : "=r" (ret) : "r" (addr)); | ||
| 95 | barrier(); | ||
| 96 | return le32_to_cpu(ret); | ||
| 97 | } | ||
| 98 | |||
| 99 | static inline u64 __raw_readq(const volatile void __iomem *addr) | ||
| 100 | { | ||
| 101 | u64 ret; | ||
| 102 | asm volatile("ld %0, %1" : "=r" (ret) : "r" (addr)); | ||
| 103 | barrier(); | ||
| 104 | return le64_to_cpu(ret); | ||
| 105 | } | ||
| 106 | |||
| 107 | static inline void __raw_writeb(u8 val, volatile void __iomem *addr) | ||
| 108 | { | ||
| 109 | *(volatile u8 __force *)addr = val; | ||
| 110 | } | ||
| 111 | |||
| 112 | static inline void __raw_writew(u16 val, volatile void __iomem *addr) | ||
| 113 | { | ||
| 114 | asm volatile("st2 %0, %1" :: "r" (addr), "r" (cpu_to_le16(val))); | ||
| 115 | } | ||
| 116 | |||
| 117 | static inline void __raw_writel(u32 val, volatile void __iomem *addr) | ||
| 118 | { | ||
| 119 | asm volatile("st4 %0, %1" :: "r" (addr), "r" (cpu_to_le32(val))); | ||
| 120 | } | ||
| 121 | |||
| 122 | static inline void __raw_writeq(u64 val, volatile void __iomem *addr) | ||
| 123 | { | ||
| 124 | asm volatile("st %0, %1" :: "r" (addr), "r" (cpu_to_le64(val))); | ||
| 125 | } | ||
| 126 | |||
| 127 | /* | ||
| 128 | * The on-chip I/O hardware on tilegx is configured with VA=PA for the | ||
| 129 | * kernel's PA range. The low-level APIs and field names use "va" and | ||
| 130 | * "void *" nomenclature, to be consistent with the general notion | ||
| 131 | * that the addresses in question are virtualizable, but in the kernel | ||
| 132 | * context we are actually manipulating PA values. (In other contexts, | ||
| 133 | * e.g. access from user space, we do in fact use real virtual addresses | ||
| 134 | * in the va fields.) To allow readers of the code to understand what's | ||
| 135 | * happening, we direct their attention to this comment by using the | ||
| 136 | * following two functions that just duplicate __va() and __pa(). | ||
| 137 | */ | ||
| 138 | typedef unsigned long tile_io_addr_t; | ||
| 139 | static inline tile_io_addr_t va_to_tile_io_addr(void *va) | ||
| 140 | { | ||
| 141 | BUILD_BUG_ON(sizeof(phys_addr_t) != sizeof(tile_io_addr_t)); | ||
| 142 | return __pa(va); | ||
| 143 | } | ||
| 144 | static inline void *tile_io_addr_to_va(tile_io_addr_t tile_io_addr) | ||
| 145 | { | ||
| 146 | return __va(tile_io_addr); | ||
| 147 | } | ||
| 148 | |||
| 149 | #else /* CHIP_HAS_MMIO() */ | ||
| 150 | |||
| 65 | #ifdef CONFIG_PCI | 151 | #ifdef CONFIG_PCI |
| 66 | 152 | ||
| 67 | extern u8 _tile_readb(unsigned long addr); | 153 | extern u8 _tile_readb(unsigned long addr); |
| @@ -73,10 +159,19 @@ extern void _tile_writew(u16 val, unsigned long addr); | |||
| 73 | extern void _tile_writel(u32 val, unsigned long addr); | 159 | extern void _tile_writel(u32 val, unsigned long addr); |
| 74 | extern void _tile_writeq(u64 val, unsigned long addr); | 160 | extern void _tile_writeq(u64 val, unsigned long addr); |
| 75 | 161 | ||
| 76 | #else | 162 | #define __raw_readb(addr) _tile_readb((unsigned long)addr) |
| 163 | #define __raw_readw(addr) _tile_readw((unsigned long)addr) | ||
| 164 | #define __raw_readl(addr) _tile_readl((unsigned long)addr) | ||
| 165 | #define __raw_readq(addr) _tile_readq((unsigned long)addr) | ||
| 166 | #define __raw_writeb(val, addr) _tile_writeb(val, (unsigned long)addr) | ||
| 167 | #define __raw_writew(val, addr) _tile_writew(val, (unsigned long)addr) | ||
| 168 | #define __raw_writel(val, addr) _tile_writel(val, (unsigned long)addr) | ||
| 169 | #define __raw_writeq(val, addr) _tile_writeq(val, (unsigned long)addr) | ||
| 170 | |||
| 171 | #else /* CONFIG_PCI */ | ||
| 77 | 172 | ||
| 78 | /* | 173 | /* |
| 79 | * The Tile architecture does not support IOMEM unless PCI is enabled. | 174 | * The tilepro architecture does not support IOMEM unless PCI is enabled. |
| 80 | * Unfortunately we can't yet simply not declare these methods, | 175 | * Unfortunately we can't yet simply not declare these methods, |
| 81 | * since some generic code that compiles into the kernel, but | 176 | * since some generic code that compiles into the kernel, but |
| 82 | * we never run, uses them unconditionally. | 177 | * we never run, uses them unconditionally. |
| @@ -88,65 +183,58 @@ static inline int iomem_panic(void) | |||
| 88 | return 0; | 183 | return 0; |
| 89 | } | 184 | } |
| 90 | 185 | ||
| 91 | static inline u8 _tile_readb(unsigned long addr) | 186 | static inline u8 readb(unsigned long addr) |
| 92 | { | 187 | { |
| 93 | return iomem_panic(); | 188 | return iomem_panic(); |
| 94 | } | 189 | } |
| 95 | 190 | ||
| 96 | static inline u16 _tile_readw(unsigned long addr) | 191 | static inline u16 _readw(unsigned long addr) |
| 97 | { | 192 | { |
| 98 | return iomem_panic(); | 193 | return iomem_panic(); |
| 99 | } | 194 | } |
| 100 | 195 | ||
| 101 | static inline u32 _tile_readl(unsigned long addr) | 196 | static inline u32 readl(unsigned long addr) |
| 102 | { | 197 | { |
| 103 | return iomem_panic(); | 198 | return iomem_panic(); |
| 104 | } | 199 | } |
| 105 | 200 | ||
| 106 | static inline u64 _tile_readq(unsigned long addr) | 201 | static inline u64 readq(unsigned long addr) |
| 107 | { | 202 | { |
| 108 | return iomem_panic(); | 203 | return iomem_panic(); |
| 109 | } | 204 | } |
| 110 | 205 | ||
| 111 | static inline void _tile_writeb(u8 val, unsigned long addr) | 206 | static inline void writeb(u8 val, unsigned long addr) |
| 112 | { | 207 | { |
| 113 | iomem_panic(); | 208 | iomem_panic(); |
| 114 | } | 209 | } |
| 115 | 210 | ||
| 116 | static inline void _tile_writew(u16 val, unsigned long addr) | 211 | static inline void writew(u16 val, unsigned long addr) |
| 117 | { | 212 | { |
| 118 | iomem_panic(); | 213 | iomem_panic(); |
| 119 | } | 214 | } |
| 120 | 215 | ||
| 121 | static inline void _tile_writel(u32 val, unsigned long addr) | 216 | static inline void writel(u32 val, unsigned long addr) |
| 122 | { | 217 | { |
| 123 | iomem_panic(); | 218 | iomem_panic(); |
| 124 | } | 219 | } |
| 125 | 220 | ||
| 126 | static inline void _tile_writeq(u64 val, unsigned long addr) | 221 | static inline void writeq(u64 val, unsigned long addr) |
| 127 | { | 222 | { |
| 128 | iomem_panic(); | 223 | iomem_panic(); |
| 129 | } | 224 | } |
| 130 | 225 | ||
| 131 | #endif | 226 | #endif /* CONFIG_PCI */ |
| 227 | |||
| 228 | #endif /* CHIP_HAS_MMIO() */ | ||
| 132 | 229 | ||
| 133 | #define readb(addr) _tile_readb((unsigned long)addr) | 230 | #define readb __raw_readb |
| 134 | #define readw(addr) _tile_readw((unsigned long)addr) | 231 | #define readw __raw_readw |
| 135 | #define readl(addr) _tile_readl((unsigned long)addr) | 232 | #define readl __raw_readl |
| 136 | #define readq(addr) _tile_readq((unsigned long)addr) | 233 | #define readq __raw_readq |
| 137 | #define writeb(val, addr) _tile_writeb(val, (unsigned long)addr) | 234 | #define writeb __raw_writeb |
| 138 | #define writew(val, addr) _tile_writew(val, (unsigned long)addr) | 235 | #define writew __raw_writew |
| 139 | #define writel(val, addr) _tile_writel(val, (unsigned long)addr) | 236 | #define writel __raw_writel |
| 140 | #define writeq(val, addr) _tile_writeq(val, (unsigned long)addr) | 237 | #define writeq __raw_writeq |
| 141 | |||
| 142 | #define __raw_readb readb | ||
| 143 | #define __raw_readw readw | ||
| 144 | #define __raw_readl readl | ||
| 145 | #define __raw_readq readq | ||
| 146 | #define __raw_writeb writeb | ||
| 147 | #define __raw_writew writew | ||
| 148 | #define __raw_writel writel | ||
| 149 | #define __raw_writeq writeq | ||
| 150 | 238 | ||
| 151 | #define readb_relaxed readb | 239 | #define readb_relaxed readb |
| 152 | #define readw_relaxed readw | 240 | #define readw_relaxed readw |
