raw/ifpga/base: support sensor
[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 static struct max10_compatible_id max10_id_table[] = {
34         {.compatible = MAX10_PAC,},
35         {.compatible = MAX10_PAC_N3000,},
36         {.compatible = MAX10_PAC_END,}
37 };
38
39 static struct max10_compatible_id *max10_match_compatible(const char *fdt_root)
40 {
41         struct max10_compatible_id *id = max10_id_table;
42
43         for (; strcmp(id->compatible, MAX10_PAC_END); id++) {
44                 if (fdt_node_check_compatible(fdt_root, 0, id->compatible))
45                         continue;
46
47                 return id;
48         }
49
50         return NULL;
51 }
52
53 static inline bool
54 is_max10_pac_n3000(struct intel_max10_device *max10)
55 {
56         return max10->id && !strcmp(max10->id->compatible,
57                         MAX10_PAC_N3000);
58 }
59
60 static void max10_check_capability(struct intel_max10_device *max10)
61 {
62         if (!max10->fdt_root)
63                 return;
64
65         if (is_max10_pac_n3000(max10)) {
66                 max10->flags |= MAX10_FLAGS_NO_I2C2 |
67                                 MAX10_FLAGS_NO_BMCIMG_FLASH;
68                 dev_info(max10, "found %s card\n", max10->id->compatible);
69         }
70 }
71
72 static int altera_nor_flash_read(u32 offset,
73                 void *buffer, u32 len)
74 {
75         int word_len;
76         int i;
77         unsigned int *buf = (unsigned int *)buffer;
78         unsigned int value;
79         int ret;
80
81         if (!buffer || len <= 0)
82                 return -ENODEV;
83
84         word_len = len/4;
85
86         for (i = 0; i < word_len; i++) {
87                 ret = max10_reg_read(offset + i*4,
88                                 &value);
89                 if (ret)
90                         return -EBUSY;
91
92                 *buf++ = value;
93         }
94
95         return 0;
96 }
97
98 static int enable_nor_flash(bool on)
99 {
100         unsigned int val = 0;
101         int ret;
102
103         ret = max10_reg_read(RSU_REG_OFF, &val);
104         if (ret) {
105                 dev_err(NULL "enabling flash error\n");
106                 return ret;
107         }
108
109         if (on)
110                 val |= RSU_ENABLE;
111         else
112                 val &= ~RSU_ENABLE;
113
114         return max10_reg_write(RSU_REG_OFF, val);
115 }
116
117 static int init_max10_device_table(struct intel_max10_device *max10)
118 {
119         struct max10_compatible_id *id;
120         struct fdt_header hdr;
121         char *fdt_root = NULL;
122
123         u32 dt_size, dt_addr, val;
124         int ret;
125
126         ret = max10_reg_read(DT_AVAIL_REG_OFF, &val);
127         if (ret) {
128                 dev_err(max10 "cannot read DT_AVAIL_REG\n");
129                 return ret;
130         }
131
132         if (!(val & DT_AVAIL)) {
133                 dev_err(max10 "DT not available\n");
134                 return -EINVAL;
135         }
136
137         ret = max10_reg_read(DT_BASE_ADDR_REG_OFF, &dt_addr);
138         if (ret) {
139                 dev_info(max10 "cannot get base addr of device table\n");
140                 return ret;
141         }
142
143         ret = enable_nor_flash(true);
144         if (ret) {
145                 dev_err(max10 "fail to enable flash\n");
146                 return ret;
147         }
148
149         ret = altera_nor_flash_read(dt_addr, &hdr, sizeof(hdr));
150         if (ret) {
151                 dev_err(max10 "read fdt header fail\n");
152                 goto done;
153         }
154
155         ret = fdt_check_header(&hdr);
156         if (ret) {
157                 dev_err(max10 "check fdt header fail\n");
158                 goto done;
159         }
160
161         dt_size = fdt_totalsize(&hdr);
162         if (dt_size > DFT_MAX_SIZE) {
163                 dev_err(max10 "invalid device table size\n");
164                 ret = -EINVAL;
165                 goto done;
166         }
167
168         fdt_root = opae_malloc(dt_size);
169         if (!fdt_root) {
170                 ret = -ENOMEM;
171                 goto done;
172         }
173
174         ret = altera_nor_flash_read(dt_addr, fdt_root, dt_size);
175         if (ret) {
176                 dev_err(max10 "cannot read device table\n");
177                 goto done;
178         }
179
180         id = max10_match_compatible(fdt_root);
181         if (!id) {
182                 dev_err(max10 "max10 compatible not found\n");
183                 ret = -ENODEV;
184                 goto done;
185         }
186
187         max10->flags |= MAX10_FLAGS_DEVICE_TABLE;
188
189         max10->id = id;
190         max10->fdt_root = fdt_root;
191
192 done:
193         ret = enable_nor_flash(false);
194
195         if (ret && fdt_root)
196                 opae_free(fdt_root);
197
198         return ret;
199 }
200
201 static u64 fdt_get_number(const fdt32_t *cell, int size)
202 {
203         u64 r = 0;
204
205         while (size--)
206                 r = (r << 32) | fdt32_to_cpu(*cell++);
207
208         return r;
209 }
210
211 static int fdt_get_reg(const void *fdt, int node, unsigned int idx,
212                 u64 *start, u64 *size)
213 {
214         const fdt32_t *prop, *end;
215         int na = 0, ns = 0, len = 0, parent;
216
217         parent = fdt_parent_offset(fdt, node);
218         if (parent < 0)
219                 return parent;
220
221         prop = fdt_getprop(fdt, parent, "#address-cells", NULL);
222         na = prop ? fdt32_to_cpu(*prop) : 2;
223
224         prop = fdt_getprop(fdt, parent, "#size-cells", NULL);
225         ns = prop ? fdt32_to_cpu(*prop) : 2;
226
227         prop = fdt_getprop(fdt, node, "reg", &len);
228         if (!prop)
229                 return -FDT_ERR_NOTFOUND;
230
231         end = prop + len/sizeof(*prop);
232         prop = prop + (na + ns) * idx;
233
234         if (prop + na + ns > end)
235                 return -FDT_ERR_NOTFOUND;
236
237         *start = fdt_get_number(prop, na);
238         *size = fdt_get_number(prop + na, ns);
239
240         return 0;
241 }
242
243 static int __fdt_stringlist_search(const void *fdt, int offset,
244                 const char *prop, const char *string)
245 {
246         int length, len, index = 0;
247         const char *list, *end;
248
249         list = fdt_getprop(fdt, offset, prop, &length);
250         if (!list)
251                 return length;
252
253         len = strlen(string) + 1;
254         end = list + length;
255
256         while (list < end) {
257                 length = strnlen(list, end - list) + 1;
258
259                 if (list + length > end)
260                         return -FDT_ERR_BADVALUE;
261
262                 if (length == len && memcmp(list, string, length) == 0)
263                         return index;
264
265                 list += length;
266                 index++;
267         }
268
269         return -FDT_ERR_NOTFOUND;
270 }
271
272 static int fdt_get_named_reg(const void *fdt, int node, const char *name,
273                 u64 *start, u64 *size)
274 {
275         int idx;
276
277         idx = __fdt_stringlist_search(fdt, node, "reg-names", name);
278         if (idx < 0)
279                 return idx;
280
281         return fdt_get_reg(fdt, node, idx, start, size);
282 }
283
284 static void max10_sensor_uinit(void)
285 {
286         struct opae_sensor_info *info;
287
288         TAILQ_FOREACH(info, &opae_sensor_list, node) {
289                 TAILQ_REMOVE(&opae_sensor_list, info, node);
290                 opae_free(info);
291         }
292 }
293
294 static bool sensor_reg_valid(struct sensor_reg *reg)
295 {
296         return !!reg->size;
297 }
298
299 static int max10_add_sensor(struct raw_sensor_info *info,
300                 struct opae_sensor_info *sensor)
301 {
302         int i;
303         int ret = 0;
304         unsigned int val;
305
306         if (!info || !sensor)
307                 return -ENODEV;
308
309         sensor->id = info->id;
310         sensor->name = info->name;
311         sensor->type = info->type;
312         sensor->multiplier = info->multiplier;
313
314         for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++) {
315                 if (!sensor_reg_valid(&info->regs[i]))
316                         continue;
317
318                 ret = max10_reg_read(info->regs[i].regoff, &val);
319                 if (ret)
320                         break;
321
322                 if (val == 0xdeadbeef)
323                         continue;
324
325                 val *= info->multiplier;
326
327                 switch (i) {
328                 case SENSOR_REG_VALUE:
329                         sensor->value_reg = info->regs[i].regoff;
330                         sensor->flags |= OPAE_SENSOR_VALID;
331                         break;
332                 case SENSOR_REG_HIGH_WARN:
333                         sensor->high_warn = val;
334                         sensor->flags |= OPAE_SENSOR_HIGH_WARN_VALID;
335                         break;
336                 case SENSOR_REG_HIGH_FATAL:
337                         sensor->high_fatal = val;
338                         sensor->flags |= OPAE_SENSOR_HIGH_FATAL_VALID;
339                         break;
340                 case SENSOR_REG_LOW_WARN:
341                         sensor->low_warn = val;
342                         sensor->flags |= OPAE_SENSOR_LOW_WARN_VALID;
343                         break;
344                 case SENSOR_REG_LOW_FATAL:
345                         sensor->low_fatal = val;
346                         sensor->flags |= OPAE_SENSOR_LOW_FATAL_VALID;
347                         break;
348                 case SENSOR_REG_HYSTERESIS:
349                         sensor->hysteresis = val;
350                         sensor->flags |= OPAE_SENSOR_HYSTERESIS_VALID;
351                         break;
352                 }
353         }
354
355         return ret;
356 }
357
358 static int max10_sensor_init(struct intel_max10_device *dev)
359 {
360         int i, ret = 0, offset = 0;
361         const fdt32_t *num;
362         const char *ptr;
363         u64 start, size;
364         struct raw_sensor_info *raw;
365         struct opae_sensor_info *sensor;
366         char *fdt_root = dev->fdt_root;
367
368         if (!fdt_root) {
369                 dev_debug(dev, "skip sensor init as not find Device Tree\n");
370                 return 0;
371         }
372
373         fdt_for_each_subnode(offset, fdt_root, 0) {
374                 ptr = fdt_get_name(fdt_root, offset, NULL);
375                 if (!ptr) {
376                         dev_err(dev, "failed to fdt get name\n");
377                         continue;
378                 }
379
380                 if (!strstr(ptr, "sensor")) {
381                         dev_debug(dev, "%s is not a sensor node\n", ptr);
382                         continue;
383                 }
384
385                 dev_debug(dev, "found sensor node %s\n", ptr);
386
387                 raw = (struct raw_sensor_info *)opae_zmalloc(sizeof(*raw));
388                 if (!raw) {
389                         ret = -ENOMEM;
390                         goto free_sensor;
391                 }
392
393                 raw->name = fdt_getprop(fdt_root, offset, "sensor_name", NULL);
394                 if (!raw->name) {
395                         ret = -EINVAL;
396                         goto free_sensor;
397                 }
398
399                 raw->type = fdt_getprop(fdt_root, offset, "type", NULL);
400                 if (!raw->type) {
401                         ret = -EINVAL;
402                         goto free_sensor;
403                 }
404
405                 for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++) {
406                         ret = fdt_get_named_reg(fdt_root, offset,
407                                         sensor_reg_name[i], &start,
408                                         &size);
409                         if (ret) {
410                                 dev_debug(dev, "no found %d: sensor node %s, %s\n",
411                                                 ret, ptr, sensor_reg_name[i]);
412                                 if (i == SENSOR_REG_VALUE) {
413                                         ret = -EINVAL;
414                                         goto free_sensor;
415                                 }
416
417                                 continue;
418                         }
419
420                         raw->regs[i].regoff = start;
421                         raw->regs[i].size = size;
422                 }
423
424                 num = fdt_getprop(fdt_root, offset, "id", NULL);
425                 if (!num) {
426                         ret = -EINVAL;
427                         goto free_sensor;
428                 }
429
430                 raw->id = fdt32_to_cpu(*num);
431                 num = fdt_getprop(fdt_root, offset, "multiplier", NULL);
432                 raw->multiplier = num ? fdt32_to_cpu(*num) : 1;
433
434                 dev_info(dev, "found sensor from DTB: %s: %s: %u: %u\n",
435                                 raw->name, raw->type,
436                                 raw->id, raw->multiplier);
437
438                 for (i = SENSOR_REG_VALUE; i < SENSOR_REG_MAX; i++)
439                         dev_debug(dev, "sensor reg[%d]: %x: %zu\n",
440                                         i, raw->regs[i].regoff,
441                                         raw->regs[i].size);
442
443                 sensor = opae_zmalloc(sizeof(*sensor));
444                 if (!sensor) {
445                         ret = -EINVAL;
446                         goto free_sensor;
447                 }
448
449                 if (max10_add_sensor(raw, sensor)) {
450                         ret = -EINVAL;
451                         opae_free(sensor);
452                         goto free_sensor;
453                 }
454
455                 if (sensor->flags & OPAE_SENSOR_VALID)
456                         TAILQ_INSERT_TAIL(&opae_sensor_list, sensor, node);
457                 else
458                         opae_free(sensor);
459
460                 opae_free(raw);
461         }
462
463         return 0;
464
465 free_sensor:
466         if (raw)
467                 opae_free(raw);
468         max10_sensor_uinit();
469         return ret;
470 }
471
472 struct intel_max10_device *
473 intel_max10_device_probe(struct altera_spi_device *spi,
474                 int chipselect)
475 {
476         struct intel_max10_device *dev;
477         int ret;
478         unsigned int val;
479
480         dev = opae_malloc(sizeof(*dev));
481         if (!dev)
482                 return NULL;
483
484         dev->spi_master = spi;
485
486         dev->spi_tran_dev = spi_transaction_init(spi, chipselect);
487         if (!dev->spi_tran_dev) {
488                 dev_err(dev, "%s spi tran init fail\n", __func__);
489                 goto free_dev;
490         }
491
492         /* set the max10 device firstly */
493         g_max10 = dev;
494
495         /* init the MAX10 device table */
496         ret = init_max10_device_table(dev);
497         if (ret) {
498                 dev_err(dev, "init max10 device table fail\n");
499                 goto free_dev;
500         }
501
502         max10_check_capability(dev);
503
504         /* read FPGA loading information */
505         ret = max10_reg_read(FPGA_PAGE_INFO_OFF, &val);
506         if (ret) {
507                 dev_err(dev, "fail to get FPGA loading info\n");
508                 goto spi_tran_fail;
509         }
510         dev_info(dev, "FPGA loaded from %s Image\n", val ? "User" : "Factory");
511
512
513         max10_sensor_init(dev);
514
515         return dev;
516
517 spi_tran_fail:
518         if (dev->fdt_root)
519                 opae_free(dev->fdt_root);
520         spi_transaction_remove(dev->spi_tran_dev);
521 free_dev:
522         g_max10 = NULL;
523         opae_free(dev);
524
525         return NULL;
526 }
527
528 int intel_max10_device_remove(struct intel_max10_device *dev)
529 {
530         if (!dev)
531                 return 0;
532
533         max10_sensor_uinit();
534
535         if (dev->spi_tran_dev)
536                 spi_transaction_remove(dev->spi_tran_dev);
537
538         if (dev->fdt_root)
539                 opae_free(dev->fdt_root);
540
541         g_max10 = NULL;
542         opae_free(dev);
543
544         return 0;
545 }