diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-07 20:59:32 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-07 20:59:32 +0300 |
commit | 9aa900c8094dba7a60dc805ecec1e9f720744ba1 (patch) | |
tree | 3cc09a579f8ea6d3a182076ba722f7c1648e682d /drivers/firmware | |
parent | f558b8364e19f9222e7976c64e9367f66bab02cc (diff) | |
parent | 05c8a4fc44a916dd897769ca69b42381f9177ec4 (diff) | |
download | linux-9aa900c8094dba7a60dc805ecec1e9f720744ba1.tar.xz |
Merge tag 'char-misc-5.8-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/misc driver patches for 5.8-rc1
Included in here are:
- habanalabs driver updates, loads
- mhi bus driver updates
- extcon driver updates
- clk driver updates (approved by the clock maintainer)
- firmware driver updates
- fpga driver updates
- gnss driver updates
- coresight driver updates
- interconnect driver updates
- parport driver updates (it's still alive!)
- nvmem driver updates
- soundwire driver updates
- visorbus driver updates
- w1 driver updates
- various misc driver updates
In short, loads of different driver subsystem updates along with the
drivers as well.
All have been in linux-next for a while with no reported issues"
* tag 'char-misc-5.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (233 commits)
habanalabs: correctly cast u64 to void*
habanalabs: initialize variable to default value
extcon: arizona: Fix runtime PM imbalance on error
extcon: max14577: Add proper dt-compatible strings
extcon: adc-jack: Fix an error handling path in 'adc_jack_probe()'
extcon: remove redundant assignment to variable idx
w1: omap-hdq: print dev_err if irq flags are not cleared
w1: omap-hdq: fix interrupt handling which did show spurious timeouts
w1: omap-hdq: fix return value to be -1 if there is a timeout
w1: omap-hdq: cleanup to add missing newline for some dev_dbg
/dev/mem: Revoke mappings when a driver claims the region
misc: xilinx-sdfec: convert get_user_pages() --> pin_user_pages()
misc: xilinx-sdfec: cleanup return value in xsdfec_table_write()
misc: xilinx-sdfec: improve get_user_pages_fast() error handling
nvmem: qfprom: remove incorrect write support
habanalabs: handle MMU cache invalidation timeout
habanalabs: don't allow hard reset with open processes
habanalabs: GAUDI does not support soft-reset
habanalabs: add print for soft reset due to event
habanalabs: improve MMU cache invalidation code
...
Diffstat (limited to 'drivers/firmware')
-rw-r--r-- | drivers/firmware/stratix10-rsu.c | 10 | ||||
-rw-r--r-- | drivers/firmware/stratix10-svc.c | 62 | ||||
-rw-r--r-- | drivers/firmware/xilinx/zynqmp-debug.c | 5 | ||||
-rw-r--r-- | drivers/firmware/xilinx/zynqmp.c | 607 |
4 files changed, 535 insertions, 149 deletions
diff --git a/drivers/firmware/stratix10-rsu.c b/drivers/firmware/stratix10-rsu.c index f8533338b018..4379475c99ed 100644 --- a/drivers/firmware/stratix10-rsu.c +++ b/drivers/firmware/stratix10-rsu.c @@ -72,7 +72,7 @@ static void rsu_status_callback(struct stratix10_svc_client *client, struct stratix10_rsu_priv *priv = client->priv; struct arm_smccc_res *res = (struct arm_smccc_res *)data->kaddr1; - if (data->status == BIT(SVC_STATUS_RSU_OK)) { + if (data->status == BIT(SVC_STATUS_OK)) { priv->status.version = FIELD_GET(RSU_VERSION_MASK, res->a2); priv->status.state = FIELD_GET(RSU_STATE_MASK, res->a2); @@ -108,9 +108,9 @@ static void rsu_command_callback(struct stratix10_svc_client *client, { struct stratix10_rsu_priv *priv = client->priv; - if (data->status == BIT(SVC_STATUS_RSU_NO_SUPPORT)) + if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) dev_warn(client->dev, "Secure FW doesn't support notify\n"); - else if (data->status == BIT(SVC_STATUS_RSU_ERROR)) + else if (data->status == BIT(SVC_STATUS_ERROR)) dev_err(client->dev, "Failure, returned status is %lu\n", BIT(data->status)); @@ -133,9 +133,9 @@ static void rsu_retry_callback(struct stratix10_svc_client *client, struct stratix10_rsu_priv *priv = client->priv; unsigned int *counter = (unsigned int *)data->kaddr1; - if (data->status == BIT(SVC_STATUS_RSU_OK)) + if (data->status == BIT(SVC_STATUS_OK)) priv->retry_counter = *counter; - else if (data->status == BIT(SVC_STATUS_RSU_NO_SUPPORT)) + else if (data->status == BIT(SVC_STATUS_NO_SUPPORT)) dev_warn(client->dev, "Secure FW doesn't support retry\n"); else dev_err(client->dev, "Failed to get retry counter %lu\n", diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c index d5f0769f3761..e0db8dbfc9d1 100644 --- a/drivers/firmware/stratix10-svc.c +++ b/drivers/firmware/stratix10-svc.c @@ -214,7 +214,7 @@ static void svc_thread_cmd_data_claim(struct stratix10_svc_controller *ctrl, complete(&ctrl->complete_status); break; } - cb_data->status = BIT(SVC_STATUS_RECONFIG_BUFFER_DONE); + cb_data->status = BIT(SVC_STATUS_BUFFER_DONE); cb_data->kaddr1 = svc_pa_to_va(res.a1); cb_data->kaddr2 = (res.a2) ? svc_pa_to_va(res.a2) : NULL; @@ -227,7 +227,7 @@ static void svc_thread_cmd_data_claim(struct stratix10_svc_controller *ctrl, __func__); } } while (res.a0 == INTEL_SIP_SMC_STATUS_OK || - res.a0 == INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY || + res.a0 == INTEL_SIP_SMC_STATUS_BUSY || wait_for_completion_timeout(&ctrl->complete_status, timeout)); } @@ -250,7 +250,7 @@ static void svc_thread_cmd_config_status(struct stratix10_svc_controller *ctrl, cb_data->kaddr1 = NULL; cb_data->kaddr2 = NULL; cb_data->kaddr3 = NULL; - cb_data->status = BIT(SVC_STATUS_RECONFIG_ERROR); + cb_data->status = BIT(SVC_STATUS_ERROR); pr_debug("%s: polling config status\n", __func__); @@ -259,7 +259,7 @@ static void svc_thread_cmd_config_status(struct stratix10_svc_controller *ctrl, ctrl->invoke_fn(INTEL_SIP_SMC_FPGA_CONFIG_ISDONE, 0, 0, 0, 0, 0, 0, 0, &res); if ((res.a0 == INTEL_SIP_SMC_STATUS_OK) || - (res.a0 == INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR)) + (res.a0 == INTEL_SIP_SMC_STATUS_ERROR)) break; /* @@ -271,7 +271,7 @@ static void svc_thread_cmd_config_status(struct stratix10_svc_controller *ctrl, } if (res.a0 == INTEL_SIP_SMC_STATUS_OK && count_in_sec) - cb_data->status = BIT(SVC_STATUS_RECONFIG_COMPLETED); + cb_data->status = BIT(SVC_STATUS_COMPLETED); p_data->chan->scl->receive_cb(p_data->chan->scl, cb_data); } @@ -294,24 +294,18 @@ static void svc_thread_recv_status_ok(struct stratix10_svc_data *p_data, switch (p_data->command) { case COMMAND_RECONFIG: - cb_data->status = BIT(SVC_STATUS_RECONFIG_REQUEST_OK); + case COMMAND_RSU_UPDATE: + case COMMAND_RSU_NOTIFY: + cb_data->status = BIT(SVC_STATUS_OK); break; case COMMAND_RECONFIG_DATA_SUBMIT: - cb_data->status = BIT(SVC_STATUS_RECONFIG_BUFFER_SUBMITTED); - break; - case COMMAND_NOOP: - cb_data->status = BIT(SVC_STATUS_RECONFIG_BUFFER_SUBMITTED); - cb_data->kaddr1 = svc_pa_to_va(res.a1); + cb_data->status = BIT(SVC_STATUS_BUFFER_SUBMITTED); break; case COMMAND_RECONFIG_STATUS: - cb_data->status = BIT(SVC_STATUS_RECONFIG_COMPLETED); - break; - case COMMAND_RSU_UPDATE: - case COMMAND_RSU_NOTIFY: - cb_data->status = BIT(SVC_STATUS_RSU_OK); + cb_data->status = BIT(SVC_STATUS_COMPLETED); break; case COMMAND_RSU_RETRY: - cb_data->status = BIT(SVC_STATUS_RSU_OK); + cb_data->status = BIT(SVC_STATUS_OK); cb_data->kaddr1 = &res.a1; break; default: @@ -430,9 +424,9 @@ static int svc_normal_to_secure_thread(void *data) if (pdata->command == COMMAND_RSU_STATUS) { if (res.a0 == INTEL_SIP_SMC_RSU_ERROR) - cbdata->status = BIT(SVC_STATUS_RSU_ERROR); + cbdata->status = BIT(SVC_STATUS_ERROR); else - cbdata->status = BIT(SVC_STATUS_RSU_OK); + cbdata->status = BIT(SVC_STATUS_OK); cbdata->kaddr1 = &res; cbdata->kaddr2 = NULL; @@ -445,7 +439,7 @@ static int svc_normal_to_secure_thread(void *data) case INTEL_SIP_SMC_STATUS_OK: svc_thread_recv_status_ok(pdata, cbdata, res); break; - case INTEL_SIP_SMC_FPGA_CONFIG_STATUS_BUSY: + case INTEL_SIP_SMC_STATUS_BUSY: switch (pdata->command) { case COMMAND_RECONFIG_DATA_SUBMIT: svc_thread_cmd_data_claim(ctrl, @@ -460,33 +454,13 @@ static int svc_normal_to_secure_thread(void *data) break; } break; - case INTEL_SIP_SMC_FPGA_CONFIG_STATUS_REJECTED: + case INTEL_SIP_SMC_STATUS_REJECTED: pr_debug("%s: STATUS_REJECTED\n", __func__); break; - case INTEL_SIP_SMC_FPGA_CONFIG_STATUS_ERROR: + case INTEL_SIP_SMC_STATUS_ERROR: case INTEL_SIP_SMC_RSU_ERROR: pr_err("%s: STATUS_ERROR\n", __func__); - switch (pdata->command) { - /* for FPGA mgr */ - case COMMAND_RECONFIG_DATA_CLAIM: - case COMMAND_RECONFIG: - case COMMAND_RECONFIG_DATA_SUBMIT: - case COMMAND_RECONFIG_STATUS: - cbdata->status = - BIT(SVC_STATUS_RECONFIG_ERROR); - break; - - /* for RSU */ - case COMMAND_RSU_STATUS: - case COMMAND_RSU_UPDATE: - case COMMAND_RSU_NOTIFY: - case COMMAND_RSU_RETRY: - cbdata->status = - BIT(SVC_STATUS_RSU_ERROR); - break; - } - - cbdata->status = BIT(SVC_STATUS_RECONFIG_ERROR); + cbdata->status = BIT(SVC_STATUS_ERROR); cbdata->kaddr1 = NULL; cbdata->kaddr2 = NULL; cbdata->kaddr3 = NULL; @@ -502,7 +476,7 @@ static int svc_normal_to_secure_thread(void *data) if ((pdata->command == COMMAND_RSU_RETRY) || (pdata->command == COMMAND_RSU_NOTIFY)) { cbdata->status = - BIT(SVC_STATUS_RSU_NO_SUPPORT); + BIT(SVC_STATUS_NO_SUPPORT); cbdata->kaddr1 = NULL; cbdata->kaddr2 = NULL; cbdata->kaddr3 = NULL; diff --git a/drivers/firmware/xilinx/zynqmp-debug.c b/drivers/firmware/xilinx/zynqmp-debug.c index 43bc6cfdab45..99606b34975e 100644 --- a/drivers/firmware/xilinx/zynqmp-debug.c +++ b/drivers/firmware/xilinx/zynqmp-debug.c @@ -85,14 +85,13 @@ static int get_pm_api_id(char *pm_api_req, u32 *pm_id) static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret) { - const struct zynqmp_eemi_ops *eemi_ops = zynqmp_pm_get_eemi_ops(); u32 pm_api_version; int ret; struct zynqmp_pm_query_data qdata = {0}; switch (pm_id) { case PM_GET_API_VERSION: - ret = eemi_ops->get_api_version(&pm_api_version); + ret = zynqmp_pm_get_api_version(&pm_api_version); sprintf(debugfs_buf, "PM-API Version = %d.%d\n", pm_api_version >> 16, pm_api_version & 0xffff); break; @@ -102,7 +101,7 @@ static int process_api_request(u32 pm_id, u64 *pm_api_arg, u32 *pm_api_ret) qdata.arg2 = pm_api_arg[2]; qdata.arg3 = pm_api_arg[3]; - ret = eemi_ops->query_data(qdata, pm_api_ret); + ret = zynqmp_pm_query_data(qdata, pm_api_ret); if (ret) break; diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c index 41b65164a367..8d1ff2454e2e 100644 --- a/drivers/firmware/xilinx/zynqmp.c +++ b/drivers/firmware/xilinx/zynqmp.c @@ -2,7 +2,7 @@ /* * Xilinx Zynq MPSoC Firmware layer * - * Copyright (C) 2014-2018 Xilinx, Inc. + * Copyright (C) 2014-2020 Xilinx, Inc. * * Michal Simek <michal.simek@xilinx.com> * Davorin Mista <davorin.mista@aggios.com> @@ -24,8 +24,6 @@ #include <linux/firmware/xlnx-zynqmp.h> #include "zynqmp-debug.h" -static const struct zynqmp_eemi_ops *eemi_ops_tbl; - static bool feature_check_enabled; static u32 zynqmp_pm_features[PM_API_MAX]; @@ -219,7 +217,7 @@ static u32 pm_tz_version; * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_get_api_version(u32 *version) +int zynqmp_pm_get_api_version(u32 *version) { u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; @@ -237,6 +235,7 @@ static int zynqmp_pm_get_api_version(u32 *version) return ret; } +EXPORT_SYMBOL_GPL(zynqmp_pm_get_api_version); /** * zynqmp_pm_get_chipid - Get silicon ID registers @@ -246,7 +245,7 @@ static int zynqmp_pm_get_api_version(u32 *version) * Return: Returns the status of the operation and the idcode and version * registers in @idcode and @version. */ -static int zynqmp_pm_get_chipid(u32 *idcode, u32 *version) +int zynqmp_pm_get_chipid(u32 *idcode, u32 *version) { u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; @@ -260,6 +259,7 @@ static int zynqmp_pm_get_chipid(u32 *idcode, u32 *version) return ret; } +EXPORT_SYMBOL_GPL(zynqmp_pm_get_chipid); /** * zynqmp_pm_get_trustzone_version() - Get secure trustzone firmware version @@ -324,7 +324,7 @@ static int get_set_conduit_method(struct device_node *np) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out) +int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out) { int ret; @@ -338,6 +338,7 @@ static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out) */ return qdata.qid == PM_QID_CLOCK_GET_NAME ? 0 : ret; } +EXPORT_SYMBOL_GPL(zynqmp_pm_query_data); /** * zynqmp_pm_clock_enable() - Enable the clock for given id @@ -348,10 +349,11 @@ static int zynqmp_pm_query_data(struct zynqmp_pm_query_data qdata, u32 *out) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_clock_enable(u32 clock_id) +int zynqmp_pm_clock_enable(u32 clock_id) { return zynqmp_pm_invoke_fn(PM_CLOCK_ENABLE, clock_id, 0, 0, 0, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_clock_enable); /** * zynqmp_pm_clock_disable() - Disable the clock for given id @@ -362,10 +364,11 @@ static int zynqmp_pm_clock_enable(u32 clock_id) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_clock_disable(u32 clock_id) +int zynqmp_pm_clock_disable(u32 clock_id) { return zynqmp_pm_invoke_fn(PM_CLOCK_DISABLE, clock_id, 0, 0, 0, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_clock_disable); /** * zynqmp_pm_clock_getstate() - Get the clock state for given id @@ -377,7 +380,7 @@ static int zynqmp_pm_clock_disable(u32 clock_id) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state) +int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state) { u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; @@ -388,6 +391,7 @@ static int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state) return ret; } +EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getstate); /** * zynqmp_pm_clock_setdivider() - Set the clock divider for given id @@ -399,11 +403,12 @@ static int zynqmp_pm_clock_getstate(u32 clock_id, u32 *state) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider) +int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider) { return zynqmp_pm_invoke_fn(PM_CLOCK_SETDIVIDER, clock_id, divider, 0, 0, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setdivider); /** * zynqmp_pm_clock_getdivider() - Get the clock divider for given id @@ -415,7 +420,7 @@ static int zynqmp_pm_clock_setdivider(u32 clock_id, u32 divider) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider) +int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider) { u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; @@ -426,6 +431,7 @@ static int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider) return ret; } +EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getdivider); /** * zynqmp_pm_clock_setrate() - Set the clock rate for given id @@ -436,13 +442,14 @@ static int zynqmp_pm_clock_getdivider(u32 clock_id, u32 *divider) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate) +int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate) { return zynqmp_pm_invoke_fn(PM_CLOCK_SETRATE, clock_id, lower_32_bits(rate), upper_32_bits(rate), 0, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setrate); /** * zynqmp_pm_clock_getrate() - Get the clock rate for given id @@ -454,7 +461,7 @@ static int zynqmp_pm_clock_setrate(u32 clock_id, u64 rate) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate) +int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate) { u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; @@ -465,6 +472,7 @@ static int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate) return ret; } +EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getrate); /** * zynqmp_pm_clock_setparent() - Set the clock parent for given id @@ -475,11 +483,12 @@ static int zynqmp_pm_clock_getrate(u32 clock_id, u64 *rate) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id) +int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id) { return zynqmp_pm_invoke_fn(PM_CLOCK_SETPARENT, clock_id, parent_id, 0, 0, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_clock_setparent); /** * zynqmp_pm_clock_getparent() - Get the clock parent for given id @@ -491,7 +500,7 @@ static int zynqmp_pm_clock_setparent(u32 clock_id, u32 parent_id) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id) +int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id) { u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; @@ -502,48 +511,191 @@ static int zynqmp_pm_clock_getparent(u32 clock_id, u32 *parent_id) return ret; } +EXPORT_SYMBOL_GPL(zynqmp_pm_clock_getparent); /** - * zynqmp_is_valid_ioctl() - Check whether IOCTL ID is valid or not - * @ioctl_id: IOCTL ID + * zynqmp_pm_set_pll_frac_mode() - PM API for set PLL mode + * + * @clk_id: PLL clock ID + * @mode: PLL mode (PLL_MODE_FRAC/PLL_MODE_INT) + * + * This function sets PLL mode * - * Return: 1 if IOCTL is valid else 0 + * Return: Returns status, either success or error+reason */ -static inline int zynqmp_is_valid_ioctl(u32 ioctl_id) +int zynqmp_pm_set_pll_frac_mode(u32 clk_id, u32 mode) { - switch (ioctl_id) { - case IOCTL_SD_DLL_RESET: - case IOCTL_SET_SD_TAPDELAY: - case IOCTL_SET_PLL_FRAC_MODE: - case IOCTL_GET_PLL_FRAC_MODE: - case IOCTL_SET_PLL_FRAC_DATA: - case IOCTL_GET_PLL_FRAC_DATA: - return 1; - default: - return 0; - } + return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_MODE, + clk_id, mode, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_mode); /** - * zynqmp_pm_ioctl() - PM IOCTL API for device control and configs - * @node_id: Node ID of the device - * @ioctl_id: ID of the requested IOCTL - * @arg1: Argument 1 to requested IOCTL call - * @arg2: Argument 2 to requested IOCTL call - * @out: Returned output value + * zynqmp_pm_get_pll_frac_mode() - PM API for get PLL mode + * + * @clk_id: PLL clock ID + * @mode: PLL mode * - * This function calls IOCTL to firmware for device control and configuration. + * This function return current PLL mode * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, - u32 *out) +int zynqmp_pm_get_pll_frac_mode(u32 clk_id, u32 *mode) { - if (!zynqmp_is_valid_ioctl(ioctl_id)) - return -EINVAL; + return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_MODE, + clk_id, 0, mode); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_mode); + +/** + * zynqmp_pm_set_pll_frac_data() - PM API for setting pll fraction data + * + * @clk_id: PLL clock ID + * @data: fraction data + * + * This function sets fraction data. + * It is valid for fraction mode only. + * + * Return: Returns status, either success or error+reason + */ +int zynqmp_pm_set_pll_frac_data(u32 clk_id, u32 data) +{ + return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_PLL_FRAC_DATA, + clk_id, data, NULL); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_set_pll_frac_data); + +/** + * zynqmp_pm_get_pll_frac_data() - PM API for getting pll fraction data + * + * @clk_id: PLL clock ID + * @data: fraction data + * + * This function returns fraction data value. + * + * Return: Returns status, either success or error+reason + */ +int zynqmp_pm_get_pll_frac_data(u32 clk_id, u32 *data) +{ + return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_GET_PLL_FRAC_DATA, + clk_id, 0, data); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_get_pll_frac_data); + +/** + * zynqmp_pm_set_sd_tapdelay() - Set tap delay for the SD device + * + * @node_id Node ID of the device + * @type Type of tap delay to set (input/output) + * @value Value to set fot the tap delay + * + * This function sets input/output tap delay for the SD device. + * + * @return Returns status, either success or error+reason + */ +int zynqmp_pm_set_sd_tapdelay(u32 node_id, u32 type, u32 value) +{ + return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY, + type, value, NULL); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_set_sd_tapdelay); + +/** + * zynqmp_pm_sd_dll_reset() - Reset DLL logic + * + * @node_id Node ID of the device + * @type Reset type + * + * This function resets DLL logic for the SD device. + * + * @return Returns status, either success or error+reason + */ +int zynqmp_pm_sd_dll_reset(u32 node_id, u32 type) +{ + return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, IOCTL_SET_SD_TAPDELAY, + type, 0, NULL); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_sd_dll_reset); + +/** + * zynqmp_pm_write_ggs() - PM API for writing global general storage (ggs) + * @index GGS register index + * @value Register value to be written + * + * This function writes value to GGS register. + * + * @return Returns status, either success or error+reason + */ +int zynqmp_pm_write_ggs(u32 index, u32 value) +{ + return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_GGS, + index, value, NULL); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_write_ggs); + +/** + * zynqmp_pm_write_ggs() - PM API for reading global general storage (ggs) + * @index GGS register index + * @value Register value to be written + * + * This function returns GGS register value. + * + * @return Returns status, either success or error+reason + */ +int zynqmp_pm_read_ggs(u32 index, u32 *value) +{ + return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_GGS, + index, 0, value); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_read_ggs); + +/** + * zynqmp_pm_write_pggs() - PM API for writing persistent global general + * storage (pggs) + * @index PGGS register index + * @value Register value to be written + * + * This function writes value to PGGS register. + * + * @return Returns status, either success or error+reason + */ +int zynqmp_pm_write_pggs(u32 index, u32 value) +{ + return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_WRITE_PGGS, index, value, + NULL); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_write_pggs); + +/** + * zynqmp_pm_write_pggs() - PM API for reading persistent global general + * storage (pggs) + * @index PGGS register index + * @value Register value to be written + * + * This function returns PGGS register value. + * + * @return Returns status, either success or error+reason + */ +int zynqmp_pm_read_pggs(u32 index, u32 *value) +{ + return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_READ_PGGS, index, 0, + value); +} +EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs); - return zynqmp_pm_invoke_fn(PM_IOCTL, node_id, ioctl_id, - arg1, arg2, out); +/** + * zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status + * @value Status value to be written + * + * This function sets healthy bit value to indicate boot health status + * to firmware. + * + * @return Returns status, either success or error+reason + */ +int zynqmp_pm_set_boot_health_status(u32 value) +{ + return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_BOOT_HEALTH_STATUS, + value, 0, NULL); } /** @@ -554,12 +706,13 @@ static int zynqmp_pm_ioctl(u32 node_id, u32 ioctl_id, u32 arg1, u32 arg2, * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset, - const enum zynqmp_pm_reset_action assert_flag) +int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset, + const enum zynqmp_pm_reset_action assert_flag) { return zynqmp_pm_invoke_fn(PM_RESET_ASSERT, reset, assert_flag, 0, 0, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_reset_assert); /** * zynqmp_pm_reset_get_status - Get status of the reset @@ -568,8 +721,7 @@ static int zynqmp_pm_reset_assert(const enum zynqmp_pm_reset reset, * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, - u32 *status) +int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, u32 *status) { u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; @@ -583,6 +735,7 @@ static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, return ret; } +EXPORT_SYMBOL_GPL(zynqmp_pm_reset_get_status); /** * zynqmp_pm_fpga_load - Perform the fpga load @@ -597,12 +750,12 @@ static int zynqmp_pm_reset_get_status(const enum zynqmp_pm_reset reset, * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_fpga_load(const u64 address, const u32 size, - const u32 flags) +int zynqmp_pm_fpga_load(const u64 address, const u32 size, const u32 flags) { return zynqmp_pm_invoke_fn(PM_FPGA_LOAD, lower_32_bits(address), upper_32_bits(address), size, flags, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_load); /** * zynqmp_pm_fpga_get_status - Read value from PCAP status register @@ -613,7 +766,7 @@ static int zynqmp_pm_fpga_load(const u64 address, const u32 size, * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_fpga_get_status(u32 *value) +int zynqmp_pm_fpga_get_status(u32 *value) { u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; @@ -626,6 +779,7 @@ static int zynqmp_pm_fpga_get_status(u32 *value) return ret; } +EXPORT_SYMBOL_GPL(zynqmp_pm_fpga_get_status); /** * zynqmp_pm_init_finalize() - PM call to inform firmware that the caller @@ -636,10 +790,11 @@ static int zynqmp_pm_fpga_get_status(u32 *value) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_init_finalize(void) +int zynqmp_pm_init_finalize(void) { return zynqmp_pm_invoke_fn(PM_PM_INIT_FINALIZE, 0, 0, 0, 0, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_init_finalize); /** * zynqmp_pm_set_suspend_mode() - Set system suspend mode @@ -649,10 +804,11 @@ static int zynqmp_pm_init_finalize(void) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_set_suspend_mode(u32 mode) +int zynqmp_pm_set_suspend_mode(u32 mode) { return zynqmp_pm_invoke_fn(PM_SET_SUSPEND_MODE, mode, 0, 0, 0, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_set_suspend_mode); /** * zynqmp_pm_request_node() - Request a node with specific capabilities @@ -666,13 +822,13 @@ static int zynqmp_pm_set_suspend_mode(u32 mode) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_request_node(const u32 node, const u32 capabilities, - const u32 qos, - const enum zynqmp_pm_request_ack ack) +int zynqmp_pm_request_node(const u32 node, const u32 capabilities, + const u32 qos, const enum zynqmp_pm_request_ack ack) { return zynqmp_pm_invoke_fn(PM_REQUEST_NODE, node, capabilities, qos, ack, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_request_node); /** * zynqmp_pm_release_node() - Release a node @@ -684,10 +840,11 @@ static int zynqmp_pm_request_node(const u32 node, const u32 capabilities, * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_release_node(const u32 node) +int zynqmp_pm_release_node(const u32 node) { return zynqmp_pm_invoke_fn(PM_RELEASE_NODE, node, 0, 0, 0, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_release_node); /** * zynqmp_pm_set_requirement() - PM call to set requirement for PM slaves @@ -701,13 +858,14 @@ static int zynqmp_pm_release_node(const u32 node) * * Return: Returns status, either success or error+reason */ -static int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities, - const u32 qos, - const enum zynqmp_pm_request_ack ack) +int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities, + const u32 qos, + const enum zynqmp_pm_request_ack ack) { return zynqmp_pm_invoke_fn(PM_SET_REQUIREMENT, node, capabilities, qos, ack, NULL); } +EXPORT_SYMBOL_GPL(zynqmp_pm_set_requirement); /** * zynqmp_pm_aes - Access AES hardware to encrypt/decrypt the data using @@ -717,7 +875,7 @@ static int zynqmp_pm_set_requirement(const u32 node, const u32 capabilities, * * Return: Returns status, either success or error code. */ -static int zynqmp_pm_aes_engine(const u64 address, u32 *out) +int zynqmp_pm_aes_engine(const u64 address, u32 *out) { u32 ret_payload[PAYLOAD_ARG_CNT]; int ret; @@ -732,47 +890,304 @@ static int zynqmp_pm_aes_engine(const u64 address, u32 *out) return ret; } +EXPORT_SYMBOL_GPL(zynqmp_pm_aes_engine); -static const struct zynqmp_eemi_ops eemi_ops = { - .get_api_version = zynqmp_pm_get_api_version, - .get_chipid = zynqmp_pm_get_chipid, - .query_data = zynqmp_pm_query_data, - .clock_enable = zynqmp_pm_clock_enable, - .clock_disable = zynqmp_pm_clock_disable, - .clock_getstate = zynqmp_pm_clock_getstate, - .clock_setdivider = zynqmp_pm_clock_setdivider, - .clock_getdivider = zynqmp_pm_clock_getdivider, - .clock_setrate = zynqmp_pm_clock_setrate, - .clock_getrate = zynqmp_pm_clock_getrate, - .clock_setparent = zynqmp_pm_clock_setparent, - .clock_getparent = zynqmp_pm_clock_getparent, - .ioctl = zynqmp_pm_ioctl, - .reset_assert = zynqmp_pm_reset_assert, - .reset_get_status = zynqmp_pm_reset_get_status, - .init_finalize = zynqmp_pm_init_finalize, - .set_suspend_mode = zynqmp_pm_set_suspend_mode, - .request_node = zynqmp_pm_request_node, - .release_node = zynqmp_pm_release_node, - .set_requirement = zynqmp_pm_set_requirement, - .fpga_load = zynqmp_pm_fpga_load, - .fpga_get_status = zynqmp_pm_fpga_get_status, - .aes = zynqmp_pm_aes_engine, +/** + * zynqmp_pm_system_shutdown - PM call to request a system shutdown or restart + * @type: Shutdown or restart? 0 for shutdown, 1 for restart + * @subtype: Specifies which system should be restarted or shut down + * + * Return: Returns status, either success or error+reason + */ +int zynqmp_pm_system_shutdown(const u32 type, const u32 subtype) +{ + return zynqmp_pm_invoke_fn(PM_SYSTEM_SHUTDOWN, type, subtype, + 0, 0, NULL); +} + +/** + * struct zynqmp_pm_shutdown_scope - Struct for shutdown scope + * @subtype: Shutdown subtype + * @name: Matching string for scope argument + * + * This struct encapsulates mapping between shutdown scope ID and string. + */ +struct zynqmp_pm_shutdown_scope { + const enum zynqmp_pm_shutdown_subtype subtype; + const char *name; +}; + +static struct zynqmp_pm_shutdown_scope shutdown_scopes[] = { + [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM] = { + .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SUBSYSTEM, + .name = "subsystem", + }, + [ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY] = { + .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_PS_ONLY, + .name = "ps_only", + }, + [ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM] = { + .subtype = ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM, + .name = "system", + }, }; +static struct zynqmp_pm_shutdown_scope *selected_scope = + &shutdown_scopes[ZYNQMP_PM_SHUTDOWN_SUBTYPE_SYSTEM]; + /** - * zynqmp_pm_get_eemi_ops - Get eemi ops functions + * zynqmp_pm_is_shutdown_scope_valid - Check if shutdown scope string is valid + * @scope_string: Shutdown scope string * - * Return: Pointer of eemi_ops structure + * Return: Return pointer to matching shutdown scope struct from + * array of available options in system if string is valid, + * otherwise returns NULL. */ -const struct zynqmp_eemi_ops *zynqmp_pm_get_eemi_ops(void) +static struct zynqmp_pm_shutdown_scope* + zynqmp_pm_is_shutdown_scope_valid(const char *scope_string) +{ + int count; + + for (count = 0; count < ARRAY_SIZE(shutdown_scopes); count++) + if (sysfs_streq(scope_string, shutdown_scopes[count].name)) + return &shutdown_scopes[count]; + + return NULL; +} + +static ssize_t shutdown_scope_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(shutdown_scopes); i++) { + if (&shutdown_scopes[i] == selected_scope) { + strcat(buf, "["); + strcat(buf, shutdown_scopes[i].name); + strcat(buf, "]"); + } else { + strcat(buf, shutdown_scopes[i].name); + } + strcat(buf, " "); + } + strcat(buf, "\n"); + + return strlen(buf); +} + +static ssize_t shutdown_scope_store(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + struct zynqmp_pm_shutdown_scope *scope; + + scope = zynqmp_pm_is_shutdown_scope_valid(buf); + if (!scope) + return -EINVAL; + + ret = zynqmp_pm_system_shutdown(ZYNQMP_PM_SHUTDOWN_TYPE_SETSCOPE_ONLY, + scope->subtype); + if (ret) { + pr_err("unable to set shutdown scope %s\n", buf); + return ret; + } + + selected_scope = scope; + + return count; +} + +static DEVICE_ATTR_RW(shutdown_scope); + +static ssize_t health_status_store(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret; + unsigned int value; + + ret = kstrtouint(buf, 10, &value); + if (ret) + return ret; + + ret = zynqmp_pm_set_boot_health_status(value); + if (ret) { + dev_err(device, "unable to set healthy bit value to %u\n", + value); + return ret; + } + + return count; +} + +static DEVICE_ATTR_WO(health_status); + +static ssize_t ggs_show(struct device *device, + struct device_attribute *attr, + char *buf, + u32 reg) +{ + int ret; + u32 ret_payload[PAYLOAD_ARG_CNT]; + + ret = zynqmp_pm_read_ggs(reg, ret_payload); + if (ret) + return ret; + + return sprintf(buf, "0x%x\n", ret_payload[1]); +} + +static ssize_t ggs_store(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count, + u32 reg) +{ + long value; + int ret; + + if (reg >= GSS_NUM_REGS) + return -EINVAL; + + ret = kstrtol(buf, 16, &value); + if (ret) { + count = -EFAULT; + goto err; + } + + ret = zynqmp_pm_write_ggs(reg, value); + if (ret) + count = -EFAULT; +err: + return count; +} + +/* GGS register show functions */ +#define GGS0_SHOW(N) \ + ssize_t ggs##N##_show(struct device *device, \ + struct device_attribute *attr, \ + char *buf) \ + { \ + return ggs_show(device, attr, buf, N); \ + } + +static GGS0_SHOW(0); +static GGS0_SHOW(1); +static GGS0_SHOW(2); +static GGS0_SHOW(3); + +/* GGS register store function */ +#define GGS0_STORE(N) \ + ssize_t ggs##N##_store(struct device *device, \ + struct device_attribute *attr, \ + const char *buf, \ + size_t count) \ + { \ + return ggs_store(device, attr, buf, count, N); \ + } + +static GGS0_STORE(0); +static GGS0_STORE(1); +static GGS0_STORE(2); +static GGS0_STORE(3); + +static ssize_t pggs_show(struct device *device, + struct device_attribute *attr, + char *buf, + u32 reg) +{ + int ret; + u32 ret_payload[PAYLOAD_ARG_CNT]; + + ret = zynqmp_pm_read_pggs(reg, ret_payload); + if (ret) + return ret; + + return sprintf(buf, "0x%x\n", ret_payload[1]); +} + +static ssize_t pggs_store(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count, + u32 reg) { - if (eemi_ops_tbl) - return eemi_ops_tbl; - else - return ERR_PTR(-EPROBE_DEFER); + long value; + int ret; + + if (reg >= GSS_NUM_REGS) + return -EINVAL; + ret = kstrtol(buf, 16, &value); + if (ret) { + count = -EFAULT; + goto err; + } + + ret = zynqmp_pm_write_pggs(reg, value); + if (ret) + count = -EFAULT; + +err: + return count; } -EXPORT_SYMBOL_GPL(zynqmp_pm_get_eemi_ops); + +#define PGGS0_SHOW(N) \ + ssize_t pggs##N##_show(struct device *device, \ + struct device_attribute *attr, \ + char *buf) \ + { \ + return pggs_show(device, attr, buf, N); \ + } + +#define PGGS0_STORE(N) \ + ssize_t pggs##N##_store(struct device *device, \ + struct device_attribute *attr, \ + const char *buf, \ + size_t count) \ + { \ + return pggs_store(device, attr, buf, count, N); \ + } + +/* PGGS register show functions */ +static PGGS0_SHOW(0); +static PGGS0_SHOW(1); +static PGGS0_SHOW(2); +static PGGS0_SHOW(3); + +/* PGGS register store functions */ +static PGGS0_STORE(0); +static PGGS0_STORE(1); +static PGGS0_STORE(2); +static PGGS0_STORE(3); + +/* GGS register attributes */ +static DEVICE_ATTR_RW(ggs0); +static DEVICE_ATTR_RW(ggs1); +static DEVICE_ATTR_RW(ggs2); +static DEVICE_ATTR_RW(ggs3); + +/* PGGS register attributes */ +static DEVICE_ATTR_RW(pggs0); +static DEVICE_ATTR_RW(pggs1); +static DEVICE_ATTR_RW(pggs2); +static DEVICE_ATTR_RW(pggs3); + +static struct attribute *zynqmp_firmware_attrs[] = { + &dev_attr_ggs0.attr, + &dev_attr_ggs1.attr, + &dev_attr_ggs2.attr, + &dev_attr_ggs3.attr, + &dev_attr_pggs0.attr, + &dev_attr_pggs1.attr, + &dev_attr_pggs2.attr, + &dev_attr_pggs3.attr, + &dev_attr_shutdown_scope.attr, + &dev_attr_health_status.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(zynqmp_firmware); static int zynqmp_firmware_probe(struct platform_device *pdev) { @@ -820,11 +1235,6 @@ static int zynqmp_firmware_probe(struct platform_device *pdev) pr_info("%s Trustzone version v%d.%d\n", __func__, pm_tz_version >> 16, pm_tz_version & 0xFFFF); - /* Assign eemi_ops_table */ - eemi_ops_tbl = &eemi_ops; - - zynqmp_pm_api_debugfs_init(); - ret = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_NONE, firmware_devs, ARRAY_SIZE(firmware_devs), NULL, 0, NULL); if (ret) { @@ -832,6 +1242,8 @@ static int zynqmp_firmware_probe(struct platform_device *pdev) return ret; } + zynqmp_pm_api_debugfs_init(); + return of_platform_populate(dev->of_node, NULL, NULL, dev); } @@ -854,6 +1266,7 @@ static struct platform_driver zynqmp_firmware_driver = { .driver = { .name = "zynqmp_firmware", .of_match_table = zynqmp_firmware_of_match, + .dev_groups = zynqmp_firmware_groups, }, .probe = zynqmp_firmware_probe, .remove = zynqmp_firmware_remove, |