brintos

brintos / linux-shallow public Read only

0
0
Text · 22.2 KiB · e20cee9 Raw
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