1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2018-2019, Intel Corporation 4 * Copyright (C) 2025, Altera Corporation 5 */ 6 7 #include <linux/arm-smccc.h> 8 #include <linux/bitfield.h> 9 #include <linux/completion.h> 10 #include <linux/kobject.h> 11 #include <linux/module.h> 12 #include <linux/mutex.h> 13 #include <linux/of.h> 14 #include <linux/platform_device.h> 15 #include <linux/firmware/intel/stratix10-svc-client.h> 16 #include <linux/string.h> 17 #include <linux/sysfs.h> 18 #include <linux/delay.h> 19 20 #define RSU_ERASE_SIZE_MASK GENMASK_ULL(63, 32) 21 #define RSU_DCMF0_MASK GENMASK_ULL(31, 0) 22 #define RSU_DCMF1_MASK GENMASK_ULL(63, 32) 23 #define RSU_DCMF2_MASK GENMASK_ULL(31, 0) 24 #define RSU_DCMF3_MASK GENMASK_ULL(63, 32) 25 #define RSU_DCMF0_STATUS_MASK GENMASK_ULL(15, 0) 26 #define RSU_DCMF1_STATUS_MASK GENMASK_ULL(31, 16) 27 #define RSU_DCMF2_STATUS_MASK GENMASK_ULL(47, 32) 28 #define RSU_DCMF3_STATUS_MASK GENMASK_ULL(63, 48) 29 30 #define RSU_TIMEOUT (msecs_to_jiffies(SVC_RSU_REQUEST_TIMEOUT_MS)) 31 32 #define INVALID_RETRY_COUNTER 0xFF 33 #define INVALID_DCMF_VERSION 0xFF 34 #define INVALID_DCMF_STATUS 0xFFFFFFFF 35 #define INVALID_SPT_ADDRESS 0x0 36 37 #define RSU_RETRY_SLEEP_MS (1U) 38 #define RSU_ASYNC_MSG_RETRY (3U) 39 #define RSU_GET_SPT_RESP_LEN (4 * sizeof(unsigned int)) 40 41 typedef void (*rsu_callback)(struct stratix10_svc_client *client, 42 struct stratix10_svc_cb_data *data); 43 /** 44 * struct stratix10_rsu_priv - rsu data structure 45 * @chan: pointer to the allocated service channel 46 * @client: active service client 47 * @completion: state for callback completion 48 * @lock: a mutex to protect callback completion state 49 * @status.current_image: address of image currently running in flash 50 * @status.fail_image: address of failed image in flash 51 * @status.version: the interface version number of RSU firmware 52 * @status.state: the state of RSU system 53 * @status.error_details: error code 54 * @status.error_location: the error offset inside the image that failed 55 * @dcmf_version.dcmf0: Quartus dcmf0 version 56 * @dcmf_version.dcmf1: Quartus dcmf1 version 57 * @dcmf_version.dcmf2: Quartus dcmf2 version 58 * @dcmf_version.dcmf3: Quartus dcmf3 version 59 * @dcmf_status.dcmf0: dcmf0 status 60 * @dcmf_status.dcmf1: dcmf1 status 61 * @dcmf_status.dcmf2: dcmf2 status 62 * @dcmf_status.dcmf3: dcmf3 status 63 * @retry_counter: the current image's retry counter 64 * @max_retry: the preset max retry value 65 * @spt0_address: address of spt0 66 * @spt1_address: address of spt1 67 */ 68 struct stratix10_rsu_priv { 69 struct stratix10_svc_chan *chan; 70 struct stratix10_svc_client client; 71 struct completion completion; 72 struct mutex lock; 73 struct { 74 unsigned long current_image; 75 unsigned long fail_image; 76 unsigned int version; 77 unsigned int state; 78 unsigned int error_details; 79 unsigned int error_location; 80 } status; 81 82 struct { 83 unsigned int dcmf0; 84 unsigned int dcmf1; 85 unsigned int dcmf2; 86 unsigned int dcmf3; 87 } dcmf_version; 88 89 struct { 90 unsigned int dcmf0; 91 unsigned int dcmf1; 92 unsigned int dcmf2; 93 unsigned int dcmf3; 94 } dcmf_status; 95 96 unsigned int retry_counter; 97 unsigned int max_retry; 98 99 unsigned long spt0_address; 100 unsigned long spt1_address; 101 }; 102 103 typedef void (*rsu_async_callback)(struct device *dev, 104 struct stratix10_rsu_priv *priv, struct stratix10_svc_cb_data *data); 105 106 /** 107 * rsu_async_status_callback() - Status callback from rsu_async_send() 108 * @dev: pointer to device object 109 * @priv: pointer to priv object 110 * @data: pointer to callback data structure 111 * 112 * Callback from rsu_async_send() to get the system rsu error status. 113 */ 114 static void rsu_async_status_callback(struct device *dev, 115 struct stratix10_rsu_priv *priv, 116 struct stratix10_svc_cb_data *data) 117 { 118 struct arm_smccc_1_2_regs *res = (struct arm_smccc_1_2_regs *)data->kaddr1; 119 120 priv->status.current_image = res->a2; 121 priv->status.fail_image = res->a3; 122 priv->status.state = res->a4; 123 priv->status.version = res->a5; 124 priv->status.error_location = res->a7; 125 priv->status.error_details = res->a8; 126 priv->retry_counter = res->a9; 127 } 128 129 /** 130 * rsu_command_callback() - Update callback from Intel Service Layer 131 * @client: pointer to client 132 * @data: pointer to callback data structure 133 * 134 * Callback from Intel service layer for RSU commands. 135 */ 136 static void rsu_command_callback(struct stratix10_svc_client *client, 137 struct stratix10_svc_cb_data *data) 138 { 139 struct stratix10_rsu_priv *priv = client->priv; 140 141 if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) 142 dev_warn(client->dev, "Secure FW doesn't support notify\n"); 143 else if (data->status == BIT(SVC_STATUS_ERROR)) 144 dev_err(client->dev, "Failure, returned status is %lu\n", 145 BIT(data->status)); 146 147 complete(&priv->completion); 148 } 149 150 151 /** 152 * rsu_max_retry_callback() - Callback from Intel service layer for getting 153 * the max retry value from the firmware 154 * @client: pointer to client 155 * @data: pointer to callback data structure 156 * 157 * Callback from Intel service layer for max retry. 158 */ 159 static void rsu_max_retry_callback(struct stratix10_svc_client *client, 160 struct stratix10_svc_cb_data *data) 161 { 162 struct stratix10_rsu_priv *priv = client->priv; 163 unsigned int *max_retry = (unsigned int *)data->kaddr1; 164 165 if (data->status == BIT(SVC_STATUS_OK)) 166 priv->max_retry = *max_retry; 167 else if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) 168 dev_warn(client->dev, "Secure FW doesn't support max retry\n"); 169 else 170 dev_err(client->dev, "Failed to get max retry %lu\n", 171 BIT(data->status)); 172 173 complete(&priv->completion); 174 } 175 176 /** 177 * rsu_dcmf_version_callback() - Callback from Intel service layer for getting 178 * the DCMF version 179 * @client: pointer to client 180 * @data: pointer to callback data structure 181 * 182 * Callback from Intel service layer for DCMF version number 183 */ 184 static void rsu_dcmf_version_callback(struct stratix10_svc_client *client, 185 struct stratix10_svc_cb_data *data) 186 { 187 struct stratix10_rsu_priv *priv = client->priv; 188 unsigned long long *value1 = (unsigned long long *)data->kaddr1; 189 unsigned long long *value2 = (unsigned long long *)data->kaddr2; 190 191 if (data->status == BIT(SVC_STATUS_OK)) { 192 priv->dcmf_version.dcmf0 = FIELD_GET(RSU_DCMF0_MASK, *value1); 193 priv->dcmf_version.dcmf1 = FIELD_GET(RSU_DCMF1_MASK, *value1); 194 priv->dcmf_version.dcmf2 = FIELD_GET(RSU_DCMF2_MASK, *value2); 195 priv->dcmf_version.dcmf3 = FIELD_GET(RSU_DCMF3_MASK, *value2); 196 } else 197 dev_err(client->dev, "failed to get DCMF version\n"); 198 199 complete(&priv->completion); 200 } 201 202 /** 203 * rsu_dcmf_status_callback() - Callback from Intel service layer for getting 204 * the DCMF status 205 * @client: pointer to client 206 * @data: pointer to callback data structure 207 * 208 * Callback from Intel service layer for DCMF status 209 */ 210 static void rsu_dcmf_status_callback(struct stratix10_svc_client *client, 211 struct stratix10_svc_cb_data *data) 212 { 213 struct stratix10_rsu_priv *priv = client->priv; 214 unsigned long long *value = (unsigned long long *)data->kaddr1; 215 216 if (data->status == BIT(SVC_STATUS_OK)) { 217 priv->dcmf_status.dcmf0 = FIELD_GET(RSU_DCMF0_STATUS_MASK, 218 *value); 219 priv->dcmf_status.dcmf1 = FIELD_GET(RSU_DCMF1_STATUS_MASK, 220 *value); 221 priv->dcmf_status.dcmf2 = FIELD_GET(RSU_DCMF2_STATUS_MASK, 222 *value); 223 priv->dcmf_status.dcmf3 = FIELD_GET(RSU_DCMF3_STATUS_MASK, 224 *value); 225 } else 226 dev_err(client->dev, "failed to get DCMF status\n"); 227 228 complete(&priv->completion); 229 } 230 231 /** 232 * rsu_async_get_spt_table_callback() - Callback to be used by the rsu_async_send() 233 * to retrieve the SPT table information. 234 * @dev: pointer to device object 235 * @priv: pointer to priv object 236 * @data: pointer to callback data structure 237 */ 238 static void rsu_async_get_spt_table_callback(struct device *dev, 239 struct stratix10_rsu_priv *priv, 240 struct stratix10_svc_cb_data *data) 241 { 242 priv->spt0_address = *((unsigned long *)data->kaddr1); 243 priv->spt1_address = *((unsigned long *)data->kaddr2); 244 } 245 246 /** 247 * rsu_send_msg() - send a message to Intel service layer 248 * @priv: pointer to rsu private data 249 * @command: RSU status or update command 250 * @arg: the request argument, the bitstream address or notify status 251 * @callback: function pointer for the callback (status or update) 252 * 253 * Start an Intel service layer transaction to perform the SMC call that 254 * is necessary to get RSU boot log or set the address of bitstream to 255 * boot after reboot. 256 * 257 * Returns 0 on success or -ETIMEDOUT on error. 258 */ 259 static int rsu_send_msg(struct stratix10_rsu_priv *priv, 260 enum stratix10_svc_command_code command, 261 unsigned long arg, 262 rsu_callback callback) 263 { 264 struct stratix10_svc_client_msg msg; 265 int ret; 266 267 mutex_lock(&priv->lock); 268 reinit_completion(&priv->completion); 269 priv->client.receive_cb = callback; 270 271 msg.command = command; 272 if (arg) 273 msg.arg[0] = arg; 274 275 ret = stratix10_svc_send(priv->chan, &msg); 276 if (ret < 0) 277 goto status_done; 278 279 ret = wait_for_completion_interruptible_timeout(&priv->completion, 280 RSU_TIMEOUT); 281 if (!ret) { 282 dev_err(priv->client.dev, 283 "timeout waiting for SMC call\n"); 284 ret = -ETIMEDOUT; 285 goto status_done; 286 } else if (ret < 0) { 287 dev_err(priv->client.dev, 288 "error %d waiting for SMC call\n", ret); 289 goto status_done; 290 } else { 291 ret = 0; 292 } 293 294 status_done: 295 stratix10_svc_done(priv->chan); 296 mutex_unlock(&priv->lock); 297 return ret; 298 } 299 300 /** 301 * soc64_async_callback() - Callback from Intel service layer for async requests 302 * @ptr: pointer to the completion object 303 */ 304 static void soc64_async_callback(void *ptr) 305 { 306 if (ptr) 307 complete(ptr); 308 } 309 310 /** 311 * rsu_send_async_msg() - send an async message to Intel service layer 312 * @dev: pointer to device object 313 * @priv: pointer to rsu private data 314 * @command: RSU status or update command 315 * @arg: the request argument, notify status 316 * @callback: function pointer for the callback (status or update) 317 */ 318 static int rsu_send_async_msg(struct device *dev, struct stratix10_rsu_priv *priv, 319 enum stratix10_svc_command_code command, 320 unsigned long arg, 321 rsu_async_callback callback) 322 { 323 struct stratix10_svc_client_msg msg = {0}; 324 struct stratix10_svc_cb_data data = {0}; 325 struct completion completion; 326 int status, index, ret; 327 void *handle = NULL; 328 329 msg.command = command; 330 msg.arg[0] = arg; 331 332 init_completion(&completion); 333 334 for (index = 0; index < RSU_ASYNC_MSG_RETRY; index++) { 335 status = stratix10_svc_async_send(priv->chan, &msg, 336 &handle, soc64_async_callback, 337 &completion); 338 if (status == 0) 339 break; 340 dev_warn(dev, "Failed to send async message\n"); 341 msleep(RSU_RETRY_SLEEP_MS); 342 } 343 344 if (status && !handle) { 345 dev_err(dev, "Failed to send async message\n"); 346 return -ETIMEDOUT; 347 } 348 349 ret = wait_for_completion_io_timeout(&completion, RSU_TIMEOUT); 350 if (ret > 0) 351 dev_dbg(dev, "Received async interrupt\n"); 352 else if (ret == 0) 353 dev_dbg(dev, "Timeout occurred. Trying to poll the response\n"); 354 355 for (index = 0; index < RSU_ASYNC_MSG_RETRY; index++) { 356 status = stratix10_svc_async_poll(priv->chan, handle, &data); 357 if (status == -EAGAIN) { 358 dev_dbg(dev, "Async message is still in progress\n"); 359 } else if (status < 0) { 360 dev_alert(dev, "Failed to poll async message\n"); 361 ret = -ETIMEDOUT; 362 } else if (status == 0) { 363 ret = 0; 364 break; 365 } 366 msleep(RSU_RETRY_SLEEP_MS); 367 } 368 369 if (ret) { 370 dev_err(dev, "Failed to get async response\n"); 371 goto status_done; 372 } 373 374 if (data.status == 0) { 375 ret = 0; 376 if (callback) 377 callback(dev, priv, &data); 378 } else { 379 dev_err(dev, "%s returned 0x%x from SDM\n", __func__, 380 data.status); 381 ret = -EFAULT; 382 } 383 384 status_done: 385 stratix10_svc_async_done(priv->chan, handle); 386 return ret; 387 } 388 389 /* 390 * This driver exposes some optional features of the Intel Stratix 10 SoC FPGA. 391 * The sysfs interfaces exposed here are FPGA Remote System Update (RSU) 392 * related. They allow user space software to query the configuration system 393 * status and to request optional reboot behavior specific to Intel FPGAs. 394 */ 395 396 static ssize_t current_image_show(struct device *dev, 397 struct device_attribute *attr, char *buf) 398 { 399 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 400 401 if (!priv) 402 return -ENODEV; 403 404 return sprintf(buf, "0x%08lx\n", priv->status.current_image); 405 } 406 407 static ssize_t fail_image_show(struct device *dev, 408 struct device_attribute *attr, char *buf) 409 { 410 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 411 412 if (!priv) 413 return -ENODEV; 414 415 return sprintf(buf, "0x%08lx\n", priv->status.fail_image); 416 } 417 418 static ssize_t version_show(struct device *dev, struct device_attribute *attr, 419 char *buf) 420 { 421 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 422 423 if (!priv) 424 return -ENODEV; 425 426 return sprintf(buf, "0x%08x\n", priv->status.version); 427 } 428 429 static ssize_t state_show(struct device *dev, struct device_attribute *attr, 430 char *buf) 431 { 432 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 433 434 if (!priv) 435 return -ENODEV; 436 437 return sprintf(buf, "0x%08x\n", priv->status.state); 438 } 439 440 static ssize_t error_location_show(struct device *dev, 441 struct device_attribute *attr, char *buf) 442 { 443 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 444 445 if (!priv) 446 return -ENODEV; 447 448 return sprintf(buf, "0x%08x\n", priv->status.error_location); 449 } 450 451 static ssize_t error_details_show(struct device *dev, 452 struct device_attribute *attr, char *buf) 453 { 454 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 455 456 if (!priv) 457 return -ENODEV; 458 459 return sprintf(buf, "0x%08x\n", priv->status.error_details); 460 } 461 462 static ssize_t retry_counter_show(struct device *dev, 463 struct device_attribute *attr, char *buf) 464 { 465 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 466 467 if (!priv) 468 return -ENODEV; 469 470 return sprintf(buf, "0x%08x\n", priv->retry_counter); 471 } 472 473 static ssize_t max_retry_show(struct device *dev, 474 struct device_attribute *attr, char *buf) 475 { 476 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 477 478 if (!priv) 479 return -ENODEV; 480 481 return sysfs_emit(buf, "0x%08x\n", priv->max_retry); 482 } 483 484 static ssize_t dcmf0_show(struct device *dev, 485 struct device_attribute *attr, char *buf) 486 { 487 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 488 489 if (!priv) 490 return -ENODEV; 491 492 return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf0); 493 } 494 495 static ssize_t dcmf1_show(struct device *dev, 496 struct device_attribute *attr, char *buf) 497 { 498 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 499 500 if (!priv) 501 return -ENODEV; 502 503 return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf1); 504 } 505 506 static ssize_t dcmf2_show(struct device *dev, 507 struct device_attribute *attr, char *buf) 508 { 509 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 510 511 if (!priv) 512 return -ENODEV; 513 514 return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf2); 515 } 516 517 static ssize_t dcmf3_show(struct device *dev, 518 struct device_attribute *attr, char *buf) 519 { 520 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 521 522 if (!priv) 523 return -ENODEV; 524 525 return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf3); 526 } 527 528 static ssize_t dcmf0_status_show(struct device *dev, 529 struct device_attribute *attr, char *buf) 530 { 531 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 532 533 if (!priv) 534 return -ENODEV; 535 536 if (priv->dcmf_status.dcmf0 == INVALID_DCMF_STATUS) 537 return -EIO; 538 539 return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf0); 540 } 541 542 static ssize_t dcmf1_status_show(struct device *dev, 543 struct device_attribute *attr, char *buf) 544 { 545 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 546 547 if (!priv) 548 return -ENODEV; 549 550 if (priv->dcmf_status.dcmf1 == INVALID_DCMF_STATUS) 551 return -EIO; 552 553 return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf1); 554 } 555 556 static ssize_t dcmf2_status_show(struct device *dev, 557 struct device_attribute *attr, char *buf) 558 { 559 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 560 561 if (!priv) 562 return -ENODEV; 563 564 if (priv->dcmf_status.dcmf2 == INVALID_DCMF_STATUS) 565 return -EIO; 566 567 return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf2); 568 } 569 570 static ssize_t dcmf3_status_show(struct device *dev, 571 struct device_attribute *attr, char *buf) 572 { 573 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 574 575 if (!priv) 576 return -ENODEV; 577 578 if (priv->dcmf_status.dcmf3 == INVALID_DCMF_STATUS) 579 return -EIO; 580 581 return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf3); 582 } 583 static ssize_t reboot_image_store(struct device *dev, 584 struct device_attribute *attr, 585 const char *buf, size_t count) 586 { 587 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 588 unsigned long address; 589 int ret; 590 591 if (!priv) 592 return -ENODEV; 593 594 ret = kstrtoul(buf, 0, &address); 595 if (ret) 596 return ret; 597 598 ret = rsu_send_msg(priv, COMMAND_RSU_UPDATE, 599 address, rsu_command_callback); 600 if (ret) { 601 dev_err(dev, "Error, RSU update returned %i\n", ret); 602 return ret; 603 } 604 605 return count; 606 } 607 608 static ssize_t notify_store(struct device *dev, 609 struct device_attribute *attr, 610 const char *buf, size_t count) 611 { 612 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 613 unsigned long status; 614 int ret; 615 616 if (!priv) 617 return -ENODEV; 618 619 ret = kstrtoul(buf, 0, &status); 620 if (ret) 621 return ret; 622 623 ret = rsu_send_async_msg(dev, priv, COMMAND_RSU_NOTIFY, status, NULL); 624 if (ret) { 625 dev_err(dev, "Error, RSU notify returned %i\n", ret); 626 return ret; 627 } 628 629 /* to get the updated state */ 630 ret = rsu_send_async_msg(dev, priv, COMMAND_RSU_STATUS, 0, 631 rsu_async_status_callback); 632 if (ret) { 633 dev_err(dev, "Error, getting RSU status %i\n", ret); 634 return ret; 635 } 636 637 return count; 638 } 639 640 static ssize_t spt0_address_show(struct device *dev, 641 struct device_attribute *attr, char *buf) 642 { 643 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 644 645 if (!priv) 646 return -ENODEV; 647 648 if (priv->spt0_address == INVALID_SPT_ADDRESS) 649 return -EIO; 650 651 return sysfs_emit(buf, "0x%08lx\n", priv->spt0_address); 652 } 653 654 static ssize_t spt1_address_show(struct device *dev, 655 struct device_attribute *attr, char *buf) 656 { 657 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 658 659 if (!priv) 660 return -ENODEV; 661 662 if (priv->spt1_address == INVALID_SPT_ADDRESS) 663 return -EIO; 664 665 return sysfs_emit(buf, "0x%08lx\n", priv->spt1_address); 666 } 667 668 static DEVICE_ATTR_RO(current_image); 669 static DEVICE_ATTR_RO(fail_image); 670 static DEVICE_ATTR_RO(state); 671 static DEVICE_ATTR_RO(version); 672 static DEVICE_ATTR_RO(error_location); 673 static DEVICE_ATTR_RO(error_details); 674 static DEVICE_ATTR_RO(retry_counter); 675 static DEVICE_ATTR_RO(max_retry); 676 static DEVICE_ATTR_RO(dcmf0); 677 static DEVICE_ATTR_RO(dcmf1); 678 static DEVICE_ATTR_RO(dcmf2); 679 static DEVICE_ATTR_RO(dcmf3); 680 static DEVICE_ATTR_RO(dcmf0_status); 681 static DEVICE_ATTR_RO(dcmf1_status); 682 static DEVICE_ATTR_RO(dcmf2_status); 683 static DEVICE_ATTR_RO(dcmf3_status); 684 static DEVICE_ATTR_WO(reboot_image); 685 static DEVICE_ATTR_WO(notify); 686 static DEVICE_ATTR_RO(spt0_address); 687 static DEVICE_ATTR_RO(spt1_address); 688 689 static struct attribute *rsu_attrs[] = { 690 &dev_attr_current_image.attr, 691 &dev_attr_fail_image.attr, 692 &dev_attr_state.attr, 693 &dev_attr_version.attr, 694 &dev_attr_error_location.attr, 695 &dev_attr_error_details.attr, 696 &dev_attr_retry_counter.attr, 697 &dev_attr_max_retry.attr, 698 &dev_attr_dcmf0.attr, 699 &dev_attr_dcmf1.attr, 700 &dev_attr_dcmf2.attr, 701 &dev_attr_dcmf3.attr, 702 &dev_attr_dcmf0_status.attr, 703 &dev_attr_dcmf1_status.attr, 704 &dev_attr_dcmf2_status.attr, 705 &dev_attr_dcmf3_status.attr, 706 &dev_attr_reboot_image.attr, 707 &dev_attr_notify.attr, 708 &dev_attr_spt0_address.attr, 709 &dev_attr_spt1_address.attr, 710 NULL 711 }; 712 713 ATTRIBUTE_GROUPS(rsu); 714 715 static int stratix10_rsu_probe(struct platform_device *pdev) 716 { 717 struct device *dev = &pdev->dev; 718 struct stratix10_rsu_priv *priv; 719 int ret; 720 721 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 722 if (!priv) 723 return -ENOMEM; 724 725 priv->client.dev = dev; 726 priv->client.receive_cb = NULL; 727 priv->client.priv = priv; 728 priv->status.current_image = 0; 729 priv->status.fail_image = 0; 730 priv->status.error_location = 0; 731 priv->status.error_details = 0; 732 priv->status.version = 0; 733 priv->status.state = 0; 734 priv->retry_counter = INVALID_RETRY_COUNTER; 735 priv->dcmf_version.dcmf0 = INVALID_DCMF_VERSION; 736 priv->dcmf_version.dcmf1 = INVALID_DCMF_VERSION; 737 priv->dcmf_version.dcmf2 = INVALID_DCMF_VERSION; 738 priv->dcmf_version.dcmf3 = INVALID_DCMF_VERSION; 739 priv->dcmf_status.dcmf0 = INVALID_DCMF_STATUS; 740 priv->dcmf_status.dcmf1 = INVALID_DCMF_STATUS; 741 priv->dcmf_status.dcmf2 = INVALID_DCMF_STATUS; 742 priv->dcmf_status.dcmf3 = INVALID_DCMF_STATUS; 743 priv->max_retry = INVALID_RETRY_COUNTER; 744 priv->spt0_address = INVALID_SPT_ADDRESS; 745 priv->spt1_address = INVALID_SPT_ADDRESS; 746 747 mutex_init(&priv->lock); 748 priv->chan = stratix10_svc_request_channel_byname(&priv->client, 749 SVC_CLIENT_RSU); 750 if (IS_ERR(priv->chan)) { 751 dev_err(dev, "couldn't get service channel %s\n", 752 SVC_CLIENT_RSU); 753 return PTR_ERR(priv->chan); 754 } 755 756 ret = stratix10_svc_add_async_client(priv->chan, false); 757 if (ret) { 758 dev_err(dev, "failed to add async client\n"); 759 stratix10_svc_free_channel(priv->chan); 760 return ret; 761 } 762 763 init_completion(&priv->completion); 764 platform_set_drvdata(pdev, priv); 765 766 /* get the initial state from firmware */ 767 ret = rsu_send_async_msg(dev, priv, COMMAND_RSU_STATUS, 0, 768 rsu_async_status_callback); 769 if (ret) { 770 dev_err(dev, "Error, getting RSU status %i\n", ret); 771 stratix10_svc_free_channel(priv->chan); 772 } 773 774 /* get DCMF version from firmware */ 775 ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_VERSION, 776 0, rsu_dcmf_version_callback); 777 if (ret) { 778 dev_err(dev, "Error, getting DCMF version %i\n", ret); 779 stratix10_svc_free_channel(priv->chan); 780 } 781 782 ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS, 783 0, rsu_dcmf_status_callback); 784 if (ret) { 785 dev_err(dev, "Error, getting DCMF status %i\n", ret); 786 stratix10_svc_free_channel(priv->chan); 787 } 788 789 ret = rsu_send_msg(priv, COMMAND_RSU_MAX_RETRY, 0, 790 rsu_max_retry_callback); 791 if (ret) { 792 dev_err(dev, "Error, getting RSU max retry %i\n", ret); 793 stratix10_svc_free_channel(priv->chan); 794 } 795 796 797 ret = rsu_send_async_msg(dev, priv, COMMAND_RSU_GET_SPT_TABLE, 0, 798 rsu_async_get_spt_table_callback); 799 if (ret) { 800 dev_err(dev, "Error, getting SPT table %i\n", ret); 801 stratix10_svc_free_channel(priv->chan); 802 } 803 804 return ret; 805 } 806 807 static void stratix10_rsu_remove(struct platform_device *pdev) 808 { 809 struct stratix10_rsu_priv *priv = platform_get_drvdata(pdev); 810 811 stratix10_svc_free_channel(priv->chan); 812 } 813 814 static struct platform_driver stratix10_rsu_driver = { 815 .probe = stratix10_rsu_probe, 816 .remove = stratix10_rsu_remove, 817 .driver = { 818 .name = "stratix10-rsu", 819 .dev_groups = rsu_groups, 820 }, 821 }; 822 823 module_platform_driver(stratix10_rsu_driver); 824 825 MODULE_LICENSE("GPL v2"); 826 MODULE_DESCRIPTION("Intel Remote System Update Driver"); 827 MODULE_AUTHOR("Richard Gong <richard.gong@intel.com>"); 828