ソースを参照

msm: camera: csiphy: Add logic to program common register

All csiphy hw common register need to program on first streamon
from any of csiphy hw in order to reduce the noise interferance
for other csiphy hw.

CRs-Fixed: 2839793
Change-Id: I256307b8b909da4a940be25a3aab60e8a301b6f8
Signed-off-by: Jigarkumar Zala <[email protected]>
Jigarkumar Zala 4 年 前
コミット
da9abb515c

+ 108 - 0
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.c

@@ -35,9 +35,19 @@
 /* Mask to enable skew calibration registers */
 #define SKEW_CAL_MASK 0x2
 
+static DEFINE_MUTEX(active_csiphy_cnt_mutex);
+
 static int csiphy_dump;
 module_param(csiphy_dump, int, 0644);
 
+struct g_csiphy_data {
+	void __iomem *base_address;
+	uint8_t is_3phase;
+};
+
+static struct g_csiphy_data g_phy_data[MAX_CSIPHY] = {{0, 0}};
+static int active_csiphy_hw_cnt;
+
 int32_t cam_csiphy_get_instance_offset(
 	struct csiphy_device *csiphy_dev,
 	int32_t dev_handle)
@@ -109,6 +119,59 @@ void cam_csiphy_reset(struct csiphy_device *csiphy_dev)
 	}
 }
 
+static void cam_csiphy_prgm_cmn_data(
+	struct csiphy_device *csiphy_dev,
+	bool reset)
+{
+	int csiphy_idx = 0;
+	uint32_t size = 0;
+	int i = 0;
+	void __iomem *csiphybase;
+	bool is_3phase = false;
+	struct csiphy_reg_t *csiphy_common_reg = NULL;
+
+	size = csiphy_dev->ctrl_reg->csiphy_reg.csiphy_common_array_size;
+
+	if (active_csiphy_hw_cnt < 0 || active_csiphy_hw_cnt >= MAX_CSIPHY) {
+		CAM_WARN(CAM_CSIPHY,
+			"MisMatched in active phy hw: %d and Max supported: %d",
+			active_csiphy_hw_cnt, MAX_CSIPHY);
+		return;
+	}
+
+	if (active_csiphy_hw_cnt == 0) {
+		CAM_DBG(CAM_CSIPHY, "CSIPHYs HW state needs to be %s",
+			reset ? "reset" : "set");
+	} else {
+		CAM_DBG(CAM_CSIPHY, "Active CSIPHY hws are %d",
+			active_csiphy_hw_cnt);
+		return;
+	}
+
+	for (csiphy_idx = 0; csiphy_idx < MAX_CSIPHY; csiphy_idx++) {
+		csiphybase = g_phy_data[csiphy_idx].base_address;
+		is_3phase = g_phy_data[csiphy_idx].is_3phase;
+
+		for (i = 0; i < size; i++) {
+			csiphy_common_reg =
+				&csiphy_dev->ctrl_reg->csiphy_common_reg[i];
+			switch (csiphy_common_reg->csiphy_param_type) {
+			case CSIPHY_DEFAULT_PARAMS:
+				cam_io_w_mb(reset ? 0x00 :
+					csiphy_common_reg->reg_data,
+					csiphybase +
+					csiphy_common_reg->reg_addr);
+				break;
+			default:
+				break;
+			}
+			if (csiphy_common_reg->delay > 0)
+				usleep_range(csiphy_common_reg->delay,
+					csiphy_common_reg->delay + 5);
+		}
+	}
+}
+
 static int32_t cam_csiphy_update_secure_info(
 	struct csiphy_device *csiphy_dev, int32_t index)
 {
@@ -1132,6 +1195,15 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 			goto release_mutex;
 		}
 
+		if (!csiphy_dev->acquire_count) {
+			g_phy_data[csiphy_dev->soc_info.index].is_3phase =
+					csiphy_acq_params.csiphy_3phase;
+			CAM_DBG(CAM_CSIPHY,
+					"g_csiphy data is updated for index: %d is_3phase: %u",
+					csiphy_dev->soc_info.index,
+					g_phy_data[csiphy_dev->soc_info.index].is_3phase);
+		}
+
 		csiphy_dev->acquire_count++;
 		CAM_DBG(CAM_CSIPHY, "ACQUIRE_CNT: %d",
 			csiphy_dev->acquire_count);
@@ -1209,6 +1281,15 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 
 		csiphy_dev->csiphy_info[offset].csiphy_cpas_cp_reg_mask = 0x0;
 
+		if (csiphy_dev->ctrl_reg->csiphy_reg
+			.prgm_cmn_reg_across_csiphy) {
+			mutex_lock(&active_csiphy_cnt_mutex);
+			active_csiphy_hw_cnt--;
+			mutex_unlock(&active_csiphy_cnt_mutex);
+
+			cam_csiphy_prgm_cmn_data(csiphy_dev, true);
+		}
+
 		rc = cam_csiphy_disable_hw(csiphy_dev);
 		if (rc < 0)
 			CAM_ERR(CAM_CSIPHY, "Failed in csiphy release");
