xref: /openbmc/linux/arch/s390/include/asm/pci_insn.h (revision 9d749629)
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