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