]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(c) 2010-2018 Intel Corporation | |
3 | */ | |
4 | ||
5 | #include "ifpga_feature_dev.h" | |
9f95a23c TL |
6 | #include "opae_spi.h" |
7 | #include "opae_intel_max10.h" | |
8 | #include "opae_i2c.h" | |
9 | #include "opae_at24_eeprom.h" | |
11fdf7f2 TL |
10 | |
11 | #define PWR_THRESHOLD_MAX 0x7F | |
12 | ||
13 | int fme_get_prop(struct ifpga_fme_hw *fme, struct feature_prop *prop) | |
14 | { | |
9f95a23c | 15 | struct ifpga_feature *feature; |
11fdf7f2 TL |
16 | |
17 | if (!fme) | |
18 | return -ENOENT; | |
19 | ||
20 | feature = get_fme_feature_by_id(fme, prop->feature_id); | |
21 | ||
22 | if (feature && feature->ops && feature->ops->get_prop) | |
23 | return feature->ops->get_prop(feature, prop); | |
24 | ||
25 | return -ENOENT; | |
26 | } | |
27 | ||
28 | int fme_set_prop(struct ifpga_fme_hw *fme, struct feature_prop *prop) | |
29 | { | |
9f95a23c | 30 | struct ifpga_feature *feature; |
11fdf7f2 TL |
31 | |
32 | if (!fme) | |
33 | return -ENOENT; | |
34 | ||
35 | feature = get_fme_feature_by_id(fme, prop->feature_id); | |
36 | ||
37 | if (feature && feature->ops && feature->ops->set_prop) | |
38 | return feature->ops->set_prop(feature, prop); | |
39 | ||
40 | return -ENOENT; | |
41 | } | |
42 | ||
43 | int fme_set_irq(struct ifpga_fme_hw *fme, u32 feature_id, void *irq_set) | |
44 | { | |
9f95a23c | 45 | struct ifpga_feature *feature; |
11fdf7f2 TL |
46 | |
47 | if (!fme) | |
48 | return -ENOENT; | |
49 | ||
50 | feature = get_fme_feature_by_id(fme, feature_id); | |
51 | ||
52 | if (feature && feature->ops && feature->ops->set_irq) | |
53 | return feature->ops->set_irq(feature, irq_set); | |
54 | ||
55 | return -ENOENT; | |
56 | } | |
57 | ||
58 | /* fme private feature head */ | |
9f95a23c | 59 | static int fme_hdr_init(struct ifpga_feature *feature) |
11fdf7f2 TL |
60 | { |
61 | struct feature_fme_header *fme_hdr; | |
62 | ||
63 | fme_hdr = (struct feature_fme_header *)feature->addr; | |
64 | ||
65 | dev_info(NULL, "FME HDR Init.\n"); | |
66 | dev_info(NULL, "FME cap %llx.\n", | |
67 | (unsigned long long)fme_hdr->capability.csr); | |
68 | ||
69 | return 0; | |
70 | } | |
71 | ||
9f95a23c | 72 | static void fme_hdr_uinit(struct ifpga_feature *feature) |
11fdf7f2 TL |
73 | { |
74 | UNUSED(feature); | |
75 | ||
76 | dev_info(NULL, "FME HDR UInit.\n"); | |
77 | } | |
78 | ||
79 | static int fme_hdr_get_revision(struct ifpga_fme_hw *fme, u64 *revision) | |
80 | { | |
81 | struct feature_fme_header *fme_hdr | |
82 | = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER); | |
83 | struct feature_header header; | |
84 | ||
85 | header.csr = readq(&fme_hdr->header); | |
86 | *revision = header.revision; | |
87 | ||
88 | return 0; | |
89 | } | |
90 | ||
91 | static int fme_hdr_get_ports_num(struct ifpga_fme_hw *fme, u64 *ports_num) | |
92 | { | |
93 | struct feature_fme_header *fme_hdr | |
94 | = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER); | |
95 | struct feature_fme_capability fme_capability; | |
96 | ||
97 | fme_capability.csr = readq(&fme_hdr->capability); | |
98 | *ports_num = fme_capability.num_ports; | |
99 | ||
100 | return 0; | |
101 | } | |
102 | ||
103 | static int fme_hdr_get_cache_size(struct ifpga_fme_hw *fme, u64 *cache_size) | |
104 | { | |
105 | struct feature_fme_header *fme_hdr | |
106 | = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER); | |
107 | struct feature_fme_capability fme_capability; | |
108 | ||
109 | fme_capability.csr = readq(&fme_hdr->capability); | |
110 | *cache_size = fme_capability.cache_size; | |
111 | ||
112 | return 0; | |
113 | } | |
114 | ||
115 | static int fme_hdr_get_version(struct ifpga_fme_hw *fme, u64 *version) | |
116 | { | |
117 | struct feature_fme_header *fme_hdr | |
118 | = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER); | |
119 | struct feature_fme_capability fme_capability; | |
120 | ||
121 | fme_capability.csr = readq(&fme_hdr->capability); | |
122 | *version = fme_capability.fabric_verid; | |
123 | ||
124 | return 0; | |
125 | } | |
126 | ||
127 | static int fme_hdr_get_socket_id(struct ifpga_fme_hw *fme, u64 *socket_id) | |
128 | { | |
129 | struct feature_fme_header *fme_hdr | |
130 | = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER); | |
131 | struct feature_fme_capability fme_capability; | |
132 | ||
133 | fme_capability.csr = readq(&fme_hdr->capability); | |
134 | *socket_id = fme_capability.socket_id; | |
135 | ||
136 | return 0; | |
137 | } | |
138 | ||
139 | static int fme_hdr_get_bitstream_id(struct ifpga_fme_hw *fme, | |
140 | u64 *bitstream_id) | |
141 | { | |
142 | struct feature_fme_header *fme_hdr | |
143 | = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER); | |
144 | ||
145 | *bitstream_id = readq(&fme_hdr->bitstream_id); | |
146 | ||
147 | return 0; | |
148 | } | |
149 | ||
150 | static int fme_hdr_get_bitstream_metadata(struct ifpga_fme_hw *fme, | |
151 | u64 *bitstream_metadata) | |
152 | { | |
153 | struct feature_fme_header *fme_hdr | |
154 | = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER); | |
155 | ||
156 | *bitstream_metadata = readq(&fme_hdr->bitstream_md); | |
157 | ||
158 | return 0; | |
159 | } | |
160 | ||
161 | static int | |
9f95a23c | 162 | fme_hdr_get_prop(struct ifpga_feature *feature, struct feature_prop *prop) |
11fdf7f2 TL |
163 | { |
164 | struct ifpga_fme_hw *fme = feature->parent; | |
165 | ||
166 | switch (prop->prop_id) { | |
167 | case FME_HDR_PROP_REVISION: | |
168 | return fme_hdr_get_revision(fme, &prop->data); | |
169 | case FME_HDR_PROP_PORTS_NUM: | |
170 | return fme_hdr_get_ports_num(fme, &prop->data); | |
171 | case FME_HDR_PROP_CACHE_SIZE: | |
172 | return fme_hdr_get_cache_size(fme, &prop->data); | |
173 | case FME_HDR_PROP_VERSION: | |
174 | return fme_hdr_get_version(fme, &prop->data); | |
175 | case FME_HDR_PROP_SOCKET_ID: | |
176 | return fme_hdr_get_socket_id(fme, &prop->data); | |
177 | case FME_HDR_PROP_BITSTREAM_ID: | |
178 | return fme_hdr_get_bitstream_id(fme, &prop->data); | |
179 | case FME_HDR_PROP_BITSTREAM_METADATA: | |
180 | return fme_hdr_get_bitstream_metadata(fme, &prop->data); | |
181 | } | |
182 | ||
183 | return -ENOENT; | |
184 | } | |
185 | ||
9f95a23c | 186 | struct ifpga_feature_ops fme_hdr_ops = { |
11fdf7f2 TL |
187 | .init = fme_hdr_init, |
188 | .uinit = fme_hdr_uinit, | |
189 | .get_prop = fme_hdr_get_prop, | |
190 | }; | |
191 | ||
192 | /* thermal management */ | |
193 | static int fme_thermal_get_threshold1(struct ifpga_fme_hw *fme, u64 *thres1) | |
194 | { | |
195 | struct feature_fme_thermal *thermal; | |
196 | struct feature_fme_tmp_threshold temp_threshold; | |
197 | ||
198 | thermal = get_fme_feature_ioaddr_by_index(fme, | |
199 | FME_FEATURE_ID_THERMAL_MGMT); | |
200 | ||
201 | temp_threshold.csr = readq(&thermal->threshold); | |
202 | *thres1 = temp_threshold.tmp_thshold1; | |
203 | ||
204 | return 0; | |
205 | } | |
206 | ||
207 | static int fme_thermal_set_threshold1(struct ifpga_fme_hw *fme, u64 thres1) | |
208 | { | |
209 | struct feature_fme_thermal *thermal; | |
210 | struct feature_fme_header *fme_hdr; | |
211 | struct feature_fme_tmp_threshold tmp_threshold; | |
212 | struct feature_fme_capability fme_capability; | |
213 | ||
214 | thermal = get_fme_feature_ioaddr_by_index(fme, | |
215 | FME_FEATURE_ID_THERMAL_MGMT); | |
216 | fme_hdr = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER); | |
217 | ||
218 | spinlock_lock(&fme->lock); | |
219 | tmp_threshold.csr = readq(&thermal->threshold); | |
220 | fme_capability.csr = readq(&fme_hdr->capability); | |
221 | ||
222 | if (fme_capability.lock_bit == 1) { | |
223 | spinlock_unlock(&fme->lock); | |
224 | return -EBUSY; | |
225 | } else if (thres1 > 100) { | |
226 | spinlock_unlock(&fme->lock); | |
227 | return -EINVAL; | |
228 | } else if (thres1 == 0) { | |
229 | tmp_threshold.tmp_thshold1_enable = 0; | |
230 | tmp_threshold.tmp_thshold1 = thres1; | |
231 | } else { | |
232 | tmp_threshold.tmp_thshold1_enable = 1; | |
233 | tmp_threshold.tmp_thshold1 = thres1; | |
234 | } | |
235 | ||
236 | writeq(tmp_threshold.csr, &thermal->threshold); | |
237 | spinlock_unlock(&fme->lock); | |
238 | ||
239 | return 0; | |
240 | } | |
241 | ||
242 | static int fme_thermal_get_threshold2(struct ifpga_fme_hw *fme, u64 *thres2) | |
243 | { | |
244 | struct feature_fme_thermal *thermal; | |
245 | struct feature_fme_tmp_threshold temp_threshold; | |
246 | ||
247 | thermal = get_fme_feature_ioaddr_by_index(fme, | |
248 | FME_FEATURE_ID_THERMAL_MGMT); | |
249 | ||
250 | temp_threshold.csr = readq(&thermal->threshold); | |
251 | *thres2 = temp_threshold.tmp_thshold2; | |
252 | ||
253 | return 0; | |
254 | } | |
255 | ||
256 | static int fme_thermal_set_threshold2(struct ifpga_fme_hw *fme, u64 thres2) | |
257 | { | |
258 | struct feature_fme_thermal *thermal; | |
259 | struct feature_fme_header *fme_hdr; | |
260 | struct feature_fme_tmp_threshold tmp_threshold; | |
261 | struct feature_fme_capability fme_capability; | |
262 | ||
263 | thermal = get_fme_feature_ioaddr_by_index(fme, | |
264 | FME_FEATURE_ID_THERMAL_MGMT); | |
265 | fme_hdr = get_fme_feature_ioaddr_by_index(fme, FME_FEATURE_ID_HEADER); | |
266 | ||
267 | spinlock_lock(&fme->lock); | |
268 | tmp_threshold.csr = readq(&thermal->threshold); | |
269 | fme_capability.csr = readq(&fme_hdr->capability); | |
270 | ||
271 | if (fme_capability.lock_bit == 1) { | |
272 | spinlock_unlock(&fme->lock); | |
273 | return -EBUSY; | |
274 | } else if (thres2 > 100) { | |
275 | spinlock_unlock(&fme->lock); | |
276 | return -EINVAL; | |
277 | } else if (thres2 == 0) { | |
278 | tmp_threshold.tmp_thshold2_enable = 0; | |
279 | tmp_threshold.tmp_thshold2 = thres2; | |
280 | } else { | |
281 | tmp_threshold.tmp_thshold2_enable = 1; | |
282 | tmp_threshold.tmp_thshold2 = thres2; | |
283 | } | |
284 | ||
285 | writeq(tmp_threshold.csr, &thermal->threshold); | |
286 | spinlock_unlock(&fme->lock); | |
287 | ||
288 | return 0; | |
289 | } | |
290 | ||
291 | static int fme_thermal_get_threshold_trip(struct ifpga_fme_hw *fme, | |
292 | u64 *thres_trip) | |
293 | { | |
294 | struct feature_fme_thermal *thermal; | |
295 | struct feature_fme_tmp_threshold temp_threshold; | |
296 | ||
297 | thermal = get_fme_feature_ioaddr_by_index(fme, | |
298 | FME_FEATURE_ID_THERMAL_MGMT); | |
299 | ||
300 | temp_threshold.csr = readq(&thermal->threshold); | |
301 | *thres_trip = temp_threshold.therm_trip_thshold; | |
302 | ||
303 | return 0; | |
304 | } | |
305 | ||
306 | static int fme_thermal_get_threshold1_reached(struct ifpga_fme_hw *fme, | |
307 | u64 *thres1_reached) | |
308 | { | |
309 | struct feature_fme_thermal *thermal; | |
310 | struct feature_fme_tmp_threshold temp_threshold; | |
311 | ||
312 | thermal = get_fme_feature_ioaddr_by_index(fme, | |
313 | FME_FEATURE_ID_THERMAL_MGMT); | |
314 | ||
315 | temp_threshold.csr = readq(&thermal->threshold); | |
316 | *thres1_reached = temp_threshold.thshold1_status; | |
317 | ||
318 | return 0; | |
319 | } | |
320 | ||
321 | static int fme_thermal_get_threshold2_reached(struct ifpga_fme_hw *fme, | |
322 | u64 *thres1_reached) | |
323 | { | |
324 | struct feature_fme_thermal *thermal; | |
325 | struct feature_fme_tmp_threshold temp_threshold; | |
326 | ||
327 | thermal = get_fme_feature_ioaddr_by_index(fme, | |
328 | FME_FEATURE_ID_THERMAL_MGMT); | |
329 | ||
330 | temp_threshold.csr = readq(&thermal->threshold); | |
331 | *thres1_reached = temp_threshold.thshold2_status; | |
332 | ||
333 | return 0; | |
334 | } | |
335 | ||
336 | static int fme_thermal_get_threshold1_policy(struct ifpga_fme_hw *fme, | |
337 | u64 *thres1_policy) | |
338 | { | |
339 | struct feature_fme_thermal *thermal; | |
340 | struct feature_fme_tmp_threshold temp_threshold; | |
341 | ||
342 | thermal = get_fme_feature_ioaddr_by_index(fme, | |
343 | FME_FEATURE_ID_THERMAL_MGMT); | |
344 | ||
345 | temp_threshold.csr = readq(&thermal->threshold); | |
346 | *thres1_policy = temp_threshold.thshold_policy; | |
347 | ||
348 | return 0; | |
349 | } | |
350 | ||
351 | static int fme_thermal_set_threshold1_policy(struct ifpga_fme_hw *fme, | |
352 | u64 thres1_policy) | |
353 | { | |
354 | struct feature_fme_thermal *thermal; | |
355 | struct feature_fme_tmp_threshold tmp_threshold; | |
356 | ||
357 | thermal = get_fme_feature_ioaddr_by_index(fme, | |
358 | FME_FEATURE_ID_THERMAL_MGMT); | |
359 | ||
360 | spinlock_lock(&fme->lock); | |
361 | tmp_threshold.csr = readq(&thermal->threshold); | |
362 | ||
363 | if (thres1_policy == 0) { | |
364 | tmp_threshold.thshold_policy = 0; | |
365 | } else if (thres1_policy == 1) { | |
366 | tmp_threshold.thshold_policy = 1; | |
367 | } else { | |
368 | spinlock_unlock(&fme->lock); | |
369 | return -EINVAL; | |
370 | } | |
371 | ||
372 | writeq(tmp_threshold.csr, &thermal->threshold); | |
373 | spinlock_unlock(&fme->lock); | |
374 | ||
375 | return 0; | |
376 | } | |
377 | ||
378 | static int fme_thermal_get_temperature(struct ifpga_fme_hw *fme, u64 *temp) | |
379 | { | |
380 | struct feature_fme_thermal *thermal; | |
381 | struct feature_fme_temp_rdsensor_fmt1 temp_rdsensor_fmt1; | |
382 | ||
383 | thermal = get_fme_feature_ioaddr_by_index(fme, | |
384 | FME_FEATURE_ID_THERMAL_MGMT); | |
385 | ||
386 | temp_rdsensor_fmt1.csr = readq(&thermal->rdsensor_fm1); | |
387 | *temp = temp_rdsensor_fmt1.fpga_temp; | |
388 | ||
389 | return 0; | |
390 | } | |
391 | ||
392 | static int fme_thermal_get_revision(struct ifpga_fme_hw *fme, u64 *revision) | |
393 | { | |
394 | struct feature_fme_thermal *fme_thermal | |
395 | = get_fme_feature_ioaddr_by_index(fme, | |
396 | FME_FEATURE_ID_THERMAL_MGMT); | |
397 | struct feature_header header; | |
398 | ||
399 | header.csr = readq(&fme_thermal->header); | |
400 | *revision = header.revision; | |
401 | ||
402 | return 0; | |
403 | } | |
404 | ||
405 | #define FME_THERMAL_CAP_NO_TMP_THRESHOLD 0x1 | |
406 | ||
9f95a23c | 407 | static int fme_thermal_mgmt_init(struct ifpga_feature *feature) |
11fdf7f2 TL |
408 | { |
409 | struct feature_fme_thermal *fme_thermal; | |
410 | struct feature_fme_tmp_threshold_cap thermal_cap; | |
411 | ||
412 | UNUSED(feature); | |
413 | ||
414 | dev_info(NULL, "FME thermal mgmt Init.\n"); | |
415 | ||
416 | fme_thermal = (struct feature_fme_thermal *)feature->addr; | |
417 | thermal_cap.csr = readq(&fme_thermal->threshold_cap); | |
418 | ||
419 | dev_info(NULL, "FME thermal cap %llx.\n", | |
420 | (unsigned long long)fme_thermal->threshold_cap.csr); | |
421 | ||
422 | if (thermal_cap.tmp_thshold_disabled) | |
423 | feature->cap |= FME_THERMAL_CAP_NO_TMP_THRESHOLD; | |
424 | ||
425 | return 0; | |
426 | } | |
427 | ||
9f95a23c | 428 | static void fme_thermal_mgmt_uinit(struct ifpga_feature *feature) |
11fdf7f2 TL |
429 | { |
430 | UNUSED(feature); | |
431 | ||
432 | dev_info(NULL, "FME thermal mgmt UInit.\n"); | |
433 | } | |
434 | ||
435 | static int | |
9f95a23c | 436 | fme_thermal_set_prop(struct ifpga_feature *feature, struct feature_prop *prop) |
11fdf7f2 TL |
437 | { |
438 | struct ifpga_fme_hw *fme = feature->parent; | |
439 | ||
440 | if (feature->cap & FME_THERMAL_CAP_NO_TMP_THRESHOLD) | |
441 | return -ENOENT; | |
442 | ||
443 | switch (prop->prop_id) { | |
444 | case FME_THERMAL_PROP_THRESHOLD1: | |
445 | return fme_thermal_set_threshold1(fme, prop->data); | |
446 | case FME_THERMAL_PROP_THRESHOLD2: | |
447 | return fme_thermal_set_threshold2(fme, prop->data); | |
448 | case FME_THERMAL_PROP_THRESHOLD1_POLICY: | |
449 | return fme_thermal_set_threshold1_policy(fme, prop->data); | |
450 | } | |
451 | ||
452 | return -ENOENT; | |
453 | } | |
454 | ||
455 | static int | |
9f95a23c | 456 | fme_thermal_get_prop(struct ifpga_feature *feature, struct feature_prop *prop) |
11fdf7f2 TL |
457 | { |
458 | struct ifpga_fme_hw *fme = feature->parent; | |
459 | ||
460 | if (feature->cap & FME_THERMAL_CAP_NO_TMP_THRESHOLD && | |
461 | prop->prop_id != FME_THERMAL_PROP_TEMPERATURE && | |
462 | prop->prop_id != FME_THERMAL_PROP_REVISION) | |
463 | return -ENOENT; | |
464 | ||
465 | switch (prop->prop_id) { | |
466 | case FME_THERMAL_PROP_THRESHOLD1: | |
467 | return fme_thermal_get_threshold1(fme, &prop->data); | |
468 | case FME_THERMAL_PROP_THRESHOLD2: | |
469 | return fme_thermal_get_threshold2(fme, &prop->data); | |
470 | case FME_THERMAL_PROP_THRESHOLD_TRIP: | |
471 | return fme_thermal_get_threshold_trip(fme, &prop->data); | |
472 | case FME_THERMAL_PROP_THRESHOLD1_REACHED: | |
473 | return fme_thermal_get_threshold1_reached(fme, &prop->data); | |
474 | case FME_THERMAL_PROP_THRESHOLD2_REACHED: | |
475 | return fme_thermal_get_threshold2_reached(fme, &prop->data); | |
476 | case FME_THERMAL_PROP_THRESHOLD1_POLICY: | |
477 | return fme_thermal_get_threshold1_policy(fme, &prop->data); | |
478 | case FME_THERMAL_PROP_TEMPERATURE: | |
479 | return fme_thermal_get_temperature(fme, &prop->data); | |
480 | case FME_THERMAL_PROP_REVISION: | |
481 | return fme_thermal_get_revision(fme, &prop->data); | |
482 | } | |
483 | ||
484 | return -ENOENT; | |
485 | } | |
486 | ||
9f95a23c | 487 | struct ifpga_feature_ops fme_thermal_mgmt_ops = { |
11fdf7f2 TL |
488 | .init = fme_thermal_mgmt_init, |
489 | .uinit = fme_thermal_mgmt_uinit, | |
490 | .get_prop = fme_thermal_get_prop, | |
491 | .set_prop = fme_thermal_set_prop, | |
492 | }; | |
493 | ||
494 | static int fme_pwr_get_consumed(struct ifpga_fme_hw *fme, u64 *consumed) | |
495 | { | |
496 | struct feature_fme_power *fme_power | |
497 | = get_fme_feature_ioaddr_by_index(fme, | |
498 | FME_FEATURE_ID_POWER_MGMT); | |
499 | struct feature_fme_pm_status pm_status; | |
500 | ||
501 | pm_status.csr = readq(&fme_power->status); | |
502 | ||
503 | *consumed = pm_status.pwr_consumed; | |
504 | ||
505 | return 0; | |
506 | } | |
507 | ||
508 | static int fme_pwr_get_threshold1(struct ifpga_fme_hw *fme, u64 *threshold) | |
509 | { | |
510 | struct feature_fme_power *fme_power | |
511 | = get_fme_feature_ioaddr_by_index(fme, | |
512 | FME_FEATURE_ID_POWER_MGMT); | |
513 | struct feature_fme_pm_ap_threshold pm_ap_threshold; | |
514 | ||
515 | pm_ap_threshold.csr = readq(&fme_power->threshold); | |
516 | ||
517 | *threshold = pm_ap_threshold.threshold1; | |
518 | ||
519 | return 0; | |
520 | } | |
521 | ||
522 | static int fme_pwr_set_threshold1(struct ifpga_fme_hw *fme, u64 threshold) | |
523 | { | |
524 | struct feature_fme_power *fme_power | |
525 | = get_fme_feature_ioaddr_by_index(fme, | |
526 | FME_FEATURE_ID_POWER_MGMT); | |
527 | struct feature_fme_pm_ap_threshold pm_ap_threshold; | |
528 | ||
529 | spinlock_lock(&fme->lock); | |
530 | pm_ap_threshold.csr = readq(&fme_power->threshold); | |
531 | ||
532 | if (threshold <= PWR_THRESHOLD_MAX) { | |
533 | pm_ap_threshold.threshold1 = threshold; | |
534 | } else { | |
535 | spinlock_unlock(&fme->lock); | |
536 | return -EINVAL; | |
537 | } | |
538 | ||
539 | writeq(pm_ap_threshold.csr, &fme_power->threshold); | |
540 | spinlock_unlock(&fme->lock); | |
541 | ||
542 | return 0; | |
543 | } | |
544 | ||
545 | static int fme_pwr_get_threshold2(struct ifpga_fme_hw *fme, u64 *threshold) | |
546 | { | |
547 | struct feature_fme_power *fme_power | |
548 | = get_fme_feature_ioaddr_by_index(fme, | |
549 | FME_FEATURE_ID_POWER_MGMT); | |
550 | struct feature_fme_pm_ap_threshold pm_ap_threshold; | |
551 | ||
552 | pm_ap_threshold.csr = readq(&fme_power->threshold); | |
553 | ||
554 | *threshold = pm_ap_threshold.threshold2; | |
555 | ||
556 | return 0; | |
557 | } | |
558 | ||
559 | static int fme_pwr_set_threshold2(struct ifpga_fme_hw *fme, u64 threshold) | |
560 | { | |
561 | struct feature_fme_power *fme_power | |
562 | = get_fme_feature_ioaddr_by_index(fme, | |
563 | FME_FEATURE_ID_POWER_MGMT); | |
564 | struct feature_fme_pm_ap_threshold pm_ap_threshold; | |
565 | ||
566 | spinlock_lock(&fme->lock); | |
567 | pm_ap_threshold.csr = readq(&fme_power->threshold); | |
568 | ||
569 | if (threshold <= PWR_THRESHOLD_MAX) { | |
570 | pm_ap_threshold.threshold2 = threshold; | |
571 | } else { | |
572 | spinlock_unlock(&fme->lock); | |
573 | return -EINVAL; | |
574 | } | |
575 | ||
576 | writeq(pm_ap_threshold.csr, &fme_power->threshold); | |
577 | spinlock_unlock(&fme->lock); | |
578 | ||
579 | return 0; | |
580 | } | |
581 | ||
582 | static int fme_pwr_get_threshold1_status(struct ifpga_fme_hw *fme, | |
583 | u64 *threshold_status) | |
584 | { | |
585 | struct feature_fme_power *fme_power | |
586 | = get_fme_feature_ioaddr_by_index(fme, | |
587 | FME_FEATURE_ID_POWER_MGMT); | |
588 | struct feature_fme_pm_ap_threshold pm_ap_threshold; | |
589 | ||
590 | pm_ap_threshold.csr = readq(&fme_power->threshold); | |
591 | ||
592 | *threshold_status = pm_ap_threshold.threshold1_status; | |
593 | ||
594 | return 0; | |
595 | } | |
596 | ||
597 | static int fme_pwr_get_threshold2_status(struct ifpga_fme_hw *fme, | |
598 | u64 *threshold_status) | |
599 | { | |
600 | struct feature_fme_power *fme_power | |
601 | = get_fme_feature_ioaddr_by_index(fme, | |
602 | FME_FEATURE_ID_POWER_MGMT); | |
603 | struct feature_fme_pm_ap_threshold pm_ap_threshold; | |
604 | ||
605 | pm_ap_threshold.csr = readq(&fme_power->threshold); | |
606 | ||
607 | *threshold_status = pm_ap_threshold.threshold2_status; | |
608 | ||
609 | return 0; | |
610 | } | |
611 | ||
612 | static int fme_pwr_get_rtl(struct ifpga_fme_hw *fme, u64 *rtl) | |
613 | { | |
614 | struct feature_fme_power *fme_power | |
615 | = get_fme_feature_ioaddr_by_index(fme, | |
616 | FME_FEATURE_ID_POWER_MGMT); | |
617 | struct feature_fme_pm_status pm_status; | |
618 | ||
619 | pm_status.csr = readq(&fme_power->status); | |
620 | ||
621 | *rtl = pm_status.fpga_latency_report; | |
622 | ||
623 | return 0; | |
624 | } | |
625 | ||
626 | static int fme_pwr_get_xeon_limit(struct ifpga_fme_hw *fme, u64 *limit) | |
627 | { | |
628 | struct feature_fme_power *fme_power | |
629 | = get_fme_feature_ioaddr_by_index(fme, | |
630 | FME_FEATURE_ID_POWER_MGMT); | |
631 | struct feature_fme_pm_xeon_limit xeon_limit; | |
632 | ||
633 | xeon_limit.csr = readq(&fme_power->xeon_limit); | |
634 | ||
635 | if (!xeon_limit.enable) | |
636 | xeon_limit.pwr_limit = 0; | |
637 | ||
638 | *limit = xeon_limit.pwr_limit; | |
639 | ||
640 | return 0; | |
641 | } | |
642 | ||
643 | static int fme_pwr_get_fpga_limit(struct ifpga_fme_hw *fme, u64 *limit) | |
644 | { | |
645 | struct feature_fme_power *fme_power | |
646 | = get_fme_feature_ioaddr_by_index(fme, | |
647 | FME_FEATURE_ID_POWER_MGMT); | |
648 | struct feature_fme_pm_fpga_limit fpga_limit; | |
649 | ||
650 | fpga_limit.csr = readq(&fme_power->fpga_limit); | |
651 | ||
652 | if (!fpga_limit.enable) | |
653 | fpga_limit.pwr_limit = 0; | |
654 | ||
655 | *limit = fpga_limit.pwr_limit; | |
656 | ||
657 | return 0; | |
658 | } | |
659 | ||
660 | static int fme_pwr_get_revision(struct ifpga_fme_hw *fme, u64 *revision) | |
661 | { | |
662 | struct feature_fme_power *fme_power | |
663 | = get_fme_feature_ioaddr_by_index(fme, | |
664 | FME_FEATURE_ID_POWER_MGMT); | |
665 | struct feature_header header; | |
666 | ||
667 | header.csr = readq(&fme_power->header); | |
668 | *revision = header.revision; | |
669 | ||
670 | return 0; | |
671 | } | |
672 | ||
9f95a23c | 673 | static int fme_power_mgmt_init(struct ifpga_feature *feature) |
11fdf7f2 TL |
674 | { |
675 | UNUSED(feature); | |
676 | ||
677 | dev_info(NULL, "FME power mgmt Init.\n"); | |
678 | ||
679 | return 0; | |
680 | } | |
681 | ||
9f95a23c | 682 | static void fme_power_mgmt_uinit(struct ifpga_feature *feature) |
11fdf7f2 TL |
683 | { |
684 | UNUSED(feature); | |
685 | ||
686 | dev_info(NULL, "FME power mgmt UInit.\n"); | |
687 | } | |
688 | ||
9f95a23c | 689 | static int fme_power_mgmt_get_prop(struct ifpga_feature *feature, |
11fdf7f2 TL |
690 | struct feature_prop *prop) |
691 | { | |
692 | struct ifpga_fme_hw *fme = feature->parent; | |
693 | ||
694 | switch (prop->prop_id) { | |
695 | case FME_PWR_PROP_CONSUMED: | |
696 | return fme_pwr_get_consumed(fme, &prop->data); | |
697 | case FME_PWR_PROP_THRESHOLD1: | |
698 | return fme_pwr_get_threshold1(fme, &prop->data); | |
699 | case FME_PWR_PROP_THRESHOLD2: | |
700 | return fme_pwr_get_threshold2(fme, &prop->data); | |
701 | case FME_PWR_PROP_THRESHOLD1_STATUS: | |
702 | return fme_pwr_get_threshold1_status(fme, &prop->data); | |
703 | case FME_PWR_PROP_THRESHOLD2_STATUS: | |
704 | return fme_pwr_get_threshold2_status(fme, &prop->data); | |
705 | case FME_PWR_PROP_RTL: | |
706 | return fme_pwr_get_rtl(fme, &prop->data); | |
707 | case FME_PWR_PROP_XEON_LIMIT: | |
708 | return fme_pwr_get_xeon_limit(fme, &prop->data); | |
709 | case FME_PWR_PROP_FPGA_LIMIT: | |
710 | return fme_pwr_get_fpga_limit(fme, &prop->data); | |
711 | case FME_PWR_PROP_REVISION: | |
712 | return fme_pwr_get_revision(fme, &prop->data); | |
713 | } | |
714 | ||
715 | return -ENOENT; | |
716 | } | |
717 | ||
9f95a23c | 718 | static int fme_power_mgmt_set_prop(struct ifpga_feature *feature, |
11fdf7f2 TL |
719 | struct feature_prop *prop) |
720 | { | |
721 | struct ifpga_fme_hw *fme = feature->parent; | |
722 | ||
723 | switch (prop->prop_id) { | |
724 | case FME_PWR_PROP_THRESHOLD1: | |
725 | return fme_pwr_set_threshold1(fme, prop->data); | |
726 | case FME_PWR_PROP_THRESHOLD2: | |
727 | return fme_pwr_set_threshold2(fme, prop->data); | |
728 | } | |
729 | ||
730 | return -ENOENT; | |
731 | } | |
732 | ||
9f95a23c | 733 | struct ifpga_feature_ops fme_power_mgmt_ops = { |
11fdf7f2 TL |
734 | .init = fme_power_mgmt_init, |
735 | .uinit = fme_power_mgmt_uinit, | |
736 | .get_prop = fme_power_mgmt_get_prop, | |
737 | .set_prop = fme_power_mgmt_set_prop, | |
738 | }; | |
9f95a23c TL |
739 | |
740 | static int fme_hssi_eth_init(struct ifpga_feature *feature) | |
741 | { | |
742 | UNUSED(feature); | |
743 | return 0; | |
744 | } | |
745 | ||
746 | static void fme_hssi_eth_uinit(struct ifpga_feature *feature) | |
747 | { | |
748 | UNUSED(feature); | |
749 | } | |
750 | ||
751 | struct ifpga_feature_ops fme_hssi_eth_ops = { | |
752 | .init = fme_hssi_eth_init, | |
753 | .uinit = fme_hssi_eth_uinit, | |
754 | }; | |
755 | ||
756 | static int fme_emif_init(struct ifpga_feature *feature) | |
757 | { | |
758 | UNUSED(feature); | |
759 | return 0; | |
760 | } | |
761 | ||
762 | static void fme_emif_uinit(struct ifpga_feature *feature) | |
763 | { | |
764 | UNUSED(feature); | |
765 | } | |
766 | ||
767 | struct ifpga_feature_ops fme_emif_ops = { | |
768 | .init = fme_emif_init, | |
769 | .uinit = fme_emif_uinit, | |
770 | }; | |
771 | ||
772 | static const char *board_type_to_string(u32 type) | |
773 | { | |
774 | switch (type) { | |
775 | case VC_8_10G: | |
776 | return "VC_8x10G"; | |
777 | case VC_4_25G: | |
778 | return "VC_4x25G"; | |
779 | case VC_2_1_25: | |
780 | return "VC_2x1x25G"; | |
781 | case VC_4_25G_2_25G: | |
782 | return "VC_4x25G+2x25G"; | |
783 | case VC_2_2_25G: | |
784 | return "VC_2x2x25G"; | |
785 | } | |
786 | ||
787 | return "unknown"; | |
788 | } | |
789 | ||
f67539c2 TL |
790 | static const char *board_major_to_string(u32 major) |
791 | { | |
792 | switch (major) { | |
793 | case VISTA_CREEK: | |
794 | return "VISTA_CREEK"; | |
795 | case RUSH_CREEK: | |
796 | return "RUSH_CREEK"; | |
797 | case DARBY_CREEK: | |
798 | return "DARBY_CREEK"; | |
799 | } | |
800 | ||
801 | return "unknown"; | |
802 | } | |
803 | ||
9f95a23c | 804 | static int board_type_to_info(u32 type, |
f67539c2 | 805 | struct opae_board_info *info) |
9f95a23c TL |
806 | { |
807 | switch (type) { | |
808 | case VC_8_10G: | |
809 | info->nums_of_retimer = 2; | |
810 | info->ports_per_retimer = 4; | |
811 | info->nums_of_fvl = 2; | |
812 | info->ports_per_fvl = 4; | |
813 | break; | |
814 | case VC_4_25G: | |
815 | info->nums_of_retimer = 1; | |
816 | info->ports_per_retimer = 4; | |
817 | info->nums_of_fvl = 2; | |
818 | info->ports_per_fvl = 2; | |
819 | break; | |
820 | case VC_2_1_25: | |
821 | info->nums_of_retimer = 2; | |
822 | info->ports_per_retimer = 1; | |
823 | info->nums_of_fvl = 1; | |
824 | info->ports_per_fvl = 2; | |
825 | break; | |
826 | case VC_2_2_25G: | |
827 | info->nums_of_retimer = 2; | |
828 | info->ports_per_retimer = 2; | |
829 | info->nums_of_fvl = 2; | |
830 | info->ports_per_fvl = 2; | |
831 | break; | |
832 | default: | |
833 | return -EINVAL; | |
834 | } | |
835 | ||
836 | return 0; | |
837 | } | |
838 | ||
839 | static int fme_get_board_interface(struct ifpga_fme_hw *fme) | |
840 | { | |
841 | struct fme_bitstream_id id; | |
f67539c2 TL |
842 | struct ifpga_hw *hw; |
843 | u32 val; | |
844 | ||
845 | hw = fme->parent; | |
846 | if (!hw) | |
847 | return -ENODEV; | |
9f95a23c TL |
848 | |
849 | if (fme_hdr_get_bitstream_id(fme, &id.id)) | |
850 | return -EINVAL; | |
851 | ||
f67539c2 TL |
852 | fme->board_info.major = id.major; |
853 | fme->board_info.minor = id.minor; | |
9f95a23c | 854 | fme->board_info.type = id.interface; |
f67539c2 TL |
855 | fme->board_info.fvl_bypass = id.fvl_bypass; |
856 | fme->board_info.mac_lightweight = id.mac_lightweight; | |
857 | fme->board_info.lightweight = id.lightweiht; | |
858 | fme->board_info.disaggregate = id.disagregate; | |
859 | fme->board_info.seu = id.seu; | |
860 | fme->board_info.ptp = id.ptp; | |
861 | ||
862 | dev_info(fme, "found: PCI dev: %02x:%02x:%x board: %s type: %s\n", | |
863 | hw->pci_data->bus, | |
864 | hw->pci_data->devid, | |
865 | hw->pci_data->function, | |
866 | board_major_to_string(fme->board_info.major), | |
867 | board_type_to_string(fme->board_info.type)); | |
868 | ||
869 | dev_info(fme, "support feature:\n" | |
870 | "fvl_bypass:%s\n" | |
871 | "mac_lightweight:%s\n" | |
872 | "lightweight:%s\n" | |
873 | "disaggregate:%s\n" | |
874 | "seu:%s\n" | |
875 | "ptp1588:%s\n", | |
876 | check_support(fme->board_info.fvl_bypass), | |
877 | check_support(fme->board_info.mac_lightweight), | |
878 | check_support(fme->board_info.lightweight), | |
879 | check_support(fme->board_info.disaggregate), | |
880 | check_support(fme->board_info.seu), | |
881 | check_support(fme->board_info.ptp)); | |
9f95a23c | 882 | |
9f95a23c TL |
883 | |
884 | if (board_type_to_info(fme->board_info.type, &fme->board_info)) | |
885 | return -EINVAL; | |
886 | ||
887 | dev_info(fme, "get board info: nums_retimers %d ports_per_retimer %d nums_fvl %d ports_per_fvl %d\n", | |
888 | fme->board_info.nums_of_retimer, | |
889 | fme->board_info.ports_per_retimer, | |
890 | fme->board_info.nums_of_fvl, | |
891 | fme->board_info.ports_per_fvl); | |
892 | ||
f67539c2 TL |
893 | if (max10_sys_read(fme->max10_dev, MAX10_BUILD_VER, &val)) |
894 | return -EINVAL; | |
895 | fme->board_info.max10_version = val & 0xffffff; | |
896 | ||
897 | if (max10_sys_read(fme->max10_dev, NIOS2_FW_VERSION, &val)) | |
898 | return -EINVAL; | |
899 | fme->board_info.nios_fw_version = val & 0xffffff; | |
900 | ||
901 | dev_info(fme, "max10 version 0x%x, nios fw version 0x%x\n", | |
902 | fme->board_info.max10_version, | |
903 | fme->board_info.nios_fw_version); | |
904 | ||
9f95a23c TL |
905 | return 0; |
906 | } | |
907 | ||
f67539c2 | 908 | static int spi_self_checking(struct intel_max10_device *dev) |
9f95a23c TL |
909 | { |
910 | u32 val; | |
911 | int ret; | |
912 | ||
f67539c2 | 913 | ret = max10_sys_read(dev, MAX10_TEST_REG, &val); |
9f95a23c TL |
914 | if (ret) |
915 | return -EIO; | |
916 | ||
f67539c2 | 917 | dev_info(NULL, "Read MAX10 test register 0x%x\n", val); |
9f95a23c TL |
918 | |
919 | return 0; | |
920 | } | |
921 | ||
922 | static int fme_spi_init(struct ifpga_feature *feature) | |
923 | { | |
924 | struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent; | |
925 | struct altera_spi_device *spi_master; | |
926 | struct intel_max10_device *max10; | |
927 | int ret = 0; | |
928 | ||
929 | dev_info(fme, "FME SPI Master (Max10) Init.\n"); | |
930 | dev_debug(fme, "FME SPI base addr %p.\n", | |
931 | feature->addr); | |
932 | dev_debug(fme, "spi param=0x%llx\n", | |
933 | (unsigned long long)opae_readq(feature->addr + 0x8)); | |
934 | ||
935 | spi_master = altera_spi_alloc(feature->addr, TYPE_SPI); | |
936 | if (!spi_master) | |
937 | return -ENODEV; | |
938 | ||
939 | altera_spi_init(spi_master); | |
940 | ||
941 | max10 = intel_max10_device_probe(spi_master, 0); | |
942 | if (!max10) { | |
943 | ret = -ENODEV; | |
944 | dev_err(fme, "max10 init fail\n"); | |
945 | goto spi_fail; | |
946 | } | |
947 | ||
f67539c2 | 948 | |
9f95a23c TL |
949 | fme->max10_dev = max10; |
950 | ||
951 | /* SPI self test */ | |
f67539c2 | 952 | if (spi_self_checking(max10)) { |
9f95a23c TL |
953 | ret = -EIO; |
954 | goto max10_fail; | |
955 | } | |
956 | ||
957 | return ret; | |
958 | ||
959 | max10_fail: | |
960 | intel_max10_device_remove(fme->max10_dev); | |
961 | spi_fail: | |
962 | altera_spi_release(spi_master); | |
963 | return ret; | |
964 | } | |
965 | ||
966 | static void fme_spi_uinit(struct ifpga_feature *feature) | |
967 | { | |
968 | struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent; | |
969 | ||
970 | if (fme->max10_dev) | |
971 | intel_max10_device_remove(fme->max10_dev); | |
972 | } | |
973 | ||
974 | struct ifpga_feature_ops fme_spi_master_ops = { | |
975 | .init = fme_spi_init, | |
976 | .uinit = fme_spi_uinit, | |
977 | }; | |
978 | ||
979 | static int nios_spi_wait_init_done(struct altera_spi_device *dev) | |
980 | { | |
981 | u32 val = 0; | |
982 | unsigned long timeout = msecs_to_timer_cycles(10000); | |
983 | unsigned long ticks; | |
f67539c2 TL |
984 | int major_version; |
985 | ||
986 | if (spi_reg_read(dev, NIOS_VERSION, &val)) | |
987 | return -EIO; | |
988 | ||
989 | major_version = (val >> NIOS_VERSION_MAJOR_SHIFT) & | |
990 | NIOS_VERSION_MAJOR; | |
991 | dev_debug(dev, "A10 NIOS FW version %d\n", major_version); | |
992 | ||
993 | if (major_version >= 3) { | |
994 | /* read NIOS_INIT to check if PKVL INIT done or not */ | |
995 | if (spi_reg_read(dev, NIOS_INIT, &val)) | |
996 | return -EIO; | |
997 | ||
998 | /* check if PKVLs are initialized already */ | |
999 | if (val & NIOS_INIT_DONE || val & NIOS_INIT_START) | |
1000 | goto nios_init_done; | |
9f95a23c | 1001 | |
f67539c2 TL |
1002 | /* start to config the default FEC mode */ |
1003 | val = NIOS_INIT_START; | |
1004 | ||
1005 | if (spi_reg_write(dev, NIOS_INIT, val)) | |
1006 | return -EIO; | |
1007 | } | |
1008 | ||
1009 | nios_init_done: | |
9f95a23c | 1010 | do { |
f67539c2 | 1011 | if (spi_reg_read(dev, NIOS_INIT, &val)) |
9f95a23c TL |
1012 | return -EIO; |
1013 | if (val) | |
1014 | break; | |
1015 | ||
1016 | ticks = rte_get_timer_cycles(); | |
1017 | if (time_after(ticks, timeout)) | |
1018 | return -ETIMEDOUT; | |
1019 | msleep(100); | |
1020 | } while (!val); | |
1021 | ||
1022 | return 0; | |
1023 | } | |
1024 | ||
1025 | static int nios_spi_check_error(struct altera_spi_device *dev) | |
1026 | { | |
1027 | u32 value = 0; | |
1028 | ||
f67539c2 | 1029 | if (spi_reg_read(dev, PKVL_A_MODE_STS, &value)) |
9f95a23c TL |
1030 | return -EIO; |
1031 | ||
f67539c2 | 1032 | dev_debug(dev, "PKVL A Mode Status 0x%x\n", value); |
9f95a23c | 1033 | |
f67539c2 | 1034 | if (value >= 0x100) |
9f95a23c TL |
1035 | return -EINVAL; |
1036 | ||
f67539c2 | 1037 | if (spi_reg_read(dev, PKVL_B_MODE_STS, &value)) |
9f95a23c TL |
1038 | return -EIO; |
1039 | ||
f67539c2 | 1040 | dev_debug(dev, "PKVL B Mode Status 0x%x\n", value); |
9f95a23c | 1041 | |
f67539c2 | 1042 | if (value >= 0x100) |
9f95a23c TL |
1043 | return -EINVAL; |
1044 | ||
1045 | return 0; | |
1046 | } | |
1047 | ||
1048 | static int fme_nios_spi_init(struct ifpga_feature *feature) | |
1049 | { | |
1050 | struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent; | |
1051 | struct altera_spi_device *spi_master; | |
1052 | struct intel_max10_device *max10; | |
f67539c2 TL |
1053 | struct ifpga_hw *hw; |
1054 | struct opae_manager *mgr; | |
9f95a23c TL |
1055 | int ret = 0; |
1056 | ||
f67539c2 TL |
1057 | hw = fme->parent; |
1058 | if (!hw) | |
1059 | return -ENODEV; | |
1060 | ||
1061 | mgr = hw->adapter->mgr; | |
1062 | if (!mgr) | |
1063 | return -ENODEV; | |
1064 | ||
9f95a23c TL |
1065 | dev_info(fme, "FME SPI Master (NIOS) Init.\n"); |
1066 | dev_debug(fme, "FME SPI base addr %p.\n", | |
1067 | feature->addr); | |
1068 | dev_debug(fme, "spi param=0x%llx\n", | |
1069 | (unsigned long long)opae_readq(feature->addr + 0x8)); | |
1070 | ||
1071 | spi_master = altera_spi_alloc(feature->addr, TYPE_NIOS_SPI); | |
1072 | if (!spi_master) | |
1073 | return -ENODEV; | |
1074 | ||
1075 | /** | |
1076 | * 1. wait A10 NIOS initial finished and | |
1077 | * release the SPI master to Host | |
1078 | */ | |
1079 | ret = nios_spi_wait_init_done(spi_master); | |
1080 | if (ret != 0) { | |
1081 | dev_err(fme, "FME NIOS_SPI init fail\n"); | |
1082 | goto release_dev; | |
1083 | } | |
1084 | ||
1085 | dev_info(fme, "FME NIOS_SPI initial done\n"); | |
1086 | ||
1087 | /* 2. check if error occur? */ | |
1088 | if (nios_spi_check_error(spi_master)) | |
1089 | dev_info(fme, "NIOS_SPI INIT done, but found some error\n"); | |
1090 | ||
1091 | /* 3. init the spi master*/ | |
1092 | altera_spi_init(spi_master); | |
1093 | ||
1094 | /* init the max10 device */ | |
1095 | max10 = intel_max10_device_probe(spi_master, 0); | |
1096 | if (!max10) { | |
1097 | ret = -ENODEV; | |
1098 | dev_err(fme, "max10 init fail\n"); | |
1099 | goto release_dev; | |
1100 | } | |
1101 | ||
f67539c2 TL |
1102 | max10->bus = hw->pci_data->bus; |
1103 | ||
9f95a23c TL |
1104 | fme_get_board_interface(fme); |
1105 | ||
1106 | fme->max10_dev = max10; | |
f67539c2 | 1107 | mgr->sensor_list = &max10->opae_sensor_list; |
9f95a23c TL |
1108 | |
1109 | /* SPI self test */ | |
f67539c2 | 1110 | if (spi_self_checking(max10)) |
9f95a23c TL |
1111 | goto spi_fail; |
1112 | ||
1113 | return ret; | |
1114 | ||
1115 | spi_fail: | |
1116 | intel_max10_device_remove(fme->max10_dev); | |
1117 | release_dev: | |
1118 | altera_spi_release(spi_master); | |
1119 | return -ENODEV; | |
1120 | } | |
1121 | ||
1122 | static void fme_nios_spi_uinit(struct ifpga_feature *feature) | |
1123 | { | |
1124 | struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent; | |
1125 | ||
1126 | if (fme->max10_dev) | |
1127 | intel_max10_device_remove(fme->max10_dev); | |
1128 | } | |
1129 | ||
1130 | struct ifpga_feature_ops fme_nios_spi_master_ops = { | |
1131 | .init = fme_nios_spi_init, | |
1132 | .uinit = fme_nios_spi_uinit, | |
1133 | }; | |
1134 | ||
1135 | static int i2c_mac_rom_test(struct altera_i2c_dev *dev) | |
1136 | { | |
1137 | char buf[20]; | |
1138 | int ret; | |
1139 | char read_buf[20] = {0,}; | |
1140 | const char *string = "1a2b3c4d5e"; | |
1141 | ||
1142 | opae_memcpy(buf, string, strlen(string)); | |
1143 | ||
1144 | ret = at24_eeprom_write(dev, AT24512_SLAVE_ADDR, 0, | |
1145 | (u8 *)buf, strlen(string)); | |
1146 | if (ret < 0) { | |
1147 | dev_err(NULL, "write i2c error:%d\n", ret); | |
1148 | return ret; | |
1149 | } | |
1150 | ||
1151 | ret = at24_eeprom_read(dev, AT24512_SLAVE_ADDR, 0, | |
1152 | (u8 *)read_buf, strlen(string)); | |
1153 | if (ret < 0) { | |
1154 | dev_err(NULL, "read i2c error:%d\n", ret); | |
1155 | return ret; | |
1156 | } | |
1157 | ||
1158 | if (memcmp(buf, read_buf, strlen(string))) { | |
1159 | dev_err(NULL, "%s test fail!\n", __func__); | |
1160 | return -EFAULT; | |
1161 | } | |
1162 | ||
1163 | dev_info(NULL, "%s test successful\n", __func__); | |
1164 | ||
1165 | return 0; | |
1166 | } | |
1167 | ||
1168 | static int fme_i2c_init(struct ifpga_feature *feature) | |
1169 | { | |
1170 | struct feature_fme_i2c *i2c; | |
1171 | struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent; | |
1172 | ||
1173 | i2c = (struct feature_fme_i2c *)feature->addr; | |
1174 | ||
1175 | dev_info(NULL, "FME I2C Master Init.\n"); | |
1176 | ||
1177 | fme->i2c_master = altera_i2c_probe(i2c); | |
1178 | if (!fme->i2c_master) | |
1179 | return -ENODEV; | |
1180 | ||
1181 | /* MAC ROM self test */ | |
1182 | i2c_mac_rom_test(fme->i2c_master); | |
1183 | ||
1184 | return 0; | |
1185 | } | |
1186 | ||
1187 | static void fme_i2c_uninit(struct ifpga_feature *feature) | |
1188 | { | |
1189 | struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent; | |
1190 | ||
1191 | altera_i2c_remove(fme->i2c_master); | |
1192 | } | |
1193 | ||
1194 | struct ifpga_feature_ops fme_i2c_master_ops = { | |
1195 | .init = fme_i2c_init, | |
1196 | .uinit = fme_i2c_uninit, | |
1197 | }; | |
1198 | ||
1199 | static int fme_eth_group_init(struct ifpga_feature *feature) | |
1200 | { | |
1201 | struct ifpga_fme_hw *fme = (struct ifpga_fme_hw *)feature->parent; | |
1202 | struct eth_group_device *dev; | |
1203 | ||
1204 | dev = (struct eth_group_device *)eth_group_probe(feature->addr); | |
1205 | if (!dev) | |
1206 | return -ENODEV; | |
1207 | ||
1208 | fme->eth_dev[dev->group_id] = dev; | |
1209 | ||
1210 | fme->eth_group_region[dev->group_id].addr = | |
1211 | feature->addr; | |
1212 | fme->eth_group_region[dev->group_id].phys_addr = | |
1213 | feature->phys_addr; | |
1214 | fme->eth_group_region[dev->group_id].len = | |
1215 | feature->size; | |
1216 | ||
1217 | fme->nums_eth_dev++; | |
1218 | ||
1219 | dev_info(NULL, "FME PHY Group %d Init.\n", dev->group_id); | |
1220 | dev_info(NULL, "found %d eth group, addr %p phys_addr 0x%llx len %u\n", | |
1221 | dev->group_id, feature->addr, | |
1222 | (unsigned long long)feature->phys_addr, | |
1223 | feature->size); | |
1224 | ||
1225 | return 0; | |
1226 | } | |
1227 | ||
1228 | static void fme_eth_group_uinit(struct ifpga_feature *feature) | |
1229 | { | |
1230 | UNUSED(feature); | |
1231 | } | |
1232 | ||
1233 | struct ifpga_feature_ops fme_eth_group_ops = { | |
1234 | .init = fme_eth_group_init, | |
1235 | .uinit = fme_eth_group_uinit, | |
1236 | }; | |
1237 | ||
1238 | int fme_mgr_read_mac_rom(struct ifpga_fme_hw *fme, int offset, | |
1239 | void *buf, int size) | |
1240 | { | |
1241 | struct altera_i2c_dev *dev; | |
1242 | ||
1243 | dev = fme->i2c_master; | |
1244 | if (!dev) | |
1245 | return -ENODEV; | |
1246 | ||
1247 | return at24_eeprom_read(dev, AT24512_SLAVE_ADDR, offset, buf, size); | |
1248 | } | |
1249 | ||
1250 | int fme_mgr_write_mac_rom(struct ifpga_fme_hw *fme, int offset, | |
1251 | void *buf, int size) | |
1252 | { | |
1253 | struct altera_i2c_dev *dev; | |
1254 | ||
1255 | dev = fme->i2c_master; | |
1256 | if (!dev) | |
1257 | return -ENODEV; | |
1258 | ||
1259 | return at24_eeprom_write(dev, AT24512_SLAVE_ADDR, offset, buf, size); | |
1260 | } | |
1261 | ||
1262 | static struct eth_group_device *get_eth_group_dev(struct ifpga_fme_hw *fme, | |
1263 | u8 group_id) | |
1264 | { | |
1265 | struct eth_group_device *dev; | |
1266 | ||
1267 | if (group_id > (MAX_ETH_GROUP_DEVICES - 1)) | |
1268 | return NULL; | |
1269 | ||
1270 | dev = (struct eth_group_device *)fme->eth_dev[group_id]; | |
1271 | if (!dev) | |
1272 | return NULL; | |
1273 | ||
1274 | if (dev->status != ETH_GROUP_DEV_ATTACHED) | |
1275 | return NULL; | |
1276 | ||
1277 | return dev; | |
1278 | } | |
1279 | ||
1280 | int fme_mgr_get_eth_group_nums(struct ifpga_fme_hw *fme) | |
1281 | { | |
1282 | return fme->nums_eth_dev; | |
1283 | } | |
1284 | ||
1285 | int fme_mgr_get_eth_group_info(struct ifpga_fme_hw *fme, | |
1286 | u8 group_id, struct opae_eth_group_info *info) | |
1287 | { | |
1288 | struct eth_group_device *dev; | |
1289 | ||
1290 | dev = get_eth_group_dev(fme, group_id); | |
1291 | if (!dev) | |
1292 | return -ENODEV; | |
1293 | ||
1294 | info->group_id = group_id; | |
1295 | info->speed = dev->speed; | |
1296 | info->nums_of_mac = dev->mac_num; | |
1297 | info->nums_of_phy = dev->phy_num; | |
1298 | ||
1299 | return 0; | |
1300 | } | |
1301 | ||
1302 | int fme_mgr_eth_group_read_reg(struct ifpga_fme_hw *fme, u8 group_id, | |
1303 | u8 type, u8 index, u16 addr, u32 *data) | |
1304 | { | |
1305 | struct eth_group_device *dev; | |
1306 | ||
1307 | dev = get_eth_group_dev(fme, group_id); | |
1308 | if (!dev) | |
1309 | return -ENODEV; | |
1310 | ||
1311 | return eth_group_read_reg(dev, type, index, addr, data); | |
1312 | } | |
1313 | ||
1314 | int fme_mgr_eth_group_write_reg(struct ifpga_fme_hw *fme, u8 group_id, | |
1315 | u8 type, u8 index, u16 addr, u32 data) | |
1316 | { | |
1317 | struct eth_group_device *dev; | |
1318 | ||
1319 | dev = get_eth_group_dev(fme, group_id); | |
1320 | if (!dev) | |
1321 | return -ENODEV; | |
1322 | ||
1323 | return eth_group_write_reg(dev, type, index, addr, data); | |
1324 | } | |
1325 | ||
1326 | static int fme_get_eth_group_speed(struct ifpga_fme_hw *fme, | |
1327 | u8 group_id) | |
1328 | { | |
1329 | struct eth_group_device *dev; | |
1330 | ||
1331 | dev = get_eth_group_dev(fme, group_id); | |
1332 | if (!dev) | |
1333 | return -ENODEV; | |
1334 | ||
1335 | return dev->speed; | |
1336 | } | |
1337 | ||
1338 | int fme_mgr_get_retimer_info(struct ifpga_fme_hw *fme, | |
1339 | struct opae_retimer_info *info) | |
1340 | { | |
1341 | struct intel_max10_device *dev; | |
1342 | ||
1343 | dev = (struct intel_max10_device *)fme->max10_dev; | |
1344 | if (!dev) | |
1345 | return -ENODEV; | |
1346 | ||
1347 | info->nums_retimer = fme->board_info.nums_of_retimer; | |
1348 | info->ports_per_retimer = fme->board_info.ports_per_retimer; | |
1349 | info->nums_fvl = fme->board_info.nums_of_fvl; | |
1350 | info->ports_per_fvl = fme->board_info.ports_per_fvl; | |
1351 | ||
1352 | /* The speed of PKVL is identical the eth group's speed */ | |
1353 | info->support_speed = fme_get_eth_group_speed(fme, | |
1354 | LINE_SIDE_GROUP_ID); | |
1355 | ||
1356 | return 0; | |
1357 | } | |
1358 | ||
1359 | int fme_mgr_get_retimer_status(struct ifpga_fme_hw *fme, | |
1360 | struct opae_retimer_status *status) | |
1361 | { | |
1362 | struct intel_max10_device *dev; | |
1363 | unsigned int val; | |
1364 | ||
1365 | dev = (struct intel_max10_device *)fme->max10_dev; | |
1366 | if (!dev) | |
1367 | return -ENODEV; | |
1368 | ||
f67539c2 | 1369 | if (max10_sys_read(dev, PKVL_LINK_STATUS, &val)) { |
9f95a23c TL |
1370 | dev_err(dev, "%s: read pkvl status fail\n", __func__); |
1371 | return -EINVAL; | |
1372 | } | |
1373 | ||
1374 | /* The speed of PKVL is identical the eth group's speed */ | |
1375 | status->speed = fme_get_eth_group_speed(fme, | |
1376 | LINE_SIDE_GROUP_ID); | |
1377 | ||
1378 | status->line_link_bitmap = val; | |
1379 | ||
1380 | dev_debug(dev, "get retimer status: speed:%d. line_link_bitmap:0x%x\n", | |
1381 | status->speed, | |
1382 | status->line_link_bitmap); | |
1383 | ||
1384 | return 0; | |
1385 | } | |
f67539c2 TL |
1386 | |
1387 | int fme_mgr_get_sensor_value(struct ifpga_fme_hw *fme, | |
1388 | struct opae_sensor_info *sensor, | |
1389 | unsigned int *value) | |
1390 | { | |
1391 | struct intel_max10_device *dev; | |
1392 | ||
1393 | dev = (struct intel_max10_device *)fme->max10_dev; | |
1394 | if (!dev) | |
1395 | return -ENODEV; | |
1396 | ||
1397 | if (max10_sys_read(dev, sensor->value_reg, value)) { | |
1398 | dev_err(dev, "%s: read sensor value register 0x%x fail\n", | |
1399 | __func__, sensor->value_reg); | |
1400 | return -EINVAL; | |
1401 | } | |
1402 | ||
1403 | *value *= sensor->multiplier; | |
1404 | ||
1405 | return 0; | |
1406 | } |