From f310a3555874809ae0ecc487bb7d75818f783166 Mon Sep 17 00:00:00 2001 From: Taejin Kim Date: Mon, 14 May 2018 18:56:06 +0900 Subject: [PATCH] [COMMON] drivers: misc: mcu_ipc: Apply mcu_ipc & shm_ipc drivers Change-Id: Ibf0effbf91de968eccbda381efa3a66315cb0f3f Signed-off-by: Taejin Kim --- drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 1 + drivers/misc/mcu_ipc/Kconfig | 26 + drivers/misc/mcu_ipc/Makefile | 6 + drivers/misc/mcu_ipc/mcu_ipc.c | 368 ++++++++++++++ drivers/misc/mcu_ipc/mcu_ipc.h | 121 +++++ drivers/misc/mcu_ipc/regs-mcu_ipc.h | 57 +++ drivers/misc/mcu_ipc/shm_ipc.c | 747 ++++++++++++++++++++++++++++ include/linux/mcu_ipc.h | 56 +++ include/linux/shm_ipc.h | 99 ++++ 10 files changed, 1482 insertions(+) create mode 100644 drivers/misc/mcu_ipc/Kconfig create mode 100644 drivers/misc/mcu_ipc/Makefile create mode 100644 drivers/misc/mcu_ipc/mcu_ipc.c create mode 100644 drivers/misc/mcu_ipc/mcu_ipc.h create mode 100644 drivers/misc/mcu_ipc/regs-mcu_ipc.h create mode 100644 drivers/misc/mcu_ipc/shm_ipc.c create mode 100644 include/linux/mcu_ipc.h create mode 100644 include/linux/shm_ipc.h diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index ce2449ad1688..c3ae75a8ecb1 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -539,4 +539,5 @@ source "drivers/misc/mic/Kconfig" source "drivers/misc/genwqe/Kconfig" source "drivers/misc/echo/Kconfig" source "drivers/misc/cxl/Kconfig" +source "drivers/misc/mcu_ipc/Kconfig" endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 63e802aebb03..c9175204c35f 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o obj-$(CONFIG_PCI_ENDPOINT_TEST) += pci_endpoint_test.o obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o +obj-$(CONFIG_MCU_IPC) += mcu_ipc/ obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o lkdtm-$(CONFIG_LKDTM) += lkdtm_core.o diff --git a/drivers/misc/mcu_ipc/Kconfig b/drivers/misc/mcu_ipc/Kconfig new file mode 100644 index 000000000000..5986087911cb --- /dev/null +++ b/drivers/misc/mcu_ipc/Kconfig @@ -0,0 +1,26 @@ +# +# MCU_IPC Device Driver +# + +config MCU_IPC + bool "MCU IPC Support" + default n + help + This enables MCU_IPC driver to control the MCU_IPC Device. + + MCU_IPC is the Mailbox which has 16 interrupts for TX/RX each + and 256 bytes memory for communicating messages. + AP and CP can share the messages through this device. + +config MCU_IPC_TEST + bool "MCU_IPC driver test" + depends on MCU_IPC + help + This enables MCU_IPC_TEST for checking mailbox at probe time. + +config SHM_IPC + bool "Shared Memory for IPC support" + default n + help + This enables SHM_IPC driver to control the Shared memory + for AP-CP Interface. diff --git a/drivers/misc/mcu_ipc/Makefile b/drivers/misc/mcu_ipc/Makefile new file mode 100644 index 000000000000..5b23d9945d61 --- /dev/null +++ b/drivers/misc/mcu_ipc/Makefile @@ -0,0 +1,6 @@ +# +# MCU_IPC Device Driver +# + +obj-$(CONFIG_MCU_IPC) += mcu_ipc.o +obj-$(CONFIG_SHM_IPC) += shm_ipc.o diff --git a/drivers/misc/mcu_ipc/mcu_ipc.c b/drivers/misc/mcu_ipc/mcu_ipc.c new file mode 100644 index 000000000000..cd9faceee1ba --- /dev/null +++ b/drivers/misc/mcu_ipc/mcu_ipc.c @@ -0,0 +1,368 @@ +/* + * Copyright (C) 2014 Samsung Electronics Co.Ltd + * http://www.samsung.com + * + * MCU IPC driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "regs-mcu_ipc.h" +#include "mcu_ipc.h" + +static irqreturn_t mcu_ipc_handler(int irq, void *data) +{ + u32 irq_stat, i; + u32 id; + + id = ((struct mcu_ipc_drv_data *)data)->id; + irq_stat = mcu_ipc_readl(id, EXYNOS_MCU_IPC_INTSR0) & 0xFFFF0000; + + /* Interrupt Clear */ + mcu_ipc_writel(id, irq_stat, EXYNOS_MCU_IPC_INTCR0); + + for (i = 0; i < 16; i++) { + if (irq_stat & (1 << (i + 16))) { + if ((1 << (i + 16)) & mcu_dat[id].registered_irq) + mcu_dat[id].hd[i].handler(mcu_dat[id].hd[i].data); + else + dev_err(mcu_dat[id].mcu_ipc_dev, + "Unregistered INT received.\n"); + + irq_stat &= ~(1 << (i + 16)); + } + + if (!irq_stat) + break; + } + + return IRQ_HANDLED; +} + +int mbox_request_irq(enum mcu_ipc_region id, u32 int_num, + void (*handler)(void *), void *data) +{ + if ((!handler) || (int_num > 15)) + return -EINVAL; + + mcu_dat[id].hd[int_num].data = data; + mcu_dat[id].hd[int_num].handler = handler; + mcu_dat[id].registered_irq |= 1 << (int_num + 16); + + return 0; +} +EXPORT_SYMBOL(mbox_request_irq); + +int mcu_ipc_unregister_handler(enum mcu_ipc_region id, u32 int_num, + void (*handler)(void *)) +{ + if (!handler || (mcu_dat[id].hd[int_num].handler != handler)) + return -EINVAL; + + mcu_dat[id].hd[int_num].data = NULL; + mcu_dat[id].hd[int_num].handler = NULL; + mcu_dat[id].registered_irq &= ~(1 << (int_num + 16)); + + return 0; +} +EXPORT_SYMBOL(mcu_ipc_unregister_handler); + +void mbox_set_interrupt(enum mcu_ipc_region id, u32 int_num) +{ + /* generate interrupt */ + if (int_num < 16) + mcu_ipc_writel(id, 0x1 << int_num, EXYNOS_MCU_IPC_INTGR1); +} +EXPORT_SYMBOL(mbox_set_interrupt); + +void mcu_ipc_send_command(enum mcu_ipc_region id, u32 int_num, u16 cmd) +{ + /* write command */ + if (int_num < 16) + mcu_ipc_writel(id, cmd, EXYNOS_MCU_IPC_ISSR0 + (8 * int_num)); + + /* generate interrupt */ + mbox_set_interrupt(id, int_num); +} +EXPORT_SYMBOL(mcu_ipc_send_command); + +u32 mbox_get_value(enum mcu_ipc_region id, u32 mbx_num) +{ + if (mbx_num < 64) + return mcu_ipc_readl(id, EXYNOS_MCU_IPC_ISSR0 + (4 * mbx_num)); + else + return 0; +} +EXPORT_SYMBOL(mbox_get_value); + +void mbox_set_value(enum mcu_ipc_region id, u32 mbx_num, u32 msg) +{ + if (mbx_num < 64) + mcu_ipc_writel(id, msg, EXYNOS_MCU_IPC_ISSR0 + (4 * mbx_num)); +} +EXPORT_SYMBOL(mbox_set_value); + +u32 mbox_extract_value(enum mcu_ipc_region id, u32 mbx_num, u32 mask, u32 pos) +{ + if (mbx_num < 64) + return (mbox_get_value(id, mbx_num) >> pos) & mask; + else + return 0; +} +EXPORT_SYMBOL(mbox_extract_value); + +void mbox_update_value(enum mcu_ipc_region id, u32 mbx_num, + u32 msg, u32 mask, u32 pos) +{ + u32 val; + unsigned long flags; + + spin_lock_irqsave(&mcu_dat[id].lock, flags); + + if (mbx_num < 64) { + val = mbox_get_value(id, mbx_num); + val &= ~(mask << pos); + val |= (msg & mask) << pos; + mbox_set_value(id, mbx_num, val); + } + + spin_unlock_irqrestore(&mcu_dat[id].lock, flags); +} +EXPORT_SYMBOL(mbox_update_value); + +void mbox_sw_reset(enum mcu_ipc_region id) +{ + u32 reg_val; + + printk("Reset Mailbox registers\n"); + + reg_val = mcu_ipc_readl(id, EXYNOS_MCU_IPC_MCUCTLR); + reg_val |= (0x1 << MCU_IPC_MCUCTLR_MSWRST); + + mcu_ipc_writel(id, reg_val, EXYNOS_MCU_IPC_MCUCTLR) ; + + udelay(5); +} +EXPORT_SYMBOL(mbox_sw_reset); + +void mcu_ipc_clear_all_interrupt(enum mcu_ipc_region id) +{ + mcu_ipc_writel(id, 0xFFFF, EXYNOS_MCU_IPC_INTCR1); +} +EXPORT_SYMBOL(mcu_ipc_clear_all_interrupt); + +#ifdef CONFIG_ARGOS +static int mcu_ipc_set_affinity(enum mcu_ipc_region id, struct device *dev, int irq) +{ + struct device_node *np = dev->of_node; + u32 irq_affinity_mask = 0; + + if (!np) { + dev_err(dev, "non-DT project, can't set irq affinity\n"); + return -ENODEV; + } + + if (of_property_read_u32(np, "mcu,irq_affinity_mask", + &irq_affinity_mask)) { + dev_err(dev, "Failed to get affinity mask\n"); + return -ENODEV; + } + + dev_info(dev, "irq_affinity_mask = 0x%x\n", irq_affinity_mask); + + if (!zalloc_cpumask_var(&mcu_dat[id].dmask, GFP_KERNEL)) + return -ENOMEM; + if (!zalloc_cpumask_var(&mcu_dat[id].imask, GFP_KERNEL)) + return -ENOMEM; + + cpumask_or(mcu_dat[id].imask, mcu_dat[id].imask, cpumask_of(irq_affinity_mask)); + cpumask_copy(mcu_dat[id].dmask, get_default_cpu_mask()); + + return argos_irq_affinity_setup_label(irq, "IPC", mcu_dat[id].imask, + mcu_dat[id].dmask); +} +#else +static int mcu_ipc_set_affinity(enum mcu_ipc_region id, struct device *dev, int irq) +{ + return 0; +} +#endif + +#ifdef CONFIG_MCU_IPC_TEST +static void test_without_dev(enum mcu_ipc_region id) +{ + int i; + char *region; + + switch(id) { + case MCU_CP: + region = "CP"; + break; + case MCU_GNSS: + region = "GNSS"; + break; + default: + region = NULL; + } + + for (i = 0; i < 64; i++) { + mbox_set_value(id, i, 64 - i); + mdelay(50); + dev_err(mcu_dat[id].mcu_ipc_dev, + "Test without %s(%d): Read mbox value[%d]: %d\n", + region, id, i, mbox_get_value(i)); + } +} +#endif + +static int mcu_ipc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res = NULL; + int mcu_ipc_irq; + int err = 0; + u32 id = 0; + struct cpumask cpumaks_mcu_ipc; + int ret; + + dev_err(&pdev->dev, "%s: mcu_ipc probe start.\n", __func__); + + err = of_property_read_u32(dev->of_node, "mcu,id", &id); + if (err) { + dev_err(&pdev->dev, "MCU IPC parse error! [id]\n"); + return err; + } + + if (id >= MCU_MAX) { + dev_err(&pdev->dev, "MCU IPC Invalid ID [%d]\n", id); + return -EINVAL; + } + + mcu_dat[id].id = id; + mcu_dat[id].mcu_ipc_dev = &pdev->dev; + + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask; + if (!pdev->dev.coherent_dma_mask) + pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); + + if (dev->of_node) { + mcu_dt_read_string(dev->of_node, "mcu,name", mcu_dat[id].name); + if (IS_ERR(&mcu_dat[id])) { + dev_err(&pdev->dev, "MCU IPC parse error!\n"); + return PTR_ERR(&mcu_dat[id]); + } + } + + /* resource for mcu_ipc SFR region */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mcu_dat[id].ioaddr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mcu_dat[id].ioaddr)) { + dev_err(&pdev->dev, "failded to request memory resource\n"); + return PTR_ERR(mcu_dat[id].ioaddr); + } + + /* Request IRQ */ + mcu_ipc_irq = platform_get_irq(pdev, 0); + err = devm_request_irq(&pdev->dev, mcu_ipc_irq, mcu_ipc_handler, 0, + pdev->name, &mcu_dat[id]); + if (err) { + dev_err(&pdev->dev, "Can't request MCU_IPC IRQ\n"); + return err; + } + + /* Set CPU affinity for mcu_ipc */ + cpumask_clear(&cpumaks_mcu_ipc); + cpumask_set_cpu(MCU_IPC_AFFINITY_CORE, &cpumaks_mcu_ipc); + ret = irq_set_affinity_hint(mcu_ipc_irq, &cpumaks_mcu_ipc); + if (ret) + dev_err(dev, "irq_set_affinity_hit error: %d\n", ret); + else + dev_info(dev, "irq_set_affinity_hint - CPU core: %d\n", + MCU_IPC_AFFINITY_CORE); + + mcu_ipc_clear_all_interrupt(id); + + /* set argos irq affinity */ + err = mcu_ipc_set_affinity(id, dev, mcu_ipc_irq); + if (err) + dev_err(dev, "Can't set IRQ affinity with(%d)\n", err); + +#ifdef CONFIG_MCU_IPC_TEST + test_without_dev(id); +#endif + + spin_lock_init(&mcu_dat[id].lock); + + dev_err(&pdev->dev, "%s: mcu_ipc probe done.\n", __func__); + + return 0; +} + +static int __exit mcu_ipc_remove(struct platform_device *pdev) +{ + /* TODO */ + return 0; +} + +#ifdef CONFIG_PM +static int mcu_ipc_suspend(struct device *dev) +{ + /* TODO */ + return 0; +} + +static int mcu_ipc_resume(struct device *dev) +{ + /* TODO */ + return 0; +} +#else +#define mcu_ipc_suspend NULL +#define mcu_ipc_resume NULL +#endif + +static const struct dev_pm_ops mcu_ipc_pm_ops = { + .suspend = mcu_ipc_suspend, + .resume = mcu_ipc_resume, +}; + +static const struct of_device_id exynos_mcu_ipc_dt_match[] = { + { .compatible = "samsung,exynos7580-mailbox", }, + { .compatible = "samsung,exynos7890-mailbox", }, + { .compatible = "samsung,exynos8890-mailbox", }, + { .compatible = "samsung,exynos7870-mailbox", }, + { .compatible = "samsung,exynos-shd-ipc-mailbox", }, + {}, +}; +MODULE_DEVICE_TABLE(of, exynos_mcu_ipc_dt_match); + +static struct platform_driver mcu_ipc_driver = { + .probe = mcu_ipc_probe, + .remove = mcu_ipc_remove, + .driver = { + .name = "mcu_ipc", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(exynos_mcu_ipc_dt_match), + .pm = &mcu_ipc_pm_ops, + .suppress_bind_attrs = true, + }, +}; +module_platform_driver(mcu_ipc_driver); + +MODULE_DESCRIPTION("MCU IPC driver"); +MODULE_AUTHOR(""); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mcu_ipc/mcu_ipc.h b/drivers/misc/mcu_ipc/mcu_ipc.h new file mode 100644 index 000000000000..aed6f837fdc3 --- /dev/null +++ b/drivers/misc/mcu_ipc/mcu_ipc.h @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2014 Samsung Electronics Co.Ltd + * http://www.samsung.com + * + * MCU IPC driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. +*/ + +#ifndef MCU_IPC_H +#define MCU_IPC_H + +/* FIXME: will be removed */ +/* Shared register with 64 * 32 words */ +#define MAX_MBOX_NUM 64 + +/* Mailbox interrupt affinity core number */ +/* It should be assigned in little core */ +#define MCU_IPC_AFFINITY_CORE 3 + +enum mcu_ipc_region { + MCU_CP, + MCU_GNSS, + MCU_MAX, +}; + +struct mcu_ipc_ipc_handler { + void *data; + void (*handler)(void *); +}; + +struct mcu_ipc_drv_data { + char *name; + u32 id; + + void __iomem *ioaddr; + u32 registered_irq; + + /** + * irq affinity cpu mask + */ + cpumask_var_t dmask; /* default cpu mask */ + cpumask_var_t imask; /* irq affinity cpu mask */ + + struct device *mcu_ipc_dev; + struct mcu_ipc_ipc_handler hd[16]; + spinlock_t lock; +}; + +static struct mcu_ipc_drv_data mcu_dat[MCU_MAX]; + +static inline void mcu_ipc_writel(enum mcu_ipc_region id, u32 val, long reg) +{ + writel(val, mcu_dat[id].ioaddr + reg); +} + +static inline u32 mcu_ipc_readl(enum mcu_ipc_region id, long reg) +{ + return readl(mcu_dat[id].ioaddr + reg); +} + +#ifdef CONFIG_ARGOS +/* kernel team needs to provide argos header file. !!! + * As of now, there's nothing to use. */ +#ifdef CONFIG_SCHED_HMP +extern struct cpumask hmp_slow_cpu_mask; +extern struct cpumask hmp_fast_cpu_mask; + +static inline struct cpumask *get_default_cpu_mask(void) +{ + return &hmp_slow_cpu_mask; +} +#else +static inline struct cpumask *get_default_cpu_mask(void) +{ + return cpu_all_mask; +} +#endif + +int argos_irq_affinity_setup_label(unsigned int irq, const char *label, + struct cpumask *affinity_cpu_mask, + struct cpumask *default_cpu_mask); +int argos_task_affinity_setup_label(struct task_struct *p, const char *label, + struct cpumask *affinity_cpu_mask, + struct cpumask *default_cpu_mask); +#endif + +#define mcu_dt_read_enum(np, prop, dest) \ + do { \ + u32 val; \ + if (of_property_read_u32(np, prop, &val)) \ + return -EINVAL; \ + dest = (__typeof__(dest))(val); \ + } while (0) + +#define mcu_dt_read_bool(np, prop, dest) \ + do { \ + u32 val; \ + if (of_property_read_u32(np, prop, &val)) \ + return -EINVAL; \ + dest = val ? true : false; \ + } while (0) + +#define mcu_dt_read_string(np, prop, dest) \ + do { \ + if (of_property_read_string(np, prop, \ + (const char **)&dest)) \ + return -EINVAL; \ + } while (0) + +#define mcu_dt_read_u32(np, prop, dest) \ + do { \ + u32 val; \ + if (of_property_read_u32(np, prop, &val)) \ + return -EINVAL; \ + dest = val; \ + } while (0) +#endif diff --git a/drivers/misc/mcu_ipc/regs-mcu_ipc.h b/drivers/misc/mcu_ipc/regs-mcu_ipc.h new file mode 100644 index 000000000000..15553e1fddeb --- /dev/null +++ b/drivers/misc/mcu_ipc/regs-mcu_ipc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Register definition file for Samsung MCU_IPC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_REGS_MCU_IPC_H +#define __ASM_ARCH_REGS_MCU_IPC_H + +/***************************************************************/ +/* MCU_IPC Registers part */ +/***************************************************************/ +#define EXYNOS_MCU_IPC_MCUCTLR 0x0 +#define EXYNOS_MCU_IPC_INTGR0 0x8 +#define EXYNOS_MCU_IPC_INTCR0 0xc +#define EXYNOS_MCU_IPC_INTMR0 0x10 +#define EXYNOS_MCU_IPC_INTSR0 0x14 +#define EXYNOS_MCU_IPC_INTMSR0 0x18 +#define EXYNOS_MCU_IPC_INTGR1 0x1c +#define EXYNOS_MCU_IPC_INTCR1 0x20 +#define EXYNOS_MCU_IPC_INTMR1 0x24 +#define EXYNOS_MCU_IPC_INTSR1 0x28 +#define EXYNOS_MCU_IPC_INTMSR1 0x2c +#define EXYNOS_MCU_IPC_ISSR0 0x80 +#define EXYNOS_MCU_IPC_ISSR1 0x84 +#define EXYNOS_MCU_IPC_ISSR2 0x88 +#define EXYNOS_MCU_IPC_ISSR3 0x8c + +/***************************************************************/ +/* MCU_IPC Bit definition part */ +/***************************************************************/ +/* SYSREG Bit definition */ +#define MCU_IPC_MCUCTLR_MSWRST (0) /* MCUCTRL S/W Reset */ + +#define MCU_IPC_RX_INT0 (1 << 16) +#define MCU_IPC_RX_INT1 (1 << 17) +#define MCU_IPC_RX_INT2 (1 << 18) +#define MCU_IPC_RX_INT3 (1 << 19) +#define MCU_IPC_RX_INT4 (1 << 20) +#define MCU_IPC_RX_INT5 (1 << 21) +#define MCU_IPC_RX_INT6 (1 << 22) +#define MCU_IPC_RX_INT7 (1 << 23) +#define MCU_IPC_RX_INT8 (1 << 24) +#define MCU_IPC_RX_INT9 (1 << 25) +#define MCU_IPC_RX_INT10 (1 << 26) +#define MCU_IPC_RX_INT11 (1 << 27) +#define MCU_IPC_RX_INT12 (1 << 28) +#define MCU_IPC_RX_INT13 (1 << 29) +#define MCU_IPC_RX_INT14 (1 << 30) +#define MCU_IPC_RX_INT15 (1 << 31) + +#endif /* __ASM_ARCH_REGS_MCU_IPC_H */ diff --git a/drivers/misc/mcu_ipc/shm_ipc.c b/drivers/misc/mcu_ipc/shm_ipc.c new file mode 100644 index 000000000000..4a45c2621ae1 --- /dev/null +++ b/drivers/misc/mcu_ipc/shm_ipc.c @@ -0,0 +1,747 @@ +/* + * Copyright (C) 2014 Samsung Electronics Co.Ltd + * http://www.samsung.com + * + * Shared memory driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_CP_RAM_LOGGING +#include +#include +#include +#include + +#define MEMSHARE_DEV_NAME "memshare" +#endif + +struct shm_plat_data { + unsigned long p_addr; + unsigned p_acpm_addr; + void __iomem *v_boot; + void __iomem *v_ipc; + void __iomem *v_zmb; + void __iomem *v_vss; + void __iomem *v_acpm; + unsigned t_size; + unsigned cp_size; + unsigned vss_size; + unsigned vparam_size; + unsigned acpm_size; + unsigned ipc_off; + unsigned ipc_size; + unsigned zmb_off; + unsigned zmb_size; + + unsigned long p_sysram_addr; + unsigned t_sysram_size; + int use_cp_memory_map; + +#ifdef CONFIG_CP_RAM_LOGGING + int cplog_on; + unsigned long p_cplog_addr; + unsigned cplog_size; + void __iomem *v_cplog; + + char name[256]; + struct miscdevice mdev; + int data_ready; +#endif +} pdata; + +#ifdef CONFIG_CP_RAM_LOGGING +static int memshare_open(struct inode *inode, struct file *filep) +{ + shm_get_cplog_region(); + return 0; +} + +static int memshare_release(struct inode *inode, struct file *filep) +{ + if (pdata.v_cplog) { + vunmap(pdata.v_cplog); + pdata.v_cplog = NULL; + } + return 0; +} + +static ssize_t memshare_read(struct file *filep, char __user *buf, + size_t count, loff_t *pos) +{ + struct shm_plat_data *rd_dev = &pdata; + void *device_mem = NULL; + unsigned long data_left = 0; + unsigned long addr = 0; + int copy_size = 0; + int ret = 0; + + if ((filep->f_flags & O_NONBLOCK) && !rd_dev->data_ready) + return -EAGAIN; + + data_left = rd_dev->cplog_size - *pos; + addr = rd_dev->p_cplog_addr + *pos; + + /* EOF check */ + if (data_left == 0) { + pr_info("%s(%s): Ramdump complete. %lld bytes read.", __func__, + rd_dev->name, *pos); + ret = 0; + goto ramdump_done; + } + + copy_size = min(count, (size_t)SZ_1M); + copy_size = min((unsigned long)copy_size, data_left); + device_mem = shm_get_cplog_region() + *pos; + + if (device_mem == NULL) { + pr_err("%s(%s): Unable to ioremap: addr %lx, size %d\n", __func__, + pdata.name, addr, copy_size); + ret = -ENOMEM; + goto ramdump_done; + } + + if (copy_to_user(buf, device_mem, copy_size)) { + pr_err("%s(%s): Couldn't copy all data to user.", __func__, + rd_dev->name); + ret = -EFAULT; + goto ramdump_done; + } + + *pos += copy_size; + + pr_debug("%s(%s): Read %d bytes from address %lx.", __func__, + pdata.name, copy_size, addr); + + return copy_size; + +ramdump_done: + *pos = 0; + return ret; +} + +static const struct file_operations memshare_file_ops = { + .open = memshare_open, + .release = memshare_release, + .read = memshare_read +}; + +static int create_memshare_device(struct shm_plat_data *pdata, + const char *dev_name, struct device *parent) +{ + int ret = -1; + + if (!dev_name) { + pr_err("%s: Invalid device name\n", __func__); + goto create_memshare_device_exit; + } + + if (!pdata) { + pr_err("%s: Invalid pdata", __func__); + goto create_memshare_device_exit; + } + + pdata->data_ready = 0; + + snprintf(pdata->name, ARRAY_SIZE(pdata->name), "ramdump_%s", + dev_name); + + pdata->mdev.minor = MISC_DYNAMIC_MINOR; + pdata->mdev.name = pdata->name; + pdata->mdev.fops = &memshare_file_ops; + pdata->mdev.parent = parent; + + ret = misc_register(&pdata->mdev); + + if (ret) { + pr_err("%s: misc_register failed for %s (%d)", __func__, + pdata->name, ret); + } + else + pdata->data_ready = 1; + +create_memshare_device_exit: + return ret; +} + +static void destroy_memshare_device(void) +{ + misc_deregister(&pdata.mdev); +} +#endif + +unsigned long shm_get_phys_base(void) +{ + return pdata.p_addr; +} + +unsigned shm_get_phys_size(void) +{ + return pdata.t_size; +} + +unsigned long shm_get_sysram_base(void) +{ + return pdata.p_sysram_addr; +} + +unsigned shm_get_sysram_size(void) +{ + return pdata.t_sysram_size; +} + +unsigned shm_get_boot_size(void) +{ + return pdata.ipc_off; +} + +unsigned shm_get_ipc_rgn_offset(void) +{ + return pdata.ipc_off; +} + +unsigned shm_get_ipc_rgn_size(void) +{ + return pdata.ipc_size; +} + +unsigned shm_get_zmb_size(void) +{ + return pdata.zmb_size; +} + +unsigned shm_get_vss_base(void) +{ + return shm_get_phys_base() + shm_get_cp_size(); +} + +unsigned shm_get_vss_size(void) +{ + return pdata.vss_size; +} + +unsigned shm_get_vparam_base(void) +{ + return shm_get_phys_base() + shm_get_cp_size() + shm_get_vss_size() + + shm_get_ipc_rgn_size() +shm_get_zmb_size(); +} + +unsigned shm_get_vparam_size(void) +{ + return pdata.vparam_size; +} + +unsigned shm_get_acpm_size(void) +{ + return pdata.acpm_size; +} + +unsigned shm_get_cp_size(void) +{ + return pdata.cp_size; +} + +#ifdef CONFIG_CP_RAM_LOGGING +unsigned long shm_get_cplog_base(void) +{ + return pdata.p_cplog_addr; +} + +unsigned shm_get_cplog_size(void) +{ + return pdata.cplog_size; +} + +int shm_get_cplog_flag(void) +{ + return pdata.cplog_on; +} +#endif + +int shm_get_use_cp_memory_map_flag(void) +{ + return pdata.use_cp_memory_map; +} + +unsigned long shm_get_security_param3(unsigned long mode, u32 main_size) +{ + unsigned long ret; + + switch (mode) { + case 0: /* CP_BOOT_MODE_NORMAL */ + ret = main_size; + break; + case 1: /* CP_BOOT_MODE_DUMP */ +#ifdef CP_NONSECURE_BOOT + ret = pdata.p_addr; +#else + ret = pdata.p_addr + pdata.ipc_off; +#endif + break; + case 2: /* CP_BOOT_RE_INIT */ + ret = 0; + break; + default: + pr_info("%s: Invalid sec_mode(%lu)\n", __func__, mode); + ret = 0; + break; + } + return ret; +} + +unsigned long shm_get_security_param2(unsigned long mode, u32 bl_size) +{ + unsigned long ret; + + switch (mode) { + case 0: /* CP_BOOT_MODE_NORMAL */ + case 1: /* CP_BOOT_MODE_DUMP */ + ret = bl_size; + break; + case 2: /* CP_BOOT_RE_INIT */ + ret = 0; + break; + default: + pr_info("%s: Invalid sec_mode(%lu)\n", __func__, mode); + ret = 0; + break; + } + return ret; +} + +void __iomem *shm_request_region(unsigned long sh_addr, unsigned size) +{ + int i; + unsigned int num_pages = (size >> PAGE_SHIFT); + pgprot_t prot = pgprot_writecombine(PAGE_KERNEL); + struct page **pages; + void *v_addr; + + if (!sh_addr) + return NULL; + + if (size > (num_pages << PAGE_SHIFT)) + num_pages++; + + pages = kmalloc(sizeof(struct page *) * num_pages, GFP_ATOMIC); + if (!pages) { + pr_err("%s: pages allocation fail!\n", __func__); + return NULL; + } + + for (i = 0; i < (num_pages); i++) { + pages[i] = phys_to_page(sh_addr); + sh_addr += PAGE_SIZE; + } + + v_addr = vmap(pages, num_pages, VM_MAP, prot); + if (v_addr == NULL) + pr_err("%s: Failed to vmap pages\n", __func__); + + kfree(pages); + + return (void __iomem *)v_addr; +} + +void __iomem *shm_get_boot_region(void) +{ + if (!pdata.v_boot) + pdata.v_boot = shm_request_region(pdata.p_addr, pdata.ipc_off); + + return pdata.v_boot; +} + +void __iomem *shm_get_ipc_region(void) +{ + if (!pdata.v_ipc) + pdata.v_ipc = shm_request_region(pdata.p_addr + pdata.ipc_off, + pdata.ipc_size); + + return pdata.v_ipc; +} + +void __iomem *shm_get_zmb_region(void) +{ + if (!pdata.v_zmb) + pdata.v_zmb = (void __iomem *)phys_to_virt(pdata.p_addr + pdata.zmb_off); + + return pdata.v_zmb; +} + +void __iomem *shm_get_vss_region(void) +{ + if (!pdata.v_vss) + pdata.v_vss = shm_request_region(pdata.p_addr + pdata.cp_size, + pdata.vss_size); + + return pdata.v_vss; +} + +#define VSS_MAGIC_OFFSET 0x500000 +void clean_vss_magic_code(void) +{ + u8* vss_base; + u32 __iomem * vss_magic; + + pr_err("%s: set vss magic code as 0\n", __func__); + + vss_base = (u8*)shm_get_vss_region(); + vss_magic = (u32 __iomem *)(vss_base + VSS_MAGIC_OFFSET); + + /* set VSS magic code as 0*/ + iowrite32(0, vss_magic); +} + +void __iomem *shm_get_acpm_region(void) +{ + if (!pdata.v_acpm) + pdata.v_acpm = shm_request_region(pdata.p_acpm_addr, + pdata.acpm_size); + + return pdata.v_acpm; +} + +#ifdef CONFIG_CP_RAM_LOGGING +void __iomem *shm_get_cplog_region(void) +{ + if (!pdata.v_cplog) + pdata.v_cplog = shm_request_region(pdata.p_cplog_addr, + pdata.cplog_size); + + return pdata.v_cplog; +} +#endif + +void shm_release_region(void *v_addr) +{ + vunmap(v_addr); +} + +void shm_release_regions(void) +{ + if (pdata.v_boot) + vunmap(pdata.v_boot); + + if (pdata.v_ipc) + vunmap(pdata.v_ipc); + + if (pdata.v_vss) + vunmap(pdata.v_vss); + + if (pdata.v_acpm) + vunmap(pdata.v_acpm); + + if (pdata.v_zmb) + vunmap(pdata.v_zmb); + +#ifdef CONFIG_CP_RAM_LOGGING + if (pdata.v_cplog) + vunmap(pdata.v_cplog); +#endif +} + +#ifdef CONFIG_CP_RAM_LOGGING +static void shm_free_reserved_mem(unsigned long addr, unsigned size) +{ + int i; + struct page *page; + + pr_err("Release cplog reserved memory\n"); + for (i = 0; i < (size >> PAGE_SHIFT); i++) { + page = phys_to_page(addr); + addr += PAGE_SIZE; + free_reserved_page(page); + } +} +#endif + +#ifdef CONFIG_OF_RESERVED_MEM +static int __init modem_if_reserved_mem_setup(struct reserved_mem *remem) +{ + pdata.p_addr = remem->base; + pdata.t_size = remem->size; + + pr_err("%s: memory reserved: paddr=%lu, t_size=%u\n", + __func__, pdata.p_addr, pdata.t_size); + + return 0; +} +RESERVEDMEM_OF_DECLARE(modem_if, "exynos,modem_if", modem_if_reserved_mem_setup); + +#ifdef CONFIG_CP_RAM_LOGGING +static int __init modem_if_reserved_cplog_setup(struct reserved_mem *remem) +{ + pdata.p_cplog_addr = remem->base; + pdata.cplog_size = remem->size; + + pr_err("%s: cplog memory reserved: paddr=%lu, t_size=%u\n", + __func__, pdata.p_cplog_addr, pdata.cplog_size); + + return 0; +} +RESERVEDMEM_OF_DECLARE(cp_ram_logging, "exynos,cp_ram_logging", + modem_if_reserved_cplog_setup); +#endif + +#if !defined (CONFIG_SOC_EXYNOS7570) +static int __init deliver_cp_reserved_mem_setup(struct reserved_mem *remem) +{ + pdata.p_sysram_addr = remem->base; + pdata.t_sysram_size = remem->size; + + pr_err("%s: memory reserved: paddr=%u, t_size=%u\n", + __func__, (u32)remem->base, (u32)remem->size); + + return 0; +} +RESERVEDMEM_OF_DECLARE(deliver_cp, "exynos,deliver_cp", deliver_cp_reserved_mem_setup); +#endif +#endif + +#ifdef CONFIG_CP_RAM_LOGGING +static int __init console_setup(char *str) +{ + if (!strcmp(str, "ON") || !strcmp(str, "on")) + pdata.cplog_on = 1; + + pr_info("cplog_on=%s, %d\n", str, pdata.cplog_on); + return 0; + } +__setup("androidboot.cp_reserved_mem=", console_setup); +#endif + +#define EXTERN_BIN_MAX_COUNT 5 + +struct extern_mem_bin_info_tag { + unsigned int ext_bin_tag; // Tag + unsigned int ext_bin_addr; // Offset address + unsigned int ext_bin_size; // binary size +}; + +struct cp_reserved_map_table { + unsigned int table_id_ver; // MEMn + unsigned int dram_size; // dram size + unsigned int ext_mem_size; // extern mem size + unsigned int ext_bin_count; // extern mem size + struct extern_mem_bin_info_tag sExtBin[EXTERN_BIN_MAX_COUNT]; + unsigned int end_flag_not_used; // Memory guard for CP boot code +}; + +struct cp_reserved_map_table cp_mem_map; + +static int verify_cp_memory_map(struct cp_reserved_map_table *tab) +{ + unsigned int total_bin = tab->ext_bin_count; + int i; + int verify = 1; + + if (tab->ext_bin_count <= 0 || (tab->ext_bin_count > EXTERN_BIN_MAX_COUNT)) { + verify = 0; + goto exit; + } + + for (i = 1; i < total_bin; i++) { + if (cp_mem_map.sExtBin[i-1].ext_bin_addr + cp_mem_map.sExtBin[i-1].ext_bin_size + != cp_mem_map.sExtBin[i].ext_bin_addr) { + verify = 0; + goto exit; + } + } +exit: + return verify; +} + +static int shm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + int ret; + int verify; + unsigned int tmp; + int i; + char *ptr; + struct device_node *np_acpm = of_find_node_by_name(NULL, "acpm_ipc"); + void __iomem *cp_mem_base; + char table_id_ver[5]; + + dev_err(dev, "%s: shmem driver init\n", __func__); + + cp_mem_base = shm_request_region(pdata.p_addr, PAGE_SIZE); + dev_info(dev, "cp_mem_base: 0x%lx, 0x%p\n", pdata.p_addr, cp_mem_base); + /* 0x200: TOC, 0xa0: cp memory map offset */ + memcpy(&cp_mem_map, cp_mem_base + 0x200 + 0xa0, sizeof(struct cp_reserved_map_table)); + + if (cp_mem_base) { + vunmap(cp_mem_base); + cp_mem_base = NULL; + } + + tmp = ntohl(cp_mem_map.table_id_ver + 0x30); + if (strncmp((const char *)&tmp, "MEM", 3) == 0) { + verify = verify_cp_memory_map(&cp_mem_map); + dev_info(dev, "CP memory map verification: %s\n", verify == 1 ? "PASS!" : "FAIL!"); + if (verify) { + pdata.use_cp_memory_map = 1; + strncpy(table_id_ver, (void *)&tmp, 4); + table_id_ver[4] = '\0'; + pdata.cp_size = cp_mem_map.dram_size; + dev_info(dev, "table_id_ver: %s\n", table_id_ver); + dev_info(dev, "bin_count: %d\n", cp_mem_map.ext_bin_count); + dev_info(dev, "cp dram_size: 0x%08X\n", pdata.cp_size); + dev_info(dev, "ext_mem_size: 0x%08X\n", cp_mem_map.ext_mem_size); + for (i = 0; i < cp_mem_map.ext_bin_count; i++) { + tmp = ntohl(cp_mem_map.sExtBin[i].ext_bin_tag); + ptr = ((char *)&tmp) + 1; + + if (strncmp((const char *)ptr, "IPC", 3) == 0) { + pdata.ipc_off = cp_mem_map.sExtBin[i].ext_bin_addr; + pdata.ipc_size = cp_mem_map.sExtBin[i].ext_bin_size; + dev_err(dev, "IPC: 0x%08x: 0x%08X\n", pdata.ipc_off, pdata.ipc_size); + } else if (strncmp((const char *)ptr, "VSS", 3) == 0) { + pdata.vss_size = cp_mem_map.sExtBin[i].ext_bin_size; + dev_err(dev, "VSS: 0x%08X: 0x%08X\n", + cp_mem_map.sExtBin[i].ext_bin_addr, pdata.vss_size); + } else if (strncmp((const char *)ptr, "VPA", 3) == 0) { + pdata.vparam_size = cp_mem_map.sExtBin[i].ext_bin_size; + dev_err(dev, "VSS PARAM: 0x%08X: 0x%08X\n", + cp_mem_map.sExtBin[i].ext_bin_addr, pdata.vparam_size); + } else if (strncmp((const char *)ptr, "ZMC", 3) == 0) { + pdata.zmb_off = cp_mem_map.sExtBin[i].ext_bin_addr; + pdata.zmb_size = cp_mem_map.sExtBin[i].ext_bin_size; + dev_err(dev, "ZMC: 0x%08X: 0x%08X\n", pdata.zmb_off, pdata.zmb_size); + } else if (strncmp((const char *)ptr, "LOG", 3) == 0) { + dev_err(dev, "LOG: 0x%08X: 0x%08X\n", + cp_mem_map.sExtBin[i].ext_bin_addr, cp_mem_map.sExtBin[i].ext_bin_size); + } + } + } else { + WARN_ONCE(!verify, "cp memory map verification fail\n"); + return -EINVAL; + } + } else if (dev->of_node) { + ret = of_property_read_u32(dev->of_node, "shmem,ipc_offset", + &pdata.ipc_off); + if (ret) { + dev_err(dev, "failed to get property, ipc_offset\n"); + return -EINVAL; + } + + ret = of_property_read_u32(dev->of_node, "shmem,ipc_size", + &pdata.ipc_size); + if (ret) { + dev_err(dev, "failed to get property, ipc_size\n"); + return -EINVAL; + } + +#ifdef CONFIG_SEC_SIPC_MODEM_IF + ret = of_property_read_u32(dev->of_node, "shmem,zmb_offset", + &pdata.zmb_off); + if (ret) { + dev_err(dev, "failed to get property, zmb_offset\n"); + return -EINVAL; + } + + ret = of_property_read_u32(dev->of_node, "shmem,zmb_size", + &pdata.zmb_size); + if (ret) { + dev_err(dev, "failed to get property, zmb_size\n"); + return -EINVAL; + } +#endif + + ret = of_property_read_u32(dev->of_node, "shmem,cp_size", + &pdata.cp_size); + if (ret) + dev_err(dev, "failed to get property, cp_size\n"); + + ret = of_property_read_u32(dev->of_node, "shmem,vss_size", + &pdata.vss_size); + if (ret) + dev_err(dev, "failed to get property, vss_size\n"); + } else { + /* To do: In case of non-DT */ + } + + if (np_acpm) { + ret = of_property_read_u32(np_acpm, "dump-base", + &pdata.p_acpm_addr); + if (ret) + dev_err(dev, "failed to get property, acpm_base\n"); + + ret = of_property_read_u32(np_acpm, "dump-size", + &pdata.acpm_size); + if (ret) + dev_err(dev, "failed to get property, acpm_size\n"); + } + + dev_info(dev, "paddr=0x%lX, total_size=0x%08X, ipc_off=0x%08X, ipc_size=0x%08X, cp_size=0x%08X, vss_size=0x%08X\n", + pdata.p_addr, pdata.t_size, pdata.ipc_off, pdata.ipc_size, + pdata.cp_size, pdata.vss_size); + + dev_info(dev, "zmb_off=0x%08X, zmb_size=0x%08X\n", pdata.zmb_off, + pdata.zmb_size); + + dev_info(dev, "acpm_base=0x%08X, acpm_size=0x%08X\n", pdata.p_acpm_addr, + pdata.acpm_size); + +#ifdef CONFIG_CP_RAM_LOGGING + if (pdata.cplog_on) { + dev_err(dev, "cplog_base=0x%08lX, cplog_size=0x%08X\n", + pdata.p_cplog_addr, pdata.cplog_size); + + /* create memshare driver */ + ret = create_memshare_device(&pdata, MEMSHARE_DEV_NAME, dev); + if (ret) { + dev_err(dev, "failed to create memshare device\n"); + } + } else { + shm_free_reserved_mem(pdata.p_cplog_addr, pdata.cplog_size); + } +#endif + return 0; +} + +static int shm_remove(struct platform_device *pdev) +{ +#ifdef CONFIG_CP_RAM_LOGGING + destroy_memshare_device(); +#endif + return 0; +} + +static const struct of_device_id exynos_shm_dt_match[] = { + { .compatible = "samsung,exynos7580-shm_ipc", }, + { .compatible = "samsung,exynos8890-shm_ipc", }, + { .compatible = "samsung,exynos7870-shm_ipc", }, + { .compatible = "samsung,exynos-shm_ipc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, exynos_shm_dt_match); + +static struct platform_driver shmem_driver = { + .probe = shm_probe, + .remove = shm_remove, + .driver = { + .name = "shm_ipc", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(exynos_shm_dt_match), + .suppress_bind_attrs = true, + }, +}; +module_platform_driver(shmem_driver); + +MODULE_DESCRIPTION(""); +MODULE_AUTHOR(""); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mcu_ipc.h b/include/linux/mcu_ipc.h new file mode 100644 index 000000000000..e68d1e927ecb --- /dev/null +++ b/include/linux/mcu_ipc.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2014 Samsung Electronics Co.Ltd + * http://www.samsung.com + * + * MCU IPC driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#ifndef MCU_IPC_H +#define MCU_IPC_H + +#define MCU_IPC_INT0 (0) +#define MCU_IPC_INT1 (1) +#define MCU_IPC_INT2 (2) +#define MCU_IPC_INT3 (3) +#define MCU_IPC_INT4 (4) +#define MCU_IPC_INT5 (5) +#define MCU_IPC_INT6 (6) +#define MCU_IPC_INT7 (7) +#define MCU_IPC_INT8 (8) +#define MCU_IPC_INT9 (9) +#define MCU_IPC_INT10 (10) +#define MCU_IPC_INT11 (11) +#define MCU_IPC_INT12 (12) +#define MCU_IPC_INT13 (13) +#define MCU_IPC_INT14 (14) +#define MCU_IPC_INT15 (15) + +/* FIXME: will be removed */ +/* Shared register with 64 * 32 words */ +#define MAX_MBOX_NUM 64 + +enum mcu_ipc_region { + MCU_CP, + MCU_GNSS, + MCU_MAX, +}; + +int mbox_request_irq(enum mcu_ipc_region id, u32 int_num, + void (*handler)(void *), void *data); +int mcu_ipc_unregister_handler(enum mcu_ipc_region id, u32 int_num, + void (*handler)(void *)); +void mbox_set_interrupt(enum mcu_ipc_region id, u32 int_num); +void mcu_ipc_send_command(enum mcu_ipc_region id, u32 int_num, u16 cmd); +u32 mbox_get_value(enum mcu_ipc_region id, u32 mbx_num); +void mbox_set_value(enum mcu_ipc_region id, u32 mbx_num, u32 msg); +void mbox_update_value(enum mcu_ipc_region id, u32 mbx_num, + u32 msg, u32 mask, u32 pos); +u32 mbox_extract_value(enum mcu_ipc_region id, u32 mbx_num, u32 mask, u32 pos); +void mbox_sw_reset(enum mcu_ipc_region id); +void mcu_ipc_clear_all_interrupt(enum mcu_ipc_region id); + +#endif diff --git a/include/linux/shm_ipc.h b/include/linux/shm_ipc.h new file mode 100644 index 000000000000..ec2c354f9114 --- /dev/null +++ b/include/linux/shm_ipc.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2014 Samsung Electronics Co.Ltd + * http://www.samsung.com + * + * Shared Memory driver + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. +*/ +#ifndef SHMEM_IPC_H +#define SHMEM_IPC_H + +struct shdmem_info { + unsigned int base; + unsigned int size; +}; + +#if IS_ENABLED(CONFIG_SHM_IPC) +unsigned long shm_get_phys_base(void); +unsigned shm_get_phys_size(void); +unsigned shm_get_boot_size(void); +unsigned shm_get_ipc_rgn_offset(void); +unsigned shm_get_ipc_rgn_size(void); +unsigned shm_get_zmb_size(void); +unsigned shm_get_vss_base(void); +unsigned shm_get_vss_size(void); +unsigned shm_get_vparam_base(void); +unsigned shm_get_vparam_size(void); +unsigned shm_get_acpm_size(void); +unsigned shm_get_cp_size(void); +unsigned long shm_get_security_param2(unsigned long mode, u32 bl_size); +unsigned long shm_get_security_param3(unsigned long mode, u32 main_size); + +void __iomem *shm_request_region(unsigned long sh_addr, unsigned size); +void __iomem *shm_get_boot_region(void); +void __iomem *shm_get_ipc_region(void); +void __iomem *shm_get_zmb_region(void); +void __iomem *shm_get_vss_region(void); +void __iomem *shm_get_acpm_region(void); + +void shm_release_region(void *v_addr); +void shm_release_regions(void); +void clean_vss_magic_code(void); +int shm_get_use_cp_memory_map_flag(void); + +#ifdef CONFIG_CP_RAM_LOGGING +unsigned long shm_get_cplog_base(void); +unsigned shm_get_cplog_size(void); +int shm_get_cplog_flag(void); +void __iomem *shm_get_cplog_region(void); +#endif +#else +static inline unsigned long shm_get_phys_base(void) { return 0; } +static inline unsigned shm_get_phys_size(void) { return 0; } +static inline unsigned shm_get_boot_size(void) { return 0; } +static inline unsigned shm_get_ipc_rgn_offset(void) { return 0; } +static inline unsigned shm_get_ipc_rgn_size(void) { return 0; } +static inline unsigned shm_get_zmb_size(void) { return 0; } +static inline unsigned shm_get_vss_base(void) { return 0; } +static inline unsigned shm_get_vss_size(void) { return 0; } +static inline unsigned shm_get_vparam_base(void) { return 0; } +static inline unsigned shm_get_vparam_size(void) { return 0; } +static inline unsigned shm_get_acpm_size(void) { return 0; } +static inline unsigned shm_get_cp_size(void) { return 0; } +static inline unsigned long shm_get_security_param2(unsigned long mode, u32 bl_size) +{ + return 0; +} +static inline unsigned long shm_get_security_param3(unsigned long mode, u32 main_size) +{ + return 0; +} + +static inline void __iomem *shm_request_region(unsigned long sh_addr, unsigned size) +{ + return 0; +} +static inline void __iomem *shm_get_boot_region(void) { return NULL; } +static inline void __iomem *shm_get_ipc_region(void) { return NULL; } +static inline void __iomem *shm_get_zmb_region(void) { return NULL; } +static inline void __iomem *shm_get_vss_region(void) { return NULL; } +static inline void __iomem *shm_get_acpm_region(void) { return NULL; } + +static inline void shm_release_region(void *v_addr) {} +static inline void shm_release_regions(void) {} +static inline void clean_vss_magic_code(void) {} +static inline int shm_get_use_cp_memory_map_flag(void) { return 0; } + +#ifdef CONFIG_CP_RAM_LOGGING +static inline unsigned long shm_get_cplog_base(void) { return 0; } +static inline unsigned shm_get_cplog_size(void) { return 0; } +static inline int shm_get_cplog_flag(void) { return 0; } +static inline void __iomem *shm_get_cplog_region(void) { return NULL; } +#endif +#endif + +#endif -- 2.20.1