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