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