Prepare resume/suspend PM. v2: Fix lima_pmu_wait_cmd timeout when mali400 case. Signed-off-by: Qiang Yu <yuq825@xxxxxxxxx> --- drivers/gpu/drm/lima/lima_device.h | 2 ++ drivers/gpu/drm/lima/lima_pmu.c | 53 +++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/lima/lima_device.h b/drivers/gpu/drm/lima/lima_device.h index 06fd9636dd72..1a5032b08883 100644 --- a/drivers/gpu/drm/lima/lima_device.h +++ b/drivers/gpu/drm/lima/lima_device.h @@ -64,6 +64,8 @@ struct lima_ip { bool async_reset; /* l2 cache */ spinlock_t lock; + /* pmu */ + u32 mask; } data; }; diff --git a/drivers/gpu/drm/lima/lima_pmu.c b/drivers/gpu/drm/lima/lima_pmu.c index 571f6d661581..d476569f2043 100644 --- a/drivers/gpu/drm/lima/lima_pmu.c +++ b/drivers/gpu/drm/lima/lima_pmu.c @@ -21,7 +21,7 @@ static int lima_pmu_wait_cmd(struct lima_ip *ip) v, v & LIMA_PMU_INT_CMD_MASK, 100, 100000); if (err) { - dev_err(dev->dev, "timeout wait pmd cmd\n"); + dev_err(dev->dev, "timeout wait pmu cmd\n"); return err; } @@ -29,6 +29,40 @@ static int lima_pmu_wait_cmd(struct lima_ip *ip) return 0; } +static u32 lima_pmu_get_ip_mask(struct lima_ip *ip) +{ + struct lima_device *dev = ip->dev; + u32 ret = 0; + int i; + + ret |= LIMA_PMU_POWER_GP0_MASK; + + if (dev->id == lima_gpu_mali400) { + ret |= LIMA_PMU_POWER_L2_MASK; + for (i = 0; i < 4; i++) { + if (dev->ip[lima_ip_pp0 + i].present) + ret |= LIMA_PMU_POWER_PP_MASK(i); + } + } else { + if (dev->ip[lima_ip_pp0].present) + ret |= LIMA450_PMU_POWER_PP0_MASK; + for (i = lima_ip_pp1; i <= lima_ip_pp3; i++) { + if (dev->ip[i].present) { + ret |= LIMA450_PMU_POWER_PP13_MASK; + break; + } + } + for (i = lima_ip_pp4; i <= lima_ip_pp7; i++) { + if (dev->ip[i].present) { + ret |= LIMA450_PMU_POWER_PP47_MASK; + break; + } + } + } + + return ret; +} + int lima_pmu_init(struct lima_ip *ip) { int err; @@ -56,5 +90,22 @@ int lima_pmu_init(struct lima_ip *ip) void lima_pmu_fini(struct lima_ip *ip) { + u32 stat; + + if (!ip->data.mask) + ip->data.mask = lima_pmu_get_ip_mask(ip); + stat = ~pmu_read(LIMA_PMU_STATUS) & ip->data.mask; + if (stat) { + pmu_write(LIMA_PMU_POWER_DOWN, stat); + + /* Don't wait for interrupt on Mali400 if all domains are + * powered off because the HW won't generate an interrupt + * in this case. + */ + if (ip->dev->id == lima_gpu_mali400) + pmu_write(LIMA_PMU_INT_CLEAR, LIMA_PMU_INT_CMD_MASK); + else + lima_pmu_wait_cmd(ip); + } } -- 2.17.1 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel