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