Merge tag 'ktest-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[platform/kernel/linux-rpi.git] / drivers / fsi / fsi-scom.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * SCOM FSI Client device driver
4  *
5  * Copyright (C) IBM Corporation 2016
6  */
7
8 #include <linux/fsi.h>
9 #include <linux/module.h>
10 #include <linux/cdev.h>
11 #include <linux/delay.h>
12 #include <linux/fs.h>
13 #include <linux/uaccess.h>
14 #include <linux/slab.h>
15 #include <linux/list.h>
16
17 #include <uapi/linux/fsi.h>
18
19 #define FSI_ENGID_SCOM          0x5
20
21 /* SCOM engine register set */
22 #define SCOM_DATA0_REG          0x00
23 #define SCOM_DATA1_REG          0x04
24 #define SCOM_CMD_REG            0x08
25 #define SCOM_FSI2PIB_RESET_REG  0x18
26 #define SCOM_STATUS_REG         0x1C /* Read */
27 #define SCOM_PIB_RESET_REG      0x1C /* Write */
28
29 /* Command register */
30 #define SCOM_WRITE_CMD          0x80000000
31 #define SCOM_READ_CMD           0x00000000
32
33 /* Status register bits */
34 #define SCOM_STATUS_ERR_SUMMARY         0x80000000
35 #define SCOM_STATUS_PROTECTION          0x01000000
36 #define SCOM_STATUS_PARITY              0x04000000
37 #define SCOM_STATUS_PIB_ABORT           0x00100000
38 #define SCOM_STATUS_PIB_RESP_MASK       0x00007000
39 #define SCOM_STATUS_PIB_RESP_SHIFT      12
40
41 #define SCOM_STATUS_ANY_ERR             (SCOM_STATUS_PROTECTION | \
42                                          SCOM_STATUS_PARITY |     \
43                                          SCOM_STATUS_PIB_ABORT | \
44                                          SCOM_STATUS_PIB_RESP_MASK)
45 /* SCOM address encodings */
46 #define XSCOM_ADDR_IND_FLAG             BIT_ULL(63)
47 #define XSCOM_ADDR_INF_FORM1            BIT_ULL(60)
48
49 /* SCOM indirect stuff */
50 #define XSCOM_ADDR_DIRECT_PART          0x7fffffffull
51 #define XSCOM_ADDR_INDIRECT_PART        0x000fffff00000000ull
52 #define XSCOM_DATA_IND_READ             BIT_ULL(63)
53 #define XSCOM_DATA_IND_COMPLETE         BIT_ULL(31)
54 #define XSCOM_DATA_IND_ERR_MASK         0x70000000ull
55 #define XSCOM_DATA_IND_ERR_SHIFT        28
56 #define XSCOM_DATA_IND_DATA             0x0000ffffull
57 #define XSCOM_DATA_IND_FORM1_DATA       0x000fffffffffffffull
58 #define XSCOM_ADDR_FORM1_LOW            0x000ffffffffull
59 #define XSCOM_ADDR_FORM1_HI             0xfff00000000ull
60 #define XSCOM_ADDR_FORM1_HI_SHIFT       20
61
62 /* Retries */
63 #define SCOM_MAX_RETRIES                100     /* Retries on busy */
64 #define SCOM_MAX_IND_RETRIES            10      /* Retries indirect not ready */
65
66 struct scom_device {
67         struct list_head link;
68         struct fsi_device *fsi_dev;
69         struct device dev;
70         struct cdev cdev;
71         struct mutex lock;
72         bool dead;
73 };
74
75 static int __put_scom(struct scom_device *scom_dev, uint64_t value,
76                       uint32_t addr, uint32_t *status)
77 {
78         __be32 data, raw_status;
79         int rc;
80
81         data = cpu_to_be32((value >> 32) & 0xffffffff);
82         rc = fsi_device_write(scom_dev->fsi_dev, SCOM_DATA0_REG, &data,
83                                 sizeof(uint32_t));
84         if (rc)
85                 return rc;
86
87         data = cpu_to_be32(value & 0xffffffff);
88         rc = fsi_device_write(scom_dev->fsi_dev, SCOM_DATA1_REG, &data,
89                                 sizeof(uint32_t));
90         if (rc)
91                 return rc;
92
93         data = cpu_to_be32(SCOM_WRITE_CMD | addr);
94         rc = fsi_device_write(scom_dev->fsi_dev, SCOM_CMD_REG, &data,
95                                 sizeof(uint32_t));
96         if (rc)
97                 return rc;
98         rc = fsi_device_read(scom_dev->fsi_dev, SCOM_STATUS_REG, &raw_status,
99                              sizeof(uint32_t));
100         if (rc)
101                 return rc;
102         *status = be32_to_cpu(raw_status);
103
104         return 0;
105 }
106
107 static int __get_scom(struct scom_device *scom_dev, uint64_t *value,
108                       uint32_t addr, uint32_t *status)
109 {
110         __be32 data, raw_status;
111         int rc;
112
113
114         *value = 0ULL;
115         data = cpu_to_be32(SCOM_READ_CMD | addr);
116         rc = fsi_device_write(scom_dev->fsi_dev, SCOM_CMD_REG, &data,
117                                 sizeof(uint32_t));
118         if (rc)
119                 return rc;
120         rc = fsi_device_read(scom_dev->fsi_dev, SCOM_STATUS_REG, &raw_status,
121                              sizeof(uint32_t));
122         if (rc)
123                 return rc;
124
125         /*
126          * Read the data registers even on error, so we don't have
127          * to interpret the status register here.
128          */
129         rc = fsi_device_read(scom_dev->fsi_dev, SCOM_DATA0_REG, &data,
130                                 sizeof(uint32_t));
131         if (rc)
132                 return rc;
133         *value |= (uint64_t)be32_to_cpu(data) << 32;
134         rc = fsi_device_read(scom_dev->fsi_dev, SCOM_DATA1_REG, &data,
135                                 sizeof(uint32_t));
136         if (rc)
137                 return rc;
138         *value |= be32_to_cpu(data);
139         *status = be32_to_cpu(raw_status);
140
141         return rc;
142 }
143
144 static int put_indirect_scom_form0(struct scom_device *scom, uint64_t value,
145                                    uint64_t addr, uint32_t *status)
146 {
147         uint64_t ind_data, ind_addr;
148         int rc, retries, err = 0;
149
150         if (value & ~XSCOM_DATA_IND_DATA)
151                 return -EINVAL;
152
153         ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
154         ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | value;
155         rc = __put_scom(scom, ind_data, ind_addr, status);
156         if (rc || (*status & SCOM_STATUS_ANY_ERR))
157                 return rc;
158
159         for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
160                 rc = __get_scom(scom, &ind_data, addr, status);
161                 if (rc || (*status & SCOM_STATUS_ANY_ERR))
162                         return rc;
163
164                 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
165                 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
166                 if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
167                         return 0;
168
169                 msleep(1);
170         }
171         return rc;
172 }
173
174 static int put_indirect_scom_form1(struct scom_device *scom, uint64_t value,
175                                    uint64_t addr, uint32_t *status)
176 {
177         uint64_t ind_data, ind_addr;
178
179         if (value & ~XSCOM_DATA_IND_FORM1_DATA)
180                 return -EINVAL;
181
182         ind_addr = addr & XSCOM_ADDR_FORM1_LOW;
183         ind_data = value | (addr & XSCOM_ADDR_FORM1_HI) << XSCOM_ADDR_FORM1_HI_SHIFT;
184         return __put_scom(scom, ind_data, ind_addr, status);
185 }
186
187 static int get_indirect_scom_form0(struct scom_device *scom, uint64_t *value,
188                                    uint64_t addr, uint32_t *status)
189 {
190         uint64_t ind_data, ind_addr;
191         int rc, retries, err = 0;
192
193         ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
194         ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | XSCOM_DATA_IND_READ;
195         rc = __put_scom(scom, ind_data, ind_addr, status);
196         if (rc || (*status & SCOM_STATUS_ANY_ERR))
197                 return rc;
198
199         for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
200                 rc = __get_scom(scom, &ind_data, addr, status);
201                 if (rc || (*status & SCOM_STATUS_ANY_ERR))
202                         return rc;
203
204                 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
205                 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
206                 *value = ind_data & XSCOM_DATA_IND_DATA;
207
208                 if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
209                         return 0;
210
211                 msleep(1);
212         }
213         return rc;
214 }
215
216 static int raw_put_scom(struct scom_device *scom, uint64_t value,
217                         uint64_t addr, uint32_t *status)
218 {
219         if (addr & XSCOM_ADDR_IND_FLAG) {
220                 if (addr & XSCOM_ADDR_INF_FORM1)
221                         return put_indirect_scom_form1(scom, value, addr, status);
222                 else
223                         return put_indirect_scom_form0(scom, value, addr, status);
224         } else
225                 return __put_scom(scom, value, addr, status);
226 }
227
228 static int raw_get_scom(struct scom_device *scom, uint64_t *value,
229                         uint64_t addr, uint32_t *status)
230 {
231         if (addr & XSCOM_ADDR_IND_FLAG) {
232                 if (addr & XSCOM_ADDR_INF_FORM1)
233                         return -ENXIO;
234                 return get_indirect_scom_form0(scom, value, addr, status);
235         } else
236                 return __get_scom(scom, value, addr, status);
237 }
238
239 static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status)
240 {
241         uint32_t dummy = -1;
242
243         if (status & SCOM_STATUS_PROTECTION)
244                 return -EPERM;
245         if (status & SCOM_STATUS_PARITY) {
246                 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
247                                  sizeof(uint32_t));
248                 return -EIO;
249         }
250         /* Return -EBUSY on PIB abort to force a retry */
251         if (status & SCOM_STATUS_PIB_ABORT)
252                 return -EBUSY;
253         return 0;
254 }
255
256 static int handle_pib_status(struct scom_device *scom, uint8_t status)
257 {
258         uint32_t dummy = -1;
259
260         if (status == SCOM_PIB_SUCCESS)
261                 return 0;
262         if (status == SCOM_PIB_BLOCKED)
263                 return -EBUSY;
264
265         /* Reset the bridge */
266         fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
267                          sizeof(uint32_t));
268
269         switch(status) {
270         case SCOM_PIB_OFFLINE:
271                 return -ENODEV;
272         case SCOM_PIB_BAD_ADDR:
273                 return -ENXIO;
274         case SCOM_PIB_TIMEOUT:
275                 return -ETIMEDOUT;
276         case SCOM_PIB_PARTIAL:
277         case SCOM_PIB_CLK_ERR:
278         case SCOM_PIB_PARITY_ERR:
279         default:
280                 return -EIO;
281         }
282 }
283
284 static int put_scom(struct scom_device *scom, uint64_t value,
285                     uint64_t addr)
286 {
287         uint32_t status, dummy = -1;
288         int rc, retries;
289
290         for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) {
291                 rc = raw_put_scom(scom, value, addr, &status);
292                 if (rc) {
293                         /* Try resetting the bridge if FSI fails */
294                         if (rc != -ENODEV && retries == 0) {
295                                 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG,
296                                                  &dummy, sizeof(uint32_t));
297                                 rc = -EBUSY;
298                         } else
299                                 return rc;
300                 } else
301                         rc = handle_fsi2pib_status(scom, status);
302                 if (rc && rc != -EBUSY)
303                         break;
304                 if (rc == 0) {
305                         rc = handle_pib_status(scom,
306                                                (status & SCOM_STATUS_PIB_RESP_MASK)
307                                                >> SCOM_STATUS_PIB_RESP_SHIFT);
308                         if (rc && rc != -EBUSY)
309                                 break;
310                 }
311                 if (rc == 0)
312                         break;
313                 msleep(1);
314         }
315         return rc;
316 }
317
318 static int get_scom(struct scom_device *scom, uint64_t *value,
319                     uint64_t addr)
320 {
321         uint32_t status, dummy = -1;
322         int rc, retries;
323
324         for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) {
325                 rc = raw_get_scom(scom, value, addr, &status);
326                 if (rc) {
327                         /* Try resetting the bridge if FSI fails */
328                         if (rc != -ENODEV && retries == 0) {
329                                 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG,
330                                                  &dummy, sizeof(uint32_t));
331                                 rc = -EBUSY;
332                         } else
333                                 return rc;
334                 } else
335                         rc = handle_fsi2pib_status(scom, status);
336                 if (rc && rc != -EBUSY)
337                         break;
338                 if (rc == 0) {
339                         rc = handle_pib_status(scom,
340                                                (status & SCOM_STATUS_PIB_RESP_MASK)
341                                                >> SCOM_STATUS_PIB_RESP_SHIFT);
342                         if (rc && rc != -EBUSY)
343                                 break;
344                 }
345                 if (rc == 0)
346                         break;
347                 msleep(1);
348         }
349         return rc;
350 }
351
352 static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
353                          loff_t *offset)
354 {
355         struct scom_device *scom = filep->private_data;
356         struct device *dev = &scom->fsi_dev->dev;
357         uint64_t val;
358         int rc;
359
360         if (len != sizeof(uint64_t))
361                 return -EINVAL;
362
363         mutex_lock(&scom->lock);
364         if (scom->dead)
365                 rc = -ENODEV;
366         else
367                 rc = get_scom(scom, &val, *offset);
368         mutex_unlock(&scom->lock);
369         if (rc) {
370                 dev_dbg(dev, "get_scom fail:%d\n", rc);
371                 return rc;
372         }
373
374         rc = copy_to_user(buf, &val, len);
375         if (rc)
376                 dev_dbg(dev, "copy to user failed:%d\n", rc);
377
378         return rc ? rc : len;
379 }
380
381 static ssize_t scom_write(struct file *filep, const char __user *buf,
382                           size_t len, loff_t *offset)
383 {
384         int rc;
385         struct scom_device *scom = filep->private_data;
386         struct device *dev = &scom->fsi_dev->dev;
387         uint64_t val;
388
389         if (len != sizeof(uint64_t))
390                 return -EINVAL;
391
392         rc = copy_from_user(&val, buf, len);
393         if (rc) {
394                 dev_dbg(dev, "copy from user failed:%d\n", rc);
395                 return -EINVAL;
396         }
397
398         mutex_lock(&scom->lock);
399         if (scom->dead)
400                 rc = -ENODEV;
401         else
402                 rc = put_scom(scom, val, *offset);
403         mutex_unlock(&scom->lock);
404         if (rc) {
405                 dev_dbg(dev, "put_scom failed with:%d\n", rc);
406                 return rc;
407         }
408
409         return len;
410 }
411
412 static loff_t scom_llseek(struct file *file, loff_t offset, int whence)
413 {
414         switch (whence) {
415         case SEEK_CUR:
416                 break;
417         case SEEK_SET:
418                 file->f_pos = offset;
419                 break;
420         default:
421                 return -EINVAL;
422         }
423
424         return offset;
425 }
426
427 static void raw_convert_status(struct scom_access *acc, uint32_t status)
428 {
429         acc->pib_status = (status & SCOM_STATUS_PIB_RESP_MASK) >>
430                 SCOM_STATUS_PIB_RESP_SHIFT;
431         acc->intf_errors = 0;
432
433         if (status & SCOM_STATUS_PROTECTION)
434                 acc->intf_errors |= SCOM_INTF_ERR_PROTECTION;
435         else if (status & SCOM_STATUS_PARITY)
436                 acc->intf_errors |= SCOM_INTF_ERR_PARITY;
437         else if (status & SCOM_STATUS_PIB_ABORT)
438                 acc->intf_errors |= SCOM_INTF_ERR_ABORT;
439         else if (status & SCOM_STATUS_ERR_SUMMARY)
440                 acc->intf_errors |= SCOM_INTF_ERR_UNKNOWN;
441 }
442
443 static int scom_raw_read(struct scom_device *scom, void __user *argp)
444 {
445         struct scom_access acc;
446         uint32_t status;
447         int rc;
448
449         if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
450                 return -EFAULT;
451
452         rc = raw_get_scom(scom, &acc.data, acc.addr, &status);
453         if (rc)
454                 return rc;
455         raw_convert_status(&acc, status);
456         if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
457                 return -EFAULT;
458         return 0;
459 }
460
461 static int scom_raw_write(struct scom_device *scom, void __user *argp)
462 {
463         u64 prev_data, mask, data;
464         struct scom_access acc;
465         uint32_t status;
466         int rc;
467
468         if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
469                 return -EFAULT;
470
471         if (acc.mask) {
472                 rc = raw_get_scom(scom, &prev_data, acc.addr, &status);
473                 if (rc)
474                         return rc;
475                 if (status & SCOM_STATUS_ANY_ERR)
476                         goto fail;
477                 mask = acc.mask;
478         } else {
479                 prev_data = mask = -1ull;
480         }
481         data = (prev_data & ~mask) | (acc.data & mask);
482         rc = raw_put_scom(scom, data, acc.addr, &status);
483         if (rc)
484                 return rc;
485  fail:
486         raw_convert_status(&acc, status);
487         if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
488                 return -EFAULT;
489         return 0;
490 }
491
492 static int scom_reset(struct scom_device *scom, void __user *argp)
493 {
494         uint32_t flags, dummy = -1;
495         int rc = 0;
496
497         if (get_user(flags, (__u32 __user *)argp))
498                 return -EFAULT;
499         if (flags & SCOM_RESET_PIB)
500                 rc = fsi_device_write(scom->fsi_dev, SCOM_PIB_RESET_REG, &dummy,
501                                       sizeof(uint32_t));
502         if (!rc && (flags & (SCOM_RESET_PIB | SCOM_RESET_INTF)))
503                 rc = fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
504                                       sizeof(uint32_t));
505         return rc;
506 }
507
508 static int scom_check(struct scom_device *scom, void __user *argp)
509 {
510         /* Still need to find out how to get "protected" */
511         return put_user(SCOM_CHECK_SUPPORTED, (__u32 __user *)argp);
512 }
513
514 static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
515 {
516         struct scom_device *scom = file->private_data;
517         void __user *argp = (void __user *)arg;
518         int rc = -ENOTTY;
519
520         mutex_lock(&scom->lock);
521         if (scom->dead) {
522                 mutex_unlock(&scom->lock);
523                 return -ENODEV;
524         }
525         switch(cmd) {
526         case FSI_SCOM_CHECK:
527                 rc = scom_check(scom, argp);
528                 break;
529         case FSI_SCOM_READ:
530                 rc = scom_raw_read(scom, argp);
531                 break;
532         case FSI_SCOM_WRITE:
533                 rc = scom_raw_write(scom, argp);
534                 break;
535         case FSI_SCOM_RESET:
536                 rc = scom_reset(scom, argp);
537                 break;
538         }
539         mutex_unlock(&scom->lock);
540         return rc;
541 }
542
543 static int scom_open(struct inode *inode, struct file *file)
544 {
545         struct scom_device *scom = container_of(inode->i_cdev, struct scom_device, cdev);
546
547         file->private_data = scom;
548
549         return 0;
550 }
551
552 static const struct file_operations scom_fops = {
553         .owner          = THIS_MODULE,
554         .open           = scom_open,
555         .llseek         = scom_llseek,
556         .read           = scom_read,
557         .write          = scom_write,
558         .unlocked_ioctl = scom_ioctl,
559 };
560
561 static void scom_free(struct device *dev)
562 {
563         struct scom_device *scom = container_of(dev, struct scom_device, dev);
564
565         put_device(&scom->fsi_dev->dev);
566         kfree(scom);
567 }
568
569 static int scom_probe(struct device *dev)
570 {
571         struct fsi_device *fsi_dev = to_fsi_dev(dev);
572         struct scom_device *scom;
573         int rc, didx;
574
575         scom = kzalloc(sizeof(*scom), GFP_KERNEL);
576         if (!scom)
577                 return -ENOMEM;
578         dev_set_drvdata(dev, scom);
579         mutex_init(&scom->lock);
580
581         /* Grab a reference to the device (parent of our cdev), we'll drop it later */
582         if (!get_device(dev)) {
583                 kfree(scom);
584                 return -ENODEV;
585         }
586         scom->fsi_dev = fsi_dev;
587
588         /* Create chardev for userspace access */
589         scom->dev.type = &fsi_cdev_type;
590         scom->dev.parent = dev;
591         scom->dev.release = scom_free;
592         device_initialize(&scom->dev);
593
594         /* Allocate a minor in the FSI space */
595         rc = fsi_get_new_minor(fsi_dev, fsi_dev_scom, &scom->dev.devt, &didx);
596         if (rc)
597                 goto err;
598
599         dev_set_name(&scom->dev, "scom%d", didx);
600         cdev_init(&scom->cdev, &scom_fops);
601         rc = cdev_device_add(&scom->cdev, &scom->dev);
602         if (rc) {
603                 dev_err(dev, "Error %d creating char device %s\n",
604                         rc, dev_name(&scom->dev));
605                 goto err_free_minor;
606         }
607
608         return 0;
609  err_free_minor:
610         fsi_free_minor(scom->dev.devt);
611  err:
612         put_device(&scom->dev);
613         return rc;
614 }
615
616 static int scom_remove(struct device *dev)
617 {
618         struct scom_device *scom = dev_get_drvdata(dev);
619
620         mutex_lock(&scom->lock);
621         scom->dead = true;
622         mutex_unlock(&scom->lock);
623         cdev_device_del(&scom->cdev, &scom->dev);
624         fsi_free_minor(scom->dev.devt);
625         put_device(&scom->dev);
626
627         return 0;
628 }
629
630 static const struct fsi_device_id scom_ids[] = {
631         {
632                 .engine_type = FSI_ENGID_SCOM,
633                 .version = FSI_VERSION_ANY,
634         },
635         { 0 }
636 };
637
638 static struct fsi_driver scom_drv = {
639         .id_table = scom_ids,
640         .drv = {
641                 .name = "scom",
642                 .bus = &fsi_bus_type,
643                 .probe = scom_probe,
644                 .remove = scom_remove,
645         }
646 };
647
648 static int scom_init(void)
649 {
650         return fsi_driver_register(&scom_drv);
651 }
652
653 static void scom_exit(void)
654 {
655         fsi_driver_unregister(&scom_drv);
656 }
657
658 module_init(scom_init);
659 module_exit(scom_exit);
660 MODULE_LICENSE("GPL");