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