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