zynqmp: pm: Implement PLL set mode EEMI API
authorJolly Shah <jollys@xilinx.com>
Fri, 4 Jan 2019 19:32:31 +0000 (11:32 -0800)
committerJolly Shah <jollys@xilinx.com>
Fri, 4 Jan 2019 19:33:56 +0000 (11:33 -0800)
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>
plat/xilinx/zynqmp/pm_service/pm_api_sys.c
plat/xilinx/zynqmp/pm_service/pm_api_sys.h
plat/xilinx/zynqmp/pm_service/pm_defs.h
plat/xilinx/zynqmp/pm_service/pm_svc_main.c

index da1669114ec038ef09b339a8b3471bfd8aca967e..b37512a23f4ba679525033f3f36ec9304cf5a97d 100644 (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);
+}
index 8ef210ac028804e9fcd07a64a565c8526cabe1c6..9b211f5f74ecc4c7e20435e25944df37c8f709a8 100644 (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 */
index 167a73331b57a2a975d83e3f5975de3e52c7b406..5927cafbb36961b78e08df0e5b2d79e34308e349 100644 (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 */
index 4e4a3ef6d169680b10235032a5ee5d4dfdb3f77a..881a593360057175013dc995ab7fdd95a8790188 100644 (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);