0001
0002
0003
0004
0005
0006 #include <linux/arm-smccc.h>
0007 #include <linux/bitfield.h>
0008 #include <linux/completion.h>
0009 #include <linux/kobject.h>
0010 #include <linux/module.h>
0011 #include <linux/mutex.h>
0012 #include <linux/of.h>
0013 #include <linux/of_platform.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/firmware/intel/stratix10-svc-client.h>
0016 #include <linux/string.h>
0017 #include <linux/sysfs.h>
0018
0019 #define RSU_STATE_MASK GENMASK_ULL(31, 0)
0020 #define RSU_VERSION_MASK GENMASK_ULL(63, 32)
0021 #define RSU_ERROR_LOCATION_MASK GENMASK_ULL(31, 0)
0022 #define RSU_ERROR_DETAIL_MASK GENMASK_ULL(63, 32)
0023 #define RSU_DCMF0_MASK GENMASK_ULL(31, 0)
0024 #define RSU_DCMF1_MASK GENMASK_ULL(63, 32)
0025 #define RSU_DCMF2_MASK GENMASK_ULL(31, 0)
0026 #define RSU_DCMF3_MASK GENMASK_ULL(63, 32)
0027 #define RSU_DCMF0_STATUS_MASK GENMASK_ULL(15, 0)
0028 #define RSU_DCMF1_STATUS_MASK GENMASK_ULL(31, 16)
0029 #define RSU_DCMF2_STATUS_MASK GENMASK_ULL(47, 32)
0030 #define RSU_DCMF3_STATUS_MASK GENMASK_ULL(63, 48)
0031
0032 #define RSU_TIMEOUT (msecs_to_jiffies(SVC_RSU_REQUEST_TIMEOUT_MS))
0033
0034 #define INVALID_RETRY_COUNTER 0xFF
0035 #define INVALID_DCMF_VERSION 0xFF
0036 #define INVALID_DCMF_STATUS 0xFFFFFFFF
0037
0038 typedef void (*rsu_callback)(struct stratix10_svc_client *client,
0039 struct stratix10_svc_cb_data *data);
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 struct stratix10_rsu_priv {
0064 struct stratix10_svc_chan *chan;
0065 struct stratix10_svc_client client;
0066 struct completion completion;
0067 struct mutex lock;
0068 struct {
0069 unsigned long current_image;
0070 unsigned long fail_image;
0071 unsigned int version;
0072 unsigned int state;
0073 unsigned int error_details;
0074 unsigned int error_location;
0075 } status;
0076
0077 struct {
0078 unsigned int dcmf0;
0079 unsigned int dcmf1;
0080 unsigned int dcmf2;
0081 unsigned int dcmf3;
0082 } dcmf_version;
0083
0084 struct {
0085 unsigned int dcmf0;
0086 unsigned int dcmf1;
0087 unsigned int dcmf2;
0088 unsigned int dcmf3;
0089 } dcmf_status;
0090
0091 unsigned int retry_counter;
0092 unsigned int max_retry;
0093 };
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104 static void rsu_status_callback(struct stratix10_svc_client *client,
0105 struct stratix10_svc_cb_data *data)
0106 {
0107 struct stratix10_rsu_priv *priv = client->priv;
0108 struct arm_smccc_res *res = (struct arm_smccc_res *)data->kaddr1;
0109
0110 if (data->status == BIT(SVC_STATUS_OK)) {
0111 priv->status.version = FIELD_GET(RSU_VERSION_MASK,
0112 res->a2);
0113 priv->status.state = FIELD_GET(RSU_STATE_MASK, res->a2);
0114 priv->status.fail_image = res->a1;
0115 priv->status.current_image = res->a0;
0116 priv->status.error_location =
0117 FIELD_GET(RSU_ERROR_LOCATION_MASK, res->a3);
0118 priv->status.error_details =
0119 FIELD_GET(RSU_ERROR_DETAIL_MASK, res->a3);
0120 } else {
0121 dev_err(client->dev, "COMMAND_RSU_STATUS returned 0x%lX\n",
0122 res->a0);
0123 priv->status.version = 0;
0124 priv->status.state = 0;
0125 priv->status.fail_image = 0;
0126 priv->status.current_image = 0;
0127 priv->status.error_location = 0;
0128 priv->status.error_details = 0;
0129 }
0130
0131 complete(&priv->completion);
0132 }
0133
0134
0135
0136
0137
0138
0139
0140
0141 static void rsu_command_callback(struct stratix10_svc_client *client,
0142 struct stratix10_svc_cb_data *data)
0143 {
0144 struct stratix10_rsu_priv *priv = client->priv;
0145
0146 if (data->status == BIT(SVC_STATUS_NO_SUPPORT))
0147 dev_warn(client->dev, "Secure FW doesn't support notify\n");
0148 else if (data->status == BIT(SVC_STATUS_ERROR))
0149 dev_err(client->dev, "Failure, returned status is %lu\n",
0150 BIT(data->status));
0151
0152 complete(&priv->completion);
0153 }
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 static void rsu_retry_callback(struct stratix10_svc_client *client,
0166 struct stratix10_svc_cb_data *data)
0167 {
0168 struct stratix10_rsu_priv *priv = client->priv;
0169 unsigned int *counter = (unsigned int *)data->kaddr1;
0170
0171 if (data->status == BIT(SVC_STATUS_OK))
0172 priv->retry_counter = *counter;
0173 else if (data->status == BIT(SVC_STATUS_NO_SUPPORT))
0174 dev_warn(client->dev, "Secure FW doesn't support retry\n");
0175 else
0176 dev_err(client->dev, "Failed to get retry counter %lu\n",
0177 BIT(data->status));
0178
0179 complete(&priv->completion);
0180 }
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190 static void rsu_max_retry_callback(struct stratix10_svc_client *client,
0191 struct stratix10_svc_cb_data *data)
0192 {
0193 struct stratix10_rsu_priv *priv = client->priv;
0194 unsigned int *max_retry = (unsigned int *)data->kaddr1;
0195
0196 if (data->status == BIT(SVC_STATUS_OK))
0197 priv->max_retry = *max_retry;
0198 else if (data->status == BIT(SVC_STATUS_NO_SUPPORT))
0199 dev_warn(client->dev, "Secure FW doesn't support max retry\n");
0200 else
0201 dev_err(client->dev, "Failed to get max retry %lu\n",
0202 BIT(data->status));
0203
0204 complete(&priv->completion);
0205 }
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 static void rsu_dcmf_version_callback(struct stratix10_svc_client *client,
0216 struct stratix10_svc_cb_data *data)
0217 {
0218 struct stratix10_rsu_priv *priv = client->priv;
0219 unsigned long long *value1 = (unsigned long long *)data->kaddr1;
0220 unsigned long long *value2 = (unsigned long long *)data->kaddr2;
0221
0222 if (data->status == BIT(SVC_STATUS_OK)) {
0223 priv->dcmf_version.dcmf0 = FIELD_GET(RSU_DCMF0_MASK, *value1);
0224 priv->dcmf_version.dcmf1 = FIELD_GET(RSU_DCMF1_MASK, *value1);
0225 priv->dcmf_version.dcmf2 = FIELD_GET(RSU_DCMF2_MASK, *value2);
0226 priv->dcmf_version.dcmf3 = FIELD_GET(RSU_DCMF3_MASK, *value2);
0227 } else
0228 dev_err(client->dev, "failed to get DCMF version\n");
0229
0230 complete(&priv->completion);
0231 }
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241 static void rsu_dcmf_status_callback(struct stratix10_svc_client *client,
0242 struct stratix10_svc_cb_data *data)
0243 {
0244 struct stratix10_rsu_priv *priv = client->priv;
0245 unsigned long long *value = (unsigned long long *)data->kaddr1;
0246
0247 if (data->status == BIT(SVC_STATUS_OK)) {
0248 priv->dcmf_status.dcmf0 = FIELD_GET(RSU_DCMF0_STATUS_MASK,
0249 *value);
0250 priv->dcmf_status.dcmf1 = FIELD_GET(RSU_DCMF1_STATUS_MASK,
0251 *value);
0252 priv->dcmf_status.dcmf2 = FIELD_GET(RSU_DCMF2_STATUS_MASK,
0253 *value);
0254 priv->dcmf_status.dcmf3 = FIELD_GET(RSU_DCMF3_STATUS_MASK,
0255 *value);
0256 } else
0257 dev_err(client->dev, "failed to get DCMF status\n");
0258
0259 complete(&priv->completion);
0260 }
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275 static int rsu_send_msg(struct stratix10_rsu_priv *priv,
0276 enum stratix10_svc_command_code command,
0277 unsigned long arg,
0278 rsu_callback callback)
0279 {
0280 struct stratix10_svc_client_msg msg;
0281 int ret;
0282
0283 mutex_lock(&priv->lock);
0284 reinit_completion(&priv->completion);
0285 priv->client.receive_cb = callback;
0286
0287 msg.command = command;
0288 if (arg)
0289 msg.arg[0] = arg;
0290
0291 ret = stratix10_svc_send(priv->chan, &msg);
0292 if (ret < 0)
0293 goto status_done;
0294
0295 ret = wait_for_completion_interruptible_timeout(&priv->completion,
0296 RSU_TIMEOUT);
0297 if (!ret) {
0298 dev_err(priv->client.dev,
0299 "timeout waiting for SMC call\n");
0300 ret = -ETIMEDOUT;
0301 goto status_done;
0302 } else if (ret < 0) {
0303 dev_err(priv->client.dev,
0304 "error %d waiting for SMC call\n", ret);
0305 goto status_done;
0306 } else {
0307 ret = 0;
0308 }
0309
0310 status_done:
0311 stratix10_svc_done(priv->chan);
0312 mutex_unlock(&priv->lock);
0313 return ret;
0314 }
0315
0316
0317
0318
0319
0320
0321
0322
0323 static ssize_t current_image_show(struct device *dev,
0324 struct device_attribute *attr, char *buf)
0325 {
0326 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0327
0328 if (!priv)
0329 return -ENODEV;
0330
0331 return sprintf(buf, "0x%08lx\n", priv->status.current_image);
0332 }
0333
0334 static ssize_t fail_image_show(struct device *dev,
0335 struct device_attribute *attr, char *buf)
0336 {
0337 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0338
0339 if (!priv)
0340 return -ENODEV;
0341
0342 return sprintf(buf, "0x%08lx\n", priv->status.fail_image);
0343 }
0344
0345 static ssize_t version_show(struct device *dev, struct device_attribute *attr,
0346 char *buf)
0347 {
0348 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0349
0350 if (!priv)
0351 return -ENODEV;
0352
0353 return sprintf(buf, "0x%08x\n", priv->status.version);
0354 }
0355
0356 static ssize_t state_show(struct device *dev, struct device_attribute *attr,
0357 char *buf)
0358 {
0359 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0360
0361 if (!priv)
0362 return -ENODEV;
0363
0364 return sprintf(buf, "0x%08x\n", priv->status.state);
0365 }
0366
0367 static ssize_t error_location_show(struct device *dev,
0368 struct device_attribute *attr, char *buf)
0369 {
0370 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0371
0372 if (!priv)
0373 return -ENODEV;
0374
0375 return sprintf(buf, "0x%08x\n", priv->status.error_location);
0376 }
0377
0378 static ssize_t error_details_show(struct device *dev,
0379 struct device_attribute *attr, char *buf)
0380 {
0381 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0382
0383 if (!priv)
0384 return -ENODEV;
0385
0386 return sprintf(buf, "0x%08x\n", priv->status.error_details);
0387 }
0388
0389 static ssize_t retry_counter_show(struct device *dev,
0390 struct device_attribute *attr, char *buf)
0391 {
0392 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0393
0394 if (!priv)
0395 return -ENODEV;
0396
0397 return sprintf(buf, "0x%08x\n", priv->retry_counter);
0398 }
0399
0400 static ssize_t max_retry_show(struct device *dev,
0401 struct device_attribute *attr, char *buf)
0402 {
0403 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0404
0405 if (!priv)
0406 return -ENODEV;
0407
0408 return scnprintf(buf, sizeof(priv->max_retry),
0409 "0x%08x\n", priv->max_retry);
0410 }
0411
0412 static ssize_t dcmf0_show(struct device *dev,
0413 struct device_attribute *attr, char *buf)
0414 {
0415 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0416
0417 if (!priv)
0418 return -ENODEV;
0419
0420 return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf0);
0421 }
0422
0423 static ssize_t dcmf1_show(struct device *dev,
0424 struct device_attribute *attr, char *buf)
0425 {
0426 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0427
0428 if (!priv)
0429 return -ENODEV;
0430
0431 return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf1);
0432 }
0433
0434 static ssize_t dcmf2_show(struct device *dev,
0435 struct device_attribute *attr, char *buf)
0436 {
0437 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0438
0439 if (!priv)
0440 return -ENODEV;
0441
0442 return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf2);
0443 }
0444
0445 static ssize_t dcmf3_show(struct device *dev,
0446 struct device_attribute *attr, char *buf)
0447 {
0448 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0449
0450 if (!priv)
0451 return -ENODEV;
0452
0453 return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf3);
0454 }
0455
0456 static ssize_t dcmf0_status_show(struct device *dev,
0457 struct device_attribute *attr, char *buf)
0458 {
0459 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0460
0461 if (!priv)
0462 return -ENODEV;
0463
0464 if (priv->dcmf_status.dcmf0 == INVALID_DCMF_STATUS)
0465 return -EIO;
0466
0467 return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf0);
0468 }
0469
0470 static ssize_t dcmf1_status_show(struct device *dev,
0471 struct device_attribute *attr, char *buf)
0472 {
0473 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0474
0475 if (!priv)
0476 return -ENODEV;
0477
0478 if (priv->dcmf_status.dcmf1 == INVALID_DCMF_STATUS)
0479 return -EIO;
0480
0481 return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf1);
0482 }
0483
0484 static ssize_t dcmf2_status_show(struct device *dev,
0485 struct device_attribute *attr, char *buf)
0486 {
0487 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0488
0489 if (!priv)
0490 return -ENODEV;
0491
0492 if (priv->dcmf_status.dcmf2 == INVALID_DCMF_STATUS)
0493 return -EIO;
0494
0495 return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf2);
0496 }
0497
0498 static ssize_t dcmf3_status_show(struct device *dev,
0499 struct device_attribute *attr, char *buf)
0500 {
0501 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0502
0503 if (!priv)
0504 return -ENODEV;
0505
0506 if (priv->dcmf_status.dcmf3 == INVALID_DCMF_STATUS)
0507 return -EIO;
0508
0509 return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf3);
0510 }
0511 static ssize_t reboot_image_store(struct device *dev,
0512 struct device_attribute *attr,
0513 const char *buf, size_t count)
0514 {
0515 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0516 unsigned long address;
0517 int ret;
0518
0519 if (!priv)
0520 return -ENODEV;
0521
0522 ret = kstrtoul(buf, 0, &address);
0523 if (ret)
0524 return ret;
0525
0526 ret = rsu_send_msg(priv, COMMAND_RSU_UPDATE,
0527 address, rsu_command_callback);
0528 if (ret) {
0529 dev_err(dev, "Error, RSU update returned %i\n", ret);
0530 return ret;
0531 }
0532
0533 return count;
0534 }
0535
0536 static ssize_t notify_store(struct device *dev,
0537 struct device_attribute *attr,
0538 const char *buf, size_t count)
0539 {
0540 struct stratix10_rsu_priv *priv = dev_get_drvdata(dev);
0541 unsigned long status;
0542 int ret;
0543
0544 if (!priv)
0545 return -ENODEV;
0546
0547 ret = kstrtoul(buf, 0, &status);
0548 if (ret)
0549 return ret;
0550
0551 ret = rsu_send_msg(priv, COMMAND_RSU_NOTIFY,
0552 status, rsu_command_callback);
0553 if (ret) {
0554 dev_err(dev, "Error, RSU notify returned %i\n", ret);
0555 return ret;
0556 }
0557
0558
0559 ret = rsu_send_msg(priv, COMMAND_RSU_STATUS,
0560 0, rsu_status_callback);
0561 if (ret) {
0562 dev_err(dev, "Error, getting RSU status %i\n", ret);
0563 return ret;
0564 }
0565
0566 ret = rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback);
0567 if (ret) {
0568 dev_err(dev, "Error, getting RSU retry %i\n", ret);
0569 return ret;
0570 }
0571
0572 return count;
0573 }
0574
0575 static DEVICE_ATTR_RO(current_image);
0576 static DEVICE_ATTR_RO(fail_image);
0577 static DEVICE_ATTR_RO(state);
0578 static DEVICE_ATTR_RO(version);
0579 static DEVICE_ATTR_RO(error_location);
0580 static DEVICE_ATTR_RO(error_details);
0581 static DEVICE_ATTR_RO(retry_counter);
0582 static DEVICE_ATTR_RO(max_retry);
0583 static DEVICE_ATTR_RO(dcmf0);
0584 static DEVICE_ATTR_RO(dcmf1);
0585 static DEVICE_ATTR_RO(dcmf2);
0586 static DEVICE_ATTR_RO(dcmf3);
0587 static DEVICE_ATTR_RO(dcmf0_status);
0588 static DEVICE_ATTR_RO(dcmf1_status);
0589 static DEVICE_ATTR_RO(dcmf2_status);
0590 static DEVICE_ATTR_RO(dcmf3_status);
0591 static DEVICE_ATTR_WO(reboot_image);
0592 static DEVICE_ATTR_WO(notify);
0593
0594 static struct attribute *rsu_attrs[] = {
0595 &dev_attr_current_image.attr,
0596 &dev_attr_fail_image.attr,
0597 &dev_attr_state.attr,
0598 &dev_attr_version.attr,
0599 &dev_attr_error_location.attr,
0600 &dev_attr_error_details.attr,
0601 &dev_attr_retry_counter.attr,
0602 &dev_attr_max_retry.attr,
0603 &dev_attr_dcmf0.attr,
0604 &dev_attr_dcmf1.attr,
0605 &dev_attr_dcmf2.attr,
0606 &dev_attr_dcmf3.attr,
0607 &dev_attr_dcmf0_status.attr,
0608 &dev_attr_dcmf1_status.attr,
0609 &dev_attr_dcmf2_status.attr,
0610 &dev_attr_dcmf3_status.attr,
0611 &dev_attr_reboot_image.attr,
0612 &dev_attr_notify.attr,
0613 NULL
0614 };
0615
0616 ATTRIBUTE_GROUPS(rsu);
0617
0618 static int stratix10_rsu_probe(struct platform_device *pdev)
0619 {
0620 struct device *dev = &pdev->dev;
0621 struct stratix10_rsu_priv *priv;
0622 int ret;
0623
0624 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0625 if (!priv)
0626 return -ENOMEM;
0627
0628 priv->client.dev = dev;
0629 priv->client.receive_cb = NULL;
0630 priv->client.priv = priv;
0631 priv->status.current_image = 0;
0632 priv->status.fail_image = 0;
0633 priv->status.error_location = 0;
0634 priv->status.error_details = 0;
0635 priv->status.version = 0;
0636 priv->status.state = 0;
0637 priv->retry_counter = INVALID_RETRY_COUNTER;
0638 priv->dcmf_version.dcmf0 = INVALID_DCMF_VERSION;
0639 priv->dcmf_version.dcmf1 = INVALID_DCMF_VERSION;
0640 priv->dcmf_version.dcmf2 = INVALID_DCMF_VERSION;
0641 priv->dcmf_version.dcmf3 = INVALID_DCMF_VERSION;
0642 priv->max_retry = INVALID_RETRY_COUNTER;
0643 priv->dcmf_status.dcmf0 = INVALID_DCMF_STATUS;
0644 priv->dcmf_status.dcmf1 = INVALID_DCMF_STATUS;
0645 priv->dcmf_status.dcmf2 = INVALID_DCMF_STATUS;
0646 priv->dcmf_status.dcmf3 = INVALID_DCMF_STATUS;
0647
0648 mutex_init(&priv->lock);
0649 priv->chan = stratix10_svc_request_channel_byname(&priv->client,
0650 SVC_CLIENT_RSU);
0651 if (IS_ERR(priv->chan)) {
0652 dev_err(dev, "couldn't get service channel %s\n",
0653 SVC_CLIENT_RSU);
0654 return PTR_ERR(priv->chan);
0655 }
0656
0657 init_completion(&priv->completion);
0658 platform_set_drvdata(pdev, priv);
0659
0660
0661 ret = rsu_send_msg(priv, COMMAND_RSU_STATUS,
0662 0, rsu_status_callback);
0663 if (ret) {
0664 dev_err(dev, "Error, getting RSU status %i\n", ret);
0665 stratix10_svc_free_channel(priv->chan);
0666 }
0667
0668
0669 ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_VERSION,
0670 0, rsu_dcmf_version_callback);
0671 if (ret) {
0672 dev_err(dev, "Error, getting DCMF version %i\n", ret);
0673 stratix10_svc_free_channel(priv->chan);
0674 }
0675
0676 ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS,
0677 0, rsu_dcmf_status_callback);
0678 if (ret) {
0679 dev_err(dev, "Error, getting DCMF status %i\n", ret);
0680 stratix10_svc_free_channel(priv->chan);
0681 }
0682
0683 ret = rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback);
0684 if (ret) {
0685 dev_err(dev, "Error, getting RSU retry %i\n", ret);
0686 stratix10_svc_free_channel(priv->chan);
0687 }
0688
0689 ret = rsu_send_msg(priv, COMMAND_RSU_MAX_RETRY, 0,
0690 rsu_max_retry_callback);
0691 if (ret) {
0692 dev_err(dev, "Error, getting RSU max retry %i\n", ret);
0693 stratix10_svc_free_channel(priv->chan);
0694 }
0695
0696 return ret;
0697 }
0698
0699 static int stratix10_rsu_remove(struct platform_device *pdev)
0700 {
0701 struct stratix10_rsu_priv *priv = platform_get_drvdata(pdev);
0702
0703 stratix10_svc_free_channel(priv->chan);
0704 return 0;
0705 }
0706
0707 static struct platform_driver stratix10_rsu_driver = {
0708 .probe = stratix10_rsu_probe,
0709 .remove = stratix10_rsu_remove,
0710 .driver = {
0711 .name = "stratix10-rsu",
0712 .dev_groups = rsu_groups,
0713 },
0714 };
0715
0716 module_platform_driver(stratix10_rsu_driver);
0717
0718 MODULE_LICENSE("GPL v2");
0719 MODULE_DESCRIPTION("Intel Remote System Update Driver");
0720 MODULE_AUTHOR("Richard Gong <richard.gong@intel.com>");