From: Rajan Vaja Date: Wed, 17 Jan 2018 10:39:25 +0000 (-0800) Subject: zynqmp: pm: Add clock control EEMI API and ioctl functions X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=caae497dfcdc562accaa2bf92d01b5a0ece4ed66;p=project%2Fbcm63xx%2Fatf.git zynqmp: pm: Add clock control EEMI API and ioctl functions These are empty functions with no logic right now. Code will be added in subsequent commits. Signed-off-by: Rajan Vaja Signed-off-by: Jolly Shah --- diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index 2abcd288..e49a9cdf 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -79,6 +79,7 @@ BL31_SOURCES += drivers/arm/cci/cci.c \ plat/xilinx/zynqmp/pm_service/pm_api_sys.c \ plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c \ plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c \ + plat/xilinx/zynqmp/pm_service/pm_api_clock.c \ plat/xilinx/zynqmp/pm_service/pm_ipi.c \ plat/xilinx/zynqmp/pm_service/pm_client.c \ plat/xilinx/zynqmp/ipi_mailbox_service/ipi_mailbox_svc.c diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c new file mode 100644 index 00000000..4096a817 --- /dev/null +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ZynqMP system level PM-API functions for clock control. + */ + +#include +#include +#include +#include +#include "pm_api_clock.h" +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_common.h" +#include "pm_ipi.h" + +#define CLK_NODE_MAX 6 + +/** + * struct pm_clock_node - Clock topology node information + * @type: Topology type (mux/div1/div2/gate/pll/fixed factor) + * @offset: Offset in control register + * @width: Width of the specific type in control register + * @clkflags: Clk specific flags + * @typeflags: Type specific flags + * @mult: Multiplier for fixed factor + * @div: Divisor for fixed factor + */ +struct pm_clock_node { + uint16_t clkflags; + uint16_t typeflags; + uint8_t type; + uint8_t offset; + uint8_t width; + uint8_t mult:4; + uint8_t div:4; +}; + +/** + * struct pm_clock - Clock structure + * @name: Clock name + * @control_reg: Control register address + * @status_reg: Status register address + * @parents: Parents for first clock node. Lower byte indicates parent + * clock id and upper byte indicate flags for that id. + * pm_clock_node: Clock nodes + */ +struct pm_clock { + char name[CLK_NAME_LEN]; + uint8_t num_nodes; + unsigned int control_reg; + unsigned int status_reg; + int32_t (*parents)[]; + struct pm_clock_node(*nodes)[]; +}; + +/* Clock array containing clock informaton */ +struct pm_clock clocks[] = {0}; + +/** + * pm_api_clock_get_name() - PM call to request a clock's name + * @clock_id Clock ID + * @name Name of clock (max 16 bytes) + * + * This function is used by master to get nmae of clock specified + * by given clock ID. + * + * @return Returns success. In case of error, name data is 0. + */ +enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_get_topology() - PM call to request a clock's topology + * @clock_id Clock ID + * @index Topology index for next toplogy node + * @topology Buffer to store nodes in topology and flags + * + * This function is used by master to get topology information for the + * clock specified by given clock ID. Each response would return 3 + * topology nodes. To get next nodes, caller needs to call this API with + * index of next node. Index starts from 0. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id, + unsigned int index, + uint32_t *topology) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_get_fixedfactor_params() - PM call to request a clock's fixed + * factor parameters for fixed clock + * @clock_id Clock ID + * @mul Multiplication value + * @div Divisor value + * + * This function is used by master to get fixed factor parameers for the + * fixed clock. This API is application only for the fixed clock. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clock_get_fixedfactor_params(unsigned int clock_id, + uint32_t *mul, + uint32_t *div) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_get_parents() - PM call to request a clock's first 3 parents + * @clock_id Clock ID + * @index Index of next parent + * @parents Parents of the given clock + * + * This function is used by master to get clock's parents information. + * This API will return 3 parents with a single response. To get other + * parents, master should call same API in loop with new parent index + * till error is returned. + * + * E.g First call should have index 0 which will return parents 0, 1 and + * 2. Next call, index should be 3 which will return parent 3,4 and 5 and + * so on. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id, + unsigned int index, + uint32_t *parents) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_get_attributes() - PM call to request a clock's attributes + * @clock_id Clock ID + * @attr Clock attributes + * + * This function is used by master to get clock's attributes + * (e.g. valid, clock type, etc). + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id, + uint32_t *attr) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_enable() - Enable the clock for given id + * @clock_id: Id of the clock to be enabled + * + * This function is used by master to enable the clock + * including peripherals and PLL clocks. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_api_clock_enable(unsigned int clock_id) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_disable - Disable the clock for given id + * @clock_id Id of the clock to be disable + * + * This function is used by master to disable the clock + * including peripherals and PLL clocks. + * + * Return: Returns status, either success or error+reason. + */ + +enum pm_ret_status pm_api_clock_disable(unsigned int clock_id) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_getstate - Get the clock state for given id + * @clock_id Id of the clock to be queried + * @state 1/0 (Enabled/Disabled) + * + * This function is used by master to get the state of clock + * including peripherals and PLL clocks. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_api_clock_getstate(unsigned int clock_id, + unsigned int *state) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_setdivider - Set the clock divider for given id + * @clock_id Id of the clock + * @divider Divider value + * + * This function is used by master to set divider for any clock + * to achieve desired rate. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_api_clock_setdivider(unsigned int clock_id, + unsigned int divider) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_getdivider - Get the clock divider for given id + * @clock_id Id of the clock + * @divider Divider value + * + * This function is used by master to get divider values + * for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_api_clock_getdivider(unsigned int clock_id, + unsigned int *divider) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_setrate - Set the clock rate for given id + * @clock_id Id of the clock + * @rate Rate value in hz + * + * This function is used by master to set rate for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_api_clock_setrate(unsigned int clock_id, + uint64_t rate) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_getrate - Get the clock rate for given id + * @clock_id Id of the clock + * @rate rate value in hz + * + * This function is used by master to get rate + * for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_api_clock_getrate(unsigned int clock_id, + uint64_t *rate) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_setparent - Set the clock parent for given id + * @clock_id Id of the clock + * @parent_id parent id + * + * This function is used by master to set parent for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_api_clock_setparent(unsigned int clock_id, + unsigned int parent_idx) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clock_getparent - Get the clock parent for given id + * @clock_id Id of the clock + * @parent_id parent id + * + * This function is used by master to get parent index + * for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_api_clock_getparent(unsigned int clock_id, + unsigned int *parent_idx) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clk_set_pll_mode() - Set PLL mode + * @pll PLL id + * @mode Mode fraction/integar + * + * This function sets PLL mode. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clk_set_pll_mode(unsigned int pll, + unsigned int mode) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_ioctl_get_pll_mode() - Get PLL mode + * @pll PLL id + * @mode Mode fraction/integar + * + * This function returns current PLL mode. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clk_get_pll_mode(unsigned int pll, + unsigned int *mode) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clk_set_pll_frac_data() - Set PLL fraction data + * @pll PLL id + * @data fraction data + * + * This function sets fraction data. It is valid for fraction + * mode only. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clk_set_pll_frac_data(unsigned int pll, + unsigned int data) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} + +/** + * pm_api_clk_get_pll_frac_data() - Get PLL fraction data + * @pll PLL id + * @data fraction data + * + * This function returns fraction data value. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_api_clk_get_pll_frac_data(unsigned int pll, + unsigned int *data) +{ + return PM_RET_ERROR_NOTSUPPORTED; +} diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h new file mode 100644 index 00000000..2e7260e1 --- /dev/null +++ b/plat/xilinx/zynqmp/pm_service/pm_api_clock.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * ZynqMP system level PM-API functions for clock control. + */ + +#ifndef _PM_API_CLOCK_H_ +#define _PM_API_CLOCK_H_ + +#include "pm_common.h" + +#define CLK_NAME_LEN 15 + +enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name); +enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id, + unsigned int index, + uint32_t *topology); +enum pm_ret_status pm_api_clock_get_fixedfactor_params(unsigned int clock_id, + uint32_t *mul, + uint32_t *div); +enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id, + unsigned int index, + uint32_t *parents); +enum pm_ret_status pm_api_clock_get_attributes(unsigned int clock_id, + uint32_t *attr); +enum pm_ret_status pm_api_clock_enable(unsigned int clock_id); +enum pm_ret_status pm_api_clock_disable(unsigned int clock_id); +enum pm_ret_status pm_api_clock_getstate(unsigned int clock_id, + unsigned int *state); +enum pm_ret_status pm_api_clock_setdivider(unsigned int clock_id, + unsigned int divider); +enum pm_ret_status pm_api_clock_getdivider(unsigned int clock_id, + unsigned int *divider); +enum pm_ret_status pm_api_clock_setrate(unsigned int clock_id, + uint64_t rate); +enum pm_ret_status pm_api_clock_getrate(unsigned int clock_id, + uint64_t *rate); +enum pm_ret_status pm_api_clock_setparent(unsigned int clock_id, + unsigned int parent_idx); +enum pm_ret_status pm_api_clock_getparent(unsigned int clock_id, + unsigned int *parent_idx); +enum pm_ret_status pm_api_clk_set_pll_mode(unsigned int pll, + unsigned int mode); +enum pm_ret_status pm_api_clk_get_pll_mode(unsigned int pll, + unsigned int *mode); +enum pm_ret_status pm_api_clk_set_pll_frac_data(unsigned int pll, + unsigned int data); +enum pm_ret_status pm_api_clk_get_pll_frac_data(unsigned int pll, + unsigned int *data); +#endif /* _PM_API_CLOCK_H_ */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c index c881d124..7634b8c8 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c @@ -12,6 +12,7 @@ #include #include #include +#include "pm_api_clock.h" #include "pm_api_ioctl.h" #include "pm_api_sys.h" #include "pm_client.h" @@ -329,6 +330,71 @@ reset_release: return ret; } +/** + * pm_ioctl_set_pll_frac_mode() - Ioctl function for + * setting pll mode + * @pll PLL id + * @mode Mode fraction/integar + * + * This function sets PLL mode + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_set_pll_frac_mode + (unsigned int pll, unsigned int mode) +{ + return pm_api_clk_set_pll_mode(pll, mode); +} + +/** + * pm_ioctl_get_pll_frac_mode() - Ioctl function for + * getting pll mode + * @pll PLL id + * @mode Mode fraction/integar + * + * This function return current PLL mode + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_get_pll_frac_mode + (unsigned int pll, unsigned int *mode) +{ + return pm_api_clk_get_pll_mode(pll, mode); +} + +/** + * pm_ioctl_set_pll_frac_data() - Ioctl function for + * setting pll fraction data + * @pll PLL id + * @data fraction data + * + * This function sets fraction data. + * It is valid for fraction mode only. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_set_pll_frac_data + (unsigned int pll, unsigned int data) +{ + return pm_api_clk_set_pll_frac_data(pll, data); +} + +/** + * pm_ioctl_get_pll_frac_data() - Ioctl function for + * getting pll fraction data + * @pll PLL id + * @data fraction data + * + * This function returns fraction data value. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_ioctl_get_pll_frac_data + (unsigned int pll, unsigned int *data) +{ + return pm_api_clk_get_pll_frac_data(pll, data); +} + /** * pm_api_ioctl() - PM IOCTL API for device control and configs * @node_id Node ID of the device @@ -374,6 +440,18 @@ enum pm_ret_status pm_api_ioctl(enum pm_node_id nid, case IOCTL_SET_SD_TAPDELAY: ret = pm_ioctl_sd_set_tapdelay(nid, arg1, arg2); break; + case IOCTL_SET_PLL_FRAC_MODE: + ret = pm_ioctl_set_pll_frac_mode(arg1, arg2); + break; + case IOCTL_GET_PLL_FRAC_MODE: + ret = pm_ioctl_get_pll_frac_mode(arg1, value); + break; + case IOCTL_SET_PLL_FRAC_DATA: + ret = pm_ioctl_set_pll_frac_data(arg1, arg2); + break; + case IOCTL_GET_PLL_FRAC_DATA: + ret = pm_ioctl_get_pll_frac_data(arg1, value); + break; default: ret = PM_RET_ERROR_NOTSUPPORTED; } diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h index a7f14a47..b290574c 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h @@ -22,6 +22,11 @@ enum pm_ioctl_id { IOCTL_SET_SGMII_MODE, IOCTL_SD_DLL_RESET, IOCTL_SET_SD_TAPDELAY, + /* Ioctl for clock driver */ + IOCTL_SET_PLL_FRAC_MODE, + IOCTL_GET_PLL_FRAC_MODE, + IOCTL_SET_PLL_FRAC_DATA, + IOCTL_GET_PLL_FRAC_DATA, }; enum rpu_oper_mode { diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c index be243717..fcc0c6e7 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -11,6 +11,7 @@ #include #include +#include "pm_api_clock.h" #include "pm_api_ioctl.h" #include "pm_api_pinctrl.h" #include "pm_api_sys.h" @@ -658,3 +659,285 @@ enum pm_ret_status pm_ioctl(enum pm_node_id nid, { return pm_api_ioctl(nid, ioctl_id, arg1, arg2, value); } + +/** + * pm_clock_get_name() - PM call to request a clock's name + * @clock_id Clock ID + * @name Name of clock (max 16 bytes) + * + * This function is used by master to get nmae of clock specified + * by given clock ID. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_clock_get_name(unsigned int clock_id, char *name) +{ + return pm_api_clock_get_name(clock_id, name); +} + +/** + * pm_clock_get_topology() - PM call to request a clock's topology + * @clock_id Clock ID + * @index Topology index for next toplogy node + * @topology Buffer to store nodes in topology and flags + * + * This function is used by master to get topology information for the + * clock specified by given clock ID. Each response would return 3 + * topology nodes. To get next nodes, caller needs to call this API with + * index of next node. Index starts from 0. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_clock_get_topology(unsigned int clock_id, + unsigned int index, + uint32_t *topology) +{ + return pm_api_clock_get_topology(clock_id, index, topology); +} + +/** + * pm_clock_get_fixedfactor_params() - PM call to request a clock's fixed factor + * parameters for fixed clock + * @clock_id Clock ID + * @mul Multiplication value + * @div Divisor value + * + * This function is used by master to get fixed factor parameers for the + * fixed clock. This API is application only for the fixed clock. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_clock_get_fixedfactor_params(unsigned int clock_id, + uint32_t *mul, + uint32_t *div) +{ + return pm_api_clock_get_fixedfactor_params(clock_id, mul, div); +} + +/** + * pm_clock_get_parents() - PM call to request a clock's first 3 parents + * @clock_id Clock ID + * @index Index of next parent + * @parents Parents of the given clock + * + * This function is used by master to get clock's parents information. + * This API will return 3 parents with a single response. To get other + * parents, master should call same API in loop with new parent index + * till error is returned. + * + * E.g First call should have index 0 which will return parents 0, 1 and + * 2. Next call, index should be 3 which will return parent 3,4 and 5 and + * so on. + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_clock_get_parents(unsigned int clock_id, + unsigned int index, + uint32_t *parents) +{ + return pm_api_clock_get_parents(clock_id, index, parents); +} + +/** + * pm_clock_get_attributes() - PM call to request a clock's attributes + * @clock_id Clock ID + * @attr Clock attributes + * + * This function is used by master to get clock's attributes + * (e.g. valid, clock type, etc). + * + * @return Returns status, either success or error+reason + */ +static enum pm_ret_status pm_clock_get_attributes(unsigned int clock_id, + uint32_t *attr) +{ + return pm_api_clock_get_attributes(clock_id, attr); +} + +/** + * pm_clock_enable() - Enable the clock for given id + * @clock_id: Id of the clock to be enabled + * + * This function is used by master to enable the clock + * including peripherals and PLL clocks. + * + * Return: Returns status, either success or error+reason. + */ + +enum pm_ret_status pm_clock_enable(unsigned int clock_id) +{ + return pm_api_clock_enable(clock_id); +} + +/** + * pm_clock_disable - Disable the clock for given id + * @clock_id: Id of the clock to be disable + * + * This function is used by master to disable the clock + * including peripherals and PLL clocks. + * + * Return: Returns status, either success or error+reason. + */ + +enum pm_ret_status pm_clock_disable(unsigned int clock_id) +{ + return pm_api_clock_disable(clock_id); +} + +/** + * pm_clock_getstate - Get the clock state for given id + * @clock_id: Id of the clock to be queried + * @state: 1/0 (Enabled/Disabled) + * + * This function is used by master to get the state of clock + * including peripherals and PLL clocks. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_getstate(unsigned int clock_id, + unsigned int *state) +{ + return pm_api_clock_getstate(clock_id, state); +} + +/** + * pm_clock_setdivider - Set the clock divider for given id + * @clock_id: Id of the clock + * @divider: divider value + * + * This function is used by master to set divider for any clock + * to achieve desired rate. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_setdivider(unsigned int clock_id, + unsigned int divider) +{ + return pm_api_clock_setdivider(clock_id, divider); +} + +/** + * pm_clock_getdivider - Get the clock divider for given id + * @clock_id: Id of the clock + * @divider: divider value + * + * This function is used by master to get divider values + * for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_getdivider(unsigned int clock_id, + unsigned int *divider) +{ + return pm_api_clock_getdivider(clock_id, divider); +} + +/** + * pm_clock_setrate - Set the clock rate for given id + * @clock_id: Id of the clock + * @rate: rate value in hz + * + * This function is used by master to set rate for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_setrate(unsigned int clock_id, + uint64_t rate) +{ + return pm_api_clock_setrate(clock_id, rate); +} + +/** + * pm_clock_getrate - Get the clock rate for given id + * @clock_id: Id of the clock + * @rate: rate value in hz + * + * This function is used by master to get rate + * for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_getrate(unsigned int clock_id, + uint64_t *rate) +{ + return pm_api_clock_getrate(clock_id, rate); +} + +/** + * pm_clock_setparent - Set the clock parent for given id + * @clock_id: Id of the clock + * @parent_id: parent id + * + * This function is used by master to set parent for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_setparent(unsigned int clock_id, + unsigned int parent_id) +{ + return pm_api_clock_setparent(clock_id, parent_id); +} + +/** + * pm_clock_getparent - Get the clock parent for given id + * @clock_id: Id of the clock + * @parent_id: parent id + * + * This function is used by master to get parent index + * for any clock. + * + * Return: Returns status, either success or error+reason. + */ +enum pm_ret_status pm_clock_getparent(unsigned int clock_id, + unsigned int *parent_id) +{ + return pm_api_clock_getparent(clock_id, parent_id); +} + +/** + * pm_query_data() - PM API for querying firmware data + * @arg1 Argument 1 to requested IOCTL call + * @arg2 Argument 2 to requested IOCTL call + * @arg3 Argument 3 to requested IOCTL call + * @arg4 Argument 4 to requested IOCTL call + * @data Returned output data + * + * This function returns requested data. + * + * @return Returns status, either success or error+reason + */ +enum pm_ret_status pm_query_data(enum pm_query_id qid, + unsigned int arg1, + unsigned int arg2, + unsigned int arg3, + unsigned int *data) +{ + enum pm_ret_status ret; + + switch (qid) { + case PM_QID_CLOCK_GET_NAME: + ret = pm_clock_get_name(arg1, (char *)data); + break; + case PM_QID_CLOCK_GET_TOPOLOGY: + ret = pm_clock_get_topology(arg1, arg2, &data[1]); + data[0] = ret; + break; + case PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS: + ret = pm_clock_get_fixedfactor_params(arg1, &data[1], &data[2]); + data[0] = ret; + break; + case PM_QID_CLOCK_GET_PARENTS: + ret = pm_clock_get_parents(arg1, arg2, &data[1]); + data[0] = ret; + break; + case PM_QID_CLOCK_GET_ATTRIBUTES: + ret = pm_clock_get_attributes(arg1, &data[1]); + data[0] = ret; + break; + default: + ret = PM_RET_ERROR_ARGS; + WARN("Unimplemented query service call: 0x%x\n", qid); + } + + return ret; +} diff --git a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h index 1c91e8f4..20d80c21 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +++ b/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -10,6 +10,15 @@ #include #include "pm_defs.h" +enum pm_query_id { + PM_QID_INVALID, + PM_QID_CLOCK_GET_NAME, + PM_QID_CLOCK_GET_TOPOLOGY, + PM_QID_CLOCK_GET_FIXEDFACTOR_PARAMS, + PM_QID_CLOCK_GET_PARENTS, + PM_QID_CLOCK_GET_ATTRIBUTES, +}; + /********************************************************** * System-level API function declarations **********************************************************/ @@ -110,5 +119,25 @@ enum pm_ret_status pm_ioctl(enum pm_node_id nid, unsigned int arg1, unsigned int arg2, unsigned int *value); - +enum pm_ret_status pm_clock_enable(unsigned int clock_id); +enum pm_ret_status pm_clock_disable(unsigned int clock_id); +enum pm_ret_status pm_clock_getstate(unsigned int clock_id, + unsigned int *state); +enum pm_ret_status pm_clock_setdivider(unsigned int clock_id, + unsigned int divider); +enum pm_ret_status pm_clock_getdivider(unsigned int clock_id, + unsigned int *divider); +enum pm_ret_status pm_clock_setrate(unsigned int clock_id, + uint64_t rate); +enum pm_ret_status pm_clock_getrate(unsigned int clock_id, + uint64_t *rate); +enum pm_ret_status pm_clock_setparent(unsigned int clock_id, + unsigned int parent_id); +enum pm_ret_status pm_clock_getparent(unsigned int clock_id, + unsigned int *parent_id); +enum pm_ret_status pm_query_data(enum pm_query_id qid, + unsigned int arg1, + unsigned int arg2, + unsigned int arg3, + unsigned int *data); #endif /* _PM_API_SYS_H_ */ diff --git a/plat/xilinx/zynqmp/pm_service/pm_defs.h b/plat/xilinx/zynqmp/pm_service/pm_defs.h index afd92f64..45a92e95 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_defs.h +++ b/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -76,6 +76,18 @@ enum pm_api_id { PM_PINCTRL_CONFIG_PARAM_GET, PM_PINCTRL_CONFIG_PARAM_SET, PM_IOCTL, + /* API to query information from firmware */ + PM_QUERY_DATA, + /* Clock control API functions */ + PM_CLOCK_ENABLE, + PM_CLOCK_DISABLE, + PM_CLOCK_GETSTATE, + PM_CLOCK_SETDIVIDER, + PM_CLOCK_GETDIVIDER, + PM_CLOCK_SETRATE, + PM_CLOCK_GETRATE, + PM_CLOCK_SETPARENT, + PM_CLOCK_GETPARENT, PM_API_MAX }; diff --git a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c index 648de24b..4fd69b91 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +++ b/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -289,6 +289,72 @@ uint64_t pm_smc_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3, SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); } + case PM_QUERY_DATA: + { + uint32_t data[4]; + + ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], data); + SMC_RET2(handle, (uint64_t)data[0] | ((uint64_t)data[1] << 32), + (uint64_t)data[2] | ((uint64_t)data[3] << 32)); + } + + case PM_CLOCK_ENABLE: + ret = pm_clock_enable(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_DISABLE: + ret = pm_clock_disable(pm_arg[0]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETSTATE: + { + uint32_t value; + + ret = pm_clock_getstate(pm_arg[0], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_CLOCK_SETDIVIDER: + ret = pm_clock_setdivider(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETDIVIDER: + { + uint32_t value; + + ret = pm_clock_getdivider(pm_arg[0], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_CLOCK_SETRATE: + ret = pm_clock_setrate(pm_arg[0], + ((uint64_t)pm_arg[2]) << 32 | pm_arg[1]); + + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETRATE: + { + uint64_t value; + + ret = pm_clock_getrate(pm_arg[0], &value); + SMC_RET2(handle, (uint64_t)ret | (value & 0xFFFFFFFF) << 32, + (value >> 32) & 0xFFFFFFFF); + + } + + case PM_CLOCK_SETPARENT: + ret = pm_clock_setparent(pm_arg[0], pm_arg[1]); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETPARENT: + { + uint32_t value; + + ret = pm_clock_getparent(pm_arg[0], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + default: WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); SMC_RET1(handle, SMC_UNK);