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 67struct 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 76static 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 108static 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 145static 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 175static 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 188static 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 217static 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 229static 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 240static 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 258static 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 286static 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 320static 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 354static 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 383static 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 414static 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 429static 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 445static 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 463static 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 494static 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 510static 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 516static 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 545static 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 554static 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 563static 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 571static 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 618static 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 632static const struct fsi_device_id scom_ids[] = { 633 { 634 .engine_type = FSI_ENGID_SCOM, 635 .version = FSI_VERSION_ANY, 636 }, 637 { 0 } 638}; 639 640static 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 650static int scom_init(void) 651{ 652 return fsi_driver_register(&scom_drv); 653} 654 655static void scom_exit(void) 656{ 657 fsi_driver_unregister(&scom_drv); 658} 659 660module_init(scom_init); 661module_exit(scom_exit); 662MODULE_LICENSE("GPL"); 663