162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public
362306a36Sopenharmony_ci * License.  See the file "COPYING" in the main directory of this archive
462306a36Sopenharmony_ci * for more details.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 1994, 1995 Waldorf GmbH
762306a36Sopenharmony_ci * Copyright (C) 1994 - 2000, 06 Ralf Baechle
862306a36Sopenharmony_ci * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
962306a36Sopenharmony_ci * Copyright (C) 2004, 2005  MIPS Technologies, Inc.  All rights reserved.
1062306a36Sopenharmony_ci *	Author: Maciej W. Rozycki <macro@mips.com>
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci#ifndef _ASM_IO_H
1362306a36Sopenharmony_ci#define _ASM_IO_H
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/compiler.h>
1662306a36Sopenharmony_ci#include <linux/kernel.h>
1762306a36Sopenharmony_ci#include <linux/types.h>
1862306a36Sopenharmony_ci#include <linux/irqflags.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include <asm/addrspace.h>
2162306a36Sopenharmony_ci#include <asm/barrier.h>
2262306a36Sopenharmony_ci#include <asm/bug.h>
2362306a36Sopenharmony_ci#include <asm/byteorder.h>
2462306a36Sopenharmony_ci#include <asm/cpu.h>
2562306a36Sopenharmony_ci#include <asm/cpu-features.h>
2662306a36Sopenharmony_ci#include <asm/page.h>
2762306a36Sopenharmony_ci#include <asm/pgtable-bits.h>
2862306a36Sopenharmony_ci#include <asm/processor.h>
2962306a36Sopenharmony_ci#include <asm/string.h>
3062306a36Sopenharmony_ci#include <mangle-port.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/*
3362306a36Sopenharmony_ci * Raw operations are never swapped in software.  OTOH values that raw
3462306a36Sopenharmony_ci * operations are working on may or may not have been swapped by the bus
3562306a36Sopenharmony_ci * hardware.  An example use would be for flash memory that's used for
3662306a36Sopenharmony_ci * execute in place.
3762306a36Sopenharmony_ci */
3862306a36Sopenharmony_ci# define __raw_ioswabb(a, x)	(x)
3962306a36Sopenharmony_ci# define __raw_ioswabw(a, x)	(x)
4062306a36Sopenharmony_ci# define __raw_ioswabl(a, x)	(x)
4162306a36Sopenharmony_ci# define __raw_ioswabq(a, x)	(x)
4262306a36Sopenharmony_ci# define ____raw_ioswabq(a, x)	(x)
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci# define __relaxed_ioswabb ioswabb
4562306a36Sopenharmony_ci# define __relaxed_ioswabw ioswabw
4662306a36Sopenharmony_ci# define __relaxed_ioswabl ioswabl
4762306a36Sopenharmony_ci# define __relaxed_ioswabq ioswabq
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/* ioswab[bwlq], __mem_ioswab[bwlq] are defined in mangle-port.h */
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/*
5262306a36Sopenharmony_ci * On MIPS I/O ports are memory mapped, so we access them using normal
5362306a36Sopenharmony_ci * load/store instructions. mips_io_port_base is the virtual address to
5462306a36Sopenharmony_ci * which all ports are being mapped.  For sake of efficiency some code
5562306a36Sopenharmony_ci * assumes that this is an address that can be loaded with a single lui
5662306a36Sopenharmony_ci * instruction, so the lower 16 bits must be zero.  Should be true on
5762306a36Sopenharmony_ci * any sane architecture; generic code does not use this assumption.
5862306a36Sopenharmony_ci */
5962306a36Sopenharmony_ciextern unsigned long mips_io_port_base;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic inline void set_io_port_base(unsigned long base)
6262306a36Sopenharmony_ci{
6362306a36Sopenharmony_ci	mips_io_port_base = base;
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci/*
6762306a36Sopenharmony_ci * Provide the necessary definitions for generic iomap. We make use of
6862306a36Sopenharmony_ci * mips_io_port_base for iomap(), but we don't reserve any low addresses for
6962306a36Sopenharmony_ci * use with I/O ports.
7062306a36Sopenharmony_ci */
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci#define HAVE_ARCH_PIO_SIZE
7362306a36Sopenharmony_ci#define PIO_OFFSET	mips_io_port_base
7462306a36Sopenharmony_ci#define PIO_MASK	IO_SPACE_LIMIT
7562306a36Sopenharmony_ci#define PIO_RESERVED	0x0UL
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/*
7862306a36Sopenharmony_ci * Enforce in-order execution of data I/O.  In the MIPS architecture
7962306a36Sopenharmony_ci * these are equivalent to corresponding platform-specific memory
8062306a36Sopenharmony_ci * barriers defined in <asm/barrier.h>.  API pinched from PowerPC,
8162306a36Sopenharmony_ci * with sync additionally defined.
8262306a36Sopenharmony_ci */
8362306a36Sopenharmony_ci#define iobarrier_rw() mb()
8462306a36Sopenharmony_ci#define iobarrier_r() rmb()
8562306a36Sopenharmony_ci#define iobarrier_w() wmb()
8662306a36Sopenharmony_ci#define iobarrier_sync() iob()
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci/*
8962306a36Sopenharmony_ci *     virt_to_phys    -       map virtual addresses to physical
9062306a36Sopenharmony_ci *     @address: address to remap
9162306a36Sopenharmony_ci *
9262306a36Sopenharmony_ci *     The returned physical address is the physical (CPU) mapping for
9362306a36Sopenharmony_ci *     the memory address given. It is only valid to use this function on
9462306a36Sopenharmony_ci *     addresses directly mapped or allocated via kmalloc.
9562306a36Sopenharmony_ci *
9662306a36Sopenharmony_ci *     This function does not give bus mappings for DMA transfers. In
9762306a36Sopenharmony_ci *     almost all conceivable cases a device driver should not be using
9862306a36Sopenharmony_ci *     this function
9962306a36Sopenharmony_ci */
10062306a36Sopenharmony_cistatic inline unsigned long __virt_to_phys_nodebug(volatile const void *address)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	return __pa(address);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_VIRTUAL
10662306a36Sopenharmony_ciextern phys_addr_t __virt_to_phys(volatile const void *x);
10762306a36Sopenharmony_ci#else
10862306a36Sopenharmony_ci#define __virt_to_phys(x)	__virt_to_phys_nodebug(x)
10962306a36Sopenharmony_ci#endif
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci#define virt_to_phys virt_to_phys
11262306a36Sopenharmony_cistatic inline phys_addr_t virt_to_phys(const volatile void *x)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	return __virt_to_phys(x);
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci/*
11862306a36Sopenharmony_ci *     phys_to_virt    -       map physical address to virtual
11962306a36Sopenharmony_ci *     @address: address to remap
12062306a36Sopenharmony_ci *
12162306a36Sopenharmony_ci *     The returned virtual address is a current CPU mapping for
12262306a36Sopenharmony_ci *     the memory address given. It is only valid to use this function on
12362306a36Sopenharmony_ci *     addresses that have a kernel mapping
12462306a36Sopenharmony_ci *
12562306a36Sopenharmony_ci *     This function does not handle bus mappings for DMA transfers. In
12662306a36Sopenharmony_ci *     almost all conceivable cases a device driver should not be using
12762306a36Sopenharmony_ci *     this function
12862306a36Sopenharmony_ci */
12962306a36Sopenharmony_cistatic inline void * phys_to_virt(unsigned long address)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	return __va(address);
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci/*
13562306a36Sopenharmony_ci * ISA I/O bus memory addresses are 1:1 with the physical address.
13662306a36Sopenharmony_ci */
13762306a36Sopenharmony_cistatic inline unsigned long isa_virt_to_bus(volatile void *address)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	return virt_to_phys(address);
14062306a36Sopenharmony_ci}
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic inline void *isa_bus_to_virt(unsigned long address)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	return phys_to_virt(address);
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci/*
14862306a36Sopenharmony_ci * Change "struct page" to physical address.
14962306a36Sopenharmony_ci */
15062306a36Sopenharmony_ci#define page_to_phys(page)	((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_civoid __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
15362306a36Sopenharmony_ci		unsigned long prot_val);
15462306a36Sopenharmony_civoid iounmap(const volatile void __iomem *addr);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci/*
15762306a36Sopenharmony_ci * ioremap     -   map bus memory into CPU space
15862306a36Sopenharmony_ci * @offset:    bus address of the memory
15962306a36Sopenharmony_ci * @size:      size of the resource to map
16062306a36Sopenharmony_ci *
16162306a36Sopenharmony_ci * ioremap performs a platform specific sequence of operations to
16262306a36Sopenharmony_ci * make bus memory CPU accessible via the readb/readw/readl/writeb/
16362306a36Sopenharmony_ci * writew/writel functions and the other mmio helpers. The returned
16462306a36Sopenharmony_ci * address is not guaranteed to be usable directly as a virtual
16562306a36Sopenharmony_ci * address.
16662306a36Sopenharmony_ci */
16762306a36Sopenharmony_ci#define ioremap(offset, size)						\
16862306a36Sopenharmony_ci	ioremap_prot((offset), (size), _CACHE_UNCACHED)
16962306a36Sopenharmony_ci#define ioremap_uc		ioremap
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci/*
17262306a36Sopenharmony_ci * ioremap_cache -	map bus memory into CPU space
17362306a36Sopenharmony_ci * @offset:	    bus address of the memory
17462306a36Sopenharmony_ci * @size:	    size of the resource to map
17562306a36Sopenharmony_ci *
17662306a36Sopenharmony_ci * ioremap_cache performs a platform specific sequence of operations to
17762306a36Sopenharmony_ci * make bus memory CPU accessible via the readb/readw/readl/writeb/
17862306a36Sopenharmony_ci * writew/writel functions and the other mmio helpers. The returned
17962306a36Sopenharmony_ci * address is not guaranteed to be usable directly as a virtual
18062306a36Sopenharmony_ci * address.
18162306a36Sopenharmony_ci *
18262306a36Sopenharmony_ci * This version of ioremap ensures that the memory is marked cachable by
18362306a36Sopenharmony_ci * the CPU.  Also enables full write-combining.	 Useful for some
18462306a36Sopenharmony_ci * memory-like regions on I/O busses.
18562306a36Sopenharmony_ci */
18662306a36Sopenharmony_ci#define ioremap_cache(offset, size)					\
18762306a36Sopenharmony_ci	ioremap_prot((offset), (size), _page_cachable_default)
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci/*
19062306a36Sopenharmony_ci * ioremap_wc     -   map bus memory into CPU space
19162306a36Sopenharmony_ci * @offset:    bus address of the memory
19262306a36Sopenharmony_ci * @size:      size of the resource to map
19362306a36Sopenharmony_ci *
19462306a36Sopenharmony_ci * ioremap_wc performs a platform specific sequence of operations to
19562306a36Sopenharmony_ci * make bus memory CPU accessible via the readb/readw/readl/writeb/
19662306a36Sopenharmony_ci * writew/writel functions and the other mmio helpers. The returned
19762306a36Sopenharmony_ci * address is not guaranteed to be usable directly as a virtual
19862306a36Sopenharmony_ci * address.
19962306a36Sopenharmony_ci *
20062306a36Sopenharmony_ci * This version of ioremap ensures that the memory is marked uncachable
20162306a36Sopenharmony_ci * but accelerated by means of write-combining feature. It is specifically
20262306a36Sopenharmony_ci * useful for PCIe prefetchable windows, which may vastly improve a
20362306a36Sopenharmony_ci * communications performance. If it was determined on boot stage, what
20462306a36Sopenharmony_ci * CPU CCA doesn't support UCA, the method shall fall-back to the
20562306a36Sopenharmony_ci * _CACHE_UNCACHED option (see cpu_probe() method).
20662306a36Sopenharmony_ci */
20762306a36Sopenharmony_ci#define ioremap_wc(offset, size)					\
20862306a36Sopenharmony_ci	ioremap_prot((offset), (size), boot_cpu_data.writecombine)
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci#include <asm-generic/iomap.h>
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci#if defined(CONFIG_CPU_CAVIUM_OCTEON)
21362306a36Sopenharmony_ci#define war_io_reorder_wmb()		wmb()
21462306a36Sopenharmony_ci#else
21562306a36Sopenharmony_ci#define war_io_reorder_wmb()		barrier()
21662306a36Sopenharmony_ci#endif
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci#define __BUILD_MEMORY_SINGLE(pfx, bwlq, type, barrier, relax, irq)	\
21962306a36Sopenharmony_ci									\
22062306a36Sopenharmony_cistatic inline void pfx##write##bwlq(type val,				\
22162306a36Sopenharmony_ci				    volatile void __iomem *mem)		\
22262306a36Sopenharmony_ci{									\
22362306a36Sopenharmony_ci	volatile type *__mem;						\
22462306a36Sopenharmony_ci	type __val;							\
22562306a36Sopenharmony_ci									\
22662306a36Sopenharmony_ci	if (barrier)							\
22762306a36Sopenharmony_ci		iobarrier_rw();						\
22862306a36Sopenharmony_ci	else								\
22962306a36Sopenharmony_ci		war_io_reorder_wmb();					\
23062306a36Sopenharmony_ci									\
23162306a36Sopenharmony_ci	__mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem));	\
23262306a36Sopenharmony_ci									\
23362306a36Sopenharmony_ci	__val = pfx##ioswab##bwlq(__mem, val);				\
23462306a36Sopenharmony_ci									\
23562306a36Sopenharmony_ci	if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) \
23662306a36Sopenharmony_ci		*__mem = __val;						\
23762306a36Sopenharmony_ci	else if (cpu_has_64bits) {					\
23862306a36Sopenharmony_ci		unsigned long __flags;					\
23962306a36Sopenharmony_ci		type __tmp;						\
24062306a36Sopenharmony_ci									\
24162306a36Sopenharmony_ci		if (irq)						\
24262306a36Sopenharmony_ci			local_irq_save(__flags);			\
24362306a36Sopenharmony_ci		__asm__ __volatile__(					\
24462306a36Sopenharmony_ci			".set	push"		"\t\t# __writeq""\n\t"	\
24562306a36Sopenharmony_ci			".set	arch=r4000"			"\n\t"	\
24662306a36Sopenharmony_ci			"dsll32 %L0, %L0, 0"			"\n\t"	\
24762306a36Sopenharmony_ci			"dsrl32 %L0, %L0, 0"			"\n\t"	\
24862306a36Sopenharmony_ci			"dsll32 %M0, %M0, 0"			"\n\t"	\
24962306a36Sopenharmony_ci			"or	%L0, %L0, %M0"			"\n\t"	\
25062306a36Sopenharmony_ci			"sd	%L0, %2"			"\n\t"	\
25162306a36Sopenharmony_ci			".set	pop"				"\n"	\
25262306a36Sopenharmony_ci			: "=r" (__tmp)					\
25362306a36Sopenharmony_ci			: "0" (__val), "m" (*__mem));			\
25462306a36Sopenharmony_ci		if (irq)						\
25562306a36Sopenharmony_ci			local_irq_restore(__flags);			\
25662306a36Sopenharmony_ci	} else								\
25762306a36Sopenharmony_ci		BUG();							\
25862306a36Sopenharmony_ci}									\
25962306a36Sopenharmony_ci									\
26062306a36Sopenharmony_cistatic inline type pfx##read##bwlq(const volatile void __iomem *mem)	\
26162306a36Sopenharmony_ci{									\
26262306a36Sopenharmony_ci	volatile type *__mem;						\
26362306a36Sopenharmony_ci	type __val;							\
26462306a36Sopenharmony_ci									\
26562306a36Sopenharmony_ci	__mem = (void *)__swizzle_addr_##bwlq((unsigned long)(mem));	\
26662306a36Sopenharmony_ci									\
26762306a36Sopenharmony_ci	if (barrier)							\
26862306a36Sopenharmony_ci		iobarrier_rw();						\
26962306a36Sopenharmony_ci									\
27062306a36Sopenharmony_ci	if (sizeof(type) != sizeof(u64) || sizeof(u64) == sizeof(long)) \
27162306a36Sopenharmony_ci		__val = *__mem;						\
27262306a36Sopenharmony_ci	else if (cpu_has_64bits) {					\
27362306a36Sopenharmony_ci		unsigned long __flags;					\
27462306a36Sopenharmony_ci									\
27562306a36Sopenharmony_ci		if (irq)						\
27662306a36Sopenharmony_ci			local_irq_save(__flags);			\
27762306a36Sopenharmony_ci		__asm__ __volatile__(					\
27862306a36Sopenharmony_ci			".set	push"		"\t\t# __readq" "\n\t"	\
27962306a36Sopenharmony_ci			".set	arch=r4000"			"\n\t"	\
28062306a36Sopenharmony_ci			"ld	%L0, %1"			"\n\t"	\
28162306a36Sopenharmony_ci			"dsra32 %M0, %L0, 0"			"\n\t"	\
28262306a36Sopenharmony_ci			"sll	%L0, %L0, 0"			"\n\t"	\
28362306a36Sopenharmony_ci			".set	pop"				"\n"	\
28462306a36Sopenharmony_ci			: "=r" (__val)					\
28562306a36Sopenharmony_ci			: "m" (*__mem));				\
28662306a36Sopenharmony_ci		if (irq)						\
28762306a36Sopenharmony_ci			local_irq_restore(__flags);			\
28862306a36Sopenharmony_ci	} else {							\
28962306a36Sopenharmony_ci		__val = 0;						\
29062306a36Sopenharmony_ci		BUG();							\
29162306a36Sopenharmony_ci	}								\
29262306a36Sopenharmony_ci									\
29362306a36Sopenharmony_ci	/* prevent prefetching of coherent DMA data prematurely */	\
29462306a36Sopenharmony_ci	if (!relax)							\
29562306a36Sopenharmony_ci		rmb();							\
29662306a36Sopenharmony_ci	return pfx##ioswab##bwlq(__mem, __val);				\
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci#define __BUILD_IOPORT_SINGLE(pfx, bwlq, type, barrier, relax, p)	\
30062306a36Sopenharmony_ci									\
30162306a36Sopenharmony_cistatic inline void pfx##out##bwlq##p(type val, unsigned long port)	\
30262306a36Sopenharmony_ci{									\
30362306a36Sopenharmony_ci	volatile type *__addr;						\
30462306a36Sopenharmony_ci	type __val;							\
30562306a36Sopenharmony_ci									\
30662306a36Sopenharmony_ci	if (barrier)							\
30762306a36Sopenharmony_ci		iobarrier_rw();						\
30862306a36Sopenharmony_ci	else								\
30962306a36Sopenharmony_ci		war_io_reorder_wmb();					\
31062306a36Sopenharmony_ci									\
31162306a36Sopenharmony_ci	__addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \
31262306a36Sopenharmony_ci									\
31362306a36Sopenharmony_ci	__val = pfx##ioswab##bwlq(__addr, val);				\
31462306a36Sopenharmony_ci									\
31562306a36Sopenharmony_ci	/* Really, we want this to be atomic */				\
31662306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long));		\
31762306a36Sopenharmony_ci									\
31862306a36Sopenharmony_ci	*__addr = __val;						\
31962306a36Sopenharmony_ci}									\
32062306a36Sopenharmony_ci									\
32162306a36Sopenharmony_cistatic inline type pfx##in##bwlq##p(unsigned long port)			\
32262306a36Sopenharmony_ci{									\
32362306a36Sopenharmony_ci	volatile type *__addr;						\
32462306a36Sopenharmony_ci	type __val;							\
32562306a36Sopenharmony_ci									\
32662306a36Sopenharmony_ci	__addr = (void *)__swizzle_addr_##bwlq(mips_io_port_base + port); \
32762306a36Sopenharmony_ci									\
32862306a36Sopenharmony_ci	BUILD_BUG_ON(sizeof(type) > sizeof(unsigned long));		\
32962306a36Sopenharmony_ci									\
33062306a36Sopenharmony_ci	if (barrier)							\
33162306a36Sopenharmony_ci		iobarrier_rw();						\
33262306a36Sopenharmony_ci									\
33362306a36Sopenharmony_ci	__val = *__addr;						\
33462306a36Sopenharmony_ci									\
33562306a36Sopenharmony_ci	/* prevent prefetching of coherent DMA data prematurely */	\
33662306a36Sopenharmony_ci	if (!relax)							\
33762306a36Sopenharmony_ci		rmb();							\
33862306a36Sopenharmony_ci	return pfx##ioswab##bwlq(__addr, __val);			\
33962306a36Sopenharmony_ci}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci#define __BUILD_MEMORY_PFX(bus, bwlq, type, relax)			\
34262306a36Sopenharmony_ci									\
34362306a36Sopenharmony_ci__BUILD_MEMORY_SINGLE(bus, bwlq, type, 1, relax, 1)
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci#define BUILDIO_MEM(bwlq, type)						\
34662306a36Sopenharmony_ci									\
34762306a36Sopenharmony_ci__BUILD_MEMORY_PFX(__raw_, bwlq, type, 0)				\
34862306a36Sopenharmony_ci__BUILD_MEMORY_PFX(__relaxed_, bwlq, type, 1)				\
34962306a36Sopenharmony_ci__BUILD_MEMORY_PFX(__mem_, bwlq, type, 0)				\
35062306a36Sopenharmony_ci__BUILD_MEMORY_PFX(, bwlq, type, 0)
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ciBUILDIO_MEM(b, u8)
35362306a36Sopenharmony_ciBUILDIO_MEM(w, u16)
35462306a36Sopenharmony_ciBUILDIO_MEM(l, u32)
35562306a36Sopenharmony_ci#ifdef CONFIG_64BIT
35662306a36Sopenharmony_ciBUILDIO_MEM(q, u64)
35762306a36Sopenharmony_ci#else
35862306a36Sopenharmony_ci__BUILD_MEMORY_PFX(__raw_, q, u64, 0)
35962306a36Sopenharmony_ci__BUILD_MEMORY_PFX(__mem_, q, u64, 0)
36062306a36Sopenharmony_ci#endif
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci#define __BUILD_IOPORT_PFX(bus, bwlq, type)				\
36362306a36Sopenharmony_ci	__BUILD_IOPORT_SINGLE(bus, bwlq, type, 1, 0,)			\
36462306a36Sopenharmony_ci	__BUILD_IOPORT_SINGLE(bus, bwlq, type, 1, 0, _p)
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci#define BUILDIO_IOPORT(bwlq, type)					\
36762306a36Sopenharmony_ci	__BUILD_IOPORT_PFX(, bwlq, type)				\
36862306a36Sopenharmony_ci	__BUILD_IOPORT_PFX(__mem_, bwlq, type)
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ciBUILDIO_IOPORT(b, u8)
37162306a36Sopenharmony_ciBUILDIO_IOPORT(w, u16)
37262306a36Sopenharmony_ciBUILDIO_IOPORT(l, u32)
37362306a36Sopenharmony_ci#ifdef CONFIG_64BIT
37462306a36Sopenharmony_ciBUILDIO_IOPORT(q, u64)
37562306a36Sopenharmony_ci#endif
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci#define __BUILDIO(bwlq, type)						\
37862306a36Sopenharmony_ci									\
37962306a36Sopenharmony_ci__BUILD_MEMORY_SINGLE(____raw_, bwlq, type, 1, 0, 0)
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci__BUILDIO(q, u64)
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci#define readb_relaxed			__relaxed_readb
38462306a36Sopenharmony_ci#define readw_relaxed			__relaxed_readw
38562306a36Sopenharmony_ci#define readl_relaxed			__relaxed_readl
38662306a36Sopenharmony_ci#ifdef CONFIG_64BIT
38762306a36Sopenharmony_ci#define readq_relaxed			__relaxed_readq
38862306a36Sopenharmony_ci#endif
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci#define writeb_relaxed			__relaxed_writeb
39162306a36Sopenharmony_ci#define writew_relaxed			__relaxed_writew
39262306a36Sopenharmony_ci#define writel_relaxed			__relaxed_writel
39362306a36Sopenharmony_ci#ifdef CONFIG_64BIT
39462306a36Sopenharmony_ci#define writeq_relaxed			__relaxed_writeq
39562306a36Sopenharmony_ci#endif
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci#define readb_be(addr)							\
39862306a36Sopenharmony_ci	__raw_readb((__force unsigned *)(addr))
39962306a36Sopenharmony_ci#define readw_be(addr)							\
40062306a36Sopenharmony_ci	be16_to_cpu(__raw_readw((__force unsigned *)(addr)))
40162306a36Sopenharmony_ci#define readl_be(addr)							\
40262306a36Sopenharmony_ci	be32_to_cpu(__raw_readl((__force unsigned *)(addr)))
40362306a36Sopenharmony_ci#define readq_be(addr)							\
40462306a36Sopenharmony_ci	be64_to_cpu(__raw_readq((__force unsigned *)(addr)))
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci#define writeb_be(val, addr)						\
40762306a36Sopenharmony_ci	__raw_writeb((val), (__force unsigned *)(addr))
40862306a36Sopenharmony_ci#define writew_be(val, addr)						\
40962306a36Sopenharmony_ci	__raw_writew(cpu_to_be16((val)), (__force unsigned *)(addr))
41062306a36Sopenharmony_ci#define writel_be(val, addr)						\
41162306a36Sopenharmony_ci	__raw_writel(cpu_to_be32((val)), (__force unsigned *)(addr))
41262306a36Sopenharmony_ci#define writeq_be(val, addr)						\
41362306a36Sopenharmony_ci	__raw_writeq(cpu_to_be64((val)), (__force unsigned *)(addr))
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci/*
41662306a36Sopenharmony_ci * Some code tests for these symbols
41762306a36Sopenharmony_ci */
41862306a36Sopenharmony_ci#ifdef CONFIG_64BIT
41962306a36Sopenharmony_ci#define readq				readq
42062306a36Sopenharmony_ci#define writeq				writeq
42162306a36Sopenharmony_ci#endif
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci#define __BUILD_MEMORY_STRING(bwlq, type)				\
42462306a36Sopenharmony_ci									\
42562306a36Sopenharmony_cistatic inline void writes##bwlq(volatile void __iomem *mem,		\
42662306a36Sopenharmony_ci				const void *addr, unsigned int count)	\
42762306a36Sopenharmony_ci{									\
42862306a36Sopenharmony_ci	const volatile type *__addr = addr;				\
42962306a36Sopenharmony_ci									\
43062306a36Sopenharmony_ci	while (count--) {						\
43162306a36Sopenharmony_ci		__mem_write##bwlq(*__addr, mem);			\
43262306a36Sopenharmony_ci		__addr++;						\
43362306a36Sopenharmony_ci	}								\
43462306a36Sopenharmony_ci}									\
43562306a36Sopenharmony_ci									\
43662306a36Sopenharmony_cistatic inline void reads##bwlq(volatile void __iomem *mem, void *addr,	\
43762306a36Sopenharmony_ci			       unsigned int count)			\
43862306a36Sopenharmony_ci{									\
43962306a36Sopenharmony_ci	volatile type *__addr = addr;					\
44062306a36Sopenharmony_ci									\
44162306a36Sopenharmony_ci	while (count--) {						\
44262306a36Sopenharmony_ci		*__addr = __mem_read##bwlq(mem);			\
44362306a36Sopenharmony_ci		__addr++;						\
44462306a36Sopenharmony_ci	}								\
44562306a36Sopenharmony_ci}
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci#define __BUILD_IOPORT_STRING(bwlq, type)				\
44862306a36Sopenharmony_ci									\
44962306a36Sopenharmony_cistatic inline void outs##bwlq(unsigned long port, const void *addr,	\
45062306a36Sopenharmony_ci			      unsigned int count)			\
45162306a36Sopenharmony_ci{									\
45262306a36Sopenharmony_ci	const volatile type *__addr = addr;				\
45362306a36Sopenharmony_ci									\
45462306a36Sopenharmony_ci	while (count--) {						\
45562306a36Sopenharmony_ci		__mem_out##bwlq(*__addr, port);				\
45662306a36Sopenharmony_ci		__addr++;						\
45762306a36Sopenharmony_ci	}								\
45862306a36Sopenharmony_ci}									\
45962306a36Sopenharmony_ci									\
46062306a36Sopenharmony_cistatic inline void ins##bwlq(unsigned long port, void *addr,		\
46162306a36Sopenharmony_ci			     unsigned int count)			\
46262306a36Sopenharmony_ci{									\
46362306a36Sopenharmony_ci	volatile type *__addr = addr;					\
46462306a36Sopenharmony_ci									\
46562306a36Sopenharmony_ci	while (count--) {						\
46662306a36Sopenharmony_ci		*__addr = __mem_in##bwlq(port);				\
46762306a36Sopenharmony_ci		__addr++;						\
46862306a36Sopenharmony_ci	}								\
46962306a36Sopenharmony_ci}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci#define BUILDSTRING(bwlq, type)						\
47262306a36Sopenharmony_ci									\
47362306a36Sopenharmony_ci__BUILD_MEMORY_STRING(bwlq, type)					\
47462306a36Sopenharmony_ci__BUILD_IOPORT_STRING(bwlq, type)
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ciBUILDSTRING(b, u8)
47762306a36Sopenharmony_ciBUILDSTRING(w, u16)
47862306a36Sopenharmony_ciBUILDSTRING(l, u32)
47962306a36Sopenharmony_ci#ifdef CONFIG_64BIT
48062306a36Sopenharmony_ciBUILDSTRING(q, u64)
48162306a36Sopenharmony_ci#endif
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic inline void memset_io(volatile void __iomem *addr, unsigned char val, int count)
48462306a36Sopenharmony_ci{
48562306a36Sopenharmony_ci	memset((void __force *) addr, val, count);
48662306a36Sopenharmony_ci}
48762306a36Sopenharmony_cistatic inline void memcpy_fromio(void *dst, const volatile void __iomem *src, int count)
48862306a36Sopenharmony_ci{
48962306a36Sopenharmony_ci	memcpy(dst, (void __force *) src, count);
49062306a36Sopenharmony_ci}
49162306a36Sopenharmony_cistatic inline void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
49262306a36Sopenharmony_ci{
49362306a36Sopenharmony_ci	memcpy((void __force *) dst, src, count);
49462306a36Sopenharmony_ci}
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci/*
49762306a36Sopenharmony_ci * The caches on some architectures aren't dma-coherent and have need to
49862306a36Sopenharmony_ci * handle this in software.  There are three types of operations that
49962306a36Sopenharmony_ci * can be applied to dma buffers.
50062306a36Sopenharmony_ci *
50162306a36Sopenharmony_ci *  - dma_cache_wback_inv(start, size) makes caches and coherent by
50262306a36Sopenharmony_ci *    writing the content of the caches back to memory, if necessary.
50362306a36Sopenharmony_ci *    The function also invalidates the affected part of the caches as
50462306a36Sopenharmony_ci *    necessary before DMA transfers from outside to memory.
50562306a36Sopenharmony_ci *  - dma_cache_wback(start, size) makes caches and coherent by
50662306a36Sopenharmony_ci *    writing the content of the caches back to memory, if necessary.
50762306a36Sopenharmony_ci *    The function also invalidates the affected part of the caches as
50862306a36Sopenharmony_ci *    necessary before DMA transfers from outside to memory.
50962306a36Sopenharmony_ci *  - dma_cache_inv(start, size) invalidates the affected parts of the
51062306a36Sopenharmony_ci *    caches.  Dirty lines of the caches may be written back or simply
51162306a36Sopenharmony_ci *    be discarded.  This operation is necessary before dma operations
51262306a36Sopenharmony_ci *    to the memory.
51362306a36Sopenharmony_ci *
51462306a36Sopenharmony_ci * This API used to be exported; it now is for arch code internal use only.
51562306a36Sopenharmony_ci */
51662306a36Sopenharmony_ci#ifdef CONFIG_DMA_NONCOHERENT
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ciextern void (*_dma_cache_wback_inv)(unsigned long start, unsigned long size);
51962306a36Sopenharmony_ciextern void (*_dma_cache_wback)(unsigned long start, unsigned long size);
52062306a36Sopenharmony_ciextern void (*_dma_cache_inv)(unsigned long start, unsigned long size);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci#define dma_cache_wback_inv(start, size)	_dma_cache_wback_inv(start, size)
52362306a36Sopenharmony_ci#define dma_cache_wback(start, size)		_dma_cache_wback(start, size)
52462306a36Sopenharmony_ci#define dma_cache_inv(start, size)		_dma_cache_inv(start, size)
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci#else /* Sane hardware */
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci#define dma_cache_wback_inv(start,size) \
52962306a36Sopenharmony_ci	do { (void) (start); (void) (size); } while (0)
53062306a36Sopenharmony_ci#define dma_cache_wback(start,size)	\
53162306a36Sopenharmony_ci	do { (void) (start); (void) (size); } while (0)
53262306a36Sopenharmony_ci#define dma_cache_inv(start,size)	\
53362306a36Sopenharmony_ci	do { (void) (start); (void) (size); } while (0)
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci#endif /* CONFIG_DMA_NONCOHERENT */
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci/*
53862306a36Sopenharmony_ci * Read a 32-bit register that requires a 64-bit read cycle on the bus.
53962306a36Sopenharmony_ci * Avoid interrupt mucking, just adjust the address for 4-byte access.
54062306a36Sopenharmony_ci * Assume the addresses are 8-byte aligned.
54162306a36Sopenharmony_ci */
54262306a36Sopenharmony_ci#ifdef __MIPSEB__
54362306a36Sopenharmony_ci#define __CSR_32_ADJUST 4
54462306a36Sopenharmony_ci#else
54562306a36Sopenharmony_ci#define __CSR_32_ADJUST 0
54662306a36Sopenharmony_ci#endif
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci#define csr_out32(v, a) (*(volatile u32 *)((unsigned long)(a) + __CSR_32_ADJUST) = (v))
54962306a36Sopenharmony_ci#define csr_in32(a)    (*(volatile u32 *)((unsigned long)(a) + __CSR_32_ADJUST))
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci/*
55262306a36Sopenharmony_ci * Convert a physical pointer to a virtual kernel pointer for /dev/mem
55362306a36Sopenharmony_ci * access
55462306a36Sopenharmony_ci */
55562306a36Sopenharmony_ci#define xlate_dev_mem_ptr(p)	__va(p)
55662306a36Sopenharmony_ci#define unxlate_dev_mem_ptr(p, v) do { } while (0)
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_civoid __ioread64_copy(void *to, const void __iomem *from, size_t count);
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci#endif /* _ASM_IO_H */
561