firmware: thead: Update always-on module drivers 30/316030/1
authorMichal Wilczynski <m.wilczynski@samsung.com>
Fri, 9 Aug 2024 14:59:07 +0000 (16:59 +0200)
committerMichal Wilczynski <m.wilczynski@samsung.com>
Mon, 12 Aug 2024 15:18:10 +0000 (17:18 +0200)
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 <m.wilczynski@samsung.com>
12 files changed:
arch/riscv/mm/cacheflush.c
drivers/firmware/thead/Makefile
drivers/firmware/thead/light_aon.c
drivers/firmware/thead/light_aon_misc.c
drivers/firmware/thead/light_aon_pd.c
drivers/firmware/thead/light_aon_test.c
drivers/firmware/thead/light_proc_debug.c [new file with mode: 0644]
include/dt-bindings/firmware/thead/rsrc.h [new file with mode: 0644]
include/linux/cacheflush.h
include/linux/firmware/thead/ipc.h [new file with mode: 0644]
include/linux/firmware/thead/light_event.h [new file with mode: 0644]
include/linux/light_proc_debug.h [new file with mode: 0644]

index f1387272a5512d14a8facdb6a97b208109468fc5..2c0d41a0a866e4b736b5e05d24411d170f2e9197 100644 (file)
@@ -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);
index 6bd2afe817ef4a6752d87579c244d6b7703d2494..55d7e81a20836cea51eeff78d5cd91aab4b2cd81 100644 (file)
@@ -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
index 5af7de821e76e5cf74e757ce5cee324e7825f292..36075f16c001883ba2ccb257b49599072b04860e 100644 (file)
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <linux/light_proc_debug.h>
+#include <linux/firmware/thead/ipc.h>
 
 /* 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);
index 3fb689f4b2615f1956442d46a59382eba686d715..849df94df5b12da395b8d7f3ae8396fae5a3ab6d 100644 (file)
@@ -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;
 }
index 3bef67df5a0a3e6b8db8ce2b1b3986e0f6ece06a..c1642f905b88ff48bd4266737fccf494e8f28890 100644 (file)
@@ -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);
index 172025430853c140882b86bb390e901e025bfc60..2bfe454d53379b20a7eb61dcb3b12f2b51529527 100644 (file)
@@ -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 (file)
index 0000000..8439764
--- /dev/null
@@ -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 <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>        
+#include <linux/io.h>
+#include <linux/cacheflush.h>
+
+#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 (file)
index 0000000..8cee0fc
--- /dev/null
@@ -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
index 55f297b2c23f493c5a93b8ffc4cdec69297d1be2..023ae3fa649c90d48d392d0b899bd5803ead6514 100644 (file)
@@ -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 (file)
index 0000000..b65568c
--- /dev/null
@@ -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 <linux/device.h>
+#include <linux/types.h>
+
+#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 (file)
index 0000000..a4f99d4
--- /dev/null
@@ -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 (file)
index 0000000..ad8ba8f
--- /dev/null
@@ -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
+
+