diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-08-04 20:05:48 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-08-04 20:05:48 +0200 |
commit | 228dfe98a313f6b6bff5da8b2c5e650e297ebf1a (patch) | |
tree | 501dc44c2453743eb2298fe23d6cdd0b5e91b2c2 /drivers/firmware | |
parent | drm/amd/display: restore code for plane with no modifiers (diff) | |
parent | drivers: lkdtm: fix clang -Wformat warning (diff) | |
download | linux-228dfe98a313f6b6bff5da8b2c5e650e297ebf1a.tar.xz linux-228dfe98a313f6b6bff5da8b2c5e650e297ebf1a.zip |
Merge tag 'char-misc-6.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char / misc driver updates from Greg KH:
"Here is the large set of char and misc and other driver subsystem
changes for 6.0-rc1.
Highlights include:
- large set of IIO driver updates, additions, and cleanups
- new habanalabs device support added (loads of register maps much
like GPUs have)
- soundwire driver updates
- phy driver updates
- slimbus driver updates
- tiny virt driver fixes and updates
- misc driver fixes and updates
- interconnect driver updates
- hwtracing driver updates
- fpga driver updates
- extcon driver updates
- firmware driver updates
- counter driver update
- mhi driver fixes and updates
- binder driver fixes and updates
- speakup driver fixes
All of these have been in linux-next for a while without any reported
problems"
* tag 'char-misc-6.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (634 commits)
drivers: lkdtm: fix clang -Wformat warning
char: remove VR41XX related char driver
misc: Mark MICROCODE_MINOR unused
spmi: trace: fix stack-out-of-bound access in SPMI tracing functions
dt-bindings: iio: adc: Add compatible for MT8188
iio: light: isl29028: Fix the warning in isl29028_remove()
iio: accel: sca3300: Extend the trigger buffer from 16 to 32 bytes
iio: fix iio_format_avail_range() printing for none IIO_VAL_INT
iio: adc: max1027: unlock on error path in max1027_read_single_value()
iio: proximity: sx9324: add empty line in front of bullet list
iio: magnetometer: hmc5843: Remove duplicate 'the'
iio: magn: yas530: Use DEFINE_RUNTIME_DEV_PM_OPS() and pm_ptr() macros
iio: magnetometer: ak8974: Use DEFINE_RUNTIME_DEV_PM_OPS() and pm_ptr() macros
iio: light: veml6030: Use DEFINE_RUNTIME_DEV_PM_OPS() and pm_ptr() macros
iio: light: vcnl4035: Use DEFINE_RUNTIME_DEV_PM_OPS() and pm_ptr() macros
iio: light: vcnl4000: Use DEFINE_RUNTIME_DEV_PM_OPS() and pm_ptr() macros
iio: light: tsl2591: Use DEFINE_RUNTIME_DEV_PM_OPS() and pm_ptr()
iio: light: tsl2583: Use DEFINE_RUNTIME_DEV_PM_OPS and pm_ptr()
iio: light: isl29028: Use DEFINE_RUNTIME_DEV_PM_OPS() and pm_ptr()
iio: light: gp2ap002: Switch to DEFINE_RUNTIME_DEV_PM_OPS and pm_ptr()
...
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/stratix10-rsu.c | 129 | ||||
-rw-r--r-- | drivers/firmware/stratix10-svc.c | 201 |
2 files changed, 302 insertions, 28 deletions
diff --git a/drivers/firmware/stratix10-rsu.c b/drivers/firmware/stratix10-rsu.c index 9378075d04e9..e51c95f8d445 100644 --- a/drivers/firmware/stratix10-rsu.c +++ b/drivers/firmware/stratix10-rsu.c @@ -24,12 +24,16 @@ #define RSU_DCMF1_MASK GENMASK_ULL(63, 32) #define RSU_DCMF2_MASK GENMASK_ULL(31, 0) #define RSU_DCMF3_MASK GENMASK_ULL(63, 32) +#define RSU_DCMF0_STATUS_MASK GENMASK_ULL(15, 0) +#define RSU_DCMF1_STATUS_MASK GENMASK_ULL(31, 16) +#define RSU_DCMF2_STATUS_MASK GENMASK_ULL(47, 32) +#define RSU_DCMF3_STATUS_MASK GENMASK_ULL(63, 48) #define RSU_TIMEOUT (msecs_to_jiffies(SVC_RSU_REQUEST_TIMEOUT_MS)) #define INVALID_RETRY_COUNTER 0xFF #define INVALID_DCMF_VERSION 0xFF - +#define INVALID_DCMF_STATUS 0xFFFFFFFF typedef void (*rsu_callback)(struct stratix10_svc_client *client, struct stratix10_svc_cb_data *data); @@ -49,6 +53,10 @@ typedef void (*rsu_callback)(struct stratix10_svc_client *client, * @dcmf_version.dcmf1: Quartus dcmf1 version * @dcmf_version.dcmf2: Quartus dcmf2 version * @dcmf_version.dcmf3: Quartus dcmf3 version + * @dcmf_status.dcmf0: dcmf0 status + * @dcmf_status.dcmf1: dcmf1 status + * @dcmf_status.dcmf2: dcmf2 status + * @dcmf_status.dcmf3: dcmf3 status * @retry_counter: the current image's retry counter * @max_retry: the preset max retry value */ @@ -73,6 +81,13 @@ struct stratix10_rsu_priv { unsigned int dcmf3; } dcmf_version; + struct { + unsigned int dcmf0; + unsigned int dcmf1; + unsigned int dcmf2; + unsigned int dcmf3; + } dcmf_status; + unsigned int retry_counter; unsigned int max_retry; }; @@ -129,7 +144,7 @@ static void rsu_command_callback(struct stratix10_svc_client *client, struct stratix10_rsu_priv *priv = client->priv; if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) - dev_warn(client->dev, "FW doesn't support notify\n"); + dev_warn(client->dev, "Secure FW doesn't support notify\n"); else if (data->status == BIT(SVC_STATUS_ERROR)) dev_err(client->dev, "Failure, returned status is %lu\n", BIT(data->status)); @@ -156,7 +171,7 @@ static void rsu_retry_callback(struct stratix10_svc_client *client, if (data->status == BIT(SVC_STATUS_OK)) priv->retry_counter = *counter; else if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) - dev_warn(client->dev, "FW doesn't support retry\n"); + dev_warn(client->dev, "Secure FW doesn't support retry\n"); else dev_err(client->dev, "Failed to get retry counter %lu\n", BIT(data->status)); @@ -181,7 +196,7 @@ static void rsu_max_retry_callback(struct stratix10_svc_client *client, if (data->status == BIT(SVC_STATUS_OK)) priv->max_retry = *max_retry; else if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) - dev_warn(client->dev, "FW doesn't support max retry\n"); + dev_warn(client->dev, "Secure FW doesn't support max retry\n"); else dev_err(client->dev, "Failed to get max retry %lu\n", BIT(data->status)); @@ -216,6 +231,35 @@ static void rsu_dcmf_version_callback(struct stratix10_svc_client *client, } /** + * rsu_dcmf_status_callback() - Callback from Intel service layer for getting + * the DCMF status + * @client: pointer to client + * @data: pointer to callback data structure + * + * Callback from Intel service layer for DCMF status + */ +static void rsu_dcmf_status_callback(struct stratix10_svc_client *client, + struct stratix10_svc_cb_data *data) +{ + struct stratix10_rsu_priv *priv = client->priv; + unsigned long long *value = (unsigned long long *)data->kaddr1; + + if (data->status == BIT(SVC_STATUS_OK)) { + priv->dcmf_status.dcmf0 = FIELD_GET(RSU_DCMF0_STATUS_MASK, + *value); + priv->dcmf_status.dcmf1 = FIELD_GET(RSU_DCMF1_STATUS_MASK, + *value); + priv->dcmf_status.dcmf2 = FIELD_GET(RSU_DCMF2_STATUS_MASK, + *value); + priv->dcmf_status.dcmf3 = FIELD_GET(RSU_DCMF3_STATUS_MASK, + *value); + } else + dev_err(client->dev, "failed to get DCMF status\n"); + + complete(&priv->completion); +} + +/** * rsu_send_msg() - send a message to Intel service layer * @priv: pointer to rsu private data * @command: RSU status or update command @@ -361,7 +405,8 @@ static ssize_t max_retry_show(struct device *dev, if (!priv) return -ENODEV; - return sprintf(buf, "0x%08x\n", priv->max_retry); + return scnprintf(buf, sizeof(priv->max_retry), + "0x%08x\n", priv->max_retry); } static ssize_t dcmf0_show(struct device *dev, @@ -408,6 +453,61 @@ static ssize_t dcmf3_show(struct device *dev, return sprintf(buf, "0x%08x\n", priv->dcmf_version.dcmf3); } +static ssize_t dcmf0_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); + + if (!priv) + return -ENODEV; + + if (priv->dcmf_status.dcmf0 == INVALID_DCMF_STATUS) + return -EIO; + + return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf0); +} + +static ssize_t dcmf1_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); + + if (!priv) + return -ENODEV; + + if (priv->dcmf_status.dcmf1 == INVALID_DCMF_STATUS) + return -EIO; + + return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf1); +} + +static ssize_t dcmf2_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); + + if (!priv) + return -ENODEV; + + if (priv->dcmf_status.dcmf2 == INVALID_DCMF_STATUS) + return -EIO; + + return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf2); +} + +static ssize_t dcmf3_status_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct stratix10_rsu_priv *priv = dev_get_drvdata(dev); + + if (!priv) + return -ENODEV; + + if (priv->dcmf_status.dcmf3 == INVALID_DCMF_STATUS) + return -EIO; + + return sprintf(buf, "0x%08x\n", priv->dcmf_status.dcmf3); +} static ssize_t reboot_image_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -484,6 +584,10 @@ static DEVICE_ATTR_RO(dcmf0); static DEVICE_ATTR_RO(dcmf1); static DEVICE_ATTR_RO(dcmf2); static DEVICE_ATTR_RO(dcmf3); +static DEVICE_ATTR_RO(dcmf0_status); +static DEVICE_ATTR_RO(dcmf1_status); +static DEVICE_ATTR_RO(dcmf2_status); +static DEVICE_ATTR_RO(dcmf3_status); static DEVICE_ATTR_WO(reboot_image); static DEVICE_ATTR_WO(notify); @@ -500,6 +604,10 @@ static struct attribute *rsu_attrs[] = { &dev_attr_dcmf1.attr, &dev_attr_dcmf2.attr, &dev_attr_dcmf3.attr, + &dev_attr_dcmf0_status.attr, + &dev_attr_dcmf1_status.attr, + &dev_attr_dcmf2_status.attr, + &dev_attr_dcmf3_status.attr, &dev_attr_reboot_image.attr, &dev_attr_notify.attr, NULL @@ -532,6 +640,10 @@ static int stratix10_rsu_probe(struct platform_device *pdev) priv->dcmf_version.dcmf2 = INVALID_DCMF_VERSION; priv->dcmf_version.dcmf3 = INVALID_DCMF_VERSION; priv->max_retry = INVALID_RETRY_COUNTER; + priv->dcmf_status.dcmf0 = INVALID_DCMF_STATUS; + priv->dcmf_status.dcmf1 = INVALID_DCMF_STATUS; + priv->dcmf_status.dcmf2 = INVALID_DCMF_STATUS; + priv->dcmf_status.dcmf3 = INVALID_DCMF_STATUS; mutex_init(&priv->lock); priv->chan = stratix10_svc_request_channel_byname(&priv->client, @@ -561,6 +673,13 @@ static int stratix10_rsu_probe(struct platform_device *pdev) stratix10_svc_free_channel(priv->chan); } + ret = rsu_send_msg(priv, COMMAND_RSU_DCMF_STATUS, + 0, rsu_dcmf_status_callback); + if (ret) { + dev_err(dev, "Error, getting DCMF status %i\n", ret); + stratix10_svc_free_channel(priv->chan); + } + ret = rsu_send_msg(priv, COMMAND_RSU_RETRY, 0, rsu_retry_callback); if (ret) { dev_err(dev, "Error, getting RSU retry %i\n", ret); diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c index 14663f671323..b4081f4d88a3 100644 --- a/drivers/firmware/stratix10-svc.c +++ b/drivers/firmware/stratix10-svc.c @@ -34,12 +34,13 @@ * timeout is set to 30 seconds (30 * 1000) at Intel Stratix10 SoC. */ #define SVC_NUM_DATA_IN_FIFO 32 -#define SVC_NUM_CHANNEL 2 +#define SVC_NUM_CHANNEL 3 #define FPGA_CONFIG_DATA_CLAIM_TIMEOUT_MS 200 #define FPGA_CONFIG_STATUS_TIMEOUT_SEC 30 /* stratix10 service layer clients */ #define STRATIX10_RSU "stratix10-rsu" +#define INTEL_FCS "intel-fcs" typedef void (svc_invoke_fn)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, @@ -53,6 +54,7 @@ struct stratix10_svc_chan; */ struct stratix10_svc { struct platform_device *stratix10_svc_rsu; + struct platform_device *intel_svc_fcs; }; /** @@ -97,8 +99,10 @@ struct stratix10_svc_data_mem { /** * struct stratix10_svc_data - service data structure * @chan: service channel - * @paddr: playload physical address - * @size: playload size + * @paddr: physical address of to be processed payload + * @size: to be processed playload size + * @paddr_output: physical address of processed payload + * @size_output: processed payload size * @command: service command requested by client * @flag: configuration type (full or partial) * @arg: args to be passed via registers and not physically mapped buffers @@ -109,6 +113,8 @@ struct stratix10_svc_data { struct stratix10_svc_chan *chan; phys_addr_t paddr; size_t size; + phys_addr_t paddr_output; + size_t size_output; u32 command; u32 flag; u64 arg[3]; @@ -246,6 +252,7 @@ static void svc_thread_cmd_config_status(struct stratix10_svc_controller *ctrl, { struct arm_smccc_res res; int count_in_sec; + unsigned long a0, a1, a2; cb_data->kaddr1 = NULL; cb_data->kaddr2 = NULL; @@ -254,24 +261,45 @@ static void svc_thread_cmd_config_status(struct stratix10_svc_controller *ctrl, pr_debug("%s: polling config status\n", __func__); + a0 = INTEL_SIP_SMC_FPGA_CONFIG_ISDONE; + a1 = (unsigned long)p_data->paddr; + a2 = (unsigned long)p_data->size; + + if (p_data->command == COMMAND_POLL_SERVICE_STATUS) + a0 = INTEL_SIP_SMC_SERVICE_COMPLETED; + count_in_sec = FPGA_CONFIG_STATUS_TIMEOUT_SEC; while (count_in_sec) { - ctrl->invoke_fn(INTEL_SIP_SMC_FPGA_CONFIG_ISDONE, - 0, 0, 0, 0, 0, 0, 0, &res); + ctrl->invoke_fn(a0, a1, a2, 0, 0, 0, 0, 0, &res); if ((res.a0 == INTEL_SIP_SMC_STATUS_OK) || - (res.a0 == INTEL_SIP_SMC_STATUS_ERROR)) + (res.a0 == INTEL_SIP_SMC_STATUS_ERROR) || + (res.a0 == INTEL_SIP_SMC_STATUS_REJECTED)) break; /* - * configuration is still in progress, wait one second then + * request is still in progress, wait one second then * poll again */ msleep(1000); count_in_sec--; } - if (res.a0 == INTEL_SIP_SMC_STATUS_OK && count_in_sec) + if (!count_in_sec) { + pr_err("%s: poll status timeout\n", __func__); + cb_data->status = BIT(SVC_STATUS_BUSY); + } else if (res.a0 == INTEL_SIP_SMC_STATUS_OK) { cb_data->status = BIT(SVC_STATUS_COMPLETED); + cb_data->kaddr2 = (res.a2) ? + svc_pa_to_va(res.a2) : NULL; + cb_data->kaddr3 = (res.a3) ? &res.a3 : NULL; + } else { + pr_err("%s: poll status error\n", __func__); + cb_data->kaddr1 = &res.a1; + cb_data->kaddr2 = (res.a2) ? + svc_pa_to_va(res.a2) : NULL; + cb_data->kaddr3 = (res.a3) ? &res.a3 : NULL; + cb_data->status = BIT(SVC_STATUS_ERROR); + } p_data->chan->scl->receive_cb(p_data->chan->scl, cb_data); } @@ -296,6 +324,10 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data, case COMMAND_RECONFIG: case COMMAND_RSU_UPDATE: case COMMAND_RSU_NOTIFY: + case COMMAND_FCS_REQUEST_SERVICE: + case COMMAND_FCS_SEND_CERTIFICATE: + case COMMAND_FCS_DATA_ENCRYPTION: + case COMMAND_FCS_DATA_DECRYPTION: cb_data->status = BIT(SVC_STATUS_OK); break; case COMMAND_RECONFIG_DATA_SUBMIT: @@ -306,15 +338,29 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data, break; case COMMAND_RSU_RETRY: case COMMAND_RSU_MAX_RETRY: + case COMMAND_RSU_DCMF_STATUS: case COMMAND_FIRMWARE_VERSION: cb_data->status = BIT(SVC_STATUS_OK); cb_data->kaddr1 = &res.a1; break; + case COMMAND_SMC_SVC_VERSION: + cb_data->status = BIT(SVC_STATUS_OK); + cb_data->kaddr1 = &res.a1; + cb_data->kaddr2 = &res.a2; + break; case COMMAND_RSU_DCMF_VERSION: cb_data->status = BIT(SVC_STATUS_OK); cb_data->kaddr1 = &res.a1; cb_data->kaddr2 = &res.a2; break; + case COMMAND_FCS_RANDOM_NUMBER_GEN: + case COMMAND_FCS_GET_PROVISION_DATA: + case COMMAND_POLL_SERVICE_STATUS: + cb_data->status = BIT(SVC_STATUS_OK); + cb_data->kaddr1 = &res.a1; + cb_data->kaddr2 = svc_pa_to_va(res.a2); + cb_data->kaddr3 = &res.a3; + break; default: pr_warn("it shouldn't happen\n"); break; @@ -341,7 +387,7 @@ static int svc_normal_to_secure_thread(void *data) struct stratix10_svc_data *pdata; struct stratix10_svc_cb_data *cbdata; struct arm_smccc_res res; - unsigned long a0, a1, a2; + unsigned long a0, a1, a2, a3, a4, a5, a6, a7; int ret_fifo = 0; pdata = kmalloc(sizeof(*pdata), GFP_KERNEL); @@ -358,6 +404,11 @@ static int svc_normal_to_secure_thread(void *data) a0 = INTEL_SIP_SMC_FPGA_CONFIG_LOOPBACK; a1 = 0; a2 = 0; + a3 = 0; + a4 = 0; + a5 = 0; + a6 = 0; + a7 = 0; pr_debug("smc_hvc_shm_thread is running\n"); @@ -428,15 +479,74 @@ static int svc_normal_to_secure_thread(void *data) a1 = 0; a2 = 0; break; + + /* for FCS */ + case COMMAND_FCS_DATA_ENCRYPTION: + a0 = INTEL_SIP_SMC_FCS_CRYPTION; + a1 = 1; + a2 = (unsigned long)pdata->paddr; + a3 = (unsigned long)pdata->size; + a4 = (unsigned long)pdata->paddr_output; + a5 = (unsigned long)pdata->size_output; + break; + case COMMAND_FCS_DATA_DECRYPTION: + a0 = INTEL_SIP_SMC_FCS_CRYPTION; + a1 = 0; + a2 = (unsigned long)pdata->paddr; + a3 = (unsigned long)pdata->size; + a4 = (unsigned long)pdata->paddr_output; + a5 = (unsigned long)pdata->size_output; + break; + case COMMAND_FCS_RANDOM_NUMBER_GEN: + a0 = INTEL_SIP_SMC_FCS_RANDOM_NUMBER; + a1 = (unsigned long)pdata->paddr; + a2 = 0; + break; + case COMMAND_FCS_REQUEST_SERVICE: + a0 = INTEL_SIP_SMC_FCS_SERVICE_REQUEST; + a1 = (unsigned long)pdata->paddr; + a2 = (unsigned long)pdata->size; + break; + case COMMAND_FCS_SEND_CERTIFICATE: + a0 = INTEL_SIP_SMC_FCS_SEND_CERTIFICATE; + a1 = (unsigned long)pdata->paddr; + a2 = (unsigned long)pdata->size; + break; + case COMMAND_FCS_GET_PROVISION_DATA: + a0 = INTEL_SIP_SMC_FCS_GET_PROVISION_DATA; + a1 = (unsigned long)pdata->paddr; + a2 = 0; + break; + + /* for polling */ + case COMMAND_POLL_SERVICE_STATUS: + a0 = INTEL_SIP_SMC_SERVICE_COMPLETED; + a1 = (unsigned long)pdata->paddr; + a2 = (unsigned long)pdata->size; + break; + case COMMAND_RSU_DCMF_STATUS: + a0 = INTEL_SIP_SMC_RSU_DCMF_STATUS; + a1 = 0; + a2 = 0; + break; + case COMMAND_SMC_SVC_VERSION: + a0 = INTEL_SIP_SMC_SVC_VERSION; + a1 = 0; + a2 = 0; + break; default: pr_warn("it shouldn't happen\n"); break; } pr_debug("%s: before SMC call -- a0=0x%016x a1=0x%016x", - __func__, (unsigned int)a0, (unsigned int)a1); + __func__, + (unsigned int)a0, + (unsigned int)a1); pr_debug(" a2=0x%016x\n", (unsigned int)a2); - - ctrl->invoke_fn(a0, a1, a2, 0, 0, 0, 0, 0, &res); + pr_debug(" a3=0x%016x\n", (unsigned int)a3); + pr_debug(" a4=0x%016x\n", (unsigned int)a4); + pr_debug(" a5=0x%016x\n", (unsigned int)a5); + ctrl->invoke_fn(a0, a1, a2, a3, a4, a5, a6, a7, &res); pr_debug("%s: after SMC call -- res.a0=0x%016x", __func__, (unsigned int)res.a0); @@ -468,6 +578,7 @@ static int svc_normal_to_secure_thread(void *data) pdata, cbdata); break; case COMMAND_RECONFIG_STATUS: + case COMMAND_POLL_SERVICE_STATUS: svc_thread_cmd_config_status(ctrl, pdata, cbdata); break; @@ -478,14 +589,31 @@ static int svc_normal_to_secure_thread(void *data) break; case INTEL_SIP_SMC_STATUS_REJECTED: pr_debug("%s: STATUS_REJECTED\n", __func__); + /* for FCS */ + switch (pdata->command) { + case COMMAND_FCS_REQUEST_SERVICE: + case COMMAND_FCS_SEND_CERTIFICATE: + case COMMAND_FCS_GET_PROVISION_DATA: + case COMMAND_FCS_DATA_ENCRYPTION: + case COMMAND_FCS_DATA_DECRYPTION: + case COMMAND_FCS_RANDOM_NUMBER_GEN: + cbdata->status = BIT(SVC_STATUS_INVALID_PARAM); + cbdata->kaddr1 = NULL; + cbdata->kaddr2 = NULL; + cbdata->kaddr3 = NULL; + pdata->chan->scl->receive_cb(pdata->chan->scl, + cbdata); + break; + } break; case INTEL_SIP_SMC_STATUS_ERROR: case INTEL_SIP_SMC_RSU_ERROR: pr_err("%s: STATUS_ERROR\n", __func__); cbdata->status = BIT(SVC_STATUS_ERROR); cbdata->kaddr1 = &res.a1; - cbdata->kaddr2 = NULL; - cbdata->kaddr3 = NULL; + cbdata->kaddr2 = (res.a2) ? + svc_pa_to_va(res.a2) : NULL; + cbdata->kaddr3 = (res.a3) ? &res.a3 : NULL; pdata->chan->scl->receive_cb(pdata->chan->scl, cbdata); break; default: @@ -493,12 +621,10 @@ static int svc_normal_to_secure_thread(void *data) /* * be compatible with older version firmware which - * doesn't support RSU notify or retry + * doesn't support newer RSU commands */ - if ((pdata->command == COMMAND_RSU_RETRY) || - (pdata->command == COMMAND_RSU_MAX_RETRY) || - (pdata->command == COMMAND_RSU_NOTIFY) || - (pdata->command == COMMAND_FIRMWARE_VERSION)) { + if ((pdata->command != COMMAND_RSU_UPDATE) && + (pdata->command != COMMAND_RSU_STATUS)) { cbdata->status = BIT(SVC_STATUS_NO_SUPPORT); cbdata->kaddr1 = NULL; @@ -852,8 +978,19 @@ int stratix10_svc_send(struct stratix10_svc_chan *chan, void *msg) list_for_each_entry(p_mem, &svc_data_mem, node) if (p_mem->vaddr == p_msg->payload) { p_data->paddr = p_mem->paddr; + p_data->size = p_msg->payload_length; break; } + if (p_msg->payload_output) { + list_for_each_entry(p_mem, &svc_data_mem, node) + if (p_mem->vaddr == p_msg->payload_output) { + p_data->paddr_output = + p_mem->paddr; + p_data->size_output = + p_msg->payload_length_output; + break; + } + } } p_data->command = p_msg->command; @@ -1036,6 +1173,11 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) chans[1].name = SVC_CLIENT_RSU; spin_lock_init(&chans[1].lock); + chans[2].scl = NULL; + chans[2].ctrl = controller; + chans[2].name = SVC_CLIENT_FCS; + spin_lock_init(&chans[2].lock); + list_add_tail(&controller->node, &svc_ctrl); platform_set_drvdata(pdev, controller); @@ -1054,8 +1196,22 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) } ret = platform_device_add(svc->stratix10_svc_rsu); - if (ret) - goto err_put_device; + if (ret) { + platform_device_put(svc->stratix10_svc_rsu); + return ret; + } + + svc->intel_svc_fcs = platform_device_alloc(INTEL_FCS, 1); + if (!svc->intel_svc_fcs) { + dev_err(dev, "failed to allocate %s device\n", INTEL_FCS); + return -ENOMEM; + } + + ret = platform_device_add(svc->intel_svc_fcs); + if (ret) { + platform_device_put(svc->intel_svc_fcs); + return ret; + } dev_set_drvdata(dev, svc); @@ -1063,8 +1219,6 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) return 0; -err_put_device: - platform_device_put(svc->stratix10_svc_rsu); err_free_kfifo: kfifo_free(&controller->svc_fifo); return ret; @@ -1075,6 +1229,7 @@ static int stratix10_svc_drv_remove(struct platform_device *pdev) struct stratix10_svc *svc = dev_get_drvdata(&pdev->dev); struct stratix10_svc_controller *ctrl = platform_get_drvdata(pdev); + platform_device_unregister(svc->intel_svc_fcs); platform_device_unregister(svc->stratix10_svc_rsu); kfifo_free(&ctrl->svc_fifo); |