soc: qcom: geni-se: Introduce helper APIs for performance control

The GENI Serial Engine (SE) drivers (I2C, SPI, and SERIAL) currently
manage performance levels and operating points directly. This resulting
in code duplication across drivers. such as configuring a specific level
or find and apply an OPP based on a clock frequency.

Introduce two new helper APIs, geni_se_set_perf_level() and
geni_se_set_perf_opp(), addresses this issue by providing a streamlined
method for the GENI Serial Engine (SE) drivers to find and set the OPP
based on the desired performance level, thereby eliminating redundancy.

Signed-off-by: Praveen Talari <praveen.talari@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Tested-by: Mattijs Korpershoek <mkorpershoek@kernel.org>
Link: https://lore.kernel.org/r/20260227061544.1785978-8-praveen.talari@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
This commit is contained in:
Praveen Talari
2026-02-27 11:45:38 +05:30
committed by Bjorn Andersson
parent f1a325d281
commit c012e28e9a
2 changed files with 54 additions and 0 deletions

View File

@@ -282,6 +282,12 @@ struct se_fw_hdr {
#define geni_setbits32(_addr, _v) writel(readl(_addr) | (_v), _addr)
#define geni_clrbits32(_addr, _v) writel(readl(_addr) & ~(_v), _addr)
enum domain_idx {
DOMAIN_IDX_POWER,
DOMAIN_IDX_PERF,
DOMAIN_IDX_MAX
};
/**
* geni_se_get_qup_hw_version() - Read the QUP wrapper Hardware version
* @se: Pointer to the corresponding serial engine.
@@ -1096,6 +1102,50 @@ int geni_se_resources_activate(struct geni_se *se)
}
EXPORT_SYMBOL_GPL(geni_se_resources_activate);
/**
* geni_se_set_perf_level() - Set performance level for GENI SE.
* @se: Pointer to the struct geni_se instance.
* @level: The desired performance level.
*
* Sets the performance level by directly calling dev_pm_opp_set_level
* on the performance device associated with the SE.
*
* Return: 0 on success, or a negative error code on failure.
*/
int geni_se_set_perf_level(struct geni_se *se, unsigned long level)
{
return dev_pm_opp_set_level(se->pd_list->pd_devs[DOMAIN_IDX_PERF], level);
}
EXPORT_SYMBOL_GPL(geni_se_set_perf_level);
/**
* geni_se_set_perf_opp() - Set performance OPP for GENI SE by frequency.
* @se: Pointer to the struct geni_se instance.
* @clk_freq: The requested clock frequency.
*
* Finds the nearest operating performance point (OPP) for the given
* clock frequency and applies it to the SE's performance device.
*
* Return: 0 on success, or a negative error code on failure.
*/
int geni_se_set_perf_opp(struct geni_se *se, unsigned long clk_freq)
{
struct device *perf_dev = se->pd_list->pd_devs[DOMAIN_IDX_PERF];
struct dev_pm_opp *opp;
int ret;
opp = dev_pm_opp_find_freq_floor(perf_dev, &clk_freq);
if (IS_ERR(opp)) {
dev_err(se->dev, "failed to find opp for freq %lu\n", clk_freq);
return PTR_ERR(opp);
}
ret = dev_pm_opp_set_opp(perf_dev, opp);
dev_pm_opp_put(opp);
return ret;
}
EXPORT_SYMBOL_GPL(geni_se_set_perf_opp);
/**
* geni_se_domain_attach() - Attach power domains to a GENI SE device.
* @se: Pointer to the geni_se structure representing the GENI SE device.

View File

@@ -550,5 +550,9 @@ int geni_se_resources_deactivate(struct geni_se *se);
int geni_load_se_firmware(struct geni_se *se, enum geni_se_protocol_type protocol);
int geni_se_domain_attach(struct geni_se *se);
int geni_se_set_perf_level(struct geni_se *se, unsigned long level);
int geni_se_set_perf_opp(struct geni_se *se, unsigned long clk_freq);
#endif
#endif