raw/ifpga: support lightweight FPGA image
[dpdk.git] / drivers / raw / ifpga / base / opae_intel_max10.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2019 Intel Corporation
3  */
4
5 #include "opae_intel_max10.h"
6 #include <libfdt.h>
7
8 static struct intel_max10_device *g_max10;
9
10 struct opae_sensor_list opae_sensor_list =
11         TAILQ_HEAD_INITIALIZER(opae_sensor_list);
12
13 int max10_reg_read(unsigned int reg, unsigned int *val)
14 {
15         if (!g_max10)
16                 return -ENODEV;
17
18         return spi_transaction_read(g_max10->spi_tran_dev,
19                         reg, 4, (unsigned char *)val);
20 }
21
22 int max10_reg_write(unsigned int reg, unsigned int val)
23 {
24         unsigned int tmp = val;
25
26         if (!g_max10)
27                 return -ENODEV;
28
29         return spi_transaction_write(g_max10->spi_tran_dev,
30                         reg, 4, (unsigned char *)&tmp);
31 }
32
33 int max10_sys_read(unsigned int offset, unsigned int *val)
34 {
35         if (!g_max10)
36                 return -ENODEV;
37
38         return max10_reg_read(g_max10->base + offset, val);
39 }
40
41 int max10_sys_write(unsigned int offset, unsigned int val)
42 {
43         if (!g_max10)
44                 return -ENODEV;
45
46         return max10_reg_write(g_max10->base + offset, val);
47 }
48
49 static struct max10_compatible_id max10_id_table[] = {
50         {.compatible = MAX10_PAC,},
51         {.compatible = MAX10_PAC_N3000,},
52         {.compatible = MAX10_PAC_END,}
53 };
54
55 static struct max10_compatible_id *max10_match_compatible(const char *fdt_root)
56 {
57         struct max10_compatible_id *id = max10_id_table;
58
59         for (; strcmp(id->compatible, MAX10_PAC_END); id++) {
60                 if (fdt_node_check_compatible(fdt_root, 0, id->compatible))
61                         continue;
62
63                 return id;
64         }
65
66         return NULL;
67 }
68
69 static inline bool
70 is_max10_pac_n3000(struct intel_max10_device *max10)
71 {
72         return max10->id && !strcmp(max10->id->compatible,
73                         MAX10_PAC_N3000);
74 }
75
76 static void max10_check_capability(struct intel_max10_device *max10)
77 {
78         if (!max10->fdt_root)
79                 return;
80
81         if (is_max10_pac_n3000(max10)) {
82                 max10->flags |= MAX10_FLAGS_NO_I2C2 |
83                                 MAX10_FLAGS_NO_BMCIMG_FLASH;
84                 dev_info(max10, "found %s card\n", max10->id->compatible);
85         } else
86                 max10->flags |= MAX10_FLAGS_MAC_CACHE;
87 }
88
89 static int altera_nor_flash_read(u32 offset,
90                 void *buffer, u32 len)
91 {
92         int word_len;
93         int i;
94         unsigned int *buf = (unsigned int *)buffer;
95         unsigned int value;
96         int ret;
97
98         if (!buffer || len <= 0)
99                 return -ENODEV;
100
101         word_len = len/4;
102
103         for (i = 0; i < word_len; i++) {
104                 ret = max10_reg_read(offset + i*4,
105                                 &value);
106                 if (ret)
107                         return -EBUSY;
108
109                 *buf++ = value;
110         }
111
112         return 0;
113 }
114
115 static int enable_nor_flash(bool on)
116 {
117         unsigned int val = 0;
118         int ret;
119
120         ret = max10_sys_read(RSU_REG, &val);
121         if (ret) {
122                 dev_err(NULL "enabling flash error\n");
123                 return ret;
124         }
125
126         if (on)
127                 val |= RSU_ENABLE;
128         else
129                 val &= ~RSU_ENABLE;
130
131         return max10_sys_write(RSU_REG, val);
132 }
133
134 static int init_max10_device_table(struct intel_max10_device *max10)
135 {
136         struct max10_compatible_id *id;
137         struct fdt_header hdr;
138         char *fdt_root = NULL;
139
140         u32 dt_size, dt_addr, val;
141         int ret;
142
143         ret = max10_sys_read(DT_AVAIL_REG, &val);
144         if (ret) {
145                 dev_err(max10 "cannot read DT_AVAIL_REG\n");
146                 return ret;
147         }
148
149         if (!(val & DT_AVAIL)) {
150                 dev_err(max10 "DT not available\n");
151                 return -EINVAL;
152         }
153
154         ret = max10_sys_read(DT_BASE_ADDR_REG, &dt_addr);
155         if (ret) {
156                 dev_info(max10 "cannot get base addr of device table\n");
157                 return ret;
158         }
159
160         ret = enable_nor_flash(true);
161         if (ret) {
162                 dev_err(max10 "fail to enable flash\n");
163                 return ret;
164         }
165
166         ret = altera_nor_flash_read(dt_addr, &hdr, sizeof(hdr));
167         if (ret) {
168                 dev_err(max10 "read fdt header fail\n");
169                 goto done;
170         }
171
172         ret = fdt_check_header(&hdr);
173         if (ret) {
174                 dev_err(max10 "check fdt header fail\n");
175                 goto done;
176         }
177
178         dt_size = fdt_totalsize(&hdr);
179         if (dt_size > DFT_MAX_SIZE) {
180                 dev_err(max10 "invalid device table size\n");
181                 ret = -EINVAL;
182                 goto done;
183         }
184
185         fdt_root = opae_malloc(dt_size);
186         if (!fdt_root) {
187                 ret = -ENOMEM;
188                 goto done;
189         }
190
191         ret = altera_nor_flash_read(dt_addr, fdt_root, dt_size);
192         if (ret) {
193                 dev_err(max10 "cannot read device table\n");
194                 goto done;
195         }
196
197         id = max10_match_compatible(fdt_root);
198         if (!id) {
199                 dev_err(max10 "max10 compatible not found\n");
200                 ret = -ENODEV;
201                 goto done;
202         }
203
204         max10->flags |= MAX10_FLAGS_DEVICE_TABLE;
205
206         max10->id = id;
207         max10->fdt_root = fdt_root;
208
209 done:
210         ret = enable_nor_flash(false);
211
212         if (ret && fdt_root)
213                 opae_free(fdt_root);
214
215         return ret;
216 }
217
218 static u64 fdt_get_number(const fdt32_t *cell, int size)
219 {
220         u64 r = 0;
221
222         while (size--)
223                 r = (r << 32) | fdt32_to_cpu(*cell++);
224
225         return r;
226 }
227
228 static int fdt_get_reg(const void *fdt, int node, unsigned int idx,
229                 u64 *start, u64 *size)
230 {
231         const fdt32_t *prop, *end;
232         int na = 0, ns = 0, len = 0, parent;
233
234         parent = fdt_parent_offset(fdt, node);
235         if (parent < 0)
236                 return parent;
237
238         prop = fdt_getprop(fdt, parent, "#address-cells", NULL);
239         na = prop ? fdt32_to_cpu(*prop) : 2;
240
241         prop = fdt_getprop(fdt, parent, "#size-cells", NULL);
242         ns = prop ? fdt32_to_cpu(*prop) : 2;
243
244         prop = fdt_getprop(fdt, node, "reg", &len);
245         if (!prop)
246                 return -FDT_ERR_NOTFOUND;
247
248         end = prop + len/sizeof(*prop);
249         prop = prop + (na + ns) * idx;
250
251         if (prop + na + ns > end)
252                 return -FDT_ERR_NOTFOUND;
253
254         *start = fdt_get_number(prop, na);
255         *size = fdt_get_number(prop + na, ns);
256
257         return 0;
258 }
259
260 static int __fdt_stringlist_search(const void *fdt, int offset,
261                 const char *prop, const char *string)
262 {
263         int length, len, index = 0;
264         const char *list, *end;
265
266         list = fdt_getprop(fdt, offset, prop, &length);
267         if (!list)
268                 return length;
269
270         len = strlen(string) + 1;
271         end = list + length;
272
273         while (list < end) {
274                 length = strnlen(list, end - list) + 1;
275
276                 if (list + length > end)
277                         return -FDT_ERR_BADVALUE;
278
279                 if (length == len && memcmp(list, string, length) == 0)
280                         return index;
281
282                 list += length;
283                 index++;
284         }
285
286         return -FDT_ERR_NOTFOUND;
287 }
288
289 static int fdt_get_named_reg(const void *fdt, int node, const char *name,
290                 u64 *start, u64 *size)
291 {
292         int idx;
293
294         idx = __fdt_stringlist_search(fdt, node, "reg-names", name);
295         if (idx < 0)
296                 return idx;
297
298         return fdt_get_reg(fdt, node, idx, start, size);
299 }
300
301 static void max10_sensor_uinit(void)
302 {
303         struct opae_sensor_info *info;
304
305         TAILQ_FOREACH(info, &opae_sensor_list, node) {
306                 TAILQ_REMOVE(&opae_sensor_list, info, node);
307                 opae_free(info);
308         }
309 }
310
311 static bool sensor_reg_valid(struct sensor_reg *reg)
312 {
313         return !!reg->size;
314 }
315
316 static int max10_add_sensor(struct raw_sensor_info *info,
317                 struct opae_sensor_info *sensor)
318 {
319         int i;
320         int ret = 0;
321         unsigned int val;
322
323         if (!info || !sensor)
324                 return -ENODEV;
325
326         sensor->id = info->id;
327         sensor->name = info->name;
328         sensor->type = info->type;
329         sensor->multiplier = info->multiplier;
330
331         for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++) {
332                 if (!sensor_reg_valid(&info->regs[i]))
333                         continue;
334
335                 ret = max10_sys_read(info->regs[i].regoff, &val);
336                 if (ret)
337                         break;
338
339                 if (val == 0xdeadbeef)
340                         continue;
341
342                 val *= info->multiplier;
343
344                 switch (i) {
345                 case SENSOR_REG_VALUE:
346                         sensor->value_reg = info->regs[i].regoff;
347                         sensor->flags |= OPAE_SENSOR_VALID;
348                         break;
349                 case SENSOR_REG_HIGH_WARN:
350                         sensor->high_warn = val;
351                         sensor->flags |= OPAE_SENSOR_HIGH_WARN_VALID;
352                         break;
353                 case SENSOR_REG_HIGH_FATAL:
354                         sensor->high_fatal = val;
355                         sensor->flags |= OPAE_SENSOR_HIGH_FATAL_VALID;
356                         break;
357                 case SENSOR_REG_LOW_WARN:
358                         sensor->low_warn = val;
359                         sensor->flags |= OPAE_SENSOR_LOW_WARN_VALID;
360                         break;
361                 case SENSOR_REG_LOW_FATAL:
362                         sensor->low_fatal = val;
363                         sensor->flags |= OPAE_SENSOR_LOW_FATAL_VALID;
364                         break;
365                 case SENSOR_REG_HYSTERESIS:
366                         sensor->hysteresis = val;
367                         sensor->flags |= OPAE_SENSOR_HYSTERESIS_VALID;
368                         break;
369                 }
370         }
371
372         return ret;
373 }
374
375 static int
376 max10_sensor_init(struct intel_max10_device *dev, int parent)
377 {
378         int i, ret = 0, offset = 0;
379         const fdt32_t *num;
380         const char *ptr;
381         u64 start, size;
382         struct raw_sensor_info *raw;
383         struct opae_sensor_info *sensor;
384         char *fdt_root = dev->fdt_root;
385
386         if (!fdt_root) {
387                 dev_debug(dev, "skip sensor init as not find Device Tree\n");
388                 return 0;
389         }
390
391         fdt_for_each_subnode(offset, fdt_root, parent) {
392                 ptr = fdt_get_name(fdt_root, offset, NULL);
393                 if (!ptr) {
394                         dev_err(dev, "failed to fdt get name\n");
395                         continue;
396                 }
397
398                 if (!strstr(ptr, "sensor")) {
399                         dev_debug(dev, "%s is not a sensor node\n", ptr);
400                         continue;
401                 }
402
403                 dev_debug(dev, "found sensor node %s\n", ptr);
404
405                 raw = (struct raw_sensor_info *)opae_zmalloc(sizeof(*raw));
406                 if (!raw) {
407                         ret = -ENOMEM;
408                         goto free_sensor;
409                 }
410
411                 raw->name = fdt_getprop(fdt_root, offset, "sensor_name", NULL);
412                 if (!raw->name) {
413                         ret = -EINVAL;
414                         goto free_sensor;
415                 }
416
417                 raw->type = fdt_getprop(fdt_root, offset, "type", NULL);
418                 if (!raw->type) {
419                         ret = -EINVAL;
420                         goto free_sensor;
421                 }
422
423                 for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++) {
424                         ret = fdt_get_named_reg(fdt_root, offset,
425                                         sensor_reg_name[i], &start,
426                                         &size);
427                         if (ret) {
428                                 dev_debug(dev, "no found %d: sensor node %s, %s\n",
429                                                 ret, ptr, sensor_reg_name[i]);
430                                 if (i == SENSOR_REG_VALUE) {
431                                         ret = -EINVAL;
432                                         goto free_sensor;
433                                 }
434
435                                 continue;
436                         }
437
438                         /* This is a hack to compatible with non-secure
439                          * solution. If sensors are included in root node,
440                          * then it's non-secure dtb, which use absolute addr
441                          * of non-secure solution.
442                          */
443                         if (parent)
444                                 raw->regs[i].regoff = start;
445                         else
446                                 raw->regs[i].regoff = start -
447                                         MAX10_BASE_ADDR;
448                         raw->regs[i].size = size;
449                 }
450
451                 num = fdt_getprop(fdt_root, offset, "id", NULL);
452                 if (!num) {
453                         ret = -EINVAL;
454                         goto free_sensor;
455                 }
456
457                 raw->id = fdt32_to_cpu(*num);
458                 num = fdt_getprop(fdt_root, offset, "multiplier", NULL);
459                 raw->multiplier = num ? fdt32_to_cpu(*num) : 1;
460
461                 dev_info(dev, "found sensor from DTB: %s: %s: %u: %u\n",
462                                 raw->name, raw->type,
463                                 raw->id, raw->multiplier);
464
465                 for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++)
466                         dev_debug(dev, "sensor reg[%d]: %x: %zu\n",
467                                         i, raw->regs[i].regoff,
468                                         raw->regs[i].size);
469
470                 sensor = opae_zmalloc(sizeof(*sensor));
471                 if (!sensor) {
472                         ret = -EINVAL;
473                         goto free_sensor;
474                 }
475
476                 if (max10_add_sensor(raw, sensor)) {
477                         ret = -EINVAL;
478                         opae_free(sensor);
479                         goto free_sensor;
480                 }
481
482                 if (sensor->flags & OPAE_SENSOR_VALID)
483                         TAILQ_INSERT_TAIL(&opae_sensor_list, sensor, node);
484                 else
485                         opae_free(sensor);
486
487                 opae_free(raw);
488         }
489
490         return 0;
491
492 free_sensor:
493         if (raw)
494                 opae_free(raw);
495         max10_sensor_uinit();
496         return ret;
497 }
498
499 static int check_max10_version(struct intel_max10_device *dev)
500 {
501         unsigned int v;
502
503         if (!max10_reg_read(MAX10_SEC_BASE_ADDR + MAX10_BUILD_VER,
504                                 &v)) {
505                 if (v != 0xffffffff) {
506                         dev_info(dev, "secure MAX10 detected\n");
507                         dev->base = MAX10_SEC_BASE_ADDR;
508                         dev->flags |= MAX10_FLAGS_SECURE;
509                 } else {
510                         dev_info(dev, "non-secure MAX10 detected\n");
511                         dev->base = MAX10_BASE_ADDR;
512                 }
513                 return 0;
514         }
515
516         return -ENODEV;
517 }
518
519 static int
520 max10_secure_hw_init(struct intel_max10_device *dev)
521 {
522         int offset, sysmgr_offset = 0;
523         char *fdt_root;
524
525         fdt_root = dev->fdt_root;
526         if (!fdt_root) {
527                 dev_debug(dev, "skip init as not find Device Tree\n");
528                 return 0;
529         }
530
531         fdt_for_each_subnode(offset, fdt_root, 0) {
532                 if (!fdt_node_check_compatible(fdt_root, offset,
533                                         "intel-max10,system-manager")) {
534                         sysmgr_offset = offset;
535                         break;
536                 }
537         }
538
539         max10_check_capability(dev);
540
541         max10_sensor_init(dev, sysmgr_offset);
542
543         return 0;
544 }
545
546 static int
547 max10_non_secure_hw_init(struct intel_max10_device *dev)
548 {
549         max10_check_capability(dev);
550
551         max10_sensor_init(dev, 0);
552
553         return 0;
554 }
555
556 struct intel_max10_device *
557 intel_max10_device_probe(struct altera_spi_device *spi,
558                 int chipselect)
559 {
560         struct intel_max10_device *dev;
561         int ret;
562         unsigned int val;
563
564         dev = opae_malloc(sizeof(*dev));
565         if (!dev)
566                 return NULL;
567
568         dev->spi_master = spi;
569
570         dev->spi_tran_dev = spi_transaction_init(spi, chipselect);
571         if (!dev->spi_tran_dev) {
572                 dev_err(dev, "%s spi tran init fail\n", __func__);
573                 goto free_dev;
574         }
575
576         /* set the max10 device firstly */
577         g_max10 = dev;
578
579         /* check the max10 version */
580         ret = check_max10_version(dev);
581         if (ret) {
582                 dev_err(dev, "Failed to find max10 hardware!\n");
583                 goto free_dev;
584         }
585
586         /* load the MAX10 device table */
587         ret = init_max10_device_table(dev);
588         if (ret) {
589                 dev_err(dev, "Init max10 device table fail\n");
590                 goto free_dev;
591         }
592
593         /* init max10 devices, like sensor*/
594         if (dev->flags & MAX10_FLAGS_SECURE)
595                 ret = max10_secure_hw_init(dev);
596         else
597                 ret = max10_non_secure_hw_init(dev);
598         if (ret) {
599                 dev_err(dev, "Failed to init max10 hardware!\n");
600                 goto free_dtb;
601         }
602
603         /* read FPGA loading information */
604         ret = max10_sys_read(FPGA_PAGE_INFO, &val);
605         if (ret) {
606                 dev_err(dev, "fail to get FPGA loading info\n");
607                 goto release_max10_hw;
608         }
609         dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" : "Factory");
610
611         return dev;
612
613 release_max10_hw:
614         max10_sensor_uinit();
615 free_dtb:
616         if (dev->fdt_root)
617                 opae_free(dev->fdt_root);
618         if (dev->spi_tran_dev)
619                 spi_transaction_remove(dev->spi_tran_dev);
620 free_dev:
621         g_max10 = NULL;
622         opae_free(dev);
623
624         return NULL;
625 }
626
627 int intel_max10_device_remove(struct intel_max10_device *dev)
628 {
629         if (!dev)
630                 return 0;
631
632         max10_sensor_uinit();
633
634         if (dev->spi_tran_dev)
635                 spi_transaction_remove(dev->spi_tran_dev);
636
637         if (dev->fdt_root)
638                 opae_free(dev->fdt_root);
639
640         g_max10 = NULL;
641         opae_free(dev);
642
643         return 0;
644 }