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