msm: camera: Request ispif_ahb_clk in ISPIF driver
ISPIF device needs to have "ispif_ahb_clk" clock when, there is a
register accesses. If this clock is not turned on and a register access
happens the following L2 master port error will happen:
<1> L2 Error detected!
<1> **L2ESR = 0x00010001
<1> **L2ESYNR0 = 0x19002008
<1> **L2ESYNR1 = 0x00409508
<1> **L2EAR0 = 0x00028106
<1> **L2EAR1 = 0x00000001
<1> **CPU bitmap = 0x1
<1> L2 master port decode error
<6> coresight-tmc fc307000.tmc: TMC aborted
<0> Kernel panic - not syncing: L2 master port error detected
Before this patch this request was left to be done by the CSID and
CSIPHY drivers, as they also need this clock. This provides a
possibility of a race condition, where the userspace, might request not
in sync the drivers and they might not enable the clocks in the correct
order. In such a case the ISPIF device might be left without clocks
being enabled, while a transaction to its register is about to be done,
which will result in the above kernel panic. To prevent this issue, the
ISPIF driver requests the required clock on its own without depending on
other drivers to do so.
Change-Id: I3f9f6239c4aaa75a9672ab3a0032ecf9ea455cf1
Signed-off-by: Vladislav Hristov <vhrist@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index e6874b7..4258bab 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -4998,6 +4998,8 @@
CLK_LOOKUP("csi3_rdi_clk", camss_csi3rdi_clk.c, "fda08c00.qcom,csid"),
/* ISPIF clocks */
+ CLK_LOOKUP("ispif_ahb_clk", camss_ispif_ahb_clk.c,
+ "fda0a000.qcom,ispif"),
CLK_LOOKUP("camss_vfe_vfe_clk", camss_vfe_vfe0_clk.c,
"fda0a000.qcom,ispif"),
CLK_LOOKUP("camss_csi_vfe_clk", camss_csi_vfe0_clk.c,
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index f209330..9dcd64c 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -167,6 +167,30 @@
return rc;
}
+static struct msm_cam_clk_info ispif_8974_ahb_clk_info[] = {
+ {"ispif_ahb_clk", -1},
+};
+
+static int msm_ispif_clk_ahb_enable(struct ispif_device *ispif, int enable)
+{
+ int rc = 0;
+
+ if (ispif->csid_version < CSID_VERSION_V3) {
+ /* Older ISPIF versiond don't need ahb clokc */
+ return 0;
+ }
+
+ rc = msm_cam_clk_enable(&ispif->pdev->dev,
+ ispif_8974_ahb_clk_info, &ispif->ahb_clk,
+ ARRAY_SIZE(ispif_8974_ahb_clk_info), enable);
+ if (rc < 0) {
+ pr_err("%s: cannot enable clock, error = %d",
+ __func__, rc);
+ }
+
+ return rc;
+}
+
static int msm_ispif_intf_reset(struct ispif_device *ispif,
struct msm_ispif_param_data *params)
{
@@ -979,12 +1003,20 @@
goto error_irq;
}
+ rc = msm_ispif_clk_ahb_enable(ispif, 1);
+ if (rc) {
+ pr_err("%s: ahb_clk enable failed", __func__);
+ goto error_ahb;
+ }
+
rc = msm_ispif_reset(ispif);
if (rc == 0) {
ispif->ispif_state = ISPIF_POWER_UP;
CDBG("%s: power up done\n", __func__);
goto end;
}
+
+error_ahb:
free_irq(ispif->irq->start, ispif);
error_irq:
iounmap(ispif->base);
@@ -1018,6 +1050,8 @@
/* make sure no streaming going on */
msm_ispif_reset(ispif);
+ msm_ispif_clk_ahb_enable(ispif, 0);
+
free_irq(ispif->irq->start, ispif);
iounmap(ispif->base);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
index 2c77292..945b5b8 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.h
@@ -58,5 +58,6 @@
enum msm_ispif_state_t ispif_state;
struct clk *ispif_clk[VFE_MAX][INTF_MAX];
struct msm_ispif_vfe_info vfe_info;
+ struct clk *ahb_clk;
};
#endif