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