Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/firmware/stratix10-rsu.c
26378 views
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/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 0xFF
34
#define INVALID_DCMF_VERSION 0xFF
35
#define INVALID_DCMF_STATUS 0xFFFFFFFF
36
#define INVALID_SPT_ADDRESS 0x0
37
38
#define RSU_GET_SPT_CMD 0x5A
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
* @get_spt_response_buf: response from sdm for get_spt command
68
*/
69
struct 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 Layer
108
* @client: pointer to service client
109
* @data: pointer to callback data structure
110
*
111
* Callback from Intel service layer for RSU status request. Status is
112
* only updated after a system reboot, so a get updated status call is
113
* made during driver probe.
114
*/
115
static 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 Layer
147
* @client: pointer to client
148
* @data: pointer to callback data structure
149
*
150
* Callback from Intel service layer for RSU commands.
151
*/
152
static 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 getting
168
* the current image's retry counter from the firmware
169
* @client: pointer to client
170
* @data: pointer to callback data structure
171
*
172
* Callback from Intel service layer for retry counter, which is used by
173
* user to know how many times the images is still allowed to reload
174
* itself before giving up and starting RSU fail-over flow.
175
*/
176
static 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
else
187
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 getting
195
* the max retry value from the firmware
196
* @client: pointer to client
197
* @data: pointer to callback data structure
198
*
199
* Callback from Intel service layer for max retry.
200
*/
201
static 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
else
212
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 getting
220
* the DCMF version
221
* @client: pointer to client
222
* @data: pointer to callback data structure
223
*
224
* Callback from Intel service layer for DCMF version number
225
*/
226
static 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
} else
239
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 getting
246
* the DCMF status
247
* @client: pointer to client
248
* @data: pointer to callback data structure
249
*
250
* Callback from Intel service layer for DCMF status
251
*/
252
static 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
} else
268
dev_err(client->dev, "failed to get DCMF status\n");
269
270
complete(&priv->completion);
271
}
272
273
static 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
294
error:
295
dev_err(client->dev, "failed to get SPTs\n");
296
297
complete:
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 layer
305
* @priv: pointer to rsu private data
306
* @command: RSU status or update command
307
* @arg: the request argument, the bitstream address or notify status
308
* @callback: function pointer for the callback (status or update)
309
*
310
* Start an Intel service layer transaction to perform the SMC call that
311
* is necessary to get RSU boot log or set the address of bitstream to
312
* boot after reboot.
313
*
314
* Returns 0 on success or -ETIMEDOUT on error.
315
*/
316
static 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
359
status_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 system
369
* status and to request optional reboot behavior specific to Intel FPGAs.
370
*/
371
372
static 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
383
static 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
394
static 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
405
static 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
416
static 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
427
static 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
438
static 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
449
static 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
461
static 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
472
static 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
483
static 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
494
static 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
505
static 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
519
static 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
533
static 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
547
static 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
}
560
static 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
585
static 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
624
static 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
638
static 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
652
static DEVICE_ATTR_RO(current_image);
653
static DEVICE_ATTR_RO(fail_image);
654
static DEVICE_ATTR_RO(state);
655
static DEVICE_ATTR_RO(version);
656
static DEVICE_ATTR_RO(error_location);
657
static DEVICE_ATTR_RO(error_details);
658
static DEVICE_ATTR_RO(retry_counter);
659
static DEVICE_ATTR_RO(max_retry);
660
static DEVICE_ATTR_RO(dcmf0);
661
static DEVICE_ATTR_RO(dcmf1);
662
static DEVICE_ATTR_RO(dcmf2);
663
static DEVICE_ATTR_RO(dcmf3);
664
static DEVICE_ATTR_RO(dcmf0_status);
665
static DEVICE_ATTR_RO(dcmf1_status);
666
static DEVICE_ATTR_RO(dcmf2_status);
667
static DEVICE_ATTR_RO(dcmf3_status);
668
static DEVICE_ATTR_WO(reboot_image);
669
static DEVICE_ATTR_WO(notify);
670
static DEVICE_ATTR_RO(spt0_address);
671
static DEVICE_ATTR_RO(spt1_address);
672
673
static 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
NULL
695
};
696
697
ATTRIBUTE_GROUPS(rsu);
698
699
static 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
796
static 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
803
static struct platform_driver stratix10_rsu_driver = {
804
.probe = stratix10_rsu_probe,
805
.remove = stratix10_rsu_remove,
806
.driver = {
807
.name = "stratix10-rsu",
808
.dev_groups = rsu_groups,
809
},
810
};
811
812
module_platform_driver(stratix10_rsu_driver);
813
814
MODULE_LICENSE("GPL v2");
815
MODULE_DESCRIPTION("Intel Remote System Update Driver");
816
MODULE_AUTHOR("Richard Gong <[email protected]>");
817
818