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