Merge tag 'seccomp-v5.14-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/kees...
[linux-2.6-microblaze.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_FSI2PIB_ERROR       (SCOM_STATUS_PROTECTION |       \
42                                          SCOM_STATUS_PARITY |           \
43                                          SCOM_STATUS_PIB_ABORT)
44 #define SCOM_STATUS_ANY_ERR             (SCOM_STATUS_FSI2PIB_ERROR |    \
45                                          SCOM_STATUS_PIB_RESP_MASK)
46 /* SCOM address encodings */
47 #define XSCOM_ADDR_IND_FLAG             BIT_ULL(63)
48 #define XSCOM_ADDR_INF_FORM1            BIT_ULL(60)
49
50 /* SCOM indirect stuff */
51 #define XSCOM_ADDR_DIRECT_PART          0x7fffffffull
52 #define XSCOM_ADDR_INDIRECT_PART        0x000fffff00000000ull
53 #define XSCOM_DATA_IND_READ             BIT_ULL(63)
54 #define XSCOM_DATA_IND_COMPLETE         BIT_ULL(31)
55 #define XSCOM_DATA_IND_ERR_MASK         0x70000000ull
56 #define XSCOM_DATA_IND_ERR_SHIFT        28
57 #define XSCOM_DATA_IND_DATA             0x0000ffffull
58 #define XSCOM_DATA_IND_FORM1_DATA       0x000fffffffffffffull
59 #define XSCOM_ADDR_FORM1_LOW            0x000ffffffffull
60 #define XSCOM_ADDR_FORM1_HI             0xfff00000000ull
61 #define XSCOM_ADDR_FORM1_HI_SHIFT       20
62
63 /* Retries */
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_FSI2PIB_ERROR)
244                 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
245                                  sizeof(uint32_t));
246
247         if (status & SCOM_STATUS_PROTECTION)
248                 return -EPERM;
249         if (status & SCOM_STATUS_PARITY)
250                 return -EIO;
251
252         if (status & SCOM_STATUS_PIB_ABORT)
253                 return -EBUSY;
254         return 0;
255 }
256
257 static int handle_pib_status(struct scom_device *scom, uint8_t status)
258 {
259         uint32_t dummy = -1;
260
261         if (status == SCOM_PIB_SUCCESS)
262                 return 0;
263         if (status == SCOM_PIB_BLOCKED)
264                 return -EBUSY;
265
266         /* Reset the bridge */
267         fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
268                          sizeof(uint32_t));
269
270         switch(status) {
271         case SCOM_PIB_OFFLINE:
272                 return -ENODEV;
273         case SCOM_PIB_BAD_ADDR:
274                 return -ENXIO;
275         case SCOM_PIB_TIMEOUT:
276                 return -ETIMEDOUT;
277         case SCOM_PIB_PARTIAL:
278         case SCOM_PIB_CLK_ERR:
279         case SCOM_PIB_PARITY_ERR:
280         default:
281                 return -EIO;
282         }
283 }
284
285 static int put_scom(struct scom_device *scom, uint64_t value,
286                     uint64_t addr)
287 {
288         uint32_t status;
289         int rc;
290
291         rc = raw_put_scom(scom, value, addr, &status);
292         if (rc == -ENODEV)
293                 return rc;
294
295         rc = handle_fsi2pib_status(scom, status);
296         if (rc)
297                 return rc;
298
299         return handle_pib_status(scom,
300                                  (status & SCOM_STATUS_PIB_RESP_MASK)
301                                  >> SCOM_STATUS_PIB_RESP_SHIFT);
302 }
303
304 static int get_scom(struct scom_device *scom, uint64_t *value,
305                     uint64_t addr)
306 {
307         uint32_t status;
308         int rc;
309
310         rc = raw_get_scom(scom, value, addr, &status);
311         if (rc == -ENODEV)
312                 return rc;
313
314         rc = handle_fsi2pib_status(scom, status);
315         if (rc)
316                 return rc;
317
318         return handle_pib_status(scom,
319                                  (status & SCOM_STATUS_PIB_RESP_MASK)
320                                  >> SCOM_STATUS_PIB_RESP_SHIFT);
321 }
322
323 static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
324                          loff_t *offset)
325 {
326         struct scom_device *scom = filep->private_data;
327         struct device *dev = &scom->fsi_dev->dev;
328         uint64_t val;
329         int rc;
330
331         if (len != sizeof(uint64_t))
332                 return -EINVAL;
333
334         mutex_lock(&scom->lock);
335         if (scom->dead)
336                 rc = -ENODEV;
337         else
338                 rc = get_scom(scom, &val, *offset);
339         mutex_unlock(&scom->lock);
340         if (rc) {
341                 dev_dbg(dev, "get_scom fail:%d\n", rc);
342                 return rc;
343         }
344
345         rc = copy_to_user(buf, &val, len);
346         if (rc)
347                 dev_dbg(dev, "copy to user failed:%d\n", rc);
348
349         return rc ? rc : len;
350 }
351
352 static ssize_t scom_write(struct file *filep, const char __user *buf,
353                           size_t len, loff_t *offset)
354 {
355         int rc;
356         struct scom_device *scom = filep->private_data;
357         struct device *dev = &scom->fsi_dev->dev;
358         uint64_t val;
359
360         if (len != sizeof(uint64_t))
361                 return -EINVAL;
362
363         rc = copy_from_user(&val, buf, len);
364         if (rc) {
365                 dev_dbg(dev, "copy from user failed:%d\n", rc);
366                 return -EINVAL;
367         }
368
369         mutex_lock(&scom->lock);
370         if (scom->dead)
371                 rc = -ENODEV;
372         else
373                 rc = put_scom(scom, val, *offset);
374         mutex_unlock(&scom->lock);
375         if (rc) {
376                 dev_dbg(dev, "put_scom failed with:%d\n", rc);
377                 return rc;
378         }
379
380         return len;
381 }
382
383 static loff_t scom_llseek(struct file *file, loff_t offset, int whence)
384 {
385         switch (whence) {
386         case SEEK_CUR:
387                 break;
388         case SEEK_SET:
389                 file->f_pos = offset;
390                 break;
391         default:
392                 return -EINVAL;
393         }
394
395         return offset;
396 }
397
398 static void raw_convert_status(struct scom_access *acc, uint32_t status)
399 {
400         acc->pib_status = (status & SCOM_STATUS_PIB_RESP_MASK) >>
401                 SCOM_STATUS_PIB_RESP_SHIFT;
402         acc->intf_errors = 0;
403
404         if (status & SCOM_STATUS_PROTECTION)
405                 acc->intf_errors |= SCOM_INTF_ERR_PROTECTION;
406         else if (status & SCOM_STATUS_PARITY)
407                 acc->intf_errors |= SCOM_INTF_ERR_PARITY;
408         else if (status & SCOM_STATUS_PIB_ABORT)
409                 acc->intf_errors |= SCOM_INTF_ERR_ABORT;
410         else if (status & SCOM_STATUS_ERR_SUMMARY)
411                 acc->intf_errors |= SCOM_INTF_ERR_UNKNOWN;
412 }
413
414 static int scom_raw_read(struct scom_device *scom, void __user *argp)
415 {
416         struct scom_access acc;
417         uint32_t status;
418         int rc;
419
420         if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
421                 return -EFAULT;
422
423         rc = raw_get_scom(scom, &acc.data, acc.addr, &status);
424         if (rc)
425                 return rc;
426         raw_convert_status(&acc, status);
427         if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
428                 return -EFAULT;
429         return 0;
430 }
431
432 static int scom_raw_write(struct scom_device *scom, void __user *argp)
433 {
434         u64 prev_data, mask, data;
435         struct scom_access acc;
436         uint32_t status;
437         int rc;
438
439         if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
440                 return -EFAULT;
441
442         if (acc.mask) {
443                 rc = raw_get_scom(scom, &prev_data, acc.addr, &status);
444                 if (rc)
445                         return rc;
446                 if (status & SCOM_STATUS_ANY_ERR)
447                         goto fail;
448                 mask = acc.mask;
449         } else {
450                 prev_data = mask = -1ull;
451         }
452         data = (prev_data & ~mask) | (acc.data & mask);
453         rc = raw_put_scom(scom, data, acc.addr, &status);
454         if (rc)
455                 return rc;
456  fail:
457         raw_convert_status(&acc, status);
458         if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
459                 return -EFAULT;
460         return 0;
461 }
462
463 static int scom_reset(struct scom_device *scom, void __user *argp)
464 {
465         uint32_t flags, dummy = -1;
466         int rc = 0;
467
468         if (get_user(flags, (__u32 __user *)argp))
469                 return -EFAULT;
470         if (flags & SCOM_RESET_PIB)
471                 rc = fsi_device_write(scom->fsi_dev, SCOM_PIB_RESET_REG, &dummy,
472                                       sizeof(uint32_t));
473         if (!rc && (flags & (SCOM_RESET_PIB | SCOM_RESET_INTF)))
474                 rc = fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
475                                       sizeof(uint32_t));
476         return rc;
477 }
478
479 static int scom_check(struct scom_device *scom, void __user *argp)
480 {
481         /* Still need to find out how to get "protected" */
482         return put_user(SCOM_CHECK_SUPPORTED, (__u32 __user *)argp);
483 }
484
485 static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
486 {
487         struct scom_device *scom = file->private_data;
488         void __user *argp = (void __user *)arg;
489         int rc = -ENOTTY;
490
491         mutex_lock(&scom->lock);
492         if (scom->dead) {
493                 mutex_unlock(&scom->lock);
494                 return -ENODEV;
495         }
496         switch(cmd) {
497         case FSI_SCOM_CHECK:
498                 rc = scom_check(scom, argp);
499                 break;
500         case FSI_SCOM_READ:
501                 rc = scom_raw_read(scom, argp);
502                 break;
503         case FSI_SCOM_WRITE:
504                 rc = scom_raw_write(scom, argp);
505                 break;
506         case FSI_SCOM_RESET:
507                 rc = scom_reset(scom, argp);
508                 break;
509         }
510         mutex_unlock(&scom->lock);
511         return rc;
512 }
513
514 static int scom_open(struct inode *inode, struct file *file)
515 {
516         struct scom_device *scom = container_of(inode->i_cdev, struct scom_device, cdev);
517
518         file->private_data = scom;
519
520         return 0;
521 }
522
523 static const struct file_operations scom_fops = {
524         .owner          = THIS_MODULE,
525         .open           = scom_open,
526         .llseek         = scom_llseek,
527         .read           = scom_read,
528         .write          = scom_write,
529         .unlocked_ioctl = scom_ioctl,
530 };
531
532 static void scom_free(struct device *dev)
533 {
534         struct scom_device *scom = container_of(dev, struct scom_device, dev);
535
536         put_device(&scom->fsi_dev->dev);
537         kfree(scom);
538 }
539
540 static int scom_probe(struct device *dev)
541 {
542         struct fsi_device *fsi_dev = to_fsi_dev(dev);
543         struct scom_device *scom;
544         int rc, didx;
545
546         scom = kzalloc(sizeof(*scom), GFP_KERNEL);
547         if (!scom)
548                 return -ENOMEM;
549         dev_set_drvdata(dev, scom);
550         mutex_init(&scom->lock);
551
552         /* Grab a reference to the device (parent of our cdev), we'll drop it later */
553         if (!get_device(dev)) {
554                 kfree(scom);
555                 return -ENODEV;
556         }
557         scom->fsi_dev = fsi_dev;
558
559         /* Create chardev for userspace access */
560         scom->dev.type = &fsi_cdev_type;
561         scom->dev.parent = dev;
562         scom->dev.release = scom_free;
563         device_initialize(&scom->dev);
564
565         /* Allocate a minor in the FSI space */
566         rc = fsi_get_new_minor(fsi_dev, fsi_dev_scom, &scom->dev.devt, &didx);
567         if (rc)
568                 goto err;
569
570         dev_set_name(&scom->dev, "scom%d", didx);
571         cdev_init(&scom->cdev, &scom_fops);
572         rc = cdev_device_add(&scom->cdev, &scom->dev);
573         if (rc) {
574                 dev_err(dev, "Error %d creating char device %s\n",
575                         rc, dev_name(&scom->dev));
576                 goto err_free_minor;
577         }
578
579         return 0;
580  err_free_minor:
581         fsi_free_minor(scom->dev.devt);
582  err:
583         put_device(&scom->dev);
584         return rc;
585 }
586
587 static int scom_remove(struct device *dev)
588 {
589         struct scom_device *scom = dev_get_drvdata(dev);
590
591         mutex_lock(&scom->lock);
592         scom->dead = true;
593         mutex_unlock(&scom->lock);
594         cdev_device_del(&scom->cdev, &scom->dev);
595         fsi_free_minor(scom->dev.devt);
596         put_device(&scom->dev);
597
598         return 0;
599 }
600
601 static const struct fsi_device_id scom_ids[] = {
602         {
603                 .engine_type = FSI_ENGID_SCOM,
604                 .version = FSI_VERSION_ANY,
605         },
606         { 0 }
607 };
608
609 static struct fsi_driver scom_drv = {
610         .id_table = scom_ids,
611         .drv = {
612                 .name = "scom",
613                 .bus = &fsi_bus_type,
614                 .probe = scom_probe,
615                 .remove = scom_remove,
616         }
617 };
618
619 static int scom_init(void)
620 {
621         return fsi_driver_register(&scom_drv);
622 }
623
624 static void scom_exit(void)
625 {
626         fsi_driver_unregister(&scom_drv);
627 }
628
629 module_init(scom_init);
630 module_exit(scom_exit);
631 MODULE_LICENSE("GPL");