1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * IO definitions for the Hexagon architecture
4 *
5 * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
6 */
7
8#ifndef _ASM_IO_H
9#define _ASM_IO_H
10
11#ifdef __KERNEL__
12
13#include <linux/types.h>
14#include <asm/iomap.h>
15#include <asm/page.h>
16#include <asm/cacheflush.h>
17
18/*
19 * We don't have PCI yet.
20 * _IO_BASE is pointing at what should be unused virtual space.
21 */
22#define IO_SPACE_LIMIT 0xffff
23#define _IO_BASE ((void __iomem *)0xfe000000)
24
25#define IOMEM(x)        ((void __force __iomem *)(x))
26
27extern int remap_area_pages(unsigned long start, unsigned long phys_addr,
28				unsigned long end, unsigned long flags);
29
30/* Defined in lib/io.c, needed for smc91x driver. */
31extern void __raw_readsw(const void __iomem *addr, void *data, int wordlen);
32extern void __raw_writesw(void __iomem *addr, const void *data, int wordlen);
33
34extern void __raw_readsl(const void __iomem *addr, void *data, int wordlen);
35extern void __raw_writesl(void __iomem *addr, const void *data, int wordlen);
36
37#define readsw(p, d, l)	__raw_readsw(p, d, l)
38#define writesw(p, d, l) __raw_writesw(p, d, l)
39
40#define readsl(p, d, l)   __raw_readsl(p, d, l)
41#define writesl(p, d, l)  __raw_writesl(p, d, l)
42
43/*
44 * virt_to_phys - map virtual address to physical
45 * @address:  address to map
46 */
47static inline unsigned long virt_to_phys(volatile void *address)
48{
49	return __pa(address);
50}
51
52/*
53 * phys_to_virt - map physical address to virtual
54 * @address: address to map
55 */
56static inline void *phys_to_virt(unsigned long address)
57{
58	return __va(address);
59}
60
61/*
62 * IO port access primitives.  Hexagon doesn't have special IO access
63 * instructions; all I/O is memory mapped.
64 *
65 * in/out are used for "ports", but we don't have "port instructions",
66 * so these are really just memory mapped too.
67 */
68
69/*
70 * readb - read byte from memory mapped device
71 * @addr:  pointer to memory
72 *
73 * Operates on "I/O bus memory space"
74 */
75static inline u8 readb(const volatile void __iomem *addr)
76{
77	u8 val;
78	asm volatile(
79		"%0 = memb(%1);"
80		: "=&r" (val)
81		: "r" (addr)
82	);
83	return val;
84}
85
86static inline u16 readw(const volatile void __iomem *addr)
87{
88	u16 val;
89	asm volatile(
90		"%0 = memh(%1);"
91		: "=&r" (val)
92		: "r" (addr)
93	);
94	return val;
95}
96
97static inline u32 readl(const volatile void __iomem *addr)
98{
99	u32 val;
100	asm volatile(
101		"%0 = memw(%1);"
102		: "=&r" (val)
103		: "r" (addr)
104	);
105	return val;
106}
107
108/*
109 * writeb - write a byte to a memory location
110 * @data: data to write to
111 * @addr:  pointer to memory
112 *
113 */
114static inline void writeb(u8 data, volatile void __iomem *addr)
115{
116	asm volatile(
117		"memb(%0) = %1;"
118		:
119		: "r" (addr), "r" (data)
120		: "memory"
121	);
122}
123
124static inline void writew(u16 data, volatile void __iomem *addr)
125{
126	asm volatile(
127		"memh(%0) = %1;"
128		:
129		: "r" (addr), "r" (data)
130		: "memory"
131	);
132
133}
134
135static inline void writel(u32 data, volatile void __iomem *addr)
136{
137	asm volatile(
138		"memw(%0) = %1;"
139		:
140		: "r" (addr), "r" (data)
141		: "memory"
142	);
143}
144
145#define __raw_writeb writeb
146#define __raw_writew writew
147#define __raw_writel writel
148
149#define __raw_readb readb
150#define __raw_readw readw
151#define __raw_readl readl
152
153/*
154 * http://comments.gmane.org/gmane.linux.ports.arm.kernel/117626
155 */
156
157#define readb_relaxed __raw_readb
158#define readw_relaxed __raw_readw
159#define readl_relaxed __raw_readl
160
161#define writeb_relaxed __raw_writeb
162#define writew_relaxed __raw_writew
163#define writel_relaxed __raw_writel
164
165/*
166 * I/O memory mapping functions.
167 */
168#define _PAGE_IOREMAP (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \
169		       (__HEXAGON_C_DEV << 6))
170
171#define __raw_writel writel
172
173static inline void memcpy_fromio(void *dst, const volatile void __iomem *src,
174	int count)
175{
176	memcpy(dst, (void *) src, count);
177}
178
179static inline void memcpy_toio(volatile void __iomem *dst, const void *src,
180	int count)
181{
182	memcpy((void *) dst, src, count);
183}
184
185static inline void memset_io(volatile void __iomem *addr, int value,
186			     size_t size)
187{
188	memset((void __force *)addr, value, size);
189}
190
191#define PCI_IO_ADDR	(volatile void __iomem *)
192
193/*
194 * inb - read byte from I/O port or something
195 * @port:  address in I/O space
196 *
197 * Operates on "I/O bus I/O space"
198 */
199static inline u8 inb(unsigned long port)
200{
201	return readb(_IO_BASE + (port & IO_SPACE_LIMIT));
202}
203
204static inline u16 inw(unsigned long port)
205{
206	return readw(_IO_BASE + (port & IO_SPACE_LIMIT));
207}
208
209static inline u32 inl(unsigned long port)
210{
211	return readl(_IO_BASE + (port & IO_SPACE_LIMIT));
212}
213
214/*
215 * outb - write a byte to a memory location
216 * @data: data to write to
217 * @addr:  address in I/O space
218 */
219static inline void outb(u8 data, unsigned long port)
220{
221	writeb(data, _IO_BASE + (port & IO_SPACE_LIMIT));
222}
223
224static inline void outw(u16 data, unsigned long port)
225{
226	writew(data, _IO_BASE + (port & IO_SPACE_LIMIT));
227}
228
229static inline void outl(u32 data, unsigned long port)
230{
231	writel(data, _IO_BASE + (port & IO_SPACE_LIMIT));
232}
233
234#define outb_p outb
235#define outw_p outw
236#define outl_p outl
237
238#define inb_p inb
239#define inw_p inw
240#define inl_p inl
241
242static inline void insb(unsigned long port, void *buffer, int count)
243{
244	if (count) {
245		u8 *buf = buffer;
246		do {
247			u8 x = inb(port);
248			*buf++ = x;
249		} while (--count);
250	}
251}
252
253static inline void insw(unsigned long port, void *buffer, int count)
254{
255	if (count) {
256		u16 *buf = buffer;
257		do {
258			u16 x = inw(port);
259			*buf++ = x;
260		} while (--count);
261	}
262}
263
264static inline void insl(unsigned long port, void *buffer, int count)
265{
266	if (count) {
267		u32 *buf = buffer;
268		do {
269			u32 x = inw(port);
270			*buf++ = x;
271		} while (--count);
272	}
273}
274
275static inline void outsb(unsigned long port, const void *buffer, int count)
276{
277	if (count) {
278		const u8 *buf = buffer;
279		do {
280			outb(*buf++, port);
281		} while (--count);
282	}
283}
284
285static inline void outsw(unsigned long port, const void *buffer, int count)
286{
287	if (count) {
288		const u16 *buf = buffer;
289		do {
290			outw(*buf++, port);
291		} while (--count);
292	}
293}
294
295static inline void outsl(unsigned long port, const void *buffer, int count)
296{
297	if (count) {
298		const u32 *buf = buffer;
299		do {
300			outl(*buf++, port);
301		} while (--count);
302	}
303}
304
305/*
306 * These defines are necessary to use the generic io.h for filling in
307 * the missing parts of the API contract. This is because the platform
308 * uses (inline) functions rather than defines and the generic helper
309 * fills in the undefined.
310 */
311#define virt_to_phys virt_to_phys
312#define phys_to_virt phys_to_virt
313#define memset_io memset_io
314#define memcpy_fromio memcpy_fromio
315#define memcpy_toio memcpy_toio
316#define readb readb
317#define readw readw
318#define readl readl
319#define writeb writeb
320#define writew writew
321#define writel writel
322#define insb insb
323#define insw insw
324#define insl insl
325#define outsb outsb
326#define outsw outsw
327#define outsl outsl
328#include <asm-generic/io.h>
329
330#endif /* __KERNEL__ */
331
332#endif
333