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