mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 07:03:09 -04:00
Merge "msm: camera: icp: Support processor-specific HFI register offsets" into camera-kernel.lnx.4.0
This commit is contained in:
commit
733005152b
6 changed files with 90 additions and 67 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 @@ alloc_fail:
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -53,6 +53,12 @@
|
|||
|
||||
#define ICP_DEVICE_IDLE_TIMEOUT 400
|
||||
|
||||
static const struct hfi_ops hfi_a5_ops = {
|
||||
.irq_raise = cam_a5_irq_raise,
|
||||
.irq_enable = cam_a5_irq_enable,
|
||||
.iface_addr = cam_a5_iface_addr,
|
||||
};
|
||||
|
||||
static struct cam_icp_hw_mgr icp_hw_mgr;
|
||||
|
||||
static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl);
|
||||
|
|
@ -3118,17 +3124,8 @@ static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr)
|
|||
|
||||
static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr)
|
||||
{
|
||||
struct cam_hw_intf *a5_dev_intf = NULL;
|
||||
struct cam_hw_info *a5_dev = NULL;
|
||||
struct hfi_mem_info hfi_mem;
|
||||
|
||||
a5_dev_intf = hw_mgr->a5_dev_intf;
|
||||
if (!a5_dev_intf) {
|
||||
CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv;
|
||||
|
||||
hfi_mem.qtbl.kva = icp_hw_mgr.hfi_mem.qtbl.kva;
|
||||
hfi_mem.qtbl.iova = icp_hw_mgr.hfi_mem.qtbl.iova;
|
||||
hfi_mem.qtbl.len = icp_hw_mgr.hfi_mem.qtbl.len;
|
||||
|
|
@ -3203,8 +3200,7 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr)
|
|||
hfi_mem.io_mem2.iova,
|
||||
hfi_mem.io_mem2.len);
|
||||
|
||||
return cam_hfi_resume(&hfi_mem,
|
||||
a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base);
|
||||
return cam_hfi_resume(&hfi_mem);
|
||||
}
|
||||
|
||||
static int cam_icp_retry_wait_for_abort(
|
||||
|
|
@ -3479,7 +3475,6 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args)
|
|||
{
|
||||
struct cam_icp_hw_mgr *hw_mgr = hw_priv;
|
||||
struct cam_hw_intf *a5_dev_intf = NULL;
|
||||
struct cam_hw_info *a5_dev = NULL;
|
||||
struct cam_icp_a5_set_irq_cb irq_cb;
|
||||
struct cam_icp_a5_set_fw_buf_info fw_buf_info;
|
||||
int rc = 0;
|
||||
|
|
@ -3494,7 +3489,7 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args)
|
|||
CAM_DBG(CAM_ICP, "a5_dev_intf is NULL");
|
||||
return -EINVAL;
|
||||
}
|
||||
a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv;
|
||||
|
||||
fw_buf_info.kva = 0;
|
||||
fw_buf_info.iova = 0;
|
||||
fw_buf_info.len = 0;
|
||||
|
|
@ -3505,8 +3500,9 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args)
|
|||
sizeof(fw_buf_info));
|
||||
if (rc)
|
||||
CAM_ERR(CAM_ICP, "nullify the fw buf failed");
|
||||
cam_hfi_deinit(
|
||||
a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base);
|
||||
|
||||
cam_hfi_deinit();
|
||||
|
||||
irq_cb.icp_hw_mgr_cb = NULL;
|
||||
irq_cb.data = NULL;
|
||||
rc = a5_dev_intf->hw_ops.process_cmd(
|
||||
|
|
@ -3624,7 +3620,7 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr)
|
|||
struct cam_hw_intf *a5_dev_intf = NULL;
|
||||
struct cam_hw_info *a5_dev = NULL;
|
||||
struct hfi_mem_info hfi_mem;
|
||||
struct hfi_ops hfi_ops;
|
||||
const struct hfi_ops *hfi_ops;
|
||||
|
||||
a5_dev_intf = hw_mgr->a5_dev_intf;
|
||||
if (!a5_dev_intf) {
|
||||
|
|
@ -3689,11 +3685,9 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr)
|
|||
hfi_mem.io_mem2.len = 0x0;
|
||||
}
|
||||
|
||||
hfi_ops.irq_raise = cam_a5_irq_raise;
|
||||
hfi_ops.irq_enable = cam_a5_irq_enable;
|
||||
hfi_ops = &hfi_a5_ops;
|
||||
|
||||
return cam_hfi_init(&hfi_mem, &hfi_ops, a5_dev, 0,
|
||||
a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base);
|
||||
return cam_hfi_init(&hfi_mem, hfi_ops, a5_dev, 0);
|
||||
}
|
||||
|
||||
static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr)
|
||||
|
|
@ -3807,7 +3801,6 @@ hw_deinit:
|
|||
static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args)
|
||||
{
|
||||
struct cam_hw_intf *a5_dev_intf = NULL;
|
||||
struct cam_hw_info *a5_dev = NULL;
|
||||
struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv;
|
||||
bool icp_pc = false;
|
||||
int rc = 0;
|
||||
|
|
@ -3827,7 +3820,7 @@ static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args)
|
|||
CAM_ERR(CAM_ICP, "a5_dev_intf is invalid");
|
||||
return -EINVAL;
|
||||
}
|
||||
a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv;
|
||||
|
||||
rc = cam_icp_allocate_hfi_mem();
|
||||
if (rc)
|
||||
goto alloc_hfi_mem_failed;
|
||||
|
|
@ -3873,8 +3866,7 @@ static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args)
|
|||
return rc;
|
||||
|
||||
fw_init_failed:
|
||||
cam_hfi_deinit(
|
||||
a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base);
|
||||
cam_hfi_deinit();
|
||||
hfi_init_failed:
|
||||
cam_icp_mgr_proc_suspend(hw_mgr);
|
||||
fw_download_failed:
|
||||
|
|
|
|||
Loading…
Reference in a new issue