Linux 4.19.133
[linux/fpc-iii.git] / drivers / fsi / fsi-scom.c
blobfdc0e458dbaaf9c2b59488e6b1a4d7102926657a
1 /*
2 * SCOM FSI Client device driver
4 * Copyright (C) IBM Corporation 2016
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERGCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <linux/fsi.h>
17 #include <linux/module.h>
18 #include <linux/cdev.h>
19 #include <linux/delay.h>
20 #include <linux/fs.h>
21 #include <linux/uaccess.h>
22 #include <linux/slab.h>
23 #include <linux/cdev.h>
24 #include <linux/list.h>
26 #include <uapi/linux/fsi.h>
28 #define FSI_ENGID_SCOM 0x5
30 /* SCOM engine register set */
31 #define SCOM_DATA0_REG 0x00
32 #define SCOM_DATA1_REG 0x04
33 #define SCOM_CMD_REG 0x08
34 #define SCOM_FSI2PIB_RESET_REG 0x18
35 #define SCOM_STATUS_REG 0x1C /* Read */
36 #define SCOM_PIB_RESET_REG 0x1C /* Write */
38 /* Command register */
39 #define SCOM_WRITE_CMD 0x80000000
40 #define SCOM_READ_CMD 0x00000000
42 /* Status register bits */
43 #define SCOM_STATUS_ERR_SUMMARY 0x80000000
44 #define SCOM_STATUS_PROTECTION 0x01000000
45 #define SCOM_STATUS_PARITY 0x04000000
46 #define SCOM_STATUS_PIB_ABORT 0x00100000
47 #define SCOM_STATUS_PIB_RESP_MASK 0x00007000
48 #define SCOM_STATUS_PIB_RESP_SHIFT 12
50 #define SCOM_STATUS_ANY_ERR (SCOM_STATUS_PROTECTION | \
51 SCOM_STATUS_PARITY | \
52 SCOM_STATUS_PIB_ABORT | \
53 SCOM_STATUS_PIB_RESP_MASK)
54 /* SCOM address encodings */
55 #define XSCOM_ADDR_IND_FLAG BIT_ULL(63)
56 #define XSCOM_ADDR_INF_FORM1 BIT_ULL(60)
58 /* SCOM indirect stuff */
59 #define XSCOM_ADDR_DIRECT_PART 0x7fffffffull
60 #define XSCOM_ADDR_INDIRECT_PART 0x000fffff00000000ull
61 #define XSCOM_DATA_IND_READ BIT_ULL(63)
62 #define XSCOM_DATA_IND_COMPLETE BIT_ULL(31)
63 #define XSCOM_DATA_IND_ERR_MASK 0x70000000ull
64 #define XSCOM_DATA_IND_ERR_SHIFT 28
65 #define XSCOM_DATA_IND_DATA 0x0000ffffull
66 #define XSCOM_DATA_IND_FORM1_DATA 0x000fffffffffffffull
67 #define XSCOM_ADDR_FORM1_LOW 0x000ffffffffull
68 #define XSCOM_ADDR_FORM1_HI 0xfff00000000ull
69 #define XSCOM_ADDR_FORM1_HI_SHIFT 20
71 /* Retries */
72 #define SCOM_MAX_RETRIES 100 /* Retries on busy */
73 #define SCOM_MAX_IND_RETRIES 10 /* Retries indirect not ready */
75 struct scom_device {
76 struct list_head link;
77 struct fsi_device *fsi_dev;
78 struct device dev;
79 struct cdev cdev;
80 struct mutex lock;
81 bool dead;
84 static int __put_scom(struct scom_device *scom_dev, uint64_t value,
85 uint32_t addr, uint32_t *status)
87 __be32 data, raw_status;
88 int rc;
90 data = cpu_to_be32((value >> 32) & 0xffffffff);
91 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_DATA0_REG, &data,
92 sizeof(uint32_t));
93 if (rc)
94 return rc;
96 data = cpu_to_be32(value & 0xffffffff);
97 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_DATA1_REG, &data,
98 sizeof(uint32_t));
99 if (rc)
100 return rc;
102 data = cpu_to_be32(SCOM_WRITE_CMD | addr);
103 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_CMD_REG, &data,
104 sizeof(uint32_t));
105 if (rc)
106 return rc;
107 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_STATUS_REG, &raw_status,
108 sizeof(uint32_t));
109 if (rc)
110 return rc;
111 *status = be32_to_cpu(raw_status);
113 return 0;
116 static int __get_scom(struct scom_device *scom_dev, uint64_t *value,
117 uint32_t addr, uint32_t *status)
119 __be32 data, raw_status;
120 int rc;
123 *value = 0ULL;
124 data = cpu_to_be32(SCOM_READ_CMD | addr);
125 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_CMD_REG, &data,
126 sizeof(uint32_t));
127 if (rc)
128 return rc;
129 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_STATUS_REG, &raw_status,
130 sizeof(uint32_t));
131 if (rc)
132 return rc;
135 * Read the data registers even on error, so we don't have
136 * to interpret the status register here.
138 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_DATA0_REG, &data,
139 sizeof(uint32_t));
140 if (rc)
141 return rc;
142 *value |= (uint64_t)be32_to_cpu(data) << 32;
143 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_DATA1_REG, &data,
144 sizeof(uint32_t));
145 if (rc)
146 return rc;
147 *value |= be32_to_cpu(data);
148 *status = be32_to_cpu(raw_status);
150 return rc;
153 static int put_indirect_scom_form0(struct scom_device *scom, uint64_t value,
154 uint64_t addr, uint32_t *status)
156 uint64_t ind_data, ind_addr;
157 int rc, retries, err = 0;
159 if (value & ~XSCOM_DATA_IND_DATA)
160 return -EINVAL;
162 ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
163 ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | value;
164 rc = __put_scom(scom, ind_data, ind_addr, status);
165 if (rc || (*status & SCOM_STATUS_ANY_ERR))
166 return rc;
168 for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
169 rc = __get_scom(scom, &ind_data, addr, status);
170 if (rc || (*status & SCOM_STATUS_ANY_ERR))
171 return rc;
173 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
174 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
175 if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
176 return 0;
178 msleep(1);
180 return rc;
183 static int put_indirect_scom_form1(struct scom_device *scom, uint64_t value,
184 uint64_t addr, uint32_t *status)
186 uint64_t ind_data, ind_addr;
188 if (value & ~XSCOM_DATA_IND_FORM1_DATA)
189 return -EINVAL;
191 ind_addr = addr & XSCOM_ADDR_FORM1_LOW;
192 ind_data = value | (addr & XSCOM_ADDR_FORM1_HI) << XSCOM_ADDR_FORM1_HI_SHIFT;
193 return __put_scom(scom, ind_data, ind_addr, status);
196 static int get_indirect_scom_form0(struct scom_device *scom, uint64_t *value,
197 uint64_t addr, uint32_t *status)
199 uint64_t ind_data, ind_addr;
200 int rc, retries, err = 0;
202 ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
203 ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | XSCOM_DATA_IND_READ;
204 rc = __put_scom(scom, ind_data, ind_addr, status);
205 if (rc || (*status & SCOM_STATUS_ANY_ERR))
206 return rc;
208 for (retries = 0; retries < SCOM_MAX_IND_RETRIES; retries++) {
209 rc = __get_scom(scom, &ind_data, addr, status);
210 if (rc || (*status & SCOM_STATUS_ANY_ERR))
211 return rc;
213 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
214 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
215 *value = ind_data & XSCOM_DATA_IND_DATA;
217 if ((ind_data & XSCOM_DATA_IND_COMPLETE) || (err != SCOM_PIB_BLOCKED))
218 return 0;
220 msleep(1);
222 return rc;
225 static int raw_put_scom(struct scom_device *scom, uint64_t value,
226 uint64_t addr, uint32_t *status)
228 if (addr & XSCOM_ADDR_IND_FLAG) {
229 if (addr & XSCOM_ADDR_INF_FORM1)
230 return put_indirect_scom_form1(scom, value, addr, status);
231 else
232 return put_indirect_scom_form0(scom, value, addr, status);
233 } else
234 return __put_scom(scom, value, addr, status);
237 static int raw_get_scom(struct scom_device *scom, uint64_t *value,
238 uint64_t addr, uint32_t *status)
240 if (addr & XSCOM_ADDR_IND_FLAG) {
241 if (addr & XSCOM_ADDR_INF_FORM1)
242 return -ENXIO;
243 return get_indirect_scom_form0(scom, value, addr, status);
244 } else
245 return __get_scom(scom, value, addr, status);
248 static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status)
250 uint32_t dummy = -1;
252 if (status & SCOM_STATUS_PROTECTION)
253 return -EPERM;
254 if (status & SCOM_STATUS_PARITY) {
255 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
256 sizeof(uint32_t));
257 return -EIO;
259 /* Return -EBUSY on PIB abort to force a retry */
260 if (status & SCOM_STATUS_PIB_ABORT)
261 return -EBUSY;
262 return 0;
265 static int handle_pib_status(struct scom_device *scom, uint8_t status)
267 uint32_t dummy = -1;
269 if (status == SCOM_PIB_SUCCESS)
270 return 0;
271 if (status == SCOM_PIB_BLOCKED)
272 return -EBUSY;
274 /* Reset the bridge */
275 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
276 sizeof(uint32_t));
278 switch(status) {
279 case SCOM_PIB_OFFLINE:
280 return -ENODEV;
281 case SCOM_PIB_BAD_ADDR:
282 return -ENXIO;
283 case SCOM_PIB_TIMEOUT:
284 return -ETIMEDOUT;
285 case SCOM_PIB_PARTIAL:
286 case SCOM_PIB_CLK_ERR:
287 case SCOM_PIB_PARITY_ERR:
288 default:
289 return -EIO;
293 static int put_scom(struct scom_device *scom, uint64_t value,
294 uint64_t addr)
296 uint32_t status, dummy = -1;
297 int rc, retries;
299 for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) {
300 rc = raw_put_scom(scom, value, addr, &status);
301 if (rc) {
302 /* Try resetting the bridge if FSI fails */
303 if (rc != -ENODEV && retries == 0) {
304 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG,
305 &dummy, sizeof(uint32_t));
306 rc = -EBUSY;
307 } else
308 return rc;
309 } else
310 rc = handle_fsi2pib_status(scom, status);
311 if (rc && rc != -EBUSY)
312 break;
313 if (rc == 0) {
314 rc = handle_pib_status(scom,
315 (status & SCOM_STATUS_PIB_RESP_MASK)
316 >> SCOM_STATUS_PIB_RESP_SHIFT);
317 if (rc && rc != -EBUSY)
318 break;
320 if (rc == 0)
321 break;
322 msleep(1);
324 return rc;
327 static int get_scom(struct scom_device *scom, uint64_t *value,
328 uint64_t addr)
330 uint32_t status, dummy = -1;
331 int rc, retries;
333 for (retries = 0; retries < SCOM_MAX_RETRIES; retries++) {
334 rc = raw_get_scom(scom, value, addr, &status);
335 if (rc) {
336 /* Try resetting the bridge if FSI fails */
337 if (rc != -ENODEV && retries == 0) {
338 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG,
339 &dummy, sizeof(uint32_t));
340 rc = -EBUSY;
341 } else
342 return rc;
343 } else
344 rc = handle_fsi2pib_status(scom, status);
345 if (rc && rc != -EBUSY)
346 break;
347 if (rc == 0) {
348 rc = handle_pib_status(scom,
349 (status & SCOM_STATUS_PIB_RESP_MASK)
350 >> SCOM_STATUS_PIB_RESP_SHIFT);
351 if (rc && rc != -EBUSY)
352 break;
354 if (rc == 0)
355 break;
356 msleep(1);
358 return rc;
361 static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
362 loff_t *offset)
364 struct scom_device *scom = filep->private_data;
365 struct device *dev = &scom->fsi_dev->dev;
366 uint64_t val;
367 int rc;
369 if (len != sizeof(uint64_t))
370 return -EINVAL;
372 mutex_lock(&scom->lock);
373 if (scom->dead)
374 rc = -ENODEV;
375 else
376 rc = get_scom(scom, &val, *offset);
377 mutex_unlock(&scom->lock);
378 if (rc) {
379 dev_dbg(dev, "get_scom fail:%d\n", rc);
380 return rc;
383 rc = copy_to_user(buf, &val, len);
384 if (rc)
385 dev_dbg(dev, "copy to user failed:%d\n", rc);
387 return rc ? rc : len;
390 static ssize_t scom_write(struct file *filep, const char __user *buf,
391 size_t len, loff_t *offset)
393 int rc;
394 struct scom_device *scom = filep->private_data;
395 struct device *dev = &scom->fsi_dev->dev;
396 uint64_t val;
398 if (len != sizeof(uint64_t))
399 return -EINVAL;
401 rc = copy_from_user(&val, buf, len);
402 if (rc) {
403 dev_dbg(dev, "copy from user failed:%d\n", rc);
404 return -EINVAL;
407 mutex_lock(&scom->lock);
408 if (scom->dead)
409 rc = -ENODEV;
410 else
411 rc = put_scom(scom, val, *offset);
412 mutex_unlock(&scom->lock);
413 if (rc) {
414 dev_dbg(dev, "put_scom failed with:%d\n", rc);
415 return rc;
418 return len;
421 static loff_t scom_llseek(struct file *file, loff_t offset, int whence)
423 switch (whence) {
424 case SEEK_CUR:
425 break;
426 case SEEK_SET:
427 file->f_pos = offset;
428 break;
429 default:
430 return -EINVAL;
433 return offset;
436 static void raw_convert_status(struct scom_access *acc, uint32_t status)
438 acc->pib_status = (status & SCOM_STATUS_PIB_RESP_MASK) >>
439 SCOM_STATUS_PIB_RESP_SHIFT;
440 acc->intf_errors = 0;
442 if (status & SCOM_STATUS_PROTECTION)
443 acc->intf_errors |= SCOM_INTF_ERR_PROTECTION;
444 else if (status & SCOM_STATUS_PARITY)
445 acc->intf_errors |= SCOM_INTF_ERR_PARITY;
446 else if (status & SCOM_STATUS_PIB_ABORT)
447 acc->intf_errors |= SCOM_INTF_ERR_ABORT;
448 else if (status & SCOM_STATUS_ERR_SUMMARY)
449 acc->intf_errors |= SCOM_INTF_ERR_UNKNOWN;
452 static int scom_raw_read(struct scom_device *scom, void __user *argp)
454 struct scom_access acc;
455 uint32_t status;
456 int rc;
458 if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
459 return -EFAULT;
461 rc = raw_get_scom(scom, &acc.data, acc.addr, &status);
462 if (rc)
463 return rc;
464 raw_convert_status(&acc, status);
465 if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
466 return -EFAULT;
467 return 0;
470 static int scom_raw_write(struct scom_device *scom, void __user *argp)
472 u64 prev_data, mask, data;
473 struct scom_access acc;
474 uint32_t status;
475 int rc;
477 if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
478 return -EFAULT;
480 if (acc.mask) {
481 rc = raw_get_scom(scom, &prev_data, acc.addr, &status);
482 if (rc)
483 return rc;
484 if (status & SCOM_STATUS_ANY_ERR)
485 goto fail;
486 mask = acc.mask;
487 } else {
488 prev_data = mask = -1ull;
490 data = (prev_data & ~mask) | (acc.data & mask);
491 rc = raw_put_scom(scom, data, acc.addr, &status);
492 if (rc)
493 return rc;
494 fail:
495 raw_convert_status(&acc, status);
496 if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
497 return -EFAULT;
498 return 0;
501 static int scom_reset(struct scom_device *scom, void __user *argp)
503 uint32_t flags, dummy = -1;
504 int rc = 0;
506 if (get_user(flags, (__u32 __user *)argp))
507 return -EFAULT;
508 if (flags & SCOM_RESET_PIB)
509 rc = fsi_device_write(scom->fsi_dev, SCOM_PIB_RESET_REG, &dummy,
510 sizeof(uint32_t));
511 if (!rc && (flags & (SCOM_RESET_PIB | SCOM_RESET_INTF)))
512 rc = fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
513 sizeof(uint32_t));
514 return rc;
517 static int scom_check(struct scom_device *scom, void __user *argp)
519 /* Still need to find out how to get "protected" */
520 return put_user(SCOM_CHECK_SUPPORTED, (__u32 __user *)argp);
523 static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
525 struct scom_device *scom = file->private_data;
526 void __user *argp = (void __user *)arg;
527 int rc = -ENOTTY;
529 mutex_lock(&scom->lock);
530 if (scom->dead) {
531 mutex_unlock(&scom->lock);
532 return -ENODEV;
534 switch(cmd) {
535 case FSI_SCOM_CHECK:
536 rc = scom_check(scom, argp);
537 break;
538 case FSI_SCOM_READ:
539 rc = scom_raw_read(scom, argp);
540 break;
541 case FSI_SCOM_WRITE:
542 rc = scom_raw_write(scom, argp);
543 break;
544 case FSI_SCOM_RESET:
545 rc = scom_reset(scom, argp);
546 break;
548 mutex_unlock(&scom->lock);
549 return rc;
552 static int scom_open(struct inode *inode, struct file *file)
554 struct scom_device *scom = container_of(inode->i_cdev, struct scom_device, cdev);
556 file->private_data = scom;
558 return 0;
561 static const struct file_operations scom_fops = {
562 .owner = THIS_MODULE,
563 .open = scom_open,
564 .llseek = scom_llseek,
565 .read = scom_read,
566 .write = scom_write,
567 .unlocked_ioctl = scom_ioctl,
570 static void scom_free(struct device *dev)
572 struct scom_device *scom = container_of(dev, struct scom_device, dev);
574 put_device(&scom->fsi_dev->dev);
575 kfree(scom);
578 static int scom_probe(struct device *dev)
580 struct fsi_device *fsi_dev = to_fsi_dev(dev);
581 struct scom_device *scom;
582 int rc, didx;
584 scom = kzalloc(sizeof(*scom), GFP_KERNEL);
585 if (!scom)
586 return -ENOMEM;
587 dev_set_drvdata(dev, scom);
588 mutex_init(&scom->lock);
590 /* Grab a reference to the device (parent of our cdev), we'll drop it later */
591 if (!get_device(dev)) {
592 kfree(scom);
593 return -ENODEV;
595 scom->fsi_dev = fsi_dev;
597 /* Create chardev for userspace access */
598 scom->dev.type = &fsi_cdev_type;
599 scom->dev.parent = dev;
600 scom->dev.release = scom_free;
601 device_initialize(&scom->dev);
603 /* Allocate a minor in the FSI space */
604 rc = fsi_get_new_minor(fsi_dev, fsi_dev_scom, &scom->dev.devt, &didx);
605 if (rc)
606 goto err;
608 dev_set_name(&scom->dev, "scom%d", didx);
609 cdev_init(&scom->cdev, &scom_fops);
610 rc = cdev_device_add(&scom->cdev, &scom->dev);
611 if (rc) {
612 dev_err(dev, "Error %d creating char device %s\n",
613 rc, dev_name(&scom->dev));
614 goto err_free_minor;
617 return 0;
618 err_free_minor:
619 fsi_free_minor(scom->dev.devt);
620 err:
621 put_device(&scom->dev);
622 return rc;
625 static int scom_remove(struct device *dev)
627 struct scom_device *scom = dev_get_drvdata(dev);
629 mutex_lock(&scom->lock);
630 scom->dead = true;
631 mutex_unlock(&scom->lock);
632 cdev_device_del(&scom->cdev, &scom->dev);
633 fsi_free_minor(scom->dev.devt);
634 put_device(&scom->dev);
636 return 0;
639 static struct fsi_device_id scom_ids[] = {
641 .engine_type = FSI_ENGID_SCOM,
642 .version = FSI_VERSION_ANY,
644 { 0 }
647 static struct fsi_driver scom_drv = {
648 .id_table = scom_ids,
649 .drv = {
650 .name = "scom",
651 .bus = &fsi_bus_type,
652 .probe = scom_probe,
653 .remove = scom_remove,
657 static int scom_init(void)
659 return fsi_driver_register(&scom_drv);
662 static void scom_exit(void)
664 fsi_driver_unregister(&scom_drv);
667 module_init(scom_init);
668 module_exit(scom_exit);
669 MODULE_LICENSE("GPL");