zynqmp: pm: Implement PLL set mode EEMI API

This API will be used to set the PLL mode: reset (unlocked), integer
or fractional (locked). If reset mode is set the PM controller will
bypass the target PLL prior to asserting the reset. If integer or
fractional mode is set the PM controller will program and trigger
locking of the PLL. If success status is returned the PLL is locked
and its bypass is deasserted. If fractional mode is set the fractional
divider (data parameter) has to have a non-zero value prior to issuing
pll set fractional mode. The caller need to ensure that the data
parameter is properly set using pll get/set parameter EEMI API.

Signed-off-by: Mirela Simonovic <mirela.simonovic@aggios.com>
Acked-by: Will Wong <WILLW@xilinx.com>
Signed-off-by: Jolly Shah <jollys@xilinx.com>
This commit is contained in:
Jolly Shah 2019-01-04 11:32:31 -08:00
parent d833f64c90
commit 5f1a5fee52
4 changed files with 48 additions and 0 deletions

View File

@ -1296,3 +1296,33 @@ enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
PM_PACK_PAYLOAD3(payload, PM_PLL_GET_PARAMETER, nid, param_id);
return pm_ipi_send_sync(primary_proc, payload, value, 1);
}
/**
* pm_pll_set_mode() - Set the PLL mode
* @nid Node id of the target PLL
* @mode PLL mode to be set
*
* If reset mode is set the PM controller will first bypass the PLL and then
* assert the reset. If integer or fractional mode is set the PM controller will
* ensure that the complete PLL programming sequence is satisfied. After this
* function returns success the PLL is locked and its bypass is deasserted.
*
* @return Error if an argument is not valid or status as returned by the
* PM controller (PMU)
*/
enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode)
{
uint32_t payload[PAYLOAD_ARG_CNT];
/* Check if given node ID is a PLL node */
if (nid < NODE_APLL || nid > NODE_IOPLL)
return PM_RET_ERROR_ARGS;
/* Check if PLL mode is valid */
if (mode >= PM_PLL_MODE_MAX)
return PM_RET_ERROR_ARGS;
/* Send request to the PMU */
PM_PACK_PAYLOAD3(payload, PM_PLL_SET_MODE, nid, mode);
return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
}

View File

@ -184,4 +184,6 @@ enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid,
enum pm_pll_param param_id,
unsigned int *value);
enum pm_ret_status pm_pll_set_mode(enum pm_node_id nid, enum pm_pll_mode mode);
#endif /* PM_API_SYS_H */

View File

@ -95,6 +95,7 @@ enum pm_api_id {
/* PLL control API functions */
PM_PLL_SET_PARAMETER,
PM_PLL_GET_PARAMETER,
PM_PLL_SET_MODE,
PM_API_MAX
};
@ -294,5 +295,16 @@ enum pm_pll_param {
PM_PLL_PARAM_MAX,
};
/**
* @PM_PLL_MODE_RESET: PLL is in reset (not locked)
* @PM_PLL_MODE_INTEGER: PLL is locked in integer mode
* @PM_PLL_MODE_FRACTIONAL: PLL is locked in fractional mode
*/
enum pm_pll_mode {
PM_PLL_MODE_RESET,
PM_PLL_MODE_INTEGER,
PM_PLL_MODE_FRACTIONAL,
PM_PLL_MODE_MAX,
};
#endif /* PM_DEFS_H */

View File

@ -575,6 +575,10 @@ 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_PLL_SET_MODE:
ret = pm_pll_set_mode(pm_arg[0], pm_arg[1]);
SMC_RET1(handle, (uint64_t)ret);
default:
WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid);
SMC_RET1(handle, SMC_UNK);