0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/fsi.h>
0009 #include <linux/module.h>
0010 #include <linux/cdev.h>
0011 #include <linux/delay.h>
0012 #include <linux/fs.h>
0013 #include <linux/uaccess.h>
0014 #include <linux/slab.h>
0015 #include <linux/list.h>
0016
0017 #include <uapi/linux/fsi.h>
0018
0019 #define FSI_ENGID_SCOM 0x5
0020
0021
0022 #define SCOM_DATA0_REG 0x00
0023 #define SCOM_DATA1_REG 0x04
0024 #define SCOM_CMD_REG 0x08
0025 #define SCOM_FSI2PIB_RESET_REG 0x18
0026 #define SCOM_STATUS_REG 0x1C
0027 #define SCOM_PIB_RESET_REG 0x1C
0028
0029
0030 #define SCOM_WRITE_CMD 0x80000000
0031 #define SCOM_READ_CMD 0x00000000
0032
0033
0034 #define SCOM_STATUS_ERR_SUMMARY 0x80000000
0035 #define SCOM_STATUS_PROTECTION 0x01000000
0036 #define SCOM_STATUS_PARITY 0x04000000
0037 #define SCOM_STATUS_PIB_ABORT 0x00100000
0038 #define SCOM_STATUS_PIB_RESP_MASK 0x00007000
0039 #define SCOM_STATUS_PIB_RESP_SHIFT 12
0040
0041 #define SCOM_STATUS_FSI2PIB_ERROR (SCOM_STATUS_PROTECTION | \
0042 SCOM_STATUS_PARITY | \
0043 SCOM_STATUS_PIB_ABORT)
0044 #define SCOM_STATUS_ANY_ERR (SCOM_STATUS_FSI2PIB_ERROR | \
0045 SCOM_STATUS_PIB_RESP_MASK)
0046
0047 #define XSCOM_ADDR_IND_FLAG BIT_ULL(63)
0048 #define XSCOM_ADDR_INF_FORM1 BIT_ULL(60)
0049
0050
0051 #define XSCOM_ADDR_DIRECT_PART 0x7fffffffull
0052 #define XSCOM_ADDR_INDIRECT_PART 0x000fffff00000000ull
0053 #define XSCOM_DATA_IND_READ BIT_ULL(63)
0054 #define XSCOM_DATA_IND_COMPLETE BIT_ULL(31)
0055 #define XSCOM_DATA_IND_ERR_MASK 0x70000000ull
0056 #define XSCOM_DATA_IND_ERR_SHIFT 28
0057 #define XSCOM_DATA_IND_DATA 0x0000ffffull
0058 #define XSCOM_DATA_IND_FORM1_DATA 0x000fffffffffffffull
0059 #define XSCOM_ADDR_FORM1_LOW 0x000ffffffffull
0060 #define XSCOM_ADDR_FORM1_HI 0xfff00000000ull
0061 #define XSCOM_ADDR_FORM1_HI_SHIFT 20
0062
0063
0064 #define SCOM_MAX_IND_RETRIES 10
0065
0066 struct scom_device {
0067 struct list_head link;
0068 struct fsi_device *fsi_dev;
0069 struct device dev;
0070 struct cdev cdev;
0071 struct mutex lock;
0072 bool dead;
0073 };
0074
0075 static int __put_scom(struct scom_device *scom_dev, uint64_t value,
0076 uint32_t addr, uint32_t *status)
0077 {
0078 __be32 data, raw_status;
0079 int rc;
0080
0081 data = cpu_to_be32((value >> 32) & 0xffffffff);
0082 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_DATA0_REG, &data,
0083 sizeof(uint32_t));
0084 if (rc)
0085 return rc;
0086
0087 data = cpu_to_be32(value & 0xffffffff);
0088 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_DATA1_REG, &data,
0089 sizeof(uint32_t));
0090 if (rc)
0091 return rc;
0092
0093 data = cpu_to_be32(SCOM_WRITE_CMD | addr);
0094 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_CMD_REG, &data,
0095 sizeof(uint32_t));
0096 if (rc)
0097 return rc;
0098 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_STATUS_REG, &raw_status,
0099 sizeof(uint32_t));
0100 if (rc)
0101 return rc;
0102 *status = be32_to_cpu(raw_status);
0103
0104 return 0;
0105 }
0106
0107 static int __get_scom(struct scom_device *scom_dev, uint64_t *value,
0108 uint32_t addr, uint32_t *status)
0109 {
0110 __be32 data, raw_status;
0111 int rc;
0112
0113
0114 *value = 0ULL;
0115 data = cpu_to_be32(SCOM_READ_CMD | addr);
0116 rc = fsi_device_write(scom_dev->fsi_dev, SCOM_CMD_REG, &data,
0117 sizeof(uint32_t));
0118 if (rc)
0119 return rc;
0120 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_STATUS_REG, &raw_status,
0121 sizeof(uint32_t));
0122 if (rc)
0123 return rc;
0124
0125
0126
0127
0128
0129 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_DATA0_REG, &data,
0130 sizeof(uint32_t));
0131 if (rc)
0132 return rc;
0133 *value |= (uint64_t)be32_to_cpu(data) << 32;
0134 rc = fsi_device_read(scom_dev->fsi_dev, SCOM_DATA1_REG, &data,
0135 sizeof(uint32_t));
0136 if (rc)
0137 return rc;
0138 *value |= be32_to_cpu(data);
0139 *status = be32_to_cpu(raw_status);
0140
0141 return rc;
0142 }
0143
0144 static int put_indirect_scom_form0(struct scom_device *scom, uint64_t value,
0145 uint64_t addr, uint32_t *status)
0146 {
0147 uint64_t ind_data, ind_addr;
0148 int rc, err;
0149
0150 if (value & ~XSCOM_DATA_IND_DATA)
0151 return -EINVAL;
0152
0153 ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
0154 ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | value;
0155 rc = __put_scom(scom, ind_data, ind_addr, status);
0156 if (rc || (*status & SCOM_STATUS_ANY_ERR))
0157 return rc;
0158
0159 rc = __get_scom(scom, &ind_data, addr, status);
0160 if (rc || (*status & SCOM_STATUS_ANY_ERR))
0161 return rc;
0162
0163 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
0164 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
0165
0166 return 0;
0167 }
0168
0169 static int put_indirect_scom_form1(struct scom_device *scom, uint64_t value,
0170 uint64_t addr, uint32_t *status)
0171 {
0172 uint64_t ind_data, ind_addr;
0173
0174 if (value & ~XSCOM_DATA_IND_FORM1_DATA)
0175 return -EINVAL;
0176
0177 ind_addr = addr & XSCOM_ADDR_FORM1_LOW;
0178 ind_data = value | (addr & XSCOM_ADDR_FORM1_HI) << XSCOM_ADDR_FORM1_HI_SHIFT;
0179 return __put_scom(scom, ind_data, ind_addr, status);
0180 }
0181
0182 static int get_indirect_scom_form0(struct scom_device *scom, uint64_t *value,
0183 uint64_t addr, uint32_t *status)
0184 {
0185 uint64_t ind_data, ind_addr;
0186 int rc, err;
0187
0188 ind_addr = addr & XSCOM_ADDR_DIRECT_PART;
0189 ind_data = (addr & XSCOM_ADDR_INDIRECT_PART) | XSCOM_DATA_IND_READ;
0190 rc = __put_scom(scom, ind_data, ind_addr, status);
0191 if (rc || (*status & SCOM_STATUS_ANY_ERR))
0192 return rc;
0193
0194 rc = __get_scom(scom, &ind_data, addr, status);
0195 if (rc || (*status & SCOM_STATUS_ANY_ERR))
0196 return rc;
0197
0198 err = (ind_data & XSCOM_DATA_IND_ERR_MASK) >> XSCOM_DATA_IND_ERR_SHIFT;
0199 *status = err << SCOM_STATUS_PIB_RESP_SHIFT;
0200 *value = ind_data & XSCOM_DATA_IND_DATA;
0201
0202 return 0;
0203 }
0204
0205 static int raw_put_scom(struct scom_device *scom, uint64_t value,
0206 uint64_t addr, uint32_t *status)
0207 {
0208 if (addr & XSCOM_ADDR_IND_FLAG) {
0209 if (addr & XSCOM_ADDR_INF_FORM1)
0210 return put_indirect_scom_form1(scom, value, addr, status);
0211 else
0212 return put_indirect_scom_form0(scom, value, addr, status);
0213 } else
0214 return __put_scom(scom, value, addr, status);
0215 }
0216
0217 static int raw_get_scom(struct scom_device *scom, uint64_t *value,
0218 uint64_t addr, uint32_t *status)
0219 {
0220 if (addr & XSCOM_ADDR_IND_FLAG) {
0221 if (addr & XSCOM_ADDR_INF_FORM1)
0222 return -ENXIO;
0223 return get_indirect_scom_form0(scom, value, addr, status);
0224 } else
0225 return __get_scom(scom, value, addr, status);
0226 }
0227
0228 static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status)
0229 {
0230 uint32_t dummy = -1;
0231
0232 if (status & SCOM_STATUS_FSI2PIB_ERROR)
0233 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
0234 sizeof(uint32_t));
0235
0236 if (status & SCOM_STATUS_PROTECTION)
0237 return -EPERM;
0238 if (status & SCOM_STATUS_PARITY)
0239 return -EIO;
0240
0241 if (status & SCOM_STATUS_PIB_ABORT)
0242 return -EBUSY;
0243 return 0;
0244 }
0245
0246 static int handle_pib_status(struct scom_device *scom, uint8_t status)
0247 {
0248 uint32_t dummy = -1;
0249
0250 if (status == SCOM_PIB_SUCCESS)
0251 return 0;
0252 if (status == SCOM_PIB_BLOCKED)
0253 return -EBUSY;
0254
0255
0256 fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
0257 sizeof(uint32_t));
0258
0259 switch(status) {
0260 case SCOM_PIB_OFFLINE:
0261 return -ENODEV;
0262 case SCOM_PIB_BAD_ADDR:
0263 return -ENXIO;
0264 case SCOM_PIB_TIMEOUT:
0265 return -ETIMEDOUT;
0266 case SCOM_PIB_PARTIAL:
0267 case SCOM_PIB_CLK_ERR:
0268 case SCOM_PIB_PARITY_ERR:
0269 default:
0270 return -EIO;
0271 }
0272 }
0273
0274 static int put_scom(struct scom_device *scom, uint64_t value,
0275 uint64_t addr)
0276 {
0277 uint32_t status;
0278 int rc;
0279
0280 rc = raw_put_scom(scom, value, addr, &status);
0281 if (rc)
0282 return rc;
0283
0284 rc = handle_fsi2pib_status(scom, status);
0285 if (rc)
0286 return rc;
0287
0288 return handle_pib_status(scom,
0289 (status & SCOM_STATUS_PIB_RESP_MASK)
0290 >> SCOM_STATUS_PIB_RESP_SHIFT);
0291 }
0292
0293 static int get_scom(struct scom_device *scom, uint64_t *value,
0294 uint64_t addr)
0295 {
0296 uint32_t status;
0297 int rc;
0298
0299 rc = raw_get_scom(scom, value, addr, &status);
0300 if (rc)
0301 return rc;
0302
0303 rc = handle_fsi2pib_status(scom, status);
0304 if (rc)
0305 return rc;
0306
0307 return handle_pib_status(scom,
0308 (status & SCOM_STATUS_PIB_RESP_MASK)
0309 >> SCOM_STATUS_PIB_RESP_SHIFT);
0310 }
0311
0312 static ssize_t scom_read(struct file *filep, char __user *buf, size_t len,
0313 loff_t *offset)
0314 {
0315 struct scom_device *scom = filep->private_data;
0316 struct device *dev = &scom->fsi_dev->dev;
0317 uint64_t val;
0318 int rc;
0319
0320 if (len != sizeof(uint64_t))
0321 return -EINVAL;
0322
0323 mutex_lock(&scom->lock);
0324 if (scom->dead)
0325 rc = -ENODEV;
0326 else
0327 rc = get_scom(scom, &val, *offset);
0328 mutex_unlock(&scom->lock);
0329 if (rc) {
0330 dev_dbg(dev, "get_scom fail:%d\n", rc);
0331 return rc;
0332 }
0333
0334 rc = copy_to_user(buf, &val, len);
0335 if (rc)
0336 dev_dbg(dev, "copy to user failed:%d\n", rc);
0337
0338 return rc ? rc : len;
0339 }
0340
0341 static ssize_t scom_write(struct file *filep, const char __user *buf,
0342 size_t len, loff_t *offset)
0343 {
0344 int rc;
0345 struct scom_device *scom = filep->private_data;
0346 struct device *dev = &scom->fsi_dev->dev;
0347 uint64_t val;
0348
0349 if (len != sizeof(uint64_t))
0350 return -EINVAL;
0351
0352 rc = copy_from_user(&val, buf, len);
0353 if (rc) {
0354 dev_dbg(dev, "copy from user failed:%d\n", rc);
0355 return -EINVAL;
0356 }
0357
0358 mutex_lock(&scom->lock);
0359 if (scom->dead)
0360 rc = -ENODEV;
0361 else
0362 rc = put_scom(scom, val, *offset);
0363 mutex_unlock(&scom->lock);
0364 if (rc) {
0365 dev_dbg(dev, "put_scom failed with:%d\n", rc);
0366 return rc;
0367 }
0368
0369 return len;
0370 }
0371
0372 static loff_t scom_llseek(struct file *file, loff_t offset, int whence)
0373 {
0374 switch (whence) {
0375 case SEEK_CUR:
0376 break;
0377 case SEEK_SET:
0378 file->f_pos = offset;
0379 break;
0380 default:
0381 return -EINVAL;
0382 }
0383
0384 return offset;
0385 }
0386
0387 static void raw_convert_status(struct scom_access *acc, uint32_t status)
0388 {
0389 acc->pib_status = (status & SCOM_STATUS_PIB_RESP_MASK) >>
0390 SCOM_STATUS_PIB_RESP_SHIFT;
0391 acc->intf_errors = 0;
0392
0393 if (status & SCOM_STATUS_PROTECTION)
0394 acc->intf_errors |= SCOM_INTF_ERR_PROTECTION;
0395 else if (status & SCOM_STATUS_PARITY)
0396 acc->intf_errors |= SCOM_INTF_ERR_PARITY;
0397 else if (status & SCOM_STATUS_PIB_ABORT)
0398 acc->intf_errors |= SCOM_INTF_ERR_ABORT;
0399 else if (status & SCOM_STATUS_ERR_SUMMARY)
0400 acc->intf_errors |= SCOM_INTF_ERR_UNKNOWN;
0401 }
0402
0403 static int scom_raw_read(struct scom_device *scom, void __user *argp)
0404 {
0405 struct scom_access acc;
0406 uint32_t status;
0407 int rc;
0408
0409 if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
0410 return -EFAULT;
0411
0412 rc = raw_get_scom(scom, &acc.data, acc.addr, &status);
0413 if (rc)
0414 return rc;
0415 raw_convert_status(&acc, status);
0416 if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
0417 return -EFAULT;
0418 return 0;
0419 }
0420
0421 static int scom_raw_write(struct scom_device *scom, void __user *argp)
0422 {
0423 u64 prev_data, mask, data;
0424 struct scom_access acc;
0425 uint32_t status;
0426 int rc;
0427
0428 if (copy_from_user(&acc, argp, sizeof(struct scom_access)))
0429 return -EFAULT;
0430
0431 if (acc.mask) {
0432 rc = raw_get_scom(scom, &prev_data, acc.addr, &status);
0433 if (rc)
0434 return rc;
0435 if (status & SCOM_STATUS_ANY_ERR)
0436 goto fail;
0437 mask = acc.mask;
0438 } else {
0439 prev_data = mask = -1ull;
0440 }
0441 data = (prev_data & ~mask) | (acc.data & mask);
0442 rc = raw_put_scom(scom, data, acc.addr, &status);
0443 if (rc)
0444 return rc;
0445 fail:
0446 raw_convert_status(&acc, status);
0447 if (copy_to_user(argp, &acc, sizeof(struct scom_access)))
0448 return -EFAULT;
0449 return 0;
0450 }
0451
0452 static int scom_reset(struct scom_device *scom, void __user *argp)
0453 {
0454 uint32_t flags, dummy = -1;
0455 int rc = 0;
0456
0457 if (get_user(flags, (__u32 __user *)argp))
0458 return -EFAULT;
0459 if (flags & SCOM_RESET_PIB)
0460 rc = fsi_device_write(scom->fsi_dev, SCOM_PIB_RESET_REG, &dummy,
0461 sizeof(uint32_t));
0462 if (!rc && (flags & (SCOM_RESET_PIB | SCOM_RESET_INTF)))
0463 rc = fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy,
0464 sizeof(uint32_t));
0465 return rc;
0466 }
0467
0468 static int scom_check(struct scom_device *scom, void __user *argp)
0469 {
0470
0471 return put_user(SCOM_CHECK_SUPPORTED, (__u32 __user *)argp);
0472 }
0473
0474 static long scom_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
0475 {
0476 struct scom_device *scom = file->private_data;
0477 void __user *argp = (void __user *)arg;
0478 int rc = -ENOTTY;
0479
0480 mutex_lock(&scom->lock);
0481 if (scom->dead) {
0482 mutex_unlock(&scom->lock);
0483 return -ENODEV;
0484 }
0485 switch(cmd) {
0486 case FSI_SCOM_CHECK:
0487 rc = scom_check(scom, argp);
0488 break;
0489 case FSI_SCOM_READ:
0490 rc = scom_raw_read(scom, argp);
0491 break;
0492 case FSI_SCOM_WRITE:
0493 rc = scom_raw_write(scom, argp);
0494 break;
0495 case FSI_SCOM_RESET:
0496 rc = scom_reset(scom, argp);
0497 break;
0498 }
0499 mutex_unlock(&scom->lock);
0500 return rc;
0501 }
0502
0503 static int scom_open(struct inode *inode, struct file *file)
0504 {
0505 struct scom_device *scom = container_of(inode->i_cdev, struct scom_device, cdev);
0506
0507 file->private_data = scom;
0508
0509 return 0;
0510 }
0511
0512 static const struct file_operations scom_fops = {
0513 .owner = THIS_MODULE,
0514 .open = scom_open,
0515 .llseek = scom_llseek,
0516 .read = scom_read,
0517 .write = scom_write,
0518 .unlocked_ioctl = scom_ioctl,
0519 };
0520
0521 static void scom_free(struct device *dev)
0522 {
0523 struct scom_device *scom = container_of(dev, struct scom_device, dev);
0524
0525 put_device(&scom->fsi_dev->dev);
0526 kfree(scom);
0527 }
0528
0529 static int scom_probe(struct device *dev)
0530 {
0531 struct fsi_device *fsi_dev = to_fsi_dev(dev);
0532 struct scom_device *scom;
0533 int rc, didx;
0534
0535 scom = kzalloc(sizeof(*scom), GFP_KERNEL);
0536 if (!scom)
0537 return -ENOMEM;
0538 dev_set_drvdata(dev, scom);
0539 mutex_init(&scom->lock);
0540
0541
0542 if (!get_device(dev)) {
0543 kfree(scom);
0544 return -ENODEV;
0545 }
0546 scom->fsi_dev = fsi_dev;
0547
0548
0549 scom->dev.type = &fsi_cdev_type;
0550 scom->dev.parent = dev;
0551 scom->dev.release = scom_free;
0552 device_initialize(&scom->dev);
0553
0554
0555 rc = fsi_get_new_minor(fsi_dev, fsi_dev_scom, &scom->dev.devt, &didx);
0556 if (rc)
0557 goto err;
0558
0559 dev_set_name(&scom->dev, "scom%d", didx);
0560 cdev_init(&scom->cdev, &scom_fops);
0561 rc = cdev_device_add(&scom->cdev, &scom->dev);
0562 if (rc) {
0563 dev_err(dev, "Error %d creating char device %s\n",
0564 rc, dev_name(&scom->dev));
0565 goto err_free_minor;
0566 }
0567
0568 return 0;
0569 err_free_minor:
0570 fsi_free_minor(scom->dev.devt);
0571 err:
0572 put_device(&scom->dev);
0573 return rc;
0574 }
0575
0576 static int scom_remove(struct device *dev)
0577 {
0578 struct scom_device *scom = dev_get_drvdata(dev);
0579
0580 mutex_lock(&scom->lock);
0581 scom->dead = true;
0582 mutex_unlock(&scom->lock);
0583 cdev_device_del(&scom->cdev, &scom->dev);
0584 fsi_free_minor(scom->dev.devt);
0585 put_device(&scom->dev);
0586
0587 return 0;
0588 }
0589
0590 static const struct fsi_device_id scom_ids[] = {
0591 {
0592 .engine_type = FSI_ENGID_SCOM,
0593 .version = FSI_VERSION_ANY,
0594 },
0595 { 0 }
0596 };
0597
0598 static struct fsi_driver scom_drv = {
0599 .id_table = scom_ids,
0600 .drv = {
0601 .name = "scom",
0602 .bus = &fsi_bus_type,
0603 .probe = scom_probe,
0604 .remove = scom_remove,
0605 }
0606 };
0607
0608 static int scom_init(void)
0609 {
0610 return fsi_driver_register(&scom_drv);
0611 }
0612
0613 static void scom_exit(void)
0614 {
0615 fsi_driver_unregister(&scom_drv);
0616 }
0617
0618 module_init(scom_init);
0619 module_exit(scom_exit);
0620 MODULE_LICENSE("GPL");