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