xref: /openbmc/linux/arch/ia64/include/asm/io.h (revision 38d110ab)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
27f30491cSTony Luck #ifndef _ASM_IA64_IO_H
37f30491cSTony Luck #define _ASM_IA64_IO_H
47f30491cSTony Luck 
57f30491cSTony Luck /*
67f30491cSTony Luck  * This file contains the definitions for the emulated IO instructions
77f30491cSTony Luck  * inb/inw/inl/outb/outw/outl and the "string versions" of the same
87f30491cSTony Luck  * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
97f30491cSTony Luck  * versions of the single-IO instructions (inb_p/inw_p/..).
107f30491cSTony Luck  *
117f30491cSTony Luck  * This file is not meant to be obfuscating: it's just complicated to
127f30491cSTony Luck  * (a) handle it all in a way that makes gcc able to optimize it as
137f30491cSTony Luck  * well as possible and (b) trying to avoid writing the same thing
147f30491cSTony Luck  * over and over again with slight variations and possibly making a
157f30491cSTony Luck  * mistake somewhere.
167f30491cSTony Luck  *
177f30491cSTony Luck  * Copyright (C) 1998-2003 Hewlett-Packard Co
187f30491cSTony Luck  *	David Mosberger-Tang <davidm@hpl.hp.com>
197f30491cSTony Luck  * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com>
207f30491cSTony Luck  * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
217f30491cSTony Luck  */
227f30491cSTony Luck 
238a549f8bSJames Bottomley #include <asm/unaligned.h>
2480926770SArd Biesheuvel #include <asm/early_ioremap.h>
258a549f8bSJames Bottomley 
267f30491cSTony Luck #define __IA64_UNCACHED_OFFSET	RGN_BASE(RGN_UNCACHED)
277f30491cSTony Luck 
287f30491cSTony Luck /*
297f30491cSTony Luck  * The legacy I/O space defined by the ia64 architecture supports only 65536 ports, but
307f30491cSTony Luck  * large machines may have multiple other I/O spaces so we can't place any a priori limit
317f30491cSTony Luck  * on IO_SPACE_LIMIT.  These additional spaces are described in ACPI.
327f30491cSTony Luck  */
337f30491cSTony Luck #define IO_SPACE_LIMIT		0xffffffffffffffffUL
347f30491cSTony Luck 
357f30491cSTony Luck #define MAX_IO_SPACES_BITS		8
367f30491cSTony Luck #define MAX_IO_SPACES			(1UL << MAX_IO_SPACES_BITS)
377f30491cSTony Luck #define IO_SPACE_BITS			24
387f30491cSTony Luck #define IO_SPACE_SIZE			(1UL << IO_SPACE_BITS)
397f30491cSTony Luck 
407f30491cSTony Luck #define IO_SPACE_NR(port)		((port) >> IO_SPACE_BITS)
417f30491cSTony Luck #define IO_SPACE_BASE(space)		((space) << IO_SPACE_BITS)
427f30491cSTony Luck #define IO_SPACE_PORT(port)		((port) & (IO_SPACE_SIZE - 1))
437f30491cSTony Luck 
447f30491cSTony Luck #define IO_SPACE_SPARSE_ENCODING(p)	((((p) >> 2) << 12) | ((p) & 0xfff))
457f30491cSTony Luck 
467f30491cSTony Luck struct io_space {
477f30491cSTony Luck 	unsigned long mmio_base;	/* base in MMIO space */
487f30491cSTony Luck 	int sparse;
497f30491cSTony Luck };
507f30491cSTony Luck 
517f30491cSTony Luck extern struct io_space io_space[];
527f30491cSTony Luck extern unsigned int num_io_spaces;
537f30491cSTony Luck 
547f30491cSTony Luck # ifdef __KERNEL__
557f30491cSTony Luck 
567f30491cSTony Luck /*
577f30491cSTony Luck  * All MMIO iomem cookies are in region 6; anything less is a PIO cookie:
587f30491cSTony Luck  *	0xCxxxxxxxxxxxxxxx	MMIO cookie (return from ioremap)
597f30491cSTony Luck  *	0x000000001SPPPPPP	PIO cookie (S=space number, P..P=port)
607f30491cSTony Luck  *
617f30491cSTony Luck  * ioread/writeX() uses the leading 1 in PIO cookies (PIO_OFFSET) to catch
627f30491cSTony Luck  * code that uses bare port numbers without the prerequisite pci_iomap().
637f30491cSTony Luck  */
647f30491cSTony Luck #define PIO_OFFSET		(1UL << (MAX_IO_SPACES_BITS + IO_SPACE_BITS))
657f30491cSTony Luck #define PIO_MASK		(PIO_OFFSET - 1)
667f30491cSTony Luck #define PIO_RESERVED		__IA64_UNCACHED_OFFSET
677f30491cSTony Luck #define HAVE_ARCH_PIO_SIZE
687f30491cSTony Luck 
697f30491cSTony Luck #include <asm/intrinsics.h>
707f30491cSTony Luck #include <asm/page.h>
717f30491cSTony Luck #include <asm-generic/iomap.h>
727f30491cSTony Luck 
737f30491cSTony Luck /*
747f30491cSTony Luck  * Change virtual addresses to physical addresses and vv.
757f30491cSTony Luck  */
767f30491cSTony Luck static inline unsigned long
virt_to_phys(volatile void * address)777f30491cSTony Luck virt_to_phys (volatile void *address)
787f30491cSTony Luck {
797f30491cSTony Luck 	return (unsigned long) address - PAGE_OFFSET;
807f30491cSTony Luck }
810bbf47eaSArnd Bergmann #define virt_to_phys virt_to_phys
827f30491cSTony Luck 
837f30491cSTony Luck static inline void*
phys_to_virt(unsigned long address)847f30491cSTony Luck phys_to_virt (unsigned long address)
857f30491cSTony Luck {
867f30491cSTony Luck 	return (void *) (address + PAGE_OFFSET);
877f30491cSTony Luck }
880bbf47eaSArnd Bergmann #define phys_to_virt phys_to_virt
897f30491cSTony Luck 
907f30491cSTony Luck #define ARCH_HAS_VALID_PHYS_ADDR_RANGE
917f30491cSTony Luck extern u64 kern_mem_attribute (unsigned long phys_addr, unsigned long size);
927e6735c3SCyril Chemparathy extern int valid_phys_addr_range (phys_addr_t addr, size_t count); /* efi.c */
937f30491cSTony Luck extern int valid_mmap_phys_addr_range (unsigned long pfn, size_t count);
947f30491cSTony Luck 
957f30491cSTony Luck # endif /* KERNEL */
967f30491cSTony Luck 
977f30491cSTony Luck /*
987f30491cSTony Luck  * Memory fence w/accept.  This should never be used in code that is
997f30491cSTony Luck  * not IA-64 specific.
1007f30491cSTony Luck  */
1017f30491cSTony Luck #define __ia64_mf_a()	ia64_mfa()
1027f30491cSTony Luck 
1037f30491cSTony Luck static inline void*
__ia64_mk_io_addr(unsigned long port)1047f30491cSTony Luck __ia64_mk_io_addr (unsigned long port)
1057f30491cSTony Luck {
1067f30491cSTony Luck 	struct io_space *space;
1077f30491cSTony Luck 	unsigned long offset;
1087f30491cSTony Luck 
1097f30491cSTony Luck 	space = &io_space[IO_SPACE_NR(port)];
1107f30491cSTony Luck 	port = IO_SPACE_PORT(port);
1117f30491cSTony Luck 	if (space->sparse)
1127f30491cSTony Luck 		offset = IO_SPACE_SPARSE_ENCODING(port);
1137f30491cSTony Luck 	else
1147f30491cSTony Luck 		offset = port;
1157f30491cSTony Luck 
1167f30491cSTony Luck 	return (void *) (space->mmio_base | offset);
1177f30491cSTony Luck }
1187f30491cSTony Luck 
1197f30491cSTony Luck /*
1207f30491cSTony Luck  * For the in/out routines, we need to do "mf.a" _after_ doing the I/O access to ensure
1217f30491cSTony Luck  * that the access has completed before executing other I/O accesses.  Since we're doing
1227f30491cSTony Luck  * the accesses through an uncachable (UC) translation, the CPU will execute them in
1237f30491cSTony Luck  * program order.  However, we still need to tell the compiler not to shuffle them around
1247f30491cSTony Luck  * during optimization, which is why we use "volatile" pointers.
1257f30491cSTony Luck  */
1267f30491cSTony Luck 
12705933aacSChristoph Hellwig #define inb inb
inb(unsigned long port)12805933aacSChristoph Hellwig static inline unsigned int inb(unsigned long port)
1297f30491cSTony Luck {
1307f30491cSTony Luck 	volatile unsigned char *addr = __ia64_mk_io_addr(port);
1317f30491cSTony Luck 	unsigned char ret;
1327f30491cSTony Luck 
1337f30491cSTony Luck 	ret = *addr;
1347f30491cSTony Luck 	__ia64_mf_a();
1357f30491cSTony Luck 	return ret;
1367f30491cSTony Luck }
1377f30491cSTony Luck 
13805933aacSChristoph Hellwig #define inw inw
inw(unsigned long port)13905933aacSChristoph Hellwig static inline unsigned int inw(unsigned long port)
1407f30491cSTony Luck {
1417f30491cSTony Luck 	volatile unsigned short *addr = __ia64_mk_io_addr(port);
1427f30491cSTony Luck 	unsigned short ret;
1437f30491cSTony Luck 
1447f30491cSTony Luck 	ret = *addr;
1457f30491cSTony Luck 	__ia64_mf_a();
1467f30491cSTony Luck 	return ret;
1477f30491cSTony Luck }
1487f30491cSTony Luck 
14905933aacSChristoph Hellwig #define inl inl
inl(unsigned long port)15005933aacSChristoph Hellwig static inline unsigned int inl(unsigned long port)
1517f30491cSTony Luck {
1527f30491cSTony Luck 	volatile unsigned int *addr = __ia64_mk_io_addr(port);
1537f30491cSTony Luck 	unsigned int ret;
1547f30491cSTony Luck 
1557f30491cSTony Luck 	ret = *addr;
1567f30491cSTony Luck 	__ia64_mf_a();
1577f30491cSTony Luck 	return ret;
1587f30491cSTony Luck }
1597f30491cSTony Luck 
16005933aacSChristoph Hellwig #define outb outb
outb(unsigned char val,unsigned long port)16105933aacSChristoph Hellwig static inline void outb(unsigned char val, unsigned long port)
1627f30491cSTony Luck {
1637f30491cSTony Luck 	volatile unsigned char *addr = __ia64_mk_io_addr(port);
1647f30491cSTony Luck 
1657f30491cSTony Luck 	*addr = val;
1667f30491cSTony Luck 	__ia64_mf_a();
1677f30491cSTony Luck }
1687f30491cSTony Luck 
16905933aacSChristoph Hellwig #define outw outw
outw(unsigned short val,unsigned long port)17005933aacSChristoph Hellwig static inline void outw(unsigned short val, unsigned long port)
1717f30491cSTony Luck {
1727f30491cSTony Luck 	volatile unsigned short *addr = __ia64_mk_io_addr(port);
1737f30491cSTony Luck 
1747f30491cSTony Luck 	*addr = val;
1757f30491cSTony Luck 	__ia64_mf_a();
1767f30491cSTony Luck }
1777f30491cSTony Luck 
17805933aacSChristoph Hellwig #define outl outl
outl(unsigned int val,unsigned long port)17905933aacSChristoph Hellwig static inline void outl(unsigned int val, unsigned long port)
1807f30491cSTony Luck {
1817f30491cSTony Luck 	volatile unsigned int *addr = __ia64_mk_io_addr(port);
1827f30491cSTony Luck 
1837f30491cSTony Luck 	*addr = val;
1847f30491cSTony Luck 	__ia64_mf_a();
1857f30491cSTony Luck }
1867f30491cSTony Luck 
18705933aacSChristoph Hellwig #define insb insb
insb(unsigned long port,void * dst,unsigned long count)18805933aacSChristoph Hellwig static inline void insb(unsigned long port, void *dst, unsigned long count)
1897f30491cSTony Luck {
1907f30491cSTony Luck 	unsigned char *dp = dst;
1917f30491cSTony Luck 
1927f30491cSTony Luck 	while (count--)
19305933aacSChristoph Hellwig 		*dp++ = inb(port);
1947f30491cSTony Luck }
1957f30491cSTony Luck 
19605933aacSChristoph Hellwig #define insw insw
insw(unsigned long port,void * dst,unsigned long count)19705933aacSChristoph Hellwig static inline void insw(unsigned long port, void *dst, unsigned long count)
1987f30491cSTony Luck {
1997f30491cSTony Luck 	unsigned short *dp = dst;
2007f30491cSTony Luck 
2017f30491cSTony Luck 	while (count--)
20205933aacSChristoph Hellwig 		put_unaligned(inw(port), dp++);
2037f30491cSTony Luck }
2047f30491cSTony Luck 
20505933aacSChristoph Hellwig #define insl insl
insl(unsigned long port,void * dst,unsigned long count)20605933aacSChristoph Hellwig static inline void insl(unsigned long port, void *dst, unsigned long count)
2077f30491cSTony Luck {
2087f30491cSTony Luck 	unsigned int *dp = dst;
2097f30491cSTony Luck 
2107f30491cSTony Luck 	while (count--)
21105933aacSChristoph Hellwig 		put_unaligned(inl(port), dp++);
2127f30491cSTony Luck }
2137f30491cSTony Luck 
21405933aacSChristoph Hellwig #define outsb outsb
outsb(unsigned long port,const void * src,unsigned long count)21505933aacSChristoph Hellwig static inline void outsb(unsigned long port, const void *src,
21605933aacSChristoph Hellwig 		unsigned long count)
2177f30491cSTony Luck {
2187f30491cSTony Luck 	const unsigned char *sp = src;
2197f30491cSTony Luck 
2207f30491cSTony Luck 	while (count--)
22105933aacSChristoph Hellwig 		outb(*sp++, port);
2227f30491cSTony Luck }
2237f30491cSTony Luck 
22405933aacSChristoph Hellwig #define outsw outsw
outsw(unsigned long port,const void * src,unsigned long count)22505933aacSChristoph Hellwig static inline void outsw(unsigned long port, const void *src,
22605933aacSChristoph Hellwig 		unsigned long count)
2277f30491cSTony Luck {
2287f30491cSTony Luck 	const unsigned short *sp = src;
2297f30491cSTony Luck 
2307f30491cSTony Luck 	while (count--)
23105933aacSChristoph Hellwig 		outw(get_unaligned(sp++), port);
2327f30491cSTony Luck }
2337f30491cSTony Luck 
23405933aacSChristoph Hellwig #define outsl outsl
outsl(unsigned long port,const void * src,unsigned long count)23505933aacSChristoph Hellwig static inline void outsl(unsigned long port, const void *src,
23605933aacSChristoph Hellwig 		unsigned long count)
2377f30491cSTony Luck {
2387f30491cSTony Luck 	const unsigned int *sp = src;
2397f30491cSTony Luck 
2407f30491cSTony Luck 	while (count--)
24105933aacSChristoph Hellwig 		outl(get_unaligned(sp++), port);
2427f30491cSTony Luck }
2437f30491cSTony Luck 
2447f30491cSTony Luck # ifdef __KERNEL__
2457f30491cSTony Luck 
246*38d110abSBaoquan He #define _PAGE_IOREMAP pgprot_val(PAGE_KERNEL)
247*38d110abSBaoquan He 
248fded1829SChristoph Hellwig extern void __iomem * ioremap_uc(unsigned long offset, unsigned long size);
249*38d110abSBaoquan He 
250*38d110abSBaoquan He #define ioremap_prot ioremap_prot
251*38d110abSBaoquan He #define ioremap_cache ioremap
252fded1829SChristoph Hellwig #define ioremap_uc ioremap_uc
2530bbf47eaSArnd Bergmann #define iounmap iounmap
2547f30491cSTony Luck 
2557f30491cSTony Luck /*
2567f30491cSTony Luck  * String version of IO memory access ops:
2577f30491cSTony Luck  */
2587f30491cSTony Luck extern void memcpy_fromio(void *dst, const volatile void __iomem *src, long n);
2597f30491cSTony Luck extern void memcpy_toio(volatile void __iomem *dst, const void *src, long n);
2607f30491cSTony Luck extern void memset_io(volatile void __iomem *s, int c, long n);
2617f30491cSTony Luck 
2620bbf47eaSArnd Bergmann #define memcpy_fromio memcpy_fromio
2630bbf47eaSArnd Bergmann #define memcpy_toio memcpy_toio
2640bbf47eaSArnd Bergmann #define memset_io memset_io
2650bbf47eaSArnd Bergmann #define xlate_dev_mem_ptr xlate_dev_mem_ptr
2660bbf47eaSArnd Bergmann #include <asm-generic/io.h>
267cc26ebbeSTony Luck #undef PCI_IOBASE
2680bbf47eaSArnd Bergmann 
2697f30491cSTony Luck # endif /* __KERNEL__ */
2707f30491cSTony Luck 
2717f30491cSTony Luck #endif /* _ASM_IA64_IO_H */
272