fsi: scom: Reset the FSI2PIB engine for any error
[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_RETRIES                100     /* Retries on busy */
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, retries, err = 0;
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         for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
161                 rc = __get_scom(scom, &ind_data, addr, status);
162                 if (rc || (*status & SCOM_STATUS_ANY_ERR))
163                         return rc;
164
165                 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
166                 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
167                 if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
168                         return 0;
169
170                 msleep(1);
171         }
172         return rc;
173 }
174
175 static int put_indirect_scom_form1(struct scom_device *scom, uint64_t value,
176                                    uint64_t addr, uint32_t *status)
177 {
178         uint64_t ind_data, ind_addr;
179
180         if (value & ~XSCOM_DATA_IND_FORM1_DATA)
181                 return -EINVAL;
182
183         ind_addr = addr & XSCOM_ADDR_FORM1_LOW;
184         ind_data = value | (addr & XSCOM_ADDR_FORM1_HI) << XSCOM_ADDR_FORM1_HI_SHIFT;
185         return __put_scom(scom, ind_data, ind_addr, status);
186 }
187
188 static int get_indirect_scom_form0(struct scom_device *scom, uint64_t *value,
189                                    uint64_t addr, uint32_t *status)
190 {
191         uint64_t ind_data, ind_addr;
192         int rc, retries, err = 0;
193
194         ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
195         ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | XSCOM_DATA_IND_READ;
196         rc = __put_scom(scom, ind_data, ind_addr, status);
197         if (rc || (*status & SCOM_STATUS_ANY_ERR))
198                 return rc;
199
200         for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
201                 rc = __get_scom(scom, &ind_data, addr, status);
202                 if (rc || (*status & SCOM_STATUS_ANY_ERR))
203                         return rc;
204
205                 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
206                 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
207                 *value = ind_data & XSCOM_DATA_IND_DATA;
208
209                 if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
210                         return 0;
211
212                 msleep(1);
213         }
214         return rc;
215 }
216
217 static int raw_put_scom(struct scom_device *scom, uint64_t value,
218                         uint64_t addr, uint32_t *status)
219 {
220         if (addr & XSCOM_ADDR_IND_FLAG) {
221                 if (addr & XSCOM_ADDR_INF_FORM1)
222                         return put_indirect_scom_form1(scom, value, addr, status);
223                 else
224                         return put_indirect_scom_form0(scom, value, addr, status);
225         } else
226                 return __put_scom(scom, value, addr, status);
227 }
228
229 static int raw_get_scom(struct scom_device *scom, uint64_t *value,
230                         uint64_t addr, uint32_t *status)
231 {
232         if (addr & XSCOM_ADDR_IND_FLAG) {
233                 if (addr & XSCOM_ADDR_INF_FORM1)
234                         return -ENXIO;
235                 return get_indirect_scom_form0(scom, value, addr, status);
236         } else
237                 return __get_scom(scom, value, addr, status);
238 }
239
240 static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status)
241 {
242         uint32_t dummy = -1;
243
244         if (status & SCOM_STATUS_FSI2PIB_ERROR)
245                 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
246                                  sizeof(uint32_t));
247
248         if (status & SCOM_STATUS_PROTECTION)
249                 return -EPERM;
250         if (status & SCOM_STATUS_PARITY)
251                 return -EIO;
252         /* Return -EBUSY on PIB abort to force a retry */
253         if (status & SCOM_STATUS_PIB_ABORT)
254                 return -EBUSY;
255         return 0;
256 }
257
258 static int handle_pib_status(struct scom_device *scom, uint8_t status)
259 {
260         uint32_t dummy = -1;
261
262         if (status == SCOM_PIB_SUCCESS)
263                 return 0;
264         if (status == SCOM_PIB_BLOCKED)
265                 return -EBUSY;
266
267         /* Reset the bridge */
268         fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
269                          sizeof(uint32_t));
270
271         switch(status) {
272         case SCOM_PIB_OFFLINE:
273                 return -ENODEV;
274         case SCOM_PIB_BAD_ADDR:
275                 return -ENXIO;
276         case SCOM_PIB_TIMEOUT:
277                 return -ETIMEDOUT;
278         case SCOM_PIB_PARTIAL:
279         case SCOM_PIB_CLK_ERR:
280         case SCOM_PIB_PARITY_ERR:
281         default:
282                 return -EIO;
283         }
284 }
285
286 static int put_scom(struct scom_device *scom, uint64_t value,
287                     uint64_t addr)
288 {
289         uint32_t status, dummy = -1;
290         int rc, retries;
291
292         for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) {
293                 rc = raw_put_scom(scom, value, addr, &status);
294                 if (rc) {
295                         /* Try resetting the bridge if FSI fails */
296                         if (rc != -ENODEV && retries == 0) {
297                                 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG,
298                                                  &dummy, sizeof(uint32_t));
299                                 rc = -EBUSY;
300                         } else
301                                 return rc;
302                 } else
303                         rc = handle_fsi2pib_status(scom, status);
304                 if (rc && rc != -EBUSY)
305                         break;
306                 if (rc == 0) {
307                         rc = handle_pib_status(scom,
308                                                (status & SCOM_STATUS_PIB_RESP_MASK)
309                                                >> SCOM_STATUS_PIB_RESP_SHIFT);
310                         if (rc && rc != -EBUSY)
311                                 break;
312                 }
313                 if (rc == 0)
314                         break;
315                 msleep(1);
316         }
317         return rc;
318 }
319
320 static int get_scom(struct scom_device *scom, uint64_t *value,
321                     uint64_t addr)
322 {
323         uint32_t status, dummy = -1;
324         int rc, retries;
325
326         for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) {
327                 rc = raw_get_scom(scom, value, addr, &status);
328                 if (rc) {
329                         /* Try resetting the bridge if FSI fails */
330                         if (rc != -ENODEV && retries == 0) {
331                                 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG,
332                                                  &dummy, sizeof(uint32_t));
333                                 rc = -EBUSY;
334                         } else
335                                 return rc;
336                 } else
337                         rc = handle_fsi2pib_status(scom, status);
338                 if (rc && rc != -EBUSY)
339                         break;
340                 if (rc == 0) {
341                         rc = handle_pib_status(scom,
342                                                (status & SCOM_STATUS_PIB_RESP_MASK)
343                                                >> SCOM_STATUS_PIB_RESP_SHIFT);
344                         if (rc && rc != -EBUSY)
345                                 break;
346                 }
347                 if (rc == 0)
348                         break;
349                 msleep(1);
350         }
351         return rc;
352 }
353
354 static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
355                          loff_t *offset)
356 {
357         struct scom_device *scom = filep->private_data;
358         struct device *dev = &scom->fsi_dev->dev;
359         uint64_t val;
360         int rc;
361
362         if (len != sizeof(uint64_t))
363                 return -EINVAL;
364
365         mutex_lock(&scom->lock);
366         if (scom->dead)
367                 rc = -ENODEV;
368         else
369                 rc = get_scom(scom, &val, *offset);
370         mutex_unlock(&scom->lock);
371         if (rc) {
372                 dev_dbg(dev, "get_scom fail:%d\n", rc);
373                 return rc;
374         }
375
376         rc = copy_to_user(buf, &val, len);
377         if (rc)
378                 dev_dbg(dev, "copy to user failed:%d\n", rc);
379
380         return rc ? rc : len;
381 }
382
383 static ssize_t scom_write(struct file *filep, const char __user *buf,
384                           size_t len, loff_t *offset)
385 {
386         int rc;
387         struct scom_device *scom = filep->private_data;
388         struct device *dev = &scom->fsi_dev->dev;
389         uint64_t val;
390
391         if (len != sizeof(uint64_t))
392                 return -EINVAL;
393
394         rc = copy_from_user(&val, buf, len);
395         if (rc) {
396                 dev_dbg(dev, "copy from user failed:%d\n", rc);
397                 return -EINVAL;
398         }
399
400         mutex_lock(&scom->lock);
401         if (scom->dead)
402                 rc = -ENODEV;
403         else
404                 rc = put_scom(scom, val, *offset);
405         mutex_unlock(&scom->lock);
406         if (rc) {
407                 dev_dbg(dev, "put_scom failed with:%d\n", rc);
408                 return rc;
409         }
410
411         return len;
412 }
413
414 static loff_t scom_llseek(struct file *file, loff_t offset, int whence)
415 {
416         switch (whence) {
417         case SEEK_CUR:
418                 break;
419         case SEEK_SET:
420                 file->f_pos = offset;
421                 break;
422         default:
423                 return -EINVAL;
424         }
425
426         return offset;
427 }
428
429 static void raw_convert_status(struct scom_access *acc, uint32_t status)
430 {
431         acc->pib_status = (status & SCOM_STATUS_PIB_RESP_MASK) >>
432                 SCOM_STATUS_PIB_RESP_SHIFT;
433         acc->intf_errors = 0;
434
435         if (status & SCOM_STATUS_PROTECTION)
436                 acc->intf_errors |= SCOM_INTF_ERR_PROTECTION;
437         else if (status & SCOM_STATUS_PARITY)
438                 acc->intf_errors |= SCOM_INTF_ERR_PARITY;
439         else if (status & SCOM_STATUS_PIB_ABORT)
440                 acc->intf_errors |= SCOM_INTF_ERR_ABORT;
441         else if (status & SCOM_STATUS_ERR_SUMMARY)
442                 acc->intf_errors |= SCOM_INTF_ERR_UNKNOWN;
443 }
444
445 static int scom_raw_read(struct scom_device *scom, void __user *argp)
446 {
447         struct scom_access acc;
448         uint32_t status;
449         int rc;
450
451         if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
452                 return -EFAULT;
453
454         rc = raw_get_scom(scom, &acc.data, acc.addr, &status);
455         if (rc)
456                 return rc;
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_raw_write(struct scom_device *scom, void __user *argp)
464 {
465         u64 prev_data, mask, data;
466         struct scom_access acc;
467         uint32_t status;
468         int rc;
469
470         if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
471                 return -EFAULT;
472
473         if (acc.mask) {
474                 rc = raw_get_scom(scom, &prev_data, acc.addr, &status);
475                 if (rc)
476                         return rc;
477                 if (status & SCOM_STATUS_ANY_ERR)
478                         goto fail;
479                 mask = acc.mask;
480         } else {
481                 prev_data = mask = -1ull;
482         }
483         data = (prev_data & ~mask) | (acc.data & mask);
484         rc = raw_put_scom(scom, data, acc.addr, &status);
485         if (rc)
486                 return rc;
487  fail:
488         raw_convert_status(&acc, status);
489         if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
490                 return -EFAULT;
491         return 0;
492 }
493
494 static int scom_reset(struct scom_device *scom, void __user *argp)
495 {
496         uint32_t flags, dummy = -1;
497         int rc = 0;
498
499         if (get_user(flags, (__u32 __user *)argp))
500                 return -EFAULT;
501         if (flags & SCOM_RESET_PIB)
502                 rc = fsi_device_write(scom->fsi_dev, SCOM_PIB_RESET_REG, &dummy,
503                                       sizeof(uint32_t));
504         if (!rc && (flags & (SCOM_RESET_PIB | SCOM_RESET_INTF)))
505                 rc = fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
506                                       sizeof(uint32_t));
507         return rc;
508 }
509
510 static int scom_check(struct scom_device *scom, void __user *argp)
511 {
512         /* Still need to find out how to get "protected" */
513         return put_user(SCOM_CHECK_SUPPORTED, (__u32 __user *)argp);
514 }
515
516 static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
517 {
518         struct scom_device *scom = file->private_data;
519         void __user *argp = (void __user *)arg;
520         int rc = -ENOTTY;
521
522         mutex_lock(&scom->lock);
523         if (scom->dead) {
524                 mutex_unlock(&scom->lock);
525                 return -ENODEV;
526         }
527         switch(cmd) {
528         case FSI_SCOM_CHECK:
529                 rc = scom_check(scom, argp);
530                 break;
531         case FSI_SCOM_READ:
532                 rc = scom_raw_read(scom, argp);
533                 break;
534         case FSI_SCOM_WRITE:
535                 rc = scom_raw_write(scom, argp);
536                 break;
537         case FSI_SCOM_RESET:
538                 rc = scom_reset(scom, argp);
539                 break;
540         }
541         mutex_unlock(&scom->lock);
542         return rc;
543 }
544
545 static int scom_open(struct inode *inode, struct file *file)
546 {
547         struct scom_device *scom = container_of(inode->i_cdev, struct scom_device, cdev);
548
549         file->private_data = scom;
550
551         return 0;
552 }
553
554 static const struct file_operations scom_fops = {
555         .owner          = THIS_MODULE,
556         .open           = scom_open,
557         .llseek         = scom_llseek,
558         .read           = scom_read,
559         .write          = scom_write,
560         .unlocked_ioctl = scom_ioctl,
561 };
562
563 static void scom_free(struct device *dev)
564 {
565         struct scom_device *scom = container_of(dev, struct scom_device, dev);
566
567         put_device(&scom->fsi_dev->dev);
568         kfree(scom);
569 }
570
571 static int scom_probe(struct device *dev)
572 {
573         struct fsi_device *fsi_dev = to_fsi_dev(dev);
574         struct scom_device *scom;
575         int rc, didx;
576
577         scom = kzalloc(sizeof(*scom), GFP_KERNEL);
578         if (!scom)
579                 return -ENOMEM;
580         dev_set_drvdata(dev, scom);
581         mutex_init(&scom->lock);
582
583         /* Grab a reference to the device (parent of our cdev), we'll drop it later */
584         if (!get_device(dev)) {
585                 kfree(scom);
586                 return -ENODEV;
587         }
588         scom->fsi_dev = fsi_dev;
589
590         /* Create chardev for userspace access */
591         scom->dev.type = &fsi_cdev_type;
592         scom->dev.parent = dev;
593         scom->dev.release = scom_free;
594         device_initialize(&scom->dev);
595
596         /* Allocate a minor in the FSI space */
597         rc = fsi_get_new_minor(fsi_dev, fsi_dev_scom, &scom->dev.devt, &didx);
598         if (rc)
599                 goto err;
600
601         dev_set_name(&scom->dev, "scom%d", didx);
602         cdev_init(&scom->cdev, &scom_fops);
603         rc = cdev_device_add(&scom->cdev, &scom->dev);
604         if (rc) {
605                 dev_err(dev, "Error %d creating char device %s\n",
606                         rc, dev_name(&scom->dev));
607                 goto err_free_minor;
608         }
609
610         return 0;
611  err_free_minor:
612         fsi_free_minor(scom->dev.devt);
613  err:
614         put_device(&scom->dev);
615         return rc;
616 }
617
618 static int scom_remove(struct device *dev)
619 {
620         struct scom_device *scom = dev_get_drvdata(dev);
621
622         mutex_lock(&scom->lock);
623         scom->dead = true;
624         mutex_unlock(&scom->lock);
625         cdev_device_del(&scom->cdev, &scom->dev);
626         fsi_free_minor(scom->dev.devt);
627         put_device(&scom->dev);
628
629         return 0;
630 }
631
632 static const struct fsi_device_id scom_ids[] = {
633         {
634                 .engine_type = FSI_ENGID_SCOM,
635                 .version = FSI_VERSION_ANY,
636         },
637         { 0 }
638 };
639
640 static struct fsi_driver scom_drv = {
641         .id_table = scom_ids,
642         .drv = {
643                 .name = "scom",
644                 .bus = &fsi_bus_type,
645                 .probe = scom_probe,
646                 .remove = scom_remove,
647         }
648 };
649
650 static int scom_init(void)
651 {
652         return fsi_driver_register(&scom_drv);
653 }
654
655 static void scom_exit(void)
656 {
657         fsi_driver_unregister(&scom_drv);
658 }
659
660 module_init(scom_init);
661 module_exit(scom_exit);
662 MODULE_LICENSE("GPL");