瀏覽代碼

msm: camera: sensor: Add i3c bus support

Add i3c bus support for qup i3c based
I3C target.

CRs-Fixed: 3169593
Change-Id: I0209f799d800daf9afe7a846310a3d4f4f2ee420
Signed-off-by: Jigarkumar Zala <[email protected]>
Signed-off-by: Jigar Agrawal <[email protected]>
Jigar Agrawal 3 年之前
父節點
當前提交
609d228234

+ 1 - 0
Kbuild

@@ -231,6 +231,7 @@ camera-$(CONFIG_SPECTRA_SENSOR) += \
 	drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.o \
 	drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.o \
 	drivers/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.o \
 	drivers/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.o \
 	drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.o \
 	drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i2c.o \
+	drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i3c.o \
 	drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.o \
 	drivers/cam_sensor_module/cam_sensor_io/cam_sensor_spi.o \
 	drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.o \
 	drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.o \
 	drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.o \
 	drivers/cam_sensor_module/cam_res_mgr/cam_res_mgr.o \

+ 3 - 0
drivers/cam_sensor_module/cam_actuator/cam_actuator_dev.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
  * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
  */
 
 
 
 
@@ -86,6 +87,7 @@ struct actuator_intf_params {
  * @cci_i2c_master: I2C structure
  * @cci_i2c_master: I2C structure
  * @io_master_info: Information about the communication master
  * @io_master_info: Information about the communication master
  * @actuator_mutex: Actuator mutex
  * @actuator_mutex: Actuator mutex
+ * @is_i3c_device : A Flag to indicate whether this actuator is I3C device
  * @act_apply_state: Actuator settings aRegulator config
  * @act_apply_state: Actuator settings aRegulator config
  * @id: Cell Index
  * @id: Cell Index
  * @res_apply_state: Actuator settings apply state
  * @res_apply_state: Actuator settings apply state
@@ -106,6 +108,7 @@ struct cam_actuator_ctrl_t {
 	struct camera_io_master io_master_info;
 	struct camera_io_master io_master_info;
 	struct cam_hw_soc_info soc_info;
 	struct cam_hw_soc_info soc_info;
 	struct mutex actuator_mutex;
 	struct mutex actuator_mutex;
+	bool is_i3c_device;
 	uint32_t id;
 	uint32_t id;
 	enum cam_actuator_apply_state_t setting_apply_state;
 	enum cam_actuator_apply_state_t setting_apply_state;
 	enum cam_actuator_state cam_act_state;
 	enum cam_actuator_state cam_act_state;

+ 9 - 0
drivers/cam_sensor_module/cam_actuator/cam_actuator_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
  */
 
 
 #include <linux/of.h>
 #include <linux/of.h>
@@ -34,6 +35,14 @@ int32_t cam_actuator_parse_dt(struct cam_actuator_ctrl_t *a_ctrl,
 
 
 	of_node = soc_info->dev->of_node;
 	of_node = soc_info->dev->of_node;
 
 
+	rc = of_property_read_bool(of_node, "i3c-target");
+	if (rc) {
+		a_ctrl->is_i3c_device = true;
+		a_ctrl->io_master_info.master_type = I3C_MASTER;
+	}
+
+	CAM_DBG(CAM_SENSOR, "I3C Target: %s", CAM_BOOL_TO_YESNO(a_ctrl->is_i3c_device));
+
 	if (a_ctrl->io_master_info.master_type == CCI_MASTER) {
 	if (a_ctrl->io_master_info.master_type == CCI_MASTER) {
 		rc = of_property_read_u32(of_node, "cci-master",
 		rc = of_property_read_u32(of_node, "cci-master",
 			&(a_ctrl->cci_i2c_master));
 			&(a_ctrl->cci_i2c_master));

+ 3 - 0
drivers/cam_sensor_module/cam_eeprom/cam_eeprom_dev.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
  * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
  */
 #ifndef _CAM_EEPROM_DEV_H_
 #ifndef _CAM_EEPROM_DEV_H_
 #define _CAM_EEPROM_DEV_H_
 #define _CAM_EEPROM_DEV_H_
@@ -164,6 +165,7 @@ struct eebin_info {
  * @gpio_num_info       :   gpio info
  * @gpio_num_info       :   gpio info
  * @cci_i2c_master      :   I2C structure
  * @cci_i2c_master      :   I2C structure
  * @v4l2_dev_str        :   V4L2 device structure
  * @v4l2_dev_str        :   V4L2 device structure
+ * @is_i3c_device       :   A flag to indicate whether this eeprom is I3C device
  * @bridge_intf         :   bridge interface params
  * @bridge_intf         :   bridge interface params
  * @cam_eeprom_state    :   eeprom_device_state
  * @cam_eeprom_state    :   eeprom_device_state
  * @userspace_probe     :   flag indicates userspace or kernel probe
  * @userspace_probe     :   flag indicates userspace or kernel probe
@@ -184,6 +186,7 @@ struct cam_eeprom_ctrl_t {
 	enum cci_i2c_master_t cci_i2c_master;
 	enum cci_i2c_master_t cci_i2c_master;
 	enum cci_device_num cci_num;
 	enum cci_device_num cci_num;
 	struct cam_subdev v4l2_dev_str;
 	struct cam_subdev v4l2_dev_str;
+	bool is_i3c_device;
 	struct cam_eeprom_intf_params bridge_intf;
 	struct cam_eeprom_intf_params bridge_intf;
 	enum msm_camera_device_type_t eeprom_device_type;
 	enum msm_camera_device_type_t eeprom_device_type;
 	enum cam_eeprom_state cam_eeprom_state;
 	enum cam_eeprom_state cam_eeprom_state;

+ 9 - 0
drivers/cam_sensor_module/cam_eeprom/cam_eeprom_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
  */
 
 
 #include <linux/of.h>
 #include <linux/of.h>
@@ -304,6 +305,14 @@ int cam_eeprom_parse_dt(struct cam_eeprom_ctrl_t *e_ctrl)
 
 
 	of_node = soc_info->dev->of_node;
 	of_node = soc_info->dev->of_node;
 
 
+	rc = of_property_read_bool(of_node, "i3c-target");
+	if (rc) {
+		e_ctrl->is_i3c_device = true;
+		e_ctrl->io_master_info.master_type = I3C_MASTER;
+	}
+
+	CAM_DBG(CAM_SENSOR, "I3C Target: %s", CAM_BOOL_TO_YESNO(e_ctrl->is_i3c_device));
+
 	if (of_property_read_bool(of_node, "multimodule-support")) {
 	if (of_property_read_bool(of_node, "multimodule-support")) {
 		CAM_DBG(CAM_UTIL, "Multi Module is Supported");
 		CAM_DBG(CAM_UTIL, "Multi Module is Supported");
 		e_ctrl->is_multimodule_mode = true;
 		e_ctrl->is_multimodule_mode = true;

+ 3 - 0
drivers/cam_sensor_module/cam_ois/cam_ois_dev.h

@@ -1,6 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
  */
 #ifndef _CAM_OIS_DEV_H_
 #ifndef _CAM_OIS_DEV_H_
 #define _CAM_OIS_DEV_H_
 #define _CAM_OIS_DEV_H_
@@ -93,6 +94,7 @@ struct cam_ois_intf_params {
  * @io_master_info  :   Information about the communication master
  * @io_master_info  :   Information about the communication master
  * @cci_i2c_master  :   I2C structure
  * @cci_i2c_master  :   I2C structure
  * @v4l2_dev_str    :   V4L2 device structure
  * @v4l2_dev_str    :   V4L2 device structure
+ * @is_i3c_device   :   A Flag to indicate whether this OIS is I3C Device or not.
  * @bridge_intf     :   bridge interface params
  * @bridge_intf     :   bridge interface params
  * @i2c_fwinit_data :   ois i2c firmware init settings
  * @i2c_fwinit_data :   ois i2c firmware init settings
  * @i2c_init_data   :   ois i2c init settings
  * @i2c_init_data   :   ois i2c init settings
@@ -116,6 +118,7 @@ struct cam_ois_ctrl_t {
 	enum cci_i2c_master_t cci_i2c_master;
 	enum cci_i2c_master_t cci_i2c_master;
 	enum cci_device_num cci_num;
 	enum cci_device_num cci_num;
 	struct cam_subdev v4l2_dev_str;
 	struct cam_subdev v4l2_dev_str;
+	bool is_i3c_device;
 	struct cam_ois_intf_params bridge_intf;
 	struct cam_ois_intf_params bridge_intf;
 	struct i2c_settings_array i2c_fwinit_data;
 	struct i2c_settings_array i2c_fwinit_data;
 	struct i2c_settings_array i2c_init_data;
 	struct i2c_settings_array i2c_init_data;

+ 9 - 1
drivers/cam_sensor_module/cam_ois/cam_ois_soc.c

@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 // SPDX-License-Identifier: GPL-2.0-only
 /*
 /*
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  */
  */
 
 
 #include <linux/of.h>
 #include <linux/of.h>
@@ -41,6 +42,14 @@ static int cam_ois_get_dt_data(struct cam_ois_ctrl_t *o_ctrl)
 		return rc;
 		return rc;
 	}
 	}
 
 
+	rc = of_property_read_bool(of_node, "i3c-target");
+	if (rc) {
+		o_ctrl->is_i3c_device = true;
+		o_ctrl->io_master_info.master_type = I3C_MASTER;
+	}
+
+	CAM_DBG(CAM_SENSOR, "I3C Target: %s", CAM_BOOL_TO_YESNO(o_ctrl->is_i3c_device));
+
 	/* Initialize regulators to default parameters */
 	/* Initialize regulators to default parameters */
 	for (i = 0; i < soc_info->num_rgltr; i++) {
 	for (i = 0; i < soc_info->num_rgltr; i++) {
 		soc_info->rgltr[i] = devm_regulator_get(soc_info->dev,
 		soc_info->rgltr[i] = devm_regulator_get(soc_info->dev,
@@ -126,7 +135,6 @@ int cam_ois_driver_soc_init(struct cam_ois_ctrl_t *o_ctrl)
 
 
 		o_ctrl->io_master_info.cci_client->cci_device = o_ctrl->cci_num;
 		o_ctrl->io_master_info.cci_client->cci_device = o_ctrl->cci_num;
 		CAM_DBG(CAM_OIS, "cci-device %d", o_ctrl->cci_num, rc);
 		CAM_DBG(CAM_OIS, "cci-device %d", o_ctrl->cci_num, rc);
-
 	}
 	}
 
 
 	rc = cam_ois_get_dt_data(o_ctrl);
 	rc = cam_ois_get_dt_data(o_ctrl);

+ 18 - 0
drivers/cam_sensor_module/cam_sensor/cam_sensor_core.c

@@ -13,6 +13,7 @@
 #include "cam_common_util.h"
 #include "cam_common_util.h"
 #include "cam_packet_util.h"
 #include "cam_packet_util.h"
 
 
+extern struct completion *cam_sensor_get_i3c_completion(uint32_t index);
 
 
 static int cam_sensor_update_req_mgr(
 static int cam_sensor_update_req_mgr(
 	struct cam_sensor_ctrl_t *s_ctrl,
 	struct cam_sensor_ctrl_t *s_ctrl,
@@ -790,7 +791,9 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
 	struct cam_sensor_power_ctrl_t *power_info =
 	struct cam_sensor_power_ctrl_t *power_info =
 		&s_ctrl->sensordata->power_info;
 		&s_ctrl->sensordata->power_info;
 	struct timespec64 ts;
 	struct timespec64 ts;
+	struct completion *i3c_probe_completion;
 	uint64_t ms, sec, min, hrs;
 	uint64_t ms, sec, min, hrs;
+	long time_left;
 
 
 	if (!s_ctrl || !arg) {
 	if (!s_ctrl || !arg) {
 		CAM_ERR(CAM_SENSOR, "s_ctrl is NULL");
 		CAM_ERR(CAM_SENSOR, "s_ctrl is NULL");
@@ -879,6 +882,21 @@ int32_t cam_sensor_driver_cmd(struct cam_sensor_ctrl_t *s_ctrl,
 				goto free_power_settings;
 				goto free_power_settings;
 			}
 			}
 		}
 		}
+
+		if (s_ctrl->io_master_info.master_type == I3C_MASTER) {
+			i3c_probe_completion =
+				cam_sensor_get_i3c_completion(s_ctrl->soc_info.index);
+
+			time_left = cam_common_wait_for_completion_timeout(
+					i3c_probe_completion,
+					msecs_to_jiffies(CAM_SENSOR_I3C_PROBE_TIMEOUT_MS));
+			if (!time_left) {
+				CAM_ERR(CAM_SENSOR, "Wait for I3C probe timedout for %s",
+					s_ctrl->sensor_name);
+				return -ETIMEDOUT;
+			}
+		}
+
 		/* Match sensor ID */
 		/* Match sensor ID */
 		rc = cam_sensor_match_id(s_ctrl);
 		rc = cam_sensor_match_id(s_ctrl);
 		if (rc < 0) {
 		if (rc < 0) {

+ 160 - 23
drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.c

@@ -9,6 +9,17 @@
 #include "cam_sensor_soc.h"
 #include "cam_sensor_soc.h"
 #include "cam_sensor_core.h"
 #include "cam_sensor_core.h"
 #include "camera_main.h"
 #include "camera_main.h"
+#include "cam_compat.h"
+
+static struct cam_sensor_i3c_sensor_data {
+	struct cam_sensor_ctrl_t                  *s_ctrl;
+	struct completion                          probe_complete;
+} g_i3c_sensor_data[MAX_CAMERAS];
+
+struct completion *cam_sensor_get_i3c_completion(uint32_t index)
+{
+	return &g_i3c_sensor_data[index].probe_complete;
+}
 
 
 static int cam_sensor_subdev_close_internal(struct v4l2_subdev *sd,
 static int cam_sensor_subdev_close_internal(struct v4l2_subdev *sd,
 	struct v4l2_subdev_fh *fh)
 	struct v4l2_subdev_fh *fh)
@@ -136,21 +147,14 @@ static int cam_sensor_init_subdev_params(struct cam_sensor_ctrl_t *s_ctrl)
 {
 {
 	int rc = 0;
 	int rc = 0;
 
 
-	s_ctrl->v4l2_dev_str.internal_ops =
-		&cam_sensor_internal_ops;
-	s_ctrl->v4l2_dev_str.ops =
-		&cam_sensor_subdev_ops;
-	strlcpy(s_ctrl->device_name, CAMX_SENSOR_DEV_NAME,
-		sizeof(s_ctrl->device_name));
-	s_ctrl->v4l2_dev_str.name =
-		s_ctrl->device_name;
-	s_ctrl->v4l2_dev_str.sd_flags =
-		(V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS);
-	s_ctrl->v4l2_dev_str.ent_function =
-		CAM_SENSOR_DEVICE_TYPE;
+	s_ctrl->v4l2_dev_str.internal_ops = &cam_sensor_internal_ops;
+	s_ctrl->v4l2_dev_str.ops = &cam_sensor_subdev_ops;
+	strscpy(s_ctrl->device_name, CAMX_SENSOR_DEV_NAME, CAM_CTX_DEV_NAME_MAX_LENGTH);
+	s_ctrl->v4l2_dev_str.name = s_ctrl->device_name;
+	s_ctrl->v4l2_dev_str.sd_flags = (V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS);
+	s_ctrl->v4l2_dev_str.ent_function = CAM_SENSOR_DEVICE_TYPE;
 	s_ctrl->v4l2_dev_str.token = s_ctrl;
 	s_ctrl->v4l2_dev_str.token = s_ctrl;
-	s_ctrl->v4l2_dev_str.close_seq_prior =
-		CAM_SD_CLOSE_MEDIUM_LOW_PRIORITY;
+	s_ctrl->v4l2_dev_str.close_seq_prior = CAM_SD_CLOSE_MEDIUM_LOW_PRIORITY;
 
 
 	rc = cam_register_subdev(&(s_ctrl->v4l2_dev_str));
 	rc = cam_register_subdev(&(s_ctrl->v4l2_dev_str));
 	if (rc)
 	if (rc)
@@ -159,6 +163,45 @@ static int cam_sensor_init_subdev_params(struct cam_sensor_ctrl_t *s_ctrl)
 	return rc;
 	return rc;
 }
 }
 
 
+static int cam_sensor_i3c_driver_probe(struct i3c_device *client)
+{
+	int32_t rc = 0;
+	struct cam_sensor_ctrl_t       *s_ctrl = NULL;
+	uint32_t                        index;
+	struct device                  *dev;
+
+	dev = i3cdev_to_dev(client);
+
+	CAM_DBG(CAM_SENSOR, "Probe for I3C Slave %s", dev_name(dev));
+
+	rc = of_property_read_u32(dev->of_node, "cell-index", &index);
+	if (rc) {
+		CAM_ERR(CAM_UTIL, "device %s failed to read cell-index", dev_name(dev));
+		return rc;
+	}
+
+	if (index >= MAX_CAMERAS) {
+		CAM_ERR(CAM_SENSOR, "Invalid Cell-Index: %u for %s", index, dev_name(dev));
+		return -EINVAL;
+	}
+
+	s_ctrl = g_i3c_sensor_data[index].s_ctrl;
+	if (!s_ctrl) {
+		CAM_ERR(CAM_SENSOR, "S_ctrl is null. I3C Probe before platfom driver probe for %s",
+			dev_name(dev));
+		return -EINVAL;
+	}
+
+	i3cdev_set_drvdata(client, s_ctrl);
+
+	s_ctrl->io_master_info.i3c_client = client;
+
+	complete_all(&g_i3c_sensor_data[index].probe_complete);
+
+	CAM_DBG(CAM_SENSOR, "I3C Probe Finished for %s", dev_name(dev));
+	return rc;
+}
+
 static int cam_sensor_i2c_component_bind(struct device *dev,
 static int cam_sensor_i2c_component_bind(struct device *dev,
 	struct device *master_dev, void *data)
 	struct device *master_dev, void *data)
 {
 {
@@ -358,6 +401,8 @@ static int cam_sensor_component_bind(struct device *dev,
 		goto free_s_ctrl;
 		goto free_s_ctrl;
 	}
 	}
 
 
+	CAM_DBG(CAM_SENSOR, "Master Type: %u", s_ctrl->io_master_info.master_type);
+
 	/* Fill platform device id*/
 	/* Fill platform device id*/
 	pdev->id = soc_info->index;
 	pdev->id = soc_info->index;
 
 
@@ -406,7 +451,10 @@ static int cam_sensor_component_bind(struct device *dev,
 	s_ctrl->sensordata->power_info.dev = &pdev->dev;
 	s_ctrl->sensordata->power_info.dev = &pdev->dev;
 	platform_set_drvdata(pdev, s_ctrl);
 	platform_set_drvdata(pdev, s_ctrl);
 	s_ctrl->sensor_state = CAM_SENSOR_INIT;
 	s_ctrl->sensor_state = CAM_SENSOR_INIT;
-	CAM_DBG(CAM_SENSOR, "Component bound successfully");
+	CAM_DBG(CAM_SENSOR, "Component bound successfully for %s", pdev->name);
+
+	g_i3c_sensor_data[soc_info->index].s_ctrl = s_ctrl;
+	init_completion(&g_i3c_sensor_data[soc_info->index].probe_complete);
 
 
 	return rc;
 	return rc;
 
 
@@ -464,13 +512,14 @@ static const struct of_device_id cam_sensor_driver_dt_match[] = {
 	{.compatible = "qcom,cam-sensor"},
 	{.compatible = "qcom,cam-sensor"},
 	{}
 	{}
 };
 };
+MODULE_DEVICE_TABLE(of, cam_sensor_driver_dt_match);
 
 
 static int32_t cam_sensor_driver_platform_probe(
 static int32_t cam_sensor_driver_platform_probe(
 	struct platform_device *pdev)
 	struct platform_device *pdev)
 {
 {
 	int rc = 0;
 	int rc = 0;
 
 
-	CAM_DBG(CAM_SENSOR, "Adding Sensor component");
+	CAM_DBG(CAM_SENSOR, "Adding Sensor component for %s", pdev->name);
 	rc = component_add(&pdev->dev, &cam_sensor_component_ops);
 	rc = component_add(&pdev->dev, &cam_sensor_component_ops);
 	if (rc)
 	if (rc)
 		CAM_ERR(CAM_SENSOR, "failed to add component rc: %d", rc);
 		CAM_ERR(CAM_SENSOR, "failed to add component rc: %d", rc);
@@ -478,8 +527,6 @@ static int32_t cam_sensor_driver_platform_probe(
 	return rc;
 	return rc;
 }
 }
 
 
-MODULE_DEVICE_TABLE(of, cam_sensor_driver_dt_match);
-
 struct platform_driver cam_sensor_platform_driver = {
 struct platform_driver cam_sensor_platform_driver = {
 	.probe = cam_sensor_driver_platform_probe,
 	.probe = cam_sensor_driver_platform_probe,
 	.driver = {
 	.driver = {
@@ -495,7 +542,6 @@ static const struct of_device_id cam_sensor_i2c_driver_dt_match[] = {
 	{.compatible = "qcom,cam-i2c-sensor"},
 	{.compatible = "qcom,cam-i2c-sensor"},
 	{}
 	{}
 };
 };
-
 MODULE_DEVICE_TABLE(of, cam_sensor_i2c_driver_dt_match);
 MODULE_DEVICE_TABLE(of, cam_sensor_i2c_driver_dt_match);
 
 
 static const struct i2c_device_id i2c_id[] = {
 static const struct i2c_device_id i2c_id[] = {
@@ -515,20 +561,110 @@ struct i2c_driver cam_sensor_i2c_driver = {
 	},
 	},
 };
 };
 
 
+static struct i3c_device_id sensor_i3c_id[MAX_I3C_DEVICE_ID_ENTRIES + 1];
+
+static struct i3c_driver cam_sensor_i3c_driver = {
+	.id_table = sensor_i3c_id,
+	.probe = cam_sensor_i3c_driver_probe,
+	.remove = cam_sensor_i3c_driver_remove,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = SENSOR_DRIVER_I3C,
+		.of_match_table = cam_sensor_driver_dt_match,
+		.suppress_bind_attrs = true,
+	},
+};
+
+static int cam_sensor_fill_i3c_device_id(void)
+{
+	struct device_node                      *dev;
+	int                                      num_entries;
+	int                                      i = 0;
+	uint8_t                                  ent_num = 0;
+	uint32_t                                 mid;
+	uint32_t                                 pid;
+	int                                      rc;
+
+	dev = of_find_node_by_path(I3C_SENSOR_DEV_ID_DT_PATH);
+	if (!dev) {
+		CAM_WARN(CAM_SENSOR, "Couldnt Find the i3c-id-table dev node");
+		return 0;
+	}
+
+	num_entries = of_property_count_u32_elems(dev, "i3c-sensor-id-table");
+	if (num_entries <= 0) {
+		CAM_WARN(CAM_SENSOR, "Failed while reading the property. num_entries:%d",
+			num_entries);
+		return 0;
+	}
+
+	while (i < num_entries) {
+		if (ent_num >= MAX_I3C_DEVICE_ID_ENTRIES) {
+			CAM_WARN(CAM_SENSOR, "Num_entries are more than MAX_I3C_DEVICE_ID_ENTRIES");
+			return -ENOMEM;
+		}
+
+		rc = of_property_read_u32_index(dev, "i3c-sensor-id-table", i, &mid);
+		if (rc) {
+			CAM_ERR(CAM_SENSOR, "Failed in reading the MID. rc: %d", rc);
+			return rc;
+		}
+		i++;
+
+		rc = of_property_read_u32_index(dev, "i3c-sensor-id-table", i, &pid);
+		if (rc) {
+			CAM_ERR(CAM_SENSOR, "Failed in reading the PID. rc: %d", rc);
+			return rc;
+		}
+		i++;
+
+		CAM_DBG(CAM_SENSOR, "PID: 0x%x, MID: 0x%x", pid, mid);
+
+		sensor_i3c_id[ent_num].manuf_id = mid;
+		sensor_i3c_id[ent_num].match_flags = I3C_MATCH_MANUF_AND_PART;
+		sensor_i3c_id[ent_num].part_id  = pid;
+		sensor_i3c_id[ent_num].data     = 0;
+
+		ent_num++;
+	}
+
+	return 0;
+}
+
 int cam_sensor_driver_init(void)
 int cam_sensor_driver_init(void)
 {
 {
-	int32_t rc = 0;
+	int rc;
 
 
 	rc = platform_driver_register(&cam_sensor_platform_driver);
 	rc = platform_driver_register(&cam_sensor_platform_driver);
 	if (rc < 0) {
 	if (rc < 0) {
-		CAM_ERR(CAM_SENSOR, "platform_driver_register Failed: rc = %d",
-			rc);
+		CAM_ERR(CAM_SENSOR, "platform_driver_register Failed: rc = %d", rc);
 		return rc;
 		return rc;
 	}
 	}
 
 
 	rc = i2c_add_driver(&cam_sensor_i2c_driver);
 	rc = i2c_add_driver(&cam_sensor_i2c_driver);
-	if (rc)
+	if (rc) {
 		CAM_ERR(CAM_SENSOR, "i2c_add_driver failed rc = %d", rc);
 		CAM_ERR(CAM_SENSOR, "i2c_add_driver failed rc = %d", rc);
+		goto i2c_register_err;
+	}
+
+	memset(sensor_i3c_id, 0, sizeof(struct i3c_device_id) * (MAX_I3C_DEVICE_ID_ENTRIES + 1));
+
+	rc = cam_sensor_fill_i3c_device_id();
+	if (rc)
+		goto i3c_register_err;
+
+	rc = i3c_driver_register_with_owner(&cam_sensor_i3c_driver, THIS_MODULE);
+	if (rc) {
+		CAM_ERR(CAM_SENSOR, "i3c_driver registration failed, rc: %d", rc);
+		goto i3c_register_err;
+	}
+
+	return 0;
+
+i3c_register_err:
+	i2c_del_driver(&cam_sensor_i2c_driver);
+i2c_register_err:
+	platform_driver_unregister(&cam_sensor_platform_driver);
 
 
 	return rc;
 	return rc;
 }
 }
@@ -537,6 +673,7 @@ void cam_sensor_driver_exit(void)
 {
 {
 	platform_driver_unregister(&cam_sensor_platform_driver);
 	platform_driver_unregister(&cam_sensor_platform_driver);
 	i2c_del_driver(&cam_sensor_i2c_driver);
 	i2c_del_driver(&cam_sensor_i2c_driver);
+	i3c_driver_unregister(&cam_sensor_i3c_driver);
 }
 }
 
 
 MODULE_DESCRIPTION("cam_sensor_driver");
 MODULE_DESCRIPTION("cam_sensor_driver");

+ 6 - 12
drivers/cam_sensor_module/cam_sensor/cam_sensor_dev.h

@@ -28,16 +28,9 @@
 
 
 #define NUM_MASTERS 2
 #define NUM_MASTERS 2
 #define NUM_QUEUES 2
 #define NUM_QUEUES 2
-
-#undef CDBG
-#ifdef CAM_SENSOR_DEBUG
-#define CDBG(fmt, args...) pr_err(fmt, ##args)
-#else
-#define CDBG(fmt, args...) pr_debug(fmt, ##args)
-#endif
-
-#define SENSOR_DRIVER_I2C "cam-i2c-sensor"
-#define CAMX_SENSOR_DEV_NAME "cam-sensor-driver"
+#define SENSOR_DRIVER_I2C                          "cam-i2c-sensor"
+#define CAMX_SENSOR_DEV_NAME                       "cam-sensor-driver"
+#define SENSOR_DRIVER_I3C                          "i3c_camera_sensor"
 
 
 enum cam_sensor_state_t {
 enum cam_sensor_state_t {
 	CAM_SENSOR_INIT,
 	CAM_SENSOR_INIT,
@@ -73,6 +66,7 @@ struct sensor_intf_params {
  * @sensor_state: Sensor states
  * @sensor_state: Sensor states
  * @is_probe_succeed: Probe succeeded or not
  * @is_probe_succeed: Probe succeeded or not
  * @id: Cell Index
  * @id: Cell Index
+ * @is_i3c_device: A Flag to indicate whether this sensor is an I3C Device.
  * @of_node: Of node ptr
  * @of_node: Of node ptr
  * @v4l2_dev_str: V4L2 device structure
  * @v4l2_dev_str: V4L2 device structure
  * @sensor_probe_addr_type: Sensor probe address type
  * @sensor_probe_addr_type: Sensor probe address type
@@ -90,8 +84,7 @@ struct sensor_intf_params {
  * @aon_camera_id: AON Camera ID associated with this sensor
  * @aon_camera_id: AON Camera ID associated with this sensor
  */
  */
 struct cam_sensor_ctrl_t {
 struct cam_sensor_ctrl_t {
-	char                           device_name[
-		CAM_CTX_DEV_NAME_MAX_LENGTH];
+	char                           device_name[CAM_CTX_DEV_NAME_MAX_LENGTH];
 	struct platform_device        *pdev;
 	struct platform_device        *pdev;
 	struct cam_hw_soc_info         soc_info;
 	struct cam_hw_soc_info         soc_info;
 	struct mutex                   cam_sensor_mutex;
 	struct mutex                   cam_sensor_mutex;
@@ -102,6 +95,7 @@ struct cam_sensor_ctrl_t {
 	enum cam_sensor_state_t        sensor_state;
 	enum cam_sensor_state_t        sensor_state;
 	uint8_t                        is_probe_succeed;
 	uint8_t                        is_probe_succeed;
 	uint32_t                       id;
 	uint32_t                       id;
+	bool                           is_i3c_device;
 	struct device_node            *of_node;
 	struct device_node            *of_node;
 	struct cam_subdev              v4l2_dev_str;
 	struct cam_subdev              v4l2_dev_str;
 	uint8_t                        sensor_probe_addr_type;
 	uint8_t                        sensor_probe_addr_type;

+ 14 - 2
drivers/cam_sensor_module/cam_sensor/cam_sensor_soc.c

@@ -110,14 +110,19 @@ static int32_t cam_sensor_init_bus_params(struct cam_sensor_ctrl_t *s_ctrl)
 	if (s_ctrl->io_master_info.master_type == CCI_MASTER) {
 	if (s_ctrl->io_master_info.master_type == CCI_MASTER) {
 		s_ctrl->io_master_info.cci_client = kzalloc(sizeof(
 		s_ctrl->io_master_info.cci_client = kzalloc(sizeof(
 			struct cam_sensor_cci_client), GFP_KERNEL);
 			struct cam_sensor_cci_client), GFP_KERNEL);
-		if (!(s_ctrl->io_master_info.cci_client))
+		if (!(s_ctrl->io_master_info.cci_client)) {
+			CAM_ERR(CAM_SENSOR, "Memory allocation failed");
 			return -ENOMEM;
 			return -ENOMEM;
+		}
 	} else if (s_ctrl->io_master_info.master_type == I2C_MASTER) {
 	} else if (s_ctrl->io_master_info.master_type == I2C_MASTER) {
 		if (!(s_ctrl->io_master_info.client))
 		if (!(s_ctrl->io_master_info.client))
 			return -EINVAL;
 			return -EINVAL;
+	} else if (s_ctrl->io_master_info.master_type == I3C_MASTER) {
+		CAM_DBG(CAM_SENSOR, "I3C Master Type");
 	} else {
 	} else {
 		CAM_ERR(CAM_SENSOR,
 		CAM_ERR(CAM_SENSOR,
-			"Invalid master / Master type Not supported");
+			"Invalid master / Master type Not supported : %d",
+				s_ctrl->io_master_info.master_type);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
@@ -161,6 +166,13 @@ static int32_t cam_sensor_driver_get_dt_data(struct cam_sensor_ctrl_t *s_ctrl)
 		goto FREE_SENSOR_DATA;
 		goto FREE_SENSOR_DATA;
 	}
 	}
 
 
+	rc = of_property_read_bool(of_node, "i3c-target");
+	if (rc) {
+		CAM_INFO(CAM_SENSOR, "I3C Target");
+		s_ctrl->is_i3c_device = true;
+		s_ctrl->io_master_info.master_type = I3C_MASTER;
+	}
+
 	/* Store the index of BoB regulator if it is available */
 	/* Store the index of BoB regulator if it is available */
 	for (i = 0; i < soc_info->num_rgltr; i++) {
 	for (i = 0; i < soc_info->num_rgltr; i++) {
 		if (!strcmp(soc_info->rgltr_name[i],
 		if (!strcmp(soc_info->rgltr_name[i],

+ 78 - 0
drivers/cam_sensor_module/cam_sensor_io/cam_sensor_i3c.h

@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _CAM_SENSOR_I3C_H_
+#define _CAM_SENSOR_I3C_H_
+
+#include <linux/delay.h>
+#include <media/v4l2-subdev.h>
+#include <media/cam_sensor.h>
+#include "cam_sensor_io.h"
+
+/**
+ * cam_qup_i3c_read : This API handles QUP I3C read operations
+ * @client    : QUP IeC client structure
+ * @data      : I3C data
+ * @addr_type : I3C address type
+ * @data_type : I3C data type
+ */
+
+int cam_qup_i3c_read(struct i3c_device *client,
+	uint32_t addr, uint32_t *data,
+	enum camera_sensor_i2c_type addr_type,
+	enum camera_sensor_i2c_type data_type);
+
+/**
+ * cam_qup_i3c_read_seq : This API handles QUP I3C Sequential read operations
+ * @client    : QUP I3C client structure
+ * @data      : I3C data
+ * @addr_type : I3C address type
+ * @num_bytes : Number of bytes to read
+ */
+
+int cam_qup_i3c_read_seq(struct i3c_device *client,
+	uint32_t addr, uint8_t *data,
+	enum camera_sensor_i2c_type addr_type,
+	uint32_t num_byte);
+
+/**
+ * cam_qup_i3c_poll : This API handles QUP based I3C poll operation
+ * @client    : QUP I3C client structure
+ * @addr      : I3C address
+ * @data      : I3C data
+ * @data_mask : I3C data mask
+ * @data_type : I3C data type
+ * @addr_type : I3C addr type
+ * @delay_ms  : Delay in milli seconds
+ */
+
+int cam_qup_i3c_poll(struct i3c_device *client,
+	uint32_t addr, uint16_t data, uint16_t data_mask,
+	enum camera_sensor_i2c_type addr_type,
+	enum camera_sensor_i2c_type data_type,
+	uint32_t delay_ms);
+
+/**
+ * cam_qup_i3c_write_table : This API Handles QUP based I3C write random operations
+ * @client        : QUP I3C client structure
+ * @write_setting : I3C register settings
+ */
+
+int cam_qup_i3c_write_table(
+	struct camera_io_master *client,
+	struct cam_sensor_i2c_reg_setting *write_setting);
+
+/**
+ * cam_qup_i3c_write_continuous_write: This API Handles QUP based I3C write continuous(Burst/Seq)
+ * @client: QUP I3C client structure
+ * @write_setting: I3C register setting
+ * @cam_sensor_i3c_write_flag: burst or seq write
+ */
+int cam_qup_i3c_write_continuous_table(
+	struct camera_io_master *client,
+	struct cam_sensor_i2c_reg_setting *write_setting,
+	uint8_t cam_sensor_i3c_write_flag);
+
+#endif /*_CAM_SENSOR_I3C_H_*/

+ 92 - 82
drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.c

@@ -6,6 +6,7 @@
 
 
 #include "cam_sensor_io.h"
 #include "cam_sensor_io.h"
 #include "cam_sensor_i2c.h"
 #include "cam_sensor_i2c.h"
+#include "cam_sensor_i3c.h"
 
 
 int32_t camera_io_dev_poll(struct camera_io_master *io_master_info,
 int32_t camera_io_dev_poll(struct camera_io_master *io_master_info,
 	uint32_t addr, uint16_t data, uint32_t data_mask,
 	uint32_t addr, uint16_t data, uint32_t data_mask,
@@ -20,48 +21,49 @@ int32_t camera_io_dev_poll(struct camera_io_master *io_master_info,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	if (io_master_info->master_type == CCI_MASTER) {
+	switch (io_master_info->master_type) {
+	case CCI_MASTER:
 		return cam_cci_i2c_poll(io_master_info->cci_client,
 		return cam_cci_i2c_poll(io_master_info->cci_client,
 			addr, data, mask, data_type, addr_type, delay_ms);
 			addr, data, mask, data_type, addr_type, delay_ms);
-	} else if (io_master_info->master_type == I2C_MASTER) {
+	case I2C_MASTER:
 		return cam_qup_i2c_poll(io_master_info->client,
 		return cam_qup_i2c_poll(io_master_info->client,
-			addr, data, data_mask, addr_type, data_type,
-			delay_ms);
-	} else {
-		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
-			io_master_info->master_type);
-		return -EINVAL;
+			addr, data, data_mask, addr_type, data_type, delay_ms);
+	case I3C_MASTER:
+		return cam_qup_i3c_poll(io_master_info->i3c_client,
+			addr, data, data_mask, addr_type, data_type, delay_ms);
+	default:
+		CAM_ERR(CAM_SENSOR, "Invalid Master Type: %d", io_master_info->master_type);
 	}
 	}
+
+	return -EINVAL;
 }
 }
 
 
 int32_t camera_io_dev_erase(struct camera_io_master *io_master_info,
 int32_t camera_io_dev_erase(struct camera_io_master *io_master_info,
 	uint32_t addr, uint32_t size)
 	uint32_t addr, uint32_t size)
 {
 {
-	int rc = 0;
-
 	if (!io_master_info) {
 	if (!io_master_info) {
 		CAM_ERR(CAM_SENSOR, "Invalid Args");
 		CAM_ERR(CAM_SENSOR, "Invalid Args");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
 	if (size == 0)
 	if (size == 0)
-		return rc;
+		return 0;
 
 
-	if (io_master_info->master_type == SPI_MASTER) {
+	switch (io_master_info->master_type) {
+	case SPI_MASTER:
 		CAM_DBG(CAM_SENSOR, "Calling SPI Erase");
 		CAM_DBG(CAM_SENSOR, "Calling SPI Erase");
-		return cam_spi_erase(io_master_info, addr,
-			CAMERA_SENSOR_I2C_TYPE_WORD, size);
-	} else if (io_master_info->master_type == I2C_MASTER ||
-		io_master_info->master_type == CCI_MASTER) {
-		CAM_ERR(CAM_SENSOR, "Erase not supported on master :%d",
-			io_master_info->master_type);
-		rc = -EINVAL;
-	} else {
-		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
+		return cam_spi_erase(io_master_info, addr, CAMERA_SENSOR_I2C_TYPE_WORD, size);
+	case I2C_MASTER:
+	case CCI_MASTER:
+	case I3C_MASTER:
+		CAM_ERR(CAM_SENSOR, "Erase not supported on Master Type: %d",
 			io_master_info->master_type);
 			io_master_info->master_type);
-		rc = -EINVAL;
+		return -EINVAL;
+	default:
+		CAM_ERR(CAM_SENSOR, "Invalid Master Type: %d", io_master_info->master_type);
 	}
 	}
-	return rc;
+
+	return -EINVAL;
 }
 }
 
 
 int32_t camera_io_dev_read(struct camera_io_master *io_master_info,
 int32_t camera_io_dev_read(struct camera_io_master *io_master_info,
@@ -75,21 +77,23 @@ int32_t camera_io_dev_read(struct camera_io_master *io_master_info,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	if (io_master_info->master_type == CCI_MASTER) {
-		return cam_cci_i2c_read(io_master_info->cci_client,
-			addr, data, addr_type, data_type, is_probing);
-	} else if (io_master_info->master_type == I2C_MASTER) {
+	switch (io_master_info->master_type) {
+	case SPI_MASTER:
+		return cam_spi_read(io_master_info, addr, data, addr_type, data_type);
+	case I2C_MASTER:
 		return cam_qup_i2c_read(io_master_info->client,
 		return cam_qup_i2c_read(io_master_info->client,
 			addr, data, addr_type, data_type);
 			addr, data, addr_type, data_type);
-	} else if (io_master_info->master_type == SPI_MASTER) {
-		return cam_spi_read(io_master_info,
+	case CCI_MASTER:
+		return cam_cci_i2c_read(io_master_info->cci_client,
+			addr, data, addr_type, data_type, is_probing);
+	case I3C_MASTER:
+		return cam_qup_i3c_read(io_master_info->i3c_client,
 			addr, data, addr_type, data_type);
 			addr, data, addr_type, data_type);
-	} else {
-		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
-			io_master_info->master_type);
-		return -EINVAL;
+	default:
+		CAM_ERR(CAM_SENSOR, "Invalid Master Type: %d", io_master_info->master_type);
 	}
 	}
-	return 0;
+
+	return -EINVAL;
 }
 }
 
 
 int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info,
 int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info,
@@ -97,24 +101,23 @@ int32_t camera_io_dev_read_seq(struct camera_io_master *io_master_info,
 	enum camera_sensor_i2c_type addr_type,
 	enum camera_sensor_i2c_type addr_type,
 	enum camera_sensor_i2c_type data_type, int32_t num_bytes)
 	enum camera_sensor_i2c_type data_type, int32_t num_bytes)
 {
 {
-	if (io_master_info->master_type == CCI_MASTER) {
+	switch (io_master_info->master_type) {
+	case CCI_MASTER:
 		return cam_camera_cci_i2c_read_seq(io_master_info->cci_client,
 		return cam_camera_cci_i2c_read_seq(io_master_info->cci_client,
 			addr, data, addr_type, data_type, num_bytes);
 			addr, data, addr_type, data_type, num_bytes);
-	} else if (io_master_info->master_type == I2C_MASTER) {
+	case I2C_MASTER:
 		return cam_qup_i2c_read_seq(io_master_info->client,
 		return cam_qup_i2c_read_seq(io_master_info->client,
 			addr, data, addr_type, num_bytes);
 			addr, data, addr_type, num_bytes);
-	} else if (io_master_info->master_type == SPI_MASTER) {
-		return cam_spi_read_seq(io_master_info,
-			addr, data, addr_type, num_bytes);
-	} else if (io_master_info->master_type == SPI_MASTER) {
-		return cam_spi_write_seq(io_master_info,
+	case SPI_MASTER:
+		return cam_spi_read_seq(io_master_info, addr, data, addr_type, num_bytes);
+	case I3C_MASTER:
+		return cam_qup_i3c_read_seq(io_master_info->i3c_client,
 			addr, data, addr_type, num_bytes);
 			addr, data, addr_type, num_bytes);
-	} else {
-		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
-			io_master_info->master_type);
-		return -EINVAL;
+	default:
+		CAM_ERR(CAM_SENSOR, "Invalid Master Type: %d", io_master_info->master_type);
 	}
 	}
-	return 0;
+
+	return -EINVAL;
 }
 }
 
 
 int32_t camera_io_dev_write(struct camera_io_master *io_master_info,
 int32_t camera_io_dev_write(struct camera_io_master *io_master_info,
@@ -132,20 +135,20 @@ int32_t camera_io_dev_write(struct camera_io_master *io_master_info,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	if (io_master_info->master_type == CCI_MASTER) {
-		return cam_cci_i2c_write_table(io_master_info,
-			write_setting);
-	} else if (io_master_info->master_type == I2C_MASTER) {
-		return cam_qup_i2c_write_table(io_master_info,
-			write_setting);
-	} else if (io_master_info->master_type == SPI_MASTER) {
-		return cam_spi_write_table(io_master_info,
-			write_setting);
-	} else {
-		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
-			io_master_info->master_type);
-		return -EINVAL;
+	switch (io_master_info->master_type) {
+	case CCI_MASTER:
+		return cam_cci_i2c_write_table(io_master_info, write_setting);
+	case I2C_MASTER:
+		return cam_qup_i2c_write_table(io_master_info, write_setting);
+	case SPI_MASTER:
+		return cam_spi_write_table(io_master_info, write_setting);
+	case I3C_MASTER:
+		return cam_qup_i3c_write_table(io_master_info, write_setting);
+	default:
+		CAM_ERR(CAM_SENSOR, "Invalid Master Type:%d", io_master_info->master_type);
 	}
 	}
+
+	return -EINVAL;
 }
 }
 
 
 int32_t camera_io_dev_write_continuous(struct camera_io_master *io_master_info,
 int32_t camera_io_dev_write_continuous(struct camera_io_master *io_master_info,
@@ -164,20 +167,23 @@ int32_t camera_io_dev_write_continuous(struct camera_io_master *io_master_info,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	if (io_master_info->master_type == CCI_MASTER) {
+	switch (io_master_info->master_type) {
+	case CCI_MASTER:
 		return cam_cci_i2c_write_continuous_table(io_master_info,
 		return cam_cci_i2c_write_continuous_table(io_master_info,
 			write_setting, cam_sensor_i2c_write_flag);
 			write_setting, cam_sensor_i2c_write_flag);
-	} else if (io_master_info->master_type == I2C_MASTER) {
+	case I2C_MASTER:
 		return cam_qup_i2c_write_continuous_table(io_master_info,
 		return cam_qup_i2c_write_continuous_table(io_master_info,
 			write_setting, cam_sensor_i2c_write_flag);
 			write_setting, cam_sensor_i2c_write_flag);
-	} else if (io_master_info->master_type == SPI_MASTER) {
-		return cam_spi_write_table(io_master_info,
-			write_setting);
-	} else {
-		CAM_ERR(CAM_SENSOR, "Invalid Comm. Master:%d",
-			io_master_info->master_type);
-		return -EINVAL;
+	case SPI_MASTER:
+		return cam_spi_write_table(io_master_info, write_setting);
+	case I3C_MASTER:
+		return cam_qup_i3c_write_continuous_table(io_master_info,
+			write_setting, cam_sensor_i2c_write_flag);
+	default:
+		CAM_ERR(CAM_SENSOR, "Invalid Master Type:%d", io_master_info->master_type);
 	}
 	}
+
+	return -EINVAL;
 }
 }
 
 
 int32_t camera_io_init(struct camera_io_master *io_master_info)
 int32_t camera_io_init(struct camera_io_master *io_master_info)
@@ -187,14 +193,16 @@ int32_t camera_io_init(struct camera_io_master *io_master_info)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	if (io_master_info->master_type == CCI_MASTER) {
-		io_master_info->cci_client->cci_subdev =
-		cam_cci_get_subdev(io_master_info->cci_client->cci_device);
-		return cam_sensor_cci_i2c_util(io_master_info->cci_client,
-			MSM_CCI_INIT);
-	} else if ((io_master_info->master_type == I2C_MASTER) ||
-			(io_master_info->master_type == SPI_MASTER)) {
-		return 0;
+	switch (io_master_info->master_type) {
+	case CCI_MASTER:
+		io_master_info->cci_client->cci_subdev = cam_cci_get_subdev(
+						io_master_info->cci_client->cci_device);
+		return cam_sensor_cci_i2c_util(io_master_info->cci_client, MSM_CCI_INIT);
+	case I2C_MASTER:
+	case SPI_MASTER:
+	case I3C_MASTER: return 0;
+	default:
+		CAM_ERR(CAM_SENSOR, "Invalid Master Type:%d", io_master_info->master_type);
 	}
 	}
 
 
 	return -EINVAL;
 	return -EINVAL;
@@ -207,12 +215,14 @@ int32_t camera_io_release(struct camera_io_master *io_master_info)
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	if (io_master_info->master_type == CCI_MASTER) {
-		return cam_sensor_cci_i2c_util(io_master_info->cci_client,
-			MSM_CCI_RELEASE);
-	} else if ((io_master_info->master_type == I2C_MASTER) ||
-			(io_master_info->master_type == SPI_MASTER)) {
-		return 0;
+	switch (io_master_info->master_type) {
+	case CCI_MASTER:
+		return cam_sensor_cci_i2c_util(io_master_info->cci_client, MSM_CCI_RELEASE);
+	case I2C_MASTER:
+	case SPI_MASTER:
+	case I3C_MASTER: return 0;
+	default:
+		CAM_ERR(CAM_SENSOR, "Invalid Master Type:%d", io_master_info->master_type);
 	}
 	}
 
 
 	return -EINVAL;
 	return -EINVAL;

+ 10 - 5
drivers/cam_sensor_module/cam_sensor_io/cam_sensor_io.h

@@ -8,22 +8,25 @@
 #define _CAM_SENSOR_IO_H_
 #define _CAM_SENSOR_IO_H_
 
 
 #include <media/cam_sensor.h>
 #include <media/cam_sensor.h>
-
 #include "cam_sensor_cmn_header.h"
 #include "cam_sensor_cmn_header.h"
 
 
-#define CCI_MASTER 1
-#define I2C_MASTER 2
-#define SPI_MASTER 3
+/* Master Types */
+#define CCI_MASTER           1
+#define I2C_MASTER           2
+#define SPI_MASTER           3
+#define I3C_MASTER           4
 
 
 /**
 /**
  * @master_type: CCI master type
  * @master_type: CCI master type
- * @client: I2C client information structure
+ * @i2c_client: I2C client information structure
+ * @i3c_client: I3C client information structure
  * @cci_client: CCI client information structure
  * @cci_client: CCI client information structure
  * @spi_client: SPI client information structure
  * @spi_client: SPI client information structure
  */
  */
 struct camera_io_master {
 struct camera_io_master {
 	int master_type;
 	int master_type;
 	struct i2c_client *client;
 	struct i2c_client *client;
+	struct i3c_device *i3c_client;
 	struct cam_sensor_cci_client *cci_client;
 	struct cam_sensor_cci_client *cci_client;
 	struct cam_sensor_spi_client *spi_client;
 	struct cam_sensor_spi_client *spi_client;
 };
 };
@@ -116,4 +119,6 @@ int32_t camera_io_dev_poll(struct camera_io_master *io_master_info,
 
 
 #include "cam_sensor_i2c.h"
 #include "cam_sensor_i2c.h"
 #include "cam_sensor_spi.h"
 #include "cam_sensor_spi.h"
+#include "cam_sensor_i3c.h"
+
 #endif /* _CAM_SENSOR_IO_H_ */
 #endif /* _CAM_SENSOR_IO_H_ */

+ 517 - 0
drivers/cam_sensor_module/cam_sensor_io/cam_sensor_qup_i3c.c

@@ -0,0 +1,517 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "cam_sensor_i3c.h"
+#include "cam_sensor_io.h"
+
+#define I3C_REG_MAX_BUF_SIZE   8
+
+static int cam_qup_i3c_rxdata(struct i3c_device *dev_client, unsigned char *rxdata,
+	enum camera_sensor_i2c_type addr_type, int data_length)
+{
+	int rc;
+	struct i3c_priv_xfer read_buf[2] = {
+		{
+			.rnw = 0,
+			.len = addr_type,
+			.data.out = rxdata,
+		},
+		{
+			.rnw = 1,
+			.len = data_length,
+			.data.in = rxdata,
+		},
+	};
+
+	rc = i3c_device_do_priv_xfers(dev_client, read_buf, ARRAY_SIZE(read_buf));
+	if (rc)
+		CAM_ERR(CAM_SENSOR, "Failed with i3c_read: rc = %d", rc);
+
+	return rc;
+}
+
+
+static int cam_qup_i3c_txdata(struct camera_io_master *dev_client, unsigned char *txdata,
+	int length)
+{
+	int rc;
+	struct i3c_priv_xfer write_buf = {
+		.rnw = 0,
+		.len = length,
+		.data.out = txdata,
+	};
+
+	rc = i3c_device_do_priv_xfers(dev_client->i3c_client, &write_buf, 1);
+	if (rc)
+		CAM_ERR(CAM_SENSOR, "Failed with i3c_write: rc = %d", rc);
+
+	return rc;
+}
+
+int cam_qup_i3c_read(struct i3c_device *client, uint32_t addr, uint32_t *data,
+	enum camera_sensor_i2c_type addr_type,
+	enum camera_sensor_i2c_type data_type)
+{
+	int rc;
+	unsigned char *buf;
+
+	if ((addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID)
+		|| (addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX)
+		|| (data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID)
+		|| (data_type >= CAMERA_SENSOR_I2C_TYPE_MAX)) {
+		CAM_ERR(CAM_SENSOR, "Failed with addr/data_type verfication");
+		return -EINVAL;
+	}
+
+	buf = kzalloc(addr_type + data_type, GFP_DMA | GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
+		buf[0] = addr;
+	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) {
+		buf[0] = addr >> 8;
+		buf[1] = addr;
+	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) {
+		buf[0] = addr >> 16;
+		buf[1] = addr >> 8;
+		buf[2] = addr;
+	} else {
+		buf[0] = addr >> 24;
+		buf[1] = addr >> 16;
+		buf[2] = addr >> 8;
+		buf[3] = addr;
+	}
+
+	rc = cam_qup_i3c_rxdata(client, buf, addr_type, data_type);
+	if (rc) {
+		CAM_ERR(CAM_SENSOR, "failed rc: %d", rc);
+		goto read_fail;
+	}
+
+	if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE)
+		*data = buf[0];
+	else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD)
+		*data = (buf[0] << 8) | buf[1];
+	else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B)
+		*data = (buf[0] << 16) | (buf[1] << 8) | buf[2];
+	else
+		*data = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+
+	CAM_DBG(CAM_SENSOR, "addr = 0x%x data: 0x%x", addr, *data);
+read_fail:
+	kfree(buf);
+	return rc;
+}
+
+int cam_qup_i3c_read_seq(struct i3c_device *client,
+	uint32_t addr, uint8_t *data,
+	enum camera_sensor_i2c_type addr_type,
+	uint32_t num_byte)
+{
+	int rc;
+	unsigned char *buf;
+	int i;
+
+	if (addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID
+		|| addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
+		CAM_ERR(CAM_SENSOR, "Failed with addr_type verification");
+		return -EFAULT;
+	}
+
+	if ((num_byte == 0) || (num_byte > I2C_REG_DATA_MAX)) {
+		CAM_ERR(CAM_SENSOR, "num_byte:0x%x max supported:0x%x",
+			num_byte, I2C_REG_DATA_MAX);
+		return -EFAULT;
+	}
+
+	buf = kzalloc(addr_type + num_byte, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
+		buf[0] = addr;
+	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) {
+		buf[0] = addr >> BITS_PER_BYTE;
+		buf[1] = addr;
+	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) {
+		buf[0] = addr >> 16;
+		buf[1] = addr >> 8;
+		buf[2] = addr;
+	} else {
+		buf[0] = addr >> 24;
+		buf[1] = addr >> 16;
+		buf[2] = addr >> 8;
+		buf[3] = addr;
+	}
+
+	rc = cam_qup_i3c_rxdata(client, buf, addr_type, num_byte);
+	if (rc) {
+		CAM_ERR(CAM_SENSOR, "failed rc: %d", rc);
+		goto read_seq_fail;
+	}
+
+	for (i = 0; i < num_byte; i++)
+		data[i] = buf[i];
+
+read_seq_fail:
+	kfree(buf);
+	return rc;
+}
+
+static int cam_qup_i3c_compare(struct i3c_device *client,
+	uint32_t addr, uint32_t data, uint16_t data_mask,
+	enum camera_sensor_i2c_type data_type,
+	enum camera_sensor_i2c_type addr_type)
+{
+	int rc;
+	uint32_t reg_data;
+
+	rc = cam_qup_i3c_read(client, addr, &reg_data,
+		addr_type, data_type);
+	if (rc < 0)
+		return rc;
+
+	reg_data = reg_data & 0xFFFF;
+	if (data != (reg_data & ~data_mask))
+		return I2C_COMPARE_MISMATCH;
+
+	return I2C_COMPARE_MATCH;
+}
+
+int cam_qup_i3c_poll(struct i3c_device *client,
+	uint32_t addr, uint16_t data, uint16_t data_mask,
+	enum camera_sensor_i2c_type addr_type,
+	enum camera_sensor_i2c_type data_type,
+	uint32_t delay_ms)
+{
+	int rc;
+	int i;
+
+	if ((delay_ms > MAX_POLL_DELAY_MS) || (delay_ms == 0)) {
+		CAM_ERR(CAM_SENSOR, "invalid delay = %d max_delay = %d",
+			delay_ms, MAX_POLL_DELAY_MS);
+		return -EINVAL;
+	}
+
+	if ((addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID
+		|| addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX
+		|| data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID
+		|| data_type >= CAMERA_SENSOR_I2C_TYPE_MAX))
+		return -EINVAL;
+
+	for (i = 0; i < delay_ms; i++) {
+		rc = cam_qup_i3c_compare(client,
+			addr, data, data_mask, data_type, addr_type);
+		if (rc == I2C_COMPARE_MATCH)
+			return rc;
+
+		usleep_range(1000, 1010);
+	}
+	/* If rc is MISMATCH then read is successful but poll is failure */
+	if (rc == I2C_COMPARE_MISMATCH)
+		CAM_ERR(CAM_SENSOR, "poll failed rc=%d(non-fatal)", rc);
+	if (rc < 0)
+		CAM_ERR(CAM_SENSOR, "poll failed rc=%d", rc);
+
+	return rc;
+}
+
+static int cam_qup_i3c_write(struct camera_io_master *client,
+	struct cam_sensor_i2c_reg_array *reg_setting,
+	enum camera_sensor_i2c_type addr_type,
+	enum camera_sensor_i2c_type data_type)
+{
+	int rc;
+	unsigned char *buf = NULL;
+	uint8_t len = 0;
+
+	buf = kzalloc(I3C_REG_MAX_BUF_SIZE, GFP_KERNEL | GFP_DMA);
+	if (!buf) {
+		CAM_ERR(CAM_SENSOR, "Buffer memory allocation failed");
+		return -ENOMEM;
+	}
+
+	CAM_DBG(CAM_SENSOR, "reg addr = 0x%x data type: %d",
+			reg_setting->reg_addr, data_type);
+	if (addr_type == CAMERA_SENSOR_I2C_TYPE_INVALID) {
+		buf[0] = reg_setting->reg_addr;
+		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]);
+		len = 1;
+	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) {
+		buf[0] = reg_setting->reg_addr >> 8;
+		buf[1] = reg_setting->reg_addr;
+		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]);
+		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len+1, buf[len+1]);
+		len = 2;
+	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) {
+		buf[0] = reg_setting->reg_addr >> 16;
+		buf[1] = reg_setting->reg_addr >> 8;
+		buf[2] = reg_setting->reg_addr;
+		len = 3;
+	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_DWORD) {
+		buf[0] = reg_setting->reg_addr >> 24;
+		buf[1] = reg_setting->reg_addr >> 16;
+		buf[2] = reg_setting->reg_addr >> 8;
+		buf[3] = reg_setting->reg_addr;
+		len = 4;
+	} else {
+		CAM_ERR(CAM_SENSOR, "Invalid I2C addr type");
+		rc = -EINVAL;
+		goto deallocate_buffer;
+	}
+
+	CAM_DBG(CAM_SENSOR, "Data: 0x%x", reg_setting->reg_data);
+	if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
+		buf[len] = reg_setting->reg_data;
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]);
+		len += 1;
+	} else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) {
+		buf[len] = reg_setting->reg_data >> 8;
+		buf[len+1] = reg_setting->reg_data;
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]);
+		len += 2;
+	} else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) {
+		buf[len] = reg_setting->reg_data >> 16;
+		buf[len + 1] = reg_setting->reg_data >> 8;
+		buf[len + 2] = reg_setting->reg_data;
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+2, buf[len+2]);
+		len += 3;
+	} else if (data_type == CAMERA_SENSOR_I2C_TYPE_DWORD) {
+		buf[len] = reg_setting->reg_data >> 24;
+		buf[len + 1] = reg_setting->reg_data >> 16;
+		buf[len + 2] = reg_setting->reg_data >> 8;
+		buf[len + 3] = reg_setting->reg_data;
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len, buf[len]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+1, buf[len+1]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+2, buf[len+2]);
+		CAM_DBG(CAM_SENSOR, "Byte %d: 0x%x", len+3, buf[len+3]);
+		len += 4;
+	} else {
+		CAM_ERR(CAM_SENSOR, "Invalid Data Type");
+		rc = -EINVAL;
+		goto deallocate_buffer;
+	}
+
+	rc = cam_qup_i3c_txdata(client, buf, len);
+	if (rc)
+		CAM_ERR(CAM_SENSOR, "failed rc: %d", rc);
+
+deallocate_buffer:
+	kfree(buf);
+	return rc;
+}
+
+int cam_qup_i3c_write_table(struct camera_io_master *client,
+	struct cam_sensor_i2c_reg_setting *write_setting)
+{
+	int i;
+	int rc = -EINVAL;
+	struct cam_sensor_i2c_reg_array *reg_setting;
+
+	if (!client || !write_setting)
+		return -EINVAL;
+
+	if ((write_setting->addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID
+		|| write_setting->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX
+		|| (write_setting->data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID
+		|| write_setting->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX)))
+		return -EINVAL;
+
+	reg_setting = write_setting->reg_setting;
+
+	for (i = 0; i < write_setting->size; i++) {
+		CAM_DBG(CAM_SENSOR, "addr 0x%x data 0x%x",
+			reg_setting->reg_addr, reg_setting->reg_data);
+
+		rc = cam_qup_i3c_write(client, reg_setting,
+			write_setting->addr_type, write_setting->data_type);
+		if (rc < 0)
+			break;
+		reg_setting++;
+	}
+
+	if (write_setting->delay > 20)
+		msleep(write_setting->delay);
+	else if (write_setting->delay)
+		usleep_range(write_setting->delay * 1000, (write_setting->delay
+			* 1000) + 1000);
+
+	return rc;
+}
+
+static int cam_qup_i3c_write_seq(struct camera_io_master *client,
+	struct cam_sensor_i2c_reg_setting *write_setting)
+{
+	int i;
+	int rc = 0;
+	struct cam_sensor_i2c_reg_array *reg_setting;
+
+	reg_setting = write_setting->reg_setting;
+
+	for (i = 0; i < write_setting->size; i++) {
+		reg_setting->reg_addr += i;
+		rc = cam_qup_i3c_write(client, reg_setting,
+			write_setting->addr_type, write_setting->data_type);
+		if (rc < 0) {
+			CAM_ERR(CAM_SENSOR,
+				"Sequential i2c write failed: rc: %d", rc);
+			break;
+		}
+		reg_setting++;
+	}
+
+	if (write_setting->delay > 20)
+		msleep(write_setting->delay);
+	else if (write_setting->delay)
+		usleep_range(write_setting->delay * 1000, (write_setting->delay
+			* 1000) + 1000);
+
+	return rc;
+}
+
+static int cam_qup_i3c_write_burst(struct camera_io_master *client,
+	struct cam_sensor_i2c_reg_setting *write_setting)
+{
+	int i;
+	int rc;
+	uint32_t len = 0;
+	unsigned char *buf;
+	struct cam_sensor_i2c_reg_array *reg_setting;
+	enum camera_sensor_i2c_type addr_type;
+	enum camera_sensor_i2c_type data_type;
+
+	buf = kzalloc((write_setting->addr_type +
+			(write_setting->size * write_setting->data_type)),
+			GFP_DMA | GFP_KERNEL);
+
+	if (!buf) {
+		CAM_ERR(CAM_SENSOR, "BUF is NULL");
+		return -ENOMEM;
+	}
+
+	reg_setting = write_setting->reg_setting;
+	addr_type = write_setting->addr_type;
+	data_type = write_setting->data_type;
+
+	CAM_DBG(CAM_SENSOR, "reg addr = 0x%x data type: %d",
+			reg_setting->reg_addr, data_type);
+	if (addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
+		buf[0] = reg_setting->reg_addr;
+		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]);
+		len = 1;
+	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_WORD) {
+		buf[0] = reg_setting->reg_addr >> 8;
+		buf[1] = reg_setting->reg_addr;
+		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len, buf[len]);
+		CAM_DBG(CAM_SENSOR, "byte %d: 0x%x", len+1, buf[len+1]);
+		len = 2;
+	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_3B) {
+		buf[0] = reg_setting->reg_addr >> 16;
+		buf[1] = reg_setting->reg_addr >> 8;
+		buf[2] = reg_setting->reg_addr;
+		len = 3;
+	} else if (addr_type == CAMERA_SENSOR_I2C_TYPE_DWORD) {
+		buf[0] = reg_setting->reg_addr >> 24;
+		buf[1] = reg_setting->reg_addr >> 16;
+		buf[2] = reg_setting->reg_addr >> 8;
+		buf[3] = reg_setting->reg_addr;
+		len = 4;
+	} else {
+		CAM_ERR(CAM_SENSOR, "Invalid I2C addr type");
+		rc = -EINVAL;
+		goto free_res;
+	}
+
+	for (i = 0; i < write_setting->size; i++) {
+		if (data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
+			buf[len] = reg_setting->reg_data;
+			CAM_DBG(CAM_SENSOR,
+				"Byte %d: 0x%x", len, buf[len]);
+			len += 1;
+		} else if (data_type == CAMERA_SENSOR_I2C_TYPE_WORD) {
+			buf[len] = reg_setting->reg_data >> 8;
+			buf[len+1] = reg_setting->reg_data;
+			CAM_DBG(CAM_SENSOR,
+				"Byte %d: 0x%x", len, buf[len]);
+			CAM_DBG(CAM_SENSOR,
+				"Byte %d: 0x%x", len+1, buf[len+1]);
+			len += 2;
+		} else if (data_type == CAMERA_SENSOR_I2C_TYPE_3B) {
+			buf[len] = reg_setting->reg_data >> 16;
+			buf[len + 1] = reg_setting->reg_data >> 8;
+			buf[len + 2] = reg_setting->reg_data;
+			CAM_DBG(CAM_SENSOR,
+				"Byte %d: 0x%x", len, buf[len]);
+			CAM_DBG(CAM_SENSOR,
+				"Byte %d: 0x%x", len+1, buf[len+1]);
+			CAM_DBG(CAM_SENSOR,
+				"Byte %d: 0x%x", len+2, buf[len+2]);
+			len += 3;
+		} else if (data_type == CAMERA_SENSOR_I2C_TYPE_DWORD) {
+			buf[len] = reg_setting->reg_data >> 24;
+			buf[len + 1] = reg_setting->reg_data >> 16;
+			buf[len + 2] = reg_setting->reg_data >> 8;
+			buf[len + 3] = reg_setting->reg_data;
+			CAM_DBG(CAM_SENSOR,
+				"Byte %d: 0x%x", len, buf[len]);
+			CAM_DBG(CAM_SENSOR,
+				"Byte %d: 0x%x", len+1, buf[len+1]);
+			CAM_DBG(CAM_SENSOR,
+				"Byte %d: 0x%x", len+2, buf[len+2]);
+			CAM_DBG(CAM_SENSOR,
+				"Byte %d: 0x%x", len+3, buf[len+3]);
+			len += 4;
+		} else {
+			CAM_ERR(CAM_SENSOR, "Invalid Data Type");
+			rc = -EINVAL;
+			goto free_res;
+		}
+		reg_setting++;
+	}
+
+	if (len > (write_setting->addr_type +
+		(write_setting->size * write_setting->data_type))) {
+		CAM_ERR(CAM_SENSOR, "Invalid Length: %u | Expected length: %u",
+			len, (write_setting->addr_type +
+			(write_setting->size * write_setting->data_type)));
+		rc = -EINVAL;
+		goto free_res;
+	}
+
+	rc = cam_qup_i3c_txdata(client, buf, len);
+	if (rc < 0)
+		CAM_ERR(CAM_SENSOR, "failed rc: %d", rc);
+
+free_res:
+	kfree(buf);
+	return rc;
+}
+
+int cam_qup_i3c_write_continuous_table(struct camera_io_master *client,
+	struct cam_sensor_i2c_reg_setting *write_settings,
+	uint8_t cam_sensor_i2c_write_flag)
+{
+	int rc = 0;
+
+	if (!client || !write_settings)
+		return -EINVAL;
+
+	if ((write_settings->addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID
+		|| write_settings->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX
+		|| (write_settings->data_type <= CAMERA_SENSOR_I2C_TYPE_INVALID
+		|| write_settings->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX)))
+		return -EINVAL;
+
+	if (cam_sensor_i2c_write_flag == CAM_SENSOR_I2C_WRITE_BURST)
+		rc = cam_qup_i3c_write_burst(client, write_settings);
+	else if (cam_sensor_i2c_write_flag == CAM_SENSOR_I2C_WRITE_SEQ)
+		rc = cam_qup_i3c_write_seq(client, write_settings);
+
+	return rc;
+}

+ 7 - 4
drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_cmn_header.h

@@ -8,6 +8,7 @@
 #define _CAM_SENSOR_CMN_HEADER_
 #define _CAM_SENSOR_CMN_HEADER_
 
 
 #include <linux/i2c.h>
 #include <linux/i2c.h>
+#include <linux/i3c/master.h>
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
@@ -19,10 +20,12 @@
 #include <media/cam_sensor.h>
 #include <media/cam_sensor.h>
 #include <media/cam_req_mgr.h>
 #include <media/cam_req_mgr.h>
 
 
-#define MAX_POWER_CONFIG    12
-
-#define MAX_PER_FRAME_ARRAY 32
-#define BATCH_SIZE_MAX      16
+#define MAX_POWER_CONFIG                       12
+#define MAX_PER_FRAME_ARRAY                    32
+#define BATCH_SIZE_MAX                         16
+#define CAM_SENSOR_I3C_PROBE_TIMEOUT_MS        10
+#define I3C_SENSOR_DEV_ID_DT_PATH              "/soc/qcom,cam-i3c-id-table"
+#define MAX_I3C_DEVICE_ID_ENTRIES              MAX_CAMERAS
 
 
 #define CAM_SENSOR_NAME    "cam-sensor"
 #define CAM_SENSOR_NAME    "cam-sensor"
 #define CAM_ACTUATOR_NAME  "cam-actuator"
 #define CAM_ACTUATOR_NAME  "cam-actuator"

+ 12 - 0
drivers/cam_utils/cam_compat.c

@@ -364,6 +364,12 @@ void cam_compat_util_put_dmabuf_va(struct dma_buf *dmabuf, void *vaddr)
 
 
 	dma_buf_vunmap(dmabuf, &mapping);
 	dma_buf_vunmap(dmabuf, &mapping);
 }
 }
+
+void cam_sensor_i3c_driver_remove(struct i3c_device *client)
+{
+	CAM_DBG(CAM_SENSOR, "I3C remove invoked for %s", dev_name(i3cdev_to_dev(client)));
+}
+
 #else
 #else
 void cam_smmu_util_iommu_custom(struct device *dev,
 void cam_smmu_util_iommu_custom(struct device *dev,
 	dma_addr_t discard_start, size_t discard_length)
 	dma_addr_t discard_start, size_t discard_length)
@@ -402,4 +408,10 @@ void cam_compat_util_put_dmabuf_va(struct dma_buf *dmabuf, void *vaddr)
 {
 {
 	dma_buf_vunmap(dmabuf, vaddr);
 	dma_buf_vunmap(dmabuf, vaddr);
 }
 }
+
+int cam_sensor_i3c_driver_remove(struct i3c_device *client)
+{
+	CAM_DBG(CAM_SENSOR, "I3C remove invoked for %s", dev_name(i3cdev_to_dev(client)));
+	return 0;
+}
 #endif
 #endif

+ 2 - 0
drivers/cam_utils/cam_compat.h

@@ -58,9 +58,11 @@ void cam_smmu_util_iommu_custom(struct device *dev,
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 0)
 int cam_req_mgr_ordered_list_cmp(void *priv,
 int cam_req_mgr_ordered_list_cmp(void *priv,
 	const struct list_head *head_1, const struct list_head *head_2);
 	const struct list_head *head_1, const struct list_head *head_2);
+void cam_sensor_i3c_driver_remove(struct i3c_device *client);
 #else
 #else
 int cam_req_mgr_ordered_list_cmp(void *priv,
 int cam_req_mgr_ordered_list_cmp(void *priv,
 	struct list_head *head_1, struct list_head *head_2);
 	struct list_head *head_1, struct list_head *head_2);
+int cam_sensor_i3c_driver_remove(struct i3c_device *client);
 #endif
 #endif
 
 
 #endif /* _CAM_COMPAT_H_ */
 #endif /* _CAM_COMPAT_H_ */