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

Commit 528d44a3 authored by Fernando Pacheco's avatar Fernando Pacheco
Browse files

msm: camera: icp: Support processor-specific HFI register offsets



The HFI interface registers will have a different base address
on the LX7 processor. We can utilize the newly added HFI ops to
abstract the calculation of the address by kicking that info out
to the device interface. The HFI register definitions have been
tweaked to support offsets based on the calculated addresses.

CRs-Fixed: 2722486
Change-Id: I93b9b2827ec0820eaac6ee2e6a611363b96a3223
Signed-off-by: default avatarFernando Pacheco <fpacheco@codeaurora.org>
parent 526970e7
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ struct hfi_mem {
 * @qdss: qdss mapped memory for fw
 * @io_mem: io memory info
 * @io_mem2: 2nd io memory info
 * @icp_base: icp base address
 */
struct hfi_mem_info {
	struct hfi_mem qtbl;
@@ -46,17 +45,18 @@ struct hfi_mem_info {
	struct hfi_mem qdss;
	struct hfi_mem io_mem;
	struct hfi_mem io_mem2;
	void __iomem *icp_base;
};

/**
 * struct hfi_ops
 * @irq_raise: called to raise H2ICP interrupt
 * @irq_enable: called to enable interrupts from ICP
 * @iface_addr: called to get interface registers base address
 */
struct hfi_ops {
	void (*irq_raise)(void *data);
	void (*irq_enable)(void *data);
	void __iomem *(*iface_addr)(void *data);
};

/**
@@ -84,12 +84,11 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, uint32_t *words_read);
 * @hfi_ops: processor-specific hfi ops
 * @priv: device private data
 * @event_driven_mode: event mode
 * @icp_base: icp base address
 *
 * Returns success(zero)/failure(non zero)
 */
int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops,
		void *priv, uint8_t event_driven_mode, void *__iomem icp_base);
int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops,
		void *priv, uint8_t event_driven_mode);

/**
 * hfi_get_hw_caps() - hardware capabilities from firmware
@@ -110,7 +109,7 @@ void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size);
/**
 * cam_hfi_deinit() - cleanup HFI
 */
void cam_hfi_deinit(void __iomem *icp_base);
void cam_hfi_deinit(void);
/**
 * hfi_set_debug_level() - set debug level
 * @a5_dbg_type: 1 for debug_q & 2 for qdss
@@ -152,11 +151,10 @@ 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
 *
 * Returns success(zero)/failure(non zero)
 */
int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base);
int cam_hfi_resume(struct hfi_mem_info *hfi_mem);

/**
 * cam_hfi_queue_dump() - utility function to dump hfi queues
+17 −22
Original line number Diff line number Diff line
@@ -9,27 +9,24 @@
#include <linux/types.h>
#include "hfi_intf.h"

/* start of ICP CSR registers */
#define HFI_REG_A5_HW_VERSION                   0x0
/* general purpose registers */
#define GEN_PURPOSE_REG(n)              (n * 4)

/* general purpose registers from */
#define HFI_REG_FW_VERSION                      0x44
#define HFI_REG_HOST_ICP_INIT_REQUEST           0x48
#define HFI_REG_ICP_HOST_INIT_RESPONSE          0x4C
#define HFI_REG_SHARED_MEM_PTR                  0x50
#define HFI_REG_SHARED_MEM_SIZE                 0x54
#define HFI_REG_QTBL_PTR                        0x58
#define HFI_REG_UNCACHED_HEAP_PTR               0x5C
#define HFI_REG_UNCACHED_HEAP_SIZE              0x60
#define HFI_REG_QDSS_IOVA                       0x6C
#define HFI_REG_SFR_PTR                         0x68
#define HFI_REG_QDSS_IOVA_SIZE                  0x70
#define HFI_REG_IO_REGION_IOVA                  0x74
#define HFI_REG_IO_REGION_SIZE                  0x78
#define HFI_REG_IO2_REGION_IOVA                 0x7C
#define HFI_REG_IO2_REGION_SIZE                 0x80

/* end of ICP CSR registers */
#define HFI_REG_FW_VERSION              GEN_PURPOSE_REG(1)
#define HFI_REG_HOST_ICP_INIT_REQUEST   GEN_PURPOSE_REG(2)
#define HFI_REG_ICP_HOST_INIT_RESPONSE  GEN_PURPOSE_REG(3)
#define HFI_REG_SHARED_MEM_PTR          GEN_PURPOSE_REG(4)
#define HFI_REG_SHARED_MEM_SIZE         GEN_PURPOSE_REG(5)
#define HFI_REG_QTBL_PTR                GEN_PURPOSE_REG(6)
#define HFI_REG_UNCACHED_HEAP_PTR       GEN_PURPOSE_REG(7)
#define HFI_REG_UNCACHED_HEAP_SIZE      GEN_PURPOSE_REG(8)
#define HFI_REG_SFR_PTR                 GEN_PURPOSE_REG(10)
#define HFI_REG_QDSS_IOVA               GEN_PURPOSE_REG(11)
#define HFI_REG_QDSS_IOVA_SIZE          GEN_PURPOSE_REG(12)
#define HFI_REG_IO_REGION_IOVA          GEN_PURPOSE_REG(13)
#define HFI_REG_IO_REGION_SIZE          GEN_PURPOSE_REG(14)
#define HFI_REG_IO2_REGION_IOVA         GEN_PURPOSE_REG(15)
#define HFI_REG_IO2_REGION_SIZE         GEN_PURPOSE_REG(16)

