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