Browse Source

msm: camera: isp: Add support for SFE sys cache config

Add support for using system cache for SFE WMs and RMs
in case of sHDR use-cases for power saving. Also add
debugfs capability to control this feature.

CRs-Fixed: 2841729
Change-Id: Ic4dad50e8c396705b33bb0bc8330d25e51ca79a2
Signed-off-by: Karthik Anantha Ram <[email protected]>
Karthik Anantha Ram 4 years ago
parent
commit
c369310c4a

+ 179 - 0
drivers/cam_cpas/cam_cpas_hw.c

@@ -2191,6 +2191,149 @@ done:
 	return rc;
 }
 
+static int cam_cpas_activate_cache(
+	struct cam_hw_info *cpas_hw,
+	struct cam_sys_cache_info *cache_info)
+{
+	int rc = 0;
+
+	mutex_lock(&cpas_hw->hw_mutex);
+	cache_info->ref_cnt++;
+	if (cache_info->ref_cnt > 1) {
+		mutex_unlock(&cpas_hw->hw_mutex);
+		CAM_DBG(CAM_CPAS, "Cache: %s has already been activated cnt: %d",
+			cache_info->name, cache_info->ref_cnt);
+		return rc;
+	}
+
+	rc = llcc_slice_activate(cache_info->slic_desc);
+	if (rc) {
+		CAM_ERR(CAM_CPAS, "Failed to activate cache:%s",
+			cache_info->name);
+		goto end;
+	}
+
+	mutex_unlock(&cpas_hw->hw_mutex);
+	CAM_DBG(CAM_CPAS, "Activated cache:%s", cache_info->name);
+	return rc;
+
+end:
+	cache_info->ref_cnt--;
+	mutex_unlock(&cpas_hw->hw_mutex);
+	return rc;
+}
+
+static int cam_cpas_deactivate_cache(
+	struct cam_hw_info *cpas_hw,
+	struct cam_sys_cache_info *cache_info)
+{
+	int rc = 0;
+
+	mutex_lock(&cpas_hw->hw_mutex);
+	if (!cache_info->ref_cnt) {
+		mutex_unlock(&cpas_hw->hw_mutex);
+		CAM_ERR(CAM_CPAS, "Unbalanced deactivate");
+		return -EFAULT;
+	}
+
+	cache_info->ref_cnt--;
+	if (cache_info->ref_cnt) {
+		mutex_unlock(&cpas_hw->hw_mutex);
+		CAM_DBG(CAM_CPAS, "activate cnt for: %s non-zero: %d",
+			cache_info->name, cache_info->ref_cnt);
+		return rc;
+	}
+
+	rc = llcc_slice_deactivate(cache_info->slic_desc);
+	if (rc)
+		CAM_ERR(CAM_CPAS, "Failed to deactivate cache:%s",
+			cache_info->name);
+
+	mutex_unlock(&cpas_hw->hw_mutex);
+	CAM_DBG(CAM_CPAS, "De-activated cache:%s", cache_info->name);
+	return rc;
+}
+
+static inline int cam_cpas_validate_cache_type(
+	uint32_t num_caches, enum cam_sys_cache_config_types type)
+{
+	if ((!num_caches) || (type < 0) || (type >= num_caches))
+		return -EINVAL;
+	else
+		return 0;
+}
+
+static int cam_cpas_get_slice_id(
+	struct cam_hw_info *cpas_hw,
+	enum cam_sys_cache_config_types type)
+{
+	struct cam_cpas_private_soc *soc_private =
+		(struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
+	uint32_t num_caches = soc_private->num_caches;
+	int scid = -1, i;
+
+	if (cam_cpas_validate_cache_type(num_caches, type))
+		goto end;
+
+	for (i = 0; i < num_caches; i++) {
+		if (type == soc_private->llcc_info[i].type) {
+			scid = soc_private->llcc_info[i].scid;
+			CAM_DBG(CAM_CPAS, "Cache:%s type:%d scid:%d",
+				soc_private->llcc_info[i].name, type, scid);
+			break;
+		}
+	}
+
+end:
+	return scid;
+}
+
+static int cam_cpas_activate_cache_slice(
+	struct cam_hw_info *cpas_hw,
+	enum cam_sys_cache_config_types type)
+{
+	struct cam_cpas_private_soc *soc_private =
+		(struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
+	uint32_t num_caches = soc_private->num_caches;
+	int rc = 0, i;
+
+	CAM_DBG(CAM_CPAS, "Activate type: %d", type);
+	if (cam_cpas_validate_cache_type(num_caches, type))
+		goto end;
+
+	for (i = 0; i < num_caches; i++) {
+		if (type == soc_private->llcc_info[i].type)
+			rc = cam_cpas_activate_cache(cpas_hw,
+				&soc_private->llcc_info[i]);
+	}
+
+end:
+	return rc;
+}
+
+static int cam_cpas_deactivate_cache_slice(
+	struct cam_hw_info *cpas_hw,
+	enum cam_sys_cache_config_types type)
+{
+	struct cam_cpas_private_soc *soc_private =
+		(struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
+	uint32_t num_caches = soc_private->num_caches;
+	int rc = 0, i;
+
+	CAM_DBG(CAM_CPAS, "De-activate type: %d", type);
+	if (cam_cpas_validate_cache_type(num_caches, type))
+		goto end;
+
+	for (i = 0; i < num_caches; i++) {
+		if (type == soc_private->llcc_info[i].type)
+			rc = cam_cpas_deactivate_cache(cpas_hw,
+				&soc_private->llcc_info[i]);
+	}
+
+end:
+	return rc;
+}
+
 static int cam_cpas_hw_process_cmd(void *hw_priv,
 	uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
 {
@@ -2327,6 +2470,42 @@ static int cam_cpas_hw_process_cmd(void *hw_priv,
 		rc = cam_cpas_select_qos(hw_priv, *selection_mask);
 		break;
 	}
+	case CAM_CPAS_HW_CMD_GET_SCID: {
+		enum cam_sys_cache_config_types type;
+
+		if (sizeof(enum cam_sys_cache_config_types) != arg_size) {
+			CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
+				cmd_type, arg_size);
+			break;
+		}
+		type = *((enum cam_sys_cache_config_types *) cmd_args);
+		rc = cam_cpas_get_slice_id(hw_priv, type);
+	}
+		break;
+	case CAM_CPAS_HW_CMD_ACTIVATE_LLC: {
+		enum cam_sys_cache_config_types type;
+
+		if (sizeof(enum cam_sys_cache_config_types) != arg_size) {
+			CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
+				cmd_type, arg_size);
+			break;
+		}
+		type = *((enum cam_sys_cache_config_types *) cmd_args);
+		rc = cam_cpas_activate_cache_slice(hw_priv, type);
+	}
+		break;
+	case CAM_CPAS_HW_CMD_DEACTIVATE_LLC: {
+		enum cam_sys_cache_config_types type;
+
+		if (sizeof(enum cam_sys_cache_config_types) != arg_size) {
+			CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
+				cmd_type, arg_size);
+			break;
+		}
+		type = *((enum cam_sys_cache_config_types *) cmd_args);
+		rc = cam_cpas_deactivate_cache_slice(hw_priv, type);
+	}
+		break;
 	default:
 		CAM_ERR(CAM_CPAS, "CPAS HW command not valid =%d", cmd_type);
 		break;

+ 4 - 1
drivers/cam_cpas/cam_cpas_hw_intf.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _CAM_CPAS_HW_INTF_H_
@@ -43,6 +43,9 @@ enum cam_cpas_hw_cmd_process {
 	CAM_CPAS_HW_CMD_LOG_VOTE,
 	CAM_CPAS_HW_CMD_SELECT_QOS,
 	CAM_CPAS_HW_CMD_LOG_EVENT,
+	CAM_CPAS_HW_CMD_GET_SCID,
+	CAM_CPAS_HW_CMD_ACTIVATE_LLC,
+	CAM_CPAS_HW_CMD_DEACTIVATE_LLC,
 	CAM_CPAS_HW_CMD_INVALID,
 };
 

+ 76 - 0
drivers/cam_cpas/cam_cpas_intf.c

@@ -589,6 +589,82 @@ int cam_cpas_register_client(
 }
 EXPORT_SYMBOL(cam_cpas_register_client);
 
+int cam_cpas_get_scid(
+	enum cam_sys_cache_config_types type)
+{
+	int rc;
+
+	if (!CAM_CPAS_INTF_INITIALIZED()) {
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
+		return -ENODEV;
+	}
+
+	if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
+		rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
+			g_cpas_intf->hw_intf->hw_priv,
+			CAM_CPAS_HW_CMD_GET_SCID, &type,
+			sizeof(type));
+	} else {
+		CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(cam_cpas_get_scid);
+
+int cam_cpas_activate_llcc(
+	enum cam_sys_cache_config_types type)
+{
+	int rc;
+
+	if (!CAM_CPAS_INTF_INITIALIZED()) {
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
+		return -ENODEV;
+	}
+
+	if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
+		rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
+			g_cpas_intf->hw_intf->hw_priv,
+			CAM_CPAS_HW_CMD_ACTIVATE_LLC, &type,
+			sizeof(type));
+		if (rc)
+			CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
+	} else {
+		CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(cam_cpas_activate_llcc);
+
+int cam_cpas_deactivate_llcc(
+	enum cam_sys_cache_config_types type)
+{
+	int rc;
+
+	if (!CAM_CPAS_INTF_INITIALIZED()) {
+		CAM_ERR(CAM_CPAS, "cpas intf not initialized");
+		return -ENODEV;
+	}
+
+	if (g_cpas_intf->hw_intf->hw_ops.process_cmd) {
+		rc = g_cpas_intf->hw_intf->hw_ops.process_cmd(
+			g_cpas_intf->hw_intf->hw_priv,
+			CAM_CPAS_HW_CMD_DEACTIVATE_LLC, &type,
+			sizeof(type));
+		if (rc)
+			CAM_ERR(CAM_CPAS, "Failed in process_cmd, rc=%d", rc);
+	} else {
+		CAM_ERR(CAM_CPAS, "Invalid process_cmd ops");
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+EXPORT_SYMBOL(cam_cpas_deactivate_llcc);
+
 int cam_cpas_subdev_cmd(struct cam_cpas_intf *cpas_intf,
 	struct cam_control *cmd)
 {

+ 109 - 0
drivers/cam_cpas/cam_cpas_soc.c

@@ -637,6 +637,105 @@ end:
 	return 0;
 }
 
+static inline enum cam_sys_cache_config_types cam_cpas_find_type_from_string(
+	const char *cache_name)
+{
+	if (strcmp(cache_name, "small-1") == 0)
+		return CAM_LLCC_SMALL_1;
+	else if (strcmp(cache_name, "small-2") == 0)
+		return CAM_LLCC_SMALL_2;
+	else
+		return CAM_LLCC_MAX;
+}
+
+static int cam_cpas_parse_sys_cache_uids(
+	struct device_node          *of_node,
+	struct cam_cpas_private_soc *soc_private)
+{
+	enum cam_sys_cache_config_types type = CAM_LLCC_MAX;
+	int num_caches, i, rc;
+	uint32_t scid;
+
+	soc_private->llcc_info = NULL;
+	soc_private->num_caches = 0;
+
+	num_caches = of_property_count_strings(of_node, "sys-cache-names");
+	if (num_caches <= 0) {
+		CAM_DBG(CAM_CPAS, "no cache-names found");
+		return 0;
+	}
+
+	if (num_caches > CAM_LLCC_MAX) {
+		CAM_ERR(CAM_CPAS,
+			"invalid number of cache-names found: 0x%x",
+			num_caches);
+		return -EINVAL;
+	}
+
+	soc_private->llcc_info = kcalloc(num_caches,
+		sizeof(struct cam_sys_cache_info), GFP_KERNEL);
+	if (!soc_private->llcc_info)
+		return -ENOMEM;
+
+	for (i = 0; i < num_caches; i++) {
+		rc = of_property_read_string_index(of_node, "sys-cache-names", i,
+			&soc_private->llcc_info[i].name);
+		if (rc) {
+			CAM_ERR(CAM_CPAS, "failed to read cache-names at %d", i);
+			goto end;
+		}
+
+		type = cam_cpas_find_type_from_string(
+			soc_private->llcc_info[i].name);
+		if (type == CAM_LLCC_MAX) {
+			CAM_ERR(CAM_CPAS, "Unsupported cache found: %s",
+				soc_private->llcc_info[i].name);
+			rc = -EINVAL;
+			goto end;
+		}
+
+		soc_private->llcc_info[i].type = type;
+		rc = of_property_read_u32_index(of_node,
+				"sys-cache-uids", i,
+				&soc_private->llcc_info[i].uid);
+		if (rc < 0) {
+			CAM_ERR(CAM_CPAS,
+				"unable to read sys cache uid at index %d", i);
+			goto end;
+		}
+
+		soc_private->llcc_info[i].slic_desc =
+			llcc_slice_getd(soc_private->llcc_info[i].uid);
+
+		if (IS_ERR_OR_NULL(soc_private->llcc_info[i].slic_desc)) {
+			CAM_ERR(CAM_CPAS,
+				"Failed to get slice desc for uid %u",
+				soc_private->llcc_info[i].uid);
+			rc = -EINVAL;
+			goto end;
+		}
+
+		scid = llcc_get_slice_id(soc_private->llcc_info[i].slic_desc);
+		soc_private->llcc_info[i].scid = scid;
+		soc_private->llcc_info[i].size =
+			llcc_get_slice_size(soc_private->llcc_info[i].slic_desc);
+		soc_private->num_caches++;
+
+		CAM_DBG(CAM_CPAS,
+			"Cache: %s uid: %u scid: %d size: %zukb",
+			soc_private->llcc_info[i].name,
+			soc_private->llcc_info[i].uid, scid,
+			soc_private->llcc_info[i].size);
+	}
+
+	return 0;
+
+end:
+	kfree(soc_private->llcc_info);
+	soc_private->llcc_info = NULL;
+	return rc;
+}
+
 int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
 	struct platform_device *pdev, struct cam_cpas_private_soc *soc_private)
 {
@@ -952,8 +1051,16 @@ int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
 		CAM_DBG(CAM_CPAS, "RPMH BCM info not available in DT, count=%d",
 			count);
 	}
+
+	/* check cache info */
+	rc = cam_cpas_parse_sys_cache_uids(of_node, soc_private);
+	if (rc)
+		goto cache_parse_fail;
+
 	return 0;
 
+cache_parse_fail:
+	soc_private->rpmh_info[CAM_RPMH_NUMBER_OF_BCMS] = 0;
 cleanup_tree:
 	cam_cpas_node_tree_cleanup(cpas_core, soc_private);
 cleanup_clients:
@@ -1011,11 +1118,13 @@ release_res:
 int cam_cpas_soc_deinit_resources(struct cam_hw_soc_info *soc_info)
 {
 	int rc;
+	struct cam_cpas_private_soc *soc_private = soc_info->soc_private;
 
 	rc = cam_soc_util_release_platform_resource(soc_info);
 	if (rc)
 		CAM_ERR(CAM_CPAS, "release platform failed, rc=%d", rc);
 
+	kfree(soc_private->llcc_info);
 	kfree(soc_info->soc_private);
 	soc_info->soc_private = NULL;
 

+ 25 - 0
drivers/cam_cpas/cam_cpas_soc.h

@@ -6,6 +6,7 @@
 #ifndef _CAM_CPAS_SOC_H_
 #define _CAM_CPAS_SOC_H_
 
+#include <linux/soc/qcom/llcc-qcom.h>
 #include "cam_soc_util.h"
 #include "cam_cpas_hw.h"
 
@@ -89,6 +90,26 @@ struct cam_cpas_feature_info {
 	uint32_t hw_map;
 };
 
+/**
+ * struct cam_sys_cache_info : Last level camera cache info
+ *
+ * @ref_cnt:   Ref cnt activate/deactivate cache
+ * @type:      cache type small/large etc.
+ * @uid:       Client user ID
+ * @size:      Cache size
+ * @scid:      Slice ID
+ * @slic_desc: Slice descriptor
+ */
+struct cam_sys_cache_info {
+	uint32_t                         ref_cnt;
+	enum cam_sys_cache_config_types  type;
+	uint32_t                         uid;
+	size_t                           size;
+	int32_t                          scid;
+	const char                      *name;
+	struct llcc_slice_desc          *slic_desc;
+};
+
 /**
  * struct cam_cpas_private_soc : CPAS private DT info
  *
@@ -112,6 +133,8 @@ struct cam_cpas_feature_info {
  * @rpmh_info: RPMH BCM info
  * @num_feature_info: number of feature_info entries
  * @feature_info: Structure for storing feature information
+ * @num_caches: Number of last level caches
+ * @llcc_info:  Cache info
  */
 struct cam_cpas_private_soc {
 	const char *arch_compat;
@@ -132,6 +155,8 @@ struct cam_cpas_private_soc {
 	uint32_t rpmh_info[CAM_RPMH_BCM_INFO_MAX];
 	uint32_t num_feature_info;
 	struct cam_cpas_feature_info  feature_info[CAM_CPAS_MAX_FUSE_FEATURE];
+	uint32_t num_caches;
+	struct cam_sys_cache_info *llcc_info;
 };
 
 void cam_cpas_util_debug_parse_data(struct cam_cpas_private_soc *soc_private);

+ 47 - 1
drivers/cam_cpas/include/cam_cpas_api.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _CAM_CPAS_API_H_
@@ -210,6 +210,16 @@ enum cam_camnoc_irq_type {
 	CAM_CAMNOC_IRQ_AHB_TIMEOUT,
 };
 
+
+/**
+ * enum cam_sys_cache_config_types - Enum for camera llc's
+ */
+enum cam_sys_cache_config_types {
+	CAM_LLCC_SMALL_1 = 0,
+	CAM_LLCC_SMALL_2 = 1,
+	CAM_LLCC_MAX = 2,
+};
+
 /**
  * struct cam_camnoc_irq_slave_err_data : Data for Slave error.
  *
@@ -721,4 +731,40 @@ int cam_cpas_select_qos_settings(uint32_t selection_mask);
 int cam_cpas_notify_event(const char *identifier_string,
 	int32_t identifier_value);
 
+/**
+ * cam_cpas_get_scid()
+ *
+ * @brief: API to obtain slice id for the given type
+ *
+ * @type: Cache type
+ *
+ * @return slice id, -1 for invalid id.
+ *
+ */
+int cam_cpas_get_scid(enum cam_sys_cache_config_types  type);
+
+/**
+ * cam_cpas_activate_llcc()
+ *
+ * @brief: API to activate system cache
+ *
+ * @type: Cache type
+ *
+ * @return 0 for success.
+ *
+ */
+int cam_cpas_activate_llcc(enum cam_sys_cache_config_types type);
+
+/**
+ * cam_cpas_deactivate_llcc()
+ *
+ * @brief: API to de-activate system cache
+ *
+ * @type: Cache type
+ *
+ * @return 0 for success.
+ *
+ */
+int cam_cpas_deactivate_llcc(enum cam_sys_cache_config_types type);
+
 #endif /* _CAM_CPAS_API_H_ */

+ 286 - 5
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c

@@ -781,6 +781,12 @@ static void cam_ife_hw_mgr_deinit_hw(
 	for (i = 0; i < max_ife_out_res; i++)
 		cam_ife_hw_mgr_deinit_hw_res(&ctx->res_list_ife_out[i]);
 
+	/* Check if any cache needs to be de-activated */
+	for (i = CAM_LLCC_SMALL_1; i < CAM_LLCC_MAX; i++) {
+		if (ctx->flags.sys_cache_usage[i])
+			cam_cpas_deactivate_llcc(i);
+		ctx->flags.sys_cache_usage[i] = false;
+	}
 	ctx->flags.init_done = false;
 }
 
@@ -890,6 +896,18 @@ static int cam_ife_hw_mgr_init_hw(
 		}
 	}
 
+	/* Check if any cache needs to be activated */
+	for (i = CAM_LLCC_SMALL_1; i < CAM_LLCC_MAX; i++) {
+		if (ctx->flags.sys_cache_usage[i]) {
+			rc = cam_cpas_activate_llcc(i);
+			if (rc) {
+				CAM_ERR(CAM_ISP,
+				"Failed to activate cache: %d", i);
+				goto deinit;
+			}
+		}
+	}
+
 	return rc;
 deinit:
 	ctx->flags.init_done = true;
@@ -6219,8 +6237,9 @@ static int cam_ife_mgr_start_hw(void *hw_mgr_priv, void *start_hw_args)
 	for (i = 0; i < CAM_SFE_HW_NUM_MAX; i++) {
 		struct cam_sfe_debug_cfg_params debug_cfg;
 
-		debug_cfg.sfe_debug_cfg = g_ife_hw_mgr.debug_cfg.sfe_debug;
-		debug_cfg.sfe_sensor_sel = g_ife_hw_mgr.debug_cfg.sfe_sensor_diag_cfg;
+		debug_cfg.cache_config = false;
+		debug_cfg.u.dbg_cfg.sfe_debug_cfg = g_ife_hw_mgr.debug_cfg.sfe_debug;
+		debug_cfg.u.dbg_cfg.sfe_sensor_sel = g_ife_hw_mgr.debug_cfg.sfe_sensor_diag_cfg;
 		if (g_ife_hw_mgr.sfe_devices[i]) {
 			rc = g_ife_hw_mgr.sfe_devices[i]->hw_ops.process_cmd(
 				g_ife_hw_mgr.sfe_devices[i]->hw_priv,
@@ -6970,8 +6989,6 @@ end:
 }
 
 static int cam_isp_blob_sfe_scratch_buf_update(
-	uint32_t                                     blob_type,
-	struct cam_isp_generic_blob_info            *blob_info,
 	struct cam_isp_sfe_init_scratch_buf_config  *scratch_config,
 	struct cam_hw_prepare_update_args           *prepare)
 {
@@ -7056,6 +7073,148 @@ static int cam_isp_blob_sfe_scratch_buf_update(
 	return 0;
 }
 
+static inline int __cam_isp_sfe_send_cache_config(
+	int32_t                                   cmd_type,
+	struct cam_isp_sfe_bus_sys_cache_config  *wm_rm_cache_cfg)
+{
+	int rc = 0;
+	struct cam_isp_resource_node *hw_res = wm_rm_cache_cfg->res;
+
+	rc = hw_res->hw_intf->hw_ops.process_cmd(
+		hw_res->hw_intf->hw_priv,
+		cmd_type, wm_rm_cache_cfg,
+		sizeof(struct cam_isp_sfe_bus_sys_cache_config));
+	if (rc) {
+		CAM_ERR(CAM_ISP,
+			"Failed in sending cache config for:%d",
+			hw_res->res_id);
+	}
+
+	return rc;
+}
+
+static int cam_isp_blob_sfe_exp_order_update(
+	uint32_t                             base_idx,
+	struct cam_isp_sfe_exp_config       *exp_config,
+	struct cam_hw_prepare_update_args   *prepare)
+{
+	int rc = 0, i, j;
+	uint32_t exp_order_max = 0;
+	uint32_t res_id_out, res_id_in;
+	struct cam_ife_hw_mgr_ctx               *ctx;
+	struct cam_isp_hw_mgr_res               *hw_mgr_res;
+	struct cam_isp_hw_mgr_res               *tmp;
+	struct cam_isp_sfe_wm_exp_order_config  *order_cfg;
+	struct cam_ife_hw_mgr                   *hw_mgr;
+	struct cam_isp_sfe_bus_sys_cache_config  wm_rm_cache_cfg;
+
+	ctx = prepare->ctxt_to_hw_map;
+	hw_mgr = ctx->hw_mgr;
+	memset(ctx->flags.sys_cache_usage, false, sizeof(ctx->flags.sys_cache_usage));
+
+	if (!hw_mgr->num_caches_found) {
+		CAM_DBG(CAM_ISP, "No caches found during probe");
+		return 0;
+	}
+
+	/*
+	 *  The last resource in the array will be considered as
+	 *  last exposure
+	 */
+	exp_order_max = exp_config->num_ports - 1;
+	for (i = 0; i < exp_config->num_ports; i++) {
+		order_cfg = &exp_config->wm_config[i];
+
+		rc = cam_ife_hw_mgr_is_sfe_rdi_for_fetch(
+			order_cfg->res_type);
+		if (!rc) {
+			CAM_ERR(CAM_ISP,
+				"Not a SFE fetch RDI: 0x%x",
+				order_cfg->res_type);
+			return -EINVAL;
+		}
+
+		/* Add more params if needed */
+		wm_rm_cache_cfg.use_cache =
+			(exp_order_max == i) ? true : false;
+		wm_rm_cache_cfg.scid = 0;
+
+		/* Currently using cache for short only */
+		if (wm_rm_cache_cfg.use_cache) {
+			if (base_idx == CAM_SFE_CORE_0) {
+				wm_rm_cache_cfg.scid =
+					hw_mgr->sys_cache_info[CAM_LLCC_SMALL_1].scid;
+				if (wm_rm_cache_cfg.scid <= 0)
+					goto end;
+
+				ctx->flags.sys_cache_usage[CAM_LLCC_SMALL_1] = true;
+			} else if (base_idx == CAM_SFE_CORE_1) {
+				wm_rm_cache_cfg.scid =
+					hw_mgr->sys_cache_info[CAM_LLCC_SMALL_2].scid;
+				if (wm_rm_cache_cfg.scid <= 0)
+					goto end;
+
+				ctx->flags.sys_cache_usage[CAM_LLCC_SMALL_2] = true;
+			}
+		}
+
+		/* Configure cache config for WM */
+		res_id_out = order_cfg->res_type & 0xFF;
+		hw_mgr_res = &ctx->res_list_sfe_out[res_id_out];
+		for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
+			if (!hw_mgr_res->hw_res[j])
+				continue;
+
+			if (hw_mgr_res->hw_res[j]->hw_intf->hw_idx != base_idx)
+				continue;
+
+			wm_rm_cache_cfg.res = hw_mgr_res->hw_res[j];
+			rc = __cam_isp_sfe_send_cache_config(
+				CAM_ISP_HW_SFE_SYS_CACHE_WM_CONFIG,
+				&wm_rm_cache_cfg);
+			if (rc)
+				return rc;
+		}
+
+		/* RDI WMs have been validated find corresponding RM */
+		if (order_cfg->res_type == CAM_ISP_SFE_OUT_RES_RDI_0)
+			res_id_in = CAM_ISP_HW_SFE_IN_RD0;
+		else if (order_cfg->res_type == CAM_ISP_SFE_OUT_RES_RDI_1)
+			res_id_in = CAM_ISP_HW_SFE_IN_RD1;
+		else
+			res_id_in = CAM_ISP_HW_SFE_IN_RD2;
+
+		/* Configure cache config for RM */
+		list_for_each_entry_safe(hw_mgr_res, tmp, &ctx->res_list_ife_in_rd, list) {
+			for (j = 0; j < CAM_ISP_HW_SPLIT_MAX; j++) {
+				if (!hw_mgr_res->hw_res[j])
+					continue;
+
+				if (hw_mgr_res->hw_res[j]->res_id != res_id_in)
+					continue;
+
+				if (hw_mgr_res->hw_res[j]->hw_intf->hw_idx != base_idx)
+					continue;
+
+				wm_rm_cache_cfg.res = hw_mgr_res->hw_res[j];
+				rc = __cam_isp_sfe_send_cache_config(
+					CAM_ISP_HW_SFE_SYS_CACHE_RM_CONFIG,
+					&wm_rm_cache_cfg);
+				if (rc)
+					return rc;
+			}
+		}
+		CAM_DBG(CAM_ISP,
+			"cache config based on exp order: %u [max: %u] for out: 0x%x",
+			i, exp_order_max, order_cfg->res_type);
+	}
+
+	return rc;
+
+end:
+	return 0;
+}
+
 static int cam_isp_blob_hfr_update(
 	uint32_t                               blob_type,
 	struct cam_isp_generic_blob_info      *blob_info,
@@ -8288,6 +8447,7 @@ static int cam_isp_packet_generic_blob_handler(void *user_data,
 	case CAM_ISP_GENERIC_BLOB_TYPE_SFE_HFR_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_SFE_FE_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_SFE_SCRATCH_BUF_CFG:
+	case CAM_ISP_GENERIC_BLOB_TYPE_SFE_EXP_ORDER_CFG:
 		break;
 	case CAM_ISP_GENERIC_BLOB_TYPE_DYNAMIC_MODE_SWITCH: {
 		struct cam_isp_mode_switch_info    *mup_config;
@@ -8604,7 +8764,7 @@ static int cam_sfe_packet_generic_blob_handler(void *user_data,
 			return -EINVAL;
 		}
 
-		rc = cam_isp_blob_sfe_scratch_buf_update(blob_type, blob_info,
+		rc = cam_isp_blob_sfe_scratch_buf_update(
 			scratch_config, prepare);
 		if (rc)
 			CAM_ERR(CAM_ISP, "SFE scratch buffer update failed");
@@ -8642,6 +8802,69 @@ static int cam_sfe_packet_generic_blob_handler(void *user_data,
 			mup_config->num_expoures;
 	}
 		break;
+	case CAM_ISP_GENERIC_BLOB_TYPE_SFE_EXP_ORDER_CFG: {
+		struct cam_isp_sfe_exp_config *exp_config;
+
+		if (!ife_mgr_ctx->flags.is_sfe_shdr) {
+			CAM_ERR(CAM_ISP,
+				"Blob %u supported only for sHDR streams",
+				blob_type);
+			return -EINVAL;
+		}
+
+		if (blob_size <
+			sizeof(struct cam_isp_sfe_exp_config)) {
+			CAM_ERR(CAM_ISP, "Invalid blob size %u", blob_size);
+			return -EINVAL;
+		}
+
+		exp_config =
+			(struct cam_isp_sfe_exp_config *)blob_data;
+
+		if ((exp_config->num_ports > CAM_SFE_FE_RDI_NUM_MAX) ||
+			(exp_config->num_ports == 0)) {
+			CAM_ERR(CAM_ISP,
+				"Invalid num_ports %u in exp order config",
+				exp_config->num_ports);
+			return -EINVAL;
+		}
+
+		/* Check for integer overflow */
+		if (exp_config->num_ports != 1) {
+			if (sizeof(struct cam_isp_sfe_wm_exp_order_config) >
+				((UINT_MAX -
+				sizeof(
+				struct cam_isp_sfe_exp_config)) /
+				(exp_config->num_ports - 1))) {
+				CAM_ERR(CAM_ISP,
+					"Max size exceeded in exp order config num_ports: %u size per port: %lu",
+					exp_config->num_ports,
+					sizeof(
+					struct cam_isp_sfe_wm_exp_order_config));
+				return -EINVAL;
+			}
+		}
+
+		if (blob_size <
+			(sizeof(struct cam_isp_sfe_exp_config) +
+			(exp_config->num_ports - 1) *
+			sizeof(struct cam_isp_sfe_wm_exp_order_config))) {
+			CAM_ERR(CAM_ISP, "Invalid blob size: %u expected: %lu",
+				blob_size,
+				sizeof(
+				struct cam_isp_sfe_exp_config) +
+				(exp_config->num_ports - 1) *
+				sizeof(
+				struct cam_isp_sfe_wm_exp_order_config));
+			return -EINVAL;
+		}
+
+		rc = cam_isp_blob_sfe_exp_order_update(
+			blob_info->base_info->idx, exp_config, prepare);
+		if (rc)
+			CAM_ERR(CAM_ISP, "SFE exp order update failed");
+	}
+		break;
 	case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG:
 	case CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG:
@@ -11086,6 +11309,49 @@ static int cam_ife_hw_mgr_sort_dev_with_caps(
 	return 0;
 }
 
+static int cam_ife_set_sfe_cache_debug(void *data, u64 val)
+{
+	int i, rc = -EINVAL;
+	uint32_t hw_idx = 0;
+	struct cam_sfe_debug_cfg_params debug_cfg;
+	struct cam_hw_intf *hw_intf = NULL;
+
+	debug_cfg.cache_config = true;
+
+	/* BITS [0:3] is for hw_idx */
+	hw_idx = val & 0xF;
+	for (i = 0; i < CAM_SFE_HW_NUM_MAX; i++) {
+		if ((g_ife_hw_mgr.sfe_devices[i]) && (i == hw_idx)) {
+			hw_intf = g_ife_hw_mgr.sfe_devices[i];
+
+			debug_cfg.u.cache_cfg.sfe_cache_dbg = (val >> 4);
+			g_ife_hw_mgr.debug_cfg.sfe_cache_debug[i] =
+				debug_cfg.u.cache_cfg.sfe_cache_dbg;
+			rc = hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
+				CAM_ISP_HW_CMD_SET_SFE_DEBUG_CFG,
+				&debug_cfg,
+				sizeof(struct cam_sfe_debug_cfg_params));
+		}
+	}
+
+	CAM_DBG(CAM_ISP, "Set SFE cache debug value: 0x%llx", val);
+	return rc;
+}
+
+static int cam_ife_get_sfe_cache_debug(void *data, u64 *val)
+{
+	*val = g_ife_hw_mgr.debug_cfg.sfe_cache_debug[CAM_SFE_CORE_1];
+	*val = *val << 32;
+	*val |=  g_ife_hw_mgr.debug_cfg.sfe_cache_debug[CAM_SFE_CORE_0];
+	CAM_DBG(CAM_ISP, "Get SFE cace debug value: 0x%llx", *val);
+
+	return 0;
+}
+
+DEFINE_DEBUGFS_ATTRIBUTE(cam_ife_sfe_cache_debug,
+	cam_ife_get_sfe_cache_debug,
+	cam_ife_set_sfe_cache_debug, "%16llu");
+
 static int cam_ife_set_csid_debug(void *data, u64 val)
 {
 	g_ife_hw_mgr.debug_cfg.csid_debug = val;
@@ -11208,6 +11474,8 @@ static int cam_ife_hw_mgr_debug_register(void)
 	dbgfileptr = debugfs_create_bool("disable_ife_mmu_prefetch", 0644,
 		g_ife_hw_mgr.debug_cfg.dentry,
 		&g_ife_hw_mgr.debug_cfg.disable_ife_mmu_prefetch);
+	dbgfileptr = debugfs_create_file("sfe_cache_debug", 0644,
+		g_ife_hw_mgr.debug_cfg.dentry, NULL, &cam_ife_sfe_cache_debug);
 
 	if (IS_ERR(dbgfileptr)) {
 		if (PTR_ERR(dbgfileptr) == -ENODEV)
@@ -11464,6 +11732,18 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
 		goto end;
 	}
 
+	/* Populate sys cache info */
+	g_ife_hw_mgr.num_caches_found = 0;
+	for (i = CAM_LLCC_SMALL_1; i < CAM_LLCC_MAX; i++) {
+		g_ife_hw_mgr.sys_cache_info[i].scid =
+			cam_cpas_get_scid(i);
+		g_ife_hw_mgr.sys_cache_info[i].type = i;
+		CAM_DBG(CAM_ISP, "Cache_%d scid: %d",
+			i, g_ife_hw_mgr.sys_cache_info[i].scid);
+		if (g_ife_hw_mgr.sys_cache_info[i].scid > 0)
+			g_ife_hw_mgr.num_caches_found++;
+	}
+
 	/* fill return structure */
 	hw_mgr_intf->hw_mgr_priv = &g_ife_hw_mgr;
 	hw_mgr_intf->hw_get_caps = cam_ife_mgr_get_hw_caps;
@@ -11531,4 +11811,5 @@ void cam_ife_hw_mgr_deinit(void)
 
 	cam_smmu_destroy_handle(g_ife_hw_mgr.mgr_common.img_iommu_hdl);
 	g_ife_hw_mgr.mgr_common.img_iommu_hdl = -1;
+	g_ife_hw_mgr.num_caches_found = 0;
 }

+ 40 - 17
drivers/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h

@@ -44,9 +44,11 @@ enum cam_ife_ctx_master_type {
  * @dentry:                    Debugfs entry
  * @csid_debug:                csid debug information
  * @enable_recovery:           enable recovery
+ * @camif_debug:               camif debug info
  * @enable_csid_recovery:      enable csid recovery
  * @sfe_debug:                 sfe debug config
  * @sfe_sensor_diag_cfg:       sfe sensor diag config
+ * @sfe_cache_debug:           sfe cache debug info
  * @enable_req_dump:           Enable request dump on HW errors
  * @per_req_reg_dump:          Enable per request reg dump
  * @disable_ubwc_comp:         Disable UBWC compression
@@ -61,6 +63,7 @@ struct cam_ife_hw_mgr_debug {
 	uint32_t       enable_csid_recovery;
 	uint32_t       sfe_debug;
 	uint32_t       sfe_sensor_diag_cfg;
+	uint32_t       sfe_cache_debug[CAM_SFE_HW_NUM_MAX];
 	bool           enable_req_dump;
 	bool           per_req_reg_dump;
 	bool           disable_ubwc_comp;
@@ -123,8 +126,11 @@ struct cam_sfe_scratch_buf_cfg {
  *                       resources
  * @is_sfe_shdr:         indicate if stream is for SFE sHDR
  * @is_sfe_fs:           indicate if stream is for inline SFE FS
- * @dump_on_flush        Set if reg dump triggered on flush
- * @dump_on_error        Set if reg dump triggered on error
+ * @dump_on_flush:       Set if reg dump triggered on flush
+ * @dump_on_error:       Set if reg dump triggered on error
+ * @sys_cache_usage:     Per context sys cache usage
+ *                       The corresponding index will be set
+ *                       for the cache type
  *
  */
 struct cam_ife_hw_mgr_ctx_flags {
@@ -144,6 +150,7 @@ struct cam_ife_hw_mgr_ctx_flags {
 	bool   is_sfe_fs;
 	bool   dump_on_flush;
 	bool   dump_on_error;
+	bool   sys_cache_usage[CAM_LLCC_MAX];
 };
 
 /**
@@ -260,6 +267,19 @@ struct cam_isp_bus_hw_caps {
 	bool         support_consumed_addr;
 };
 
+/*
+ * struct cam_isp_sys_cache_info:
+ *
+ * @Brief:                   ISP Bus sys cache info
+ *
+ * @type:                    Cache type
+ * @scid:                    Cache slice ID
+ */
+struct cam_isp_sys_cache_info {
+	enum cam_sys_cache_config_types type;
+	int32_t                         scid;
+};
+
 /**
  * struct cam_ife_hw_mgr - IFE HW Manager
  *
@@ -292,23 +312,26 @@ struct cam_ife_hw_mgr {
 	struct cam_hw_intf            *sfe_devices[CAM_SFE_HW_NUM_MAX];
 	struct cam_soc_reg_map        *cdm_reg_map[CAM_IFE_HW_NUM_MAX];
 
-	struct mutex                   ctx_mutex;
-	atomic_t                       active_ctx_cnt;
-	struct list_head               free_ctx_list;
-	struct list_head               used_ctx_list;
-	struct cam_ife_hw_mgr_ctx      ctx_pool[CAM_IFE_CTX_MAX];
+	struct mutex                     ctx_mutex;
+	atomic_t                         active_ctx_cnt;
+	struct list_head                 free_ctx_list;
+	struct list_head                 used_ctx_list;
+	struct cam_ife_hw_mgr_ctx        ctx_pool[CAM_IFE_CTX_MAX];
 
-	struct cam_ife_csid_hw_caps    csid_hw_caps[
+	struct cam_ife_csid_hw_caps      csid_hw_caps[
 						CAM_IFE_CSID_HW_NUM_MAX];
-	struct cam_vfe_hw_get_hw_cap   ife_dev_caps[CAM_IFE_HW_NUM_MAX];
-	struct cam_req_mgr_core_workq *workq;
-	struct cam_ife_hw_mgr_debug    debug_cfg;
-	spinlock_t                     ctx_lock;
-	bool                           hw_pid_support;
-	bool                           csid_rup_en;
-	bool                           csid_global_reset_en;
-	struct cam_isp_bus_hw_caps     isp_bus_caps;
-	struct cam_isp_hw_path_port_map   path_port_map;
+	struct cam_vfe_hw_get_hw_cap     ife_dev_caps[CAM_IFE_HW_NUM_MAX];
+	struct cam_req_mgr_core_workq   *workq;
+	struct cam_ife_hw_mgr_debug      debug_cfg;
+	spinlock_t                       ctx_lock;
+	bool                             hw_pid_support;
+	bool                             csid_rup_en;
+	bool                             csid_global_reset_en;
+	struct cam_isp_bus_hw_caps       isp_bus_caps;
+	struct cam_isp_hw_path_port_map  path_port_map;
+
+	uint32_t                         num_caches_found;
+	struct cam_isp_sys_cache_info    sys_cache_info[CAM_LLCC_MAX];
 };
 
 /**

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h

@@ -157,6 +157,8 @@ enum cam_isp_hw_cmd_type {
 	CAM_ISP_HW_CMD_IS_PDAF_RDI2_MUX_EN,
 	CAM_ISP_HW_CMD_GET_PATH_PORT_MAP,
 	CAM_ISP_HW_CMD_IFE_BUS_DEBUG_CFG,
+	CAM_ISP_HW_SFE_SYS_CACHE_WM_CONFIG,
+	CAM_ISP_HW_SFE_SYS_CACHE_RM_CONFIG,
 	CAM_ISP_HW_CMD_MAX,
 };
 

+ 50 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/include/cam_sfe_hw_intf.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _CAM_SFE_HW_INTF_H_
@@ -14,6 +14,12 @@
 #define SFE_RT_CDM_BASE_IDX         1
 #define CAM_SFE_HW_NUM_MAX          2
 
+enum cam_sfe_core_id {
+	CAM_SFE_CORE_0,
+	CAM_SFE_CORE_1,
+	CAM_SFE_CORE_MAX,
+};
+
 enum cam_isp_hw_sfe_in {
 	CAM_ISP_HW_SFE_IN_PIX,
 	CAM_ISP_HW_SFE_IN_RD0,
@@ -56,16 +62,40 @@ enum cam_sfe_bus_rd_irq_regs {
 };
 
 /*
- * struct cam_sfe_debug_cfg_params:
+ * struct cam_sfe_generic_debug_config:
  *
  * @sfe_debug_cfg : SFE debug cfg value
  * @sfe_sensor_sel: SFE sensor sel for diag data
  */
-struct cam_sfe_debug_cfg_params {
+struct cam_sfe_generic_debug_config {
 	uint32_t sfe_debug_cfg;
 	uint32_t sfe_sensor_sel;
 };
 
+/*
+ * struct cam_sfe_sys_cache_debug_config:
+ *
+ * @sfe_cache_dbg:  SFE cache debug cfg
+ */
+
+struct cam_sfe_sys_cache_debug_config {
+	uint32_t sfe_cache_dbg;
+};
+
+
+/*
+ * struct cam_sfe_debug_cfg_params:
+ *
+ * @cache_config: If the config is for cache
+ */
+struct cam_sfe_debug_cfg_params {
+	bool cache_config;
+	union {
+		struct cam_sfe_generic_debug_config   dbg_cfg;
+		struct cam_sfe_sys_cache_debug_config cache_cfg;
+	} u;
+};
+
 /*
  * struct cam_sfe_bw_control_args:
  *
@@ -122,6 +152,23 @@ struct cam_sfe_core_config_args {
 	struct cam_isp_sfe_core_config     core_config;
 };
 
+/**
+ * struct cam_isp_sfe_bus_sys_cache_config:
+ *
+ * @Brief:         Based on exp order rxved from userland
+ *                 configure sys cache for SFE WMs & RMs
+ *
+ * @res:           SFE WM/RM Resource node
+ * @use_cache:     If set cache configured
+ * @type:          Dictates which slice ID to be used
+ *
+ */
+struct cam_isp_sfe_bus_sys_cache_config {
+	struct cam_isp_resource_node        *res;
+	bool                                 use_cache;
+	int                                  scid;
+};
+
 /*
  * struct cam_sfe_top_irq_evt_payload:
  *

+ 3 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe680.h

@@ -311,6 +311,7 @@ static struct cam_sfe_bus_rd_hw_info sfe680_bus_rd_hw_info = {
 			.stride                   = 0x00000464,
 			.unpacker_cfg             = 0x00000468,
 			.latency_buf_allocation   = 0x0000047C,
+			.system_cache_cfg         = 0x0000049C,
 		},
 		/* BUS Client 1 */
 		{
@@ -321,6 +322,7 @@ static struct cam_sfe_bus_rd_hw_info sfe680_bus_rd_hw_info = {
 			.stride                   = 0x00000504,
 			.unpacker_cfg             = 0x00000508,
 			.latency_buf_allocation   = 0x0000051C,
+			.system_cache_cfg         = 0x0000053C,
 		},
 		/* BUS Client 2 */
 		{
@@ -331,6 +333,7 @@ static struct cam_sfe_bus_rd_hw_info sfe680_bus_rd_hw_info = {
 			.stride                   = 0x000005A4,
 			.unpacker_cfg             = 0x000005A8,
 			.latency_buf_allocation   = 0x000005BC,
+			.system_cache_cfg         = 0x000005DC,
 		},
 	},
 	.num_bus_rd_resc = 3,

+ 2 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/cam_sfe_core.c

@@ -334,6 +334,7 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type,
 	case CAM_ISP_HW_CMD_WM_CONFIG_UPDATE:
 	case CAM_ISP_HW_CMD_GET_SECURE_MODE:
 	case CAM_ISP_HW_CMD_QUERY_BUS_CAP:
+	case CAM_ISP_HW_SFE_SYS_CACHE_WM_CONFIG:
 		rc = core_info->sfe_bus_wr->hw_ops.process_cmd(
 			core_info->sfe_bus_wr->bus_priv, cmd_type,
 			cmd_args, arg_size);
@@ -342,6 +343,7 @@ int cam_sfe_process_cmd(void *hw_priv, uint32_t cmd_type,
 	case CAM_ISP_HW_CMD_GET_BUF_UPDATE_RM:
 	case CAM_ISP_HW_CMD_BUF_UPDATE_RM:
 	case CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD:
+	case CAM_ISP_HW_SFE_SYS_CACHE_RM_CONFIG:
 		rc = core_info->sfe_bus_rd->hw_ops.process_cmd(
 			core_info->sfe_bus_rd->bus_priv, cmd_type,
 			cmd_args, arg_size);

+ 75 - 1
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus.c

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  */
 
 #include "cam_sfe_bus.h"
@@ -90,3 +90,77 @@ int cam_sfe_bus_deinit(
 	return rc;
 }
 
+static inline int __cam_sfe_bus_validate_alloc_type(
+	uint32_t alloc_type) {
+
+	if ((alloc_type >= CACHE_ALLOC_NONE) &&
+		(alloc_type <= CACHE_ALLOC_TBH_ALLOC))
+		return 1;
+	else
+		return 0;
+}
+
+void cam_sfe_bus_parse_cache_cfg(
+	bool is_read,
+	uint32_t debug_val,
+	struct cam_sfe_bus_cache_dbg_cfg *dbg_cfg)
+{
+	uint32_t scratch_alloc_shift = 0, buf_alloc_shift = 0;
+	uint32_t scratch_cfg, buf_cfg, alloc_type;
+
+	if (debug_val >= DISABLE_CACHING_FOR_ALL) {
+		dbg_cfg->disable_all = true;
+		goto end;
+	}
+
+	if (is_read) {
+		scratch_alloc_shift = CACHE_SCRATCH_RD_ALLOC_SHIFT;
+		buf_alloc_shift = CACHE_BUF_RD_ALLOC_SHIFT;
+	} else {
+		scratch_alloc_shift = CACHE_SCRATCH_WR_ALLOC_SHIFT;
+		buf_alloc_shift = CACHE_BUF_WR_ALLOC_SHIFT;
+	}
+
+	scratch_cfg = (debug_val >> CACHE_SCRATCH_DEBUG_SHIFT) & 0xF;
+	buf_cfg = (debug_val >> CACHE_BUF_DEBUG_SHIFT) & 0xF;
+
+	/* Check for scratch cfg */
+	if (scratch_cfg == 0xF) {
+		dbg_cfg->disable_for_scratch = true;
+	} else if (scratch_cfg == 1) {
+		alloc_type =
+			(debug_val >> scratch_alloc_shift) & 0xF;
+		if (__cam_sfe_bus_validate_alloc_type(alloc_type)) {
+			dbg_cfg->scratch_alloc = alloc_type;
+			dbg_cfg->scratch_dbg_cfg = true;
+		}
+		dbg_cfg->disable_for_scratch = false;
+	} else {
+		/* Reset to default */
+		dbg_cfg->disable_for_scratch = false;
+		dbg_cfg->scratch_dbg_cfg = false;
+	}
+
+	/* Check for buf cfg */
+	if (buf_cfg == 0xF) {
+		dbg_cfg->disable_for_buf = true;
+	} else if (buf_cfg == 1) {
+		alloc_type =
+			(debug_val >> buf_alloc_shift) & 0xF;
+		if (__cam_sfe_bus_validate_alloc_type(alloc_type)) {
+			dbg_cfg->buf_alloc = alloc_type;
+			dbg_cfg->buf_dbg_cfg = true;
+		}
+		dbg_cfg->disable_for_buf = false;
+	} else {
+		/* Reset to default */
+		dbg_cfg->disable_for_buf = false;
+		dbg_cfg->buf_dbg_cfg = false;
+	}
+
+	/* Reset to default */
+	dbg_cfg->disable_all = false;
+
+end:
+	return;
+}

+ 123 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.c

@@ -74,6 +74,8 @@ struct cam_sfe_bus_rd_common_data {
 	cam_hw_mgr_event_cb_func                    event_cb;
 	bool                                        err_irq_subscribe;
 	uint32_t                                    sfe_debug_cfg;
+
+	struct cam_sfe_bus_cache_dbg_cfg            cache_dbg_cfg;
 };
 
 struct cam_sfe_bus_rd_rm_resource_data {
@@ -94,6 +96,9 @@ struct cam_sfe_bus_rd_rm_resource_data {
 	uint32_t             en_cfg;
 	uint32_t             img_addr;
 	uint32_t             input_if_cmd;
+	bool                 enable_caching;
+	uint32_t             cache_cfg;
+	uint32_t             current_scid;
 };
 
 struct cam_sfe_bus_rd_data {
@@ -398,6 +403,9 @@ static int cam_sfe_bus_acquire_rm(
 		cam_sfe_bus_get_unpacker_fmt(unpacker_fmt);
 	rsrc_data->latency_buf_allocation =
 		BUS_RD_DEFAULT_LATENCY_BUF_ALLOC;
+	rsrc_data->enable_caching =  false;
+	/* Default register value */
+	rsrc_data->cache_cfg = 0x20;
 
 	*rm_res = rm_res_local;
 
@@ -472,6 +480,7 @@ static int cam_sfe_bus_stop_rm(struct cam_isp_resource_node *rm_res)
 	cam_io_w_mb(0x0, common_data->mem_base + rsrc_data->hw_regs->cfg);
 
 	rm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
+	rsrc_data->enable_caching =  false;
 
 	CAM_DBG(CAM_SFE, "SFE:%d RM:%d stopped",
 		rsrc_data->common_data->core_index, rsrc_data->index);
@@ -1133,11 +1142,13 @@ static int cam_sfe_bus_rd_config_rm(void *priv, void *cmd_args,
 	struct cam_isp_hw_get_cmd_update       *update_buf;
 	struct cam_sfe_bus_rd_data             *sfe_bus_rd_data = NULL;
 	struct cam_sfe_bus_rd_rm_resource_data *rm_data = NULL;
+	struct cam_sfe_bus_cache_dbg_cfg       *cache_dbg_cfg = NULL;
 	uint32_t width = 0, height = 0, stride = 0;
 	uint32_t  i;
 
 	bus_priv = (struct cam_sfe_bus_rd_priv  *) priv;
 	update_buf =  (struct cam_isp_hw_get_cmd_update *) cmd_args;
+	cache_dbg_cfg = &bus_priv->common_data.cache_dbg_cfg;
 
 	sfe_bus_rd_data = (struct cam_sfe_bus_rd_data *)
 		update_buf->res->res_priv;
@@ -1170,6 +1181,25 @@ static int cam_sfe_bus_rd_config_rm(void *priv, void *cmd_args,
 			rm_data->unpacker_cfg, &rm_data->width);
 		rm_data->height = height;
 
+		rm_data->cache_cfg = 0x20;
+		if ((!cache_dbg_cfg->disable_for_scratch) &&
+			(rm_data->enable_caching)) {
+			rm_data->cache_cfg =
+				rm_data->current_scid << 8;
+			rm_data->cache_cfg |= (3 << 4);
+			if (cache_dbg_cfg->scratch_dbg_cfg)
+				rm_data->cache_cfg |= cache_dbg_cfg->scratch_alloc;
+			else
+				rm_data->cache_cfg |= CACHE_ALLOC_FORGET;
+		}
+
+		cam_io_w_mb(rm_data->cache_cfg,
+			rm_data->common_data->mem_base +
+			rm_data->hw_regs->system_cache_cfg);
+		CAM_DBG(CAM_SFE, "SFE:%d RM:%d cache_cfg:0x%x",
+			rm_data->common_data->core_index,
+			rm_data->index, rm_data->cache_cfg);
+
 		cam_io_w_mb(rm_data->width,
 			rm_data->common_data->mem_base +
 			rm_data->hw_regs->buf_width);
@@ -1213,6 +1243,7 @@ static int cam_sfe_bus_rd_update_rm(void *priv, void *cmd_args,
 	struct cam_sfe_bus_rd_data             *sfe_bus_rd_data = NULL;
 	struct cam_sfe_bus_rd_rm_resource_data *rm_data = NULL;
 	struct cam_cdm_utils_ops               *cdm_util_ops;
+	struct cam_sfe_bus_cache_dbg_cfg       *cache_dbg_cfg = NULL;
 	uint32_t *reg_val_pair;
 	uint32_t num_regval_pairs = 0;
 	uint32_t width = 0, height = 0, stride = 0;
@@ -1220,6 +1251,7 @@ static int cam_sfe_bus_rd_update_rm(void *priv, void *cmd_args,
 
 	bus_priv = (struct cam_sfe_bus_rd_priv  *) priv;
 	update_buf =  (struct cam_isp_hw_get_cmd_update *) cmd_args;
+	cache_dbg_cfg = &bus_priv->common_data.cache_dbg_cfg;
 
 	sfe_bus_rd_data = (struct cam_sfe_bus_rd_data *)
 		update_buf->res->res_priv;
@@ -1270,6 +1302,42 @@ static int cam_sfe_bus_rd_update_rm(void *priv, void *cmd_args,
 			rm_data->unpacker_cfg, &rm_data->width);
 		rm_data->height = height;
 
+		rm_data->cache_cfg = 0x20;
+		if (rm_data->enable_caching) {
+			if ((cache_dbg_cfg->disable_for_scratch) &&
+				(update_buf->use_scratch_cfg))
+				goto skip_cache_cfg;
+
+			if ((cache_dbg_cfg->disable_for_buf) &&
+				(!update_buf->use_scratch_cfg))
+				goto skip_cache_cfg;
+
+			rm_data->cache_cfg =
+				rm_data->current_scid << 8;
+			rm_data->cache_cfg |= (3 << 4);
+			if ((update_buf->use_scratch_cfg) &&
+				(cache_dbg_cfg->scratch_dbg_cfg)) {
+				rm_data->cache_cfg |= cache_dbg_cfg->scratch_alloc;
+			} else if ((!update_buf->use_scratch_cfg) &&
+				(cache_dbg_cfg->buf_dbg_cfg)) {
+				rm_data->cache_cfg |= cache_dbg_cfg->buf_alloc;
+			} else {
+				if (update_buf->use_scratch_cfg)
+					rm_data->cache_cfg |= CACHE_ALLOC_FORGET;
+				else
+					rm_data->cache_cfg |= CACHE_ALLOC_DEALLOC;
+			}
+		}
+
+skip_cache_cfg:
+
+		CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+			rm_data->hw_regs->system_cache_cfg,
+			rm_data->cache_cfg);
+		CAM_DBG(CAM_SFE, "SFE:%d RM:%d cache_cfg:0x%x",
+			rm_data->common_data->core_index,
+			rm_data->index, reg_val_pair[j-1]);
+
 		CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
 			rm_data->hw_regs->buf_width, rm_data->width);
 		CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
@@ -1336,6 +1404,45 @@ static int cam_sfe_bus_deinit_hw(void *hw_priv,
 	return 0;
 }
 
+static int cam_sfe_bus_rd_cache_config(void *priv, void *cmd_args,
+	uint32_t arg_size)
+{
+	int i;
+	struct cam_sfe_bus_rd_priv              *bus_priv;
+	struct cam_isp_sfe_bus_sys_cache_config *cache_cfg;
+	struct cam_sfe_bus_rd_data              *sfe_bus_rd_data = NULL;
+	struct cam_sfe_bus_rd_rm_resource_data  *rm_data = NULL;
+
+	bus_priv = (struct cam_sfe_bus_rd_priv  *)priv;
+	cache_cfg =  (struct cam_isp_sfe_bus_sys_cache_config *)cmd_args;
+
+	sfe_bus_rd_data = (struct cam_sfe_bus_rd_data *)
+		cache_cfg->res->res_priv;
+
+	if (!sfe_bus_rd_data) {
+		CAM_ERR(CAM_SFE, "Invalid data");
+		return -EINVAL;
+	}
+
+	if (bus_priv->common_data.cache_dbg_cfg.disable_all)
+		return 0;
+
+	for (i = 0; i < sfe_bus_rd_data->num_rm; i++) {
+		rm_data = (struct cam_sfe_bus_rd_rm_resource_data *)
+			sfe_bus_rd_data->rm_res[i]->res_priv;
+		rm_data->enable_caching = cache_cfg->use_cache;
+		rm_data->current_scid = cache_cfg->scid;
+
+		CAM_DBG(CAM_SFE, "SFE:%d RM:%d cache_enable:%s scid:%u",
+			rm_data->common_data->core_index,
+			rm_data->index,
+			(rm_data->enable_caching ? "true" : "false"),
+			rm_data->current_scid);
+	}
+
+	return 0;
+}
+
 static int cam_sfe_bus_rd_set_debug_cfg(
 	void *priv, void *cmd_args)
 {
@@ -1345,11 +1452,17 @@ static int cam_sfe_bus_rd_set_debug_cfg(
 
 	debug_cfg = (struct cam_sfe_debug_cfg_params *)cmd_args;
 
-	bus_priv->common_data.sfe_debug_cfg = debug_cfg->sfe_debug_cfg;
+	if (debug_cfg->cache_config)
+		cam_sfe_bus_parse_cache_cfg(true,
+			debug_cfg->u.cache_cfg.sfe_cache_dbg,
+			&bus_priv->common_data.cache_dbg_cfg);
+	else
+		bus_priv->common_data.sfe_debug_cfg =
+			debug_cfg->u.dbg_cfg.sfe_debug_cfg;
+
 	return 0;
 }
 
-
 static int cam_sfe_bus_rd_process_cmd(
 	void *priv, uint32_t cmd_type,
 	void *cmd_args, uint32_t arg_size)
@@ -1379,6 +1492,9 @@ static int cam_sfe_bus_rd_process_cmd(
 	case CAM_ISP_HW_CMD_SET_SFE_DEBUG_CFG:
 		rc = cam_sfe_bus_rd_set_debug_cfg(priv, cmd_args);
 		break;
+	case CAM_ISP_HW_SFE_SYS_CACHE_RM_CONFIG:
+		rc = cam_sfe_bus_rd_cache_config(priv, cmd_args, arg_size);
+		break;
 	default:
 		CAM_ERR_RATE_LIMIT(CAM_SFE,
 			"Invalid SFE BUS RD command type: %d",
@@ -1397,6 +1513,7 @@ int cam_sfe_bus_rd_init(
 	struct cam_sfe_bus                  **sfe_bus)
 {
 	int i, rc = 0;
+	struct cam_sfe_soc_private    *soc_private;
 	struct cam_sfe_bus_rd_priv    *bus_priv = NULL;
 	struct cam_sfe_bus            *sfe_bus_local;
 	struct cam_sfe_bus_rd_hw_info *bus_rd_hw_info = bus_hw_info;
@@ -1409,6 +1526,7 @@ int cam_sfe_bus_rd_init(
 		goto end;
 	}
 
+	soc_private = soc_info->soc_private;
 	sfe_bus_local = kzalloc(sizeof(struct cam_sfe_bus), GFP_KERNEL);
 	if (!sfe_bus_local) {
 		CAM_DBG(CAM_SFE, "Failed to alloc for sfe_bus");
@@ -1484,6 +1602,9 @@ int cam_sfe_bus_rd_init(
 	*sfe_bus = sfe_bus_local;
 	bus_priv->common_data.sfe_debug_cfg = 0;
 
+	/* Remove after sys cache verification */
+	bus_priv->common_data.cache_dbg_cfg.disable_all = true;
+
 	return rc;
 
 deinit_sfe_bus_rd:

+ 1 - 0
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_rd.h

@@ -46,6 +46,7 @@ struct cam_sfe_bus_rd_reg_offset_bus_client {
 	uint32_t stride;
 	uint32_t unpacker_cfg;
 	uint32_t latency_buf_allocation;
+	uint32_t system_cache_cfg;
 };
 
 /*

+ 120 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/cam_sfe_bus_wr.c

@@ -93,6 +93,7 @@ struct cam_sfe_bus_wr_common_data {
 	cam_hw_mgr_event_cb_func                    event_cb;
 
 	uint32_t                                    sfe_debug_cfg;
+	struct cam_sfe_bus_cache_dbg_cfg            cache_dbg_cfg;
 };
 
 struct cam_sfe_wr_scratch_buf_info {
@@ -132,6 +133,10 @@ struct cam_sfe_bus_wr_wm_resource_data {
 
 	uint32_t             acquired_width;
 	uint32_t             acquired_height;
+
+	bool                 enable_caching;
+	uint32_t             cache_cfg;
+	int32_t              current_scid;
 };
 
 struct cam_sfe_bus_wr_comp_grp_data {
@@ -591,6 +596,7 @@ static int cam_sfe_bus_acquire_wm(
 	rsrc_data->acquired_width = out_port_info->width;
 	rsrc_data->acquired_height = out_port_info->height;
 	rsrc_data->is_dual = is_dual;
+	rsrc_data->enable_caching =  false;
 
 	/* RDI0-2 line based mode by default */
 	if (sfe_out_res_id == CAM_SFE_BUS_SFE_OUT_RDI0 ||
@@ -783,6 +789,7 @@ static int cam_sfe_bus_stop_wm(struct cam_isp_resource_node *wm_res)
 	wm_res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED;
 	rsrc_data->init_cfg_done = false;
 	rsrc_data->hfr_cfg_done = false;
+	rsrc_data->enable_caching =  false;
 
 	return 0;
 }
@@ -1007,7 +1014,7 @@ static int cam_sfe_bus_release_comp_grp(
 	if (in_rsrc_data->acquire_dev_cnt == 0) {
 		list_del(&comp_grp->list);
 
-		in_rsrc_data->dual_slave_core = CAM_SFE_BUS_SFE_CORE_MAX;
+		in_rsrc_data->dual_slave_core = CAM_SFE_CORE_MAX;
 		in_rsrc_data->addr_sync_mode = 0;
 		in_rsrc_data->composite_mask = 0;
 
@@ -1083,7 +1090,7 @@ static int cam_sfe_bus_wr_init_comp_grp(uint32_t index,
 
 	rsrc_data->comp_grp_type   = index;
 	rsrc_data->common_data     = &bus_priv->common_data;
-	rsrc_data->dual_slave_core = CAM_SFE_BUS_SFE_CORE_MAX;
+	rsrc_data->dual_slave_core = CAM_SFE_CORE_MAX;
 
 	list_add_tail(&comp_grp->list, &bus_priv->free_comp_grp);
 
@@ -2072,6 +2079,7 @@ static int cam_sfe_bus_wr_update_wm(void *priv, void *cmd_args,
 	struct cam_sfe_bus_wr_out_data         *sfe_out_data = NULL;
 	struct cam_cdm_utils_ops               *cdm_util_ops;
 	struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL;
+	struct cam_sfe_bus_cache_dbg_cfg       *cache_dbg_cfg = NULL;
 	uint32_t *reg_val_pair;
 	uint32_t num_regval_pairs = 0;
 	uint32_t  i, j, k, size = 0;
@@ -2080,6 +2088,7 @@ static int cam_sfe_bus_wr_update_wm(void *priv, void *cmd_args,
 
 	bus_priv = (struct cam_sfe_bus_wr_priv  *) priv;
 	update_buf =  (struct cam_isp_hw_get_cmd_update *) cmd_args;
+	cache_dbg_cfg = &bus_priv->common_data.cache_dbg_cfg;
 
 	sfe_out_data = (struct cam_sfe_bus_wr_out_data *)
 		update_buf->res->res_priv;
@@ -2121,6 +2130,37 @@ static int cam_sfe_bus_wr_update_wm(void *priv, void *cmd_args,
 			wm_data->index, sfe_out_data->wm_res[i].res_name,
 			reg_val_pair[j-1]);
 
+		wm_data->cache_cfg = 0;
+		if (wm_data->enable_caching) {
+			if ((cache_dbg_cfg->disable_for_scratch) &&
+				(update_buf->use_scratch_cfg))
+				goto skip_cache_cfg;
+
+			if ((cache_dbg_cfg->disable_for_buf) &&
+				(!update_buf->use_scratch_cfg))
+				goto skip_cache_cfg;
+
+			wm_data->cache_cfg =
+				wm_data->current_scid << 8;
+			wm_data->cache_cfg |= 3 << 4;
+			if ((update_buf->use_scratch_cfg) &&
+				(cache_dbg_cfg->scratch_dbg_cfg))
+				wm_data->cache_cfg |= cache_dbg_cfg->scratch_alloc;
+			else if ((!update_buf->use_scratch_cfg) &&
+				(cache_dbg_cfg->buf_dbg_cfg))
+				wm_data->cache_cfg |= cache_dbg_cfg->buf_alloc;
+			else
+				wm_data->cache_cfg |= CACHE_ALLOC_ALLOC;
+		}
+
+skip_cache_cfg:
+
+		CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
+			wm_data->hw_regs->system_cache_cfg,
+			wm_data->cache_cfg);
+		CAM_DBG(CAM_SFE, "WM:%d cache_cfg:0x%x",
+			wm_data->index, reg_val_pair[j-1]);
+
 		val = (wm_data->height << 16) | wm_data->width;
 		CAM_SFE_ADD_REG_VAL_PAIR(reg_val_pair, j,
 			wm_data->hw_regs->image_cfg_0, val);
@@ -2239,12 +2279,14 @@ static int cam_sfe_bus_wr_config_wm(void *priv, void *cmd_args,
 	struct cam_isp_hw_get_cmd_update       *update_buf;
 	struct cam_sfe_bus_wr_out_data         *sfe_out_data = NULL;
 	struct cam_sfe_bus_wr_wm_resource_data *wm_data = NULL;
+	struct cam_sfe_bus_cache_dbg_cfg       *cache_dbg_cfg = NULL;
 	uint32_t  i, k;
 	uint32_t  frame_inc = 0, val;
 	uint32_t loop_size = 0, stride = 0, slice_h = 0;
 
 	bus_priv = (struct cam_sfe_bus_wr_priv  *) priv;
 	update_buf =  (struct cam_isp_hw_get_cmd_update *) cmd_args;
+	cache_dbg_cfg = &bus_priv->common_data.cache_dbg_cfg;
 
 	sfe_out_data = (struct cam_sfe_bus_wr_out_data *)
 		update_buf->res->res_priv;
@@ -2328,6 +2370,24 @@ static int cam_sfe_bus_wr_config_wm(void *priv, void *cmd_args,
 		CAM_DBG(CAM_SFE, "WM:%d frame_inc %d",
 			wm_data->index, frame_inc);
 
+		wm_data->cache_cfg = 0;
+		if ((!cache_dbg_cfg->disable_for_scratch) &&
+			(wm_data->enable_caching)) {
+			wm_data->cache_cfg =
+				wm_data->current_scid << 8;
+			wm_data->cache_cfg |= 3 << 4;
+			if (cache_dbg_cfg->scratch_dbg_cfg)
+				wm_data->cache_cfg |= cache_dbg_cfg->scratch_alloc;
+			else
+				wm_data->cache_cfg |= CACHE_ALLOC_ALLOC;
+		}
+
+		cam_io_w_mb(wm_data->cache_cfg,
+			wm_data->common_data->mem_base +
+			wm_data->hw_regs->system_cache_cfg);
+		CAM_DBG(CAM_SFE, "WM:%d cache_cfg:0x%x",
+			wm_data->index, wm_data->cache_cfg);
+
 		/* enable the WM */
 		cam_io_w_mb(wm_data->en_cfg,
 			wm_data->common_data->mem_base +
@@ -2596,6 +2656,47 @@ static int __cam_sfe_bus_wr_process_cmd(
 		cmd_args, arg_size);
 }
 
+static int cam_sfe_bus_wr_cache_config(
+	void *priv, void *cmd_args,
+	uint32_t arg_size)
+{
+	int i;
+	struct cam_sfe_bus_wr_priv              *bus_priv;
+	struct cam_isp_sfe_bus_sys_cache_config *cache_cfg;
+	struct cam_sfe_bus_wr_out_data          *sfe_out_data = NULL;
+	struct cam_sfe_bus_wr_wm_resource_data  *wm_data = NULL;
+
+
+	bus_priv = (struct cam_sfe_bus_wr_priv  *)priv;
+	cache_cfg = (struct cam_isp_sfe_bus_sys_cache_config *)cmd_args;
+
+	sfe_out_data = (struct cam_sfe_bus_wr_out_data *)
+		cache_cfg->res->res_priv;
+
+	if (!sfe_out_data) {
+		CAM_ERR(CAM_SFE, "Invalid data");
+		return -EINVAL;
+	}
+
+	if (bus_priv->common_data.cache_dbg_cfg.disable_all)
+		return 0;
+
+	for (i = 0; i < sfe_out_data->num_wm; i++) {
+		wm_data = (struct cam_sfe_bus_wr_wm_resource_data *)
+			sfe_out_data->wm_res[i].res_priv;
+		wm_data->enable_caching = cache_cfg->use_cache;
+		wm_data->current_scid = cache_cfg->scid;
+
+		CAM_DBG(CAM_SFE, "SFE:%d WM:%d cache_enable:%s scid:%u",
+			wm_data->common_data->core_index,
+			wm_data->index,
+			(wm_data->enable_caching ? "true" : "false"),
+			wm_data->current_scid);
+	}
+
+	return 0;
+}
+
 static int cam_sfe_bus_wr_set_debug_cfg(
 	void *priv, void *cmd_args)
 {
@@ -2605,7 +2706,14 @@ static int cam_sfe_bus_wr_set_debug_cfg(
 
 	debug_cfg = (struct cam_sfe_debug_cfg_params *)cmd_args;
 
-	bus_priv->common_data.sfe_debug_cfg = debug_cfg->sfe_debug_cfg;
+	if (debug_cfg->cache_config)
+		cam_sfe_bus_parse_cache_cfg(false,
+			debug_cfg->u.cache_cfg.sfe_cache_dbg,
+			&bus_priv->common_data.cache_dbg_cfg);
+	else
+		bus_priv->common_data.sfe_debug_cfg =
+			debug_cfg->u.dbg_cfg.sfe_debug_cfg;
+
 	return 0;
 }
 
@@ -2667,6 +2775,9 @@ static int cam_sfe_bus_wr_process_cmd(
 		rc = 0;
 	}
 		break;
+	case CAM_ISP_HW_SFE_SYS_CACHE_WM_CONFIG:
+		rc = cam_sfe_bus_wr_cache_config(priv, cmd_args, arg_size);
+		break;
 	case CAM_ISP_HW_CMD_SET_SFE_DEBUG_CFG:
 		rc = cam_sfe_bus_wr_set_debug_cfg(priv, cmd_args);
 		break;
@@ -2687,6 +2798,7 @@ int cam_sfe_bus_wr_init(
 	struct cam_sfe_bus                  **sfe_bus)
 {
 	int i, rc = 0;
+	struct cam_sfe_soc_private    *soc_private;
 	struct cam_sfe_bus_wr_priv    *bus_priv = NULL;
 	struct cam_sfe_bus            *sfe_bus_local;
 	struct cam_sfe_bus_wr_hw_info *hw_info = bus_hw_info;
@@ -2701,6 +2813,7 @@ int cam_sfe_bus_wr_init(
 		goto end;
 	}
 
+	soc_private = soc_info->soc_private;
 	sfe_bus_local = kzalloc(sizeof(struct cam_sfe_bus), GFP_KERNEL);
 	if (!sfe_bus_local) {
 		CAM_DBG(CAM_SFE, "Failed to alloc for sfe_bus");
@@ -2810,8 +2923,12 @@ int cam_sfe_bus_wr_init(
 	sfe_bus_local->bottom_half_handler = NULL;
 	sfe_bus_local->hw_ops.process_cmd  = __cam_sfe_bus_wr_process_cmd;
 	bus_priv->bus_irq_handle = 0;
+	bus_priv->common_data.sfe_debug_cfg = 0;
 	*sfe_bus = sfe_bus_local;
 
+	/* Remove after sys cache verification */
+	bus_priv->common_data.cache_dbg_cfg.disable_all = true;
+
 	CAM_DBG(CAM_SFE, "Exit");
 	return rc;
 

+ 57 - 5
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_bus/include/cam_sfe_bus.h

@@ -21,11 +21,22 @@
 #define ALIGNUP(value, alignment) \
 	((value + alignment - 1) / alignment * alignment)
 
-enum cam_sfe_bus_sfe_core_id {
-	CAM_SFE_BUS_SFE_CORE_0,
-	CAM_SFE_BUS_SFE_CORE_1,
-	CAM_SFE_BUS_SFE_CORE_MAX,
-};
+#define CACHE_ALLOC_NONE               0
+#define CACHE_ALLOC_ALLOC              1
+#define CACHE_ALLOC_ALLOC_CLEAN        2
+#define CACHE_ALLOC_ALLOC_TRANS        3
+#define CACHE_ALLOC_CLEAN              5
+#define CACHE_ALLOC_DEALLOC            6
+#define CACHE_ALLOC_FORGET             7
+#define CACHE_ALLOC_TBH_ALLOC          8
+
+#define DISABLE_CACHING_FOR_ALL           0xFFFFFF
+#define CACHE_SCRATCH_RD_ALLOC_SHIFT      0
+#define CACHE_SCRATCH_WR_ALLOC_SHIFT      4
+#define CACHE_SCRATCH_DEBUG_SHIFT         8
+#define CACHE_BUF_RD_ALLOC_SHIFT          12
+#define CACHE_BUF_WR_ALLOC_SHIFT          16
+#define CACHE_BUF_DEBUG_SHIFT             20
 
 enum cam_sfe_bus_plane_type {
 	PLANE_Y,
@@ -39,6 +50,31 @@ enum cam_sfe_bus_type {
 	BUS_TYPE_SFE_MAX,
 };
 
+/*
+ * struct cam_sfe_bus_cache_dbg_cfg:
+ *
+ * @Brief:                   Bus cache debug cfg
+ *
+ * @disable_all:             Disable caching for all [scratch/snapshot]
+ * @disable_for_scratch:     Disable caching for scratch
+ * @scratch_dbg_cfg:         Scratch alloc configured
+ * @scratch_alloc:           Alloc type for scratch
+ * @disable_for_buf:         Disable caching for buffer
+ * @buf_dbg_cfg:             Buf alloc configured
+ * @buf_alloc:               Alloc type for actual buffer
+ */
+struct cam_sfe_bus_cache_dbg_cfg {
+	bool disable_all;
+
+	bool disable_for_scratch;
+	bool scratch_dbg_cfg;
+	uint32_t scratch_alloc;
+
+	bool disable_for_buf;
+	bool buf_dbg_cfg;
+	uint32_t buf_alloc;
+};
+
 /*
  * struct cam_sfe_bus:
  *
@@ -98,4 +134,20 @@ int cam_sfe_bus_deinit(
 	int                        bus_type,
 	struct cam_sfe_bus       **sfe_bus);
 
+
+/*
+ * cam_sfe_bus_parse_cache_cfg()
+ *
+ * @Brief:                   Parse SFE debug config
+ *
+ * @is_read:                 If set it's RM
+ * @debug_val:               Debug val to be parsed
+ * @dbg_cfg:                 Debug cfg of RM/WM
+ *
+ */
+void cam_sfe_bus_parse_cache_cfg(
+	bool is_read,
+	uint32_t debug_val,
+	struct cam_sfe_bus_cache_dbg_cfg *dbg_cfg);
+
 #endif /* _CAM_SFE_BUS_ */

+ 4 - 2
drivers/cam_isp/isp_hw_mgr/isp_hw/sfe_hw/sfe_top/cam_sfe_top.c

@@ -927,8 +927,10 @@ static int cam_sfe_set_top_debug(
 	struct cam_sfe_debug_cfg_params *debug_cfg;
 
 	debug_cfg = (struct cam_sfe_debug_cfg_params *)cmd_args;
-	top_priv->sfe_debug_cfg = debug_cfg->sfe_debug_cfg;
-	top_priv->sensor_sel_diag_cfg = debug_cfg->sfe_sensor_sel;
+	if (!debug_cfg->cache_config) {
+		top_priv->sfe_debug_cfg = debug_cfg->u.dbg_cfg.sfe_debug_cfg;
+		top_priv->sensor_sel_diag_cfg = debug_cfg->u.dbg_cfg.sfe_sensor_sel;
+	}
 
 	return 0;
 }