14526ebbcSRichard Gong // SPDX-License-Identifier: GPL-2.0 24526ebbcSRichard Gong /* 34526ebbcSRichard Gong * Copyright (C) 2018-2019, Intel Corporation 44526ebbcSRichard Gong */ 54526ebbcSRichard Gong 64526ebbcSRichard Gong #include <linux/arm-smccc.h> 74526ebbcSRichard Gong #include <linux/bitfield.h> 84526ebbcSRichard Gong #include <linux/completion.h> 94526ebbcSRichard Gong #include <linux/kobject.h> 104526ebbcSRichard Gong #include <linux/module.h> 114526ebbcSRichard Gong #include <linux/mutex.h> 124526ebbcSRichard Gong #include <linux/of.h> 134526ebbcSRichard Gong #include <linux/of_platform.h> 144526ebbcSRichard Gong #include <linux/platform_device.h> 154526ebbcSRichard Gong #include <linux/firmware/intel/stratix10-svc-client.h> 164526ebbcSRichard Gong #include <linux/string.h> 174526ebbcSRichard Gong #include <linux/sysfs.h> 184526ebbcSRichard Gong 194526ebbcSRichard Gong #define RSU_STATE_MASK GENMASK_ULL(31, 0) 204526ebbcSRichard Gong #define RSU_VERSION_MASK GENMASK_ULL(63, 32) 214526ebbcSRichard Gong #define RSU_ERROR_LOCATION_MASK GENMASK_ULL(31, 0) 224526ebbcSRichard Gong #define RSU_ERROR_DETAIL_MASK GENMASK_ULL(63, 32) 234526ebbcSRichard Gong 244526ebbcSRichard Gong #define RSU_TIMEOUT (msecs_to_jiffies(SVC_RSU_REQUEST_TIMEOUT_MS)) 254526ebbcSRichard Gong 264526ebbcSRichard Gong #define INVALID_RETRY_COUNTER 0xFFFFFFFF 274526ebbcSRichard Gong 284526ebbcSRichard Gong typedef void (*rsu_callback)(struct stratix10_svc_client *client, 294526ebbcSRichard Gong struct stratix10_svc_cb_data *data); 304526ebbcSRichard Gong /** 314526ebbcSRichard Gong * struct stratix10_rsu_priv - rsu data structure 324526ebbcSRichard Gong * @chan: pointer to the allocated service channel 334526ebbcSRichard Gong * @client: active service client 344526ebbcSRichard Gong * @completion: state for callback completion 354526ebbcSRichard Gong * @lock: a mutex to protect callback completion state 364526ebbcSRichard Gong * @status.current_image: address of image currently running in flash 374526ebbcSRichard Gong * @status.fail_image: address of failed image in flash 384526ebbcSRichard Gong * @status.version: the version number of RSU firmware 394526ebbcSRichard Gong * @status.state: the state of RSU system 404526ebbcSRichard Gong * @status.error_details: error code 414526ebbcSRichard Gong * @status.error_location: the error offset inside the image that failed 424526ebbcSRichard Gong * @retry_counter: the current image's retry counter 434526ebbcSRichard Gong */ 444526ebbcSRichard Gong struct stratix10_rsu_priv { 454526ebbcSRichard Gong struct stratix10_svc_chan *chan; 464526ebbcSRichard Gong struct stratix10_svc_client client; 474526ebbcSRichard Gong struct completion completion; 484526ebbcSRichard Gong struct mutex lock; 494526ebbcSRichard Gong struct { 504526ebbcSRichard Gong unsigned long current_image; 514526ebbcSRichard Gong unsigned long fail_image; 524526ebbcSRichard Gong unsigned int version; 534526ebbcSRichard Gong unsigned int state; 544526ebbcSRichard Gong unsigned int error_details; 554526ebbcSRichard Gong unsigned int error_location; 564526ebbcSRichard Gong } status; 574526ebbcSRichard Gong unsigned int retry_counter; 584526ebbcSRichard Gong }; 594526ebbcSRichard Gong 604526ebbcSRichard Gong /** 614526ebbcSRichard Gong * rsu_status_callback() - Status callback from Intel Service Layer 624526ebbcSRichard Gong * @client: pointer to service client 634526ebbcSRichard Gong * @data: pointer to callback data structure 644526ebbcSRichard Gong * 654526ebbcSRichard Gong * Callback from Intel service layer for RSU status request. Status is 664526ebbcSRichard Gong * only updated after a system reboot, so a get updated status call is 674526ebbcSRichard Gong * made during driver probe. 684526ebbcSRichard Gong */ 694526ebbcSRichard Gong static void rsu_status_callback(struct stratix10_svc_client *client, 704526ebbcSRichard Gong struct stratix10_svc_cb_data *data) 714526ebbcSRichard Gong { 724526ebbcSRichard Gong struct stratix10_rsu_priv *priv = client->priv; 734526ebbcSRichard Gong struct arm_smccc_res *res = (struct arm_smccc_res *)data->kaddr1; 744526ebbcSRichard Gong 754526ebbcSRichard Gong if (data->status == BIT(SVC_STATUS_RSU_OK)) { 764526ebbcSRichard Gong priv->status.version = FIELD_GET(RSU_VERSION_MASK, 774526ebbcSRichard Gong res->a2); 784526ebbcSRichard Gong priv->status.state = FIELD_GET(RSU_STATE_MASK, res->a2); 794526ebbcSRichard Gong priv->status.fail_image = res->a1; 804526ebbcSRichard Gong priv->status.current_image = res->a0; 814526ebbcSRichard Gong priv->status.error_location = 824526ebbcSRichard Gong FIELD_GET(RSU_ERROR_LOCATION_MASK, res->a3); 834526ebbcSRichard Gong priv->status.error_details = 844526ebbcSRichard Gong FIELD_GET(RSU_ERROR_DETAIL_MASK, res->a3); 854526ebbcSRichard Gong } else { 864526ebbcSRichard Gong dev_err(client->dev, "COMMAND_RSU_STATUS returned 0x%lX\n", 874526ebbcSRichard Gong res->a0); 884526ebbcSRichard Gong priv->status.version = 0; 894526ebbcSRichard Gong priv->status.state = 0; 904526ebbcSRichard Gong priv->status.fail_image = 0; 914526ebbcSRichard Gong priv->status.current_image = 0; 924526ebbcSRichard Gong priv->status.error_location = 0; 934526ebbcSRichard Gong priv->status.error_details = 0; 944526ebbcSRichard Gong } 954526ebbcSRichard Gong 964526ebbcSRichard Gong complete(&priv->completion); 974526ebbcSRichard Gong } 984526ebbcSRichard Gong 994526ebbcSRichard Gong /** 1004526ebbcSRichard Gong * rsu_command_callback() - Update callback from Intel Service Layer 1014526ebbcSRichard Gong * @client: pointer to client 1024526ebbcSRichard Gong * @data: pointer to callback data structure 1034526ebbcSRichard Gong * 1044526ebbcSRichard Gong * Callback from Intel service layer for RSU commands. 1054526ebbcSRichard Gong */ 1064526ebbcSRichard Gong static void rsu_command_callback(struct stratix10_svc_client *client, 1074526ebbcSRichard Gong struct stratix10_svc_cb_data *data) 1084526ebbcSRichard Gong { 1094526ebbcSRichard Gong struct stratix10_rsu_priv *priv = client->priv; 1104526ebbcSRichard Gong 111*e9cb0497SRichard Gong if (data->status == BIT(SVC_STATUS_RSU_NO_SUPPORT)) 112*e9cb0497SRichard Gong dev_warn(client->dev, "Secure FW doesn't support notify\n"); 113*e9cb0497SRichard Gong else if (data->status == BIT(SVC_STATUS_RSU_ERROR)) 114*e9cb0497SRichard Gong dev_err(client->dev, "Failure, returned status is %lu\n", 115*e9cb0497SRichard Gong BIT(data->status)); 116*e9cb0497SRichard Gong 1174526ebbcSRichard Gong complete(&priv->completion); 1184526ebbcSRichard Gong } 1194526ebbcSRichard Gong 1204526ebbcSRichard Gong /** 1214526ebbcSRichard Gong * rsu_retry_callback() - Callback from Intel service layer for getting 1224526ebbcSRichard Gong * the current image's retry counter from firmware 1234526ebbcSRichard Gong * @client: pointer to client 1244526ebbcSRichard Gong * @data: pointer to callback data structure 1254526ebbcSRichard Gong * 1264526ebbcSRichard Gong * Callback from Intel service layer for retry counter, which is used by 1274526ebbcSRichard Gong * user to know how many times the images is still allowed to reload 1284526ebbcSRichard Gong * itself before giving up and starting RSU fail-over flow. 1294526ebbcSRichard Gong */ 1304526ebbcSRichard Gong static void rsu_retry_callback(struct stratix10_svc_client *client, 1314526ebbcSRichard Gong struct stratix10_svc_cb_data *data) 1324526ebbcSRichard Gong { 1334526ebbcSRichard Gong struct stratix10_rsu_priv *priv = client->priv; 1344526ebbcSRichard Gong unsigned int *counter = (unsigned int *)data->kaddr1; 1354526ebbcSRichard Gong 1364526ebbcSRichard Gong if (data->status == BIT(SVC_STATUS_RSU_OK)) 1374526ebbcSRichard Gong priv->retry_counter = *counter; 138*e9cb0497SRichard Gong else if (data->status == BIT(SVC_STATUS_RSU_NO_SUPPORT)) 139*e9cb0497SRichard Gong dev_warn(client->dev, "Secure FW doesn't support retry\n"); 1404526ebbcSRichard Gong else 141*e9cb0497SRichard Gong dev_err(client->dev, "Failed to get retry counter %lu\n", 142*e9cb0497SRichard Gong BIT(data->status)); 1434526ebbcSRichard Gong 1444526ebbcSRichard Gong complete(&priv->completion); 1454526ebbcSRichard Gong } 1464526ebbcSRichard Gong 1474526ebbcSRichard Gong /** 1484526ebbcSRichard Gong * rsu_send_msg() - send a message to Intel service layer 1494526ebbcSRichard Gong * @priv: pointer to rsu private data 1504526ebbcSRichard Gong * @command: RSU status or update command 1514526ebbcSRichard Gong * @arg: the request argument, the bitstream address or notify status 1524526ebbcSRichard Gong * @callback: function pointer for the callback (status or update) 1534526ebbcSRichard Gong * 1544526ebbcSRichard Gong * Start an Intel service layer transaction to perform the SMC call that 1554526ebbcSRichard Gong * is necessary to get RSU boot log or set the address of bitstream to 1564526ebbcSRichard Gong * boot after reboot. 1574526ebbcSRichard Gong * 1584526ebbcSRichard Gong * Returns 0 on success or -ETIMEDOUT on error. 1594526ebbcSRichard Gong */ 1604526ebbcSRichard Gong static int rsu_send_msg(struct stratix10_rsu_priv *priv, 1614526ebbcSRichard Gong enum stratix10_svc_command_code command, 1624526ebbcSRichard Gong unsigned long arg, 1634526ebbcSRichard Gong rsu_callback callback) 1644526ebbcSRichard Gong { 1654526ebbcSRichard Gong struct stratix10_svc_client_msg msg; 1664526ebbcSRichard Gong int ret; 1674526ebbcSRichard Gong 1684526ebbcSRichard Gong mutex_lock(&priv->lock); 1694526ebbcSRichard Gong reinit_completion(&priv->completion); 1704526ebbcSRichard Gong priv->client.receive_cb = callback; 1714526ebbcSRichard Gong 1724526ebbcSRichard Gong msg.command = command; 1734526ebbcSRichard Gong if (arg) 1744526ebbcSRichard Gong msg.arg[0] = arg; 1754526ebbcSRichard Gong 1764526ebbcSRichard Gong ret = stratix10_svc_send(priv->chan, &msg); 1774526ebbcSRichard Gong if (ret < 0) 1784526ebbcSRichard Gong goto status_done; 1794526ebbcSRichard Gong 1804526ebbcSRichard Gong ret = wait_for_completion_interruptible_timeout(&priv->completion, 1814526ebbcSRichard Gong RSU_TIMEOUT); 1824526ebbcSRichard Gong if (!ret) { 1834526ebbcSRichard Gong dev_err(priv->client.dev, 1844526ebbcSRichard Gong "timeout waiting for SMC call\n"); 1854526ebbcSRichard Gong ret = -ETIMEDOUT; 1864526ebbcSRichard Gong goto status_done; 1874526ebbcSRichard Gong } else if (ret < 0) { 1884526ebbcSRichard Gong dev_err(priv->client.dev, 1894526ebbcSRichard Gong "error %d waiting for SMC call\n", ret); 1904526ebbcSRichard Gong goto status_done; 1914526ebbcSRichard Gong } else { 1924526ebbcSRichard Gong ret = 0; 1934526ebbcSRichard Gong } 1944526ebbcSRichard Gong 1954526ebbcSRichard Gong status_done: 1964526ebbcSRichard Gong stratix10_svc_done(priv->chan); 1974526ebbcSRichard Gong mutex_unlock(&priv->lock); 1984526ebbcSRichard Gong return ret; 1994526ebbcSRichard Gong } 2004526ebbcSRichard Gong 2014526ebbcSRichard Gong /* 2024526ebbcSRichard Gong * This driver exposes some optional features of the Intel Stratix 10 SoC FPGA. 2034526ebbcSRichard Gong * The sysfs interfaces exposed here are FPGA Remote System Update (RSU) 2044526ebbcSRichard Gong * related. They allow user space software to query the configuration system 2054526ebbcSRichard Gong * status and to request optional reboot behavior specific to Intel FPGAs. 2064526ebbcSRichard Gong */ 2074526ebbcSRichard Gong 2084526ebbcSRichard Gong static ssize_t current_image_show(struct device *dev, 2094526ebbcSRichard Gong struct device_attribute *attr, char *buf) 2104526ebbcSRichard Gong { 2114526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 2124526ebbcSRichard Gong 2134526ebbcSRichard Gong if (!priv) 2144526ebbcSRichard Gong return -ENODEV; 2154526ebbcSRichard Gong 2164526ebbcSRichard Gong return sprintf(buf, "0x%08lx\n", priv->status.current_image); 2174526ebbcSRichard Gong } 2184526ebbcSRichard Gong 2194526ebbcSRichard Gong static ssize_t fail_image_show(struct device *dev, 2204526ebbcSRichard Gong struct device_attribute *attr, char *buf) 2214526ebbcSRichard Gong { 2224526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 2234526ebbcSRichard Gong 2244526ebbcSRichard Gong if (!priv) 2254526ebbcSRichard Gong return -ENODEV; 2264526ebbcSRichard Gong 2274526ebbcSRichard Gong return sprintf(buf, "0x%08lx\n", priv->status.fail_image); 2284526ebbcSRichard Gong } 2294526ebbcSRichard Gong 2304526ebbcSRichard Gong static ssize_t version_show(struct device *dev, struct device_attribute *attr, 2314526ebbcSRichard Gong char *buf) 2324526ebbcSRichard Gong { 2334526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 2344526ebbcSRichard Gong 2354526ebbcSRichard Gong if (!priv) 2364526ebbcSRichard Gong return -ENODEV; 2374526ebbcSRichard Gong 2384526ebbcSRichard Gong return sprintf(buf, "0x%08x\n", priv->status.version); 2394526ebbcSRichard Gong } 2404526ebbcSRichard Gong 2414526ebbcSRichard Gong static ssize_t state_show(struct device *dev, struct device_attribute *attr, 2424526ebbcSRichard Gong char *buf) 2434526ebbcSRichard Gong { 2444526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 2454526ebbcSRichard Gong 2464526ebbcSRichard Gong if (!priv) 2474526ebbcSRichard Gong return -ENODEV; 2484526ebbcSRichard Gong 2494526ebbcSRichard Gong return sprintf(buf, "0x%08x\n", priv->status.state); 2504526ebbcSRichard Gong } 2514526ebbcSRichard Gong 2524526ebbcSRichard Gong static ssize_t error_location_show(struct device *dev, 2534526ebbcSRichard Gong struct device_attribute *attr, char *buf) 2544526ebbcSRichard Gong { 2554526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 2564526ebbcSRichard Gong 2574526ebbcSRichard Gong if (!priv) 2584526ebbcSRichard Gong return -ENODEV; 2594526ebbcSRichard Gong 2604526ebbcSRichard Gong return sprintf(buf, "0x%08x\n", priv->status.error_location); 2614526ebbcSRichard Gong } 2624526ebbcSRichard Gong 2634526ebbcSRichard Gong static ssize_t error_details_show(struct device *dev, 2644526ebbcSRichard Gong struct device_attribute *attr, char *buf) 2654526ebbcSRichard Gong { 2664526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 2674526ebbcSRichard Gong 2684526ebbcSRichard Gong if (!priv) 2694526ebbcSRichard Gong return -ENODEV; 2704526ebbcSRichard Gong 2714526ebbcSRichard Gong return sprintf(buf, "0x%08x\n", priv->status.error_details); 2724526ebbcSRichard Gong } 2734526ebbcSRichard Gong 2744526ebbcSRichard Gong static ssize_t retry_counter_show(struct device *dev, 2754526ebbcSRichard Gong struct device_attribute *attr, char *buf) 2764526ebbcSRichard Gong { 2774526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 2784526ebbcSRichard Gong 2794526ebbcSRichard Gong if (!priv) 2804526ebbcSRichard Gong return -ENODEV; 2814526ebbcSRichard Gong 2824526ebbcSRichard Gong return sprintf(buf, "0x%08x\n", priv->retry_counter); 2834526ebbcSRichard Gong } 2844526ebbcSRichard Gong 2854526ebbcSRichard Gong static ssize_t reboot_image_store(struct device *dev, 2864526ebbcSRichard Gong struct device_attribute *attr, 2874526ebbcSRichard Gong const char *buf, size_t count) 2884526ebbcSRichard Gong { 2894526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 2904526ebbcSRichard Gong unsigned long address; 2914526ebbcSRichard Gong int ret; 2924526ebbcSRichard Gong 2934526ebbcSRichard Gong if (priv == 0) 2944526ebbcSRichard Gong return -ENODEV; 2954526ebbcSRichard Gong 2964526ebbcSRichard Gong ret = kstrtoul(buf, 0, &address); 2974526ebbcSRichard Gong if (ret) 2984526ebbcSRichard Gong return ret; 2994526ebbcSRichard Gong 3004526ebbcSRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_UPDATE, 3014526ebbcSRichard Gong address, rsu_command_callback); 3024526ebbcSRichard Gong if (ret) { 3034526ebbcSRichard Gong dev_err(dev, "Error, RSU update returned %i\n", ret); 3044526ebbcSRichard Gong return ret; 3054526ebbcSRichard Gong } 3064526ebbcSRichard Gong 3074526ebbcSRichard Gong return count; 3084526ebbcSRichard Gong } 3094526ebbcSRichard Gong 3104526ebbcSRichard Gong static ssize_t notify_store(struct device *dev, 3114526ebbcSRichard Gong struct device_attribute *attr, 3124526ebbcSRichard Gong const char *buf, size_t count) 3134526ebbcSRichard Gong { 3144526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 3154526ebbcSRichard Gong unsigned long status; 3164526ebbcSRichard Gong int ret; 3174526ebbcSRichard Gong 3184526ebbcSRichard Gong if (priv == 0) 3194526ebbcSRichard Gong return -ENODEV; 3204526ebbcSRichard Gong 3214526ebbcSRichard Gong ret = kstrtoul(buf, 0, &status); 3224526ebbcSRichard Gong if (ret) 3234526ebbcSRichard Gong return ret; 3244526ebbcSRichard Gong 3254526ebbcSRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_NOTIFY, 3264526ebbcSRichard Gong status, rsu_command_callback); 3274526ebbcSRichard Gong if (ret) { 3284526ebbcSRichard Gong dev_err(dev, "Error, RSU notify returned %i\n", ret); 3294526ebbcSRichard Gong return ret; 3304526ebbcSRichard Gong } 3314526ebbcSRichard Gong 3324526ebbcSRichard Gong /* to get the updated state */ 3334526ebbcSRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_STATUS, 3344526ebbcSRichard Gong 0, rsu_status_callback); 3354526ebbcSRichard Gong if (ret) { 3364526ebbcSRichard Gong dev_err(dev, "Error, getting RSU status %i\n", ret); 3374526ebbcSRichard Gong return ret; 3384526ebbcSRichard Gong } 3394526ebbcSRichard Gong 340*e9cb0497SRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback); 3414526ebbcSRichard Gong if (ret) { 342*e9cb0497SRichard Gong dev_err(dev, "Error, getting RSU retry %i\n", ret); 3434526ebbcSRichard Gong return ret; 3444526ebbcSRichard Gong } 3454526ebbcSRichard Gong 3464526ebbcSRichard Gong return count; 3474526ebbcSRichard Gong } 3484526ebbcSRichard Gong 3494526ebbcSRichard Gong static DEVICE_ATTR_RO(current_image); 3504526ebbcSRichard Gong static DEVICE_ATTR_RO(fail_image); 3514526ebbcSRichard Gong static DEVICE_ATTR_RO(state); 3524526ebbcSRichard Gong static DEVICE_ATTR_RO(version); 3534526ebbcSRichard Gong static DEVICE_ATTR_RO(error_location); 3544526ebbcSRichard Gong static DEVICE_ATTR_RO(error_details); 3554526ebbcSRichard Gong static DEVICE_ATTR_RO(retry_counter); 3564526ebbcSRichard Gong static DEVICE_ATTR_WO(reboot_image); 3574526ebbcSRichard Gong static DEVICE_ATTR_WO(notify); 3584526ebbcSRichard Gong 3594526ebbcSRichard Gong static struct attribute *rsu_attrs[] = { 3604526ebbcSRichard Gong &dev_attr_current_image.attr, 3614526ebbcSRichard Gong &dev_attr_fail_image.attr, 3624526ebbcSRichard Gong &dev_attr_state.attr, 3634526ebbcSRichard Gong &dev_attr_version.attr, 3644526ebbcSRichard Gong &dev_attr_error_location.attr, 3654526ebbcSRichard Gong &dev_attr_error_details.attr, 3664526ebbcSRichard Gong &dev_attr_retry_counter.attr, 3674526ebbcSRichard Gong &dev_attr_reboot_image.attr, 3684526ebbcSRichard Gong &dev_attr_notify.attr, 3694526ebbcSRichard Gong NULL 3704526ebbcSRichard Gong }; 3714526ebbcSRichard Gong 3724526ebbcSRichard Gong ATTRIBUTE_GROUPS(rsu); 3734526ebbcSRichard Gong 3744526ebbcSRichard Gong static int stratix10_rsu_probe(struct platform_device *pdev) 3754526ebbcSRichard Gong { 3764526ebbcSRichard Gong struct device *dev = &pdev->dev; 3774526ebbcSRichard Gong struct stratix10_rsu_priv *priv; 3784526ebbcSRichard Gong int ret; 3794526ebbcSRichard Gong 3804526ebbcSRichard Gong priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 3814526ebbcSRichard Gong if (!priv) 3824526ebbcSRichard Gong return -ENOMEM; 3834526ebbcSRichard Gong 3844526ebbcSRichard Gong priv->client.dev = dev; 3854526ebbcSRichard Gong priv->client.receive_cb = NULL; 3864526ebbcSRichard Gong priv->client.priv = priv; 3874526ebbcSRichard Gong priv->status.current_image = 0; 3884526ebbcSRichard Gong priv->status.fail_image = 0; 3894526ebbcSRichard Gong priv->status.error_location = 0; 3904526ebbcSRichard Gong priv->status.error_details = 0; 3914526ebbcSRichard Gong priv->status.version = 0; 3924526ebbcSRichard Gong priv->status.state = 0; 3934526ebbcSRichard Gong priv->retry_counter = INVALID_RETRY_COUNTER; 3944526ebbcSRichard Gong 3954526ebbcSRichard Gong mutex_init(&priv->lock); 3964526ebbcSRichard Gong priv->chan = stratix10_svc_request_channel_byname(&priv->client, 3974526ebbcSRichard Gong SVC_CLIENT_RSU); 3984526ebbcSRichard Gong if (IS_ERR(priv->chan)) { 3994526ebbcSRichard Gong dev_err(dev, "couldn't get service channel %s\n", 4004526ebbcSRichard Gong SVC_CLIENT_RSU); 4014526ebbcSRichard Gong return PTR_ERR(priv->chan); 4024526ebbcSRichard Gong } 4034526ebbcSRichard Gong 4044526ebbcSRichard Gong init_completion(&priv->completion); 4054526ebbcSRichard Gong platform_set_drvdata(pdev, priv); 4064526ebbcSRichard Gong 4074526ebbcSRichard Gong /* get the initial state from firmware */ 4084526ebbcSRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_STATUS, 4094526ebbcSRichard Gong 0, rsu_status_callback); 4104526ebbcSRichard Gong if (ret) { 4114526ebbcSRichard Gong dev_err(dev, "Error, getting RSU status %i\n", ret); 4124526ebbcSRichard Gong stratix10_svc_free_channel(priv->chan); 4134526ebbcSRichard Gong } 4144526ebbcSRichard Gong 415*e9cb0497SRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback); 4164526ebbcSRichard Gong if (ret) { 417*e9cb0497SRichard Gong dev_err(dev, "Error, getting RSU retry %i\n", ret); 4184526ebbcSRichard Gong stratix10_svc_free_channel(priv->chan); 4194526ebbcSRichard Gong } 4204526ebbcSRichard Gong 4214526ebbcSRichard Gong return ret; 4224526ebbcSRichard Gong } 4234526ebbcSRichard Gong 4244526ebbcSRichard Gong static int stratix10_rsu_remove(struct platform_device *pdev) 4254526ebbcSRichard Gong { 4264526ebbcSRichard Gong struct stratix10_rsu_priv *priv = platform_get_drvdata(pdev); 4274526ebbcSRichard Gong 4284526ebbcSRichard Gong stratix10_svc_free_channel(priv->chan); 4294526ebbcSRichard Gong return 0; 4304526ebbcSRichard Gong } 4314526ebbcSRichard Gong 4324526ebbcSRichard Gong static struct platform_driver stratix10_rsu_driver = { 4334526ebbcSRichard Gong .probe = stratix10_rsu_probe, 4344526ebbcSRichard Gong .remove = stratix10_rsu_remove, 4354526ebbcSRichard Gong .driver = { 4364526ebbcSRichard Gong .name = "stratix10-rsu", 4374526ebbcSRichard Gong .dev_groups = rsu_groups, 4384526ebbcSRichard Gong }, 4394526ebbcSRichard Gong }; 4404526ebbcSRichard Gong 4414526ebbcSRichard Gong module_platform_driver(stratix10_rsu_driver); 4424526ebbcSRichard Gong 4434526ebbcSRichard Gong MODULE_LICENSE("GPL v2"); 4444526ebbcSRichard Gong MODULE_DESCRIPTION("Intel Remote System Update Driver"); 4454526ebbcSRichard Gong MODULE_AUTHOR("Richard Gong <richard.gong@intel.com>"); 446