@@ -1451,6 +1532,16 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
 			goto release_mutex;
 		}
 		csiphy_dev->start_dev_count++;
+
+		if (csiphy_dev->ctrl_reg->csiphy_reg
+			.prgm_cmn_reg_across_csiphy) {
+			cam_csiphy_prgm_cmn_data(csiphy_dev, false);
+
+			mutex_lock(&active_csiphy_cnt_mutex);
+			active_csiphy_hw_cnt++;
+			mutex_unlock(&active_csiphy_cnt_mutex);
+		}
+
 		CAM_DBG(CAM_CSIPHY, "START DEV CNT: %d",
 			csiphy_dev->start_dev_count);
 		csiphy_dev->csiphy_state = CAM_CSIPHY_START;
@@ -1480,3 +1571,20 @@ release_mutex:
 
 	return rc;
 }
+
+void cam_csiphy_register_baseaddress(struct csiphy_device *csiphy_dev)
+{
+	if (!csiphy_dev) {
+		CAM_WARN(CAM_CSIPHY, "Data is NULL");
+		return;
+	}
+
+	if (csiphy_dev->soc_info.index >= MAX_CSIPHY) {
+		CAM_ERR(CAM_CSIPHY, "Invalid soc index: %u Max soc index: %u",
+			csiphy_dev->soc_info.index, MAX_CSIPHY);
+		return;
+	}
+
+	g_phy_data[csiphy_dev->soc_info.index].base_address =
+		csiphy_dev->soc_info.reg_map[0].mem_base;
+}

+ 8 - 1
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_core.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved.
  */
 
 #ifndef _CAM_CSIPHY_CORE_H_
@@ -49,4 +49,11 @@ irqreturn_t cam_csiphy_irq(int irq_num, void *data);
  */
 void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev);
 
+/**
+ * @soc_idx : CSIPHY cell index
+ *
+ * This API registers base address per soc_idx
+ */
+void cam_csiphy_register_baseaddress(struct csiphy_device *csiphy_dev);
+
 #endif /* _CAM_CSIPHY_CORE_H_ */

+ 4 - 0
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.c

@@ -221,6 +221,10 @@ static int cam_csiphy_component_bind(struct device *dev,
 	CAM_DBG(CAM_CSIPHY, "CPAS registration successful handle=%d",
 		cpas_parms.client_handle);
 	new_csiphy_dev->cpas_handle = cpas_parms.client_handle;
+
+	cam_csiphy_register_baseaddress(new_csiphy_dev);
+
+
 	CAM_DBG(CAM_CSIPHY, "%s component bound successfully",
 		pdev->name);
 	return rc;

+ 1 - 0
drivers/cam_sensor_module/cam_csiphy/cam_csiphy_dev.h

@@ -117,6 +117,7 @@ struct csiphy_reg_parms_t {
 	uint32_t csiphy_cpas_cp_3ph_offset;
 	uint32_t csiphy_2ph_clock_lane;
 	uint32_t csiphy_2ph_combo_ck_ln;
+	uint32_t prgm_cmn_reg_across_csiphy;
 };
 
 /**

+ 3 - 8
drivers/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_2_3_hwreg.h

@@ -13,13 +13,14 @@ struct csiphy_reg_parms_t csiphy_v1_2_3 = {
 	.mipi_csiphy_interrupt_clear0_addr = 0x858,
 	.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
 	.csiphy_interrupt_status_size = 11,
-	.csiphy_common_array_size = 8,
-	.csiphy_reset_array_size = 5,
+	.csiphy_common_array_size = 5,
+	.csiphy_reset_array_size = 2,
 	.csiphy_2ph_config_array_size = 16,
 	.csiphy_3ph_config_array_size = 26,
 	.csiphy_2ph_3ph_config_array_size = 0,
 	.csiphy_2ph_clock_lane = 0x1,
 	.csiphy_2ph_combo_ck_ln = 0x10,
+	.prgm_cmn_reg_across_csiphy = 1,
 };
 
 struct csiphy_reg_t csiphy_common_reg_1_2_3[] = {
@@ -28,15 +29,9 @@ struct csiphy_reg_t csiphy_common_reg_1_2_3[] = {
 	{0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
 	{0x081C, 0x5A, 0x00, CSIPHY_DEFAULT_PARAMS},
 	{0x0824, 0x72, 0x00, CSIPHY_2PH_REGS},
-	{0x0800, 0x01, 0x02, CSIPHY_DEFAULT_PARAMS},
-	{0x0800, 0x02, 0x00, CSIPHY_2PH_REGS},
-	{0x0800, 0x0E, 0x00, CSIPHY_3PH_REGS},
 };
 
 struct csiphy_reg_t csiphy_reset_reg_1_2_3[] = {
-	{0x0814, 0x00, 0x00, CSIPHY_LANE_ENABLE},
-	{0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
-	{0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
 	{0x0800, 0x01, 0x02, CSIPHY_DEFAULT_PARAMS},
 	{0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
 };