1 #ifndef _ASM_S390_PCI_INSN_H 2 #define _ASM_S390_PCI_INSN_H 3 4 #include <linux/delay.h> 5 6 #define ZPCI_INSN_BUSY_DELAY 1 /* 1 microsecond */ 7 8 /* Load/Store status codes */ 9 #define ZPCI_PCI_ST_FUNC_NOT_ENABLED 4 10 #define ZPCI_PCI_ST_FUNC_IN_ERR 8 11 #define ZPCI_PCI_ST_BLOCKED 12 12 #define ZPCI_PCI_ST_INSUF_RES 16 13 #define ZPCI_PCI_ST_INVAL_AS 20 14 #define ZPCI_PCI_ST_FUNC_ALREADY_ENABLED 24 15 #define ZPCI_PCI_ST_DMA_AS_NOT_ENABLED 28 16 #define ZPCI_PCI_ST_2ND_OP_IN_INV_AS 36 17 #define ZPCI_PCI_ST_FUNC_NOT_AVAIL 40 18 #define ZPCI_PCI_ST_ALREADY_IN_RQ_STATE 44 19 20 /* Load/Store return codes */ 21 #define ZPCI_PCI_LS_OK 0 22 #define ZPCI_PCI_LS_ERR 1 23 #define ZPCI_PCI_LS_BUSY 2 24 #define ZPCI_PCI_LS_INVAL_HANDLE 3 25 26 /* Load/Store address space identifiers */ 27 #define ZPCI_PCIAS_MEMIO_0 0 28 #define ZPCI_PCIAS_MEMIO_1 1 29 #define ZPCI_PCIAS_MEMIO_2 2 30 #define ZPCI_PCIAS_MEMIO_3 3 31 #define ZPCI_PCIAS_MEMIO_4 4 32 #define ZPCI_PCIAS_MEMIO_5 5 33 #define ZPCI_PCIAS_CFGSPC 15 34 35 /* Modify PCI Function Controls */ 36 #define ZPCI_MOD_FC_REG_INT 2 37 #define ZPCI_MOD_FC_DEREG_INT 3 38 #define ZPCI_MOD_FC_REG_IOAT 4 39 #define ZPCI_MOD_FC_DEREG_IOAT 5 40 #define ZPCI_MOD_FC_REREG_IOAT 6 41 #define ZPCI_MOD_FC_RESET_ERROR 7 42 #define ZPCI_MOD_FC_RESET_BLOCK 9 43 #define ZPCI_MOD_FC_SET_MEASURE 10 44 45 /* FIB function controls */ 46 #define ZPCI_FIB_FC_ENABLED 0x80 47 #define ZPCI_FIB_FC_ERROR 0x40 48 #define ZPCI_FIB_FC_LS_BLOCKED 0x20 49 #define ZPCI_FIB_FC_DMAAS_REG 0x10 50 51 /* FIB function controls */ 52 #define ZPCI_FIB_FC_ENABLED 0x80 53 #define ZPCI_FIB_FC_ERROR 0x40 54 #define ZPCI_FIB_FC_LS_BLOCKED 0x20 55 #define ZPCI_FIB_FC_DMAAS_REG 0x10 56 57 /* Function Information Block */ 58 struct zpci_fib { 59 u32 fmt : 8; /* format */ 60 u32 : 24; 61 u32 reserved1; 62 u8 fc; /* function controls */ 63 u8 reserved2; 64 u16 reserved3; 65 u32 reserved4; 66 u64 pba; /* PCI base address */ 67 u64 pal; /* PCI address limit */ 68 u64 iota; /* I/O Translation Anchor */ 69 u32 : 1; 70 u32 isc : 3; /* Interrupt subclass */ 71 u32 noi : 12; /* Number of interrupts */ 72 u32 : 2; 73 u32 aibvo : 6; /* Adapter interrupt bit vector offset */ 74 u32 sum : 1; /* Adapter int summary bit enabled */ 75 u32 : 1; 76 u32 aisbo : 6; /* Adapter int summary bit offset */ 77 u32 reserved5; 78 u64 aibv; /* Adapter int bit vector address */ 79 u64 aisb; /* Adapter int summary bit address */ 80 u64 fmb_addr; /* Function measurement block address and key */ 81 u64 reserved6; 82 u64 reserved7; 83 } __packed; 84 85 /* Modify PCI Function Controls */ 86 static inline u8 __mpcifc(u64 req, struct zpci_fib *fib, u8 *status) 87 { 88 u8 cc; 89 90 asm volatile ( 91 " .insn rxy,0xe300000000d0,%[req],%[fib]\n" 92 " ipm %[cc]\n" 93 " srl %[cc],28\n" 94 : [cc] "=d" (cc), [req] "+d" (req), [fib] "+Q" (*fib) 95 : : "cc"); 96 *status = req >> 24 & 0xff; 97 return cc; 98 } 99 100 static inline int mpcifc_instr(u64 req, struct zpci_fib *fib) 101 { 102 u8 cc, status; 103 104 do { 105 cc = __mpcifc(req, fib, &status); 106 if (cc == 2) 107 msleep(ZPCI_INSN_BUSY_DELAY); 108 } while (cc == 2); 109 110 if (cc) 111 printk_once(KERN_ERR "%s: error cc: %d status: %d\n", 112 __func__, cc, status); 113 return (cc) ? -EIO : 0; 114 } 115 116 /* Refresh PCI Translations */ 117 static inline u8 __rpcit(u64 fn, u64 addr, u64 range, u8 *status) 118 { 119 register u64 __addr asm("2") = addr; 120 register u64 __range asm("3") = range; 121 u8 cc; 122 123 asm volatile ( 124 " .insn rre,0xb9d30000,%[fn],%[addr]\n" 125 " ipm %[cc]\n" 126 " srl %[cc],28\n" 127 : [cc] "=d" (cc), [fn] "+d" (fn) 128 : [addr] "d" (__addr), "d" (__range) 129 : "cc"); 130 *status = fn >> 24 & 0xff; 131 return cc; 132 } 133 134 static inline int rpcit_instr(u64 fn, u64 addr, u64 range) 135 { 136 u8 cc, status; 137 138 do { 139 cc = __rpcit(fn, addr, range, &status); 140 if (cc == 2) 141 udelay(ZPCI_INSN_BUSY_DELAY); 142 } while (cc == 2); 143 144 if (cc) 145 printk_once(KERN_ERR "%s: error cc: %d status: %d dma_addr: %Lx size: %Lx\n", 146 __func__, cc, status, addr, range); 147 return (cc) ? -EIO : 0; 148 } 149 150 /* Store PCI function controls */ 151 static inline u8 __stpcifc(u32 handle, u8 space, struct zpci_fib *fib, u8 *status) 152 { 153 u64 fn = (u64) handle << 32 | space << 16; 154 u8 cc; 155 156 asm volatile ( 157 " .insn rxy,0xe300000000d4,%[fn],%[fib]\n" 158 " ipm %[cc]\n" 159 " srl %[cc],28\n" 160 : [cc] "=d" (cc), [fn] "+d" (fn), [fib] "=m" (*fib) 161 : : "cc"); 162 *status = fn >> 24 & 0xff; 163 return cc; 164 } 165 166 /* Set Interruption Controls */ 167 static inline void sic_instr(u16 ctl, char *unused, u8 isc) 168 { 169 asm volatile ( 170 " .insn rsy,0xeb00000000d1,%[ctl],%[isc],%[u]\n" 171 : : [ctl] "d" (ctl), [isc] "d" (isc << 27), [u] "Q" (*unused)); 172 } 173 174 /* PCI Load */ 175 static inline u8 __pcilg(u64 *data, u64 req, u64 offset, u8 *status) 176 { 177 register u64 __req asm("2") = req; 178 register u64 __offset asm("3") = offset; 179 u64 __data; 180 u8 cc; 181 182 asm volatile ( 183 " .insn rre,0xb9d20000,%[data],%[req]\n" 184 " ipm %[cc]\n" 185 " srl %[cc],28\n" 186 : [cc] "=d" (cc), [data] "=d" (__data), [req] "+d" (__req) 187 : "d" (__offset) 188 : "cc"); 189 *status = __req >> 24 & 0xff; 190 *data = __data; 191 return cc; 192 } 193 194 static inline int pcilg_instr(u64 *data, u64 req, u64 offset) 195 { 196 u8 cc, status; 197 198 do { 199 cc = __pcilg(data, req, offset, &status); 200 if (cc == 2) 201 udelay(ZPCI_INSN_BUSY_DELAY); 202 } while (cc == 2); 203 204 if (cc) { 205 printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n", 206 __func__, cc, status, req, offset); 207 /* TODO: on IO errors set data to 0xff... 208 * here or in users of pcilg (le conversion)? 209 */ 210 } 211 return (cc) ? -EIO : 0; 212 } 213 214 /* PCI Store */ 215 static inline u8 __pcistg(u64 data, u64 req, u64 offset, u8 *status) 216 { 217 register u64 __req asm("2") = req; 218 register u64 __offset asm("3") = offset; 219 u8 cc; 220 221 asm volatile ( 222 " .insn rre,0xb9d00000,%[data],%[req]\n" 223 " ipm %[cc]\n" 224 " srl %[cc],28\n" 225 : [cc] "=d" (cc), [req] "+d" (__req) 226 : "d" (__offset), [data] "d" (data) 227 : "cc"); 228 *status = __req >> 24 & 0xff; 229 return cc; 230 } 231 232 static inline int pcistg_instr(u64 data, u64 req, u64 offset) 233 { 234 u8 cc, status; 235 236 do { 237 cc = __pcistg(data, req, offset, &status); 238 if (cc == 2) 239 udelay(ZPCI_INSN_BUSY_DELAY); 240 } while (cc == 2); 241 242 if (cc) 243 printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n", 244 __func__, cc, status, req, offset); 245 return (cc) ? -EIO : 0; 246 } 247 248 /* PCI Store Block */ 249 static inline u8 __pcistb(const u64 *data, u64 req, u64 offset, u8 *status) 250 { 251 u8 cc; 252 253 asm volatile ( 254 " .insn rsy,0xeb00000000d0,%[req],%[offset],%[data]\n" 255 " ipm %[cc]\n" 256 " srl %[cc],28\n" 257 : [cc] "=d" (cc), [req] "+d" (req) 258 : [offset] "d" (offset), [data] "Q" (*data) 259 : "cc"); 260 *status = req >> 24 & 0xff; 261 return cc; 262 } 263 264 static inline int pcistb_instr(const u64 *data, u64 req, u64 offset) 265 { 266 u8 cc, status; 267 268 do { 269 cc = __pcistb(data, req, offset, &status); 270 if (cc == 2) 271 udelay(ZPCI_INSN_BUSY_DELAY); 272 } while (cc == 2); 273 274 if (cc) 275 printk_once(KERN_ERR "%s: error cc: %d status: %d req: %Lx offset: %Lx\n", 276 __func__, cc, status, req, offset); 277 return (cc) ? -EIO : 0; 278 } 279 280 #endif 281