MLK-16225: clk: imx8: Do not register clocks for unowned resources

Registering clocks for unowned resources can result in lots of pointless
scfw errors and potential faults when attempting to use LPCG.

Solve this by checking ownership via sc_rm_is_resource_owned and
returning -ENODEV from clock registration functions. The top-level clock
provider is also modified so that it accepts such errors silently.

This is intended for xen but could also be useful for SCFW partitioning.

Signed-off-by: Leonard Crestez <leonard.crestez@nxp.com>
Reviewed-by: Ranjani Vaidyanathan <Ranjani.vaidyanathan@nxp.com>
This commit is contained in:
Leonard Crestez 2017-09-26 17:53:17 +03:00 committed by Jason Liu
parent 87c8e7562e
commit 0bf9578916
6 changed files with 61 additions and 1 deletions

View file

@ -103,6 +103,11 @@ struct clk *imx_clk_divider_scu(const char *name,
struct clk *clk;
struct clk_init_data init;
if (!imx8_clk_is_resource_owned(rsrc_id)) {
pr_debug("skip clk %s rsrc %d not owned\n", name, rsrc_id);
return ERR_PTR(-ENODEV);
}
div_clk = kzalloc(sizeof(*div_clk), GFP_KERNEL);
if (!div_clk)
return ERR_PTR(-ENOMEM);
@ -130,6 +135,11 @@ struct clk *imx_clk_divider2_scu(const char *name, const char *parent_name,
struct clk *clk;
struct clk_init_data init;
if (!imx8_clk_is_resource_owned(rsrc_id)) {
pr_debug("skip clk %s rsrc %d not owned\n", name, rsrc_id);
return ERR_PTR(-ENODEV);
}
div_clk = kzalloc(sizeof(*div_clk), GFP_KERNEL);
if (!div_clk)
return ERR_PTR(-ENOMEM);
@ -212,6 +222,11 @@ struct clk *imx_clk_divider3_scu(const char *name, const char *parent_name,
struct clk *clk;
struct clk_init_data init;
if (!imx8_clk_is_resource_owned(rsrc_id)) {
pr_debug("skip clk %s rsrc %d not owned\n", name, rsrc_id);
return ERR_PTR(-ENODEV);
}
div = kzalloc(sizeof(struct clk_divider3_scu), GFP_KERNEL);
if (!div)
return ERR_PTR(-ENOMEM);

View file

@ -174,6 +174,11 @@ struct clk *clk_register_gate_scu(struct device *dev, const char *name,
struct clk *clk;
struct clk_init_data init;
if (!imx8_clk_is_resource_owned(rsrc_id)) {
pr_debug("skip clk %s rsrc %d not owned\n", name, rsrc_id);
return ERR_PTR(-ENODEV);
}
gate = kzalloc(sizeof(struct clk_gate_scu), GFP_KERNEL);
if (!gate)
return ERR_PTR(-ENOMEM);
@ -409,6 +414,11 @@ struct clk *clk_register_gate3_scu(struct device *dev, const char *name,
struct clk *clk;
struct clk_init_data init;
if (!imx8_clk_is_resource_owned(rsrc_id)) {
pr_debug("skip clk %s rsrc %d not owned\n", name, rsrc_id);
return ERR_PTR(-ENODEV);
}
gate = kzalloc(sizeof(struct clk_gate_scu), GFP_KERNEL);
if (!gate)
return ERR_PTR(-ENOMEM);

View file

@ -43,3 +43,27 @@ int imx8_clk_mu_init(void)
return 0;
}
bool imx8_clk_is_resource_owned(sc_rsrc_t rsrc)
{
/*
* A-core resources are special. SCFW reports they are not "owned" by
* current partition but linux can still adjust them for cpufreq.
*
* So force this to return false when running as a VM guest and always
* true otherwise.
*/
if (rsrc == SC_R_A53 || rsrc == SC_R_A72 || rsrc == SC_R_A35) {
if (xen_domain() && !xen_initial_domain())
return false;
return true;
}
if (!ccm_ipc_handle) {
pr_warn("%s: no ipc handle!\n", __func__);
/* should have handled -EPROBE_DEFER from clk_mu_init earlier. */
return false;
}
return sc_rm_is_resource_owned(ccm_ipc_handle, rsrc);
}

View file

@ -10,6 +10,7 @@ extern spinlock_t imx_ccm_lock;
extern sc_ipc_t ccm_ipc_handle;
int imx8_clk_mu_init(void);
bool imx8_clk_is_resource_owned(sc_rsrc_t rsrc);
struct clk *imx_clk_divider_scu(const char *name,
sc_rsrc_t rsrc_id, sc_pm_clk_t clk_type);

View file

@ -885,7 +885,7 @@ static int imx8qm_clk_probe(struct platform_device *pdev)
clks[IMX8QM_HSIO_SATA_EPCS_TX_CLK] = imx_clk_gate2_scu("hsio_sata_epcs_tx_clk", "dummy", LPCG_ADDR(HSIO_PHY_X1_LPCG), 4, FUNCTION_NAME(PD_HSIO_SATA_0));
for (i = 0; i < ARRAY_SIZE(clks); i++)
if (IS_ERR(clks[i]))
if (IS_ERR(clks[i]) && PTR_ERR(clks[i]) != -ENODEV)
pr_err("i.MX8QM clk %d: register failed with %ld\n",
i, PTR_ERR(clks[i]));

View file

@ -335,6 +335,11 @@ struct clk *clk_register_mux_gpr_scu(struct device *dev, const char *name,
struct clk *clk;
struct clk_init_data init;
if (!imx8_clk_is_resource_owned(rsrc_id)) {
pr_debug("skip clk %s rsrc %d not owned\n", name, rsrc_id);
return ERR_PTR(-ENODEV);
}
if (rsrc_id >= SC_R_LAST)
return NULL;
@ -410,6 +415,11 @@ struct clk *clk_register_mux2_scu(struct device *dev, const char *name,
struct clk *clk;
struct clk_init_data init;
if (!imx8_clk_is_resource_owned(rsrc_id)) {
pr_debug("skip clk %s rsrc %d not owned\n", name, rsrc_id);
return ERR_PTR(-ENODEV);
}
if (rsrc_id >= SC_R_LAST)
return ERR_PTR(-EINVAL);