media: atomisp: simplify the power down/up code

Use the version from intel_atomisp2_pm.c for power up/down,
removing some code duplication and using just one kAPI call
for modifying the ISPSSPM0 register.

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
This commit is contained in:
Mauro Carvalho Chehab 2020-05-12 15:13:50 +02:00
parent a27b581181
commit 0f441fd70b

View File

@ -761,91 +761,76 @@ static void punit_ddr_dvfs_enable(bool enable)
pr_info("DDR DVFS, door bell is not cleared within 3ms\n"); pr_info("DDR DVFS, door bell is not cleared within 3ms\n");
} }
/* Workaround for pmu_nc_set_power_state not ready in MRFLD */ static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable)
int atomisp_mrfld_power_down(struct atomisp_device *isp)
{ {
unsigned long timeout; unsigned long timeout;
u32 reg_value; u32 val = enable ? MRFLD_ISPSSPM0_IUNIT_POWER_ON :
MRFLD_ISPSSPM0_IUNIT_POWER_OFF;
/* writing 0x3 to ISPSSPM0 bit[1:0] to power off the IUNIT */ dev_dbg(isp->dev, "IUNIT power-%s.\n", enable ? "on" : "off");
iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &reg_value);
reg_value &= ~MRFLD_ISPSSPM0_ISPSSC_MASK;
reg_value |= MRFLD_ISPSSPM0_IUNIT_POWER_OFF;
iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, MRFLD_ISPSSPM0, reg_value);
/*WA:Enable DVFS*/ /*WA:Enable DVFS*/
if (IS_CHT) if (IS_CHT && enable)
punit_ddr_dvfs_enable(true); punit_ddr_dvfs_enable(true);
/*
* There should be no iunit access while power-down is
* in progress HW sighting: 4567865
* FIXME: msecs_to_jiffies(50)- experienced value
*/
timeout = jiffies + msecs_to_jiffies(50);
while (1) {
iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &reg_value);
dev_dbg(isp->dev, "power-off in progress, ISPSSPM0: 0x%x\n",
reg_value);
/* wait until ISPSSPM0 bit[25:24] shows 0x3 */
if ((reg_value >> MRFLD_ISPSSPM0_ISPSSS_OFFSET) ==
MRFLD_ISPSSPM0_IUNIT_POWER_OFF) {
trace_ipu_cstate(0);
return 0;
}
if (time_after(jiffies, timeout)) {
dev_err(isp->dev, "power-off iunit timeout.\n");
return -EBUSY;
}
/* FIXME: experienced value for delay */
usleep_range(100, 150);
}
}
/* Workaround for pmu_nc_set_power_state not ready in MRFLD */
int atomisp_mrfld_power_up(struct atomisp_device *isp)
{
unsigned long timeout;
u32 reg_value;
/*WA for PUNIT, if DVFS enabled, ISP timeout observed*/
if (IS_CHT)
punit_ddr_dvfs_enable(false);
/* /*
* FIXME:WA for ECS28A, with this sleep, CTS * FIXME:WA for ECS28A, with this sleep, CTS
* android.hardware.camera2.cts.CameraDeviceTest#testCameraDeviceAbort * android.hardware.camera2.cts.CameraDeviceTest#testCameraDeviceAbort
* PASS, no impact on other platforms * PASS, no impact on other platforms
*/ */
if (IS_BYT) if (IS_BYT && enable)
msleep(10); msleep(10);
/* writing 0x0 to ISPSSPM0 bit[1:0] to power off the IUNIT */ /* Write to ISPSSPM0 bit[1:0] to power on/off the IUNIT */
iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &reg_value); iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0,
reg_value &= ~MRFLD_ISPSSPM0_ISPSSC_MASK; val, MRFLD_ISPSSPM0_ISPSSC_MASK);
iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, MRFLD_ISPSSPM0, reg_value);
/* FIXME: experienced value for delay */ /*WA:Enable DVFS*/
if (IS_CHT && !enable)
punit_ddr_dvfs_enable(true);
/*
* There should be no IUNIT access while power-down is
* in progress. HW sighting: 4567865.
* Wait up to 50 ms for the IUNIT to shut down.
* And we do the same for power on.
*/
timeout = jiffies + msecs_to_jiffies(50); timeout = jiffies + msecs_to_jiffies(50);
while (1) { do {
iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &reg_value); u32 tmp;
dev_dbg(isp->dev, "power-on in progress, ISPSSPM0: 0x%x\n",
reg_value); /* Wait until ISPSSPM0 bit[25:24] shows the right value */
/* wait until ISPSSPM0 bit[25:24] shows 0x0 */ iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &tmp);
if ((reg_value >> MRFLD_ISPSSPM0_ISPSSS_OFFSET) == tmp = (tmp & MRFLD_ISPSSPM0_ISPSSC_MASK) >> MRFLD_ISPSSPM0_ISPSSS_OFFSET;
MRFLD_ISPSSPM0_IUNIT_POWER_ON) { if (tmp == val) {
trace_ipu_cstate(1); trace_ipu_cstate(enable);
return 0; return 0;
} }
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout))
dev_err(isp->dev, "power-on iunit timeout.\n"); break;
return -EBUSY;
}
/* FIXME: experienced value for delay */ /* FIXME: experienced value for delay */
usleep_range(100, 150); usleep_range(100, 150);
} } while (1);
if (enable)
msleep(10);
dev_err(isp->dev, "IUNIT power-%s timeout.\n", enable ? "on" : "off");
return -EBUSY;
}
/* Workaround for pmu_nc_set_power_state not ready in MRFLD */
int atomisp_mrfld_power_down(struct atomisp_device *isp)
{
return atomisp_mrfld_power(isp, false);
}
/* Workaround for pmu_nc_set_power_state not ready in MRFLD */
int atomisp_mrfld_power_up(struct atomisp_device *isp)
{
return atomisp_mrfld_power(isp, true);
} }
int atomisp_runtime_suspend(struct device *dev) int atomisp_runtime_suspend(struct device *dev)