1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */ 2cd248341SJan Glauber #ifndef _ASM_S390_PCI_IO_H 3cd248341SJan Glauber #define _ASM_S390_PCI_IO_H 4cd248341SJan Glauber 5cd248341SJan Glauber #ifdef CONFIG_PCI 6cd248341SJan Glauber 7cd248341SJan Glauber #include <linux/kernel.h> 8cd248341SJan Glauber #include <linux/slab.h> 9cd248341SJan Glauber #include <asm/pci_insn.h> 10cd248341SJan Glauber 11f058599eSNiklas Schnelle /* I/O size constraints */ 12f058599eSNiklas Schnelle #define ZPCI_MAX_READ_SIZE 8 13f058599eSNiklas Schnelle #define ZPCI_MAX_WRITE_SIZE 128 14f058599eSNiklas Schnelle 15cd248341SJan Glauber /* I/O Map */ 16bf19c94dSSebastian Ott #define ZPCI_IOMAP_SHIFT 48 17bf19c94dSSebastian Ott #define ZPCI_IOMAP_ADDR_BASE 0x8000000000000000UL 18bf19c94dSSebastian Ott #define ZPCI_IOMAP_ADDR_OFF_MASK ((1UL << ZPCI_IOMAP_SHIFT) - 1) 19bf19c94dSSebastian Ott #define ZPCI_IOMAP_MAX_ENTRIES \ 20bf19c94dSSebastian Ott ((ULONG_MAX - ZPCI_IOMAP_ADDR_BASE + 1) / (1UL << ZPCI_IOMAP_SHIFT)) 21bf19c94dSSebastian Ott #define ZPCI_IOMAP_ADDR_IDX_MASK \ 22bf19c94dSSebastian Ott (~ZPCI_IOMAP_ADDR_OFF_MASK - ZPCI_IOMAP_ADDR_BASE) 23cd248341SJan Glauber 24cd248341SJan Glauber struct zpci_iomap_entry { 25cd248341SJan Glauber u32 fh; 26cd248341SJan Glauber u8 bar; 278cfc99b5SMichael S. Tsirkin u16 count; 28cd248341SJan Glauber }; 29cd248341SJan Glauber 30cd248341SJan Glauber extern struct zpci_iomap_entry *zpci_iomap_start; 31cd248341SJan Glauber 32bf19c94dSSebastian Ott #define ZPCI_ADDR(idx) (ZPCI_IOMAP_ADDR_BASE | ((u64) idx << ZPCI_IOMAP_SHIFT)) 33cd248341SJan Glauber #define ZPCI_IDX(addr) \ 34bf19c94dSSebastian Ott (((__force u64) addr & ZPCI_IOMAP_ADDR_IDX_MASK) >> ZPCI_IOMAP_SHIFT) 35cd248341SJan Glauber #define ZPCI_OFFSET(addr) \ 36cd248341SJan Glauber ((__force u64) addr & ZPCI_IOMAP_ADDR_OFF_MASK) 37cd248341SJan Glauber 38cd248341SJan Glauber #define ZPCI_CREATE_REQ(handle, space, len) \ 39cd248341SJan Glauber ((u64) handle << 32 | space << 16 | len) 40cd248341SJan Glauber 41cd248341SJan Glauber #define zpci_read(LENGTH, RETTYPE) \ 42cd248341SJan Glauber static inline RETTYPE zpci_read_##RETTYPE(const volatile void __iomem *addr) \ 43cd248341SJan Glauber { \ 44cd248341SJan Glauber u64 data; \ 45cd248341SJan Glauber int rc; \ 46cd248341SJan Glauber \ 4781deca12SSebastian Ott rc = zpci_load(&data, addr, LENGTH); \ 48cd248341SJan Glauber if (rc) \ 49cd248341SJan Glauber data = -1ULL; \ 50cd248341SJan Glauber return (RETTYPE) data; \ 51cd248341SJan Glauber } 52cd248341SJan Glauber 53cd248341SJan Glauber #define zpci_write(LENGTH, VALTYPE) \ 54cd248341SJan Glauber static inline void zpci_write_##VALTYPE(VALTYPE val, \ 55cd248341SJan Glauber const volatile void __iomem *addr) \ 56cd248341SJan Glauber { \ 57cd248341SJan Glauber u64 data = (VALTYPE) val; \ 58cd248341SJan Glauber \ 5981deca12SSebastian Ott zpci_store(addr, data, LENGTH); \ 60cd248341SJan Glauber } 61cd248341SJan Glauber 62cd248341SJan Glauber zpci_read(8, u64) 63cd248341SJan Glauber zpci_read(4, u32) 64cd248341SJan Glauber zpci_read(2, u16) 65cd248341SJan Glauber zpci_read(1, u8) 66cd248341SJan Glauber zpci_write(8, u64) 67cd248341SJan Glauber zpci_write(4, u32) 68cd248341SJan Glauber zpci_write(2, u16) 69cd248341SJan Glauber zpci_write(1, u8) 70cd248341SJan Glauber 7181deca12SSebastian Ott static inline int zpci_write_single(volatile void __iomem *dst, const void *src, 7281deca12SSebastian Ott unsigned long len) 73cd248341SJan Glauber { 74cd248341SJan Glauber u64 val; 75cd248341SJan Glauber 76cd248341SJan Glauber switch (len) { 77cd248341SJan Glauber case 1: 7881deca12SSebastian Ott val = (u64) *((u8 *) src); 79cd248341SJan Glauber break; 80cd248341SJan Glauber case 2: 8181deca12SSebastian Ott val = (u64) *((u16 *) src); 82cd248341SJan Glauber break; 83cd248341SJan Glauber case 4: 8481deca12SSebastian Ott val = (u64) *((u32 *) src); 85cd248341SJan Glauber break; 86cd248341SJan Glauber case 8: 8781deca12SSebastian Ott val = (u64) *((u64 *) src); 88cd248341SJan Glauber break; 89cd248341SJan Glauber default: 90cd248341SJan Glauber val = 0; /* let FW report error */ 91cd248341SJan Glauber break; 92cd248341SJan Glauber } 9381deca12SSebastian Ott return zpci_store(dst, val, len); 94cd248341SJan Glauber } 95cd248341SJan Glauber 9681deca12SSebastian Ott static inline int zpci_read_single(void *dst, const volatile void __iomem *src, 9781deca12SSebastian Ott unsigned long len) 98cd248341SJan Glauber { 99cd248341SJan Glauber u64 data; 100f0bacb7fSSebastian Ott int cc; 101cd248341SJan Glauber 10281deca12SSebastian Ott cc = zpci_load(&data, src, len); 103b170bad4SSebastian Ott if (cc) 104b170bad4SSebastian Ott goto out; 105b170bad4SSebastian Ott 106cd248341SJan Glauber switch (len) { 107cd248341SJan Glauber case 1: 108cd248341SJan Glauber *((u8 *) dst) = (u8) data; 109cd248341SJan Glauber break; 110cd248341SJan Glauber case 2: 111cd248341SJan Glauber *((u16 *) dst) = (u16) data; 112cd248341SJan Glauber break; 113cd248341SJan Glauber case 4: 114cd248341SJan Glauber *((u32 *) dst) = (u32) data; 115cd248341SJan Glauber break; 116cd248341SJan Glauber case 8: 117cd248341SJan Glauber *((u64 *) dst) = (u64) data; 118cd248341SJan Glauber break; 119cd248341SJan Glauber } 120b170bad4SSebastian Ott out: 121cd248341SJan Glauber return cc; 122cd248341SJan Glauber } 123cd248341SJan Glauber 12481deca12SSebastian Ott int zpci_write_block(volatile void __iomem *dst, const void *src, 12581deca12SSebastian Ott unsigned long len); 126cd248341SJan Glauber 127cd248341SJan Glauber static inline u8 zpci_get_max_write_size(u64 src, u64 dst, int len, int max) 128cd248341SJan Glauber { 129cd248341SJan Glauber int count = len > max ? max : len, size = 1; 130cd248341SJan Glauber 131cd248341SJan Glauber while (!(src & 0x1) && !(dst & 0x1) && ((size << 1) <= count)) { 132cd248341SJan Glauber dst = dst >> 1; 133cd248341SJan Glauber src = src >> 1; 134cd248341SJan Glauber size = size << 1; 135cd248341SJan Glauber } 136cd248341SJan Glauber return size; 137cd248341SJan Glauber } 138cd248341SJan Glauber 139cd248341SJan Glauber static inline int zpci_memcpy_fromio(void *dst, 140cd248341SJan Glauber const volatile void __iomem *src, 141cd248341SJan Glauber unsigned long n) 142cd248341SJan Glauber { 143cd248341SJan Glauber int size, rc = 0; 144cd248341SJan Glauber 145cd248341SJan Glauber while (n > 0) { 1465b9f2081SMartin Schwidefsky size = zpci_get_max_write_size((u64 __force) src, 147f058599eSNiklas Schnelle (u64) dst, n, 148f058599eSNiklas Schnelle ZPCI_MAX_READ_SIZE); 14981deca12SSebastian Ott rc = zpci_read_single(dst, src, size); 150cd248341SJan Glauber if (rc) 151cd248341SJan Glauber break; 15281deca12SSebastian Ott src += size; 153cd248341SJan Glauber dst += size; 154cd248341SJan Glauber n -= size; 155cd248341SJan Glauber } 156cd248341SJan Glauber return rc; 157cd248341SJan Glauber } 158cd248341SJan Glauber 159cd248341SJan Glauber static inline int zpci_memcpy_toio(volatile void __iomem *dst, 160cd248341SJan Glauber const void *src, unsigned long n) 161cd248341SJan Glauber { 162cd248341SJan Glauber int size, rc = 0; 163cd248341SJan Glauber 164cd248341SJan Glauber if (!src) 165cd248341SJan Glauber return -EINVAL; 166cd248341SJan Glauber 167cd248341SJan Glauber while (n > 0) { 1685b9f2081SMartin Schwidefsky size = zpci_get_max_write_size((u64 __force) dst, 169f058599eSNiklas Schnelle (u64) src, n, 170f058599eSNiklas Schnelle ZPCI_MAX_WRITE_SIZE); 171cd248341SJan Glauber if (size > 8) /* main path */ 17281deca12SSebastian Ott rc = zpci_write_block(dst, src, size); 173cd248341SJan Glauber else 17481deca12SSebastian Ott rc = zpci_write_single(dst, src, size); 175cd248341SJan Glauber if (rc) 176cd248341SJan Glauber break; 177cd248341SJan Glauber src += size; 17881deca12SSebastian Ott dst += size; 179cd248341SJan Glauber n -= size; 180cd248341SJan Glauber } 181cd248341SJan Glauber return rc; 182cd248341SJan Glauber } 183cd248341SJan Glauber 184cd248341SJan Glauber static inline int zpci_memset_io(volatile void __iomem *dst, 185cd248341SJan Glauber unsigned char val, size_t count) 186cd248341SJan Glauber { 187cd248341SJan Glauber u8 *src = kmalloc(count, GFP_KERNEL); 188cd248341SJan Glauber int rc; 189cd248341SJan Glauber 190cd248341SJan Glauber if (src == NULL) 191cd248341SJan Glauber return -ENOMEM; 192cd248341SJan Glauber memset(src, val, count); 193cd248341SJan Glauber 194cd248341SJan Glauber rc = zpci_memcpy_toio(dst, src, count); 195cd248341SJan Glauber kfree(src); 196cd248341SJan Glauber return rc; 197cd248341SJan Glauber } 198cd248341SJan Glauber 199cd248341SJan Glauber #endif /* CONFIG_PCI */ 200cd248341SJan Glauber 201cd248341SJan Glauber #endif /* _ASM_S390_PCI_IO_H */ 202