/* start of Queue table and queues */
#define MAX_ICP_HFI_QUEUES                      4
@@ -278,7 +275,6 @@ struct hfi_qtbl {
 * @cmd_q_state: State of command queue
 * @mutex msg_q_lock: Lock for message queue
 * @msg_q_state: State of message queue
 * @csr_base: CSR base address
 * @priv: device private data
 */
struct hfi_info {
@@ -292,7 +288,6 @@ struct hfi_info {
	bool cmd_q_state;
	struct mutex msg_q_lock;
	bool msg_q_state;
	void __iomem *csr_base;
	void *priv;
};

+33 −13
Original line number Diff line number Diff line
@@ -51,6 +51,16 @@ static void hfi_irq_enable(struct hfi_info *hfi)
		hfi->ops.irq_enable(hfi->priv);
}

static void __iomem *hfi_iface_addr(struct hfi_info *hfi)
{
	void __iomem *ret = NULL;

	if (hfi->ops.iface_addr)
		ret = hfi->ops.iface_addr(hfi->priv);

	return IS_ERR_OR_NULL(ret) ? NULL : ret;
}

void cam_hfi_queue_dump(void)
{
	struct hfi_qtbl *qtbl;
@@ -550,12 +560,16 @@ int hfi_get_hw_caps(void *query_buf)
	return 0;
}

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

	g_hfi->csr_base = icp_base;
	if (!icp_base) {
		CAM_ERR(CAM_HFI, "invalid HFI interface address");
		return -EINVAL;
	}

	if (readl_poll_timeout(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE,
			       status, status == ICP_INIT_RESP_SUCCESS,
@@ -602,15 +616,16 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base)
	return rc;
}

int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops,
		void *priv, uint8_t event_driven_mode, void __iomem *icp_base)
int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops,
		void *priv, uint8_t event_driven_mode)
{
	int rc = 0;
	uint32_t status = 0;
	struct hfi_qtbl *qtbl;
	struct hfi_qtbl_hdr *qtbl_hdr;
	struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr;
	uint32_t hw_version, fw_version, status = 0;
	struct sfr_buf *sfr_buffer;
	void __iomem *icp_base;

	if (!hfi_mem || !hfi_ops || !priv) {
		CAM_ERR(CAM_HFI,
@@ -752,6 +767,16 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops,
		break;
	}

	g_hfi->ops = *hfi_ops;
	g_hfi->priv = priv;

	icp_base = hfi_iface_addr(g_hfi);
	if (!icp_base) {
		CAM_ERR(CAM_HFI, "invalid HFI interface address");
		rc = -EINVAL;
		goto regions_fail;
	}

	cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova,
		icp_base + HFI_REG_QTBL_PTR);
	cam_io_w_mb((uint32_t)hfi_mem->sfr_buf.iova,
@@ -792,17 +817,12 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops,
		goto regions_fail;
	}

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

	g_hfi->csr_base = icp_base;
	g_hfi->hfi_state = HFI_READY;
	g_hfi->cmd_q_state = true;
	g_hfi->msg_q_state = true;
	g_hfi->ops = *hfi_ops;
	g_hfi->priv = priv;

	hfi_irq_enable(g_hfi);

@@ -819,7 +839,7 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops,
	return rc;
}

void cam_hfi_deinit(void __iomem *icp_base)
void cam_hfi_deinit(void)
{
	mutex_lock(&hfi_cmd_q_mutex);
	mutex_lock(&hfi_msg_q_mutex);
+17 −0
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@
#define PC_POLL_DELAY_US 100
#define PC_POLL_TIMEOUT_US 10000

#define A5_GEN_PURPOSE_REG_OFFSET 0x40

static int cam_a5_cpas_vote(struct cam_a5_device_core_info *core_info,
	struct cam_icp_cpas_vote *cpas_vote)
{
@@ -513,6 +515,21 @@ void cam_a5_irq_enable(void *priv)
		ICP_SIERRA_A5_CSR_A2HOSTINTEN);
}

void __iomem *cam_a5_iface_addr(void *priv)
{
	struct cam_hw_info *a5_info = priv;
	void __iomem *base;

	if (!a5_info) {
		CAM_ERR(CAM_ICP, "invalid A5 device info");
		return ERR_PTR(-EINVAL);
	}

	base = a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base;

	return base + A5_GEN_PURPOSE_REG_OFFSET;
}

int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type,
	void *cmd_args, uint32_t arg_size)
{
+1 −0
Original line number Diff line number Diff line
@@ -83,6 +83,7 @@ irqreturn_t cam_a5_irq(int irq_num, void *data);

void cam_a5_irq_raise(void *priv);
void cam_a5_irq_enable(void *priv);
void __iomem *cam_a5_iface_addr(void *priv);

/**
 * @brief : API to register a5 hw to platform framework.
Loading