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

Commit ab976d3b authored by Jeyaprakash Soundrapandian's avatar Jeyaprakash Soundrapandian Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: icp: Add Power Collapse" into dev/msm-4.9-camx

parents 9834fe7f 466bed2f
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_ */
+9 −0
Original line number Diff line number Diff line
@@ -51,6 +51,15 @@
#define ICP_CSR_DBGSWENABLE                     (1 << 22)
#define ICP_CSR_A5_STATUS_WFI                   (1 << 7)

#define ICP_FLAG_A5_CTRL_DBG_EN                 (ICP_FLAG_CSR_WAKE_UP_EN|\
						ICP_FLAG_CSR_A5_EN|\
						ICP_CSR_EDBGRQ|\
						ICP_CSR_DBGSWENABLE)

#define ICP_FLAG_A5_CTRL_EN                     (ICP_FLAG_CSR_WAKE_UP_EN|\
						ICP_FLAG_CSR_A5_EN|\
						ICP_CSR_EN_CLKGATE_WFI)

/* start of Queue table and queues */
#define MAX_ICP_HFI_QUEUES                      4
#define ICP_QHDR_TX_TYPE_MASK                   0xFF000000
+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;

/**
+82 −7
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,28 @@ void cam_hfi_disable_cpu(void __iomem *icp_base)
{
	uint32_t data;
	uint32_t val;
	uint32_t try = 0;

	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;
		/* Need to poll here to confirm that FW is going trigger wfi
		 * and Host can the proceed. No interrupt is expected from FW
		 * at this time.
		 */
		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 +454,64 @@ 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(ICP_FLAG_A5_CTRL_DBG_EN,
			(icp_base + HFI_REG_A5_CSR_A5_CONTROL));

		/* Barrier needed as next write should be done after
		 * sucessful previous write. Next write enable clock
		 * gating
		 */
		wmb();

		cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN,
			icp_base + HFI_REG_A5_CSR_A5_CONTROL);

	} else {
		cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN,
			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;

Loading