162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci#ifndef _ASM_POWERPC_IO_H
362306a36Sopenharmony_ci#define _ASM_POWERPC_IO_H
462306a36Sopenharmony_ci#ifdef __KERNEL__
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci/*
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/* Check of existence of legacy devices */
1062306a36Sopenharmony_ciextern int check_legacy_ioport(unsigned long base_port);
1162306a36Sopenharmony_ci#define I8042_DATA_REG	0x60
1262306a36Sopenharmony_ci#define FDC_BASE	0x3f0
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#if defined(CONFIG_PPC64) && defined(CONFIG_PCI)
1562306a36Sopenharmony_ciextern struct pci_dev *isa_bridge_pcidev;
1662306a36Sopenharmony_ci/*
1762306a36Sopenharmony_ci * has legacy ISA devices ?
1862306a36Sopenharmony_ci */
1962306a36Sopenharmony_ci#define arch_has_dev_port()	(isa_bridge_pcidev != NULL || isa_io_special)
2062306a36Sopenharmony_ci#endif
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include <linux/device.h>
2362306a36Sopenharmony_ci#include <linux/compiler.h>
2462306a36Sopenharmony_ci#include <linux/mm.h>
2562306a36Sopenharmony_ci#include <asm/page.h>
2662306a36Sopenharmony_ci#include <asm/byteorder.h>
2762306a36Sopenharmony_ci#include <asm/synch.h>
2862306a36Sopenharmony_ci#include <asm/delay.h>
2962306a36Sopenharmony_ci#include <asm/mmiowb.h>
3062306a36Sopenharmony_ci#include <asm/mmu.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#define SIO_CONFIG_RA	0x398
3362306a36Sopenharmony_ci#define SIO_CONFIG_RD	0x399
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci/* 32 bits uses slightly different variables for the various IO
3662306a36Sopenharmony_ci * bases. Most of this file only uses _IO_BASE though which we
3762306a36Sopenharmony_ci * define properly based on the platform
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_ci#ifndef CONFIG_PCI
4062306a36Sopenharmony_ci#define _IO_BASE	0
4162306a36Sopenharmony_ci#define _ISA_MEM_BASE	0
4262306a36Sopenharmony_ci#define PCI_DRAM_OFFSET 0
4362306a36Sopenharmony_ci#elif defined(CONFIG_PPC32)
4462306a36Sopenharmony_ci#define _IO_BASE	isa_io_base
4562306a36Sopenharmony_ci#define _ISA_MEM_BASE	isa_mem_base
4662306a36Sopenharmony_ci#define PCI_DRAM_OFFSET	pci_dram_offset
4762306a36Sopenharmony_ci#else
4862306a36Sopenharmony_ci#define _IO_BASE	pci_io_base
4962306a36Sopenharmony_ci#define _ISA_MEM_BASE	isa_mem_base
5062306a36Sopenharmony_ci#define PCI_DRAM_OFFSET	0
5162306a36Sopenharmony_ci#endif
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ciextern unsigned long isa_io_base;
5462306a36Sopenharmony_ciextern unsigned long pci_io_base;
5562306a36Sopenharmony_ciextern unsigned long pci_dram_offset;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ciextern resource_size_t isa_mem_base;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/* Boolean set by platform if PIO accesses are suppored while _IO_BASE
6062306a36Sopenharmony_ci * is not set or addresses cannot be translated to MMIO. This is typically
6162306a36Sopenharmony_ci * set when the platform supports "special" PIO accesses via a non memory
6262306a36Sopenharmony_ci * mapped mechanism, and allows things like the early udbg UART code to
6362306a36Sopenharmony_ci * function.
6462306a36Sopenharmony_ci */
6562306a36Sopenharmony_ciextern bool isa_io_special;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci#ifdef CONFIG_PPC32
6862306a36Sopenharmony_ci#if defined(CONFIG_PPC_INDIRECT_PIO) || defined(CONFIG_PPC_INDIRECT_MMIO)
6962306a36Sopenharmony_ci#error CONFIG_PPC_INDIRECT_{PIO,MMIO} are not yet supported on 32 bits
7062306a36Sopenharmony_ci#endif
7162306a36Sopenharmony_ci#endif
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/*
7462306a36Sopenharmony_ci *
7562306a36Sopenharmony_ci * Low level MMIO accessors
7662306a36Sopenharmony_ci *
7762306a36Sopenharmony_ci * This provides the non-bus specific accessors to MMIO. Those are PowerPC
7862306a36Sopenharmony_ci * specific and thus shouldn't be used in generic code. The accessors
7962306a36Sopenharmony_ci * provided here are:
8062306a36Sopenharmony_ci *
8162306a36Sopenharmony_ci *	in_8, in_le16, in_be16, in_le32, in_be32, in_le64, in_be64
8262306a36Sopenharmony_ci *	out_8, out_le16, out_be16, out_le32, out_be32, out_le64, out_be64
8362306a36Sopenharmony_ci *	_insb, _insw_ns, _insl_ns, _outsb, _outsw_ns, _outsl_ns
8462306a36Sopenharmony_ci *
8562306a36Sopenharmony_ci * Those operate directly on a kernel virtual address. Note that the prototype
8662306a36Sopenharmony_ci * for the out_* accessors has the arguments in opposite order from the usual
8762306a36Sopenharmony_ci * linux PCI accessors. Unlike those, they take the address first and the value
8862306a36Sopenharmony_ci * next.
8962306a36Sopenharmony_ci *
9062306a36Sopenharmony_ci * Note: I might drop the _ns suffix on the stream operations soon as it is
9162306a36Sopenharmony_ci * simply normal for stream operations to not swap in the first place.
9262306a36Sopenharmony_ci *
9362306a36Sopenharmony_ci */
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/* -mprefixed can generate offsets beyond range, fall back hack */
9662306a36Sopenharmony_ci#ifdef CONFIG_PPC_KERNEL_PREFIXED
9762306a36Sopenharmony_ci#define DEF_MMIO_IN_X(name, size, insn)				\
9862306a36Sopenharmony_cistatic inline u##size name(const volatile u##size __iomem *addr)	\
9962306a36Sopenharmony_ci{									\
10062306a36Sopenharmony_ci	u##size ret;							\
10162306a36Sopenharmony_ci	__asm__ __volatile__("sync;"#insn" %0,0,%1;twi 0,%0,0;isync"	\
10262306a36Sopenharmony_ci		: "=r" (ret) : "r" (addr) : "memory");			\
10362306a36Sopenharmony_ci	return ret;							\
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci#define DEF_MMIO_OUT_X(name, size, insn)				\
10762306a36Sopenharmony_cistatic inline void name(volatile u##size __iomem *addr, u##size val)	\
10862306a36Sopenharmony_ci{									\
10962306a36Sopenharmony_ci	__asm__ __volatile__("sync;"#insn" %1,0,%0"			\
11062306a36Sopenharmony_ci		: : "r" (addr), "r" (val) : "memory");			\
11162306a36Sopenharmony_ci	mmiowb_set_pending();						\
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci#define DEF_MMIO_IN_D(name, size, insn)				\
11562306a36Sopenharmony_cistatic inline u##size name(const volatile u##size __iomem *addr)	\
11662306a36Sopenharmony_ci{									\
11762306a36Sopenharmony_ci	u##size ret;							\
11862306a36Sopenharmony_ci	__asm__ __volatile__("sync;"#insn" %0,0(%1);twi 0,%0,0;isync"\
11962306a36Sopenharmony_ci		: "=r" (ret) : "b" (addr) : "memory");	\
12062306a36Sopenharmony_ci	return ret;							\
12162306a36Sopenharmony_ci}
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci#define DEF_MMIO_OUT_D(name, size, insn)				\
12462306a36Sopenharmony_cistatic inline void name(volatile u##size __iomem *addr, u##size val)	\
12562306a36Sopenharmony_ci{									\
12662306a36Sopenharmony_ci	__asm__ __volatile__("sync;"#insn" %1,0(%0)"			\
12762306a36Sopenharmony_ci		: : "b" (addr), "r" (val) : "memory");	\
12862306a36Sopenharmony_ci	mmiowb_set_pending();						\
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci#else
13162306a36Sopenharmony_ci#define DEF_MMIO_IN_X(name, size, insn)				\
13262306a36Sopenharmony_cistatic inline u##size name(const volatile u##size __iomem *addr)	\
13362306a36Sopenharmony_ci{									\
13462306a36Sopenharmony_ci	u##size ret;							\
13562306a36Sopenharmony_ci	__asm__ __volatile__("sync;"#insn" %0,%y1;twi 0,%0,0;isync"	\
13662306a36Sopenharmony_ci		: "=r" (ret) : "Z" (*addr) : "memory");			\
13762306a36Sopenharmony_ci	return ret;							\
13862306a36Sopenharmony_ci}
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci#define DEF_MMIO_OUT_X(name, size, insn)				\
14162306a36Sopenharmony_cistatic inline void name(volatile u##size __iomem *addr, u##size val)	\
14262306a36Sopenharmony_ci{									\
14362306a36Sopenharmony_ci	__asm__ __volatile__("sync;"#insn" %1,%y0"			\
14462306a36Sopenharmony_ci		: "=Z" (*addr) : "r" (val) : "memory");			\
14562306a36Sopenharmony_ci	mmiowb_set_pending();						\
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci#define DEF_MMIO_IN_D(name, size, insn)				\
14962306a36Sopenharmony_cistatic inline u##size name(const volatile u##size __iomem *addr)	\
15062306a36Sopenharmony_ci{									\
15162306a36Sopenharmony_ci	u##size ret;							\
15262306a36Sopenharmony_ci	__asm__ __volatile__("sync;"#insn"%U1%X1 %0,%1;twi 0,%0,0;isync"\
15362306a36Sopenharmony_ci		: "=r" (ret) : "m<>" (*addr) : "memory");	\
15462306a36Sopenharmony_ci	return ret;							\
15562306a36Sopenharmony_ci}
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci#define DEF_MMIO_OUT_D(name, size, insn)				\
15862306a36Sopenharmony_cistatic inline void name(volatile u##size __iomem *addr, u##size val)	\
15962306a36Sopenharmony_ci{									\
16062306a36Sopenharmony_ci	__asm__ __volatile__("sync;"#insn"%U0%X0 %1,%0"			\
16162306a36Sopenharmony_ci		: "=m<>" (*addr) : "r" (val) : "memory");	\
16262306a36Sopenharmony_ci	mmiowb_set_pending();						\
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci#endif
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ciDEF_MMIO_IN_D(in_8,     8, lbz);
16762306a36Sopenharmony_ciDEF_MMIO_OUT_D(out_8,   8, stb);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci#ifdef __BIG_ENDIAN__
17062306a36Sopenharmony_ciDEF_MMIO_IN_D(in_be16, 16, lhz);
17162306a36Sopenharmony_ciDEF_MMIO_IN_D(in_be32, 32, lwz);
17262306a36Sopenharmony_ciDEF_MMIO_IN_X(in_le16, 16, lhbrx);
17362306a36Sopenharmony_ciDEF_MMIO_IN_X(in_le32, 32, lwbrx);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ciDEF_MMIO_OUT_D(out_be16, 16, sth);
17662306a36Sopenharmony_ciDEF_MMIO_OUT_D(out_be32, 32, stw);
17762306a36Sopenharmony_ciDEF_MMIO_OUT_X(out_le16, 16, sthbrx);
17862306a36Sopenharmony_ciDEF_MMIO_OUT_X(out_le32, 32, stwbrx);
17962306a36Sopenharmony_ci#else
18062306a36Sopenharmony_ciDEF_MMIO_IN_X(in_be16, 16, lhbrx);
18162306a36Sopenharmony_ciDEF_MMIO_IN_X(in_be32, 32, lwbrx);
18262306a36Sopenharmony_ciDEF_MMIO_IN_D(in_le16, 16, lhz);
18362306a36Sopenharmony_ciDEF_MMIO_IN_D(in_le32, 32, lwz);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ciDEF_MMIO_OUT_X(out_be16, 16, sthbrx);
18662306a36Sopenharmony_ciDEF_MMIO_OUT_X(out_be32, 32, stwbrx);
18762306a36Sopenharmony_ciDEF_MMIO_OUT_D(out_le16, 16, sth);
18862306a36Sopenharmony_ciDEF_MMIO_OUT_D(out_le32, 32, stw);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci#endif /* __BIG_ENDIAN */
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci#ifdef __powerpc64__
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci#ifdef __BIG_ENDIAN__
19562306a36Sopenharmony_ciDEF_MMIO_OUT_D(out_be64, 64, std);
19662306a36Sopenharmony_ciDEF_MMIO_IN_D(in_be64, 64, ld);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci/* There is no asm instructions for 64 bits reverse loads and stores */
19962306a36Sopenharmony_cistatic inline u64 in_le64(const volatile u64 __iomem *addr)
20062306a36Sopenharmony_ci{
20162306a36Sopenharmony_ci	return swab64(in_be64(addr));
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cistatic inline void out_le64(volatile u64 __iomem *addr, u64 val)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	out_be64(addr, swab64(val));
20762306a36Sopenharmony_ci}
20862306a36Sopenharmony_ci#else
20962306a36Sopenharmony_ciDEF_MMIO_OUT_D(out_le64, 64, std);
21062306a36Sopenharmony_ciDEF_MMIO_IN_D(in_le64, 64, ld);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci/* There is no asm instructions for 64 bits reverse loads and stores */
21362306a36Sopenharmony_cistatic inline u64 in_be64(const volatile u64 __iomem *addr)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	return swab64(in_le64(addr));
21662306a36Sopenharmony_ci}
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_cistatic inline void out_be64(volatile u64 __iomem *addr, u64 val)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	out_le64(addr, swab64(val));
22162306a36Sopenharmony_ci}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci#endif
22462306a36Sopenharmony_ci#endif /* __powerpc64__ */
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci/*
22762306a36Sopenharmony_ci * Low level IO stream instructions are defined out of line for now
22862306a36Sopenharmony_ci */
22962306a36Sopenharmony_ciextern void _insb(const volatile u8 __iomem *addr, void *buf, long count);
23062306a36Sopenharmony_ciextern void _outsb(volatile u8 __iomem *addr,const void *buf,long count);
23162306a36Sopenharmony_ciextern void _insw_ns(const volatile u16 __iomem *addr, void *buf, long count);
23262306a36Sopenharmony_ciextern void _outsw_ns(volatile u16 __iomem *addr, const void *buf, long count);
23362306a36Sopenharmony_ciextern void _insl_ns(const volatile u32 __iomem *addr, void *buf, long count);
23462306a36Sopenharmony_ciextern void _outsl_ns(volatile u32 __iomem *addr, const void *buf, long count);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci/* The _ns naming is historical and will be removed. For now, just #define
23762306a36Sopenharmony_ci * the non _ns equivalent names
23862306a36Sopenharmony_ci */
23962306a36Sopenharmony_ci#define _insw	_insw_ns
24062306a36Sopenharmony_ci#define _insl	_insl_ns
24162306a36Sopenharmony_ci#define _outsw	_outsw_ns
24262306a36Sopenharmony_ci#define _outsl	_outsl_ns
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci/*
24662306a36Sopenharmony_ci * memset_io, memcpy_toio, memcpy_fromio base implementations are out of line
24762306a36Sopenharmony_ci */
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ciextern void _memset_io(volatile void __iomem *addr, int c, unsigned long n);
25062306a36Sopenharmony_ciextern void _memcpy_fromio(void *dest, const volatile void __iomem *src,
25162306a36Sopenharmony_ci			   unsigned long n);
25262306a36Sopenharmony_ciextern void _memcpy_toio(volatile void __iomem *dest, const void *src,
25362306a36Sopenharmony_ci			 unsigned long n);
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci/*
25662306a36Sopenharmony_ci *
25762306a36Sopenharmony_ci * PCI and standard ISA accessors
25862306a36Sopenharmony_ci *
25962306a36Sopenharmony_ci * Those are globally defined linux accessors for devices on PCI or ISA
26062306a36Sopenharmony_ci * busses. They follow the Linux defined semantics. The current implementation
26162306a36Sopenharmony_ci * for PowerPC is as close as possible to the x86 version of these, and thus
26262306a36Sopenharmony_ci * provides fairly heavy weight barriers for the non-raw versions
26362306a36Sopenharmony_ci *
26462306a36Sopenharmony_ci * In addition, they support a hook mechanism when CONFIG_PPC_INDIRECT_MMIO
26562306a36Sopenharmony_ci * or CONFIG_PPC_INDIRECT_PIO are set allowing the platform to provide its
26662306a36Sopenharmony_ci * own implementation of some or all of the accessors.
26762306a36Sopenharmony_ci */
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci/*
27062306a36Sopenharmony_ci * Include the EEH definitions when EEH is enabled only so they don't get
27162306a36Sopenharmony_ci * in the way when building for 32 bits
27262306a36Sopenharmony_ci */
27362306a36Sopenharmony_ci#ifdef CONFIG_EEH
27462306a36Sopenharmony_ci#include <asm/eeh.h>
27562306a36Sopenharmony_ci#endif
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci/* Shortcut to the MMIO argument pointer */
27862306a36Sopenharmony_ci#define PCI_IO_ADDR	volatile void __iomem *
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci/* Indirect IO address tokens:
28162306a36Sopenharmony_ci *
28262306a36Sopenharmony_ci * When CONFIG_PPC_INDIRECT_MMIO is set, the platform can provide hooks
28362306a36Sopenharmony_ci * on all MMIOs. (Note that this is all 64 bits only for now)
28462306a36Sopenharmony_ci *
28562306a36Sopenharmony_ci * To help platforms who may need to differentiate MMIO addresses in
28662306a36Sopenharmony_ci * their hooks, a bitfield is reserved for use by the platform near the
28762306a36Sopenharmony_ci * top of MMIO addresses (not PIO, those have to cope the hard way).
28862306a36Sopenharmony_ci *
28962306a36Sopenharmony_ci * The highest address in the kernel virtual space are:
29062306a36Sopenharmony_ci *
29162306a36Sopenharmony_ci *  d0003fffffffffff	# with Hash MMU
29262306a36Sopenharmony_ci *  c00fffffffffffff	# with Radix MMU
29362306a36Sopenharmony_ci *
29462306a36Sopenharmony_ci * The top 4 bits are reserved as the region ID on hash, leaving us 8 bits
29562306a36Sopenharmony_ci * that can be used for the field.
29662306a36Sopenharmony_ci *
29762306a36Sopenharmony_ci * The direct IO mapping operations will then mask off those bits
29862306a36Sopenharmony_ci * before doing the actual access, though that only happen when
29962306a36Sopenharmony_ci * CONFIG_PPC_INDIRECT_MMIO is set, thus be careful when you use that
30062306a36Sopenharmony_ci * mechanism
30162306a36Sopenharmony_ci *
30262306a36Sopenharmony_ci * For PIO, there is a separate CONFIG_PPC_INDIRECT_PIO which makes
30362306a36Sopenharmony_ci * all PIO functions call through a hook.
30462306a36Sopenharmony_ci */
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci#ifdef CONFIG_PPC_INDIRECT_MMIO
30762306a36Sopenharmony_ci#define PCI_IO_IND_TOKEN_SHIFT	52
30862306a36Sopenharmony_ci#define PCI_IO_IND_TOKEN_MASK	(0xfful << PCI_IO_IND_TOKEN_SHIFT)
30962306a36Sopenharmony_ci#define PCI_FIX_ADDR(addr)						\
31062306a36Sopenharmony_ci	((PCI_IO_ADDR)(((unsigned long)(addr)) & ~PCI_IO_IND_TOKEN_MASK))
31162306a36Sopenharmony_ci#define PCI_GET_ADDR_TOKEN(addr)					\
31262306a36Sopenharmony_ci	(((unsigned long)(addr) & PCI_IO_IND_TOKEN_MASK) >> 		\
31362306a36Sopenharmony_ci		PCI_IO_IND_TOKEN_SHIFT)
31462306a36Sopenharmony_ci#define PCI_SET_ADDR_TOKEN(addr, token) 				\
31562306a36Sopenharmony_cido {									\
31662306a36Sopenharmony_ci	unsigned long __a = (unsigned long)(addr);			\
31762306a36Sopenharmony_ci	__a &= ~PCI_IO_IND_TOKEN_MASK;					\
31862306a36Sopenharmony_ci	__a |= ((unsigned long)(token)) << PCI_IO_IND_TOKEN_SHIFT;	\
31962306a36Sopenharmony_ci	(addr) = (void __iomem *)__a;					\
32062306a36Sopenharmony_ci} while(0)
32162306a36Sopenharmony_ci#else
32262306a36Sopenharmony_ci#define PCI_FIX_ADDR(addr) (addr)
32362306a36Sopenharmony_ci#endif
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci/*
32762306a36Sopenharmony_ci * Non ordered and non-swapping "raw" accessors
32862306a36Sopenharmony_ci */
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_cistatic inline unsigned char __raw_readb(const volatile void __iomem *addr)
33162306a36Sopenharmony_ci{
33262306a36Sopenharmony_ci	return *(volatile unsigned char __force *)PCI_FIX_ADDR(addr);
33362306a36Sopenharmony_ci}
33462306a36Sopenharmony_ci#define __raw_readb __raw_readb
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_cistatic inline unsigned short __raw_readw(const volatile void __iomem *addr)
33762306a36Sopenharmony_ci{
33862306a36Sopenharmony_ci	return *(volatile unsigned short __force *)PCI_FIX_ADDR(addr);
33962306a36Sopenharmony_ci}
34062306a36Sopenharmony_ci#define __raw_readw __raw_readw
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_cistatic inline unsigned int __raw_readl(const volatile void __iomem *addr)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	return *(volatile unsigned int __force *)PCI_FIX_ADDR(addr);
34562306a36Sopenharmony_ci}
34662306a36Sopenharmony_ci#define __raw_readl __raw_readl
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_cistatic inline void __raw_writeb(unsigned char v, volatile void __iomem *addr)
34962306a36Sopenharmony_ci{
35062306a36Sopenharmony_ci	*(volatile unsigned char __force *)PCI_FIX_ADDR(addr) = v;
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ci#define __raw_writeb __raw_writeb
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_cistatic inline void __raw_writew(unsigned short v, volatile void __iomem *addr)
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	*(volatile unsigned short __force *)PCI_FIX_ADDR(addr) = v;
35762306a36Sopenharmony_ci}
35862306a36Sopenharmony_ci#define __raw_writew __raw_writew
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_cistatic inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
36162306a36Sopenharmony_ci{
36262306a36Sopenharmony_ci	*(volatile unsigned int __force *)PCI_FIX_ADDR(addr) = v;
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ci#define __raw_writel __raw_writel
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci#ifdef __powerpc64__
36762306a36Sopenharmony_cistatic inline unsigned long __raw_readq(const volatile void __iomem *addr)
36862306a36Sopenharmony_ci{
36962306a36Sopenharmony_ci	return *(volatile unsigned long __force *)PCI_FIX_ADDR(addr);
37062306a36Sopenharmony_ci}
37162306a36Sopenharmony_ci#define __raw_readq __raw_readq
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic inline void __raw_writeq(unsigned long v, volatile void __iomem *addr)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	*(volatile unsigned long __force *)PCI_FIX_ADDR(addr) = v;
37662306a36Sopenharmony_ci}
37762306a36Sopenharmony_ci#define __raw_writeq __raw_writeq
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_cistatic inline void __raw_writeq_be(unsigned long v, volatile void __iomem *addr)
38062306a36Sopenharmony_ci{
38162306a36Sopenharmony_ci	__raw_writeq((__force unsigned long)cpu_to_be64(v), addr);
38262306a36Sopenharmony_ci}
38362306a36Sopenharmony_ci#define __raw_writeq_be __raw_writeq_be
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci/*
38662306a36Sopenharmony_ci * Real mode versions of the above. Those instructions are only supposed
38762306a36Sopenharmony_ci * to be used in hypervisor real mode as per the architecture spec.
38862306a36Sopenharmony_ci */
38962306a36Sopenharmony_cistatic inline void __raw_rm_writeb(u8 val, volatile void __iomem *paddr)
39062306a36Sopenharmony_ci{
39162306a36Sopenharmony_ci	__asm__ __volatile__(".machine push;   \
39262306a36Sopenharmony_ci			      .machine power6; \
39362306a36Sopenharmony_ci			      stbcix %0,0,%1;  \
39462306a36Sopenharmony_ci			      .machine pop;"
39562306a36Sopenharmony_ci		: : "r" (val), "r" (paddr) : "memory");
39662306a36Sopenharmony_ci}
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cistatic inline void __raw_rm_writew(u16 val, volatile void __iomem *paddr)
39962306a36Sopenharmony_ci{
40062306a36Sopenharmony_ci	__asm__ __volatile__(".machine push;   \
40162306a36Sopenharmony_ci			      .machine power6; \
40262306a36Sopenharmony_ci			      sthcix %0,0,%1;  \
40362306a36Sopenharmony_ci			      .machine pop;"
40462306a36Sopenharmony_ci		: : "r" (val), "r" (paddr) : "memory");
40562306a36Sopenharmony_ci}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_cistatic inline void __raw_rm_writel(u32 val, volatile void __iomem *paddr)
40862306a36Sopenharmony_ci{
40962306a36Sopenharmony_ci	__asm__ __volatile__(".machine push;   \
41062306a36Sopenharmony_ci			      .machine power6; \
41162306a36Sopenharmony_ci			      stwcix %0,0,%1;  \
41262306a36Sopenharmony_ci			      .machine pop;"
41362306a36Sopenharmony_ci		: : "r" (val), "r" (paddr) : "memory");
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr)
41762306a36Sopenharmony_ci{
41862306a36Sopenharmony_ci	__asm__ __volatile__(".machine push;   \
41962306a36Sopenharmony_ci			      .machine power6; \
42062306a36Sopenharmony_ci			      stdcix %0,0,%1;  \
42162306a36Sopenharmony_ci			      .machine pop;"
42262306a36Sopenharmony_ci		: : "r" (val), "r" (paddr) : "memory");
42362306a36Sopenharmony_ci}
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_cistatic inline void __raw_rm_writeq_be(u64 val, volatile void __iomem *paddr)
42662306a36Sopenharmony_ci{
42762306a36Sopenharmony_ci	__raw_rm_writeq((__force u64)cpu_to_be64(val), paddr);
42862306a36Sopenharmony_ci}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_cistatic inline u8 __raw_rm_readb(volatile void __iomem *paddr)
43162306a36Sopenharmony_ci{
43262306a36Sopenharmony_ci	u8 ret;
43362306a36Sopenharmony_ci	__asm__ __volatile__(".machine push;   \
43462306a36Sopenharmony_ci			      .machine power6; \
43562306a36Sopenharmony_ci			      lbzcix %0,0, %1; \
43662306a36Sopenharmony_ci			      .machine pop;"
43762306a36Sopenharmony_ci			     : "=r" (ret) : "r" (paddr) : "memory");
43862306a36Sopenharmony_ci	return ret;
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_cistatic inline u16 __raw_rm_readw(volatile void __iomem *paddr)
44262306a36Sopenharmony_ci{
44362306a36Sopenharmony_ci	u16 ret;
44462306a36Sopenharmony_ci	__asm__ __volatile__(".machine push;   \
44562306a36Sopenharmony_ci			      .machine power6; \
44662306a36Sopenharmony_ci			      lhzcix %0,0, %1; \
44762306a36Sopenharmony_ci			      .machine pop;"
44862306a36Sopenharmony_ci			     : "=r" (ret) : "r" (paddr) : "memory");
44962306a36Sopenharmony_ci	return ret;
45062306a36Sopenharmony_ci}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_cistatic inline u32 __raw_rm_readl(volatile void __iomem *paddr)
45362306a36Sopenharmony_ci{
45462306a36Sopenharmony_ci	u32 ret;
45562306a36Sopenharmony_ci	__asm__ __volatile__(".machine push;   \
45662306a36Sopenharmony_ci			      .machine power6; \
45762306a36Sopenharmony_ci			      lwzcix %0,0, %1; \
45862306a36Sopenharmony_ci			      .machine pop;"
45962306a36Sopenharmony_ci			     : "=r" (ret) : "r" (paddr) : "memory");
46062306a36Sopenharmony_ci	return ret;
46162306a36Sopenharmony_ci}
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_cistatic inline u64 __raw_rm_readq(volatile void __iomem *paddr)
46462306a36Sopenharmony_ci{
46562306a36Sopenharmony_ci	u64 ret;
46662306a36Sopenharmony_ci	__asm__ __volatile__(".machine push;   \
46762306a36Sopenharmony_ci			      .machine power6; \
46862306a36Sopenharmony_ci			      ldcix %0,0, %1;  \
46962306a36Sopenharmony_ci			      .machine pop;"
47062306a36Sopenharmony_ci			     : "=r" (ret) : "r" (paddr) : "memory");
47162306a36Sopenharmony_ci	return ret;
47262306a36Sopenharmony_ci}
47362306a36Sopenharmony_ci#endif /* __powerpc64__ */
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci/*
47662306a36Sopenharmony_ci *
47762306a36Sopenharmony_ci * PCI PIO and MMIO accessors.
47862306a36Sopenharmony_ci *
47962306a36Sopenharmony_ci *
48062306a36Sopenharmony_ci * On 32 bits, PIO operations have a recovery mechanism in case they trigger
48162306a36Sopenharmony_ci * machine checks (which they occasionally do when probing non existing
48262306a36Sopenharmony_ci * IO ports on some platforms, like PowerMac and 8xx).
48362306a36Sopenharmony_ci * I always found it to be of dubious reliability and I am tempted to get
48462306a36Sopenharmony_ci * rid of it one of these days. So if you think it's important to keep it,
48562306a36Sopenharmony_ci * please voice up asap. We never had it for 64 bits and I do not intend
48662306a36Sopenharmony_ci * to port it over
48762306a36Sopenharmony_ci */
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci#ifdef CONFIG_PPC32
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci#define __do_in_asm(name, op)				\
49262306a36Sopenharmony_cistatic inline unsigned int name(unsigned int port)	\
49362306a36Sopenharmony_ci{							\
49462306a36Sopenharmony_ci	unsigned int x;					\
49562306a36Sopenharmony_ci	__asm__ __volatile__(				\
49662306a36Sopenharmony_ci		"sync\n"				\
49762306a36Sopenharmony_ci		"0:"	op "	%0,0,%1\n"		\
49862306a36Sopenharmony_ci		"1:	twi	0,%0,0\n"		\
49962306a36Sopenharmony_ci		"2:	isync\n"			\
50062306a36Sopenharmony_ci		"3:	nop\n"				\
50162306a36Sopenharmony_ci		"4:\n"					\
50262306a36Sopenharmony_ci		".section .fixup,\"ax\"\n"		\
50362306a36Sopenharmony_ci		"5:	li	%0,-1\n"		\
50462306a36Sopenharmony_ci		"	b	4b\n"			\
50562306a36Sopenharmony_ci		".previous\n"				\
50662306a36Sopenharmony_ci		EX_TABLE(0b, 5b)			\
50762306a36Sopenharmony_ci		EX_TABLE(1b, 5b)			\
50862306a36Sopenharmony_ci		EX_TABLE(2b, 5b)			\
50962306a36Sopenharmony_ci		EX_TABLE(3b, 5b)			\
51062306a36Sopenharmony_ci		: "=&r" (x)				\
51162306a36Sopenharmony_ci		: "r" (port + _IO_BASE)			\
51262306a36Sopenharmony_ci		: "memory");  				\
51362306a36Sopenharmony_ci	return x;					\
51462306a36Sopenharmony_ci}
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci#define __do_out_asm(name, op)				\
51762306a36Sopenharmony_cistatic inline void name(unsigned int val, unsigned int port) \
51862306a36Sopenharmony_ci{							\
51962306a36Sopenharmony_ci	__asm__ __volatile__(				\
52062306a36Sopenharmony_ci		"sync\n"				\
52162306a36Sopenharmony_ci		"0:" op " %0,0,%1\n"			\
52262306a36Sopenharmony_ci		"1:	sync\n"				\
52362306a36Sopenharmony_ci		"2:\n"					\
52462306a36Sopenharmony_ci		EX_TABLE(0b, 2b)			\
52562306a36Sopenharmony_ci		EX_TABLE(1b, 2b)			\
52662306a36Sopenharmony_ci		: : "r" (val), "r" (port + _IO_BASE)	\
52762306a36Sopenharmony_ci		: "memory");   	   	   		\
52862306a36Sopenharmony_ci}
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci__do_in_asm(_rec_inb, "lbzx")
53162306a36Sopenharmony_ci__do_in_asm(_rec_inw, "lhbrx")
53262306a36Sopenharmony_ci__do_in_asm(_rec_inl, "lwbrx")
53362306a36Sopenharmony_ci__do_out_asm(_rec_outb, "stbx")
53462306a36Sopenharmony_ci__do_out_asm(_rec_outw, "sthbrx")
53562306a36Sopenharmony_ci__do_out_asm(_rec_outl, "stwbrx")
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci#endif /* CONFIG_PPC32 */
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci/* The "__do_*" operations below provide the actual "base" implementation
54062306a36Sopenharmony_ci * for each of the defined accessors. Some of them use the out_* functions
54162306a36Sopenharmony_ci * directly, some of them still use EEH, though we might change that in the
54262306a36Sopenharmony_ci * future. Those macros below provide the necessary argument swapping and
54362306a36Sopenharmony_ci * handling of the IO base for PIO.
54462306a36Sopenharmony_ci *
54562306a36Sopenharmony_ci * They are themselves used by the macros that define the actual accessors
54662306a36Sopenharmony_ci * and can be used by the hooks if any.
54762306a36Sopenharmony_ci *
54862306a36Sopenharmony_ci * Note that PIO operations are always defined in terms of their corresonding
54962306a36Sopenharmony_ci * MMIO operations. That allows platforms like iSeries who want to modify the
55062306a36Sopenharmony_ci * behaviour of both to only hook on the MMIO version and get both. It's also
55162306a36Sopenharmony_ci * possible to hook directly at the toplevel PIO operation if they have to
55262306a36Sopenharmony_ci * be handled differently
55362306a36Sopenharmony_ci */
55462306a36Sopenharmony_ci#define __do_writeb(val, addr)	out_8(PCI_FIX_ADDR(addr), val)
55562306a36Sopenharmony_ci#define __do_writew(val, addr)	out_le16(PCI_FIX_ADDR(addr), val)
55662306a36Sopenharmony_ci#define __do_writel(val, addr)	out_le32(PCI_FIX_ADDR(addr), val)
55762306a36Sopenharmony_ci#define __do_writeq(val, addr)	out_le64(PCI_FIX_ADDR(addr), val)
55862306a36Sopenharmony_ci#define __do_writew_be(val, addr) out_be16(PCI_FIX_ADDR(addr), val)
55962306a36Sopenharmony_ci#define __do_writel_be(val, addr) out_be32(PCI_FIX_ADDR(addr), val)
56062306a36Sopenharmony_ci#define __do_writeq_be(val, addr) out_be64(PCI_FIX_ADDR(addr), val)
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci#ifdef CONFIG_EEH
56362306a36Sopenharmony_ci#define __do_readb(addr)	eeh_readb(PCI_FIX_ADDR(addr))
56462306a36Sopenharmony_ci#define __do_readw(addr)	eeh_readw(PCI_FIX_ADDR(addr))
56562306a36Sopenharmony_ci#define __do_readl(addr)	eeh_readl(PCI_FIX_ADDR(addr))
56662306a36Sopenharmony_ci#define __do_readq(addr)	eeh_readq(PCI_FIX_ADDR(addr))
56762306a36Sopenharmony_ci#define __do_readw_be(addr)	eeh_readw_be(PCI_FIX_ADDR(addr))
56862306a36Sopenharmony_ci#define __do_readl_be(addr)	eeh_readl_be(PCI_FIX_ADDR(addr))
56962306a36Sopenharmony_ci#define __do_readq_be(addr)	eeh_readq_be(PCI_FIX_ADDR(addr))
57062306a36Sopenharmony_ci#else /* CONFIG_EEH */
57162306a36Sopenharmony_ci#define __do_readb(addr)	in_8(PCI_FIX_ADDR(addr))
57262306a36Sopenharmony_ci#define __do_readw(addr)	in_le16(PCI_FIX_ADDR(addr))
57362306a36Sopenharmony_ci#define __do_readl(addr)	in_le32(PCI_FIX_ADDR(addr))
57462306a36Sopenharmony_ci#define __do_readq(addr)	in_le64(PCI_FIX_ADDR(addr))
57562306a36Sopenharmony_ci#define __do_readw_be(addr)	in_be16(PCI_FIX_ADDR(addr))
57662306a36Sopenharmony_ci#define __do_readl_be(addr)	in_be32(PCI_FIX_ADDR(addr))
57762306a36Sopenharmony_ci#define __do_readq_be(addr)	in_be64(PCI_FIX_ADDR(addr))
57862306a36Sopenharmony_ci#endif /* !defined(CONFIG_EEH) */
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci#ifdef CONFIG_PPC32
58162306a36Sopenharmony_ci#define __do_outb(val, port)	_rec_outb(val, port)
58262306a36Sopenharmony_ci#define __do_outw(val, port)	_rec_outw(val, port)
58362306a36Sopenharmony_ci#define __do_outl(val, port)	_rec_outl(val, port)
58462306a36Sopenharmony_ci#define __do_inb(port)		_rec_inb(port)
58562306a36Sopenharmony_ci#define __do_inw(port)		_rec_inw(port)
58662306a36Sopenharmony_ci#define __do_inl(port)		_rec_inl(port)
58762306a36Sopenharmony_ci#else /* CONFIG_PPC32 */
58862306a36Sopenharmony_ci#define __do_outb(val, port)	writeb(val,(PCI_IO_ADDR)_IO_BASE+port);
58962306a36Sopenharmony_ci#define __do_outw(val, port)	writew(val,(PCI_IO_ADDR)_IO_BASE+port);
59062306a36Sopenharmony_ci#define __do_outl(val, port)	writel(val,(PCI_IO_ADDR)_IO_BASE+port);
59162306a36Sopenharmony_ci#define __do_inb(port)		readb((PCI_IO_ADDR)_IO_BASE + port);
59262306a36Sopenharmony_ci#define __do_inw(port)		readw((PCI_IO_ADDR)_IO_BASE + port);
59362306a36Sopenharmony_ci#define __do_inl(port)		readl((PCI_IO_ADDR)_IO_BASE + port);
59462306a36Sopenharmony_ci#endif /* !CONFIG_PPC32 */
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci#ifdef CONFIG_EEH
59762306a36Sopenharmony_ci#define __do_readsb(a, b, n)	eeh_readsb(PCI_FIX_ADDR(a), (b), (n))
59862306a36Sopenharmony_ci#define __do_readsw(a, b, n)	eeh_readsw(PCI_FIX_ADDR(a), (b), (n))
59962306a36Sopenharmony_ci#define __do_readsl(a, b, n)	eeh_readsl(PCI_FIX_ADDR(a), (b), (n))
60062306a36Sopenharmony_ci#else /* CONFIG_EEH */
60162306a36Sopenharmony_ci#define __do_readsb(a, b, n)	_insb(PCI_FIX_ADDR(a), (b), (n))
60262306a36Sopenharmony_ci#define __do_readsw(a, b, n)	_insw(PCI_FIX_ADDR(a), (b), (n))
60362306a36Sopenharmony_ci#define __do_readsl(a, b, n)	_insl(PCI_FIX_ADDR(a), (b), (n))
60462306a36Sopenharmony_ci#endif /* !CONFIG_EEH */
60562306a36Sopenharmony_ci#define __do_writesb(a, b, n)	_outsb(PCI_FIX_ADDR(a),(b),(n))
60662306a36Sopenharmony_ci#define __do_writesw(a, b, n)	_outsw(PCI_FIX_ADDR(a),(b),(n))
60762306a36Sopenharmony_ci#define __do_writesl(a, b, n)	_outsl(PCI_FIX_ADDR(a),(b),(n))
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci#define __do_insb(p, b, n)	readsb((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
61062306a36Sopenharmony_ci#define __do_insw(p, b, n)	readsw((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
61162306a36Sopenharmony_ci#define __do_insl(p, b, n)	readsl((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
61262306a36Sopenharmony_ci#define __do_outsb(p, b, n)	writesb((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
61362306a36Sopenharmony_ci#define __do_outsw(p, b, n)	writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
61462306a36Sopenharmony_ci#define __do_outsl(p, b, n)	writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_ci#define __do_memset_io(addr, c, n)	\
61762306a36Sopenharmony_ci				_memset_io(PCI_FIX_ADDR(addr), c, n)
61862306a36Sopenharmony_ci#define __do_memcpy_toio(dst, src, n)	\
61962306a36Sopenharmony_ci				_memcpy_toio(PCI_FIX_ADDR(dst), src, n)
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci#ifdef CONFIG_EEH
62262306a36Sopenharmony_ci#define __do_memcpy_fromio(dst, src, n)	\
62362306a36Sopenharmony_ci				eeh_memcpy_fromio(dst, PCI_FIX_ADDR(src), n)
62462306a36Sopenharmony_ci#else /* CONFIG_EEH */
62562306a36Sopenharmony_ci#define __do_memcpy_fromio(dst, src, n)	\
62662306a36Sopenharmony_ci				_memcpy_fromio(dst,PCI_FIX_ADDR(src),n)
62762306a36Sopenharmony_ci#endif /* !CONFIG_EEH */
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci#ifdef CONFIG_PPC_INDIRECT_PIO
63062306a36Sopenharmony_ci#define DEF_PCI_HOOK_pio(x)	x
63162306a36Sopenharmony_ci#else
63262306a36Sopenharmony_ci#define DEF_PCI_HOOK_pio(x)	NULL
63362306a36Sopenharmony_ci#endif
63462306a36Sopenharmony_ci
63562306a36Sopenharmony_ci#ifdef CONFIG_PPC_INDIRECT_MMIO
63662306a36Sopenharmony_ci#define DEF_PCI_HOOK_mem(x)	x
63762306a36Sopenharmony_ci#else
63862306a36Sopenharmony_ci#define DEF_PCI_HOOK_mem(x)	NULL
63962306a36Sopenharmony_ci#endif
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci/* Structure containing all the hooks */
64262306a36Sopenharmony_ciextern struct ppc_pci_io {
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)	ret (*name) at;
64562306a36Sopenharmony_ci#define DEF_PCI_AC_NORET(name, at, al, space, aa)	void (*name) at;
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci#include <asm/io-defs.h>
64862306a36Sopenharmony_ci
64962306a36Sopenharmony_ci#undef DEF_PCI_AC_RET
65062306a36Sopenharmony_ci#undef DEF_PCI_AC_NORET
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci} ppc_pci_io;
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci/* The inline wrappers */
65562306a36Sopenharmony_ci#define DEF_PCI_AC_RET(name, ret, at, al, space, aa)		\
65662306a36Sopenharmony_cistatic inline ret name at					\
65762306a36Sopenharmony_ci{								\
65862306a36Sopenharmony_ci	if (DEF_PCI_HOOK_##space(ppc_pci_io.name) != NULL)	\
65962306a36Sopenharmony_ci		return ppc_pci_io.name al;			\
66062306a36Sopenharmony_ci	return __do_##name al;					\
66162306a36Sopenharmony_ci}
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci#define DEF_PCI_AC_NORET(name, at, al, space, aa)		\
66462306a36Sopenharmony_cistatic inline void name at					\
66562306a36Sopenharmony_ci{								\
66662306a36Sopenharmony_ci	if (DEF_PCI_HOOK_##space(ppc_pci_io.name) != NULL)		\
66762306a36Sopenharmony_ci		ppc_pci_io.name al;				\
66862306a36Sopenharmony_ci	else							\
66962306a36Sopenharmony_ci		__do_##name al;					\
67062306a36Sopenharmony_ci}
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci#include <asm/io-defs.h>
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci#undef DEF_PCI_AC_RET
67562306a36Sopenharmony_ci#undef DEF_PCI_AC_NORET
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci/* Some drivers check for the presence of readq & writeq with
67862306a36Sopenharmony_ci * a #ifdef, so we make them happy here.
67962306a36Sopenharmony_ci */
68062306a36Sopenharmony_ci#define readb readb
68162306a36Sopenharmony_ci#define readw readw
68262306a36Sopenharmony_ci#define readl readl
68362306a36Sopenharmony_ci#define writeb writeb
68462306a36Sopenharmony_ci#define writew writew
68562306a36Sopenharmony_ci#define writel writel
68662306a36Sopenharmony_ci#define readsb readsb
68762306a36Sopenharmony_ci#define readsw readsw
68862306a36Sopenharmony_ci#define readsl readsl
68962306a36Sopenharmony_ci#define writesb writesb
69062306a36Sopenharmony_ci#define writesw writesw
69162306a36Sopenharmony_ci#define writesl writesl
69262306a36Sopenharmony_ci#define inb inb
69362306a36Sopenharmony_ci#define inw inw
69462306a36Sopenharmony_ci#define inl inl
69562306a36Sopenharmony_ci#define outb outb
69662306a36Sopenharmony_ci#define outw outw
69762306a36Sopenharmony_ci#define outl outl
69862306a36Sopenharmony_ci#define insb insb
69962306a36Sopenharmony_ci#define insw insw
70062306a36Sopenharmony_ci#define insl insl
70162306a36Sopenharmony_ci#define outsb outsb
70262306a36Sopenharmony_ci#define outsw outsw
70362306a36Sopenharmony_ci#define outsl outsl
70462306a36Sopenharmony_ci#ifdef __powerpc64__
70562306a36Sopenharmony_ci#define readq	readq
70662306a36Sopenharmony_ci#define writeq	writeq
70762306a36Sopenharmony_ci#endif
70862306a36Sopenharmony_ci#define memset_io memset_io
70962306a36Sopenharmony_ci#define memcpy_fromio memcpy_fromio
71062306a36Sopenharmony_ci#define memcpy_toio memcpy_toio
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci/*
71362306a36Sopenharmony_ci * Convert a physical pointer to a virtual kernel pointer for /dev/mem
71462306a36Sopenharmony_ci * access
71562306a36Sopenharmony_ci */
71662306a36Sopenharmony_ci#define xlate_dev_mem_ptr(p)	__va(p)
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci/*
71962306a36Sopenharmony_ci * We don't do relaxed operations yet, at least not with this semantic
72062306a36Sopenharmony_ci */
72162306a36Sopenharmony_ci#define readb_relaxed(addr)	readb(addr)
72262306a36Sopenharmony_ci#define readw_relaxed(addr)	readw(addr)
72362306a36Sopenharmony_ci#define readl_relaxed(addr)	readl(addr)
72462306a36Sopenharmony_ci#define readq_relaxed(addr)	readq(addr)
72562306a36Sopenharmony_ci#define writeb_relaxed(v, addr)	writeb(v, addr)
72662306a36Sopenharmony_ci#define writew_relaxed(v, addr)	writew(v, addr)
72762306a36Sopenharmony_ci#define writel_relaxed(v, addr)	writel(v, addr)
72862306a36Sopenharmony_ci#define writeq_relaxed(v, addr)	writeq(v, addr)
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci#ifndef CONFIG_GENERIC_IOMAP
73162306a36Sopenharmony_ci/*
73262306a36Sopenharmony_ci * Here comes the implementation of the IOMAP interfaces.
73362306a36Sopenharmony_ci */
73462306a36Sopenharmony_cistatic inline unsigned int ioread16be(const void __iomem *addr)
73562306a36Sopenharmony_ci{
73662306a36Sopenharmony_ci	return readw_be(addr);
73762306a36Sopenharmony_ci}
73862306a36Sopenharmony_ci#define ioread16be ioread16be
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_cistatic inline unsigned int ioread32be(const void __iomem *addr)
74162306a36Sopenharmony_ci{
74262306a36Sopenharmony_ci	return readl_be(addr);
74362306a36Sopenharmony_ci}
74462306a36Sopenharmony_ci#define ioread32be ioread32be
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_ci#ifdef __powerpc64__
74762306a36Sopenharmony_cistatic inline u64 ioread64_lo_hi(const void __iomem *addr)
74862306a36Sopenharmony_ci{
74962306a36Sopenharmony_ci	return readq(addr);
75062306a36Sopenharmony_ci}
75162306a36Sopenharmony_ci#define ioread64_lo_hi ioread64_lo_hi
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_cistatic inline u64 ioread64_hi_lo(const void __iomem *addr)
75462306a36Sopenharmony_ci{
75562306a36Sopenharmony_ci	return readq(addr);
75662306a36Sopenharmony_ci}
75762306a36Sopenharmony_ci#define ioread64_hi_lo ioread64_hi_lo
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_cistatic inline u64 ioread64be(const void __iomem *addr)
76062306a36Sopenharmony_ci{
76162306a36Sopenharmony_ci	return readq_be(addr);
76262306a36Sopenharmony_ci}
76362306a36Sopenharmony_ci#define ioread64be ioread64be
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_cistatic inline u64 ioread64be_lo_hi(const void __iomem *addr)
76662306a36Sopenharmony_ci{
76762306a36Sopenharmony_ci	return readq_be(addr);
76862306a36Sopenharmony_ci}
76962306a36Sopenharmony_ci#define ioread64be_lo_hi ioread64be_lo_hi
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_cistatic inline u64 ioread64be_hi_lo(const void __iomem *addr)
77262306a36Sopenharmony_ci{
77362306a36Sopenharmony_ci	return readq_be(addr);
77462306a36Sopenharmony_ci}
77562306a36Sopenharmony_ci#define ioread64be_hi_lo ioread64be_hi_lo
77662306a36Sopenharmony_ci#endif /* __powerpc64__ */
77762306a36Sopenharmony_ci
77862306a36Sopenharmony_cistatic inline void iowrite16be(u16 val, void __iomem *addr)
77962306a36Sopenharmony_ci{
78062306a36Sopenharmony_ci	writew_be(val, addr);
78162306a36Sopenharmony_ci}
78262306a36Sopenharmony_ci#define iowrite16be iowrite16be
78362306a36Sopenharmony_ci
78462306a36Sopenharmony_cistatic inline void iowrite32be(u32 val, void __iomem *addr)
78562306a36Sopenharmony_ci{
78662306a36Sopenharmony_ci	writel_be(val, addr);
78762306a36Sopenharmony_ci}
78862306a36Sopenharmony_ci#define iowrite32be iowrite32be
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci#ifdef __powerpc64__
79162306a36Sopenharmony_cistatic inline void iowrite64_lo_hi(u64 val, void __iomem *addr)
79262306a36Sopenharmony_ci{
79362306a36Sopenharmony_ci	writeq(val, addr);
79462306a36Sopenharmony_ci}
79562306a36Sopenharmony_ci#define iowrite64_lo_hi iowrite64_lo_hi
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_cistatic inline void iowrite64_hi_lo(u64 val, void __iomem *addr)
79862306a36Sopenharmony_ci{
79962306a36Sopenharmony_ci	writeq(val, addr);
80062306a36Sopenharmony_ci}
80162306a36Sopenharmony_ci#define iowrite64_hi_lo iowrite64_hi_lo
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_cistatic inline void iowrite64be(u64 val, void __iomem *addr)
80462306a36Sopenharmony_ci{
80562306a36Sopenharmony_ci	writeq_be(val, addr);
80662306a36Sopenharmony_ci}
80762306a36Sopenharmony_ci#define iowrite64be iowrite64be
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_cistatic inline void iowrite64be_lo_hi(u64 val, void __iomem *addr)
81062306a36Sopenharmony_ci{
81162306a36Sopenharmony_ci	writeq_be(val, addr);
81262306a36Sopenharmony_ci}
81362306a36Sopenharmony_ci#define iowrite64be_lo_hi iowrite64be_lo_hi
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_cistatic inline void iowrite64be_hi_lo(u64 val, void __iomem *addr)
81662306a36Sopenharmony_ci{
81762306a36Sopenharmony_ci	writeq_be(val, addr);
81862306a36Sopenharmony_ci}
81962306a36Sopenharmony_ci#define iowrite64be_hi_lo iowrite64be_hi_lo
82062306a36Sopenharmony_ci#endif /* __powerpc64__ */
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_cistruct pci_dev;
82362306a36Sopenharmony_civoid pci_iounmap(struct pci_dev *dev, void __iomem *addr);
82462306a36Sopenharmony_ci#define pci_iounmap pci_iounmap
82562306a36Sopenharmony_civoid __iomem *ioport_map(unsigned long port, unsigned int len);
82662306a36Sopenharmony_ci#define ioport_map ioport_map
82762306a36Sopenharmony_ci#endif
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_cistatic inline void iosync(void)
83062306a36Sopenharmony_ci{
83162306a36Sopenharmony_ci        __asm__ __volatile__ ("sync" : : : "memory");
83262306a36Sopenharmony_ci}
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci/* Enforce in-order execution of data I/O.
83562306a36Sopenharmony_ci * No distinction between read/write on PPC; use eieio for all three.
83662306a36Sopenharmony_ci * Those are fairly week though. They don't provide a barrier between
83762306a36Sopenharmony_ci * MMIO and cacheable storage nor do they provide a barrier vs. locks,
83862306a36Sopenharmony_ci * they only provide barriers between 2 __raw MMIO operations and
83962306a36Sopenharmony_ci * possibly break write combining.
84062306a36Sopenharmony_ci */
84162306a36Sopenharmony_ci#define iobarrier_rw() eieio()
84262306a36Sopenharmony_ci#define iobarrier_r()  eieio()
84362306a36Sopenharmony_ci#define iobarrier_w()  eieio()
84462306a36Sopenharmony_ci
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci/*
84762306a36Sopenharmony_ci * output pause versions need a delay at least for the
84862306a36Sopenharmony_ci * w83c105 ide controller in a p610.
84962306a36Sopenharmony_ci */
85062306a36Sopenharmony_ci#define inb_p(port)             inb(port)
85162306a36Sopenharmony_ci#define outb_p(val, port)       (udelay(1), outb((val), (port)))
85262306a36Sopenharmony_ci#define inw_p(port)             inw(port)
85362306a36Sopenharmony_ci#define outw_p(val, port)       (udelay(1), outw((val), (port)))
85462306a36Sopenharmony_ci#define inl_p(port)             inl(port)
85562306a36Sopenharmony_ci#define outl_p(val, port)       (udelay(1), outl((val), (port)))
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci#define IO_SPACE_LIMIT ~(0UL)
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci/**
86162306a36Sopenharmony_ci * ioremap     -   map bus memory into CPU space
86262306a36Sopenharmony_ci * @address:   bus address of the memory
86362306a36Sopenharmony_ci * @size:      size of the resource to map
86462306a36Sopenharmony_ci *
86562306a36Sopenharmony_ci * ioremap performs a platform specific sequence of operations to
86662306a36Sopenharmony_ci * make bus memory CPU accessible via the readb/readw/readl/writeb/
86762306a36Sopenharmony_ci * writew/writel functions and the other mmio helpers. The returned
86862306a36Sopenharmony_ci * address is not guaranteed to be usable directly as a virtual
86962306a36Sopenharmony_ci * address.
87062306a36Sopenharmony_ci *
87162306a36Sopenharmony_ci * We provide a few variations of it:
87262306a36Sopenharmony_ci *
87362306a36Sopenharmony_ci * * ioremap is the standard one and provides non-cacheable guarded mappings
87462306a36Sopenharmony_ci *   and can be hooked by the platform via ppc_md
87562306a36Sopenharmony_ci *
87662306a36Sopenharmony_ci * * ioremap_prot allows to specify the page flags as an argument and can
87762306a36Sopenharmony_ci *   also be hooked by the platform via ppc_md.
87862306a36Sopenharmony_ci *
87962306a36Sopenharmony_ci * * ioremap_wc enables write combining
88062306a36Sopenharmony_ci *
88162306a36Sopenharmony_ci * * ioremap_wt enables write through
88262306a36Sopenharmony_ci *
88362306a36Sopenharmony_ci * * ioremap_coherent maps coherent cached memory
88462306a36Sopenharmony_ci *
88562306a36Sopenharmony_ci * * iounmap undoes such a mapping and can be hooked
88662306a36Sopenharmony_ci *
88762306a36Sopenharmony_ci * * __ioremap_caller is the same as above but takes an explicit caller
88862306a36Sopenharmony_ci *   reference rather than using __builtin_return_address(0)
88962306a36Sopenharmony_ci *
89062306a36Sopenharmony_ci */
89162306a36Sopenharmony_ciextern void __iomem *ioremap(phys_addr_t address, unsigned long size);
89262306a36Sopenharmony_ci#define ioremap ioremap
89362306a36Sopenharmony_ci#define ioremap_prot ioremap_prot
89462306a36Sopenharmony_ciextern void __iomem *ioremap_wc(phys_addr_t address, unsigned long size);
89562306a36Sopenharmony_ci#define ioremap_wc ioremap_wc
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci#ifdef CONFIG_PPC32
89862306a36Sopenharmony_civoid __iomem *ioremap_wt(phys_addr_t address, unsigned long size);
89962306a36Sopenharmony_ci#define ioremap_wt ioremap_wt
90062306a36Sopenharmony_ci#endif
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_civoid __iomem *ioremap_coherent(phys_addr_t address, unsigned long size);
90362306a36Sopenharmony_ci#define ioremap_uc(addr, size)		ioremap((addr), (size))
90462306a36Sopenharmony_ci#define ioremap_cache(addr, size) \
90562306a36Sopenharmony_ci	ioremap_prot((addr), (size), pgprot_val(PAGE_KERNEL))
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci#define iounmap iounmap
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_civoid __iomem *ioremap_phb(phys_addr_t paddr, unsigned long size);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ciint early_ioremap_range(unsigned long ea, phys_addr_t pa,
91262306a36Sopenharmony_ci			unsigned long size, pgprot_t prot);
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ciextern void __iomem *__ioremap_caller(phys_addr_t, unsigned long size,
91562306a36Sopenharmony_ci				      pgprot_t prot, void *caller);
91662306a36Sopenharmony_ci
91762306a36Sopenharmony_ci/*
91862306a36Sopenharmony_ci * When CONFIG_PPC_INDIRECT_PIO is set, we use the generic iomap implementation
91962306a36Sopenharmony_ci * which needs some additional definitions here. They basically allow PIO
92062306a36Sopenharmony_ci * space overall to be 1GB. This will work as long as we never try to use
92162306a36Sopenharmony_ci * iomap to map MMIO below 1GB which should be fine on ppc64
92262306a36Sopenharmony_ci */
92362306a36Sopenharmony_ci#define HAVE_ARCH_PIO_SIZE		1
92462306a36Sopenharmony_ci#define PIO_OFFSET			0x00000000UL
92562306a36Sopenharmony_ci#define PIO_MASK			(FULL_IO_SIZE - 1)
92662306a36Sopenharmony_ci#define PIO_RESERVED			(FULL_IO_SIZE)
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci#define mmio_read16be(addr)		readw_be(addr)
92962306a36Sopenharmony_ci#define mmio_read32be(addr)		readl_be(addr)
93062306a36Sopenharmony_ci#define mmio_read64be(addr)		readq_be(addr)
93162306a36Sopenharmony_ci#define mmio_write16be(val, addr)	writew_be(val, addr)
93262306a36Sopenharmony_ci#define mmio_write32be(val, addr)	writel_be(val, addr)
93362306a36Sopenharmony_ci#define mmio_write64be(val, addr)	writeq_be(val, addr)
93462306a36Sopenharmony_ci#define mmio_insb(addr, dst, count)	readsb(addr, dst, count)
93562306a36Sopenharmony_ci#define mmio_insw(addr, dst, count)	readsw(addr, dst, count)
93662306a36Sopenharmony_ci#define mmio_insl(addr, dst, count)	readsl(addr, dst, count)
93762306a36Sopenharmony_ci#define mmio_outsb(addr, src, count)	writesb(addr, src, count)
93862306a36Sopenharmony_ci#define mmio_outsw(addr, src, count)	writesw(addr, src, count)
93962306a36Sopenharmony_ci#define mmio_outsl(addr, src, count)	writesl(addr, src, count)
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci/**
94262306a36Sopenharmony_ci *	virt_to_phys	-	map virtual addresses to physical
94362306a36Sopenharmony_ci *	@address: address to remap
94462306a36Sopenharmony_ci *
94562306a36Sopenharmony_ci *	The returned physical address is the physical (CPU) mapping for
94662306a36Sopenharmony_ci *	the memory address given. It is only valid to use this function on
94762306a36Sopenharmony_ci *	addresses directly mapped or allocated via kmalloc.
94862306a36Sopenharmony_ci *
94962306a36Sopenharmony_ci *	This function does not give bus mappings for DMA transfers. In
95062306a36Sopenharmony_ci *	almost all conceivable cases a device driver should not be using
95162306a36Sopenharmony_ci *	this function
95262306a36Sopenharmony_ci */
95362306a36Sopenharmony_cistatic inline unsigned long virt_to_phys(volatile void * address)
95462306a36Sopenharmony_ci{
95562306a36Sopenharmony_ci	WARN_ON(IS_ENABLED(CONFIG_DEBUG_VIRTUAL) && !virt_addr_valid(address));
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	return __pa((unsigned long)address);
95862306a36Sopenharmony_ci}
95962306a36Sopenharmony_ci#define virt_to_phys virt_to_phys
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci/**
96262306a36Sopenharmony_ci *	phys_to_virt	-	map physical address to virtual
96362306a36Sopenharmony_ci *	@address: address to remap
96462306a36Sopenharmony_ci *
96562306a36Sopenharmony_ci *	The returned virtual address is a current CPU mapping for
96662306a36Sopenharmony_ci *	the memory address given. It is only valid to use this function on
96762306a36Sopenharmony_ci *	addresses that have a kernel mapping
96862306a36Sopenharmony_ci *
96962306a36Sopenharmony_ci *	This function does not handle bus mappings for DMA transfers. In
97062306a36Sopenharmony_ci *	almost all conceivable cases a device driver should not be using
97162306a36Sopenharmony_ci *	this function
97262306a36Sopenharmony_ci */
97362306a36Sopenharmony_cistatic inline void * phys_to_virt(unsigned long address)
97462306a36Sopenharmony_ci{
97562306a36Sopenharmony_ci	return (void *)__va(address);
97662306a36Sopenharmony_ci}
97762306a36Sopenharmony_ci#define phys_to_virt phys_to_virt
97862306a36Sopenharmony_ci
97962306a36Sopenharmony_ci/*
98062306a36Sopenharmony_ci * Change "struct page" to physical address.
98162306a36Sopenharmony_ci */
98262306a36Sopenharmony_cistatic inline phys_addr_t page_to_phys(struct page *page)
98362306a36Sopenharmony_ci{
98462306a36Sopenharmony_ci	unsigned long pfn = page_to_pfn(page);
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_ci	WARN_ON(IS_ENABLED(CONFIG_DEBUG_VIRTUAL) && !pfn_valid(pfn));
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	return PFN_PHYS(pfn);
98962306a36Sopenharmony_ci}
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci/*
99262306a36Sopenharmony_ci * 32 bits still uses virt_to_bus() for it's implementation of DMA
99362306a36Sopenharmony_ci * mappings se we have to keep it defined here. We also have some old
99462306a36Sopenharmony_ci * drivers (shame shame shame) that use bus_to_virt() and haven't been
99562306a36Sopenharmony_ci * fixed yet so I need to define it here.
99662306a36Sopenharmony_ci */
99762306a36Sopenharmony_ci#ifdef CONFIG_PPC32
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_cistatic inline unsigned long virt_to_bus(volatile void * address)
100062306a36Sopenharmony_ci{
100162306a36Sopenharmony_ci        if (address == NULL)
100262306a36Sopenharmony_ci		return 0;
100362306a36Sopenharmony_ci        return __pa(address) + PCI_DRAM_OFFSET;
100462306a36Sopenharmony_ci}
100562306a36Sopenharmony_ci#define virt_to_bus virt_to_bus
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_cistatic inline void * bus_to_virt(unsigned long address)
100862306a36Sopenharmony_ci{
100962306a36Sopenharmony_ci        if (address == 0)
101062306a36Sopenharmony_ci		return NULL;
101162306a36Sopenharmony_ci        return __va(address - PCI_DRAM_OFFSET);
101262306a36Sopenharmony_ci}
101362306a36Sopenharmony_ci#define bus_to_virt bus_to_virt
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci#endif /* CONFIG_PPC32 */
101662306a36Sopenharmony_ci
101762306a36Sopenharmony_ci/* access ports */
101862306a36Sopenharmony_ci#define setbits32(_addr, _v) out_be32((_addr), in_be32(_addr) |  (_v))
101962306a36Sopenharmony_ci#define clrbits32(_addr, _v) out_be32((_addr), in_be32(_addr) & ~(_v))
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci#define setbits16(_addr, _v) out_be16((_addr), in_be16(_addr) |  (_v))
102262306a36Sopenharmony_ci#define clrbits16(_addr, _v) out_be16((_addr), in_be16(_addr) & ~(_v))
102362306a36Sopenharmony_ci
102462306a36Sopenharmony_ci#define setbits8(_addr, _v) out_8((_addr), in_8(_addr) |  (_v))
102562306a36Sopenharmony_ci#define clrbits8(_addr, _v) out_8((_addr), in_8(_addr) & ~(_v))
102662306a36Sopenharmony_ci
102762306a36Sopenharmony_ci/* Clear and set bits in one shot.  These macros can be used to clear and
102862306a36Sopenharmony_ci * set multiple bits in a register using a single read-modify-write.  These
102962306a36Sopenharmony_ci * macros can also be used to set a multiple-bit bit pattern using a mask,
103062306a36Sopenharmony_ci * by specifying the mask in the 'clear' parameter and the new bit pattern
103162306a36Sopenharmony_ci * in the 'set' parameter.
103262306a36Sopenharmony_ci */
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci#define clrsetbits(type, addr, clear, set) \
103562306a36Sopenharmony_ci	out_##type((addr), (in_##type(addr) & ~(clear)) | (set))
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci#ifdef __powerpc64__
103862306a36Sopenharmony_ci#define clrsetbits_be64(addr, clear, set) clrsetbits(be64, addr, clear, set)
103962306a36Sopenharmony_ci#define clrsetbits_le64(addr, clear, set) clrsetbits(le64, addr, clear, set)
104062306a36Sopenharmony_ci#endif
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_ci#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set)
104362306a36Sopenharmony_ci#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set)
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set)
104662306a36Sopenharmony_ci#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set)
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set)
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci#include <asm-generic/io.h>
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci#endif /* __KERNEL__ */
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci#endif /* _ASM_POWERPC_IO_H */
1055