Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 78093d36 authored by Alok Pandey's avatar Alok Pandey
Browse files

msm: camera: icp: Add Power Collapse



It adds power collapse and removes fw download being done two times.
FW Download is done once only during bootup in camera server context.
After FW download, a5 is put to power collapse and wfi. During the time
of first acquire a5 core is brought back out in action.
Interframe Power collapse is enabled here. During each acquire of
ipe0/ipe1/bps FW is given control of GDSC.
A5 power collapse is always enabled. Interframe Power Collapse is
enabled by default. Interframe power collapse can be disabled using below
command. It must be disabled before usecase start.

adb shell "echo 0 > /sys/kernel/debug/camera_icp/icp_pc"

Change-Id: Idf14f164b5443fcd2872acd3526fc10acc82d11c
Signed-off-by: default avatarAlok Pandey <akumarpa@codeaurora.org>
parent 0d5bb702
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -123,8 +123,9 @@ int hfi_set_debug_level(uint32_t lvl);
 * power collapse for IPE and BPS hardware.
 *
 * @enable: flag to enable/disable
 * @core_info: Core information to firmware
 */
int hfi_enable_ipe_bps_pc(bool enable);
int hfi_enable_ipe_bps_pc(bool enable, uint32_t core_info);

/**
 * hfi_cmd_ubwc_config() - UBWC configuration to firmware
@@ -132,4 +133,15 @@ int hfi_enable_ipe_bps_pc(bool enable);
 */
int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg);

/**
 * cam_hfi_resume() - function to resume
 * @hfi_mem: hfi memory info
 * @icp_base: icp base address
 * @debug: debug flag
 *
 * Returns success(zero)/failure(non zero)
 */
int cam_hfi_resume(struct hfi_mem_info *hfi_mem,
	void __iomem *icp_base, bool debug);

#endif /* _HFI_INTF_H_ */
+2 −0
Original line number Diff line number Diff line
@@ -254,9 +254,11 @@ struct hfi_debug {
 * struct hfi_ipe_bps_pc
 * payload structure to configure HFI_PROPERTY_SYS_IPEBPS_PC
 * @enable: Flag to enable IPE, BPS interfrane power collapse
 * @core_info: Core information to firmware
 */
struct hfi_ipe_bps_pc {
	uint32_t enable;
	uint32_t core_info;
} __packed;

/**
+77 −6
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@
#define HFI_VERSION_INFO_STEP_BMSK   0xFF
#define HFI_VERSION_INFO_STEP_SHFT  0

#define HFI_MAX_POLL_TRY 5

static struct hfi_info *g_hfi;
unsigned int g_icp_mmu_hdl;
static DEFINE_MUTEX(hfi_cmd_q_mutex);
@@ -248,7 +250,7 @@ int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg)
	return 0;
}

int hfi_enable_ipe_bps_pc(bool enable)
int hfi_enable_ipe_bps_pc(bool enable, uint32_t core_info)
{
	uint8_t *prop;
	struct hfi_cmd_prop *dbg_prop;
@@ -267,6 +269,7 @@ int hfi_enable_ipe_bps_pc(bool enable)
	dbg_prop->num_prop = 1;
	dbg_prop->prop_data[0] = HFI_PROP_SYS_IPEBPS_PC;
	dbg_prop->prop_data[1] = enable;
	dbg_prop->prop_data[2] = core_info;

	hfi_write_cmd(prop);
	kfree(prop);
@@ -420,14 +423,27 @@ void cam_hfi_disable_cpu(void __iomem *icp_base)
{
	uint32_t data;
	uint32_t val;
	uint32_t try = 0;

	data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);

	while (try < HFI_MAX_POLL_TRY) {
		data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
	/* Add waiting logic in case it is not idle */
	if (data & ICP_CSR_A5_STATUS_WFI) {
		CAM_DBG(CAM_HFI, "wfi status = %x\n", (int)data);

		if (data & ICP_CSR_A5_STATUS_WFI)
			break;

		msleep(100);
		try++;
	}

	val = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_CONTROL);
	val &= ~(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN);
	cam_io_w(val, icp_base + HFI_REG_A5_CSR_A5_CONTROL);
	}

	val = cam_io_r(icp_base + HFI_REG_A5_CSR_NSEC_RESET);
	cam_io_w(val, icp_base + HFI_REG_A5_CSR_NSEC_RESET);
}

