This source file includes following definitions.
- nfp_cpp_readl
- nfp_cpp_writel
- nfp_cpp_readq
- nfp_cpp_writeq
- nfp_cpp_model_autodetect
- nfp_bytemask
- nfp_cpp_explicit_read
- nfp_cpp_explicit_write
- nfp_cpp_map_area
1
2
3
4
5
6
7
8
9
10
11
12 #include <asm/unaligned.h>
13 #include <linux/bitfield.h>
14 #include <linux/delay.h>
15 #include <linux/kernel.h>
16 #include <linux/module.h>
17 #include <linux/slab.h>
18 #include <linux/sched.h>
19
20 #include "nfp_cpp.h"
21 #include "nfp6000/nfp6000.h"
22 #include "nfp6000/nfp_xpb.h"
23
24
25 #define NFP_PL_DEVICE_ID 0x00000004
26 #define NFP_PL_DEVICE_ID_MASK GENMASK(7, 0)
27 #define NFP_PL_DEVICE_PART_MASK GENMASK(31, 16)
28 #define NFP_PL_DEVICE_MODEL_MASK (NFP_PL_DEVICE_PART_MASK | \
29 NFP_PL_DEVICE_ID_MASK)
30
31
32
33
34
35
36
37
38
39
40 int nfp_cpp_readl(struct nfp_cpp *cpp, u32 cpp_id,
41 unsigned long long address, u32 *value)
42 {
43 u8 tmp[4];
44 int n;
45
46 n = nfp_cpp_read(cpp, cpp_id, address, tmp, sizeof(tmp));
47 if (n != sizeof(tmp))
48 return n < 0 ? n : -EIO;
49
50 *value = get_unaligned_le32(tmp);
51 return 0;
52 }
53
54
55
56
57
58
59
60
61
62
63 int nfp_cpp_writel(struct nfp_cpp *cpp, u32 cpp_id,
64 unsigned long long address, u32 value)
65 {
66 u8 tmp[4];
67 int n;
68
69 put_unaligned_le32(value, tmp);
70 n = nfp_cpp_write(cpp, cpp_id, address, tmp, sizeof(tmp));
71
72 return n == sizeof(tmp) ? 0 : n < 0 ? n : -EIO;
73 }
74
75
76
77
78
79
80
81
82
83
84 int nfp_cpp_readq(struct nfp_cpp *cpp, u32 cpp_id,
85 unsigned long long address, u64 *value)
86 {
87 u8 tmp[8];
88 int n;
89
90 n = nfp_cpp_read(cpp, cpp_id, address, tmp, sizeof(tmp));
91 if (n != sizeof(tmp))
92 return n < 0 ? n : -EIO;
93
94 *value = get_unaligned_le64(tmp);
95 return 0;
96 }
97
98
99
100
101
102
103
104
105
106
107 int nfp_cpp_writeq(struct nfp_cpp *cpp, u32 cpp_id,
108 unsigned long long address, u64 value)
109 {
110 u8 tmp[8];
111 int n;
112
113 put_unaligned_le64(value, tmp);
114 n = nfp_cpp_write(cpp, cpp_id, address, tmp, sizeof(tmp));
115
116 return n == sizeof(tmp) ? 0 : n < 0 ? n : -EIO;
117 }
118
119
120
121
122 int nfp_cpp_model_autodetect(struct nfp_cpp *cpp, u32 *model)
123 {
124 u32 reg;
125 int err;
126
127 err = nfp_xpb_readl(cpp, NFP_XPB_DEVICE(1, 1, 16) + NFP_PL_DEVICE_ID,
128 ®);
129 if (err < 0)
130 return err;
131
132 *model = reg & NFP_PL_DEVICE_MODEL_MASK;
133 if (*model & NFP_PL_DEVICE_ID_MASK)
134 *model -= 0x10;
135
136 return 0;
137 }
138
139 static u8 nfp_bytemask(int width, u64 addr)
140 {
141 if (width == 8)
142 return 0xff;
143 else if (width == 4)
144 return 0x0f << (addr & 4);
145 else if (width == 2)
146 return 0x03 << (addr & 6);
147 else if (width == 1)
148 return 0x01 << (addr & 7);
149 else
150 return 0;
151 }
152
153 int nfp_cpp_explicit_read(struct nfp_cpp *cpp, u32 cpp_id,
154 u64 addr, void *buff, size_t len, int width_read)
155 {
156 struct nfp_cpp_explicit *expl;
157 char *tmp = buff;
158 int err, i, incr;
159 u8 byte_mask;
160
161 if (len & (width_read - 1))
162 return -EINVAL;
163
164 expl = nfp_cpp_explicit_acquire(cpp);
165 if (!expl)
166 return -EBUSY;
167
168 incr = min_t(int, 16 * width_read, 128);
169 incr = min_t(int, incr, len);
170
171
172 if (NFP_CPP_ID_ACTION_of(cpp_id) == NFP_CPP_ACTION_RW)
173 cpp_id = NFP_CPP_ID(NFP_CPP_ID_TARGET_of(cpp_id), 0,
174 NFP_CPP_ID_TOKEN_of(cpp_id));
175
176 byte_mask = nfp_bytemask(width_read, addr);
177
178 nfp_cpp_explicit_set_target(expl, cpp_id,
179 incr / width_read - 1, byte_mask);
180 nfp_cpp_explicit_set_posted(expl, 1, 0, NFP_SIGNAL_PUSH,
181 0, NFP_SIGNAL_NONE);
182
183 for (i = 0; i < len; i += incr, addr += incr, tmp += incr) {
184 if (i + incr > len) {
185 incr = len - i;
186 nfp_cpp_explicit_set_target(expl, cpp_id,
187 incr / width_read - 1,
188 0xff);
189 }
190
191 err = nfp_cpp_explicit_do(expl, addr);
192 if (err < 0)
193 goto exit_release;
194
195 err = nfp_cpp_explicit_get(expl, tmp, incr);
196 if (err < 0)
197 goto exit_release;
198 }
199 err = len;
200 exit_release:
201 nfp_cpp_explicit_release(expl);
202
203 return err;
204 }
205
206 int nfp_cpp_explicit_write(struct nfp_cpp *cpp, u32 cpp_id, u64 addr,
207 const void *buff, size_t len, int width_write)
208 {
209 struct nfp_cpp_explicit *expl;
210 const char *tmp = buff;
211 int err, i, incr;
212 u8 byte_mask;
213
214 if (len & (width_write - 1))
215 return -EINVAL;
216
217 expl = nfp_cpp_explicit_acquire(cpp);
218 if (!expl)
219 return -EBUSY;
220
221 incr = min_t(int, 16 * width_write, 128);
222 incr = min_t(int, incr, len);
223
224
225 if (NFP_CPP_ID_ACTION_of(cpp_id) == NFP_CPP_ACTION_RW)
226 cpp_id = NFP_CPP_ID(NFP_CPP_ID_TARGET_of(cpp_id), 1,
227 NFP_CPP_ID_TOKEN_of(cpp_id));
228
229 byte_mask = nfp_bytemask(width_write, addr);
230
231 nfp_cpp_explicit_set_target(expl, cpp_id,
232 incr / width_write - 1, byte_mask);
233 nfp_cpp_explicit_set_posted(expl, 1, 0, NFP_SIGNAL_PULL,
234 0, NFP_SIGNAL_NONE);
235
236 for (i = 0; i < len; i += incr, addr += incr, tmp += incr) {
237 if (i + incr > len) {
238 incr = len - i;
239 nfp_cpp_explicit_set_target(expl, cpp_id,
240 incr / width_write - 1,
241 0xff);
242 }
243
244 err = nfp_cpp_explicit_put(expl, tmp, incr);
245 if (err < 0)
246 goto exit_release;
247
248 err = nfp_cpp_explicit_do(expl, addr);
249 if (err < 0)
250 goto exit_release;
251 }
252 err = len;
253 exit_release:
254 nfp_cpp_explicit_release(expl);
255
256 return err;
257 }
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273 u8 __iomem *
274 nfp_cpp_map_area(struct nfp_cpp *cpp, const char *name, u32 cpp_id, u64 addr,
275 unsigned long size, struct nfp_cpp_area **area)
276 {
277 u8 __iomem *res;
278
279 *area = nfp_cpp_area_alloc_acquire(cpp, name, cpp_id, addr, size);
280 if (!*area)
281 goto err_eio;
282
283 res = nfp_cpp_area_iomem(*area);
284 if (!res)
285 goto err_release_free;
286
287 return res;
288
289 err_release_free:
290 nfp_cpp_area_release_free(*area);
291 err_eio:
292 return (u8 __iomem *)ERR_PTR(-EIO);
293 }