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) 2375bc73fcSRichard Gong #define RSU_DCMF0_MASK GENMASK_ULL(31, 0) 2475bc73fcSRichard Gong #define RSU_DCMF1_MASK GENMASK_ULL(63, 32) 2575bc73fcSRichard Gong #define RSU_DCMF2_MASK GENMASK_ULL(31, 0) 2675bc73fcSRichard Gong #define RSU_DCMF3_MASK GENMASK_ULL(63, 32) 274a6c8c56SKah Jing Lee #define RSU_DCMF0_STATUS_MASK GENMASK_ULL(15, 0) 284a6c8c56SKah Jing Lee #define RSU_DCMF1_STATUS_MASK GENMASK_ULL(31, 16) 294a6c8c56SKah Jing Lee #define RSU_DCMF2_STATUS_MASK GENMASK_ULL(47, 32) 304a6c8c56SKah Jing Lee #define RSU_DCMF3_STATUS_MASK GENMASK_ULL(63, 48) 314526ebbcSRichard Gong 324526ebbcSRichard Gong #define RSU_TIMEOUT (msecs_to_jiffies(SVC_RSU_REQUEST_TIMEOUT_MS)) 334526ebbcSRichard Gong 3475bc73fcSRichard Gong #define INVALID_RETRY_COUNTER 0xFF 3575bc73fcSRichard Gong #define INVALID_DCMF_VERSION 0xFF 364a6c8c56SKah Jing Lee #define INVALID_DCMF_STATUS 0xFFFFFFFF 37*abe8ff43SRadu Bacrau #define INVALID_SPT_ADDRESS 0x0 38*abe8ff43SRadu Bacrau 39*abe8ff43SRadu Bacrau #define RSU_GET_SPT_CMD 0x5A 40*abe8ff43SRadu Bacrau #define RSU_GET_SPT_RESP_LEN (4 * sizeof(unsigned int)) 414526ebbcSRichard Gong 424526ebbcSRichard Gong typedef void (*rsu_callback)(struct stratix10_svc_client *client, 434526ebbcSRichard Gong struct stratix10_svc_cb_data *data); 444526ebbcSRichard Gong /** 454526ebbcSRichard Gong * struct stratix10_rsu_priv - rsu data structure 464526ebbcSRichard Gong * @chan: pointer to the allocated service channel 474526ebbcSRichard Gong * @client: active service client 484526ebbcSRichard Gong * @completion: state for callback completion 494526ebbcSRichard Gong * @lock: a mutex to protect callback completion state 504526ebbcSRichard Gong * @status.current_image: address of image currently running in flash 514526ebbcSRichard Gong * @status.fail_image: address of failed image in flash 5275bc73fcSRichard Gong * @status.version: the interface version number of RSU firmware 534526ebbcSRichard Gong * @status.state: the state of RSU system 544526ebbcSRichard Gong * @status.error_details: error code 554526ebbcSRichard Gong * @status.error_location: the error offset inside the image that failed 5675bc73fcSRichard Gong * @dcmf_version.dcmf0: Quartus dcmf0 version 5775bc73fcSRichard Gong * @dcmf_version.dcmf1: Quartus dcmf1 version 5875bc73fcSRichard Gong * @dcmf_version.dcmf2: Quartus dcmf2 version 5975bc73fcSRichard Gong * @dcmf_version.dcmf3: Quartus dcmf3 version 604a6c8c56SKah Jing Lee * @dcmf_status.dcmf0: dcmf0 status 614a6c8c56SKah Jing Lee * @dcmf_status.dcmf1: dcmf1 status 624a6c8c56SKah Jing Lee * @dcmf_status.dcmf2: dcmf2 status 634a6c8c56SKah Jing Lee * @dcmf_status.dcmf3: dcmf3 status 644526ebbcSRichard Gong * @retry_counter: the current image's retry counter 6575bc73fcSRichard Gong * @max_retry: the preset max retry value 66*abe8ff43SRadu Bacrau * @spt0_address: address of spt0 67*abe8ff43SRadu Bacrau * @spt1_address: address of spt1 68*abe8ff43SRadu Bacrau * @get_spt_response_buf: response from sdm for get_spt command 694526ebbcSRichard Gong */ 704526ebbcSRichard Gong struct stratix10_rsu_priv { 714526ebbcSRichard Gong struct stratix10_svc_chan *chan; 724526ebbcSRichard Gong struct stratix10_svc_client client; 734526ebbcSRichard Gong struct completion completion; 744526ebbcSRichard Gong struct mutex lock; 754526ebbcSRichard Gong struct { 764526ebbcSRichard Gong unsigned long current_image; 774526ebbcSRichard Gong unsigned long fail_image; 784526ebbcSRichard Gong unsigned int version; 794526ebbcSRichard Gong unsigned int state; 804526ebbcSRichard Gong unsigned int error_details; 814526ebbcSRichard Gong unsigned int error_location; 824526ebbcSRichard Gong } status; 8375bc73fcSRichard Gong 8475bc73fcSRichard Gong struct { 8575bc73fcSRichard Gong unsigned int dcmf0; 8675bc73fcSRichard Gong unsigned int dcmf1; 8775bc73fcSRichard Gong unsigned int dcmf2; 8875bc73fcSRichard Gong unsigned int dcmf3; 8975bc73fcSRichard Gong } dcmf_version; 9075bc73fcSRichard Gong 914a6c8c56SKah Jing Lee struct { 924a6c8c56SKah Jing Lee unsigned int dcmf0; 934a6c8c56SKah Jing Lee unsigned int dcmf1; 944a6c8c56SKah Jing Lee unsigned int dcmf2; 954a6c8c56SKah Jing Lee unsigned int dcmf3; 964a6c8c56SKah Jing Lee } dcmf_status; 974a6c8c56SKah Jing Lee 984526ebbcSRichard Gong unsigned int retry_counter; 9975bc73fcSRichard Gong unsigned int max_retry; 100*abe8ff43SRadu Bacrau 101*abe8ff43SRadu Bacrau unsigned long spt0_address; 102*abe8ff43SRadu Bacrau unsigned long spt1_address; 103*abe8ff43SRadu Bacrau 104*abe8ff43SRadu Bacrau unsigned int *get_spt_response_buf; 1054526ebbcSRichard Gong }; 1064526ebbcSRichard Gong 1074526ebbcSRichard Gong /** 1084526ebbcSRichard Gong * rsu_status_callback() - Status callback from Intel Service Layer 1094526ebbcSRichard Gong * @client: pointer to service client 1104526ebbcSRichard Gong * @data: pointer to callback data structure 1114526ebbcSRichard Gong * 1124526ebbcSRichard Gong * Callback from Intel service layer for RSU status request. Status is 1134526ebbcSRichard Gong * only updated after a system reboot, so a get updated status call is 1144526ebbcSRichard Gong * made during driver probe. 1154526ebbcSRichard Gong */ 1164526ebbcSRichard Gong static void rsu_status_callback(struct stratix10_svc_client *client, 1174526ebbcSRichard Gong struct stratix10_svc_cb_data *data) 1184526ebbcSRichard Gong { 1194526ebbcSRichard Gong struct stratix10_rsu_priv *priv = client->priv; 1204526ebbcSRichard Gong struct arm_smccc_res *res = (struct arm_smccc_res *)data->kaddr1; 1214526ebbcSRichard Gong 1227536ad8dSRichard Gong if (data->status == BIT(SVC_STATUS_OK)) { 1234526ebbcSRichard Gong priv->status.version = FIELD_GET(RSU_VERSION_MASK, 1244526ebbcSRichard Gong res->a2); 1254526ebbcSRichard Gong priv->status.state = FIELD_GET(RSU_STATE_MASK, res->a2); 1264526ebbcSRichard Gong priv->status.fail_image = res->a1; 1274526ebbcSRichard Gong priv->status.current_image = res->a0; 1284526ebbcSRichard Gong priv->status.error_location = 1294526ebbcSRichard Gong FIELD_GET(RSU_ERROR_LOCATION_MASK, res->a3); 1304526ebbcSRichard Gong priv->status.error_details = 1314526ebbcSRichard Gong FIELD_GET(RSU_ERROR_DETAIL_MASK, res->a3); 1324526ebbcSRichard Gong } else { 1334526ebbcSRichard Gong dev_err(client->dev, "COMMAND_RSU_STATUS returned 0x%lX\n", 1344526ebbcSRichard Gong res->a0); 1354526ebbcSRichard Gong priv->status.version = 0; 1364526ebbcSRichard Gong priv->status.state = 0; 1374526ebbcSRichard Gong priv->status.fail_image = 0; 1384526ebbcSRichard Gong priv->status.current_image = 0; 1394526ebbcSRichard Gong priv->status.error_location = 0; 1404526ebbcSRichard Gong priv->status.error_details = 0; 1414526ebbcSRichard Gong } 1424526ebbcSRichard Gong 1434526ebbcSRichard Gong complete(&priv->completion); 1444526ebbcSRichard Gong } 1454526ebbcSRichard Gong 1464526ebbcSRichard Gong /** 1474526ebbcSRichard Gong * rsu_command_callback() - Update callback from Intel Service Layer 1484526ebbcSRichard Gong * @client: pointer to client 1494526ebbcSRichard Gong * @data: pointer to callback data structure 1504526ebbcSRichard Gong * 1514526ebbcSRichard Gong * Callback from Intel service layer for RSU commands. 1524526ebbcSRichard Gong */ 1534526ebbcSRichard Gong static void rsu_command_callback(struct stratix10_svc_client *client, 1544526ebbcSRichard Gong struct stratix10_svc_cb_data *data) 1554526ebbcSRichard Gong { 1564526ebbcSRichard Gong struct stratix10_rsu_priv *priv = client->priv; 1574526ebbcSRichard Gong 1587536ad8dSRichard Gong if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) 1594a6c8c56SKah Jing Lee dev_warn(client->dev, "Secure FW doesn't support notify\n"); 1607536ad8dSRichard Gong else if (data->status == BIT(SVC_STATUS_ERROR)) 161e9cb0497SRichard Gong dev_err(client->dev, "Failure, returned status is %lu\n", 162e9cb0497SRichard Gong BIT(data->status)); 163e9cb0497SRichard Gong 1644526ebbcSRichard Gong complete(&priv->completion); 1654526ebbcSRichard Gong } 1664526ebbcSRichard Gong 1674526ebbcSRichard Gong /** 1684526ebbcSRichard Gong * rsu_retry_callback() - Callback from Intel service layer for getting 16975bc73fcSRichard Gong * the current image's retry counter from the firmware 1704526ebbcSRichard Gong * @client: pointer to client 1714526ebbcSRichard Gong * @data: pointer to callback data structure 1724526ebbcSRichard Gong * 1734526ebbcSRichard Gong * Callback from Intel service layer for retry counter, which is used by 1744526ebbcSRichard Gong * user to know how many times the images is still allowed to reload 1754526ebbcSRichard Gong * itself before giving up and starting RSU fail-over flow. 1764526ebbcSRichard Gong */ 1774526ebbcSRichard Gong static void rsu_retry_callback(struct stratix10_svc_client *client, 1784526ebbcSRichard Gong struct stratix10_svc_cb_data *data) 1794526ebbcSRichard Gong { 1804526ebbcSRichard Gong struct stratix10_rsu_priv *priv = client->priv; 1814526ebbcSRichard Gong unsigned int *counter = (unsigned int *)data->kaddr1; 1824526ebbcSRichard Gong 1837536ad8dSRichard Gong if (data->status == BIT(SVC_STATUS_OK)) 1844526ebbcSRichard Gong priv->retry_counter = *counter; 1857536ad8dSRichard Gong else if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) 1864a6c8c56SKah Jing Lee dev_warn(client->dev, "Secure FW doesn't support retry\n"); 1874526ebbcSRichard Gong else 188e9cb0497SRichard Gong dev_err(client->dev, "Failed to get retry counter %lu\n", 189e9cb0497SRichard Gong BIT(data->status)); 1904526ebbcSRichard Gong 1914526ebbcSRichard Gong complete(&priv->completion); 1924526ebbcSRichard Gong } 1934526ebbcSRichard Gong 1944526ebbcSRichard Gong /** 19575bc73fcSRichard Gong * rsu_max_retry_callback() - Callback from Intel service layer for getting 19675bc73fcSRichard Gong * the max retry value from the firmware 19775bc73fcSRichard Gong * @client: pointer to client 19875bc73fcSRichard Gong * @data: pointer to callback data structure 19975bc73fcSRichard Gong * 20075bc73fcSRichard Gong * Callback from Intel service layer for max retry. 20175bc73fcSRichard Gong */ 20275bc73fcSRichard Gong static void rsu_max_retry_callback(struct stratix10_svc_client *client, 20375bc73fcSRichard Gong struct stratix10_svc_cb_data *data) 20475bc73fcSRichard Gong { 20575bc73fcSRichard Gong struct stratix10_rsu_priv *priv = client->priv; 20675bc73fcSRichard Gong unsigned int *max_retry = (unsigned int *)data->kaddr1; 20775bc73fcSRichard Gong 20875bc73fcSRichard Gong if (data->status == BIT(SVC_STATUS_OK)) 20975bc73fcSRichard Gong priv->max_retry = *max_retry; 21075bc73fcSRichard Gong else if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) 2114a6c8c56SKah Jing Lee dev_warn(client->dev, "Secure FW doesn't support max retry\n"); 21275bc73fcSRichard Gong else 21375bc73fcSRichard Gong dev_err(client->dev, "Failed to get max retry %lu\n", 21475bc73fcSRichard Gong BIT(data->status)); 21575bc73fcSRichard Gong 21675bc73fcSRichard Gong complete(&priv->completion); 21775bc73fcSRichard Gong } 21875bc73fcSRichard Gong 21975bc73fcSRichard Gong /** 22075bc73fcSRichard Gong * rsu_dcmf_version_callback() - Callback from Intel service layer for getting 22175bc73fcSRichard Gong * the DCMF version 22275bc73fcSRichard Gong * @client: pointer to client 22375bc73fcSRichard Gong * @data: pointer to callback data structure 22475bc73fcSRichard Gong * 22575bc73fcSRichard Gong * Callback from Intel service layer for DCMF version number 22675bc73fcSRichard Gong */ 22775bc73fcSRichard Gong static void rsu_dcmf_version_callback(struct stratix10_svc_client *client, 22875bc73fcSRichard Gong struct stratix10_svc_cb_data *data) 22975bc73fcSRichard Gong { 23075bc73fcSRichard Gong struct stratix10_rsu_priv *priv = client->priv; 23175bc73fcSRichard Gong unsigned long long *value1 = (unsigned long long *)data->kaddr1; 23275bc73fcSRichard Gong unsigned long long *value2 = (unsigned long long *)data->kaddr2; 23375bc73fcSRichard Gong 23475bc73fcSRichard Gong if (data->status == BIT(SVC_STATUS_OK)) { 23575bc73fcSRichard Gong priv->dcmf_version.dcmf0 = FIELD_GET(RSU_DCMF0_MASK, *value1); 23675bc73fcSRichard Gong priv->dcmf_version.dcmf1 = FIELD_GET(RSU_DCMF1_MASK, *value1); 23775bc73fcSRichard Gong priv->dcmf_version.dcmf2 = FIELD_GET(RSU_DCMF2_MASK, *value2); 23875bc73fcSRichard Gong priv->dcmf_version.dcmf3 = FIELD_GET(RSU_DCMF3_MASK, *value2); 23975bc73fcSRichard Gong } else 24075bc73fcSRichard Gong dev_err(client->dev, "failed to get DCMF version\n"); 24175bc73fcSRichard Gong 24275bc73fcSRichard Gong complete(&priv->completion); 24375bc73fcSRichard Gong } 24475bc73fcSRichard Gong 24575bc73fcSRichard Gong /** 2464a6c8c56SKah Jing Lee * rsu_dcmf_status_callback() - Callback from Intel service layer for getting 2474a6c8c56SKah Jing Lee * the DCMF status 2484a6c8c56SKah Jing Lee * @client: pointer to client 2494a6c8c56SKah Jing Lee * @data: pointer to callback data structure 2504a6c8c56SKah Jing Lee * 2514a6c8c56SKah Jing Lee * Callback from Intel service layer for DCMF status 2524a6c8c56SKah Jing Lee */ 2534a6c8c56SKah Jing Lee static void rsu_dcmf_status_callback(struct stratix10_svc_client *client, 2544a6c8c56SKah Jing Lee struct stratix10_svc_cb_data *data) 2554a6c8c56SKah Jing Lee { 2564a6c8c56SKah Jing Lee struct stratix10_rsu_priv *priv = client->priv; 2574a6c8c56SKah Jing Lee unsigned long long *value = (unsigned long long *)data->kaddr1; 2584a6c8c56SKah Jing Lee 2594a6c8c56SKah Jing Lee if (data->status == BIT(SVC_STATUS_OK)) { 2604a6c8c56SKah Jing Lee priv->dcmf_status.dcmf0 = FIELD_GET(RSU_DCMF0_STATUS_MASK, 2614a6c8c56SKah Jing Lee *value); 2624a6c8c56SKah Jing Lee priv->dcmf_status.dcmf1 = FIELD_GET(RSU_DCMF1_STATUS_MASK, 2634a6c8c56SKah Jing Lee *value); 2644a6c8c56SKah Jing Lee priv->dcmf_status.dcmf2 = FIELD_GET(RSU_DCMF2_STATUS_MASK, 2654a6c8c56SKah Jing Lee *value); 2664a6c8c56SKah Jing Lee priv->dcmf_status.dcmf3 = FIELD_GET(RSU_DCMF3_STATUS_MASK, 2674a6c8c56SKah Jing Lee *value); 2684a6c8c56SKah Jing Lee } else 2694a6c8c56SKah Jing Lee dev_err(client->dev, "failed to get DCMF status\n"); 2704a6c8c56SKah Jing Lee 2714a6c8c56SKah Jing Lee complete(&priv->completion); 2724a6c8c56SKah Jing Lee } 2734a6c8c56SKah Jing Lee 274*abe8ff43SRadu Bacrau static void rsu_get_spt_callback(struct stratix10_svc_client *client, 275*abe8ff43SRadu Bacrau struct stratix10_svc_cb_data *data) 276*abe8ff43SRadu Bacrau { 277*abe8ff43SRadu Bacrau struct stratix10_rsu_priv *priv = client->priv; 278*abe8ff43SRadu Bacrau unsigned long *mbox_err = (unsigned long *)data->kaddr1; 279*abe8ff43SRadu Bacrau unsigned long *resp_len = (unsigned long *)data->kaddr2; 280*abe8ff43SRadu Bacrau 281*abe8ff43SRadu Bacrau if (data->status != BIT(SVC_STATUS_OK) || (*mbox_err) || 282*abe8ff43SRadu Bacrau (*resp_len != RSU_GET_SPT_RESP_LEN)) 283*abe8ff43SRadu Bacrau goto error; 284*abe8ff43SRadu Bacrau 285*abe8ff43SRadu Bacrau priv->spt0_address = priv->get_spt_response_buf[0]; 286*abe8ff43SRadu Bacrau priv->spt0_address <<= 32; 287*abe8ff43SRadu Bacrau priv->spt0_address |= priv->get_spt_response_buf[1]; 288*abe8ff43SRadu Bacrau 289*abe8ff43SRadu Bacrau priv->spt1_address = priv->get_spt_response_buf[2]; 290*abe8ff43SRadu Bacrau priv->spt1_address <<= 32; 291*abe8ff43SRadu Bacrau priv->spt1_address |= priv->get_spt_response_buf[3]; 292*abe8ff43SRadu Bacrau 293*abe8ff43SRadu Bacrau goto complete; 294*abe8ff43SRadu Bacrau 295*abe8ff43SRadu Bacrau error: 296*abe8ff43SRadu Bacrau dev_err(client->dev, "failed to get SPTs\n"); 297*abe8ff43SRadu Bacrau 298*abe8ff43SRadu Bacrau complete: 299*abe8ff43SRadu Bacrau stratix10_svc_free_memory(priv->chan, priv->get_spt_response_buf); 300*abe8ff43SRadu Bacrau priv->get_spt_response_buf = NULL; 301*abe8ff43SRadu Bacrau complete(&priv->completion); 302*abe8ff43SRadu Bacrau } 303*abe8ff43SRadu Bacrau 3044a6c8c56SKah Jing Lee /** 3054526ebbcSRichard Gong * rsu_send_msg() - send a message to Intel service layer 3064526ebbcSRichard Gong * @priv: pointer to rsu private data 3074526ebbcSRichard Gong * @command: RSU status or update command 3084526ebbcSRichard Gong * @arg: the request argument, the bitstream address or notify status 3094526ebbcSRichard Gong * @callback: function pointer for the callback (status or update) 3104526ebbcSRichard Gong * 3114526ebbcSRichard Gong * Start an Intel service layer transaction to perform the SMC call that 3124526ebbcSRichard Gong * is necessary to get RSU boot log or set the address of bitstream to 3134526ebbcSRichard Gong * boot after reboot. 3144526ebbcSRichard Gong * 3154526ebbcSRichard Gong * Returns 0 on success or -ETIMEDOUT on error. 3164526ebbcSRichard Gong */ 3174526ebbcSRichard Gong static int rsu_send_msg(struct stratix10_rsu_priv *priv, 3184526ebbcSRichard Gong enum stratix10_svc_command_code command, 3194526ebbcSRichard Gong unsigned long arg, 3204526ebbcSRichard Gong rsu_callback callback) 3214526ebbcSRichard Gong { 3224526ebbcSRichard Gong struct stratix10_svc_client_msg msg; 3234526ebbcSRichard Gong int ret; 3244526ebbcSRichard Gong 3254526ebbcSRichard Gong mutex_lock(&priv->lock); 3264526ebbcSRichard Gong reinit_completion(&priv->completion); 3274526ebbcSRichard Gong priv->client.receive_cb = callback; 3284526ebbcSRichard Gong 3294526ebbcSRichard Gong msg.command = command; 3304526ebbcSRichard Gong if (arg) 3314526ebbcSRichard Gong msg.arg[0] = arg; 3324526ebbcSRichard Gong 333*abe8ff43SRadu Bacrau if (command == COMMAND_MBOX_SEND_CMD) { 334*abe8ff43SRadu Bacrau msg.arg[1] = 0; 335*abe8ff43SRadu Bacrau msg.payload = NULL; 336*abe8ff43SRadu Bacrau msg.payload_length = 0; 337*abe8ff43SRadu Bacrau msg.payload_output = priv->get_spt_response_buf; 338*abe8ff43SRadu Bacrau msg.payload_length_output = RSU_GET_SPT_RESP_LEN; 339*abe8ff43SRadu Bacrau } 340*abe8ff43SRadu Bacrau 3414526ebbcSRichard Gong ret = stratix10_svc_send(priv->chan, &msg); 3424526ebbcSRichard Gong if (ret < 0) 3434526ebbcSRichard Gong goto status_done; 3444526ebbcSRichard Gong 3454526ebbcSRichard Gong ret = wait_for_completion_interruptible_timeout(&priv->completion, 3464526ebbcSRichard Gong RSU_TIMEOUT); 3474526ebbcSRichard Gong if (!ret) { 3484526ebbcSRichard Gong dev_err(priv->client.dev, 3494526ebbcSRichard Gong "timeout waiting for SMC call\n"); 3504526ebbcSRichard Gong ret = -ETIMEDOUT; 3514526ebbcSRichard Gong goto status_done; 3524526ebbcSRichard Gong } else if (ret < 0) { 3534526ebbcSRichard Gong dev_err(priv->client.dev, 3544526ebbcSRichard Gong "error %d waiting for SMC call\n", ret); 3554526ebbcSRichard Gong goto status_done; 3564526ebbcSRichard Gong } else { 3574526ebbcSRichard Gong ret = 0; 3584526ebbcSRichard Gong } 3594526ebbcSRichard Gong 3604526ebbcSRichard Gong status_done: 3614526ebbcSRichard Gong stratix10_svc_done(priv->chan); 3624526ebbcSRichard Gong mutex_unlock(&priv->lock); 3634526ebbcSRichard Gong return ret; 3644526ebbcSRichard Gong } 3654526ebbcSRichard Gong 3664526ebbcSRichard Gong /* 3674526ebbcSRichard Gong * This driver exposes some optional features of the Intel Stratix 10 SoC FPGA. 3684526ebbcSRichard Gong * The sysfs interfaces exposed here are FPGA Remote System Update (RSU) 3694526ebbcSRichard Gong * related. They allow user space software to query the configuration system 3704526ebbcSRichard Gong * status and to request optional reboot behavior specific to Intel FPGAs. 3714526ebbcSRichard Gong */ 3724526ebbcSRichard Gong 3734526ebbcSRichard Gong static ssize_t current_image_show(struct device *dev, 3744526ebbcSRichard Gong struct device_attribute *attr, char *buf) 3754526ebbcSRichard Gong { 3764526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 3774526ebbcSRichard Gong 3784526ebbcSRichard Gong if (!priv) 3794526ebbcSRichard Gong return -ENODEV; 3804526ebbcSRichard Gong 3814526ebbcSRichard Gong return sprintf(buf, "0x%08lx\n", priv->status.current_image); 3824526ebbcSRichard Gong } 3834526ebbcSRichard Gong 3844526ebbcSRichard Gong static ssize_t fail_image_show(struct device *dev, 3854526ebbcSRichard Gong struct device_attribute *attr, char *buf) 3864526ebbcSRichard Gong { 3874526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 3884526ebbcSRichard Gong 3894526ebbcSRichard Gong if (!priv) 3904526ebbcSRichard Gong return -ENODEV; 3914526ebbcSRichard Gong 3924526ebbcSRichard Gong return sprintf(buf, "0x%08lx\n", priv->status.fail_image); 3934526ebbcSRichard Gong } 3944526ebbcSRichard Gong 3954526ebbcSRichard Gong static ssize_t version_show(struct device *dev, struct device_attribute *attr, 3964526ebbcSRichard Gong char *buf) 3974526ebbcSRichard Gong { 3984526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 3994526ebbcSRichard Gong 4004526ebbcSRichard Gong if (!priv) 4014526ebbcSRichard Gong return -ENODEV; 4024526ebbcSRichard Gong 4034526ebbcSRichard Gong return sprintf(buf, "0x%08x\n", priv->status.version); 4044526ebbcSRichard Gong } 4054526ebbcSRichard Gong 4064526ebbcSRichard Gong static ssize_t state_show(struct device *dev, struct device_attribute *attr, 4074526ebbcSRichard Gong char *buf) 4084526ebbcSRichard Gong { 4094526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 4104526ebbcSRichard Gong 4114526ebbcSRichard Gong if (!priv) 4124526ebbcSRichard Gong return -ENODEV; 4134526ebbcSRichard Gong 4144526ebbcSRichard Gong return sprintf(buf, "0x%08x\n", priv->status.state); 4154526ebbcSRichard Gong } 4164526ebbcSRichard Gong 4174526ebbcSRichard Gong static ssize_t error_location_show(struct device *dev, 4184526ebbcSRichard Gong struct device_attribute *attr, char *buf) 4194526ebbcSRichard Gong { 4204526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 4214526ebbcSRichard Gong 4224526ebbcSRichard Gong if (!priv) 4234526ebbcSRichard Gong return -ENODEV; 4244526ebbcSRichard Gong 4254526ebbcSRichard Gong return sprintf(buf, "0x%08x\n", priv->status.error_location); 4264526ebbcSRichard Gong } 4274526ebbcSRichard Gong 4284526ebbcSRichard Gong static ssize_t error_details_show(struct device *dev, 4294526ebbcSRichard Gong struct device_attribute *attr, char *buf) 4304526ebbcSRichard Gong { 4314526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 4324526ebbcSRichard Gong 4334526ebbcSRichard Gong if (!priv) 4344526ebbcSRichard Gong return -ENODEV; 4354526ebbcSRichard Gong 4364526ebbcSRichard Gong return sprintf(buf, "0x%08x\n", priv->status.error_details); 4374526ebbcSRichard Gong } 4384526ebbcSRichard Gong 4394526ebbcSRichard Gong static ssize_t retry_counter_show(struct device *dev, 4404526ebbcSRichard Gong struct device_attribute *attr, char *buf) 4414526ebbcSRichard Gong { 4424526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 4434526ebbcSRichard Gong 4444526ebbcSRichard Gong if (!priv) 4454526ebbcSRichard Gong return -ENODEV; 4464526ebbcSRichard Gong 4474526ebbcSRichard Gong return sprintf(buf, "0x%08x\n", priv->retry_counter); 4484526ebbcSRichard Gong } 4494526ebbcSRichard Gong 45075bc73fcSRichard Gong static ssize_t max_retry_show(struct device *dev, 45175bc73fcSRichard Gong struct device_attribute *attr, char *buf) 45275bc73fcSRichard Gong { 45375bc73fcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 45475bc73fcSRichard Gong 45575bc73fcSRichard Gong if (!priv) 45675bc73fcSRichard Gong return -ENODEV; 45775bc73fcSRichard Gong 4584a6c8c56SKah Jing Lee return scnprintf(buf, sizeof(priv->max_retry), 4594a6c8c56SKah Jing Lee "0x%08x\n", priv->max_retry); 46075bc73fcSRichard Gong } 46175bc73fcSRichard Gong 46275bc73fcSRichard Gong static ssize_t dcmf0_show(struct device *dev, 46375bc73fcSRichard Gong struct device_attribute *attr, char *buf) 46475bc73fcSRichard Gong { 46575bc73fcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 46675bc73fcSRichard Gong 46775bc73fcSRichard Gong if (!priv) 46875bc73fcSRichard Gong return -ENODEV; 46975bc73fcSRichard Gong 47075bc73fcSRichard Gong return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf0); 47175bc73fcSRichard Gong } 47275bc73fcSRichard Gong 47375bc73fcSRichard Gong static ssize_t dcmf1_show(struct device *dev, 47475bc73fcSRichard Gong struct device_attribute *attr, char *buf) 47575bc73fcSRichard Gong { 47675bc73fcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 47775bc73fcSRichard Gong 47875bc73fcSRichard Gong if (!priv) 47975bc73fcSRichard Gong return -ENODEV; 48075bc73fcSRichard Gong 48175bc73fcSRichard Gong return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf1); 48275bc73fcSRichard Gong } 48375bc73fcSRichard Gong 48475bc73fcSRichard Gong static ssize_t dcmf2_show(struct device *dev, 48575bc73fcSRichard Gong struct device_attribute *attr, char *buf) 48675bc73fcSRichard Gong { 48775bc73fcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 48875bc73fcSRichard Gong 48975bc73fcSRichard Gong if (!priv) 49075bc73fcSRichard Gong return -ENODEV; 49175bc73fcSRichard Gong 49275bc73fcSRichard Gong return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf2); 49375bc73fcSRichard Gong } 49475bc73fcSRichard Gong 49575bc73fcSRichard Gong static ssize_t dcmf3_show(struct device *dev, 49675bc73fcSRichard Gong struct device_attribute *attr, char *buf) 49775bc73fcSRichard Gong { 49875bc73fcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 49975bc73fcSRichard Gong 50075bc73fcSRichard Gong if (!priv) 50175bc73fcSRichard Gong return -ENODEV; 50275bc73fcSRichard Gong 50375bc73fcSRichard Gong return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf3); 50475bc73fcSRichard Gong } 50575bc73fcSRichard Gong 5064a6c8c56SKah Jing Lee static ssize_t dcmf0_status_show(struct device *dev, 5074a6c8c56SKah Jing Lee struct device_attribute *attr, char *buf) 5084a6c8c56SKah Jing Lee { 5094a6c8c56SKah Jing Lee struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 5104a6c8c56SKah Jing Lee 5114a6c8c56SKah Jing Lee if (!priv) 5124a6c8c56SKah Jing Lee return -ENODEV; 5134a6c8c56SKah Jing Lee 5144a6c8c56SKah Jing Lee if (priv->dcmf_status.dcmf0 == INVALID_DCMF_STATUS) 5154a6c8c56SKah Jing Lee return -EIO; 5164a6c8c56SKah Jing Lee 5174a6c8c56SKah Jing Lee return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf0); 5184a6c8c56SKah Jing Lee } 5194a6c8c56SKah Jing Lee 5204a6c8c56SKah Jing Lee static ssize_t dcmf1_status_show(struct device *dev, 5214a6c8c56SKah Jing Lee struct device_attribute *attr, char *buf) 5224a6c8c56SKah Jing Lee { 5234a6c8c56SKah Jing Lee struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 5244a6c8c56SKah Jing Lee 5254a6c8c56SKah Jing Lee if (!priv) 5264a6c8c56SKah Jing Lee return -ENODEV; 5274a6c8c56SKah Jing Lee 5284a6c8c56SKah Jing Lee if (priv->dcmf_status.dcmf1 == INVALID_DCMF_STATUS) 5294a6c8c56SKah Jing Lee return -EIO; 5304a6c8c56SKah Jing Lee 5314a6c8c56SKah Jing Lee return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf1); 5324a6c8c56SKah Jing Lee } 5334a6c8c56SKah Jing Lee 5344a6c8c56SKah Jing Lee static ssize_t dcmf2_status_show(struct device *dev, 5354a6c8c56SKah Jing Lee struct device_attribute *attr, char *buf) 5364a6c8c56SKah Jing Lee { 5374a6c8c56SKah Jing Lee struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 5384a6c8c56SKah Jing Lee 5394a6c8c56SKah Jing Lee if (!priv) 5404a6c8c56SKah Jing Lee return -ENODEV; 5414a6c8c56SKah Jing Lee 5424a6c8c56SKah Jing Lee if (priv->dcmf_status.dcmf2 == INVALID_DCMF_STATUS) 5434a6c8c56SKah Jing Lee return -EIO; 5444a6c8c56SKah Jing Lee 5454a6c8c56SKah Jing Lee return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf2); 5464a6c8c56SKah Jing Lee } 5474a6c8c56SKah Jing Lee 5484a6c8c56SKah Jing Lee static ssize_t dcmf3_status_show(struct device *dev, 5494a6c8c56SKah Jing Lee struct device_attribute *attr, char *buf) 5504a6c8c56SKah Jing Lee { 5514a6c8c56SKah Jing Lee struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 5524a6c8c56SKah Jing Lee 5534a6c8c56SKah Jing Lee if (!priv) 5544a6c8c56SKah Jing Lee return -ENODEV; 5554a6c8c56SKah Jing Lee 5564a6c8c56SKah Jing Lee if (priv->dcmf_status.dcmf3 == INVALID_DCMF_STATUS) 5574a6c8c56SKah Jing Lee return -EIO; 5584a6c8c56SKah Jing Lee 5594a6c8c56SKah Jing Lee return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf3); 5604a6c8c56SKah Jing Lee } 5614526ebbcSRichard Gong static ssize_t reboot_image_store(struct device *dev, 5624526ebbcSRichard Gong struct device_attribute *attr, 5634526ebbcSRichard Gong const char *buf, size_t count) 5644526ebbcSRichard Gong { 5654526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 5664526ebbcSRichard Gong unsigned long address; 5674526ebbcSRichard Gong int ret; 5684526ebbcSRichard Gong 56952f944eeSRichard Gong if (!priv) 5704526ebbcSRichard Gong return -ENODEV; 5714526ebbcSRichard Gong 5724526ebbcSRichard Gong ret = kstrtoul(buf, 0, &address); 5734526ebbcSRichard Gong if (ret) 5744526ebbcSRichard Gong return ret; 5754526ebbcSRichard Gong 5764526ebbcSRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_UPDATE, 5774526ebbcSRichard Gong address, rsu_command_callback); 5784526ebbcSRichard Gong if (ret) { 5794526ebbcSRichard Gong dev_err(dev, "Error, RSU update returned %i\n", ret); 5804526ebbcSRichard Gong return ret; 5814526ebbcSRichard Gong } 5824526ebbcSRichard Gong 5834526ebbcSRichard Gong return count; 5844526ebbcSRichard Gong } 5854526ebbcSRichard Gong 5864526ebbcSRichard Gong static ssize_t notify_store(struct device *dev, 5874526ebbcSRichard Gong struct device_attribute *attr, 5884526ebbcSRichard Gong const char *buf, size_t count) 5894526ebbcSRichard Gong { 5904526ebbcSRichard Gong struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 5914526ebbcSRichard Gong unsigned long status; 5924526ebbcSRichard Gong int ret; 5934526ebbcSRichard Gong 59452f944eeSRichard Gong if (!priv) 5954526ebbcSRichard Gong return -ENODEV; 5964526ebbcSRichard Gong 5974526ebbcSRichard Gong ret = kstrtoul(buf, 0, &status); 5984526ebbcSRichard Gong if (ret) 5994526ebbcSRichard Gong return ret; 6004526ebbcSRichard Gong 6014526ebbcSRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_NOTIFY, 6024526ebbcSRichard Gong status, rsu_command_callback); 6034526ebbcSRichard Gong if (ret) { 6044526ebbcSRichard Gong dev_err(dev, "Error, RSU notify returned %i\n", ret); 6054526ebbcSRichard Gong return ret; 6064526ebbcSRichard Gong } 6074526ebbcSRichard Gong 6084526ebbcSRichard Gong /* to get the updated state */ 6094526ebbcSRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_STATUS, 6104526ebbcSRichard Gong 0, rsu_status_callback); 6114526ebbcSRichard Gong if (ret) { 6124526ebbcSRichard Gong dev_err(dev, "Error, getting RSU status %i\n", ret); 6134526ebbcSRichard Gong return ret; 6144526ebbcSRichard Gong } 6154526ebbcSRichard Gong 616e9cb0497SRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback); 6174526ebbcSRichard Gong if (ret) { 618e9cb0497SRichard Gong dev_err(dev, "Error, getting RSU retry %i\n", ret); 6194526ebbcSRichard Gong return ret; 6204526ebbcSRichard Gong } 6214526ebbcSRichard Gong 6224526ebbcSRichard Gong return count; 6234526ebbcSRichard Gong } 6244526ebbcSRichard Gong 625*abe8ff43SRadu Bacrau static ssize_t spt0_address_show(struct device *dev, 626*abe8ff43SRadu Bacrau struct device_attribute *attr, char *buf) 627*abe8ff43SRadu Bacrau { 628*abe8ff43SRadu Bacrau struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 629*abe8ff43SRadu Bacrau 630*abe8ff43SRadu Bacrau if (!priv) 631*abe8ff43SRadu Bacrau return -ENODEV; 632*abe8ff43SRadu Bacrau 633*abe8ff43SRadu Bacrau if (priv->spt0_address == INVALID_SPT_ADDRESS) 634*abe8ff43SRadu Bacrau return -EIO; 635*abe8ff43SRadu Bacrau 636*abe8ff43SRadu Bacrau return scnprintf(buf, PAGE_SIZE, "0x%08lx\n", priv->spt0_address); 637*abe8ff43SRadu Bacrau } 638*abe8ff43SRadu Bacrau 639*abe8ff43SRadu Bacrau static ssize_t spt1_address_show(struct device *dev, 640*abe8ff43SRadu Bacrau struct device_attribute *attr, char *buf) 641*abe8ff43SRadu Bacrau { 642*abe8ff43SRadu Bacrau struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); 643*abe8ff43SRadu Bacrau 644*abe8ff43SRadu Bacrau if (!priv) 645*abe8ff43SRadu Bacrau return -ENODEV; 646*abe8ff43SRadu Bacrau 647*abe8ff43SRadu Bacrau if (priv->spt1_address == INVALID_SPT_ADDRESS) 648*abe8ff43SRadu Bacrau return -EIO; 649*abe8ff43SRadu Bacrau 650*abe8ff43SRadu Bacrau return scnprintf(buf, PAGE_SIZE, "0x%08lx\n", priv->spt1_address); 651*abe8ff43SRadu Bacrau } 652*abe8ff43SRadu Bacrau 6534526ebbcSRichard Gong static DEVICE_ATTR_RO(current_image); 6544526ebbcSRichard Gong static DEVICE_ATTR_RO(fail_image); 6554526ebbcSRichard Gong static DEVICE_ATTR_RO(state); 6564526ebbcSRichard Gong static DEVICE_ATTR_RO(version); 6574526ebbcSRichard Gong static DEVICE_ATTR_RO(error_location); 6584526ebbcSRichard Gong static DEVICE_ATTR_RO(error_details); 6594526ebbcSRichard Gong static DEVICE_ATTR_RO(retry_counter); 66075bc73fcSRichard Gong static DEVICE_ATTR_RO(max_retry); 66175bc73fcSRichard Gong static DEVICE_ATTR_RO(dcmf0); 66275bc73fcSRichard Gong static DEVICE_ATTR_RO(dcmf1); 66375bc73fcSRichard Gong static DEVICE_ATTR_RO(dcmf2); 66475bc73fcSRichard Gong static DEVICE_ATTR_RO(dcmf3); 6654a6c8c56SKah Jing Lee static DEVICE_ATTR_RO(dcmf0_status); 6664a6c8c56SKah Jing Lee static DEVICE_ATTR_RO(dcmf1_status); 6674a6c8c56SKah Jing Lee static DEVICE_ATTR_RO(dcmf2_status); 6684a6c8c56SKah Jing Lee static DEVICE_ATTR_RO(dcmf3_status); 6694526ebbcSRichard Gong static DEVICE_ATTR_WO(reboot_image); 6704526ebbcSRichard Gong static DEVICE_ATTR_WO(notify); 671*abe8ff43SRadu Bacrau static DEVICE_ATTR_RO(spt0_address); 672*abe8ff43SRadu Bacrau static DEVICE_ATTR_RO(spt1_address); 6734526ebbcSRichard Gong 6744526ebbcSRichard Gong static struct attribute *rsu_attrs[] = { 6754526ebbcSRichard Gong &dev_attr_current_image.attr, 6764526ebbcSRichard Gong &dev_attr_fail_image.attr, 6774526ebbcSRichard Gong &dev_attr_state.attr, 6784526ebbcSRichard Gong &dev_attr_version.attr, 6794526ebbcSRichard Gong &dev_attr_error_location.attr, 6804526ebbcSRichard Gong &dev_attr_error_details.attr, 6814526ebbcSRichard Gong &dev_attr_retry_counter.attr, 68275bc73fcSRichard Gong &dev_attr_max_retry.attr, 68375bc73fcSRichard Gong &dev_attr_dcmf0.attr, 68475bc73fcSRichard Gong &dev_attr_dcmf1.attr, 68575bc73fcSRichard Gong &dev_attr_dcmf2.attr, 68675bc73fcSRichard Gong &dev_attr_dcmf3.attr, 6874a6c8c56SKah Jing Lee &dev_attr_dcmf0_status.attr, 6884a6c8c56SKah Jing Lee &dev_attr_dcmf1_status.attr, 6894a6c8c56SKah Jing Lee &dev_attr_dcmf2_status.attr, 6904a6c8c56SKah Jing Lee &dev_attr_dcmf3_status.attr, 6914526ebbcSRichard Gong &dev_attr_reboot_image.attr, 6924526ebbcSRichard Gong &dev_attr_notify.attr, 693*abe8ff43SRadu Bacrau &dev_attr_spt0_address.attr, 694*abe8ff43SRadu Bacrau &dev_attr_spt1_address.attr, 6954526ebbcSRichard Gong NULL 6964526ebbcSRichard Gong }; 6974526ebbcSRichard Gong 6984526ebbcSRichard Gong ATTRIBUTE_GROUPS(rsu); 6994526ebbcSRichard Gong 7004526ebbcSRichard Gong static int stratix10_rsu_probe(struct platform_device *pdev) 7014526ebbcSRichard Gong { 7024526ebbcSRichard Gong struct device *dev = &pdev->dev; 7034526ebbcSRichard Gong struct stratix10_rsu_priv *priv; 7044526ebbcSRichard Gong int ret; 7054526ebbcSRichard Gong 7064526ebbcSRichard Gong priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 7074526ebbcSRichard Gong if (!priv) 7084526ebbcSRichard Gong return -ENOMEM; 7094526ebbcSRichard Gong 7104526ebbcSRichard Gong priv->client.dev = dev; 7114526ebbcSRichard Gong priv->client.receive_cb = NULL; 7124526ebbcSRichard Gong priv->client.priv = priv; 7134526ebbcSRichard Gong priv->status.current_image = 0; 7144526ebbcSRichard Gong priv->status.fail_image = 0; 7154526ebbcSRichard Gong priv->status.error_location = 0; 7164526ebbcSRichard Gong priv->status.error_details = 0; 7174526ebbcSRichard Gong priv->status.version = 0; 7184526ebbcSRichard Gong priv->status.state = 0; 7194526ebbcSRichard Gong priv->retry_counter = INVALID_RETRY_COUNTER; 72075bc73fcSRichard Gong priv->dcmf_version.dcmf0 = INVALID_DCMF_VERSION; 72175bc73fcSRichard Gong priv->dcmf_version.dcmf1 = INVALID_DCMF_VERSION; 72275bc73fcSRichard Gong priv->dcmf_version.dcmf2 = INVALID_DCMF_VERSION; 72375bc73fcSRichard Gong priv->dcmf_version.dcmf3 = INVALID_DCMF_VERSION; 7244a6c8c56SKah Jing Lee priv->dcmf_status.dcmf0 = INVALID_DCMF_STATUS; 7254a6c8c56SKah Jing Lee priv->dcmf_status.dcmf1 = INVALID_DCMF_STATUS; 7264a6c8c56SKah Jing Lee priv->dcmf_status.dcmf2 = INVALID_DCMF_STATUS; 7274a6c8c56SKah Jing Lee priv->dcmf_status.dcmf3 = INVALID_DCMF_STATUS; 728*abe8ff43SRadu Bacrau priv->max_retry = INVALID_RETRY_COUNTER; 729*abe8ff43SRadu Bacrau priv->spt0_address = INVALID_SPT_ADDRESS; 730*abe8ff43SRadu Bacrau priv->spt1_address = INVALID_SPT_ADDRESS; 7314526ebbcSRichard Gong 7324526ebbcSRichard Gong mutex_init(&priv->lock); 7334526ebbcSRichard Gong priv->chan = stratix10_svc_request_channel_byname(&priv->client, 7344526ebbcSRichard Gong SVC_CLIENT_RSU); 7354526ebbcSRichard Gong if (IS_ERR(priv->chan)) { 7364526ebbcSRichard Gong dev_err(dev, "couldn't get service channel %s\n", 7374526ebbcSRichard Gong SVC_CLIENT_RSU); 7384526ebbcSRichard Gong return PTR_ERR(priv->chan); 7394526ebbcSRichard Gong } 7404526ebbcSRichard Gong 7414526ebbcSRichard Gong init_completion(&priv->completion); 7424526ebbcSRichard Gong platform_set_drvdata(pdev, priv); 7434526ebbcSRichard Gong 7444526ebbcSRichard Gong /* get the initial state from firmware */ 7454526ebbcSRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_STATUS, 7464526ebbcSRichard Gong 0, rsu_status_callback); 7474526ebbcSRichard Gong if (ret) { 7484526ebbcSRichard Gong dev_err(dev, "Error, getting RSU status %i\n", ret); 7494526ebbcSRichard Gong stratix10_svc_free_channel(priv->chan); 7504526ebbcSRichard Gong } 7514526ebbcSRichard Gong 75275bc73fcSRichard Gong /* get DCMF version from firmware */ 75375bc73fcSRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_VERSION, 75475bc73fcSRichard Gong 0, rsu_dcmf_version_callback); 75575bc73fcSRichard Gong if (ret) { 75675bc73fcSRichard Gong dev_err(dev, "Error, getting DCMF version %i\n", ret); 75775bc73fcSRichard Gong stratix10_svc_free_channel(priv->chan); 75875bc73fcSRichard Gong } 75975bc73fcSRichard Gong 7604a6c8c56SKah Jing Lee ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS, 7614a6c8c56SKah Jing Lee 0, rsu_dcmf_status_callback); 7624a6c8c56SKah Jing Lee if (ret) { 7634a6c8c56SKah Jing Lee dev_err(dev, "Error, getting DCMF status %i\n", ret); 7644a6c8c56SKah Jing Lee stratix10_svc_free_channel(priv->chan); 7654a6c8c56SKah Jing Lee } 7664a6c8c56SKah Jing Lee 767e9cb0497SRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback); 7684526ebbcSRichard Gong if (ret) { 769e9cb0497SRichard Gong dev_err(dev, "Error, getting RSU retry %i\n", ret); 7704526ebbcSRichard Gong stratix10_svc_free_channel(priv->chan); 7714526ebbcSRichard Gong } 7724526ebbcSRichard Gong 77375bc73fcSRichard Gong ret = rsu_send_msg(priv, COMMAND_RSU_MAX_RETRY, 0, 77475bc73fcSRichard Gong rsu_max_retry_callback); 77575bc73fcSRichard Gong if (ret) { 77675bc73fcSRichard Gong dev_err(dev, "Error, getting RSU max retry %i\n", ret); 77775bc73fcSRichard Gong stratix10_svc_free_channel(priv->chan); 77875bc73fcSRichard Gong } 77975bc73fcSRichard Gong 780*abe8ff43SRadu Bacrau priv->get_spt_response_buf = 781*abe8ff43SRadu Bacrau stratix10_svc_allocate_memory(priv->chan, RSU_GET_SPT_RESP_LEN); 782*abe8ff43SRadu Bacrau 783*abe8ff43SRadu Bacrau if (IS_ERR(priv->get_spt_response_buf)) { 784*abe8ff43SRadu Bacrau dev_err(dev, "failed to allocate get spt buffer\n"); 785*abe8ff43SRadu Bacrau } else { 786*abe8ff43SRadu Bacrau ret = rsu_send_msg(priv, COMMAND_MBOX_SEND_CMD, 787*abe8ff43SRadu Bacrau RSU_GET_SPT_CMD, rsu_get_spt_callback); 788*abe8ff43SRadu Bacrau if (ret) { 789*abe8ff43SRadu Bacrau dev_err(dev, "Error, getting SPT table %i\n", ret); 790*abe8ff43SRadu Bacrau stratix10_svc_free_channel(priv->chan); 791*abe8ff43SRadu Bacrau } 792*abe8ff43SRadu Bacrau } 793*abe8ff43SRadu Bacrau 7944526ebbcSRichard Gong return ret; 7954526ebbcSRichard Gong } 7964526ebbcSRichard Gong 7974526ebbcSRichard Gong static int stratix10_rsu_remove(struct platform_device *pdev) 7984526ebbcSRichard Gong { 7994526ebbcSRichard Gong struct stratix10_rsu_priv *priv = platform_get_drvdata(pdev); 8004526ebbcSRichard Gong 8014526ebbcSRichard Gong stratix10_svc_free_channel(priv->chan); 8024526ebbcSRichard Gong return 0; 8034526ebbcSRichard Gong } 8044526ebbcSRichard Gong 8054526ebbcSRichard Gong static struct platform_driver stratix10_rsu_driver = { 8064526ebbcSRichard Gong .probe = stratix10_rsu_probe, 8074526ebbcSRichard Gong .remove = stratix10_rsu_remove, 8084526ebbcSRichard Gong .driver = { 8094526ebbcSRichard Gong .name = "stratix10-rsu", 8104526ebbcSRichard Gong .dev_groups = rsu_groups, 8114526ebbcSRichard Gong }, 8124526ebbcSRichard Gong }; 8134526ebbcSRichard Gong 8144526ebbcSRichard Gong module_platform_driver(stratix10_rsu_driver); 8154526ebbcSRichard Gong 8164526ebbcSRichard Gong MODULE_LICENSE("GPL v2"); 8174526ebbcSRichard Gong MODULE_DESCRIPTION("Intel Remote System Update Driver"); 8184526ebbcSRichard Gong MODULE_AUTHOR("Richard Gong <richard.gong@intel.com>"); 819