*
* @return Pointer to PLL structure if found, NULL otherwise
*/
-static struct pm_pll *pm_clock_get_pll(enum clock_id clock_id)
+struct pm_pll *pm_clock_get_pll(enum clock_id clock_id)
{
uint32_t i;
}
/**
- * pm_api_clock_enable() - Enable the clock for given id
- * @clock_id: Id of the clock to be enabled
+ * pm_clock_pll_enable() - "Enable" the PLL clock (lock the PLL)
+ * @pll: PLL to be locked
*
- * This function is used by master to enable the clock
- * including peripherals and PLL clocks.
+ * This function is used to map IOCTL/linux-based PLL handling to system-level
+ * EEMI APIs
*
- * Return: Returns status, either success or error+reason.
+ * Return: Error if the argument is not valid or status as returned by PMU
*/
-enum pm_ret_status pm_api_clock_enable(unsigned int clock_id)
+enum pm_ret_status pm_clock_pll_enable(struct pm_pll *pll)
{
- enum pm_ret_status ret = PM_RET_SUCCESS;
-
- if (!pm_clock_valid(clock_id))
+ if (!pll)
return PM_RET_ERROR_ARGS;
- if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
- return PM_RET_ERROR_NOTSUPPORTED;
-
- /*
- * PLL type clock should not enable explicitly.
- * It is done by FSBL on boot-up and by PMUFW whenever required.
- */
- if (!ISPLL(clock_id))
- ret = pm_api_clk_enable_disable(clock_id, 1);
+ /* Set the PLL mode according to the buffered mode value */
+ if (pll->mode == PLL_FRAC_MODE)
+ return pm_pll_set_mode(pll->nid, PM_PLL_MODE_FRACTIONAL);
- return ret;
+ return pm_pll_set_mode(pll->nid, PM_PLL_MODE_INTEGER);
}
/**
return PM_RET_SUCCESS;
}
+
+/**
+ * pm_clock_id_is_valid() - Check if given clock ID is valid
+ * @clock_id ID of the clock to be checked
+ *
+ * @return Returns success if clock_id is valid, otherwise an error
+ */
+enum pm_ret_status pm_clock_id_is_valid(unsigned int clock_id)
+{
+ if (!pm_clock_valid(clock_id))
+ return PM_RET_ERROR_ARGS;
+
+ if (pm_clock_type(clock_id) != CLK_TYPE_OUTPUT)
+ return PM_RET_ERROR_NOTSUPPORTED;
+
+ return PM_RET_SUCCESS;
+}
#define TYPE_DIV2 5U
#define TYPE_GATE 6U
+struct pm_pll;
+struct pm_pll *pm_clock_get_pll(enum clock_id clock_id);
enum pm_ret_status pm_api_clock_get_name(unsigned int clock_id, char *name);
enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks);
enum pm_ret_status pm_clock_get_pll_node_id(enum clock_id clock_id,
enum pm_node_id *node_id);
+enum pm_ret_status pm_clock_id_is_valid(unsigned int clock_id);
-enum pm_ret_status pm_api_clock_enable(unsigned int clock_id);
+enum pm_ret_status pm_clock_pll_enable(struct pm_pll *pll);
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);
return pm_api_clock_get_attributes(clock_id, attr);
}
+/**
+ * pm_clock_gate() - Configure clock gate
+ * @clock_id Id of the clock to be configured
+ * @enable Flag 0=disable (gate the clock), !0=enable (activate the clock)
+ *
+ * @return Error if an argument is not valid or status as returned by the
+ * PM controller (PMU)
+ */
+static enum pm_ret_status pm_clock_gate(unsigned int clock_id,
+ unsigned char enable)
+{
+ uint32_t payload[PAYLOAD_ARG_CNT];
+ enum pm_ret_status status;
+ enum pm_api_id api_id;
+
+ /* Check if clock ID is valid and return an error if it is not */
+ status = pm_clock_id_is_valid(clock_id);
+ if (status != PM_RET_SUCCESS)
+ return status;
+
+ if (enable)
+ api_id = PM_CLOCK_ENABLE;
+ else
+ api_id = PM_CLOCK_DISABLE;
+
+ /* Send request to the PMU */
+ PM_PACK_PAYLOAD2(payload, api_id, clock_id);
+ return pm_ipi_send_sync(primary_proc, payload, NULL, 0);
+}
+
/**
* 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.
+ * @return: Error if an argument is not valid or status as returned by the
+ * pm_clock_gate
*/
-
enum pm_ret_status pm_clock_enable(unsigned int clock_id)
{
- return pm_api_clock_enable(clock_id);
+ struct pm_pll *pll;
+
+ /* First try to handle it as a PLL */
+ pll = pm_clock_get_pll(clock_id);
+ if (pll)
+ return pm_clock_pll_enable(pll);
+
+ /* It's an on-chip clock, PMU should configure clock's gate */
+ return pm_clock_gate(clock_id, 1);
}
/**