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"); 629