From: Michal Wilczynski Date: Fri, 9 Aug 2024 14:59:07 +0000 (+0200) Subject: firmware: thead: Update always-on module drivers X-Git-Tag: accepted/tizen/unified/x/20240818.074458~10 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=50e34c3dec6aeb507d5765e5c16fe70e5f824fba;p=platform%2Fkernel%2Flinux-thead.git firmware: thead: Update always-on module drivers GPU resides in it's own power island. The always-on module is resposible for powering the GPU on. Update the drivers to the newest available from [1]. In new version the extra debug FW info was added. Sadly this new debug module called light-proc-debug needs custom thead cache flushing functions to work correctly. Port them as well. [1] - https://github.com/revyos/thead-kernel.git Change-Id: I98a3e4549cb7e3ae5d0d282af35953a04db82882 Signed-off-by: Michal Wilczynski --- diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c index f1387272a551..2c0d41a0a866 100644 --- a/arch/riscv/mm/cacheflush.c +++ b/arch/riscv/mm/cacheflush.c @@ -139,3 +139,43 @@ void __init riscv_init_cbo_blocksizes(void) if (cboz_block_size) riscv_cboz_block_size = cboz_block_size; } + +static bool thead_dma_init_flag = false; + +#define sync_is() asm volatile (".long 0x01a0000b") +void dma_wbinv_range(unsigned long start, unsigned long end) +{ + register unsigned long i asm("a0") = start & ~(L1_CACHE_BYTES - 1); + + if (!thead_dma_init_flag) + return; + + for (; i < end; i += L1_CACHE_BYTES) + asm volatile (".long 0x02b5000b"); /* dcache.cipa a0 */ + + sync_is(); +} + +void dma_wb_range(unsigned long start, unsigned long end) +{ + register unsigned long i asm("a0") = start & ~(L1_CACHE_BYTES - 1); + + if (!thead_dma_init_flag) + return; + + for (; i < end; i += L1_CACHE_BYTES) + asm volatile (".long 0x0295000b"); /* dcache.cpa a0 */ + + sync_is(); +} + +#define THEAD_VENDOR_ID 0x5b7 + +static int __init thead_dma_init(void) +{ + if (sbi_get_mvendorid() == THEAD_VENDOR_ID) + thead_dma_init_flag = true; + + return 0; +} +arch_initcall(thead_dma_init); diff --git a/drivers/firmware/thead/Makefile b/drivers/firmware/thead/Makefile index 6bd2afe817ef..55d7e81a2083 100644 --- a/drivers/firmware/thead/Makefile +++ b/drivers/firmware/thead/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_LIGHT_AON) += light_aon.o light_aon_misc.o light_aon_test.o obj-$(CONFIG_LIGHT_AON_PD) += light_aon_pd.o +obj-y += light_proc_debug.o diff --git a/drivers/firmware/thead/light_aon.c b/drivers/firmware/thead/light_aon.c index 5af7de821e76..36075f16c001 100644 --- a/drivers/firmware/thead/light_aon.c +++ b/drivers/firmware/thead/light_aon.c @@ -12,7 +12,12 @@ #include #include #include +#include +#include #include +#include +#include +#include /* wait for response for 3000ms instead of 300ms (fix me pls)*/ #define MAX_RX_TIMEOUT (msecs_to_jiffies(3000)) @@ -24,6 +29,12 @@ struct light_aon_chan { struct mbox_client cl; struct mbox_chan *ch; struct completion tx_done; + /*for log proc*/ + phys_addr_t log_phy; + size_t log_size; + void __iomem *log_mem; + void *log_ctrl; + struct proc_dir_entry *proc_dir; }; struct light_aon_ipc { @@ -101,9 +112,11 @@ static void light_aon_rx_callback(struct mbox_client *c, void *msg) { struct light_aon_chan *aon_chan = container_of(c, struct light_aon_chan, cl); struct light_aon_ipc *aon_ipc = aon_chan->aon_ipc; + struct light_aon_rpc_msg_hdr* hdr = (struct light_aon_rpc_msg_hdr*)msg; + uint8_t recv_size = sizeof(struct light_aon_rpc_msg_hdr) + hdr->size; - memcpy(aon_ipc->msg, msg, LIGHT_AON_RPC_MSG_NUM * sizeof(u32)); - dev_dbg(aon_ipc->dev, "msg head: 0x%x\n", *((u32 *)msg)); + memcpy(aon_ipc->msg, msg, recv_size); + dev_dbg(aon_ipc->dev, "msg head: 0x%x, size:%d\n", *((u32 *)msg), recv_size); complete(&aon_ipc->done); } @@ -140,19 +153,29 @@ static int light_aon_ipc_write(struct light_aon_ipc *aon_ipc, void *msg) /* * RPC command/response */ -int light_aon_call_rpc(struct light_aon_ipc *aon_ipc, void *msg, bool have_resp) +int light_aon_call_rpc(struct light_aon_ipc *aon_ipc, void *msg, void *ack_msg, bool have_resp) { - struct light_aon_rpc_msg_hdr *hdr; - int ret; + struct light_aon_rpc_msg_hdr *hdr = msg; + int ret = 0; if (WARN_ON(!aon_ipc || !msg)) return -EINVAL; - + if(have_resp && WARN_ON(!ack_msg)) + return -EINVAL; mutex_lock(&aon_ipc->lock); reinit_completion(&aon_ipc->done); - if (have_resp) - aon_ipc->msg = msg; + RPC_SET_VER(hdr, LIGHT_AON_RPC_VERSION); + /*svc id use 6bit for version 2*/ + RPC_SET_SVC_ID(hdr, hdr->svc); + RPC_SET_SVC_FLAG_MSG_TYPE(hdr, RPC_SVC_MSG_TYPE_DATA); + + if (have_resp){ + aon_ipc->msg = ack_msg; + RPC_SET_SVC_FLAG_ACK_TYPE(hdr, RPC_SVC_MSG_NEED_ACK); + } else { + RPC_SET_SVC_FLAG_ACK_TYPE(hdr, RPC_SVC_MSG_NO_NEED_ACK); + } ret = light_aon_ipc_write(aon_ipc, msg); if (ret < 0) { @@ -168,9 +191,9 @@ int light_aon_call_rpc(struct light_aon_ipc *aon_ipc, void *msg, bool have_resp) return -ETIMEDOUT; } - /* response status is stored in hdr->func field */ - hdr = msg; - ret = hdr->func; + /* response status is stored in msg data[0] field */ + struct light_aon_rpc_ack_common* ack = ack_msg; + ret = ack->err_code; } out: @@ -182,12 +205,41 @@ out: } EXPORT_SYMBOL(light_aon_call_rpc); +int get_aon_log_mem(struct device *dev, phys_addr_t* mem, size_t* mem_size) +{ + struct resource r; + ssize_t fw_size; + void *mem_va; + struct device_node *node; + int ret; + + *mem = 0; + *mem_size = 0; + + node = of_parse_phandle(dev->of_node, "log-memory-region", 0); + if (!node) { + dev_err(dev, "no memory-region specified\n"); + return -EINVAL; + } + + ret = of_address_to_resource(node, 0, &r); + if (ret) { + dev_err(dev, "memory-region get resource faild\n"); + return -EINVAL; + } + + *mem = r.start; + *mem_size = resource_size(&r); + return 0; +} + static int light_aon_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct light_aon_ipc *aon_ipc; struct light_aon_chan *aon_chan; struct mbox_client *cl; + char dir_name[32] = {0x0}; int ret; aon_ipc = devm_kzalloc(dev, sizeof(*aon_ipc), GFP_KERNEL); @@ -220,7 +272,33 @@ static int light_aon_probe(struct platform_device *pdev) aon_ipc->dev = dev; mutex_init(&aon_ipc->lock); init_completion(&aon_ipc->done); + aon_chan->log_ctrl = NULL; + ret = get_aon_log_mem(dev, &aon_chan->log_phy, &aon_chan->log_size); + if(ret) { + return ret; + } + aon_chan->log_mem = ioremap(aon_chan->log_phy, aon_chan->log_size); + if (!IS_ERR(aon_chan->log_mem)) { + printk("%s:virtual_log_mem=0x%p, phy base=0x%llx,size:%d\n", + __func__, aon_chan->log_mem, aon_chan->log_phy, + aon_chan->log_size); + } else { + aon_chan->log_mem = NULL; + dev_err(dev, "%s:get aon log region fail\n", + __func__); + return -1; + } + + sprintf(dir_name, "aon_proc"); + aon_chan->proc_dir = proc_mkdir(dir_name, NULL); + if (NULL != aon_chan->proc_dir) { + aon_chan->log_ctrl = light_create_panic_log_proc(aon_chan->log_phy, + aon_chan->proc_dir, aon_chan->log_mem, aon_chan->log_size); + } else { + dev_err(dev, "create %s fail\n", dir_name); + return ret; + } light_aon_ipc_handle = aon_ipc; return devm_of_platform_populate(dev); diff --git a/drivers/firmware/thead/light_aon_misc.c b/drivers/firmware/thead/light_aon_misc.c index 3fb689f4b261..849df94df5b1 100644 --- a/drivers/firmware/thead/light_aon_misc.c +++ b/drivers/firmware/thead/light_aon_misc.c @@ -11,37 +11,37 @@ struct light_aon_msg_req_misc_set_ctrl { u32 val; u16 resource; u16 reserved[7]; -} __packed __aligned(4); +} __packed __aligned(1); struct light_aon_msg_req_misc_get_ctrl { struct light_aon_rpc_msg_hdr hdr; u32 ctrl; u16 resource; u16 reserved[9]; -} __packed __aligned(4); +} __packed __aligned(1); struct light_aon_msg_resp_misc_get_ctrl { - struct light_aon_rpc_msg_hdr hdr; + struct light_aon_rpc_ack_common ack_hdr; u32 val; u32 reserved[5]; -} __packed __aligned(4); +} __packed __aligned(1); int light_aon_misc_set_control(struct light_aon_ipc *ipc, u16 resource, u32 ctrl, u32 val) { struct light_aon_msg_req_misc_set_ctrl msg; + struct light_aon_rpc_ack_common ack_msg; struct light_aon_rpc_msg_hdr *hdr = &msg.hdr; - hdr->ver = LIGHT_AON_RPC_VERSION; hdr->svc = (uint8_t)LIGHT_AON_RPC_SVC_MISC; hdr->func = (uint8_t)LIGHT_AON_MISC_FUNC_SET_CONTROL; hdr->size = LIGHT_AON_RPC_MSG_NUM; - msg.ctrl = ctrl; - msg.val = val; - msg.resource = resource; + RPC_SET_BE32(&msg.ctrl, 0, ctrl); + RPC_SET_BE32(&msg.ctrl, 4, val); + RPC_SET_BE16(&msg.ctrl, 8, resource); - return light_aon_call_rpc(ipc, &msg, true); + return light_aon_call_rpc(ipc, &msg, &ack_msg, true); } EXPORT_SYMBOL(light_aon_misc_set_control); @@ -49,25 +49,23 @@ int light_aon_misc_get_control(struct light_aon_ipc *ipc, u16 resource, u32 ctrl, u32 *val) { struct light_aon_msg_req_misc_get_ctrl msg; - struct light_aon_msg_resp_misc_get_ctrl *resp; + struct light_aon_msg_resp_misc_get_ctrl resp; struct light_aon_rpc_msg_hdr *hdr = &msg.hdr; int ret; - hdr->ver = LIGHT_AON_RPC_VERSION; hdr->svc = (uint8_t)LIGHT_AON_RPC_SVC_MISC; hdr->func = (uint8_t)LIGHT_AON_MISC_FUNC_GET_CONTROL; hdr->size = LIGHT_AON_RPC_MSG_NUM; - msg.ctrl = ctrl; - msg.resource = resource; + RPC_SET_BE32(&msg.ctrl, 0, ctrl); + RPC_SET_BE16(&msg.ctrl, 4, resource); - ret = light_aon_call_rpc(ipc, &msg, true); + ret = light_aon_call_rpc(ipc, &msg, &resp, true); if (ret) return ret; - resp = (struct light_aon_msg_resp_misc_get_ctrl *)&msg; if (val != NULL) - *val = resp->val; + RPC_GET_BE32(&resp.val, 0, val); return 0; } diff --git a/drivers/firmware/thead/light_aon_pd.c b/drivers/firmware/thead/light_aon_pd.c index 3bef67df5a0a..c1642f905b88 100644 --- a/drivers/firmware/thead/light_aon_pd.c +++ b/drivers/firmware/thead/light_aon_pd.c @@ -23,7 +23,7 @@ struct light_aon_msg_req_set_resource_power_mode { u16 resource; u16 mode; u16 reserved[10]; -} __packed __aligned(4); +} __packed __aligned(1); #define LIGHT_AONU_PD_NAME_SIZE 20 #define LIGHT_AONU_PD_STATE_NAME_SIZE 10 @@ -79,21 +79,21 @@ static inline struct light_aon_pm_domain *to_light_aon_pd(struct generic_pm_doma static int light_aon_pd_power(struct generic_pm_domain *domain, bool power_on) { struct light_aon_msg_req_set_resource_power_mode msg; + struct light_aon_rpc_ack_common ack_msg; struct light_aon_rpc_msg_hdr *hdr = &msg.hdr; struct light_aon_pm_domain *pd; int ret; pd = to_light_aon_pd(domain); - hdr->ver = LIGHT_AON_RPC_VERSION; hdr->svc = LIGHT_AON_RPC_SVC_PM; hdr->func = LIGHT_AON_PM_FUNC_SET_RESOURCE_POWER_MODE; hdr->size = LIGHT_AON_RPC_MSG_NUM; - msg.resource = pd->rsrc; - msg.mode = power_on ? LIGHT_AON_PM_PW_MODE_ON : LIGHT_AON_PM_PW_MODE_OFF; + RPC_SET_BE16(&msg.resource, 0, pd->rsrc); + RPC_SET_BE16(&msg.resource, 2, (power_on ? LIGHT_AON_PM_PW_MODE_ON : LIGHT_AON_PM_PW_MODE_OFF)); - ret = light_aon_call_rpc(pm_ipc_handle, &msg, true); + ret = light_aon_call_rpc(pm_ipc_handle, &msg, &ack_msg, true); if (ret) dev_err(&domain->dev, "failed to power %s resource %d ret %d\n", power_on ? "up" : "off", pd->rsrc, ret); diff --git a/drivers/firmware/thead/light_aon_test.c b/drivers/firmware/thead/light_aon_test.c index 172025430853..2bfe454d5337 100644 --- a/drivers/firmware/thead/light_aon_test.c +++ b/drivers/firmware/thead/light_aon_test.c @@ -25,20 +25,20 @@ struct light_aon_msg_req_misc_set_ctrl { u32 val; u16 resource; u16 reserved[7]; -} __packed __aligned(4); +} __packed __aligned(1); struct light_aon_msg_req_misc_get_ctrl { struct light_aon_rpc_msg_hdr hdr; u32 ctrl; u16 resource; u16 reserved[9]; -} __packed __aligned(4); +} __packed __aligned(1); struct light_aon_msg_resp_misc_get_ctrl { struct light_aon_rpc_msg_hdr hdr; u32 val; u32 reserved[5]; -} __packed __aligned(4); +} __packed __aligned(1); struct light_aon_device { struct device *dev; diff --git a/drivers/firmware/thead/light_proc_debug.c b/drivers/firmware/thead/light_proc_debug.c new file mode 100644 index 000000000000..8439764901bc --- /dev/null +++ b/drivers/firmware/thead/light_proc_debug.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * sys log sys for light c906 and e902 + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GET_PAGE_NUM(size, offset) \ + ((((size) + ((offset) & ~PAGE_MASK)) + PAGE_SIZE - 1) >> PAGE_SHIFT) + +struct light_log_ring_buffer { + __u32 read; + __u32 write; + __u32 size; + __u32 reserved[1]; + __u8 data[0]; +}; + +struct light_hw_log { + __u32 panic; + __u32 reserved[2]; + struct light_log_ring_buffer rb; +}; + +struct light_proc_log_ctrl { + struct light_hw_log __iomem *log; + struct proc_dir_entry *log_proc_file; + phys_addr_t log_phy; +}; + +static void memset_hw(void __iomem *dst, int c, size_t sz) +{ + int i; + volatile u32 *d_ptr = dst; + for (i = 0; i < sz / 4; i++) { + __raw_writel(c, d_ptr++); + } +} +static void dump_regs(const char *fn, void *hw_arg) +{ + struct light_proc_log_ctrl *log_ctrl = hw_arg; + + if (!log_ctrl->log) + return; + + pr_debug("%s: panic = 0x%08x\n", fn, + __raw_readl(&log_ctrl->log->panic)); + pr_debug("%s: read = 0x%08x, write = 0x%08x, size = 0x%08x\n", fn, + __raw_readl(&log_ctrl->log->rb.read), + __raw_readl(&log_ctrl->log->rb.write), + __raw_readl(&log_ctrl->log->rb.size)); +} + +static int log_proc_show(struct seq_file *file, void *v) +{ + struct light_proc_log_ctrl *log_ctrl = file->private; + char *buf; + size_t i; + /*dcache clean and invalid*/ + dma_wbinv_range(log_ctrl->log_phy, ((char *)log_ctrl->log_phy + + sizeof(struct light_hw_log))); + + uint32_t write = __raw_readl(&log_ctrl->log->rb.write); + uint32_t read = __raw_readl(&log_ctrl->log->rb.read); + uint32_t size = __raw_readl(&log_ctrl->log->rb.size); + size_t log_size = write >= read ? write - read : size + write - read; + + seq_printf(file, "****************** device log >>>>>>>>>>>>>>>>>\n"); + dump_regs(__func__, log_ctrl); + if (!log_size) { + seq_printf( + file, + "****************** end device log <<<<<<<<<<<<<<<<<\n"); + return 0; + } + + int page_num = GET_PAGE_NUM(log_size, 0); + + int log_patch_1 = -1, log_patch_2 = -1; + + buf = kmalloc(PAGE_SIZE * page_num, GFP_KERNEL); + if (buf) { + if (read + log_size >= size) { + log_patch_2 = read + log_size - size + 1; + log_patch_1 = log_size - log_patch_2; + + } else { + log_patch_1 = log_size; + } + + memcpy_fromio(buf, &log_ctrl->log->rb.data[read], log_patch_1); + if (log_patch_2 > 0) { + memcpy_fromio(buf, &log_ctrl->log->rb.data[0], + log_patch_2); + } + + uint8_t last_fame_size = log_size % 64; + + for (i = 0; i < log_size - last_fame_size; i += 64) { + seq_printf(file, " %*pEp", 64, buf + i); + } + if (last_fame_size) { + seq_printf(file, " %*pEp", last_fame_size, + buf + log_size - last_fame_size); + } + + __raw_writel(write, &log_ctrl->log->rb.read); + kfree(buf); + /*dcahce clean*/ + dma_wb_range(log_ctrl->log_phy, ((char *)log_ctrl->log_phy + + sizeof(struct light_hw_log))); + //seq_printf(file,"\n%d %d %d %d %d\n",log_patch_1, log_patch_2, log_size ,last_fame_size, read); + seq_printf( + file, + "\n****************** end device log <<<<<<<<<<<<<<<<<\n"); + return 0; + } else { + pr_debug("Fail to alloc buf\n"); + return -1; + } + return 0; +} + +static bool light_panic_init(struct light_hw_log *hw_log, size_t size) +{ + if (size < sizeof(struct light_hw_log)) { + return false; + } + hw_log->rb.read = 0; + hw_log->rb.size = size - sizeof(struct light_hw_log); + return true; +} + +void *light_create_panic_log_proc(phys_addr_t log_phy, void *dir, + void *log_info_addr, size_t size) +{ + struct light_proc_log_ctrl *log_ctrl = + kmalloc(sizeof(struct light_proc_log_ctrl), GFP_KERNEL); + + if (log_ctrl == NULL) + return NULL; + + log_ctrl->log = log_info_addr; + + light_panic_init(log_ctrl->log, size); + + log_ctrl->log_proc_file = proc_create_single_data( + "proc_log", 0644, dir, &log_proc_show, log_ctrl); + if (log_ctrl->log_proc_file == NULL) { + pr_debug("Error: Could not initialize %s\n", "dsp_log"); + kfree(log_ctrl); + log_ctrl = NULL; + } else { + pr_debug("%s create Success!\n", "dsp_log"); + } + log_ctrl->log_phy = log_phy; + return log_ctrl; +} + +void light_remove_panic_log_proc(void *arg) +{ + struct light_proc_log_ctrl *log_ctrl = + (struct light_proc_log_ctrl *)arg; + + proc_remove(log_ctrl->log_proc_file); + kfree(log_ctrl); + pr_debug("light proc log removed\n"); +} \ No newline at end of file diff --git a/include/dt-bindings/firmware/thead/rsrc.h b/include/dt-bindings/firmware/thead/rsrc.h new file mode 100644 index 000000000000..8cee0fcaeb74 --- /dev/null +++ b/include/dt-bindings/firmware/thead/rsrc.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2022 Alibaba Group Holding Limited. + */ + +#ifndef __DT_BINDINGS_RSCRC_LIGHT_H +#define __DT_BINDINGS_RSCRC_LIGHT_H + +#define LIGHT_AON_AUDIO_PD 0 +#define LIGHT_AON_VDEC_PD 1 +#define LIGHT_AON_NPU_PD 2 +#define LIGHT_AON_VENC_PD 3 +#define LIGHT_AON_GPU_PD 4 +#define LIGHT_AON_DSP0_PD 5 +#define LIGHT_AON_DSP1_PD 6 + +#endif diff --git a/include/linux/cacheflush.h b/include/linux/cacheflush.h index 55f297b2c23f..023ae3fa649c 100644 --- a/include/linux/cacheflush.h +++ b/include/linux/cacheflush.h @@ -24,6 +24,9 @@ static inline void flush_icache_pages(struct vm_area_struct *vma, } #endif +void dma_wbinv_range(unsigned long start, unsigned long end); +void dma_wb_range(unsigned long start, unsigned long end); + #define flush_icache_page(vma, page) flush_icache_pages(vma, page, 1) #endif /* _LINUX_CACHEFLUSH_H */ diff --git a/include/linux/firmware/thead/ipc.h b/include/linux/firmware/thead/ipc.h new file mode 100644 index 000000000000..b65568c95cca --- /dev/null +++ b/include/linux/firmware/thead/ipc.h @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ + +#ifndef _SC_IPC_H +#define _SC_IPC_H + +#include +#include + +#define AON_RPC_MSG_MAGIC (0xef) +#define LIGHT_AON_RPC_VERSION 2 +#define LIGHT_AON_RPC_MSG_NUM 7 + +struct light_aon_ipc; + +enum light_aon_rpc_svc { + LIGHT_AON_RPC_SVC_UNKNOWN = 0, + LIGHT_AON_RPC_SVC_PM = 1, + LIGHT_AON_RPC_SVC_MISC = 2, + LIGHT_AON_RPC_SVC_AVFS = 3, + LIGHT_AON_RPC_SVC_SYS = 4, + LIGHT_AON_RPC_SVC_WDG = 5, + LIGHT_AON_RPC_SVC_LPM = 6, + LIGHT_AON_RPC_SVC_MAX = 0x3F, +}; + +enum light_aon_misc_func { + LIGHT_AON_MISC_FUNC_UNKNOWN = 0, + LIGHT_AON_MISC_FUNC_SET_CONTROL = 1, + LIGHT_AON_MISC_FUNC_GET_CONTROL = 2, + LIGHT_AON_MISC_FUNC_REGDUMP_CFG = 3, +}; + +enum light_aon_wdg_func { + LIGHT_AON_WDG_FUNC_UNKNOWN = 0, + LIGHT_AON_WDG_FUNC_START = 1, + LIGHT_AON_WDG_FUNC_STOP = 2, + LIGHT_AON_WDG_FUNC_PING = 3, + LIGHT_AON_WDG_FUNC_TIMEOUTSET = 4, + LIGHT_AON_WDG_FUNC_RESTART = 5, + LIGHT_AON_WDG_FUNC_GET_STATE = 6, + LIGHT_AON_WDG_FUNC_POWER_OFF = 7, + LIGHT_AON_WDG_FUNC_AON_WDT_ON = 8, + LIGHT_AON_WDG_FUNC_AON_WDT_OFF = 9, +}; + +enum light_aon_sys_func { + LIGHT_AON_SYS_FUNC_UNKNOWN = 0, + LIGHT_AON_SYS_FUNC_AON_RESERVE_MEM = 1, +}; + +enum light_aon_lpm_func { + LIGHT_AON_LPM_FUNC_UNKNOWN = 0, + LIGHT_AON_LPM_FUNC_REQUIRE_STR = 1, + LIGHT_AON_LPM_FUNC_RESUME_STR = 2, + LIGHT_AON_LPM_FUNC_REQUIRE_STD = 3, + LIGHT_AON_LPM_FUNC_CPUHP = 4, + LIGHT_AON_LPM_FUNC_REGDUMP_CFG = 5, +}; + +enum light_aon_pm_func { + LIGHT_AON_PM_FUNC_UNKNOWN = 0, + LIGHT_AON_PM_FUNC_SET_RESOURCE_REGULATOR = 1, + LIGHT_AON_PM_FUNC_GET_RESOURCE_REGULATOR = 2, + LIGHT_AON_PM_FUNC_SET_RESOURCE_POWER_MODE = 3, + LIGHT_AON_PM_FUNC_PWR_SET = 4, + LIGHT_AON_PM_FUNC_PWR_GET = 5, + LIGHT_AON_PM_FUNC_CHECK_FAULT = 6, + LIGHT_AON_PM_FUNC_GET_TEMPERATURE = 7, +}; + +struct light_aon_rpc_msg_hdr { + uint8_t ver; ///< version of msg hdr + uint8_t size; ///< msg size ,uinit in bytes,the size includes rpc msg header self. + uint8_t svc; ///< rpc main service id + uint8_t func; ///< rpc sub func id of specific service, sent by caller +} __packed __aligned(1); + +struct light_aon_rpc_ack_common { + struct light_aon_rpc_msg_hdr hdr; + u8 err_code; +} __packed __aligned(1); + +#define RPC_SVC_MSG_TYPE_DATA 0 +#define RPC_SVC_MSG_TYPE_ACK 1 +#define RPC_SVC_MSG_NEED_ACK 0 +#define RPC_SVC_MSG_NO_NEED_ACK 1 + +#define RPC_GET_VER(MESG) ((MESG)->ver) +#define RPC_SET_VER(MESG, VER) ((MESG)->ver = (VER)) +#define RPC_GET_SVC_ID(MESG) ((MESG)->svc & 0x3F) +#define RPC_SET_SVC_ID(MESG, ID) ((MESG)->svc |= 0x3F & (ID)) +#define RPC_GET_SVC_FLAG_MSG_TYPE(MESG) (((MESG)->svc & 0x80) >> 7) +#define RPC_SET_SVC_FLAG_MSG_TYPE(MESG, TYPE) ((MESG)->svc |= (TYPE) << 7) +#define RPC_GET_SVC_FLAG_ACK_TYPE(MESG) (((MESG)->svc & 0x40) >> 6) +#define RPC_SET_SVC_FLAG_ACK_TYPE(MESG, ACK) ((MESG)->svc |= (ACK) << 6) + +#define RPC_SET_BE64(MESG, OFFSET, SET_DATA) do {uint8_t* data = (uint8_t*)(MESG); \ + data[OFFSET + 7] = (SET_DATA) & 0xFF; \ + data[OFFSET + 6] = ((SET_DATA) & 0xFF00) >> 8; \ + data[OFFSET + 5] = ((SET_DATA) & 0xFF0000) >> 16; \ + data[OFFSET + 4] = ((SET_DATA) & 0xFF000000) >> 24; \ + data[OFFSET + 3] = ((SET_DATA) & 0xFF00000000) >> 32; \ + data[OFFSET + 2] = ((SET_DATA) & 0xFF0000000000) >> 40; \ + data[OFFSET + 1] = ((SET_DATA) & 0xFF000000000000) >> 48; \ + data[OFFSET + 0] = ((SET_DATA) & 0xFF00000000000000) >> 56; \ + } while(0) + +#define RPC_SET_BE32(MESG, OFFSET, SET_DATA) do { uint8_t* data = (uint8_t*)(MESG); \ + data[OFFSET + 3] = (SET_DATA) & 0xFF; \ + data[OFFSET + 2] = ((SET_DATA) & 0xFF00) >> 8; \ + data[OFFSET + 1] = ((SET_DATA) & 0xFF0000) >> 16; \ + data[OFFSET + 0] = ((SET_DATA) & 0xFF000000) >> 24; \ + } while(0) +#define RPC_SET_BE16(MESG, OFFSET, SET_DATA) do { uint8_t* data = (uint8_t*)(MESG); \ + data[OFFSET + 1] = (SET_DATA) & 0xFF; \ + data[OFFSET + 0] = ((SET_DATA) & 0xFF00) >> 8; \ + } while(0) +#define RPC_SET_U8(MESG, OFFSET, SET_DATA) do { uint8_t* data = (uint8_t*)(MESG); \ + data[OFFSET] = (SET_DATA) & 0xFF; \ + } while(0) +#define RPC_GET_BE64(MESG, OFFSET, PTR) do {uint8_t* data = (uint8_t*)(MESG); \ + *(uint32_t*)(PTR) = (data[OFFSET + 7] | data[OFFSET + 6] << 8 | data[OFFSET + 5] << 16 | data[OFFSET + 4] << 24 | \ + data[OFFSET + 3] << 32 | data[OFFSET + 2] << 40 | data[OFFSET + 1] << 48 | data[OFFSET + 0] << 56); \ + } while(0) +#define RPC_GET_BE32(MESG, OFFSET, PTR) do {uint8_t* data = (uint8_t*)(MESG); \ + *(uint32_t*)(PTR) = (data[OFFSET + 3] | data[OFFSET + 2] << 8 | data[OFFSET + 1] << 16 | data[OFFSET + 0] << 24); \ + } while(0) +#define RPC_GET_BE16(MESG, OFFSET, PTR) do {uint8_t* data = (uint8_t*)(MESG); \ + *(uint16_t*)(PTR) = (data[OFFSET + 1] | data[OFFSET + 0] << 8); \ + } while(0) +#define RPC_GET_U8(MESG, OFFSET, PTR) do {uint8_t* data = (uint8_t*)(MESG); \ + *(uint8_t*)(PTR) = (data[OFFSET]); \ + } while(0) + + +/* + * Defines for SC PM Power Mode + */ +#define LIGHT_AON_PM_PW_MODE_OFF 0 /* Power off */ +#define LIGHT_AON_PM_PW_MODE_STBY 1 /* Power in standby */ +#define LIGHT_AON_PM_PW_MODE_LP 2 /* Power in low-power */ +#define LIGHT_AON_PM_PW_MODE_ON 3 /* Power on */ + +int light_aon_call_rpc(struct light_aon_ipc *ipc, void *msg, void *ack_msg, bool have_resp); +int light_aon_get_handle(struct light_aon_ipc **ipc); +int light_aon_misc_set_control(struct light_aon_ipc *ipc, u16 resource, u32 ctrl, u32 val); +int light_aon_misc_get_control(struct light_aon_ipc *ipc, u16 resource, u32 ctrl, u32 *val); +#endif /* _SC_IPC_H */ diff --git a/include/linux/firmware/thead/light_event.h b/include/linux/firmware/thead/light_event.h new file mode 100644 index 000000000000..a4f99d41c2d1 --- /dev/null +++ b/include/linux/firmware/thead/light_event.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LIGHT_EVENT_H +#define _LIGHT_EVENT_H + +enum light_rebootmode_index { + /* C902 event rebootmode */ + LIGHT_EVENT_PMIC_RESET = 0x0, + LIGHT_EVENT_PMIC_ONKEY, + LIGHT_EVENT_PMIC_POWERUP, + + /* C910 event rebootmode */ + LIGHT_EVENT_SW_REBOOT = 0x20, + LIGHT_EVENT_SW_WATCHDOG, + LIGHT_EVENT_SW_PANIC, + LIGHT_EVENT_SW_HANG, + LIGHT_EVENT_MAX, +}; + +#if IS_ENABLED(CONFIG_LIGHT_REBOOTMODE) +extern int light_event_set_rebootmode(enum light_rebootmode_index mode); +extern int light_event_get_rebootmode(enum light_rebootmode_index *mode); +#else +static int light_event_set_rebootmode(enum light_rebootmode_index mode) +{ + return 0; +} +static int light_event_get_rebootmode(enum light_rebootmode_index *mode) +{ + *mode = LIGHT_EVENT_MAX; + + return 0; +} +#endif + +#endif diff --git a/include/linux/light_proc_debug.h b/include/linux/light_proc_debug.h new file mode 100644 index 000000000000..ad8ba8f32363 --- /dev/null +++ b/include/linux/light_proc_debug.h @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Alibaba Group Holding Limited. + */ + +#ifndef __LIGHT_PROC_DEBUG_H_ +#define __LIGHT_PROC_DEBUG_H_ + + +void *light_create_panic_log_proc(phys_addr_t log_phy, void *dir, void *log_addr, size_t size); +void light_remove_panic_log_proc(void *arg); + +#endif + +