1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * arch/arm/mach-s3c2410/include/mach/io.h
4 * from arch/arm/mach-rpc/include/mach/io.h
5 *
6 * Copyright (C) 1997 Russell King
7 * (C) 2003 Simtec Electronics
8 */
9
10 #ifndef __ASM_ARM_ARCH_IO_H
11 #define __ASM_ARM_ARCH_IO_H
12
13 #include <mach/hardware.h>
14
15 #define IO_SPACE_LIMIT 0xffffffff
16
17 /*
18 * We use two different types of addressing - PC style addresses, and ARM
19 * addresses. PC style accesses the PC hardware with the normal PC IO
20 * addresses, eg 0x3f8 for serial#1. ARM addresses are above A28
21 * and are translated to the start of IO. Note that all addresses are
22 * not shifted left!
23 */
24
25 #define __PORT_PCIO(x) ((x) < (1<<28))
26
27 #define PCIO_BASE (S3C24XX_VA_ISA_WORD)
28 #define PCIO_BASE_b (S3C24XX_VA_ISA_BYTE)
29 #define PCIO_BASE_w (S3C24XX_VA_ISA_WORD)
30 #define PCIO_BASE_l (S3C24XX_VA_ISA_WORD)
31 /*
32 * Dynamic IO functions - let the compiler
33 * optimize the expressions
34 */
35
36 #define DECLARE_DYN_OUT(sz,fnsuffix,instr) \
37 static inline void __out##fnsuffix (unsigned int val, unsigned int port) \
38 { \
39 unsigned long temp; \
40 __asm__ __volatile__( \
41 "cmp %2, #(1<<28)\n\t" \
42 "mov %0, %2\n\t" \
43 "addcc %0, %0, %3\n\t" \
44 "str" instr " %1, [%0, #0 ] @ out" #fnsuffix \
45 : "=&r" (temp) \
46 : "r" (val), "r" (port), "Ir" (PCIO_BASE_##fnsuffix) \
47 : "cc"); \
48 }
49
50
51 #define DECLARE_DYN_IN(sz,fnsuffix,instr) \
52 static inline unsigned sz __in##fnsuffix (unsigned int port) \
53 { \
54 unsigned long temp, value; \
55 __asm__ __volatile__( \
56 "cmp %2, #(1<<28)\n\t" \
57 "mov %0, %2\n\t" \
58 "addcc %0, %0, %3\n\t" \
59 "ldr" instr " %1, [%0, #0 ] @ in" #fnsuffix \
60 : "=&r" (temp), "=r" (value) \
61 : "r" (port), "Ir" (PCIO_BASE_##fnsuffix) \
62 : "cc"); \
63 return (unsigned sz)value; \
64 }
65
__ioaddr(unsigned long port)66 static inline void __iomem *__ioaddr (unsigned long port)
67 {
68 return __PORT_PCIO(port) ? (PCIO_BASE + port) : (void __iomem *)port;
69 }
70
71 #define DECLARE_IO(sz,fnsuffix,instr) \
72 DECLARE_DYN_IN(sz,fnsuffix,instr) \
73 DECLARE_DYN_OUT(sz,fnsuffix,instr)
74
75 DECLARE_IO(char,b,"b")
76 DECLARE_IO(short,w,"h")
77 DECLARE_IO(int,l,"")
78
79 #undef DECLARE_IO
80 #undef DECLARE_DYN_IN
81
82 /*
83 * Constant address IO functions
84 *
85 * These have to be macros for the 'J' constraint to work -
86 * +/-4096 immediate operand.
87 */
88 #define __outbc(value,port) \
89 ({ \
90 if (__PORT_PCIO((port))) \
91 __asm__ __volatile__( \
92 "strb %0, [%1, %2] @ outbc" \
93 : : "r" (value), "r" (PCIO_BASE), "Jr" ((port))); \
94 else \
95 __asm__ __volatile__( \
96 "strb %0, [%1, #0] @ outbc" \
97 : : "r" (value), "r" ((port))); \
98 })
99
100 #define __inbc(port) \
101 ({ \
102 unsigned char result; \
103 if (__PORT_PCIO((port))) \
104 __asm__ __volatile__( \
105 "ldrb %0, [%1, %2] @ inbc" \
106 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port))); \
107 else \
108 __asm__ __volatile__( \
109 "ldrb %0, [%1, #0] @ inbc" \
110 : "=r" (result) : "r" ((port))); \
111 result; \
112 })
113
114 #define __outwc(value,port) \
115 ({ \
116 unsigned long v = value; \
117 if (__PORT_PCIO((port))) { \
118 if ((port) < 256 && (port) > -256) \
119 __asm__ __volatile__( \
120 "strh %0, [%1, %2] @ outwc" \
121 : : "r" (v), "r" (PCIO_BASE), "Jr" ((port))); \
122 else if ((port) > 0) \
123 __asm__ __volatile__( \
124 "strh %0, [%1, %2] @ outwc" \
125 : : "r" (v), \
126 "r" (PCIO_BASE + ((port) & ~0xff)), \
127 "Jr" (((port) & 0xff))); \
128 else \
129 __asm__ __volatile__( \
130 "strh %0, [%1, #0] @ outwc" \
131 : : "r" (v), \
132 "r" (PCIO_BASE + (port))); \
133 } else \
134 __asm__ __volatile__( \
135 "strh %0, [%1, #0] @ outwc" \
136 : : "r" (v), "r" ((port))); \
137 })
138
139 #define __inwc(port) \
140 ({ \
141 unsigned short result; \
142 if (__PORT_PCIO((port))) { \
143 if ((port) < 256 && (port) > -256 ) \
144 __asm__ __volatile__( \
145 "ldrh %0, [%1, %2] @ inwc" \
146 : "=r" (result) \
147 : "r" (PCIO_BASE), \
148 "Jr" ((port))); \
149 else if ((port) > 0) \
150 __asm__ __volatile__( \
151 "ldrh %0, [%1, %2] @ inwc" \
152 : "=r" (result) \
153 : "r" (PCIO_BASE + ((port) & ~0xff)), \
154 "Jr" (((port) & 0xff))); \
155 else \
156 __asm__ __volatile__( \
157 "ldrh %0, [%1, #0] @ inwc" \
158 : "=r" (result) \
159 : "r" (PCIO_BASE + ((port)))); \
160 } else \
161 __asm__ __volatile__( \
162 "ldrh %0, [%1, #0] @ inwc" \
163 : "=r" (result) : "r" ((port))); \
164 result; \
165 })
166
167 #define __outlc(value,port) \
168 ({ \
169 unsigned long v = value; \
170 if (__PORT_PCIO((port))) \
171 __asm__ __volatile__( \
172 "str %0, [%1, %2] @ outlc" \
173 : : "r" (v), "r" (PCIO_BASE), "Jr" ((port))); \
174 else \
175 __asm__ __volatile__( \
176 "str %0, [%1, #0] @ outlc" \
177 : : "r" (v), "r" ((port))); \
178 })
179
180 #define __inlc(port) \
181 ({ \
182 unsigned long result; \
183 if (__PORT_PCIO((port))) \
184 __asm__ __volatile__( \
185 "ldr %0, [%1, %2] @ inlc" \
186 : "=r" (result) : "r" (PCIO_BASE), "Jr" ((port))); \
187 else \
188 __asm__ __volatile__( \
189 "ldr %0, [%1, #0] @ inlc" \
190 : "=r" (result) : "r" ((port))); \
191 result; \
192 })
193
194 #define __ioaddrc(port) ((__PORT_PCIO(port) ? PCIO_BASE + (port) : (void __iomem *)0 + (port)))
195
196 #define inb(p) (__builtin_constant_p((p)) ? __inbc(p) : __inb(p))
197 #define inw(p) (__builtin_constant_p((p)) ? __inwc(p) : __inw(p))
198 #define inl(p) (__builtin_constant_p((p)) ? __inlc(p) : __inl(p))
199 #define outb(v,p) (__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p))
200 #define outw(v,p) (__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
201 #define outl(v,p) (__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
202 #define __ioaddr(p) (__builtin_constant_p((p)) ? __ioaddr(p) : __ioaddrc(p))
203
204 #define insb(p,d,l) __raw_readsb(__ioaddr(p),d,l)
205 #define insw(p,d,l) __raw_readsw(__ioaddr(p),d,l)
206 #define insl(p,d,l) __raw_readsl(__ioaddr(p),d,l)
207
208 #define outsb(p,d,l) __raw_writesb(__ioaddr(p),d,l)
209 #define outsw(p,d,l) __raw_writesw(__ioaddr(p),d,l)
210 #define outsl(p,d,l) __raw_writesl(__ioaddr(p),d,l)
211
212 #endif
213