mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-28 12:53:14 +01:00
pmdomain: imx8m-blk-ctrl: Serialize power on/off across sibling domains
On i.MX8MP the VPU blk-ctrl exposes G1, G2 and VC8000E as three separate
genpds, each serialized only by its own genpd lock, so their power_on and
power_off callbacks can run concurrently on SMP.
The sequences are not independent: they share the VPUMIX bus domain, the
VPU_NOC and the ADB400 handshake. On power up the GPC cannot ack-verify
the ADB400 handshake - the ack only completes once blk-ctrl sets the bus
clk-en bit - so it just waits a fixed delay instead of polling hskack. A
sibling transition landing inside another domain's reset window disturbs
that shared clock and handshake timing, the victim's reset does not take
effect, and its block registers read back all zeros: the decoder times
out or the encoder fails its format check.
Serialize the blk-ctrl reset sequence with a per-blk-ctrl mutex; the
driver deliberately avoids a genpd hierarchy, so the genpd core gives no
cross-sibling serialization.
Fixes: a1a5f15f7f ("soc: imx: imx8m-blk-ctrl: add i.MX8MP VPU blk ctrl")
Signed-off-by: Ming Qian <[email protected]>
Reviewed-by: Frank Li <[email protected]>
Cc: [email protected]
Signed-off-by: Ulf Hansson <[email protected]>
This commit is contained in:
1 parent
df2908090c
commit
51c2db3ef0
1 file changed
+15
@@ -15,6 +15,7 @@
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <dt-bindings/power/imx8mm-power.h>
|
||||
#include <dt-bindings/power/imx8mn-power.h>
|
||||
@@ -34,6 +35,12 @@ struct imx8m_blk_ctrl {
|
||||
struct regmap *regmap;
|
||||
struct imx8m_blk_ctrl_domain *domains;
|
||||
struct genpd_onecell_data onecell_data;
|
||||
/*
|
||||
* Serializes the blk-ctrl reset/clock sequence across sibling domains;
|
||||
* their transitions interact through the shared VPUMIX bus domain,
|
||||
* VPU_NOC and the not-ack-verified ADB400 handshake (ERR050531).
|
||||
*/
|
||||
struct mutex power_lock;
|
||||
};
|
||||
|
||||
struct imx8m_blk_ctrl_domain_data {
|
||||
@@ -98,6 +105,8 @@ static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
|
||||
struct imx8m_blk_ctrl *bc = domain->bc;
|
||||
int ret;
|
||||
|
||||
guard(mutex)(&bc->power_lock);
|
||||
|
||||
/* make sure bus domain is awake */
|
||||
ret = pm_runtime_get_sync(bc->bus_power_dev);
|
||||
if (ret < 0) {
|
||||
@@ -164,6 +173,8 @@ static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd)
|
||||
const struct imx8m_blk_ctrl_domain_data *data = domain->data;
|
||||
struct imx8m_blk_ctrl *bc = domain->bc;
|
||||
|
||||
guard(mutex)(&bc->power_lock);
|
||||
|
||||
/* put devices into reset and disable clocks */
|
||||
if (data->mipi_phy_rst_mask)
|
||||
regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
|
||||
@@ -202,6 +213,10 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
|
||||
|
||||
bc->dev = dev;
|
||||
|
||||
ret = devm_mutex_init(dev, &bc->power_lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bc_data = of_device_get_match_data(dev);
|
||||
|
||||
base = devm_platform_ioremap_resource(pdev, 0);
|
||||
|
||||
Reference in new issue
Block a user