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