void cam_hfi_enable_cpu(void __iomem *icp_base)
@@ -437,6 +453,61 @@ void cam_hfi_enable_cpu(void __iomem *icp_base)
	cam_io_w((uint32_t)0x10, icp_base + HFI_REG_A5_CSR_NSEC_RESET);
}

int cam_hfi_resume(struct hfi_mem_info *hfi_mem,
	void __iomem *icp_base, bool debug)
{
	int rc = 0;
	uint32_t data;
	uint32_t fw_version, status = 0;

	cam_hfi_enable_cpu(icp_base);
	g_hfi->csr_base = icp_base;

	rc = readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE),
		status, status != ICP_INIT_RESP_SUCCESS, 15, 200);

	if (rc) {
		CAM_ERR(CAM_HFI, "timed out , status = %u", status);
		return -EINVAL;
	}

	fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION);
	CAM_DBG(CAM_HFI, "fw version : [%x]", fw_version);

	cam_io_w((uint32_t)INTR_ENABLE, icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);

	if (debug) {
		cam_io_w_mb(
		(uint32_t)(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN |
		ICP_CSR_EDBGRQ | ICP_CSR_DBGSWENABLE),
		icp_base + HFI_REG_A5_CSR_A5_CONTROL);
		msleep(100);
		cam_io_w_mb((uint32_t)(ICP_FLAG_CSR_A5_EN |
		ICP_FLAG_CSR_WAKE_UP_EN | ICP_CSR_EN_CLKGATE_WFI),
		icp_base + HFI_REG_A5_CSR_A5_CONTROL);
	} else {
		cam_io_w_mb((uint32_t)ICP_FLAG_CSR_A5_EN |
			ICP_FLAG_CSR_WAKE_UP_EN | ICP_CSR_EN_CLKGATE_WFI,
		icp_base + HFI_REG_A5_CSR_A5_CONTROL);
	}

	data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
	CAM_DBG(CAM_HFI, "wfi status = %x", (int)data);

	cam_io_w((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR);
	cam_io_w((uint32_t)hfi_mem->shmem.iova,
		icp_base + HFI_REG_SHARED_MEM_PTR);
	cam_io_w((uint32_t)hfi_mem->shmem.len,
		icp_base + HFI_REG_SHARED_MEM_SIZE);
	cam_io_w((uint32_t)hfi_mem->sec_heap.iova,
		icp_base + HFI_REG_UNCACHED_HEAP_PTR);
	cam_io_w((uint32_t)hfi_mem->sec_heap.len,
		icp_base + HFI_REG_UNCACHED_HEAP_SIZE);

	cam_io_w((uint32_t)INTR_ENABLE, icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
	return rc;
}

int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem,
		void __iomem *icp_base, bool debug)
{
+5 −0
Original line number Diff line number Diff line
@@ -422,6 +422,11 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type,
	case CAM_ICP_A5_SEND_INIT:
		hfi_send_system_cmd(HFI_CMD_SYS_INIT, 0, 0);
		break;

	case CAM_ICP_A5_CMD_PC_PREP:
		hfi_send_system_cmd(HFI_CMD_SYS_PC_PREP, 0, 0);
		break;

	case CAM_ICP_A5_CMD_VOTE_CPAS: {
		struct cam_icp_cpas_vote *cpas_vote = cmd_args;

+5 −2
Original line number Diff line number Diff line
@@ -157,9 +157,12 @@ static int cam_bps_handle_pc(struct cam_hw_info *bps_dev)
			CAM_CPAS_REG_CPASTOP,
			hw_info->pwr_ctrl, true, 0x1);

		if ((pwr_status >> BPS_PWR_ON_MASK))
		if ((pwr_status >> BPS_PWR_ON_MASK)) {
			CAM_ERR(CAM_ICP, "BPS: pwr_status(%x):pwr_ctrl(%x)",
				pwr_status, pwr_ctrl);
			return -EINVAL;
		}
	}
	cam_bps_get_gdsc_control(soc_info);
	cam_cpas_reg_read(core_info->cpas_handle,
		CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true,
@@ -189,7 +192,7 @@ static int cam_bps_handle_resume(struct cam_hw_info *bps_dev)
	cam_cpas_reg_read(core_info->cpas_handle,
		CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl);
	if (pwr_ctrl & BPS_COLLAPSE_MASK) {
		CAM_ERR(CAM_ICP, "BPS: resume failed : %d", pwr_ctrl);
		CAM_ERR(CAM_ICP, "BPS: pwr_ctrl(%x)", pwr_ctrl);
		return -EINVAL;
	}

Loading