From 29fc9b4333fe417d0354bda6446f1e4ccf212ef2 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 21 Oct 2011 10:51:09 +0200 Subject: staging: Add STE mmio driver Add STE camera IO driver code in staging Signed-off-by: Robert Marklund --- drivers/staging/mmio/Kconfig | 7 + drivers/staging/mmio/Makefile | 1 + drivers/staging/mmio/mmio.h | 175 +++++++ drivers/staging/mmio/st_mmio.c | 1128 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1311 insertions(+) create mode 100644 drivers/staging/mmio/Kconfig create mode 100644 drivers/staging/mmio/Makefile create mode 100644 drivers/staging/mmio/mmio.h create mode 100644 drivers/staging/mmio/st_mmio.c diff --git a/drivers/staging/mmio/Kconfig b/drivers/staging/mmio/Kconfig new file mode 100644 index 00000000000..eb4a93e2545 --- /dev/null +++ b/drivers/staging/mmio/Kconfig @@ -0,0 +1,7 @@ + +config U8500_MMIO + bool "ST-Ericsson MMIO (Camera) Driver" + depends on ARCH_U8500 + help + Enables the ST-Ericsson MMIO (Camera) Driver + diff --git a/drivers/staging/mmio/Makefile b/drivers/staging/mmio/Makefile new file mode 100644 index 00000000000..bec2a6efe63 --- /dev/null +++ b/drivers/staging/mmio/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_U8500_MMIO) := st_mmio.o diff --git a/drivers/staging/mmio/mmio.h b/drivers/staging/mmio/mmio.h new file mode 100644 index 00000000000..9dee32055ef --- /dev/null +++ b/drivers/staging/mmio/mmio.h @@ -0,0 +1,175 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * + * Author: Joakim Axelsson for ST-Ericsson + * Author: Rajat Verma for ST-Ericsson + * License Terms: GNU General Public License v2 + */ + +#ifndef MMIO_H +#define MMIO_H + +#include + +#define MMIO_NAME "mmio_camera" + +#ifdef SRA_SUPPORT +#define SREG_16_BIT (0x1) +#define SREG_32_BIT (0x2) +#endif +/* Kernel side interface for MMIO */ +/* Which camera is currently active */ +enum camera_slot_t { + PRIMARY_CAMERA = 0, + SECONDARY_CAMERA, + CAMERA_SLOT_END +}; +struct mmio_gpio { + int gpio; /* Set to zero if not in use */ + int active_high;/* Set if pin is active high */ + int udelay; /* Time to wait when activating the pin, in usec */ +}; +enum mmio_select_i2c_t { + MMIO_ACTIVATE_IPI2C2 = 0, + MMIO_ACTIVATE_I2C_HOST, + MMIO_DEACTIVATE_I2C +}; + +enum mmio_select_xshutdown_t { + MMIO_ENABLE_XSHUTDOWN_FW = 0, + MMIO_ENABLE_XSHUTDOWN_HOST, + MMIO_DISABLE_XSHUTDOWN +}; +struct mmio_platform_data { + struct device *dev; + enum camera_slot_t camera_slot; /* Which camera is currently used, + * Primary/Secondary */ + void *extra; /* Board's private data structure + * placeholder */ + int reset_ipgpio[CAMERA_SLOT_END]; /* Contains logical IP GPIO for + * reset pin */ + int sia_base; + int cr_base; + int (*platform_init)(struct mmio_platform_data *pdata); + void (*platform_exit)(struct mmio_platform_data *pdata); + int (*power_enable)(struct mmio_platform_data *pdata); + void (*power_disable)(struct mmio_platform_data *pdata); + int (*config_xshutdown_pins)(struct mmio_platform_data *pdata, + enum mmio_select_xshutdown_t select, int is_active_high); + int (*config_i2c_pins)(struct mmio_platform_data *pdata, + enum mmio_select_i2c_t select); + int (*clock_enable)(struct mmio_platform_data *pdata); + void (*clock_disable)(struct mmio_platform_data *pdata); + void (*set_xshutdown)(struct mmio_platform_data *pdata); +}; + +#define USER_SIDE_INTERFACE 1 +/* User side is only allowed to access code in USER_SIDE_INTERFACE block */ +#ifdef USER_SIDE_INTERFACE +enum mmio_bool_t { + MMIO_FALSE = 0, + MMIO_TRUE = !MMIO_FALSE, + MMIO_BOOL_MAX = 0x7FFFFFFF +}; + +struct xshutdown_info_t { + int ip_gpio; + int camera_function; +}; + +struct xp70_fw_t { + void __iomem *addr_sdram_ext; + void __iomem *addr_esram_ext; + void __iomem *addr_split; + void __iomem *addr_data; + unsigned int size_sdram_ext; + unsigned int size_esram_ext; + unsigned int size_split; + unsigned int size_data; +}; + +struct isp_write_t { + unsigned long t1_dest; + unsigned long *data; + unsigned long count; +}; + +struct trace_buf_t { + void *address; + unsigned int size; +}; + +#ifdef SRA_SUPPORT +struct s_reg { + unsigned int addr; + unsigned int value; + unsigned int mask; +}; + +struct s_reg_list { + unsigned int access_mode; + unsigned int entries; + struct s_reg *s_regs_p; +}; +#endif +struct mmio_input_output_t { + union { + enum mmio_bool_t power_on; + struct xp70_fw_t xp70_fw; + struct isp_write_t isp_write; + unsigned int addr_to_map; + struct xshutdown_info_t xshutdown_info; + enum camera_slot_t camera_slot; + struct trace_buf_t trace_buf; +#ifdef SRA_SUPPORT + struct s_reg_list s_reg_list; +#endif + } mmio_arg; +}; + +#define MMIO_TRUE (1) +#define MMIO_FALSE (0) +#define MMIO_INVALID (~0) + +/*Xshutdown from host takes two arguments*/ +#define MMIO_XSHUTDOWN_ENABLE (0x1) +#define MMIO_XSHUTDOWN_ACTIVE_HIGH (0x2) + +#define MMIO_MAGIC_NUMBER 0x15 + +#define MMIO_CAM_INITBOARD _IOW(MMIO_MAGIC_NUMBER, 1,\ +struct mmio_input_output_t*) +#define MMIO_CAM_PWR_SENSOR _IOW(MMIO_MAGIC_NUMBER, 2,\ +struct mmio_input_output_t*) +#define MMIO_CAM_SET_EXT_CLK _IOW(MMIO_MAGIC_NUMBER, 3,\ +struct mmio_input_output_t*) +#define MMIO_CAM_SET_PRI_HWIF _IO(MMIO_MAGIC_NUMBER, 4) +#define MMIO_CAM_SET_SEC_HWIF _IO(MMIO_MAGIC_NUMBER, 5) +#define MMIO_CAM_INITMMDSPTIMER _IO(MMIO_MAGIC_NUMBER, 6) +#define MMIO_CAM_LOAD_XP70_FW _IOW(MMIO_MAGIC_NUMBER, 7,\ +struct mmio_input_output_t*) +#define MMIO_CAM_MAP_STATS_AREA _IOWR(MMIO_MAGIC_NUMBER, 8,\ +struct mmio_input_output_t*) +#define MMIO_ACTIVATE_I2C2 _IOW(MMIO_MAGIC_NUMBER, 9, int*) +#define MMIO_ENABLE_XSHUTDOWN_FROM_HOST _IOW(MMIO_MAGIC_NUMBER, 10, int*) +#define MMIO_CAM_ISP_WRITE _IOW(MMIO_MAGIC_NUMBER, 11,\ +struct mmio_input_output_t*) +#define MMIO_CAM_GET_IP_GPIO _IOWR(MMIO_MAGIC_NUMBER, 12,\ +struct mmio_input_output_t*) +#define MMIO_CAM_DESINITBOARD _IO(MMIO_MAGIC_NUMBER, 13) +#define MMIO_CAM_SET_TRACE_BUFFER _IOW(MMIO_MAGIC_NUMBER, 14,\ +struct mmio_input_output_t*) + +#ifdef SRA_SUPPORT +#define MMIO_CAM_READ_REGS _IOWR(MMIO_MAGIC_NUMBER, 15,\ +struct mmio_input_output_t*) +#define MMIO_CAM_MODIFY_REGS _IOWR(MMIO_MAGIC_NUMBER, 16,\ +struct mmio_input_output_t*) +#define MMIO_CAM_WRITE_REGS _IOWR(MMIO_MAGIC_NUMBER, 17,\ +struct mmio_input_output_t*) +#endif + +#endif /* USER_SIDE_INTERFACE */ + +#endif +/* MMIO_H */ diff --git a/drivers/staging/mmio/st_mmio.c b/drivers/staging/mmio/st_mmio.c new file mode 100644 index 00000000000..1dc82a9671b --- /dev/null +++ b/drivers/staging/mmio/st_mmio.c @@ -0,0 +1,1128 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Pankaj Chauhan for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ +#include +#include /* Initiliasation support */ +#include /* Module support */ +#include /* Kernel support */ +#include /* Kernel version */ +#include /* File operations (fops) defines */ +#include /* Defines standard err codes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ISP_REGION_IO (0xE0000000) +#define SIA_ISP_REG_ADDR (0x521E4) +#define SIA_BASE_ADDR (0x54000) +#define SIA_ISP_MEM (0x56000) +#define SIA_TIMER_ITC (0x5BC00) +#define SIA_ISP_MCU_SYS_SIZE (0x100000) +#define SIA_ISP_MEM_PAGE_REG (0x54070) +#define SIA_ISP_MCU_SYS_ADDR0_OFFSET (SIA_BASE_ADDR + 0x40) +#define SIA_ISP_MCU_SYS_SIZE0_OFFSET (SIA_BASE_ADDR + 0x42) +#define SIA_ISP_MCU_SYS_ADDR1_OFFSET (SIA_ISP_MCU_SYS_ADDR0_OFFSET + 0x04) +#define SIA_ISP_MCU_SYS_SIZE1_OFFSET (SIA_ISP_MCU_SYS_SIZE0_OFFSET + 0x04) +#define SIA_ISP_MCU_IO_ADDR0_HI (SIA_BASE_ADDR + 0x60) + +/* HTimer enable in CR register */ +#define CR_REG0_HTIMEN (1 << 26) +#define PICTOR_IN_XP70_L2_MEM_BASE_ADDR (0x40000) +#define PICTOR_IN_XP70_TCDM_MEM_BASE_ADDR (0x60000) +#define L2_PSRAM_MEM_SIZE (0x10000) + +#define FW_TO_HOST_ADDR_MASK (0x00001FFF) +#define FW_TO_HOST_ADDR_SHIFT (0xD) +#define FW_TO_HOST_CLR_MASK (0x3F) +#define PHY_TO_ISP_MCU_IO_ADDR0_HI(x) (((x) >> 24) << 8) +#define XP70_ADDR_MASK (0x00FFFFFF) + +#define CLOCK_ENABLE_DELAY (0x2) + +#define MAX_PRCMU_QOS_APP (0x64) + +#define ISP_WRITE_DATA_SIZE (0x4) + +#define clrbits32(_addr, _clear) \ + writel(readl(_addr) & ~(u32)(_clear), _addr) +#define setbits32(_addr, _set) \ + writel(readl(_addr) | (u32)(_set), _addr) + +#define XP70_BLOCK_SIZE 124 +#define XP70_NB_BLOCK 50 +/* + * For 30 fps video, there is 33 msec delay between every two frames + * MMIO driver reads traces from trace buffer every XP70_TIMEOUT_MSEC. + * If traces are not read in time from trace buffer, camera firmware + * will start overwiting the traces as size of trace buffer is limited. + */ +#define XP70_TIMEOUT_MSEC 30 +#define XP70_DEFAULT_MSG_ID (0xCDCDCDCD) +#define XP70_MAX_BLOCK_ID (0xFFFFFFFF) + +#define upper_16_bits(n) ((u16)((u32)(n) >> 16)) + +struct trace_block { + u32 msg_id; + char data[XP70_BLOCK_SIZE]; +}; + +struct mmio_trace { + u32 nb_block; + u32 block_size; + u32 block_id; + u32 overwrite_count; + struct trace_block block[XP70_NB_BLOCK]; +}; + +struct trace_buffer_status { + u32 prev_overwrite_count; + u32 prev_block_id; +}; + +struct mmio_info { + struct mmio_platform_data *pdata; /* Config from board */ + struct device *dev; /* My device */ + /* Runtime variables */ + struct miscdevice misc_dev; + void __iomem *siabase; + void __iomem *crbase; + /* States */ + int xshutdown_enabled; + int xshutdown_is_active_high; + /* tracing */ + struct trace_buffer_status trace_status; + struct mmio_trace *trace_buffer; + struct delayed_work trace_work; + int trace_allowed; +}; + +/* + * The one and only private data holder. Default inited to NULL. + * Declare it here so no code above can use it directly. + */ +static struct mmio_info *info; + +static int mmio_cam_pwr_sensor(struct mmio_info *info, int on) +{ + int err = 0; + + if (on) { + err = info->pdata->power_enable(info->pdata); + + if (err) + dev_err(info->dev, + "power_enable failed. err = %d\n", err); + + /* + * When switching from secondary YUV camera + * to primary Raw Bayer Camera, a hang is observed without the + * below delay. I2C access failure are observed while + * communicating with primary camera sensor indicating camera + * sensor was not powered up correctly. + */ + mdelay(CLOCK_ENABLE_DELAY); + } else { + info->pdata->power_disable(info->pdata); + } + + return err; +} + +static int mmio_cam_control_clocks(struct mmio_info *info, + enum mmio_bool_t power_on) +{ + int err = 0; + + if (power_on) { + err = info->pdata->clock_enable(info->pdata); + + if (err) + dev_err(info->dev, + "clock_enable failed, err = %d\n", + err); + } else { + info->pdata->clock_disable(info->pdata); + } + + return err; +} + +static int mmio_cam_set_pri_hwif(struct mmio_info *info) +{ + if (info->xshutdown_enabled) + info->pdata->set_xshutdown(info->pdata); + + return 0; +} + +static int mmio_cam_set_sec_hwif(struct mmio_info *info) +{ + if (info->xshutdown_enabled) + info->pdata->set_xshutdown(info->pdata); + + return 0; +} + +static int mmio_cam_init_mmdsp_timer(struct mmio_info *info) +{ + /* Disabling Accelerators timers */ + clrbits32(info->crbase, CR_REG0_HTIMEN); + /* Write MMDSPTimer */ + writel(0, info->siabase + SIA_TIMER_ITC); + /* Enabling Accelerators timers */ + setbits32(info->crbase, CR_REG0_HTIMEN); + return 0; +} + +static u32 t1_to_arm(u32 t1_addr, void __iomem *smia_base_address, + u16 *p_mem_page) +{ + u16 mem_page_update = 0; + mem_page_update = (t1_addr >> FW_TO_HOST_ADDR_SHIFT) & + FW_TO_HOST_CLR_MASK; + + if (mem_page_update != *p_mem_page) { + /* Update sia_mem_page register */ + dev_dbg(info->dev, "mem_page_update=0x%x, mem_page=0x%x\n", + mem_page_update, *p_mem_page); + writew(mem_page_update, smia_base_address + + SIA_ISP_MEM_PAGE_REG); + *p_mem_page = mem_page_update; + } + + return SIA_ISP_MEM + (t1_addr & FW_TO_HOST_ADDR_MASK); +} + +static int copy_user_buffer(void __iomem **dest_buf, + void __iomem *src_buf, u32 size) +{ + int err = 0; + + if (!src_buf) + return -EINVAL; + + *dest_buf = kmalloc(size, GFP_KERNEL); + + if (!dest_buf) { + err = -ENOMEM; + goto nomem; + } + + if (copy_from_user(*dest_buf, src_buf, size)) { + err = -EFAULT; + goto cp_failed; + } + + return err; +cp_failed: + kfree(*dest_buf); +nomem: + return err; +} +static int mmio_load_xp70_fw(struct mmio_info *info, + struct xp70_fw_t *xp70_fw) +{ + u32 i = 0; + u32 offset = 0; + u32 itval = 0; + u16 mem_page = 0; + void __iomem *addr_split = NULL; + void __iomem *addr_data = NULL; + int err = 0; + + if (xp70_fw->size_split != 0) { + err = copy_user_buffer(&addr_split, xp70_fw->addr_split, + xp70_fw->size_split); + + if (err) + goto err_exit; + + writel(0x0, info->siabase + SIA_ISP_REG_ADDR); + + /* Put the low 64k IRP firmware in ISP MCU L2 PSRAM */ + for (i = PICTOR_IN_XP70_L2_MEM_BASE_ADDR; + i < (PICTOR_IN_XP70_L2_MEM_BASE_ADDR + + L2_PSRAM_MEM_SIZE); i = i + 2) { + itval = t1_to_arm(i, info->siabase, &mem_page); + itval = ((u32) info->siabase) + itval; + /* Copy fw in L2 */ + writew((*((u16 *) addr_split + offset++)), itval); + } + + kfree(addr_split); + } + + if (xp70_fw->size_data != 0) { + mem_page = 0; + offset = 0; + err = copy_user_buffer(&addr_data, xp70_fw->addr_data, + xp70_fw->size_data); + + if (err) + goto err_exit; + + writel(0x0, info->siabase + SIA_ISP_REG_ADDR); + + for (i = PICTOR_IN_XP70_TCDM_MEM_BASE_ADDR; + i < (PICTOR_IN_XP70_TCDM_MEM_BASE_ADDR + + (xp70_fw->size_data)); i = i + 2) { + itval = t1_to_arm(i, info->siabase, &mem_page); + itval = ((u32) info->siabase) + itval; + /* Copy fw data in TCDM */ + writew((*((u16 *) addr_data + offset++)), itval); + } + + kfree(addr_data); + } + + if (xp70_fw->size_esram_ext != 0) { + /* + * ISP_MCU_SYS_ADDRx XP70 register (@ of ESRAM where the + * external code has been loaded + */ + writew(upper_16_bits(xp70_fw->addr_esram_ext), + info->siabase + SIA_ISP_MCU_SYS_ADDR0_OFFSET); + /* ISP_MCU_SYS_SIZEx XP70 register (size of the code =64KB) */ + writew(0x0, info->siabase + SIA_ISP_MCU_SYS_SIZE0_OFFSET); + } + + if (xp70_fw->size_sdram_ext != 0) { + /* + * ISP_MCU_SYS_ADDRx XP70 register (@ of SDRAM where the + * external code has been loaded + */ + writew(upper_16_bits(xp70_fw->addr_sdram_ext), + info->siabase + SIA_ISP_MCU_SYS_ADDR1_OFFSET); + /* ISP_MCU_SYS_SIZEx XP70 register (size of the code =64KB) */ + writew(0x0, info->siabase + SIA_ISP_MCU_SYS_SIZE1_OFFSET); + } + + return 0; +err_exit: + dev_err(info->dev, "Loading XP70 fw failed\n"); + return -EFAULT; +} + +static int mmio_map_statistics_mem_area(struct mmio_info *info, + void __iomem *addr_to_map) +{ + u16 value; + BUG_ON(addr_to_map == NULL); + /* 16 Mbyte aligned page */ + value = PHY_TO_ISP_MCU_IO_ADDR0_HI(*((u32 *)addr_to_map)); + writew(value, info->siabase + SIA_ISP_MCU_IO_ADDR0_HI); + /* Return the address in the XP70 address space */ + *((u32 *)addr_to_map) = (*((u32 *)addr_to_map) & XP70_ADDR_MASK) | + ISP_REGION_IO; + return 0; +} + +static int mmio_activate_i2c2(struct mmio_info *info, unsigned long enable) +{ + int err = 0; + + switch (enable) { + case MMIO_ACTIVATE_I2C_HOST: + /* Select I2C-2 */ + err = info->pdata->config_i2c_pins(info->pdata, + MMIO_ACTIVATE_I2C_HOST); + + if (err) { + dev_err(info->dev, "Failed to Enable I2C-2, err %d\n", + err); + goto out; + } + + break; + case MMIO_ACTIVATE_IPI2C2: + /* Select IPI2C */ + err = info->pdata->config_i2c_pins(info->pdata, + MMIO_ACTIVATE_IPI2C2); + + if (err) { + dev_err(info->dev, "Failed to Enable IPI2C, err %d\n", + err); + goto out; + } + + break; + case MMIO_DEACTIVATE_I2C: { + info->pdata->config_i2c_pins(info->pdata, MMIO_DEACTIVATE_I2C); + } + break; + default: + dev_warn(info->dev, "Invalid I2C2 config\n"); + err = -EINVAL; + break; + } + +out: + return err; +} + +static int mmio_enable_xshutdown_from_host(struct mmio_info *info, + unsigned long enable) +{ + int err = 0; + info->xshutdown_is_active_high = enable & MMIO_XSHUTDOWN_ACTIVE_HIGH; + + if (enable & MMIO_XSHUTDOWN_ENABLE) { + err = info->pdata->config_xshutdown_pins(info->pdata, + MMIO_ENABLE_XSHUTDOWN_HOST, enable & + MMIO_XSHUTDOWN_ACTIVE_HIGH); + } else { + info->pdata->config_xshutdown_pins(info->pdata, + MMIO_ENABLE_XSHUTDOWN_FW, -1); + /* + * XShutdown is controlled by firmware, initial output value is + * provided by firmware + */ + } + + info->xshutdown_enabled = enable & MMIO_XSHUTDOWN_ENABLE; + return 0; +} + +static int mmio_cam_initboard(struct mmio_info *info) +{ + int err = 0; + err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, MMIO_NAME, + MAX_PRCMU_QOS_APP); + + if (err) { + dev_err(info->dev, "Error adding PRCMU QoS requirement %d\n", + err); + goto out; + } + + /* Configure xshutdown to be disabled by default */ + err = mmio_enable_xshutdown_from_host(info, 0); + + if (err) + goto out; + + /* Enable IPI2C */ + err = mmio_activate_i2c2(info, MMIO_ACTIVATE_IPI2C2); +out: + return err; +} + +static int mmio_cam_desinitboard(struct mmio_info *info) +{ + prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, MMIO_NAME); + return 0; +} + +static int mmio_isp_write(struct mmio_info *info, + struct isp_write_t *isp_write_p) +{ + int err = 0, i; + void __iomem *data = NULL; + void __iomem *addr = NULL; + u16 mem_page = 0; + + if (!isp_write_p->count) { + dev_warn(info->dev, "no data to write to isp\n"); + return -EINVAL; + } + + err = copy_user_buffer(&data, isp_write_p->data, + isp_write_p->count * ISP_WRITE_DATA_SIZE); + + if (err) + goto out; + + for (i = 0; i < isp_write_p->count; i++) { + addr = (void *)(info->siabase + t1_to_arm(isp_write_p->t1_dest + + ISP_WRITE_DATA_SIZE * i, + info->siabase, &mem_page)); + *((u32 *)addr) = *((u32 *)data + i); + } + + kfree(data); +out: + return err; +} + +static int mmio_set_trace_buffer(struct mmio_info *info, + struct trace_buf_t *buf) +{ + u32 i; + int ret = 0; + + if (info->trace_allowed != 1) { + dev_warn(info->dev, "trace disabled in kernel\n"); + ret = -EPERM; + goto out; + } + + if (!buf->size || !buf->address + || buf->size < sizeof(struct mmio_trace)) { + dev_err(info->dev, "invalid xp70 trace buffer\n"); + ret = -EINVAL; + goto out; + } + + if (info->trace_buffer) { + dev_info(info->dev, "unmap old buffer"); + iounmap(info->trace_buffer); + info->trace_buffer = NULL; + } + + info->trace_buffer = ioremap((u32)buf->address, buf->size); + + if (!info->trace_buffer) { + dev_err(info->dev, "failed to map trace buffer\n"); + ret = -ENOMEM; + goto out; + } + + dev_info(info->dev, "xp70 overwrite_cnt=%d (0x%x) blk_id=%d (0x%x)", + info->trace_buffer->overwrite_count, + info->trace_buffer->overwrite_count, + info->trace_buffer->block_id, info->trace_buffer->block_id); +#ifndef CAM_SHARED_MEM_DEBUG + + /* Reset the allocated buffer contents */ + for (i = 0; i < XP70_NB_BLOCK; i++) + info->trace_buffer->block[i].msg_id = XP70_DEFAULT_MSG_ID; + +#endif /* CAM_SHARED_MEMORY_DEBUG */ + dev_info(info->dev, "xp70 overwrite_cnt=%d (0x%x) blk_id=%d (0x%x)\n", + info->trace_buffer->overwrite_count, + info->trace_buffer->overwrite_count, + info->trace_buffer->block_id, info->trace_buffer->block_id); + info->trace_status.prev_overwrite_count = 0; + info->trace_status.prev_block_id = 0; + + /* schedule work */ + if (!schedule_delayed_work(&info->trace_work, + msecs_to_jiffies(XP70_TIMEOUT_MSEC))) + dev_err(info->dev, "failed to schedule work\n"); + +out: + return ret; +} + +static int mmio_ioctl(struct inode *node, struct file *filp, u32 cmd, + unsigned long arg) +{ + struct mmio_input_output_t data; + int no_of_bytes; + int enable; + int ret = 0; + struct mmio_info *info = (struct mmio_info *)filp->private_data; + BUG_ON(info == NULL); + + switch (cmd) { + case MMIO_CAM_INITBOARD: + no_of_bytes = sizeof(struct mmio_input_output_t); + memset(&data, 0, sizeof(struct mmio_input_output_t)); + + if (copy_from_user(&data, (struct mmio_input_output_t *)arg, + no_of_bytes)) { + dev_err(info->dev, + "Copy from userspace failed\n"); + ret = -EFAULT; + break; + } + + info->pdata->camera_slot = data.mmio_arg.camera_slot; + ret = mmio_cam_initboard(info); + break; + case MMIO_CAM_DESINITBOARD: + ret = mmio_cam_desinitboard(info); + break; + case MMIO_CAM_PWR_SENSOR: + no_of_bytes = sizeof(struct mmio_input_output_t); + memset(&data, 0, sizeof(struct mmio_input_output_t)); + + if (copy_from_user + (&data, (struct mmio_input_output_t *)arg, + no_of_bytes)) { + dev_err(info->dev, + "Copy from userspace failed\n"); + ret = -EFAULT; + break; + } + + ret = mmio_cam_pwr_sensor(info, data.mmio_arg.power_on); + break; + case MMIO_CAM_SET_EXT_CLK: + no_of_bytes = sizeof(struct mmio_input_output_t); + memset(&data, 0, sizeof(struct mmio_input_output_t)); + + if (copy_from_user + (&data, (struct mmio_input_output_t *)arg, + no_of_bytes)) { + dev_err(info->dev, + "Copy from userspace failed\n"); + ret = -EFAULT; + break; + } + + ret = mmio_cam_control_clocks(info, data.mmio_arg.power_on); + break; + case MMIO_CAM_LOAD_XP70_FW: + no_of_bytes = sizeof(struct mmio_input_output_t); + memset(&data, 0, sizeof(struct mmio_input_output_t)); + + if (copy_from_user + (&data, (struct mmio_input_output_t *)arg, + no_of_bytes)) { + dev_err(info->dev, + "Copy from userspace failed\n"); + ret = -EFAULT; + break; + } + + ret = mmio_load_xp70_fw(info, &data.mmio_arg.xp70_fw); + break; + case MMIO_CAM_MAP_STATS_AREA: + no_of_bytes = sizeof(struct mmio_input_output_t); + memset(&data, 0, sizeof(struct mmio_input_output_t)); + + if (copy_from_user + (&data, (struct mmio_input_output_t *)arg, + no_of_bytes)) { + dev_err(info->dev, + "Copy from userspace failed\n"); + ret = -EFAULT; + break; + } + + ret = mmio_map_statistics_mem_area(info, + &data.mmio_arg.addr_to_map); + + if (0 != ret) { + dev_err(info->dev, + "Unable to map Statistics Mem area\n"); + break; + } + + if (copy_to_user((struct mmio_input_output_t *)arg, + &data, sizeof(no_of_bytes))) { + dev_err(info->dev, + "Copy to userspace failed\n"); + ret = -EFAULT; + break; + } + + break; + case MMIO_CAM_SET_PRI_HWIF: + ret = mmio_cam_set_pri_hwif(info); + break; + case MMIO_CAM_SET_SEC_HWIF: + ret = mmio_cam_set_sec_hwif(info); + break; + case MMIO_CAM_INITMMDSPTIMER: + ret = mmio_cam_init_mmdsp_timer(info); + break; + case MMIO_CAM_ISP_WRITE: + no_of_bytes = sizeof(struct mmio_input_output_t); + memset(&data, 0, sizeof(struct mmio_input_output_t)); + + if (copy_from_user + (&data, (struct mmio_input_output_t *)arg, + no_of_bytes)) { + dev_err(info->dev, + "Copy from userspace failed\n"); + ret = -EFAULT; + break; + } + + ret = mmio_isp_write(info, &data.mmio_arg.isp_write); + break; + case MMIO_ACTIVATE_I2C2: + no_of_bytes = sizeof(struct mmio_input_output_t); + memset(&data, 0, sizeof(struct mmio_input_output_t)); + + if (copy_from_user + (&enable, (int *)arg, sizeof(enable))) { + dev_err(info->dev, + "Copy from userspace failed\n"); + ret = -EFAULT; + break; + } + + ret = mmio_activate_i2c2(info, enable); + break; + case MMIO_ENABLE_XSHUTDOWN_FROM_HOST: + no_of_bytes = sizeof(struct mmio_input_output_t); + memset(&data, 0, sizeof(struct mmio_input_output_t)); + + if (copy_from_user + (&enable, (int *)arg, sizeof(enable))) { + dev_err(info->dev, + "Copy from userspace failed\n"); + ret = -EFAULT; + break; + } + + ret = mmio_enable_xshutdown_from_host(info, enable); + break; + case MMIO_CAM_GET_IP_GPIO: + no_of_bytes = sizeof(struct mmio_input_output_t); + memset(&data, 0, sizeof(struct mmio_input_output_t)); + + if (copy_from_user + (&data, (struct mmio_input_output_t *)arg, + no_of_bytes)) { + dev_err(info->dev, + "Copy from userspace failed\n"); + ret = -EFAULT; + break; + } + + data.mmio_arg.xshutdown_info.ip_gpio = + info->pdata->reset_ipgpio + [data.mmio_arg.xshutdown_info.camera_function]; + + if (copy_to_user((struct mmio_input_output_t *)arg, + &data, sizeof(no_of_bytes))) { + dev_err(info->dev, + "Copy to userspace failed\n"); + ret = -EFAULT; + break; + } + + break; + case MMIO_CAM_SET_TRACE_BUFFER: + no_of_bytes = sizeof(struct mmio_input_output_t); + memset(&data, 0, sizeof(struct mmio_input_output_t)); + + if (copy_from_user + (&data, (struct mmio_input_output_t *) arg, + no_of_bytes)) { + dev_err(info->dev, + "Copy from userspace failed\n"); + ret = -EFAULT; + break; + } + + ret = mmio_set_trace_buffer(info, &data.mmio_arg.trace_buf); + break; + default: + dev_err(info->dev, "Not an ioctl for this module\n"); + ret = -EINVAL; + break; + } + + return ret; +} + +static int mmio_release(struct inode *node, struct file *filp) +{ + struct mmio_info *info = filp->private_data; + BUG_ON(info == NULL); + mmio_activate_i2c2(info, MMIO_DEACTIVATE_I2C); + info->pdata->config_xshutdown_pins(info->pdata, MMIO_DISABLE_XSHUTDOWN, + -1); + + if (info->trace_buffer) { + iounmap(info->trace_buffer); + info->trace_buffer = NULL; + } + + flush_delayed_work(&info->trace_work); + return 0; +} + +static int mmio_open(struct inode *node, struct file *filp) +{ + filp->private_data = info; /* Hook our mmio info */ + return 0; +} + +static const struct file_operations mmio_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = mmio_ioctl, + .open = mmio_open, + .release = mmio_release, +}; + + +static ssize_t xp70_data_show(struct device *device, + struct device_attribute *attr, char *buf) +{ + int i; + int len; + int size = 0; + int count = 0; + int first_index; + first_index = info->trace_status.prev_block_id + 1; + + if (!info->trace_buffer || info->trace_buffer->block_id == + XP70_MAX_BLOCK_ID) + goto out_unlock; + + if (info->trace_allowed != 1) { + dev_warn(info->dev, "xp70 trace disabled in kernel\n"); + size = sprintf(buf, "xp70 trace disabled in kernel, " + "use sysfs to enable\n"); + goto out_unlock; + } + + count = info->trace_buffer->block_id - info->trace_status.prev_block_id; + + if ((info->trace_buffer->overwrite_count - + info->trace_status.prev_overwrite_count) * XP70_NB_BLOCK + + (info->trace_buffer->block_id - + info->trace_status.prev_block_id) + >= XP70_NB_BLOCK) { + /* overflow case */ + info->trace_status.prev_block_id = + info->trace_buffer->block_id - XP70_NB_BLOCK; + first_index = info->trace_buffer->block_id + 1; + count = XP70_NB_BLOCK; + len = sprintf(buf, "XP70 trace overflow\n"); + size += len; + buf += len; + } + + for (i = first_index; count; count--) { + int msg_len; + + if (i < 0 || i >= XP70_NB_BLOCK || count > XP70_NB_BLOCK) { + dev_err(info->dev, "trace index out-of-bounds\n"); + goto out_unlock; + } + + msg_len = strnlen(info->trace_buffer->block[i].data, + XP70_BLOCK_SIZE); + + if (msg_len > 0) { + /* zero terminate full length message */ + if (msg_len == XP70_BLOCK_SIZE) + info->trace_buffer->block[i].data[ + XP70_BLOCK_SIZE - 1] = '\0'; + + len = snprintf(buf, PAGE_SIZE - size, "%d %s\n", + info->trace_buffer->block[i].msg_id, + info->trace_buffer->block[i].data); + + if (len > PAGE_SIZE - size) { + dev_err(info->dev, "sysfs buffer overflow\n"); + size = PAGE_SIZE; + goto out_unlock; + } + + size += len; + buf += len; + } + + i = (i + 1) % XP70_NB_BLOCK; + } + +out_unlock: + return size; +} + +static ssize_t xp70_trace_allowed_show(struct device *device, + struct device_attribute *attr, + char *buf) +{ + int len; + len = sprintf(buf, "%d\n", info->trace_allowed); + return len; +} + +static ssize_t xp70_trace_allowed_store(struct device *device, + struct device_attribute *attr, + const char *buf, size_t count) +{ + if (count <= 0) { + dev_err(info->dev, "empty buffer to store\n"); + return 0; + } + + if (buf[0] == '1') + info->trace_allowed = 1; + else if (buf[0] == '0') + info->trace_allowed = 0; + else + dev_err(info->dev, "illegal trace_allowed val %c\n", + buf[0]); + + return count; +} + +static struct device_attribute xp70_device_attrs[] = { + __ATTR_RO(xp70_data), + __ATTR(trace_allowed, S_IRUGO | S_IWUSR, xp70_trace_allowed_show, + xp70_trace_allowed_store), + __ATTR_NULL +}; + +static void xp70_buffer_wqtask(struct work_struct *data) +{ + int i; + int first_index = info->trace_status.prev_block_id + 1; + int count; + + if (!info->trace_buffer) + goto out_err; + + dev_dbg(info->dev, "xp70 overwrite_cnt=%d (0x%x) blk_id=%d (0x%x)", + info->trace_buffer->overwrite_count, + info->trace_buffer->overwrite_count, + info->trace_buffer->block_id, info->trace_buffer->block_id); + + /* check if trace already started */ + if (info->trace_buffer->block_id == XP70_MAX_BLOCK_ID || + info->trace_buffer->block_id == XP70_DEFAULT_MSG_ID || + info->trace_buffer->overwrite_count == XP70_DEFAULT_MSG_ID) + goto out; + + if ((info->trace_buffer->overwrite_count - + info->trace_status.prev_overwrite_count) * XP70_NB_BLOCK + + (info->trace_buffer->block_id - + info->trace_status.prev_block_id) + >= XP70_NB_BLOCK) { + /* overflow case */ + info->trace_status.prev_block_id = + info->trace_buffer->block_id - XP70_NB_BLOCK; + first_index = info->trace_buffer->block_id + 1; + count = XP70_NB_BLOCK; + + if (printk_ratelimit()) + dev_info(info->dev, "XP70 trace overflow\n"); + } else if (info->trace_buffer->block_id + >= info->trace_status.prev_block_id) { + count = info->trace_buffer->block_id - + info->trace_status.prev_block_id; + } else { + u32 block_id, prev_block_id, diff; + block_id = (u32)(info->trace_buffer->block_id); + prev_block_id = (u32)(info->trace_status.prev_block_id); + diff = (block_id + XP70_NB_BLOCK) - prev_block_id; + count = (u32)diff; + } + + for (i = first_index; count; count--) { + if (i < 0 || i >= XP70_NB_BLOCK || count > XP70_NB_BLOCK) { + if (printk_ratelimit()) + dev_info(info->dev, "trace index out-of-bounds" + "i=%d count=%d XP70_NB_BLOCK=%d\n", + i, count, XP70_NB_BLOCK); + + break; + } + + if (info->trace_buffer->block[i].msg_id != + XP70_DEFAULT_MSG_ID) { + int msg_len = strnlen( + info->trace_buffer->block[i].data, + XP70_BLOCK_SIZE); + + /* zero terminate full length message */ + if (msg_len > 0) { + if (msg_len == XP70_BLOCK_SIZE) + info->trace_buffer->block[i].data[ + XP70_BLOCK_SIZE - 1] = '\0'; + + dev_info(info->dev, "%d %s\n", + info->trace_buffer->block[i].msg_id, + info->trace_buffer->block[i].data); + } + } + + i = (i + 1) % XP70_NB_BLOCK; + } + + info->trace_status.prev_overwrite_count = + info->trace_buffer->overwrite_count; + info->trace_status.prev_block_id = info->trace_buffer->block_id; +out: + + /* Schedule work */ + if (!schedule_delayed_work(&info->trace_work, + msecs_to_jiffies(XP70_TIMEOUT_MSEC))) + dev_info(info->dev, "failed to schedule work\n"); + +out_err: + return; +} + +/** +* mmio_probe() - Initialize MMIO Camera resources. +* @pdev: Platform device. +* +* Initialize the module and register misc device. +* +* Returns: +* 0 if there is no err. +* -ENOMEM if allocation fails. +* -EEXIST if device has already been started. +* Error codes from misc_register. +*/ +static int __devinit mmio_probe(struct platform_device *pdev) +{ + int err; + int i; + int ret; + printk(KERN_INFO "%s\n", __func__); + /* Initialize private data. */ + info = kzalloc(sizeof(struct mmio_info), GFP_KERNEL); + + if (!info) { + dev_err(&pdev->dev, "Could not alloc info struct\n"); + err = -ENOMEM; + goto err_alloc; + } + + /* Fill in private data */ + info->pdata = pdev->dev.platform_data; + info->dev = &pdev->dev; + info->pdata->dev = &pdev->dev; + info->misc_dev.minor = MISC_DYNAMIC_MINOR; + info->misc_dev.name = MMIO_NAME; + info->misc_dev.fops = &mmio_fops; + info->misc_dev.parent = pdev->dev.parent; + info->xshutdown_enabled = 0; + info->xshutdown_is_active_high = 0; + info->trace_allowed = 0; + /* Register Misc character device */ + err = misc_register(&(info->misc_dev)); + + if (err) { + dev_err(&pdev->dev, "Error %d registering misc dev!", err); + goto err_miscreg; + } + + /* Memory mapping */ + info->siabase = ioremap(info->pdata->sia_base, SIA_ISP_MCU_SYS_SIZE); + + if (!info->siabase) { + dev_err(info->dev, "Could not ioremap SIA_BASE\n"); + err = -ENOMEM; + goto err_ioremap_sia_base; + } + + info->crbase = ioremap(info->pdata->cr_base, PAGE_SIZE); + + if (!info->crbase) { + dev_err(info->dev, "Could not ioremap CR_BASE\n"); + err = -ENOMEM; + goto err_ioremap_cr_base; + } + + /* Initialize platform specific data */ + err = info->pdata->platform_init(info->pdata); + + if (err) + goto err_platform_init; + + /* create sysfs entries */ + for (i = 0; attr_name(xp70_device_attrs[i]); i++) { + ret = device_create_file(info->misc_dev.this_device, + &xp70_device_attrs[i]); + + if (ret) { + dev_err(info->dev, "Error creating SYSFS entry" + " %s (%d)\n", xp70_device_attrs[i].attr.name, + ret); + } + } + + INIT_DELAYED_WORK(&info->trace_work, xp70_buffer_wqtask); + dev_info(&pdev->dev, "MMIO driver initialized with minor=%d\n", + info->misc_dev.minor); + return 0; +err_platform_init: + iounmap(info->crbase); +err_ioremap_cr_base: + iounmap(info->siabase); +err_ioremap_sia_base: + misc_deregister(&info->misc_dev); +err_miscreg: + kfree(info); + info = NULL; +err_alloc: + return err; +} + +/** +* mmio_remove() - Release MMIO Camera resources. +* @pdev: Platform device. +* +* Remove misc device and free resources. +* +* Returns: +* 0 if success. +* Error codes from misc_deregister. +*/ +static int __devexit mmio_remove(struct platform_device *pdev) +{ + int err; + int i; + + if (!info) + return 0; + + flush_scheduled_work(); + + /* sysfs parameters */ + for (i = 0; attr_name(xp70_device_attrs[i]); i++) + device_remove_file(info->misc_dev.this_device, + &xp70_device_attrs[i]); + + err = misc_deregister(&info->misc_dev); + + if (err) + dev_err(&pdev->dev, "Error %d deregistering misc dev", err); + + info->pdata->platform_exit(info->pdata); + iounmap(info->siabase); + iounmap(info->crbase); + kfree(info); + info = NULL; + return 0; +} +static struct platform_driver mmio_driver = { + .driver = { + .name = MMIO_NAME, + .owner = THIS_MODULE, + }, + .probe = mmio_probe, + .remove = __devexit_p(mmio_remove) +}; + +/** +* mmio_init() - Initialize module. +* +* Registers platform driver. +*/ +static int __init mmio_init(void) +{ + printk(KERN_INFO "%s\n", __func__); + return platform_driver_register(&mmio_driver); +} + +/** +* mmio_exit() - Remove module. +* +* Unregisters platform driver. +*/ +static void __exit mmio_exit(void) +{ + printk(KERN_INFO "%s\n", __func__); + platform_driver_unregister(&mmio_driver); +} + +module_init(mmio_init); +module_exit(mmio_exit); + +MODULE_AUTHOR("Joakim Axelsson ST-Ericsson"); +MODULE_AUTHOR("Pankaj Chauhan ST-Ericsson"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("MMIO Camera driver"); -- cgit v1.2.3 From f771e310ce7ce833ea192acb0d4e4fa905f2c11d Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Wed, 22 Jun 2011 20:40:01 +0200 Subject: mach-ux500: Add mmio device files and device Updates board_mop500.c so that mmio driver can obtain gpio config from platform Adds sensor clock configuration to board specific file. Adds support for impplementing different power cycling schemes for primary and secondary camera sensors. Signed-off-by: Robert Marklund --- arch/arm/mach-ux500/board-mop500-mmio.c | 510 ++++++++++++++++++++++++++++++++ 1 file changed, 510 insertions(+) create mode 100644 arch/arm/mach-ux500/board-mop500-mmio.c diff --git a/arch/arm/mach-ux500/board-mop500-mmio.c b/arch/arm/mach-ux500/board-mop500-mmio.c new file mode 100644 index 00000000000..762ac2553bc --- /dev/null +++ b/arch/arm/mach-ux500/board-mop500-mmio.c @@ -0,0 +1,510 @@ +/* + * Copyright (C) 2011 ST-Ericsson + * Author: Joakim Axelsson for ST-Ericsson + * Author: Rajat Verma for ST-Ericsson. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pins-db8500.h" +#include "pins.h" +#include "board-mop500.h" +#include "../drivers/staging/mmio/mmio.h" + +static pin_cfg_t i2c2_pins[] = { + GPIO8_I2C2_SDA, + GPIO9_I2C2_SCL +}; +static pin_cfg_t ipi2c_pins[] = { + GPIO8_IPI2C_SDA, + GPIO9_IPI2C_SCL +}; +static pin_cfg_t i2c_disable_pins[] = { + GPIO8_GPIO, + GPIO9_GPIO +}; +static pin_cfg_t xshutdown_host[] = { + GPIO141_GPIO, + GPIO142_GPIO +}; +static pin_cfg_t xshutdown_fw[] = { + GPIO141_IP_GPIO2, + GPIO142_IP_GPIO3 +}; +static pin_cfg_t xshutdown_disable[] = { + GPIO141_GPIO, + GPIO142_GPIO +}; + +struct mmio_board_data{ + int number_of_regulators; + struct regulator **mmio_regulators; + /* Pin configs */ + int xenon_charge; + struct mmio_gpio xshutdown_pins[CAMERA_SLOT_END]; + /* Internal clocks */ + struct clk *clk_ptr_bml; + struct clk *clk_ptr_ipi2c; + /* External clocks */ + struct clk *clk_ptr_ext[CAMERA_SLOT_END]; +}; + +/* Fill names of regulators required for powering up the + * camera sensor in below array */ +static char *regulator_names[] = {"v-mmio-camera" , "v-ana"}; + +/* This function is used to translate the physical GPIO used for reset GPIO + * to logical IPGPIO that needs to be communicated to Firmware. so that + * firmware can control reset GPIO of a RAW Bayer sensor */ +static int mmio_get_ipgpio(struct mmio_platform_data *pdata, int gpio, + int *ip_gpio) +{ + int err = 0; + dev_dbg(pdata->dev, "%s() : IPGPIO requested for %d", __func__, gpio); + switch (gpio) { + case 67: + case 140: + *ip_gpio = 7; + break; + case 5: + case 66: + *ip_gpio = 6; + break; + case 81: + case 65: + *ip_gpio = 5; + break; + case 80: + case 64: + *ip_gpio = 4; + break; + case 10: + case 79: + case 142: + *ip_gpio = 3; + break; + case 11: + case 78: + case 141: + *ip_gpio = 2; + break; + case 7: + case 150: + *ip_gpio = 1; + break; + case 6: + case 149: + *ip_gpio = 0; + break; + default: + *ip_gpio = -1; + err = -1; + break; + } + return err; +} + +static int mmio_clock_init(struct mmio_platform_data *pdata) +{ + int err; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + + extra->clk_ptr_bml = clk_get_sys("bml", NULL); + if (IS_ERR(extra->clk_ptr_bml)) { + err = PTR_ERR(extra->clk_ptr_bml); + dev_err(pdata->dev, "Error %d getting clock 'bml'\n", err); + goto err_bml_clk; + } + extra->clk_ptr_ipi2c = clk_get_sys("ipi2", NULL); + if (IS_ERR(extra->clk_ptr_ipi2c)) { + err = PTR_ERR(extra->clk_ptr_ipi2c); + dev_err(pdata->dev, "Error %d getting clock 'ipi2'\n", err); + goto err_ipi2c_clk; + } + extra->clk_ptr_ext[PRIMARY_CAMERA] = clk_get_sys("pri-cam", NULL); + if (IS_ERR(extra->clk_ptr_ext[PRIMARY_CAMERA])) { + err = PTR_ERR(extra->clk_ptr_ext[PRIMARY_CAMERA]); + dev_err(pdata->dev, "Error %d getting clock 'pri-cam'\n", err); + goto err_pri_ext_clk; + } + extra->clk_ptr_ext[SECONDARY_CAMERA] = clk_get_sys("sec-cam", NULL); + if (IS_ERR(extra->clk_ptr_ext[SECONDARY_CAMERA])) { + err = PTR_ERR(extra->clk_ptr_ext[SECONDARY_CAMERA]); + dev_err(pdata->dev, "Error %d getting clock 'sec-cam'\n", err); + goto err_sec_ext_clk; + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_sec_ext_clk: + clk_put(extra->clk_ptr_ext[PRIMARY_CAMERA]); +err_pri_ext_clk: + clk_put(extra->clk_ptr_ipi2c); +err_ipi2c_clk: + clk_put(extra->clk_ptr_bml); +err_bml_clk: + return err; +} +static void mmio_clock_exit(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + clk_put(extra->clk_ptr_bml); + clk_put(extra->clk_ptr_ipi2c); + clk_put(extra->clk_ptr_ext[PRIMARY_CAMERA]); + clk_put(extra->clk_ptr_ext[SECONDARY_CAMERA]); +} + + +static int mmio_pin_cfg_init(struct mmio_platform_data *pdata) +{ + int err; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + + extra->xshutdown_pins[PRIMARY_CAMERA].gpio = XSHUTDOWN_PRIMARY_SENSOR; + extra->xshutdown_pins[PRIMARY_CAMERA].active_high = 0; + extra->xshutdown_pins[PRIMARY_CAMERA].udelay = 500; + + extra->xshutdown_pins[SECONDARY_CAMERA].active_high = 0; + extra->xshutdown_pins[SECONDARY_CAMERA].udelay = 500; + + /* Update GPIO mappings according to board */ + if (machine_is_hrefv60()) { + extra->xenon_charge = HREFV60_MMIO_XENON_CHARGE; + xshutdown_host[SECONDARY_CAMERA] = GPIO140_GPIO; + xshutdown_fw[SECONDARY_CAMERA] = GPIO140_IP_GPIO7; + xshutdown_disable[SECONDARY_CAMERA] = GPIO140_GPIO; + extra->xshutdown_pins[SECONDARY_CAMERA].gpio = 140; + } else { + extra->xenon_charge = GPIO_MMIO_XENON_CHARGE; + xshutdown_host[SECONDARY_CAMERA] = GPIO142_GPIO; + xshutdown_fw[SECONDARY_CAMERA] = GPIO142_IP_GPIO3; + xshutdown_disable[SECONDARY_CAMERA] = GPIO142_GPIO; + extra->xshutdown_pins[SECONDARY_CAMERA].gpio = 142; + } + /* Setup Xenon Charge */ + err = gpio_request(extra->xenon_charge, "xenon charge"); + if (err) { + dev_err(pdata->dev, "Error %d while requesting xenon charge\n", + err); + goto err_xenon_gpio_req; + } + err = gpio_direction_output(extra->xenon_charge, 0); + if (err) { + dev_err(pdata->dev, "Error %d while setting xenon charge in" + "output mode\n", err); + goto err_xenon_gpio_set_dir; + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_xenon_gpio_set_dir: + gpio_free(extra->xenon_charge); +err_xenon_gpio_req: + return err; +} + +static void mmio_pin_cfg_exit(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + gpio_free(extra->xenon_charge); +} + +/* For now, both sensors on HREF have some power up sequence. If different + * sequences are needed for primary and secondary sensors, it can be + * implemented easily. Just use camera_slot field of mmio_platform_data + * to determine which camera needs to be powered up */ +static int mmio_power_init(struct mmio_platform_data *pdata) +{ + int err = 0, i = 0; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + extra->number_of_regulators = sizeof(regulator_names)/ + sizeof(regulator_names[0]); + extra->mmio_regulators = + kzalloc(sizeof(struct regulator *) * extra->number_of_regulators, + GFP_KERNEL); + if (!extra->mmio_regulators) { + dev_err(pdata->dev , "Error while allocating memory for mmio" + "regulators\n"); + err = -ENOMEM; + goto err_no_mem_reg; + } + for (i = 0; i < + extra->number_of_regulators; i++) { + extra->mmio_regulators[i] = + regulator_get(pdata->dev, regulator_names[i]); + if (IS_ERR(extra->mmio_regulators[i])) { + err = PTR_ERR(extra->mmio_regulators[i]); + dev_err(pdata->dev , "Error %d getting regulator '%s'" + "\n", err, regulator_names[i]); + goto err_regulator; + } + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_regulator: + /* Return regulators we have already requested */ + while (i--) + regulator_put(extra->mmio_regulators[i]); + kfree(extra->mmio_regulators); +err_no_mem_reg: + return err; +} +static void mmio_power_exit(struct mmio_platform_data *pdata) +{ + int i = 0; + struct mmio_board_data *extra = pdata->extra;; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + for (i = 0; i < extra->number_of_regulators; i++) + regulator_put(extra->mmio_regulators[i]); + kfree(extra->mmio_regulators); +} + +static int mmio_platform_init(struct mmio_platform_data *pdata) +{ + int err = 0; + struct mmio_board_data *extra = NULL; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* Alloc memory for our own extra data */ + extra = kzalloc(sizeof(struct mmio_board_data), GFP_KERNEL); + if (!extra) { + dev_err(pdata->dev, "%s: memory alloc failed for " + "mmio_board_data\n", __func__); + err = -ENOMEM; + goto err_no_mem_extra; + } + /* Hook the data for other callbacks to use */ + pdata->extra = extra; + + pdata->camera_slot = -1; + + err = mmio_power_init(pdata); + if (err) + goto err_regulator; + err = mmio_clock_init(pdata); + if (err) + goto err_clock; + err = mmio_pin_cfg_init(pdata); + if (err) + goto err_pin_cfg; + /* Store logical IPGPIO for physical reset GPIOs used */ + err = mmio_get_ipgpio(pdata, + extra->xshutdown_pins[PRIMARY_CAMERA].gpio, + &(pdata->reset_ipgpio[PRIMARY_CAMERA])); + if (err) { + dev_err(pdata->dev, "Error getting ipgpio for pri cam\n"); + goto err_ipgpio; + } + err = mmio_get_ipgpio(pdata, + extra->xshutdown_pins[SECONDARY_CAMERA].gpio, + &(pdata->reset_ipgpio[SECONDARY_CAMERA])); + if (err) { + dev_err(pdata->dev, "Error getting ipgpio for sec cam\n"); + goto err_ipgpio; + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_ipgpio: + mmio_pin_cfg_exit(pdata); +err_pin_cfg: + mmio_clock_exit(pdata); +err_clock: + mmio_power_exit(pdata); +err_regulator: + kfree(extra); +err_no_mem_extra: + return err; +} +static void mmio_platform_exit(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + mmio_power_exit(pdata); + mmio_clock_exit(pdata); + mmio_pin_cfg_exit(pdata); + kfree(extra); + pdata->extra = NULL; +} + +static int mmio_power_enable(struct mmio_platform_data *pdata) +{ + int err = 0, i = 0; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* Enable the regulators */ + for (i = 0; i < extra->number_of_regulators; i++) { + err = regulator_enable(extra->mmio_regulators[i]); + if (IS_ERR(extra->mmio_regulators[i])) { + err = PTR_ERR(extra->mmio_regulators[i]); + dev_err(pdata->dev , "Error %d enabling regulator '%s'" + "\n", err, regulator_names[i]); + goto err_regulator; + } + } + /* Set Xenon Charge */ + gpio_set_value(extra->xenon_charge, 1); + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_regulator: + /* Disable regulators we already enabled */ + while (i--) + regulator_disable(extra->mmio_regulators[i]); + return err; +} + +static void mmio_power_disable(struct mmio_platform_data *pdata) +{ + int i; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* Disable the regulators */ + for (i = 0; i < extra->number_of_regulators; i++) + regulator_disable(extra->mmio_regulators[i]); + /* Disable Xenon Charge */ + gpio_set_value(extra->xenon_charge, 0); +} +static int mmio_clock_enable(struct mmio_platform_data *pdata) +{ + int err = 0; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* Enable internal clocks */ + err = clk_enable(extra->clk_ptr_bml); + if (err) { + dev_err(pdata->dev, "Error activating bml clock %d\n", err); + goto err_bml_clk; + } + err = clk_enable(extra->clk_ptr_ipi2c); + if (err) { + dev_err(pdata->dev, "Error activating i2c2 clock %d\n", err); + goto err_ipi2c_clk; + } + /* Enable appropriate external clock */ + err = clk_enable(extra->clk_ptr_ext[pdata->camera_slot]); + if (err) { + dev_err(pdata->dev, "Error activating clock for sensor %d, err" + "%d\n", pdata->camera_slot, err); + goto err_ext_clk; + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_ext_clk: + clk_disable(extra->clk_ptr_ipi2c); +err_ipi2c_clk: + clk_disable(extra->clk_ptr_bml); +err_bml_clk: + return err; +} + +static void mmio_clock_disable(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + clk_disable(extra->clk_ptr_bml); + clk_disable(extra->clk_ptr_ipi2c); + clk_disable(extra->clk_ptr_ext[pdata->camera_slot]); +} + + +static int mmio_config_xshutdown_pins(struct mmio_platform_data *pdata, + enum mmio_select_xshutdown_t select, + int is_active_high) +{ + int err = 0; + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + switch (select) { + case MMIO_ENABLE_XSHUTDOWN_HOST: + extra->xshutdown_pins[pdata->camera_slot].active_high = + is_active_high; + err = nmk_config_pin(xshutdown_host[pdata->camera_slot] | + (is_active_high ? PIN_OUTPUT_LOW : PIN_OUTPUT_HIGH), + 0); + break; + case MMIO_ENABLE_XSHUTDOWN_FW: + err = nmk_config_pin(xshutdown_fw[pdata->camera_slot], 0); + break; + case MMIO_DISABLE_XSHUTDOWN: + err = nmk_config_pin(xshutdown_disable[pdata->camera_slot], + 0); + break; + default: + break; + } + if (err) + dev_dbg(pdata->dev , "Error configuring xshutdown, err = %d\n", + err); + return err; +} +static void mmio_set_xshutdown(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + gpio_set_value(extra->xshutdown_pins[pdata->camera_slot].gpio , + (extra->xshutdown_pins[pdata->camera_slot].active_high ? 1 : + 0)); + udelay(extra->xshutdown_pins[pdata->camera_slot].udelay); +} +static int mmio_config_i2c_pins(struct mmio_platform_data *pdata, + enum mmio_select_i2c_t select) +{ + int err = 0; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + switch (select) { + case MMIO_ACTIVATE_I2C_HOST: + err = nmk_config_pins(i2c2_pins, ARRAY_SIZE(i2c2_pins)); + break; + case MMIO_ACTIVATE_IPI2C2: + err = nmk_config_pins(ipi2c_pins, ARRAY_SIZE(ipi2c_pins)); + break; + case MMIO_DEACTIVATE_I2C: + err = nmk_config_pins(i2c_disable_pins, + ARRAY_SIZE(i2c_disable_pins)); + break; + default: + break; + } + + return err; +} +static struct mmio_platform_data mmio_config = { + .platform_init = mmio_platform_init, + .platform_exit = mmio_platform_exit, + .power_enable = mmio_power_enable, + .power_disable = mmio_power_disable, + .clock_enable = mmio_clock_enable, + .clock_disable = mmio_clock_disable, + .config_i2c_pins = mmio_config_i2c_pins, + .config_xshutdown_pins = mmio_config_xshutdown_pins, + .set_xshutdown = mmio_set_xshutdown, + .sia_base = U8500_SIA_BASE, + .cr_base = U8500_CR_BASE +}; + +struct platform_device ux500_mmio_device = { + .name = MMIO_NAME, + .id = -1, + .dev = { + .platform_data = &mmio_config, + } +}; -- cgit v1.2.3 From 96cbc30f4a4b9ae712d117fe96a57be0f3a6be68 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 21 Oct 2011 11:03:05 +0200 Subject: staging: nmf-cm: Add NMF/CM driver This is driver for loading code to a DSP Signed-off-by: Philippe Langlais Signed-off-by: Robert Marklund --- drivers/staging/camera_flash/Kconfig | 7 + drivers/staging/camera_flash/Makefile | 5 + drivers/staging/camera_flash/adp1653.c | 595 +++++++++ drivers/staging/camera_flash/adp1653.h | 82 ++ drivers/staging/camera_flash/camera_flash.h | 74 ++ .../staging/camera_flash/camera_flash_bitfields.h | 83 ++ drivers/staging/camera_flash/flash_common.c | 460 +++++++ drivers/staging/camera_flash/flash_common.h | 56 + drivers/staging/nmf-cm/Kconfig | 12 + drivers/staging/nmf-cm/Make.config | 8 + drivers/staging/nmf-cm/Makefile | 99 ++ .../staging/nmf-cm/cm/engine/api/channel_engine.h | 101 ++ drivers/staging/nmf-cm/cm/engine/api/cm_engine.h | 48 + .../nmf-cm/cm/engine/api/communication_engine.h | 73 + .../nmf-cm/cm/engine/api/component_engine.h | 403 ++++++ .../nmf-cm/cm/engine/api/configuration_engine.h | 28 + .../cm/engine/api/control/configuration_engine.h | 193 +++ .../nmf-cm/cm/engine/api/control/control_engine.h | 26 + .../nmf-cm/cm/engine/api/control/irq_engine.h | 108 ++ .../staging/nmf-cm/cm/engine/api/domain_engine.h | 108 ++ .../cm/engine/api/executive_engine_mgt_engine.h | 28 + .../staging/nmf-cm/cm/engine/api/memory_engine.h | 98 ++ .../nmf-cm/cm/engine/api/migration_engine.h | 16 + .../nmf-cm/cm/engine/api/perfmeter_engine.h | 41 + .../nmf-cm/cm/engine/api/repository_mgt_engine.h | 86 ++ .../engine/communication/fifo/inc/nmf_fifo_arm.h | 56 + .../engine/communication/fifo/src/nmf_fifo_arm.c | 241 ++++ .../cm/engine/communication/inc/communication.h | 44 + .../engine/communication/inc/communication_type.h | 61 + .../cm/engine/communication/src/communication.c | 326 +++++ .../staging/nmf-cm/cm/engine/component/inc/bind.h | 443 +++++++ .../cm/engine/component/inc/component_type.h | 65 + .../nmf-cm/cm/engine/component/inc/description.h | 109 ++ .../nmf-cm/cm/engine/component/inc/dspevent.h | 28 + .../nmf-cm/cm/engine/component/inc/initializer.h | 29 + .../nmf-cm/cm/engine/component/inc/instance.h | 220 ++++ .../nmf-cm/cm/engine/component/inc/introspection.h | 109 ++ .../nmf-cm/cm/engine/component/inc/nmfheaderabi.h | 154 +++ .../nmf-cm/cm/engine/component/inc/template.h | 89 ++ .../nmf-cm/cm/engine/component/src/binder.c | 1310 ++++++++++++++++++ .../nmf-cm/cm/engine/component/src/binder_check.c | 205 +++ .../cm/engine/component/src/component_wrapper.c | 1297 ++++++++++++++++++ .../nmf-cm/cm/engine/component/src/dspevent.c | 76 ++ .../nmf-cm/cm/engine/component/src/initializer.c | 329 +++++ .../nmf-cm/cm/engine/component/src/instantiater.c | 819 ++++++++++++ .../nmf-cm/cm/engine/component/src/introspection.c | 325 +++++ .../nmf-cm/cm/engine/component/src/loader.c | 338 +++++ .../cm/engine/configuration/inc/configuration.h | 40 + .../configuration/inc/configuration_status.h | 45 + .../engine/configuration/inc/configuration_type.h | 82 ++ .../cm/engine/configuration/src/configuration.c | 213 +++ .../configuration/src/configuration_wrapper.c | 301 +++++ drivers/staging/nmf-cm/cm/engine/dsp/inc/dsp.h | 454 +++++++ .../nmf-cm/cm/engine/dsp/inc/semaphores_dsp.h | 22 + .../nmf-cm/cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h | 959 ++++++++++++++ .../nmf-cm/cm/engine/dsp/mmdsp/inc/mmdsp_macros.h | 86 ++ drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c | 1074 +++++++++++++++ drivers/staging/nmf-cm/cm/engine/elf/inc/bfd.h | 123 ++ drivers/staging/nmf-cm/cm/engine/elf/inc/common.h | 125 ++ drivers/staging/nmf-cm/cm/engine/elf/inc/elfabi.h | 539 ++++++++ drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h | 123 ++ drivers/staging/nmf-cm/cm/engine/elf/inc/memory.h | 77 ++ .../nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h | 49 + drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp.h | 31 + drivers/staging/nmf-cm/cm/engine/elf/inc/mpcal.h | 20 + drivers/staging/nmf-cm/cm/engine/elf/inc/reloc.h | 35 + drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c | 47 + drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c | 749 +++++++++++ .../staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c | 575 ++++++++ .../staging/nmf-cm/cm/engine/elf/src/elfrelocate.c | 79 ++ drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c | 591 +++++++++ .../staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c | 287 ++++ drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c | 6 + .../inc/executive_engine_mgt.h | 42 + .../src/executive_engine_mgt.c | 349 +++++ .../nmf-cm/cm/engine/memory/inc/chunk_mgr.h | 41 + .../staging/nmf-cm/cm/engine/memory/inc/domain.h | 154 +++ .../nmf-cm/cm/engine/memory/inc/domain_type.h | 61 + .../staging/nmf-cm/cm/engine/memory/inc/memory.h | 19 + .../nmf-cm/cm/engine/memory/inc/memory_type.h | 152 +++ .../nmf-cm/cm/engine/memory/inc/migration.h | 32 + .../nmf-cm/cm/engine/memory/inc/remote_allocator.h | 262 ++++ .../cm/engine/memory/inc/remote_allocator_utils.h | 33 + .../nmf-cm/cm/engine/memory/src/chunk_mgr.c | 94 ++ .../staging/nmf-cm/cm/engine/memory/src/domain.c | 590 +++++++++ .../nmf-cm/cm/engine/memory/src/domain_wrapper.c | 95 ++ .../nmf-cm/cm/engine/memory/src/memory_wrapper.c | 243 ++++ .../nmf-cm/cm/engine/memory/src/migration.c | 391 ++++++ .../nmf-cm/cm/engine/memory/src/remote_allocator.c | 680 ++++++++++ .../cm/engine/memory/src/remote_allocator_utils.c | 270 ++++ .../os_adaptation_layer/inc/os_adaptation_layer.h | 471 +++++++ .../os_adaptation_layer/src/os_adaptation_layer.c | 39 + .../nmf-cm/cm/engine/perfmeter/inc/mpcload.h | 21 + .../cm/engine/perfmeter/inc/perfmeter_type.h | 34 + .../nmf-cm/cm/engine/perfmeter/src/mpcload.c | 116 ++ .../staging/nmf-cm/cm/engine/power_mgt/inc/power.h | 59 + .../nmf-cm/cm/engine/power_mgt/src/cmpower.c | 226 ++++ .../cm/engine/repository_mgt/inc/repository_mgt.h | 55 + .../cm/engine/repository_mgt/inc/repository_type.h | 28 + .../cm/engine/repository_mgt/src/repository_mgt.c | 311 +++++ .../semaphores/hw_semaphores/inc/hw_semaphores.h | 32 + .../semaphores/hw_semaphores/src/hw_semaphores.c | 171 +++ .../nmf-cm/cm/engine/semaphores/inc/semaphores.h | 25 + .../nmf-cm/cm/engine/semaphores/src/semaphores.c | 94 ++ drivers/staging/nmf-cm/cm/engine/trace/inc/trace.h | 48 + .../staging/nmf-cm/cm/engine/trace/inc/xtitrace.h | 42 + drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 222 ++++ drivers/staging/nmf-cm/cm/engine/trace/src/trace.c | 220 ++++ .../staging/nmf-cm/cm/engine/utils/inc/convert.h | 21 + drivers/staging/nmf-cm/cm/engine/utils/inc/mem.h | 19 + .../staging/nmf-cm/cm/engine/utils/inc/string.h | 33 + drivers/staging/nmf-cm/cm/engine/utils/inc/swap.h | 23 + drivers/staging/nmf-cm/cm/engine/utils/inc/table.h | 59 + .../staging/nmf-cm/cm/engine/utils/src/convert.c | 20 + drivers/staging/nmf-cm/cm/engine/utils/src/mem.c | 27 + .../staging/nmf-cm/cm/engine/utils/src/string.c | 229 ++++ drivers/staging/nmf-cm/cm/engine/utils/src/swap.c | 156 +++ drivers/staging/nmf-cm/cm/engine/utils/src/table.c | 155 +++ drivers/staging/nmf-cm/cm/inc/cm.h | 22 + drivers/staging/nmf-cm/cm/inc/cm_def.h | 50 + drivers/staging/nmf-cm/cm/inc/cm_macros.h | 148 +++ drivers/staging/nmf-cm/cm/inc/cm_type.h | 147 +++ drivers/staging/nmf-cm/cm_dma.c | 178 +++ drivers/staging/nmf-cm/cm_dma.h | 24 + drivers/staging/nmf-cm/cm_service.c | 94 ++ drivers/staging/nmf-cm/cm_service.h | 22 + drivers/staging/nmf-cm/cm_syscall.c | 1390 ++++++++++++++++++++ drivers/staging/nmf-cm/cmioctl.h | 588 +++++++++ drivers/staging/nmf-cm/cmld.c | 1317 +++++++++++++++++++ drivers/staging/nmf-cm/cmld.h | 134 ++ drivers/staging/nmf-cm/configuration.c | 115 ++ drivers/staging/nmf-cm/configuration.h | 74 ++ drivers/staging/nmf-cm/ee/api/ee.h | 197 +++ drivers/staging/nmf-cm/ee/api/ee_type.h | 32 + drivers/staging/nmf-cm/ee/api/list.idt | 18 + drivers/staging/nmf-cm/ee/api/outnotify.h | 14 + drivers/staging/nmf-cm/ee/api/panic.idt | 73 + drivers/staging/nmf-cm/ee/api/priority.idt | 24 + drivers/staging/nmf-cm/inc/nmf-def.h | 42 + drivers/staging/nmf-cm/inc/nmf-limits.h | 107 ++ drivers/staging/nmf-cm/inc/nmf-tracedescription.h | 324 +++++ drivers/staging/nmf-cm/inc/nmf_type.idt | 64 + drivers/staging/nmf-cm/inc/type.h | 36 + drivers/staging/nmf-cm/inc/typedef.h | 193 +++ drivers/staging/nmf-cm/nmf/inc/channel_type.h | 41 + drivers/staging/nmf-cm/nmf/inc/component_type.h | 27 + drivers/staging/nmf-cm/nmf/inc/service_type.h | 94 ++ drivers/staging/nmf-cm/osal-kernel.c | 1162 ++++++++++++++++ drivers/staging/nmf-cm/osal-kernel.h | 144 ++ .../share/communication/inc/communication_fifo.h | 19 + .../nmf-cm/share/communication/inc/initializer.h | 37 + .../nmf-cm/share/communication/inc/nmf_fifo_desc.h | 36 + .../nmf-cm/share/communication/inc/nmf_service.h | 16 + drivers/staging/nmf-cm/share/inc/macros.h | 214 +++ drivers/staging/nmf-cm/share/inc/nmf.h | 47 + drivers/staging/nmf-cm/share/inc/nomadik_mapping.h | 98 ++ .../nmf-cm/share/semaphores/inc/hwsem_hwp.h | 85 ++ .../nmf-cm/share/semaphores/inc/semaphores.h | 43 + 158 files changed, 30197 insertions(+) create mode 100644 drivers/staging/camera_flash/Kconfig create mode 100644 drivers/staging/camera_flash/Makefile create mode 100644 drivers/staging/camera_flash/adp1653.c create mode 100755 drivers/staging/camera_flash/adp1653.h create mode 100644 drivers/staging/camera_flash/camera_flash.h create mode 100644 drivers/staging/camera_flash/camera_flash_bitfields.h create mode 100644 drivers/staging/camera_flash/flash_common.c create mode 100755 drivers/staging/camera_flash/flash_common.h create mode 100644 drivers/staging/nmf-cm/Kconfig create mode 100644 drivers/staging/nmf-cm/Make.config create mode 100644 drivers/staging/nmf-cm/Makefile create mode 100644 drivers/staging/nmf-cm/cm/engine/api/channel_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/cm_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/communication_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/component_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/configuration_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/control/configuration_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/control/control_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/domain_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/executive_engine_mgt_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/memory_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/migration_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/perfmeter_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/api/repository_mgt_engine.h create mode 100644 drivers/staging/nmf-cm/cm/engine/communication/fifo/inc/nmf_fifo_arm.h create mode 100644 drivers/staging/nmf-cm/cm/engine/communication/fifo/src/nmf_fifo_arm.c create mode 100644 drivers/staging/nmf-cm/cm/engine/communication/inc/communication.h create mode 100644 drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h create mode 100644 drivers/staging/nmf-cm/cm/engine/communication/src/communication.c create mode 100644 drivers/staging/nmf-cm/cm/engine/component/inc/bind.h create mode 100644 drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h create mode 100644 drivers/staging/nmf-cm/cm/engine/component/inc/description.h create mode 100644 drivers/staging/nmf-cm/cm/engine/component/inc/dspevent.h create mode 100644 drivers/staging/nmf-cm/cm/engine/component/inc/initializer.h create mode 100644 drivers/staging/nmf-cm/cm/engine/component/inc/instance.h create mode 100644 drivers/staging/nmf-cm/cm/engine/component/inc/introspection.h create mode 100644 drivers/staging/nmf-cm/cm/engine/component/inc/nmfheaderabi.h create mode 100644 drivers/staging/nmf-cm/cm/engine/component/inc/template.h create mode 100644 drivers/staging/nmf-cm/cm/engine/component/src/binder.c create mode 100644 drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c create mode 100644 drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c create mode 100644 drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c create mode 100644 drivers/staging/nmf-cm/cm/engine/component/src/initializer.c create mode 100644 drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c create mode 100644 drivers/staging/nmf-cm/cm/engine/component/src/introspection.c create mode 100644 drivers/staging/nmf-cm/cm/engine/component/src/loader.c create mode 100644 drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration.h create mode 100644 drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_status.h create mode 100644 drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h create mode 100644 drivers/staging/nmf-cm/cm/engine/configuration/src/configuration.c create mode 100644 drivers/staging/nmf-cm/cm/engine/configuration/src/configuration_wrapper.c create mode 100644 drivers/staging/nmf-cm/cm/engine/dsp/inc/dsp.h create mode 100644 drivers/staging/nmf-cm/cm/engine/dsp/inc/semaphores_dsp.h create mode 100644 drivers/staging/nmf-cm/cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h create mode 100644 drivers/staging/nmf-cm/cm/engine/dsp/mmdsp/inc/mmdsp_macros.h create mode 100644 drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/inc/bfd.h create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/inc/common.h create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/inc/elfabi.h create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/inc/memory.h create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp.h create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/inc/mpcal.h create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/inc/reloc.h create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/src/elfrelocate.c create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c create mode 100644 drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c create mode 100644 drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h create mode 100644 drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/inc/chunk_mgr.h create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/inc/memory.h create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/inc/migration.h create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator_utils.h create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/src/chunk_mgr.c create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/src/domain.c create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/src/domain_wrapper.c create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/src/migration.c create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c create mode 100644 drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator_utils.c create mode 100644 drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h create mode 100644 drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/src/os_adaptation_layer.c create mode 100644 drivers/staging/nmf-cm/cm/engine/perfmeter/inc/mpcload.h create mode 100644 drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h create mode 100644 drivers/staging/nmf-cm/cm/engine/perfmeter/src/mpcload.c create mode 100644 drivers/staging/nmf-cm/cm/engine/power_mgt/inc/power.h create mode 100644 drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c create mode 100644 drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_mgt.h create mode 100644 drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h create mode 100644 drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c create mode 100644 drivers/staging/nmf-cm/cm/engine/semaphores/hw_semaphores/inc/hw_semaphores.h create mode 100644 drivers/staging/nmf-cm/cm/engine/semaphores/hw_semaphores/src/hw_semaphores.c create mode 100644 drivers/staging/nmf-cm/cm/engine/semaphores/inc/semaphores.h create mode 100644 drivers/staging/nmf-cm/cm/engine/semaphores/src/semaphores.c create mode 100644 drivers/staging/nmf-cm/cm/engine/trace/inc/trace.h create mode 100644 drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h create mode 100644 drivers/staging/nmf-cm/cm/engine/trace/src/panic.c create mode 100644 drivers/staging/nmf-cm/cm/engine/trace/src/trace.c create mode 100644 drivers/staging/nmf-cm/cm/engine/utils/inc/convert.h create mode 100644 drivers/staging/nmf-cm/cm/engine/utils/inc/mem.h create mode 100644 drivers/staging/nmf-cm/cm/engine/utils/inc/string.h create mode 100644 drivers/staging/nmf-cm/cm/engine/utils/inc/swap.h create mode 100644 drivers/staging/nmf-cm/cm/engine/utils/inc/table.h create mode 100644 drivers/staging/nmf-cm/cm/engine/utils/src/convert.c create mode 100644 drivers/staging/nmf-cm/cm/engine/utils/src/mem.c create mode 100644 drivers/staging/nmf-cm/cm/engine/utils/src/string.c create mode 100644 drivers/staging/nmf-cm/cm/engine/utils/src/swap.c create mode 100644 drivers/staging/nmf-cm/cm/engine/utils/src/table.c create mode 100644 drivers/staging/nmf-cm/cm/inc/cm.h create mode 100644 drivers/staging/nmf-cm/cm/inc/cm_def.h create mode 100644 drivers/staging/nmf-cm/cm/inc/cm_macros.h create mode 100644 drivers/staging/nmf-cm/cm/inc/cm_type.h create mode 100644 drivers/staging/nmf-cm/cm_dma.c create mode 100644 drivers/staging/nmf-cm/cm_dma.h create mode 100644 drivers/staging/nmf-cm/cm_service.c create mode 100644 drivers/staging/nmf-cm/cm_service.h create mode 100644 drivers/staging/nmf-cm/cm_syscall.c create mode 100644 drivers/staging/nmf-cm/cmioctl.h create mode 100644 drivers/staging/nmf-cm/cmld.c create mode 100644 drivers/staging/nmf-cm/cmld.h create mode 100644 drivers/staging/nmf-cm/configuration.c create mode 100644 drivers/staging/nmf-cm/configuration.h create mode 100644 drivers/staging/nmf-cm/ee/api/ee.h create mode 100644 drivers/staging/nmf-cm/ee/api/ee_type.h create mode 100644 drivers/staging/nmf-cm/ee/api/list.idt create mode 100644 drivers/staging/nmf-cm/ee/api/outnotify.h create mode 100644 drivers/staging/nmf-cm/ee/api/panic.idt create mode 100644 drivers/staging/nmf-cm/ee/api/priority.idt create mode 100644 drivers/staging/nmf-cm/inc/nmf-def.h create mode 100644 drivers/staging/nmf-cm/inc/nmf-limits.h create mode 100644 drivers/staging/nmf-cm/inc/nmf-tracedescription.h create mode 100644 drivers/staging/nmf-cm/inc/nmf_type.idt create mode 100644 drivers/staging/nmf-cm/inc/type.h create mode 100644 drivers/staging/nmf-cm/inc/typedef.h create mode 100644 drivers/staging/nmf-cm/nmf/inc/channel_type.h create mode 100644 drivers/staging/nmf-cm/nmf/inc/component_type.h create mode 100644 drivers/staging/nmf-cm/nmf/inc/service_type.h create mode 100644 drivers/staging/nmf-cm/osal-kernel.c create mode 100644 drivers/staging/nmf-cm/osal-kernel.h create mode 100644 drivers/staging/nmf-cm/share/communication/inc/communication_fifo.h create mode 100644 drivers/staging/nmf-cm/share/communication/inc/initializer.h create mode 100644 drivers/staging/nmf-cm/share/communication/inc/nmf_fifo_desc.h create mode 100644 drivers/staging/nmf-cm/share/communication/inc/nmf_service.h create mode 100644 drivers/staging/nmf-cm/share/inc/macros.h create mode 100644 drivers/staging/nmf-cm/share/inc/nmf.h create mode 100644 drivers/staging/nmf-cm/share/inc/nomadik_mapping.h create mode 100644 drivers/staging/nmf-cm/share/semaphores/inc/hwsem_hwp.h create mode 100644 drivers/staging/nmf-cm/share/semaphores/inc/semaphores.h diff --git a/drivers/staging/camera_flash/Kconfig b/drivers/staging/camera_flash/Kconfig new file mode 100644 index 00000000000..187217d763f --- /dev/null +++ b/drivers/staging/camera_flash/Kconfig @@ -0,0 +1,7 @@ + +config U8500_FLASH + bool "ST-Ericsson Flash (Camera) Driver" + depends on ARCH_U8500 + help + Adds ST-Ericsson Flash (Camera) Driver + diff --git a/drivers/staging/camera_flash/Makefile b/drivers/staging/camera_flash/Makefile new file mode 100644 index 00000000000..bf2f5aa2dd3 --- /dev/null +++ b/drivers/staging/camera_flash/Makefile @@ -0,0 +1,5 @@ +export ADP1653_SUPPORT +EXTRA_CFLAGS += -DADP1653_SUPPORT +obj-$(CONFIG_U8500_FLASH) := camera_flash.o +camera_flash-y := flash_common.o +camera_flash-y += adp1653.o diff --git a/drivers/staging/camera_flash/adp1653.c b/drivers/staging/camera_flash/adp1653.c new file mode 100644 index 00000000000..c97014fc5ad --- /dev/null +++ b/drivers/staging/camera_flash/adp1653.c @@ -0,0 +1,595 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * adp1653: Driver Adp1653 HPLED flash driver chip. This driver + * currently support I2C interface, 2bit interface is not supported. + * Author: Pankaj Chauhan/pankaj.chauhan@stericsson.com for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "flash_common.h" +#include "adp1653.h" +#include "camera_flash.h" + +/* This data is platform specific for 8500 href-v1 platform, + * Ideally this should be supplied from platform code + */ +//#define ADAPTER_I2C2 (2) +#define STR_GPIO (6) + +static int strobe_gpio = 0; //TODO: set to 0 when it works +static int adapter_i2c2 = 2; +static int flash_irq = 7; +static int enable_gpio = 272; +static int flash_position = 0; +module_param(strobe_gpio, int, S_IRUGO); +MODULE_PARM_DESC(strobe_gpio, "use GPIO 6 to strobe, 0 means that someone else (sensor?) will strobe for us"); +module_param(adapter_i2c2, int, S_IRUGO); +MODULE_PARM_DESC(adapter_i2c2, "use the given I2C adaptater to communicate with the chip"); +module_param(flash_irq, int, S_IRUGO); +MODULE_PARM_DESC(flash_irq, "the GPIO number associated to the i2c irq line"); +module_param(enable_gpio, int, S_IRUGO); +MODULE_PARM_DESC(enable_gpio, "use the given GPIO line to enable the chip"); +module_param(flash_position, int, S_IRUGO); +MODULE_PARM_DESC(flash_position, "the position of the flash chip (0=PRIMARY, 1=SECONDARY)"); + + +int __flash_gpio_to_irq(int gpio) +{ + + return NOMADIK_GPIO_TO_IRQ(gpio); +} + +#define DEBUG_LOG(...) printk(KERN_DEBUG "Adp1653 flash driver: " __VA_ARGS__) + +#define ADP1653_SUPPORTED_MODES (FLASH_MODE_VIDEO_LED | FLASH_MODE_STILL_LED | \ + FLASH_MODE_STILL_LED_EXTERNAL_STROBE | \ + FLASH_MODE_AF_ASSISTANT | FLASH_MODE_INDICATOR) + +#define ADP1653_SELFTEST_SUPPORTED_MODES (FLASH_SELFTEST_CONNECTION | FLASH_SELFTEST_FLASH_WITH_STROBE | \ + FLASH_SELFTEST_VIDEO_LIGHT | FLASH_SELFTEST_AF_LIGHT | FLASH_SELFTEST_INDICATOR | FLASH_SELFTEST_TORCH_LIGHT) + +static int adp1653_trigger_strobe(void *priv_data, int enable); + +static int adp1653_get_modes(void *priv_data,unsigned long *modes) +{ + int err; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv_data; + err = i2c_smbus_read_byte_data(priv_p->i2c_client, FAULT_STATUS_REG); + if (err) + *modes = 0x0; + else + *modes = ADP1653_SUPPORTED_MODES; + return 0; +} + +static int adp1653_get_mode_details(void *priv_data, unsigned long mode, +struct flash_mode_details *details_p) +{ + int err = 0; + memset(details_p,0,sizeof(struct flash_mode_details)); + + details_p->led_type = 2; + + /* Still LED settings*/ + details_p->nbFaultRegisters = 1; + if(mode & (FLASH_MODE_STILL_LED | FLASH_MODE_STILL_LED_EXTERNAL_STROBE)){ + details_p->max_intensity_uAmp = FLASH_MAX_INTENSITY; + details_p->min_intensity_uAmp = FLASH_MIN_INTENSITY; + details_p->max_strobe_duration_uSecs = FLASH_MAX_STROBE_DURATION; + details_p->feature_bitmap = INTENSITY_PROGRAMMABLE | DURATION_PROGRAMMABLE; + goto out; + } + /*Video LED settings*/ + if(mode & FLASH_MODE_VIDEO_LED){ + details_p->max_intensity_uAmp = TORCH_MAX_INTENSITY; + details_p->min_intensity_uAmp = TORCH_MIN_INTENSITY; + details_p->max_strobe_duration_uSecs = 0; + details_p->feature_bitmap = INTENSITY_PROGRAMMABLE; + goto out; + } + /*Privacy Indicator settings */ + if(mode & FLASH_MODE_INDICATOR){ + details_p->max_intensity_uAmp = ILED_MAX_INTENSITY; + details_p->min_intensity_uAmp = ILED_MIN_INTENSITY; + details_p->max_strobe_duration_uSecs = 0; + details_p->feature_bitmap = INTENSITY_PROGRAMMABLE; + goto out; + } + DEBUG_LOG("Mode %lx, not supported\n",mode); + err = EINVAL; +out: + return err; +} + +static int adp1653_enable_flash_mode(void *priv_data, + unsigned long mode, int enable) +{ + int err = 0; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv_data; + + if(enable){ + + if(!(mode & ADP1653_SUPPORTED_MODES)){ + DEBUG_LOG("Unsupported mode %lx\n",mode); + err = -EINVAL; + goto out; + } + /*Nothing to be done in enabling, just set current mode and return*/ + /*May be enable disable can be done here but why not enable in + *probe and keep it on always + */ + adp1653_trigger_strobe(priv_p,0); + priv_p->curr_mode = mode; + }else{ + adp1653_trigger_strobe(priv_p,0); + priv_p->curr_mode =0; + } +out: + return err; +} + +static int adp1653_configure_flash_mode(void *priv,unsigned long mode, +struct flash_mode_params *params_p) +{ + int err = 0; + unsigned char intensity_code; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv; + + if(!(mode & ADP1653_SUPPORTED_MODES)){ + DEBUG_LOG("Mode %lx not supported\n",mode); + err = -EINVAL; + goto out; + } + switch(mode){ + case FLASH_MODE_STILL_LED: + case FLASH_MODE_STILL_LED_EXTERNAL_STROBE: + { + FLASH_UAMP_TO_CODE(intensity_code,params_p->intensity_uAmp); + if(params_p->duration_uSecs){ + DURATION_USEC_TO_CODE(priv_p->flash_duration, + params_p->duration_uSecs); + DEBUG_LOG("Duration %lu, code 0x%x\n",params_p->duration_uSecs, + priv_p->flash_duration); + priv_p->flash_duration |= TIMER_ENABLE; + }else{ + priv_p->flash_duration = 0; + } + priv_p->flash_intensity = intensity_code << 3; + } + break; + case FLASH_MODE_VIDEO_LED: + { + TORCH_UAMP_TO_CODE(intensity_code,params_p->intensity_uAmp); + DEBUG_LOG("Torch mode setting intensity 0x%x, current(uA) %lu\n", + intensity_code,params_p->intensity_uAmp); + priv_p->torch_intensity = intensity_code << 3; + } + break; + case FLASH_MODE_INDICATOR: + { + ILED_UAMP_TO_CODE(intensity_code,params_p->intensity_uAmp); + DEBUG_LOG("ILED setting intensity 0x%x, current(uA) %lu\n", + intensity_code,params_p->intensity_uAmp); + priv_p->indicator_intensity = intensity_code; + } + break; + default: + err = -EINVAL; + DEBUG_LOG("Unsupported mode %lx\n",mode); + break; + } + + if((mode == FLASH_MODE_STILL_LED_EXTERNAL_STROBE) || (mode == FLASH_MODE_STILL_LED)) + { + adp1653_trigger_strobe(priv_p,0); + DEBUG_LOG("CONFIG_TIMER_REG : 0x%x\n",priv_p->flash_duration); + DEBUG_LOG("OUTPUT_SEL_REG : 0x%x\n",priv_p->flash_intensity); + + /*TimeOut Must be programmed before Intensity*/ + err = i2c_smbus_write_byte_data(priv_p->i2c_client,CONFIG_TIMER_REG, + priv_p->flash_duration); + if(err){ + DEBUG_LOG("I2C: Unsable to write timer config, err %d\n",err); + goto out; + } + err = i2c_smbus_write_byte_data(priv_p->i2c_client,OUTPUT_SEL_REG, + priv_p->flash_intensity); + if(err){ + DEBUG_LOG("I2C: Unable to write OUTPUT_SEL_REG , err %d\n",err); + goto out; + } + } +out: + return err; +} + +static int adp1653_set_intensity(struct adp1653_priv_data *priv_p, uint8_t intensity) +{ + return i2c_smbus_write_byte_data(priv_p->i2c_client,OUTPUT_SEL_REG,intensity); +} + +static int adp1653_strobe_still_led(struct adp1653_priv_data *priv_p,int enable) +{ + int err=0,gpio_val; + uint8_t intensity,duration; + + if(enable){ + intensity = priv_p->flash_intensity; + duration = priv_p->flash_duration; + gpio_val = 1; + }else{ + intensity = 0; + duration = 0; + gpio_val = 0; + } + + err = adp1653_set_intensity(priv_p,intensity); + if(err){ + DEBUG_LOG("I2C: Unable to write OUTPUT_SEL_REG reg, err %d\n",err); + goto out; + } + + /*TimeOut Must be programmed before Intensity*/ + err = i2c_smbus_write_byte_data(priv_p->i2c_client,CONFIG_TIMER_REG, + priv_p->flash_duration); + if(err){ + DEBUG_LOG("I2C: Unsable to write timer config, err %d\n",err); + goto out; + } + err = i2c_smbus_write_byte_data(priv_p->i2c_client,OUTPUT_SEL_REG,intensity); + if(err){ + DEBUG_LOG("I2C: Unable to write OUTPUT_SEL_REG, err %d\n",err); + goto out; + } + + if (strobe_gpio != 0 ) + { + gpio_set_value(priv_p->strobe_gpio,gpio_val); + } + +out: + return err; +} + +static int adp1653_trigger_strobe(void *priv, int enable) +{ + int err = 0; + uint8_t intensity; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv; + + switch(priv_p->curr_mode){ + case FLASH_MODE_STILL_LED: + case FLASH_MODE_STILL_LED_EXTERNAL_STROBE: + err = adp1653_strobe_still_led(priv_p,enable); + break; + case FLASH_MODE_VIDEO_LED: + { + if(enable) + intensity = priv_p->torch_intensity; + else + intensity = 0; + err = adp1653_set_intensity(priv_p,intensity); + } + break; + case FLASH_MODE_INDICATOR: + { + if(enable) + intensity = priv_p->indicator_intensity; + else + intensity =0; + err = adp1653_set_intensity(priv_p,intensity); + } + break; + default: + DEBUG_LOG("Unsupported mode %lx\n",priv_p->curr_mode); + goto out; + } + if(err){ + DEBUG_LOG("Unable to enable/disable %d, strobe. Mode %lx, err %d\n",enable, + priv_p->curr_mode,err); + goto out; + } + disable_irq(priv_p->i2c_client->irq); + if(enable) + SET_FLASH_STATUS(priv_p->status,FLASH_STATUS_LIT); + else + CLR_FLASH_STATUS(priv_p->status,FLASH_STATUS_LIT); + + enable_irq(priv_p->i2c_client->irq); + +out: + return err; +} +#define FLASH_ERR_ALL (FLASH_ERR_OVER_CHARGE |FLASH_ERR_OVER_HEAT | \ + FLASH_ERR_SHORT_CIRCUIT | FLASH_ERR_TIMEOUT | \ + FLASH_ERR_OVER_VOLTAGE) +int adp1653_get_status(void *priv_data,unsigned long *status) +{ + struct adp1653_priv_data *priv_p= (struct adp1653_priv_data *)priv_data; + disable_irq(priv_p->i2c_client->irq); + if(priv_p->fault){ + if(priv_p->fault & OVER_VOLTAGE_FAULT) + SET_FLASH_ERROR(priv_p->status,FLASH_ERR_OVER_VOLTAGE); + if(priv_p->fault & TIMEOUT_FAULT) + SET_FLASH_ERROR(priv_p->status,FLASH_ERR_TIMEOUT); + if(priv_p->fault & OVER_TEMPERATURE_FAULT) + SET_FLASH_ERROR(priv_p->status,FLASH_ERR_OVER_HEAT); + if(priv_p->fault & SHORT_CIRCUIT_FAULT){ + CLR_FLASH_STATUS(priv_p->status,FLASH_STATUS_READY); + SET_FLASH_STATUS(priv_p->status,FLASH_STATUS_BROKEN); + SET_FLASH_ERROR(priv_p->status,FLASH_ERR_SHORT_CIRCUIT); + } + priv_p->fault =0; + }else{ + CLR_FLASH_ERROR(priv_p->status,FLASH_ERR_ALL); + } + enable_irq(priv_p->i2c_client->irq); + *status = priv_p->status; + return 0; +} + +int adp1653_get_selftest_modes(void *priv_data, unsigned long *modes) +{ + int err; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv_data; + err = i2c_smbus_read_byte_data(priv_p->i2c_client, FAULT_STATUS_REG); + if (err) *modes = 0x0; + else *modes = ADP1653_SELFTEST_SUPPORTED_MODES; + return 0; +} + +int adp1653_get_fault_registers(void *priv_data, unsigned long mode, unsigned long *status) +{ + int err = 0; + struct adp1653_priv_data *priv_p = (struct adp1653_priv_data *)priv_data; + + *status = i2c_smbus_read_byte_data(priv_p->i2c_client, FAULT_STATUS_REG); + + /* clear fault register */ + err = i2c_smbus_write_byte_data(priv_p->i2c_client,OUTPUT_SEL_REG,0); + if(0 != err) + { + DEBUG_LOG("Unable to write OUTPUT_SEL_REG, err %d\n",err); + } + return err; +} + +struct flash_chip_ops adp1653_ops = { + .get_modes = adp1653_get_modes, + .get_mode_details = adp1653_get_mode_details, + .get_status = adp1653_get_status, + .enable_flash_mode = adp1653_enable_flash_mode, + .configure_flash_mode = adp1653_configure_flash_mode, + .trigger_strobe = adp1653_trigger_strobe, + .get_selftest_modes = adp1653_get_selftest_modes, + .get_fault_registers = adp1653_get_fault_registers +}; + +static irqreturn_t adp1653_irq_hdlr(int irq_no,void *data) +{ + int err; + struct adp1653_priv_data *priv_p= (struct adp1653_priv_data *)data; + + priv_p->fault = i2c_smbus_read_byte_data(priv_p->i2c_client, + FAULT_STATUS_REG); + DEBUG_LOG("Got Fault, status 0x%x\n",priv_p->fault); + /*Writing 0 to OUTPUT_SEL_REG clears the interrtup + *and FAULT_STATUS_REG register + */ + err = i2c_smbus_write_byte_data(priv_p->i2c_client,OUTPUT_SEL_REG,0); + if(err) + DEBUG_LOG("Unable to write OUTPUT_SEL_REG to clr intr, err %d\n",err); + /*TBD: send even to user process*/ + return IRQ_HANDLED; +} +static int __devinit adp1653_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + int err=0; + struct flash_chip *flash_chip_p=NULL; + struct adp1653_priv_data *priv_p=NULL; + + DEBUG_LOG("> adp1653_probe\n"); + + priv_p = kzalloc(sizeof(struct adp1653_priv_data),GFP_KERNEL); + if(!priv_p){ + DEBUG_LOG("Kmalloc failed for priv data\n"); + err = ENOMEM; + goto out; + } + priv_p->i2c_client = client; + flash_chip_p = kzalloc(sizeof(struct flash_chip),GFP_KERNEL); + if(!flash_chip_p){ + DEBUG_LOG("Kmalloc failed for flash_chip_p"); + err = ENOMEM; + goto out; + } + flash_chip_p->priv_data = priv_p; + flash_chip_p->ops = &adp1653_ops; + SET_FLASHCHIP_TYPE(flash_chip_p,FLASH_TYPE_HPLED); + SET_FLASHCHIP_ID(flash_chip_p,ADP1653_ID); + + strncpy(flash_chip_p->name,"Adp1653",FLASH_NAME_SIZE); + + i2c_set_clientdata(client,priv_p); + /*Request GPIO and Register IRQ if supported by platform and flash chip*/ + + if(machine_is_hrefv60()) + enable_gpio = 21; + else + enable_gpio = 272; + + if(enable_gpio){ + err = gpio_request(enable_gpio,"Camera LED flash Enable"); + if(err){ + DEBUG_LOG("Unable to get GPIO %d, for enable\n",enable_gpio); + goto out; + } + priv_p->enable_gpio = enable_gpio; + + err = gpio_direction_output(priv_p->enable_gpio, 1); + if(err){ + DEBUG_LOG("Unable to set GPIO %lu in output mode, err %d\n",priv_p->enable_gpio,err); + gpio_free(priv_p->enable_gpio); + goto out; + } + gpio_set_value(priv_p->enable_gpio, 1); + } + + if (strobe_gpio != 0) + { + err = gpio_request(STR_GPIO,"Camera flash strobe\n"); + if(err){ + DEBUG_LOG("Unable to request strobe GPIO\n"); + // somebody else requested this gpio ... + //goto out; + } + + err = gpio_direction_output(STR_GPIO, 0); + if(err){ + DEBUG_LOG("Unable to set GPIO %d in output mode, err %d\n",STR_GPIO,err); + goto out; + } + } + else + { + err = gpio_request(STR_GPIO,"Camera flash strobe\n"); + if(err){ + DEBUG_LOG("Unable to request strobe GPIO\n"); + // somebody else requested this gpio ... + //goto out; + } + + err = gpio_direction_input(STR_GPIO); + if(err){ + DEBUG_LOG("Unable to set GPIO %d in input mode, err %d\n",STR_GPIO,err); + goto out; + } + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) + err = nmk_gpio_set_pull(STR_GPIO, NMK_GPIO_PULL_DOWN); +#endif + if(err){ + DEBUG_LOG("Unable to set pull down on GPIO %d\n",STR_GPIO); + goto out; + } + + } + + priv_p->strobe_gpio = STR_GPIO; + + if(client->irq){ + err = request_threaded_irq(client->irq,NULL,adp1653_irq_hdlr, + IRQF_ONESHOT|IRQF_TRIGGER_FALLING, + "Adp1653 flash",priv_p); + if(err){ + DEBUG_LOG("Unable to register flash IRQ handler, irq %d, err %d\n", + client->irq,err); + goto out; + } + } + err = register_flash_chip(flash_position,flash_chip_p); + if(err){ + DEBUG_LOG("Failed to register Adp1653 as flash for %s camera\n", + (flash_position?"Primary":"Secondary")); + goto out; + } + SET_FLASH_STATUS(priv_p->status,FLASH_STATUS_READY); + DEBUG_LOG("< adp1653_probe ok\n"); + return err; +out: + if(priv_p->irq_no) + free_irq(priv_p->irq_no,NULL); + if(priv_p->enable_gpio) + gpio_free(priv_p->enable_gpio); + if(priv_p) + kfree(priv_p); + if(flash_chip_p) + kfree(flash_chip_p); + DEBUG_LOG("< adp1653_probe (%d)\n", err); + return err; +} + +static int __devexit adp1653_remove(struct i2c_client *client) +{ + int err=0; + /*Nothing here yet, implement it later.*/ + return err; +} +static const struct i2c_device_id adp1653_id[] = { + { "adp1653", 0}, + {} +}; +static struct i2c_driver adp1653_i2c_driver = { + .driver = { + .name = "adp1653", + .owner = THIS_MODULE, + }, + .probe = adp1653_probe, + .remove = __devexit_p(adp1653_remove), + .id_table = adp1653_id, +}; + +int adp1653_init(void){ + int err=0; + struct i2c_adapter *adap_p; + struct i2c_board_info info; + + /*Registration of I2C flash device is platform specific code + *Ideally it should be done from kernel (arch/arm/mach-XXX). + *Do it locally till the time it gets into platform code + *OR This portion (registration of device) and flash chip init + *Routine can be moved to Flash chip module init. + */ + DEBUG_LOG("getting I2C adaptor %d\n",adapter_i2c2); + adap_p = i2c_get_adapter(adapter_i2c2); + if(!adap_p){ + DEBUG_LOG("Unable to get I2C adaptor\n"); + goto out; + } + memset(&info,0,sizeof( struct i2c_board_info)); + + info.irq = __flash_gpio_to_irq(flash_irq); + + strcpy(&info.type[0],"adp1653"); + DEBUG_LOG("trying to register %s at position %d, GPIO enable %d, GPIO IRQ line %d\n", + info.type, + flash_position, + enable_gpio, + flash_irq); + + /* I2C framework expects least significant 7 bits as address, not complete + * 8 bits with bit 0 (read/write bit) + */ + info.addr = 0x60 >> 1; + + + err = i2c_add_driver(&adp1653_i2c_driver); + if(err) + { + DEBUG_LOG("Failed to register i2c driver\n"); + goto out; + } + + + DEBUG_LOG("Initialized adp1653\n"); + if(!i2c_new_device(adap_p,&info)){ + DEBUG_LOG("Unable to add i2c dev: %s (err=%d)\n",info.type, err); + goto out; + } + +out: + return err; +} + +/* +MODULE_DEPEND +*/ diff --git a/drivers/staging/camera_flash/adp1653.h b/drivers/staging/camera_flash/adp1653.h new file mode 100755 index 00000000000..3035ab56d99 --- /dev/null +++ b/drivers/staging/camera_flash/adp1653.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * License terms: GNU General Public License (GPL), version 2. + */ +#ifndef __ADP1653_H__ +#define __ADP1653_H__ + +#include +#define ADP1653_ID (0) /*chip does not give any id :) so be it zero!*/ + +#define OUTPUT_SEL_REG (0x00) +#define CONFIG_TIMER_REG (0x01) +#define SW_STROBE_REG (0x02) +#define FAULT_STATUS_REG (0x03) + +/* Fault codes, FALUT_STATUS_REG bits */ +#define OVER_VOLTAGE_FAULT (0x01) +#define TIMEOUT_FAULT (0x02) +#define OVER_TEMPERATURE_FAULT (0x04) +#define SHORT_CIRCUIT_FAULT (0x08) + +/*CONFIG_TIMER_REG bits*/ +#define TIMER_ENABLE (0x10) + +struct adp1653_priv_data{ + struct i2c_client *i2c_client; + unsigned long curr_mode; + unsigned long enable_gpio; + unsigned long strobe_gpio; + unsigned long irq_no; + unsigned long status; + uint8_t fault; + uint8_t flash_intensity; + uint8_t flash_duration; + uint8_t torch_intensity; + uint8_t indicator_intensity; +}; + +/*Intensity current limits in Micro Amps*/ +/* over 250mA flash current is reduced */ +/* do not know why, neither really care about */ +//#define FLASH_MAX_INTENSITY (500000) /*code - 31*/ +#define FLASH_MAX_INTENSITY (250000) +#define FLASH_MIN_INTENSITY (215000) /*code - 12*/ +#define TORCH_MAX_INTENSITY (200000) /*code - 11*/ +#define TORCH_MIN_INTENSITY (50000) /*code - 1*/ +#define ILED_MAX_INTENSITY (17500) /*Code - 7*/ +#define ILED_MIN_INTENSITY (2500) /*code - 1*/ + +#define FLASH_MAX_STROBE_DURATION (820000) /*820 uSec*/ + +#define DURATION_USEC_TO_CODE(_code,_duration) do{ \ + if(_duration > FLASH_MAX_STROBE_DURATION) \ + _duration = FLASH_MAX_STROBE_DURATION; \ + _code = (FLASH_MAX_STROBE_DURATION - _duration) / 54600;\ +}while(0); + +#define HPLED_UAMP_TO_CODE(_current) ((_current - 35000) / 15000) + +#define FLASH_UAMP_TO_CODE(_code,_current){ \ + if(_current > FLASH_MAX_INTENSITY) \ + _current = FLASH_MAX_INTENSITY; \ + if(_current < FLASH_MIN_INTENSITY) \ + _current = FLASH_MIN_INTENSITY; \ + _code = HPLED_UAMP_TO_CODE(_current); \ +}while(0) + +#define TORCH_UAMP_TO_CODE(_code,_current){ \ + if(_current > TORCH_MAX_INTENSITY) \ + _current = TORCH_MAX_INTENSITY; \ + if(_current < TORCH_MIN_INTENSITY) \ + _current = TORCH_MIN_INTENSITY; \ + _code = HPLED_UAMP_TO_CODE(_current); \ +}while(0) + +#define ILED_UAMP_TO_CODE(_code,_current) do { \ + if(_current > ILED_MAX_INTENSITY) \ + _current = ILED_MAX_INTENSITY; \ + _code = _current / ILED_MIN_INTENSITY; /* Min current: 2.5mA/2500uA*/ \ +}while(0) + +#endif diff --git a/drivers/staging/camera_flash/camera_flash.h b/drivers/staging/camera_flash/camera_flash.h new file mode 100644 index 00000000000..15faf706dc9 --- /dev/null +++ b/drivers/staging/camera_flash/camera_flash.h @@ -0,0 +1,74 @@ +#ifndef __CAMERA_FLASH_H__ +#define __CAMERA_FLASH_H__ + +#define FLASH_NAME_SIZE (20) + +struct flash_mode_details { + unsigned long led_type; + unsigned long max_intensity_uAmp; + unsigned long min_intensity_uAmp; + unsigned long max_strobe_duration_uSecs; + unsigned long feature_bitmap; + unsigned char nbFaultRegisters; +}; + +/*feature_bitmap (in struct flash_mode_details) bit values*/ +#define INTENSITY_PROGRAMMABLE (0x01) +#define DURATION_PROGRAMMABLE (0x02) +#define TIMEOUT_PROGRAMMABLE (0x04) + +/*Status word returned by driver has status in lower 16 bits + *and Error in higher 16 bits. definition of status and error + *bits are there in flash_bitfields.h + */ +#define SET_FLASH_STATUS(_bitmap, _status) (_bitmap |= (_status & 0xffff)) +#define CLR_FLASH_STATUS(_bitmap, _status) (_bitmap &= ~(_status & 0xffff)) +#define SET_FLASH_ERROR(_bitmap, _status) (_bitmap |= (_status << 16)) +#define CLR_FLASH_ERROR(_bitmap, _status) (_bitmap &= ~(_status << 16)) +#define GET_FLASH_STATUS(_bitmap) (_bitmap & 0xffff) +#define GET_FLASH_ERROR(_bitmap) (_bitmap >> 16) + +struct flash_mode_params { + unsigned long duration_uSecs; + unsigned long intensity_uAmp; + unsigned long timeout_uSecs; +}; + +struct flash_ioctl_args_t { + unsigned long flash_mode; + unsigned long cam; + unsigned long status; + union mode_arg{ + struct flash_mode_details details; + struct flash_mode_params params; + unsigned long strobe_enable; + } mode_arg; +}; + +#define FLASH_MAGIC_NUMBER 0x17 +#define FLASH_GET_MODES _IOR(FLASH_MAGIC_NUMBER, 1,\ +struct flash_ioctl_args_t *) +#define FLASH_GET_MODE_DETAILS _IOWR(FLASH_MAGIC_NUMBER, 2,\ +struct flash_ioctl_args_t *) +#define FLASH_ENABLE_MODE _IOW(FLASH_MAGIC_NUMBER, 3,\ +struct flash_ioctl_args_t *) +#define FLASH_DISABLE_MODE _IOW(FLASH_MAGIC_NUMBER, 4,\ +struct flash_ioctl_args_t *) +#define FLASH_CONFIGURE_MODE _IOW(FLASH_MAGIC_NUMBER, 5,\ +struct flash_ioctl_args_t *) +#define FLASH_TRIGGER_STROBE _IOW(FLASH_MAGIC_NUMBER, 6,\ +struct flash_ioctl_args_t *) +#define FLASH_GET_STATUS _IOW(FLASH_MAGIC_NUMBER, 7,\ +struct flash_ioctl_args_t *) +#define FLASH_GET_LIFE_COUNTER _IOW(FLASH_MAGIC_NUMBER, 8,\ +struct flash_ioctl_args_t *) +#define FLASH_GET_SELF_TEST_MODES _IOR(FLASH_MAGIC_NUMBER, 9,\ +struct flash_ioctl_args_t *) +#define FLASH_SELF_TEST _IOW(FLASH_MAGIC_NUMBER, 10,\ +struct flash_ioctl_args_t *) +#define FLASH_GET_FAULT_REGISTERS _IOR(FLASH_MAGIC_NUMBER, 11,\ +struct flash_ioctl_args_t *) +#define FLASH_GET_SELF_TEST_RESULT _IOR(FLASH_MAGIC_NUMBER, 12,\ +struct flash_ioctl_args_t *) + +#endif diff --git a/drivers/staging/camera_flash/camera_flash_bitfields.h b/drivers/staging/camera_flash/camera_flash_bitfields.h new file mode 100644 index 00000000000..05da9c5ef58 --- /dev/null +++ b/drivers/staging/camera_flash/camera_flash_bitfields.h @@ -0,0 +1,83 @@ +/* + * 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. + */ +/** +* \file camera_flash_bitfields.h +* \brief Define some constants for the flash drivers API. +* \author ST-Ericsson +*/ +#ifndef __CAMERA_FLASH_BITFIELDS_H__ +#define __CAMERA_FLASH_BITFIELDS_H__ + +/* Flash Mode definitions */ +/* All Operating Modes are off (shutdown low power state)*/ +#define FLASH_MODE_NONE (0x000) +/* Enables the xenon driver. Strobe is managed by the flash driver itself. +Charges the xenon. Automatic periodic recharge is abstracted by the driver */ +#define FLASH_MODE_XENON (0x001) +/* Enables the xenon driver. Strobe is managed externally to the driver */ +#define FLASH_MODE_XENON_EXTERNAL_STROBE (0x002) +/* Enables the video led driver. Strobing is managed by the driver */ +#define FLASH_MODE_VIDEO_LED (0x004) +/* Enables the video led driver. Strobing is managed externally to driver */ +#define FLASH_MODE_VIDEO_LED_EXTERNAL_STROBE (0x008) +/* Enables the still LED driver. Strobing is managed by the driver itself */ +#define FLASH_MODE_STILL_LED (0x010) +/* Enables the still LED driver. Strobe is managed externally to the driver */ +#define FLASH_MODE_STILL_LED_EXTERNAL_STROBE (0x020) +/* Enables the AF assistant driver. Strobe is managed by the driver */ +#define FLASH_MODE_AF_ASSISTANT (0x040) +/* Enable the driver. Strobe is managed by the driver */ +#define FLASH_MODE_INDICATOR (0x080) +/* Enables the still HP LED driver. Strobing is managed by the driver itself */ +#define FLASH_MODE_STILL_HPLED (0x100) +/* Enables the still HP LED driver. Strobe is managed externally to the +driver */ +#define FLASH_MODE_STILL_HPLED_EXTERNAL_STROBE (0x200) + + +/* The flash is not usable anymore */ +#define FLASH_STATUS_BROKEN (0x00) +/* The flash is ready to be fired and unlit */ +#define FLASH_STATUS_READY (0x01) +/* The flash is discharged and by construction, charging; usually an +application shall not try to fire it in that state (although possible +typically in sport mode flash) */ +#define FLASH_STATUS_NOT_READY (0x02) +/* The flash is in shutdown state */ +#define FLASH_STATUS_SHUTDOWN (0x04) +/* Intermediate state that may exist where I2C registers can be programmed */ +#define FLASH_STATUS_STANDBY (0x08) +/* The flash is already strobing */ +#define FLASH_STATUS_LIT (0x10) + +#define FLASH_SELFTEST_NONE 0x000 +/* tests connections to flash driver ICs */ +#define FLASH_SELFTEST_CONNECTION 0x001 +/* tests capture flash without using strobe signal from camera */ +#define FLASH_SELFTEST_FLASH 0x002 +/* tests capture flash using strobe signal from camera: ONLY this one needs to +be done in idle state from flash tests cases */ +#define FLASH_SELFTEST_FLASH_WITH_STROBE 0x004 +/* tests video light */ +#define FLASH_SELFTEST_VIDEO_LIGHT 0x008 +/* tests AF assistance light */ +#define FLASH_SELFTEST_AF_LIGHT 0x010 +/* tests capture indicator light */ +#define FLASH_SELFTEST_INDICATOR 0x020 +/* tests flash in torch mode */ +#define FLASH_SELFTEST_TORCH_LIGHT 0x040 + +/** \brief Flash Error */ +enum TFlashError { + FLASH_ERR_NONE , /* None */ + FLASH_ERR_OVER_CHARGE , /* Error happened during the charge */ + FLASH_ERR_OVER_HEAT , /* Over temperature */ + FLASH_ERR_SHORT_CIRCUIT , /* Short circuit */ + FLASH_ERR_TIMEOUT , /* Timeout */ + FLASH_ERR_OVER_VOLTAGE /* Over voltage */ +} ; + +#endif diff --git a/drivers/staging/camera_flash/flash_common.c b/drivers/staging/camera_flash/flash_common.c new file mode 100644 index 00000000000..fc59879a170 --- /dev/null +++ b/drivers/staging/camera_flash/flash_common.c @@ -0,0 +1,460 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * camera flash: Flash driver to export camera flash to user space application. + * It supports two flashes, one for primary and one for secondary camera + * Author: Pankaj Chauhan/pankaj.chauhan@stericsson.com for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "camera_flash.h" +#include "flash_common.h" + +#define DEBUG_LOG(...) printk(KERN_DEBUG "Camera Flash driver: " __VA_ARGS__) + +#define PRIMARY_CAMERA (0) +#define SECONDARY_CAMERA (1) +static struct miscdevice misc_dev; +struct flash_chip *flash_chips[2]; +struct fasync_struct * async_queue; +struct task_struct* ptaskStruct; +wait_queue_head_t waitQueue; +int waitCondition = 0; +struct flash_ioctl_args_t flashArg; + +#define COPY_ARG_FROM_USER(_to,_from_usr) do{ \ + memset((_to),0,sizeof(struct flash_ioctl_args_t)); \ + if (copy_from_user((_to), (struct flash_ioctl_args_t*) (_from_usr), sizeof(struct flash_ioctl_args_t))) { \ + DEBUG_LOG("Could not copy data from userspace successfully\n"); \ + break; \ + } \ +}while(0) + +#define COPY_ARG_TO_USER(_to_usr,_from) do{ \ + if (copy_to_user((struct flash_ioctl_args_t *)(_to_usr), (_from), sizeof(struct flash_ioctl_args_t))) { \ + DEBUG_LOG("Could not copy data from userspace successfully\n"); \ + break; \ + } \ +}while(0) + + +static long flash_ioctl(struct file *file_p, unsigned int cmd, unsigned long arg) +{ + int err=0; + struct flash_chip *flash_p = NULL; + struct flash_chip_ops *ops = NULL; + char *my_name=NULL; + struct flash_ioctl_args_t flash_arg; + + if (_IOC_TYPE(cmd) != FLASH_MAGIC_NUMBER) { + printk(KERN_ALERT "Flash driver: Not an ioctl for this module\n"); + err = -EINVAL; + } + + COPY_ARG_FROM_USER(&flash_arg,arg); + + if(flash_arg.cam == SECONDARY_CAMERA || flash_arg.cam == PRIMARY_CAMERA) + flash_p = flash_chips[flash_arg.cam]; + else{ + DEBUG_LOG("unsupported cam %lu\n",flash_arg.cam); + err = -ENODEV; + goto out; + } + my_name = flash_arg.cam ?"Secondary":"Primary"; + + if (flash_arg.cam == PRIMARY_CAMERA) + { + ops = flash_p->ops; + } + + switch(cmd){ + case FLASH_GET_MODES: + { + if (flash_arg.cam == PRIMARY_CAMERA) + { + err = ops->get_modes(flash_p->priv_data,&flash_arg.flash_mode); + if(!err){ + DEBUG_LOG("Supported flash modes for %s camera: %lx\n", + my_name,flash_arg.flash_mode); + COPY_ARG_TO_USER(arg,&flash_arg); + }else{ + DEBUG_LOG("unable to get supported modes for %s camera\n",my_name); + } + } + else + { + flash_arg.flash_mode = FLASH_MODE_NONE; + COPY_ARG_TO_USER(arg,&flash_arg); + } + } + break; + case FLASH_GET_MODE_DETAILS: + { + err = ops->get_mode_details(flash_p->priv_data,flash_arg.flash_mode, + &flash_arg.mode_arg.details); + if(!err){ + COPY_ARG_TO_USER(arg,&flash_arg); + }else{ + DEBUG_LOG("Unable to get mode details for %s camera, flash mode %lx\n", + my_name,flash_arg.flash_mode); + } + } + break; + case FLASH_ENABLE_MODE: + case FLASH_DISABLE_MODE: + { + int enable=0; + if(cmd == FLASH_ENABLE_MODE){ + enable = 1; + } + err = ops->enable_flash_mode(flash_p->priv_data,flash_arg.flash_mode,enable); + if(err){ + DEBUG_LOG("Unable to %s: %s camera, flash mode %lx\n", + (enable ?"Enable":"Disable"), my_name,flash_arg.flash_mode); + } + } + break; + case FLASH_CONFIGURE_MODE: + err = ops->configure_flash_mode(flash_p->priv_data,flash_arg.flash_mode, + &flash_arg.mode_arg.params); + if(err){ + DEBUG_LOG("Unable to configure %s camera, flash mode %lx\n", + my_name,flash_arg.flash_mode); + } + break; + case FLASH_TRIGGER_STROBE: + err = ops->trigger_strobe(flash_p->priv_data,flash_arg.mode_arg.strobe_enable); + if(err){ + DEBUG_LOG("Unable to %s: %s camera strobe trigger, mode %lx\n", + (arg ?"Enable":"Disable"), my_name,flash_arg.flash_mode); + } + break; + case FLASH_GET_STATUS: + err = ops->get_status(flash_p->priv_data,&flash_arg.status); + if(!err){ + COPY_ARG_TO_USER(arg,&flash_arg); + }else{ + DEBUG_LOG("Unable to get status details for %s camera, flash mode %lx\n", + my_name,flash_arg.flash_mode); + } + break; + case FLASH_GET_LIFE_COUNTER: + DEBUG_LOG("Not Implemented\n"); + break; + case FLASH_SELF_TEST: + flashArg = flash_arg; + if (0 != (flashArg.cam & (FLASH_SELFTEST_FLASH | FLASH_SELFTEST_FLASH_WITH_STROBE))) + { + err = ENODEV; + } + else + { + /* wake up worker thread */ + waitCondition = 1; + wake_up_interruptible(&waitQueue); + } + break; + case FLASH_GET_SELF_TEST_MODES: + { + if (flash_arg.cam == PRIMARY_CAMERA) + { + err = ops->get_selftest_modes(flash_p->priv_data,&flash_arg.flash_mode); + if(!err){ + COPY_ARG_TO_USER(arg,&flash_arg); + }else{ + DEBUG_LOG("unable to get supported modes for %s camera\n",my_name); + } + } + else + { + flash_arg.flash_mode = FLASH_SELFTEST_NONE; + COPY_ARG_TO_USER(arg,&flash_arg); + } + break; + } + case FLASH_GET_FAULT_REGISTERS: + { + err = ops->get_fault_registers(flash_p->priv_data,flash_arg.flash_mode,&flash_arg.status); + if(!err){ + COPY_ARG_TO_USER(arg,&flash_arg); + }else{ + DEBUG_LOG("unable to get supported modes for %s camera\n",my_name); + } + + break; + } + case FLASH_GET_SELF_TEST_RESULT: + { + COPY_ARG_TO_USER(arg,&flashArg); + DEBUG_LOG("FLASH_GET_SELF_TEST_RESULT arg : 0x%lx\n", flashArg.status); + break; + } + default: + DEBUG_LOG("Unknown command %x\n",cmd); + + } +out: + return err; +} + +int worker_thread (void* data) +{ + int err = 0; + struct flash_chip *flash_p=NULL; + struct flash_chip_ops *ops=NULL; + struct flash_mode_params params; + struct flash_mode_details details; + + while (1) + { + /* waiting for some job to do */ + wait_event_interruptible(waitQueue, (waitCondition != 0)); + waitCondition = 0; + + DEBUG_LOG("worker_thread wakes up\n"); + /* do we need to stop ? */ + err = kthread_should_stop(); + if (0 != err) + { + DEBUG_LOG("worker_thread stops\n"); + break; + } + + /* do the job */ + flash_p = flash_chips[flashArg.cam]; + ops = flash_p->ops; + + /* clear fault registers */ + err = ops->get_fault_registers(flash_p->priv_data, FLASH_MODE_INDICATOR, &flashArg.status); + if (0 != err) + { + flashArg.status = flashArg.flash_mode; + flashArg.flash_mode = 0; + } + flashArg.status = 0; + + /* do all selftests */ + while (flashArg.flash_mode != FLASH_SELFTEST_NONE) + { + if (0 != (flashArg.flash_mode & FLASH_SELFTEST_CONNECTION)) + { + err = ops->get_mode_details(flash_p->priv_data, FLASH_MODE_INDICATOR, &details); + if (0 != err) + { + DEBUG_LOG("not able to get mode FLASH_MODE_INDICATOR details\n"); + flashArg.status |= FLASH_SELFTEST_CONNECTION; + } + flashArg.flash_mode &= ~FLASH_SELFTEST_CONNECTION; + } + else if (0 != (flashArg.flash_mode & (FLASH_SELFTEST_FLASH | FLASH_SELFTEST_FLASH_WITH_STROBE))) + { + if (0 != (flashArg.flash_mode & FLASH_SELFTEST_FLASH)) + { + flashArg.status |= FLASH_SELFTEST_FLASH; + flashArg.flash_mode &= ~FLASH_SELFTEST_FLASH; + } + else + { + flashArg.status |= FLASH_SELFTEST_FLASH_WITH_STROBE; + flashArg.flash_mode &= ~FLASH_SELFTEST_FLASH_WITH_STROBE; + } + } + /* FLASH_SELFTEST_VIDEO_LIGHT | FLASH_SELFTEST_AF_LIGHT | FLASH_SELFTEST_INDICATOR | FLASH_SELFTEST_TORCH_LIGHT */ + else + { + unsigned long currentSelftest = FLASH_SELFTEST_NONE; + unsigned long currentFlashMode = FLASH_MODE_NONE; + + if (0 != (flashArg.flash_mode & FLASH_SELFTEST_VIDEO_LIGHT)) + { + currentSelftest = FLASH_SELFTEST_VIDEO_LIGHT; + currentFlashMode = FLASH_MODE_VIDEO_LED; + } + else if (0 != (flashArg.flash_mode & FLASH_SELFTEST_AF_LIGHT)) + { + currentSelftest = FLASH_SELFTEST_AF_LIGHT; + currentFlashMode = FLASH_MODE_AF_ASSISTANT; + } + else if (0 != (flashArg.flash_mode & FLASH_SELFTEST_INDICATOR)) + { + currentSelftest = FLASH_SELFTEST_INDICATOR; + currentFlashMode = FLASH_MODE_INDICATOR; + } + else + { + currentSelftest = FLASH_SELFTEST_TORCH_LIGHT; + currentFlashMode = FLASH_MODE_VIDEO_LED; + } + + err = ops->get_mode_details(flash_p->priv_data, currentFlashMode, &details); + if (0 != err) + { + DEBUG_LOG("not able to get mode 0x%lx details\n",currentFlashMode); + flashArg.status |= currentSelftest; + flashArg.flash_mode &= ~currentSelftest; + continue; + } + + err = ops->enable_flash_mode(flash_p->priv_data, currentFlashMode, 1); + if (0 != err) + { + DEBUG_LOG("not able to enable flash mode 0x%lx\n",currentFlashMode); + flashArg.status |= currentSelftest; + flashArg.flash_mode &= ~currentSelftest; + continue; + } + + params.duration_uSecs = 0; + params.intensity_uAmp = details.max_intensity_uAmp; + params.timeout_uSecs = 0; + err = ops->configure_flash_mode(flash_p->priv_data, currentFlashMode, ¶ms); + if (0 != err) + { + DEBUG_LOG("not able to configure flash mode 0x%lx\n",currentFlashMode); + flashArg.status |= currentSelftest; + flashArg.flash_mode &= ~currentSelftest; + continue; + } + + err = ops->trigger_strobe(flash_p->priv_data,1); + if (0 != err) + { + DEBUG_LOG("not able to strobe, mode : 0x%lx\n",currentFlashMode); + flashArg.status |= currentSelftest; + flashArg.flash_mode &= ~currentSelftest; + continue; + } + + wait_event_timeout(waitQueue, 0, msecs_to_jiffies(1000)); + + err = ops->trigger_strobe(flash_p->priv_data,0); + if (0 != err) + { + DEBUG_LOG("not able to strobe, mode : 0x%lx\n",currentFlashMode); + flashArg.status |= currentSelftest; + flashArg.flash_mode &= ~currentSelftest; + continue; + } + flashArg.flash_mode &= ~currentSelftest; + } + } + + /* job's done ! */ + flash_async_notify(); + } + return 0; +} + +int flash_open(struct inode *node, struct file *file_p) +{ + // init sleep queue + init_waitqueue_head(&waitQueue); + + // start worker thread + ptaskStruct = kthread_run (&worker_thread, NULL, "flashDriverWorker"); + + return 0; +} + +int register_flash_chip(unsigned int cam, struct flash_chip *flash_p) +{ + int err =0; + DEBUG_LOG("Registering cam %d\n", cam); + DEBUG_LOG("flash_p: name=%s\n", flash_p->name); + if(cam > 1 || !flash_p){ + DEBUG_LOG("Registration: something is wrong! cam %d, flash_p %x \n",cam,(int)flash_p); + err = EINVAL; + goto out; + } + if(!flash_chips[cam]){ + flash_chips[cam] = flash_p; + DEBUG_LOG("Registered flash: id %lx, %s for camera %d\n", + flash_p->id,flash_p->name,cam); + }else{ + DEBUG_LOG("%s flash already registered for camera %d, ignore flash %s\n", + flash_chips[cam]->name,cam, flash_p->name); + } +out: + return err; +} + +int flash_async_notify () +{ + kill_fasync(&async_queue, SIGIO, POLL_IN); + return 0; +} + +static int flash_fasync(int fd, struct file *filp, int mode) +{ + DEBUG_LOG("registered async notification on %d fd\n",fd); + return fasync_helper(fd, filp, mode, &async_queue); +} + +static int flash_release(struct inode *node, struct file *file_p) +{ + int err = 0; + + fasync_helper(-1, file_p, 0, &async_queue); + + // stop worker thread + waitCondition = 1; + err = kthread_stop(ptaskStruct); + return err; +} + +static struct file_operations flash_fops = { + owner:THIS_MODULE, + unlocked_ioctl:flash_ioctl, + open:flash_open, + release:flash_release, + fasync:flash_fasync, +}; + +int major_device_number; + +/*Temporary here (adp_init)*/ +extern int adp1653_init(void); +static int __init flash_init(void) +{ + int err = 0; + err = adp1653_init(); + if(err){ + DEBUG_LOG("Unable to initialize adp1653, err %d\n",err); + goto out; + } + /* Register misc device */ + misc_dev.minor = MISC_DYNAMIC_MINOR; + misc_dev.name = "camera_flash"; + misc_dev.fops = &flash_fops; + err = misc_register(&misc_dev); + if (err < 0) { + printk(KERN_INFO "camera_flash driver misc_register failed (%d)\n", err); + return err; + } else { + major_device_number = err; + printk(KERN_INFO "camera_flash driver initialized with minor=%d\n", misc_dev.minor); + } +out: + return err; +} + +static void __exit flash_exit(void) +{ + misc_deregister(&misc_dev); + printk(KERN_INFO"Camera flash driver unregistered\n"); +} + +module_init(flash_init); +module_exit(flash_exit); +MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(register_flash_chip); +EXPORT_SYMBOL(flash_async_notify); diff --git a/drivers/staging/camera_flash/flash_common.h b/drivers/staging/camera_flash/flash_common.h new file mode 100755 index 00000000000..1153badddd1 --- /dev/null +++ b/drivers/staging/camera_flash/flash_common.h @@ -0,0 +1,56 @@ +#ifndef __FLASH_COMMON_H__ +#define __FLASH_COMMON_H__ + +#include "camera_flash_bitfields.h" + +struct flash_chip_ops{ + int (*get_modes)( void *priv_data, unsigned long *modes); + int (*get_mode_details)(void *priv_data,unsigned long mode, + struct flash_mode_details *details_p); + int (*enable_flash_mode) (void *priv_data,unsigned long mode, + int enable); + int (*configure_flash_mode) (void *priv_data, unsigned long mode, + struct flash_mode_params *params_p); + int (*trigger_strobe) (void *priv_data, int enable); + int (*get_life_counter) (void *priv_data); + int (*get_status) (void *priv_data, unsigned long *status); + int (*get_selftest_modes) (void *priv_data, + unsigned long *modes); + int (*get_fault_registers) (void *priv_data, unsigned long mode, + unsigned long *status); +}; + +#define FLASH_TYPE_XENON (0x1) +#define FLASH_TYPE_HPLED (0x2) + +#define SET_FLASHCHIP_TYPE(flash_chip_p,_TYPE) ((flash_chip_p)->id |= _TYPE) +#define GET_FLASHHIP_TYPE(flash_chip_p) ((flash_chip_p)->id & 0xffff) +#define GET_FLASHCHIP_ID(flash_chip_p) ((flash_chip_p)->id >> 16) +#define SET_FLASHCHIP_ID(flash_chip_p,_ID) ((flash_chip_p)->id |= (_ID << 16)) + +struct flash_chip { + unsigned long id; + struct flash_chip_ops *ops; + void *priv_data; + unsigned char name[FLASH_NAME_SIZE]; +}; + +/** + * struct flash_platform_data: + * platform specific data For flash chip driver + * @cam : 0 - primary, 1 - secondary + * @strobe_gpio: GPIO used as strobe + * @enable_gpio: GPIO used for enable/reset input + */ +struct flash_platform_data{ + unsigned long cam; + unsigned long strobe_gpio; + unsigned long strobe_gpio_alt_func; + unsigned long enable_gpio; + unsigned long enable_gpio_alt_func; +}; + +extern int register_flash_chip(unsigned int cam, struct flash_chip *flash_p); +extern int flash_async_notify (void ); + +#endif diff --git a/drivers/staging/nmf-cm/Kconfig b/drivers/staging/nmf-cm/Kconfig new file mode 100644 index 00000000000..9545fd5acd1 --- /dev/null +++ b/drivers/staging/nmf-cm/Kconfig @@ -0,0 +1,12 @@ + +config U8500_CM + tristate "U8500 Component Manager driver" + depends on UX500_SOC_DB8500 + help + This is the Component Manager driver. It is part of the + Nomadik Multiprocessing Framework. + + Note: This option allows the kernel developers to build + the driver in kernel to ease there life. By default, this driver + must be built outside this kernel source tree. + diff --git a/drivers/staging/nmf-cm/Make.config b/drivers/staging/nmf-cm/Make.config new file mode 100644 index 00000000000..ccbc150158b --- /dev/null +++ b/drivers/staging/nmf-cm/Make.config @@ -0,0 +1,8 @@ +# Copyright (C) ST-Ericsson SA 2011. All rights reserved. +# This code is ST-Ericsson proprietary and confidential. +# Any use of the code for whatever purpose is subject to +# specific written permission of ST-Ericsson SA. + +#CM driver file to copy but not to compile +CMENGINESRC_COPY_NO_BUILD = cm/engine/elf/src/elfxx.c + diff --git a/drivers/staging/nmf-cm/Makefile b/drivers/staging/nmf-cm/Makefile new file mode 100644 index 00000000000..82fa97f81d1 --- /dev/null +++ b/drivers/staging/nmf-cm/Makefile @@ -0,0 +1,99 @@ +# +# Copyright (C) ST-Ericsson SA 2010 +# Author: Pierre Peiffer for ST-Ericsson. +# License terms: GNU General Public License (GPL), version 2. +# + +# +# Rules to build kernel modules +# +ifndef MM_MAKEFILES_DIR + + # $(src): current relative dir; $(kbuild-dir): cur absolute dir + ifdef kbuild-dir + SRCDIR = $(realpath $(kbuild-dir)) + else + SRCDIR = $(realpath $(src)) + endif + include $(SRCDIR)/Make.config + ifndef FIXED_CPPFLAGS + # In Android env, we can not depend on files that are out of kernel tree. + # and thus we can't include $(SRCDIR)/../../../../mmenv/SharedARMFlags.mk + # where FIXED_CPPFLAGS is defined. + # So, define FIXED_CPPFLAGS here + FIXED_CPPFLAGS=-D__STN_8500=30 -DLINUX -D__ARM_LINUX + endif + EXTRA_CFLAGS := -I$(SRCDIR) $(FIXED_CPPFLAGS) + EXTRA_CFLAGS += -Wall -Werror + #EXTRA_CFLAGS += -DCM_DEBUG_ALLOC + + # + # CM object files to compile with + # + GENERIC_CM_FILES:=$(shell cd $(SRCDIR); find cm -name "*.c") + GENERIC_CM_FILES := $(filter-out $(CMENGINESRC_COPY_NO_BUILD), $(GENERIC_CM_FILES)) + + CM_OBJS := $(GENERIC_CM_FILES:.c=.o) + CM_OBJS += cmld.o cm_syscall.o osal-kernel.o cm_service.o configuration.o + CM_OBJS += cm_dma.o + + obj-$(CONFIG_U8500_CM) := cm.o + + #Note: build system prepends the $(PWD) directory to these objects paths + cm-objs := $(CM_OBJS) + +else + + # CM module is built in kernel in android env + # or as module otherwise (OSI env, ...) + export CONFIG_U8500_CM ?= m + + ifeq ($(findstring install,$(MAKECMDGOALS)),) + # If not only performing install then include needed files for build + include $(MM_MAKEFILES_DIR)/SharedARMFlags.mk + export FIXED_CPPFLAGS + -include $(MM_MAKEFILES_DIR)/KernelConfig.mk + + ifeq ($(findstring clean,$(MAKECMDGOALS)),) + ifndef KERNEL_BUILD_DIR + $(error KERNEL_BUILD_DIR not defined) + endif + endif + endif + + include $(MM_MAKEFILES_DIR)/SharedConfig.mk + + module: + $(MAKE) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNEL_BUILD_DIR) \ + M=$(PWD) INSTALL_HEADER_DIR=$(INSTALL_HEADER_DIR) \ + modules + + all: module + $(MAKE) ARCH=arm CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNEL_BUILD_DIR) \ + M=$(PWD) INSTALL_HEADER_DIR=$(INSTALL_HEADER_DIR) \ + INSTALL_MOD_PATH=$(PWD)/lib/$(PLATFORM) \ + modules_install + rm -f $(PWD)/lib/$(PLATFORM)/lib/modules/*/modules.* + + # + # Rules to clean and install + # + clean: + @rm -rf $(PLATFORM) $(CM_OBJS) .built-in.o.cmd .cm*o.cmd Module.symvers \ + .tmp_versions modules.order cm.ko cm.o cm.mod.* lib \ + $(foreach f,$(CM_OBJS), $(dir $f).$(notdir $f).cmd) + + realclean: clean + $(foreach platform, \ + $(shell grep property ../../component/component.xml | cut -d\" -f 4), \ + rm -rf $(platform);) + @rm -rf *~ + + install: + $(GEN_LN) -d lib/$(PLATFORM)/lib $(INSTALL_LIB_DIR)/lib + + uninstall: + $(GEN_LN) -r -d lib/$(PLATFORM)/lib $(INSTALL_LIB_DIR)/lib + +endif #ifdef KERNELRELEASE + diff --git a/drivers/staging/nmf-cm/cm/engine/api/channel_engine.h b/drivers/staging/nmf-cm/cm/engine/api/channel_engine.h new file mode 100644 index 00000000000..19353ee7328 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/channel_engine.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief Communication Component Manager internal API type. + */ + +#ifndef CHANNEL_ENGINE_H +#define CHANNEL_ENGINE_H + +#include +#include +#include + +/*! + * \brief Internal channel identification. + * + * Same as t_nmf_channel meaning but this the channel used internaly by + * OS Integration part + * + * \ingroup CM_OS_API + */ +typedef t_uint32 t_os_channel; + +/*! + * \brief Invalid value for os_channel + * + * Invalid value for os channel. + * + * \ingroup CM_OS_API + */ +#define NMF_OS_CHANNEL_INVALID_HANDLE 0xffffffff + +/*! + * \brief Structure used for storing required parameters for Interface Callback + * messages. + * + * This struture is used internally by CM_GetMessage() and CM_ExecuteMessage() as + * the message content in the given buffer. + * + * \ingroup CM_ENGINE_API + */ +typedef struct { + t_nmf_mpc2host_handle THIS; //!< Context of interface implementation + t_uint32 methodIndex; //!< Method index in interface + char params[1]; //!< Is of variable length concretely +} t_interface_data; + +/*! + * \brief Structure used for storing required parameters for Service Callback + * messages. + * + * This struture is used internally by CM_GetMessage() and CM_ExecuteMessage() as + * the message content in the given buffer. + * + * \ingroup CM_ENGINE_API + */ +typedef struct { + t_nmf_service_type type; //!< Type of the service message + t_nmf_service_data data; +} t_service_data; + +typedef enum { + MSG_INTERFACE, + MSG_SERVICE +} t_message_type; + +/*! + * \brief Structure used for storing required parameters for the internal NMF + * messages. + * + * This struture is used internally by CM_GetMessage() and CM_ExecuteMessage() as + * the message content in the given buffer. + * + * \ingroup CM_ENGINE_API + */ +typedef struct { + t_message_type type; //!< Type of the nmf message + union { + t_interface_data itf; + t_service_data srv; + } data; +} t_os_message; + +/*! + * \brief Structure used for storing required parameters for the internal NMF + * messages. + * + * This struture is used internally by CM_GetMessage() and CM_ExecuteMessage() as + * the message content in the given buffer. + * + * \ingroup CM_ENGINE_API + */ +typedef struct { + t_nmf_channel channel; //!< Channel (required to handle service message) + t_os_message osMsg; +} t_nmf_message; + +#endif /* CHANNEL_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/api/cm_engine.h b/drivers/staging/nmf-cm/cm/engine/api/cm_engine.h new file mode 100644 index 00000000000..0f4c1e4219e --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/cm_engine.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief CM Engine API. + * + * This file contains the Component Manager Engine API. + */ + +/*! + * \defgroup CM_ENGINE_MODULE CM Engine + */ +/*! + * \defgroup CM_ENGINE_API CM Engine API + * + * \note This API is not for user developers, this API is only an internal API. + * + * \warning All parameters in out from this API means that the parameter is a reference to a data that is complete by the call. + * + * This API is provided by CM Engine and shall be required by driver kernel part. + * \ingroup CM_ENGINE_MODULE + */ + +#ifndef CM_ENGINE_H_ +#define CM_ENGINE_H_ + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +#endif /*CM_ENGINE_H_*/ + diff --git a/drivers/staging/nmf-cm/cm/engine/api/communication_engine.h b/drivers/staging/nmf-cm/cm/engine/api/communication_engine.h new file mode 100644 index 00000000000..477a66a4002 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/communication_engine.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief Communication User Engine API. + * + * This file contains the Communication Engine API for manipulating components. + * + */ +#ifndef COMMUNICATION_ENGINE_H_ +#define COMMUNICATION_ENGINE_H_ + +#include + +/*! + * \brief Allocate Event buffer where parameters will be marshalled. + * + * In order to optimize call, this method don't need to be exported to user space, + * but must be used by CM driver. + * + * See \ref HOST2MPC "Host->MPC binding" for seeing an integration example. + * + * \note This method is not called from user space!!! + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_event_params_handle CM_ENGINE_AllocEvent(t_cm_bf_host2mpc_handle host2mpcId); + +/*! + * \brief Push a event in Fifo. + * + * In order to optimize call, this method don't need to be exported to user space, + * but must be used by CM driver. + * + * See \ref HOST2MPC "Host->MPC binding" for seeing an integration example. + * + * \note This method is not called from user space!!! + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_PushEvent(t_cm_bf_host2mpc_handle host2mpcId, t_event_params_handle h, t_uint32 methodIndex); + +/*! + * \brief Push a event in Fifo. + * + * In order to optimize call, this method need to be exported to user space + * and must be implemented by CM driver. + * + * See \ref HOST2MPC "Host->MPC binding" for seeing an integration example. + * + * \note No implementation of this method is provided in kernel CM engine!!! + * + * \ingroup CM_ENGINE_API + */ +PUBLIC t_cm_error CM_ENGINE_PushEventWithSize(t_cm_bf_host2mpc_handle host2mpcId, t_event_params_handle h, t_uint32 size, t_uint32 methodIndex); + +/*! + * \brief Aknowledge a Fifo that the received event has been demarshalled. + * + * In order to optimize call, this method don't need to be exported to user space, + * but must be used by CM driver. + * + * See \ref MPC2HOST "MPC->Host binding" for seeing an integration example. + * + * \note This method is not called from user space!!! + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED void CM_ENGINE_AcknowledgeEvent(t_cm_bf_mpc2host_handle mpc2hostId); + +#endif /*COMMUNICATION_ENGINE_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/api/component_engine.h b/drivers/staging/nmf-cm/cm/engine/api/component_engine.h new file mode 100644 index 00000000000..cbd61769597 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/component_engine.h @@ -0,0 +1,403 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief Components Component Manager User Engine API. + * + * This file contains the Component Manager Engine API for manipulating components. + * + */ + +#ifndef COMPONENT_ENGINE_H_ +#define COMPONENT_ENGINE_H_ + +#include +#include +#include +#include + +/*! + * \brief Instantiate a new component. + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_InstantiateComponent( + const char templateName[MAX_TEMPLATE_NAME_LENGTH], //!< [in] Null terminated string (Max size=\ref MAX_TEMPLATE_NAME_LENGTH) + t_cm_domain_id domainId, //!< [in] Domain + t_nmf_client_id clientId, //!< [in] Client ID (aka PID) + t_nmf_ee_priority priority, //!< [in] Component priority + const char localName[MAX_COMPONENT_NAME_LENGTH], //!< [in] Null terminated string (Max size=\ref MAX_COMPONENT_NAME_LENGTH) + const char *dataFile, //!< [in] Optional reference on file where component is stored + t_cm_instance_handle *component //!< [out] component + ); + +/*! + * \brief Start a component. + * + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_StartComponent( + t_cm_instance_handle component, + t_nmf_client_id clientId); + +/*! + * \brief Stop a component. + * + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_StopComponent( + t_cm_instance_handle component, + t_nmf_client_id clientId); + +/*! + * \brief Destroy a component. + * + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_DestroyComponent( + t_cm_instance_handle component, + t_nmf_client_id clientId); + +/*! + * \brief Stop and destroy all components belonging to the given client. + * + * \param[in] client + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_FlushComponents( + t_nmf_client_id client); + +/*! + * \brief Bind two components together. + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_BindComponent( + const t_cm_instance_handle client, //!< + const char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH], //!< Null terminated string (Max size=\ref MAX_INTERFACE_NAME_LENGTH). + const t_cm_instance_handle server, //!< + const char providedItfServerName[MAX_INTERFACE_NAME_LENGTH], //!< Null terminated string (Max size=\ref MAX_INTERFACE_NAME_LENGTH). + t_bool traced, //!< FALSE for synchronous binding, TRUE for traced one + t_nmf_client_id clientId, //!< Client ID + const char *dataFileTrace //!< Component file data in case on traced (Note: could be null if file already in cache) + ); + +/*! + * \brief Unbind a component. + * + * \param[in] client + * \param[in] requiredItfClientName Null terminated string (Max size=\ref MAX_INTERFACE_NAME_LENGTH). + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_UnbindComponent( + const t_cm_instance_handle client, + const char * requiredItfClientName, + t_nmf_client_id clientId); + +/*! + * \brief Bind a component to void (silently ignore a call). + * + * \param[in] client + * \param[in] requiredItfClientName Null terminated string (Max size=\ref MAX_INTERFACE_NAME_LENGTH). + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_BindComponentToVoid( + const t_cm_instance_handle client, + const char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH], + t_nmf_client_id clientId); + +/*! + * \brief Bind two components together in an asynchronous way + * (the components can be on the same MPC or on two different MPC) + * + * \param[in] client + * \param[in] requiredItfClientName Null terminated string (Max size=\ref MAX_INTERFACE_NAME_LENGTH). + * \param[in] server + * \param[in] providedItfServerName Null terminated string (Max size=\ref MAX_INTERFACE_NAME_LENGTH). + * \param[in] fifosize + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_BindComponentAsynchronous( + const t_cm_instance_handle client, + const char * requiredItfClientName, + const t_cm_instance_handle server, + const char * providedItfServerName, + t_uint32 fifosize, + t_cm_mpc_memory_type eventMemType, + t_nmf_client_id clientId, + const char *dataFileSkeletonOrEvent, + const char *dataFileStub); + +/*! + * \brief Unbind a component previously binded asynchronously + * + * \param[in] client + * \param[in] requiredItfClientName Null terminated string (Max size=\ref MAX_INTERFACE_NAME_LENGTH). + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentAsynchronous( + const t_cm_instance_handle client, + const char * requiredItfClientName, + t_nmf_client_id clientId); + +/*! + * \brief Bind the Host to a component. + * + * \param[in] server + * \param[in] providedItfServerName Null terminated string (Max size=\ref MAX_INTERFACE_NAME_LENGTH). + * \param[in] fifosize + * \param[out] host2mpcId + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_BindComponentFromCMCore( + const t_cm_instance_handle server, + const char * providedItfServerName, + t_uint32 fifosize, + t_cm_mpc_memory_type eventMemType, + t_cm_bf_host2mpc_handle *host2mpcId, + t_nmf_client_id clientId, + const char *dataFileSkeleton); + +/*! + * \brief Unbind a component from the Host. + * + * \param[in] host2mpcId + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentFromCMCore( + t_cm_bf_host2mpc_handle host2mpcId); + +/*! + * \brief Bind a component to the Host, see \ref CM_ENGINE_BindComponentToCMCore. + * + * See \ref MPC2HOST "MPC->Host binding" for seeing an integration example. + * + * \note This method is not called from CM Proxy, its only there for wrapping purpose!!! + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_BindComponentToCMCore( + const t_cm_instance_handle client, + const char *requiredItfClientName, + t_uint32 fifosize, + t_nmf_mpc2host_handle upLayerThis, + const char *dataFileStub, + t_cm_bf_mpc2host_handle *mpc2hostId, + t_nmf_client_id clientId); + +/*! + * \brief Unbind a component to the Host, see \ref CM_ENGINE_UnbindComponentToCMCore. + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentToCMCore( + const t_cm_instance_handle client, + const char *requiredItfClientName, + t_nmf_mpc2host_handle *upLayerThis, + t_nmf_client_id clientId); + +/*! + * \brief Read a value on an attribute exported by a component instance. + * + * \param[in] component + * \param[in] attrName Null terminated string (Max size=\ref MAX_ATTRIBUTE_NAME_LENGTH). + * \param[out] value + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_ReadComponentAttribute( + const t_cm_instance_handle component, + const char* attrName, + t_uint24 *value); + +/*! + * \brief Get the older component. + * + * \param[in] client + * \param[out] headerComponent + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetComponentListHeader( + const t_nmf_client_id client, + t_cm_instance_handle *headerComponent); + +/*! + * \brief Get the next component. + * + * \param[in] client + * \param[in] prevComponent + * \param[out] nextComponent + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetComponentListNext( + const t_nmf_client_id client, + const t_cm_instance_handle prevComponent, + t_cm_instance_handle *nextComponent); + +/*! + * \brief Get a component description + * + * \param[in] component + * \param[in] templateNameLength + * \param[in] localNameLength + * \param[out] templateName Null terminated string (Size=templateNameLength, Max size=\ref MAX_TEMPLATE_NAME_LENGTH). + * \param[out] coreId + * \param[out] localName Null terminated string (Size=localNameLength, Max size=\ref MAX_COMPONENT_NAME_LENGTH). + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetComponentDescription( + const t_cm_instance_handle component, + char *templateName, + t_uint32 templateNameLength, + t_nmf_core_id *coreId, + char *localName, + t_uint32 localNameLength, + t_nmf_ee_priority *priority); + +/*! + * \brief Get number of interface required by a component. + * + * \param[in] component + * \param[out] numberRequiredInterfaces + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterfaceNumber( + const t_cm_instance_handle component, + t_uint8 *numberRequiredInterfaces); + +/*! + * \brief Return information about required interface. + * + * \param[in] component + * \param[in] index + * \param[in] itfNameLength + * \param[in] itfTypeLength + * \param[out] itfName Null terminated string (Size=itfNameLength, Max size=\ref MAX_INTERFACE_NAME_LENGTH). + * \param[out] itfType Null terminated string (Size=itfTypeLength, Max size=\ref MAX_INTERFACE_TYPE_NAME_LENGTH). + * \param[out] collectionSize + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterface( + const t_cm_instance_handle component, + const t_uint8 index, + char *itfName, + t_uint32 itfNameLength, + char *itfType, + t_uint32 itfTypeLength, + t_cm_require_state *requireState, + t_sint16 *collectionSize); + +/*! + * \brief Get the component binded to a required interface. + * + * \param[in] component + * \param[in] itfName Null terminated string (Max size=\ref MAX_INTERFACE_NAME_LENGTH). + * \param[in] serverItfNameLength + * \param[out] server + * \param[out] serverItfName Null terminated string (Size=serverItfNameLength, Max size=\ref MAX_INTERFACE_NAME_LENGTH). + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterfaceBinding( + const t_cm_instance_handle component, + const char *itfName, + t_cm_instance_handle *server, + char *serverItfName, + t_uint32 serverItfNameLength); + +/*! + * \brief Get number of interface provided by a component. + * + * \param[in] component + * \param[out] numberProvidedInterfaces + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetComponentProvidedInterfaceNumber( + const t_cm_instance_handle component, + t_uint8 *numberProvidedInterfaces); + +/*! + * \brief Return information about provided interface. + * + * \param[in] component + * \param[in] index + * \param[in] itfNameLength + * \param[in] itfTypeLength + * \param[out] itfName Null terminated string (Size=itfNameLength, Max size=\ref MAX_INTERFACE_NAME_LENGTH). + * \param[out] itfType Null terminated string (Size=itfTypeLength, Max size=\ref MAX_INTERFACE_TYPE_NAME_LENGTH). + * \param[out] collectionSize + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetComponentProvidedInterface( + const t_cm_instance_handle component, + const t_uint8 index, + char *itfName, + t_uint32 itfNameLength, + char *itfType, + t_uint32 itfTypeLength, + t_sint16 *collectionSize); + +/*! + * \brief Get number of properties of a component. + * + * \param[in] component + * \param[out] numberProperties + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetComponentPropertyNumber( + const t_cm_instance_handle component, + t_uint8 *numberProperties); + +/*! + * \brief Return the name of a property. + * + * \param[in] component + * \param[in] index + * \param[in] propertyNameLength + * \param[out] propertyName Null terminated string (Size=propertyNameLength, Max size=\ref MAX_PROPERTY_NAME_LENGTH). + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetComponentPropertyName( + const t_cm_instance_handle component, + const t_uint8 index, + char *propertyName, + t_uint32 propertyNameLength); + +/*! + * \brief Get property value of a component. + * + * \param[in] component + * \param[in] propertyName + * \param[in] propertyValueLength + * \param[out] propertyValue Null terminated string (Size=propertyValueLength, Max size=\ref MAX_PROPERTY_VALUE_LENGTH). + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetComponentPropertyValue( + const t_cm_instance_handle component, + const char *propertyName, + char *propertyValue, + t_uint32 propertyValueLength); + +#endif /*COMPONENT_ENGINE_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/api/configuration_engine.h b/drivers/staging/nmf-cm/cm/engine/api/configuration_engine.h new file mode 100644 index 00000000000..0336f62265e --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/configuration_engine.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief Configuration Component Manager User Engine API. + * + * This file contains the Configuration CM Engine API for manipulating CM. + * + */ + +#ifndef CONFIGURATION_ENGINE_H +#define CONFIGURATION_ENGINE_H + +#include + +/*! + * \brief Dynamically set some debug parameters of the CM + * + * \param[in] aCmdID The command for the parameter to update + * \param[in] aParam The actual value to set for the given command + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_SetMode(t_cm_cmd_id aCmdID, t_sint32 aParam); + +#endif /* CONFIGURATION_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/api/control/configuration_engine.h b/drivers/staging/nmf-cm/cm/engine/api/control/configuration_engine.h new file mode 100644 index 00000000000..a9543a2af39 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/control/configuration_engine.h @@ -0,0 +1,193 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief Configuration Component Manager User Engine API. + * + * This file contains the Configuration CM Engine API for manipulating CM. + */ + +#ifndef CONTROL_CONFIGURATION_ENGINE_H +#define CONTROL_CONFIGURATION_ENGINE_H + +#include +#include +#include + +/*****************************************************************************************/ +/* Component Manager dedicated (for Configuration purpose) structured types definition */ +/*****************************************************************************************/ + +/*! + * \brief Description of the Nomadik HW mapping configuration + * + * Describe the Nomadik mapping that is to say: + * - the ESRAM memory managed by the CM (The ESRAM address space SHALL BE declared as non cacheable, non bufferable inside host MMU table) + * - the mapping of the System HW Semaphore IP + * \ingroup CM_ENGINE_CONTROL_API + */ +typedef struct { + t_nmf_memory_segment esramDesc; //!< Description of the ESRAM memory mapping into Nomadik SOC + t_cm_system_address hwSemaphoresMappingBaseAddr; //!< Description of the System HW Semaphores IP mapping into Nomadik SOC +} t_nmf_hw_mapping_desc; + +/*! + * @defgroup t_nmf_nomadik_version t_nmf_nomadik_version + * \brief Description of the various supported Nomadik SOC version + * @{ + * \ingroup CM_ENGINE_CONTROL_API + */ +typedef t_uint8 t_nmf_nomadik_version; //!< Fake enumeration type +#define NOMADIK_8810 ((t_nmf_nomadik_version)0) //!< STn8810 chip (any cut) +#define NOMADIK_8815A0 ((t_nmf_nomadik_version)1) //!< STn8815 chip (cut A0) +#define NOMADIK_8815 ((t_nmf_nomadik_version)2) //!< STn8815 chip (other cuts) +#define NOMADIK_8820 ((t_nmf_nomadik_version)3) //!< STn8820 chip +#define NOMADIK_8500 ((t_nmf_nomadik_version)4) //!< STn8500 chip +/* @} */ + +/*! + * \brief Description of the configuration parameters of the Component Manager + * \ingroup CM_ENGINE_CONTROL_API + */ +typedef struct { + t_nmf_coms_location comsLocation; //!< Configure where CM Communications objects are put (see \ref t_nmf_coms_location) +} t_nmf_config_desc; + +/*! + * @defgroup t_nmf_power_ctx t_nmf_power_ctx + * \brief Definition of the CM-engine context + * + * OS integrator uses this value to known the context where the associated OSAL routine is called + * + * @{ + * \ingroup CM_ENGINE_CONTROL_API + */ + +typedef t_uint32 t_nmf_power_ctx; //!< Fake enumeration type +#define PWR_FLUSH_REQ_INTERRUPT_CTX ((t_nmf_power_ctx)0x00) //!< Interrupt context - called by \ref CM_ProcessMpcEvent +#define PWR_FLUSH_REQ_NORMAL_CTX ((t_nmf_power_ctx)0x01) //!< Normal context (CM user call) + +/* @} */ + + +/****************************************************************************************************************/ +/* Component Manager dedicated (for Media Processors Cores Configuration purpose) structured types definition */ +/****************************************************************************************************************/ +/*! + * @defgroup t_nmf_executive_engine_id t_nmf_executive_engine_id + * \brief Identification of the Media Processor Executive Engine to deploy + * @{ + * \ingroup CM_ENGINE_CONTROL_API + */ +typedef t_uint8 t_nmf_executive_engine_id; //!< Fake enumeration type +#define SYNCHRONOUS_EXECUTIVE_ENGINE ((t_nmf_executive_engine_id)0) //!< MPC Synchronous executive engine +#define HYBRID_EXECUTIVE_ENGINE ((t_nmf_executive_engine_id)1) //!< MPC Hybrid synchronous executive engine +/* @} */ + +/*! + * @defgroup t_nmf_semaphore_type_id t_nmf_semaphore_type_id + * \brief Definition of which type semaphore shall be used for the given Media Processor communication mechanism + * @{ + * \ingroup CM_ENGINE_CONTROL_API + */ +typedef t_uint8 t_nmf_semaphore_type_id; //!< Fake enumeration type +#define LOCAL_SEMAPHORES ((t_nmf_semaphore_type_id)0) //!< Embedded MMDSP macrocell semaphore, so CM_ProcessMpcEvent() shall be called under ISR connected to local MMDSP IRQ0 +#define SYSTEM_SEMAPHORES ((t_nmf_semaphore_type_id)1) //!< Shared system HW Semaphores, so CM_ProcessMpcEvent(ARM_CORE_ID) shall be called under ISR connected to shared HW Sem Host IRQ +/* @} */ + + +/*! + * \brief Opaque type for allocator, returned at CM configuration. + */ +typedef t_uint32 t_cfg_allocator_id; + +/********************************************************************************/ +/* Configuration Component Manager API prototypes */ +/********************************************************************************/ + +/*! + * \brief Initialisation part + * + * This routine initialize and configure the Component Manager. + * + * \param[in] pNmfHwMappingDesc hardware mapping description + * \param[in] pNmfConfigDesc NMF (mainly CM) Configuration description + * + * \exception TBD + * \return exception number. + * + * \warning The ESRAM address space SHALL BE declared as non cacheable, non bufferable inside host MMU table + * + * \ingroup CM_ENGINE_CONTROL_API + */ +PUBLIC t_cm_error CM_ENGINE_Init( + const t_nmf_hw_mapping_desc *pNmfHwMappingDesc, + const t_nmf_config_desc *pNmfConfigDesc + ); + + +/*! + * \brief Media Processor core initialisation part + * + * This routine configures a given Media Processor core + * + * \param[in] coreId Media Processor identifier + * \param[in] executiveEngineId Media Processor Executive Engine identifier + * \param[in] semaphoreTypeId Media Processor semaphores (to be used by communication mechanism) identifier + * \param[in] nbYramBanks is the number of tcm ram banks to reserved for y memory + * \param[in] mediaProcessorMappingBaseAddr Media Processor mapping into host CPU addressable space + * \param[in] commDomain Domain for allocating communication FIFOs + * \param[in] eeDomain Domain for EE instantiation + * \param[in] sdramCodeAllocId Allocator Id for the SDRAM Code segment + * \param[in] sdramDataAllocId Allocator Id for the SDRAM Data segment + * + * \exception TBD + * \return exception number. + * + * \warning The Media Processor mapping address space SHALL BE declared as non cacheable, non bufferable inside host MMU table + * + * \ingroup CM_ENGINE_CONTROL_API + */ +PUBLIC t_cm_error CM_ENGINE_ConfigureMediaProcessorCore( + t_nmf_core_id coreId, + t_nmf_executive_engine_id executiveEngineId, + t_nmf_semaphore_type_id semaphoreTypeId, + t_uint8 nbYramBanks, + const t_cm_system_address *mediaProcessorMappingBaseAddr, + const t_cm_domain_id eeDomain, + const t_cfg_allocator_id sdramCodeAllocId, + const t_cfg_allocator_id sdramDataAllocId + ); + +/*! + * \brief Configure a memory segment for later + * + * \exception TBD + * \return TBD + * + * \warning + * + * \ingroup CM_ENGINE_CONTROL_API + */ +PUBLIC t_cm_error CM_ENGINE_AddMpcSdramSegment( + const t_nmf_memory_segment *pDesc, //!< [in] Memory segment description. + t_cfg_allocator_id *allocId, //!< [out] Identifier of the created allocator. + const char *memoryname //!< [in] Memory purpose name + ); + +/********************************************************************************/ +/* Destruction Component Manager API prototypes */ +/********************************************************************************/ +/*! + * \brief Destruction part + * + * This routine destroyes and releases all resources used by the Component Manager. + * + * \ingroup CM_ENGINE_CONTROL_API + */ +PUBLIC void CM_ENGINE_Destroy(void); + + +#endif /* CONTROL_CONFIGURATION_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/api/control/control_engine.h b/drivers/staging/nmf-cm/cm/engine/api/control/control_engine.h new file mode 100644 index 00000000000..1d823b27fc1 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/control/control_engine.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief CM Engine API. + * + * This file contains the Component Manager Engine API. + */ +/*! + * \defgroup CM_ENGINE_CONTROL_API CM Engine Control API + * \note This API is not for OS integrator, it's only for low level system integration. + * \ingroup CM_ENGINE_MODULE + */ + +#ifndef CM_CONTROL_H_ +#define CM_CONTROL_H_ + +#include + +#include + +#include + +#endif /*CM_CONTROL_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h new file mode 100644 index 00000000000..20313f13256 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief NMF API for interrupt handler. + * + * This file contains the Component Manager API for interrupt handler. + */ +#ifndef CONTROL_IRQ_ENGINE_H +#define CONTROL_IRQ_ENGINE_H + +#include +#include +#include + +/*! + * \brief MPCs -> HOST communication handler + * + * This routine shall be integrated as interrupt handler into the OS + * + * If the given Media Processor Core has been configured (through CM_ConfigureMediaProcessorCore()) as using \ref LOCAL_SEMAPHORES, then + * the NMF communication mechanism will use the embedded MMDSP macrocell semaphore, + * so CM_ProcessMpcEvent(<\e coreId>) shall be called under ISR connected to local MMDSP IRQ0, with the related \e coreId as parameter. + * + * If the given Media Processor Core has been configured (through CM_ConfigureMediaProcessorCore()) as using \ref SYSTEM_SEMAPHORES, then + * the NMF communication mechanism will use the shared system HW Semaphores, + * so CM_ProcessMpcEvent(\ref ARM_CORE_ID) shall be called under ISR connected to shared HW Sem Host IRQ, with \ref ARM_CORE_ID as parameter. + * + * NB: A Media Processor Core belonging to the distribution pool shall be configured with \ref SYSTEM_SEMAPHORES + * + * \see t_nmf_semaphore_type_id description + * + * \param[in] coreId identification of the source of the interrupt + * + * \ingroup CM_ENGINE_CONTROL_API + */ +PUBLIC IMPORT_SHARED void CM_ProcessMpcEvent(t_nmf_core_id coreId); + +/*! + * \brief Service type + * + * \note We used an enumeration in structure since this description remain inside the kernel + * and we assume that everything in the kernel is compile with same compiler and option. + * + * \ingroup CM_ENGINE_CONTROL_API + */ +typedef enum { // Allowed since i + CM_MPC_SERVICE_NONE = 0, //!< No service found + CM_MPC_SERVICE_PANIC = 1, //!< Panic service found + CM_MPC_SERVICE_PRINT = 2 //!< Print service found +} t_cm_service_type; + //!< Service description type +/*! + * \brief Service description data + * + * + * \ingroup CM_ENGINE_CONTROL_API + */ +typedef struct { + union { + t_nmf_panic_data panic; //!< Panic description + struct { + t_uint32 dspAddress; + t_uint32 value1; + t_uint32 value2; + } print; //!< Printf like description + } u; //!< Union of service description +} t_cm_service_description; + +/*! + * \brief MPC Panic handler + * + * This routine shall be called as interrupt handler into the OS. + * + * So CM_getPanicDescription shall be called under ISR connected to local MMDSP IRQ1, with the related \e coreId as parameter. + * + * \param[in] coreId identification of the source of the interrupt + * \param[out] srcType Pointer on service type + * \param[out] srcDescr Pointer on service description + * + * \ingroup CM_ENGINE_CONTROL_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_getServiceDescription( + t_nmf_core_id coreId, + t_cm_service_type *srcType, + t_cm_service_description *srcDescr); + +/*! + * \brief Read a null terminated string inside an MPC + * + * This routine could be used to read the MPC string give as parameter during an CM_NMF_SERVICE_PRINT + * + * \param[in] coreId Identification of the code where read string + * \param[in] dspAddress Address of the string in the MPC + * \param[out] buffer Buffer pointer where returning null terminated string + * \param[in] bufferSize Buffer size + * + * \ingroup CM_ENGINE_CONTROL_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ReadMPCString( + t_nmf_core_id coreId, + t_uint32 dspAddress, + char * buffer, + t_uint32 bufferSize); + +#endif /* CONTROL_IRQ_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/api/domain_engine.h b/drivers/staging/nmf-cm/cm/engine/api/domain_engine.h new file mode 100644 index 00000000000..7cc6f33ed90 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/domain_engine.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief Public Component Manager Memory User SYSCALL API. + * + * This file contains the Component Manager SYSCALL API for manipulating domains. + * + */ + +#ifndef __INC_DOMAIN_ENGINE_H +#define __INC_DOMAIN_ENGINE_H + +#include + +/*! + * \brief Create a domain. + * + * Create a memory domain for use in the CM for component instantiation and memory allocation. + * + * \param[in] client Id of the client. + * \param[in] domain Description of domain memories. + * \param[out] handle Idetifier of the created domain + * + * \exception CM_INVALID_DOMAIN_DEFINITION + * \exception CM_INTERNAL_DOMAIN_OVERFLOW + * \exception CM_OK + * + * \return Error code. + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_CreateMemoryDomain( + const t_nmf_client_id client, + const t_cm_domain_memory *domain, + t_cm_domain_id *handle + ); + +/*! + * \brief Create a scratch domain. + * + * Create a scratch memory domain. Scratch domains + * are used to perform overlapping allocations. + * + * \param[in] client Id of the client. + * \param[in] parentId Identifier of the parent domain. + * \param[in] domain Description of domain memories. + * \param[out] handle Idetifier of the created domain + * + * \exception CM_INVALID_DOMAIN_DEFINITION + * \exception CM_INTERNAL_DOMAIN_OVERFLOW + * \exception CM_NO_MORE_MEMORY + * \exception CM_OK + * + * \return Error code. + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_CreateMemoryDomainScratch( + const t_nmf_client_id client, + const t_cm_domain_id parentId, + const t_cm_domain_memory *domain, + t_cm_domain_id *handle + ); + +/*! + * \brief Destroy a memory domain. + + * \param[in] handle Domain identifier to destroy. + * + * \exception CM_INVALID_DOMAIN_HANDLE + * \exception CM_OK + * + * \return Error code. + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_DestroyMemoryDomain( + t_cm_domain_id handle); + +/*! + * \brief Destroy all domains belonging to a given client. + * + * \param[in] client + * + * \return Error code. + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_FlushMemoryDomains( + t_nmf_client_id client); + +/*! + * \brief Retrieve the coreId for a given domain. Utility. + + * \param[in] domainId Domain identifier. + * \param[out] coreId Core identifier. + * + * \exception CM_INVALID_DOMAIN_HANDLE Invalid domain handle + * \exception CM_OK + * + * \return Error code. + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetDomainCoreId(const t_cm_domain_id domainId, t_nmf_core_id *coreId); + +#endif /* __INC_DOMAIN_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/api/executive_engine_mgt_engine.h b/drivers/staging/nmf-cm/cm/engine/api/executive_engine_mgt_engine.h new file mode 100644 index 00000000000..9cb8bc1481b --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/executive_engine_mgt_engine.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief CM executive engine management Engine API. + * + * This file contains the Component Manager executive engine management Engine API. + */ +#ifndef CM_EXECUTIVE_ENGINE_MANAGEMENT_ENGINE_H_ +#define CM_EXECUTIVE_ENGINE_MANAGEMENT_ENGINE_H_ + +#include + +/*! + * \brief Return executive engine handle for given core + * + * \param[in] coreId The core for which we want executive engine handle. + * \param[out] executiveEngineHandle executive engine instance (null if the executive engine is not loaded) + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetExecutiveEngineHandle( + t_cm_domain_id domainId, + t_cm_instance_handle *executiveEngineHandle); + +#endif /*CM_EXECUTIVE_ENGINE_MANAGEMENT_ENGINE_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/api/memory_engine.h b/drivers/staging/nmf-cm/cm/engine/api/memory_engine.h new file mode 100644 index 00000000000..49c0c815669 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/memory_engine.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief Public Component Manager Memory User Engine API. + * + * This file contains the Component Manager Engine API for manipulating memory. + * + */ + +#ifndef CM_MEMORY_ENGINE_H_ +#define CM_MEMORY_ENGINE_H_ + +#include +#include + +/*! + * \brief Allocate memory in a Media Processor Core memory + * + * \param[in] domainId + * \param[in] memType + * \param[in] size + * \param[in] memAlignment + * \param[out] pHandle + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_AllocMpcMemory( + t_cm_domain_id domainId, + t_nmf_client_id clientId, //!< [in] Client ID (aka PID) + t_cm_mpc_memory_type memType, + t_cm_size size, + t_cm_mpc_memory_alignment memAlignment, + t_cm_memory_handle *pHandle + ); + + +/*! + * \brief Free a MPC memory block. + * + * \param[in] handle + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_FreeMpcMemory(t_cm_memory_handle handle); + +/*! + * \brief Get the start address of the MPC memory block seen by the host CPU (physical and logical) + * + * The logical system address returned by this method is valid only in kernel space and the physical + * address is accessible only from kernel space too. + * + * \see OSMem "OS Memory management" for seeing an integration example. + * + * \param[in] handle + * \param[out] pSystemAddress + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemorySystemAddress( + t_cm_memory_handle handle, + t_cm_system_address *pSystemAddress); + +/*! + * \brief Get the start address of the memory block seen by the Media Processor Core + * + * \param[in] handle + * \param[out] pMpcAddress + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryMpcAddress( + t_cm_memory_handle handle, + t_uint32 *pMpcAddress); + +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemorySize( + t_cm_memory_handle handle, + t_uint32 *pSize); + +/*! + * \brief Get the memory status for given memory type of a given Media Processor Core + * + * \param[in] domainId + * \param[in] memType + * \param[out] pStatus + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryStatus( + t_cm_domain_id domainId, + t_cm_mpc_memory_type memType, + t_cm_allocator_status *pStatus); + + +#endif /* CM_MEMORY_ENGINE_H_ */ + diff --git a/drivers/staging/nmf-cm/cm/engine/api/migration_engine.h b/drivers/staging/nmf-cm/cm/engine/api/migration_engine.h new file mode 100644 index 00000000000..77a266d4459 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/migration_engine.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#ifndef CM_MIGRATION_ENGINE_H +#define CM_MIGRATION_ENGINE_H + +#include +#include + +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_Migrate(const t_cm_domain_id srcShared, const t_cm_domain_id src, const t_cm_domain_id dst); + +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_Unmigrate(void); + +#endif /* CM_MIGRATION_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/api/perfmeter_engine.h b/drivers/staging/nmf-cm/cm/engine/api/perfmeter_engine.h new file mode 100644 index 00000000000..bead49dc81e --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/perfmeter_engine.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief CM Performance Meter Engine API. + * + * This file contains the Component Manager Performance Meter Engine API. + */ +#ifndef CM_ENGINE_PERFMETER_ENGINE_H_ +#define CM_ENGINE_PERFMETER_ENGINE_H_ + +#include + +/*! + * \brief MPC cpu load + * + * \param[in] coreId identification of mpc from which we want cpu load + * \param[out] mpcLoadCounter will contain mpc cpu load counters value if success + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_getMpcLoadCounter( + t_nmf_core_id coreId, + t_cm_mpc_load_counter *mpcLoadCounter); + +/*! + * \brief MPC cpu load + * Same as \ref CM_ENGINE_getMpcLoadCounter() without lock + * + * \param[in] coreId identification of mpc from which we want cpu load + * \param[out] mpcLoadCounter will contain mpc cpu load counters value if success + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_GetMpcLoadCounter( + t_nmf_core_id coreId, + t_cm_mpc_load_counter *mpcLoadCounter); + +#endif /*CM_ENGINE_PERFMETER_ENGINE_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/api/repository_mgt_engine.h b/drivers/staging/nmf-cm/cm/engine/api/repository_mgt_engine.h new file mode 100644 index 00000000000..3520f974be6 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/api/repository_mgt_engine.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief Repository Component Manager User Engine API. + * + * This file contains the Component Manager Engine API for manipulating the components files. + */ + +#ifndef REPOSITORY_MGT_ENGINE_H_ +#define REPOSITORY_MGT_ENGINE_H_ + +#include +#include + +/*! + * \brief Get the name(s) of the component(s) to load. + * + * \param[in] client Handle of the client component (optional) + * \param[in] requiredItfClientName Null terminated string (Max size=\ref MAX_INTERFACE_NAME_LENGTH) (optional). + * \param[in] server Handle of the server component (optional) + * \param[in] providedItfServerName Null terminated string (Max size==\ref MAX_INTERFACE_NAME_LENGTH) (optional). + * \param[out] fileList List of required component(s). + * \param[in,out] listSize Initial size of the list as input. Updated with the number of entries really used. + * \param[out] type Interface type of the client required or server provided interface. Null terminated string (Max size=\ref MAX_INTERFACE_TYPE_NAME_LENGTH) (optional) . + * \param[out] methodNumber Number of method in the interface type of the client required interface. (only used when called from CM_BindComponentToUser) (optional) + * + * \note It returns the component(s) name(s) to load, depending on the first four parameters. + * + * - If all 4 are NULL, it returns the name of the Executive Engine components to load + * - If 'client' is NULL, it returns the name of the required components for a Bind From CMCore. + * - If 'server' is NULL, it returns the name of the required components for a Bind To CMCore. + * - If none is NULL, it returns the name of the required components for an asynchronous binding + * + * The names are returned in fileList, whose initial size is specified in listSize. + * (sizeList must be the number of provided entries of \ref MAX_INTERFACE_TYPE_NAME_LENGTH length + * If not enough space is provided, CM_NO_MORE_MEMORY is returned + * + * sizeList is updated with the number entries really filled. + * + * This method is also used to retrieve the interface type when called from CM_BindComponentToUser and CM_BindComponentFromUser + * and the number of methods when called from CM_BindComponentToUser. + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetRequiredComponentFiles( + // IN + t_action_to_do action, + const t_cm_instance_handle client, + const char *requiredItfClientName, + const t_cm_instance_handle server, + const char *providedItfServerName, + // OUT component to be pushed + char fileList[][MAX_INTERFACE_TYPE_NAME_LENGTH], + // IN max component allowed to be pushed + t_uint32 listSize, + // OUT interface information + char type[MAX_INTERFACE_TYPE_NAME_LENGTH], + t_uint32 *methodNumber); + +/*! + * \brief Push a component into the CM Component Cache. + * + * \param[in] name Component name, null terminated string (Max size=\ref MAX_INTERFACE_TYPE_NAME_LENGTH) + * \param[in] data Pointer to _user_ data of the component. + * \param[in] size Size of the data. + * + * \note Push a component in the Component Cache + * The 'data' must be provided such a way that they can be freed by a call to OSAL_Free() + * The caller doesn't need and must NOT free the data, even in case of failure. + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_PushComponent(const char *name, const void *data, t_cm_size size); + +/*! + * \brief Remove a component from the CM Component Cache. + * + * \param[in] name Component name, null terminated string (Max size=\ref MAX_INTERFACE_TYPE_NAME_LENGTH) + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_ReleaseComponent (const char *name); + +#endif /*REPOSITORY_MGT_ENGINE_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/communication/fifo/inc/nmf_fifo_arm.h b/drivers/staging/nmf-cm/cm/engine/communication/fifo/inc/nmf_fifo_arm.h new file mode 100644 index 00000000000..41c4f7a7ad6 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/communication/fifo/inc/nmf_fifo_arm.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#ifndef __INC_NMF_FIFO_ARM +#define __INC_NMF_FIFO_ARM + +#include +#include +#include +#include +#include +#include + +/* + * ARM Fifo descriptor (encapsulate the share one) + */ +typedef struct +{ + t_uint32 magic; + t_memory_handle chunkHandle; + t_nmf_core_id pusherCoreId; + t_nmf_core_id poperCoreId; + t_shared_addr dspAdress; + t_dsp_address_info dspAddressInfo; + t_nmf_fifo_desc *fifoDesc; //used for all fifo operations and systematically updated by the migrated offset (see cm_AllocEvent) + t_nmf_fifo_desc *fifoDescShadow; //shadow desc, is used to restore state after migration and perform the update of the real desc + + // ExtendedField + t_memory_handle extendedFieldHandle; + t_shared_field *extendedField; +} t_nmf_fifo_arm_desc; + +PUBLIC t_uint32 fifo_isFifoIdValid(t_nmf_fifo_arm_desc *pArmFifo); +PUBLIC t_nmf_fifo_arm_desc* fifo_alloc( + t_nmf_core_id pusherCoreId, t_nmf_core_id poperCoreId, + t_uint16 size_in_16bit, t_uint16 nbElem, t_uint16 nbExtendedSharedFields, + t_dsp_memory_type_id memType, t_dsp_memory_type_id memExtendedFieldType, t_cm_domain_id domainId); +PUBLIC void fifo_free(t_nmf_fifo_arm_desc *pArmFifo); +PUBLIC t_uint16 fifo_normalizeDepth(t_uint16 requestedDepth); + +PUBLIC t_shared_addr fifo_getAndAckNextElemToWritePointer(t_nmf_fifo_arm_desc *pArmFifo); +PUBLIC t_shared_addr fifo_getAndAckNextElemToReadPointer(t_nmf_fifo_arm_desc *pArmFifo); +PUBLIC t_shared_addr fifo_getNextElemToWritePointer(t_nmf_fifo_arm_desc *pArmFifo); +PUBLIC t_shared_addr fifo_getNextElemToReadPointer(t_nmf_fifo_arm_desc *pArmFifo); +PUBLIC void fifo_acknowledgeRead(t_nmf_fifo_arm_desc *pArmFifo); +PUBLIC void fifo_acknowledgeWrite(t_nmf_fifo_arm_desc *pArmFifo); +PUBLIC void fifo_coms_acknowledgeWriteAndInterruptGeneration(t_nmf_fifo_arm_desc *pArmFifo); + +PUBLIC t_cm_error fifo_params_setSharedField(t_nmf_fifo_arm_desc *pArmFifo, t_uint32 sharedFieldIndex, t_shared_field value); + +#endif /* __INC_NMF_FIFO_ARM */ diff --git a/drivers/staging/nmf-cm/cm/engine/communication/fifo/src/nmf_fifo_arm.c b/drivers/staging/nmf-cm/cm/engine/communication/fifo/src/nmf_fifo_arm.c new file mode 100644 index 00000000000..48d7f9e9f03 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/communication/fifo/src/nmf_fifo_arm.c @@ -0,0 +1,241 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include +#include +#include +#include +#include "../inc/nmf_fifo_arm.h" + +#include +#include +#include +#include + +/* define value of fifo magic number */ +#define NMF_FIFO_MAGIC_NB 0xF1F0BEEF + +PRIVATE t_uint16 fifo_getCount( + t_uint16 writeIndex, + t_uint16 readIndex, + t_uint16 fifoSize +) +{ + if (writeIndex >= readIndex) {return writeIndex - readIndex;} + else {return fifoSize - readIndex + writeIndex;} +} + +PRIVATE t_uint16 fifo_incrementIndex( + t_uint16 index, + t_uint16 wrappingValue +) +{ + if (++index == wrappingValue) {index = 0;} + + return index; +} + +PUBLIC t_uint16 fifo_normalizeDepth(t_uint16 requestedDepth) +{ + /* with new implementation we don't align on power of two */ + return requestedDepth; +} + +PUBLIC t_nmf_fifo_arm_desc* fifo_alloc( + t_nmf_core_id pusherCoreId, t_nmf_core_id poperCoreId, + t_uint16 size_in_16bit, t_uint16 nbElem, t_uint16 nbExtendedSharedFields, + t_dsp_memory_type_id memType, t_dsp_memory_type_id memExtendedFieldType, t_cm_domain_id domainId) +{ + t_uint16 realNbElem = nbElem + 1;/* we need one more elem in new implementation */ + t_uint16 sizeToAlloc = sizeof(t_nmf_fifo_desc) + ((size_in_16bit<<1)*realNbElem); + t_nmf_fifo_arm_desc *pArmFifoDesc; + + pArmFifoDesc = (t_nmf_fifo_arm_desc*)OSAL_Alloc(sizeof (t_nmf_fifo_arm_desc)); + if (pArmFifoDesc == NULL) + goto errorde; + + pArmFifoDesc->chunkHandle = cm_DM_Alloc(domainId, memType, + (sizeToAlloc/2), CM_MM_ALIGN_2WORDS, TRUE); /* size in 16-bit since we use EXT16 memory */ + if (pArmFifoDesc->chunkHandle == INVALID_MEMORY_HANDLE) + goto errorsh; + + pArmFifoDesc->magic = NMF_FIFO_MAGIC_NB; + pArmFifoDesc->pusherCoreId = pusherCoreId; + pArmFifoDesc->poperCoreId = poperCoreId; + + pArmFifoDesc->fifoDesc = (t_nmf_fifo_desc *)cm_DSP_GetHostLogicalAddress(pArmFifoDesc->chunkHandle); + cm_DSP_GetDspAddress(pArmFifoDesc->chunkHandle, &pArmFifoDesc->dspAdress); + + pArmFifoDesc->fifoDescShadow = pArmFifoDesc->fifoDesc; + cm_DSP_GetDspDataAddressInfo(cm_DM_GetDomainCoreId(domainId), pArmFifoDesc->dspAdress, &pArmFifoDesc->dspAddressInfo); + + pArmFifoDesc->extendedFieldHandle = INVALID_MEMORY_HANDLE; + pArmFifoDesc->extendedField = NULL; + + pArmFifoDesc->fifoDesc->elemSize = size_in_16bit; + pArmFifoDesc->fifoDesc->fifoFullValue = nbElem; + pArmFifoDesc->fifoDesc->wrappingValue = realNbElem; + + pArmFifoDesc->fifoDesc->semId = cm_SEM_Alloc(pusherCoreId, poperCoreId); + pArmFifoDesc->fifoDesc->readIndex = 0; + pArmFifoDesc->fifoDesc->writeIndex = 0; + + LOG_INTERNAL(2, "\n##### Fifo alloc 0x%x (0x%x)\n\n", pArmFifoDesc, pArmFifoDesc->fifoDesc, 0, 0, 0, 0); + + if (nbExtendedSharedFields >= 1) + { + if(poperCoreId == ARM_CORE_ID) + { + /* Optimization: Don't put extended Field in DSP memory since use only by ARM if popper */ + pArmFifoDesc->extendedField = (t_shared_field*)OSAL_Alloc(nbExtendedSharedFields * sizeof(t_shared_field)); + if (pArmFifoDesc->extendedField == NULL) + goto errorex; + + pArmFifoDesc->fifoDesc->extendedField = (t_uint32)pArmFifoDesc->extendedField; + } + else + { + pArmFifoDesc->extendedFieldHandle = cm_DM_Alloc(domainId, memExtendedFieldType, + nbExtendedSharedFields * sizeof(t_shared_field) / 4, CM_MM_ALIGN_WORD, TRUE); + if (pArmFifoDesc->extendedFieldHandle == INVALID_MEMORY_HANDLE) + goto errorex; + + pArmFifoDesc->extendedField = (t_shared_field*)cm_DSP_GetHostLogicalAddress(pArmFifoDesc->extendedFieldHandle); + cm_DSP_GetDspAddress(pArmFifoDesc->extendedFieldHandle, (t_uint32*)&pArmFifoDesc->fifoDesc->extendedField); + } + + pArmFifoDesc->extendedField[EXTENDED_FIELD_BCTHIS_OR_TOP] = (t_shared_field)0; + } + + return pArmFifoDesc; + +errorex: + (void)cm_DM_Free(pArmFifoDesc->chunkHandle, TRUE); +errorsh: + OSAL_Free(pArmFifoDesc); +errorde: + return NULL; +} + +PUBLIC t_uint32 fifo_isFifoIdValid(t_nmf_fifo_arm_desc *pArmFifo) +{ + if (((t_uint32)pArmFifo & CM_MM_ALIGN_WORD) != 0) {return FALSE;} + if (pArmFifo->magic == NMF_FIFO_MAGIC_NB) {return TRUE;} + else {return FALSE;} +} + +PUBLIC void fifo_free(t_nmf_fifo_arm_desc *pArmFifo) +{ + CM_ASSERT(pArmFifo->pusherCoreId != ARM_CORE_ID || pArmFifo->poperCoreId != ARM_CORE_ID); + + pArmFifo->magic = ~NMF_FIFO_MAGIC_NB; + + if(pArmFifo->extendedFieldHandle != INVALID_MEMORY_HANDLE) + (void)cm_DM_Free(pArmFifo->extendedFieldHandle, TRUE); + else if(pArmFifo->extendedField != NULL) + OSAL_Free(pArmFifo->extendedField); + + (void)cm_DM_Free(pArmFifo->chunkHandle, TRUE); + OSAL_Free(pArmFifo); +} + +PUBLIC t_shared_addr fifo_getAndAckNextElemToWritePointer(t_nmf_fifo_arm_desc *pArmFifo) +{ + t_shared_addr retValue; + + retValue = fifo_getNextElemToWritePointer(pArmFifo); + if (retValue != 0) + { + fifo_acknowledgeWrite(pArmFifo); + } + + return retValue; +} + +PUBLIC t_shared_addr fifo_getAndAckNextElemToReadPointer(t_nmf_fifo_arm_desc *pArmFifo) +{ + t_shared_addr retValue; + + retValue = fifo_getNextElemToReadPointer(pArmFifo); + if (retValue != 0) + { + fifo_acknowledgeRead(pArmFifo); + } + + return retValue; +} + +PUBLIC t_shared_addr fifo_getNextElemToWritePointer(t_nmf_fifo_arm_desc *pArmFifo) +{ + t_shared_addr retValue = 0; + t_nmf_fifo_desc *pDesc; + t_uint16 count; + + if ((NULL == pArmFifo) || (NULL == (pDesc = pArmFifo->fifoDesc))) + return 0; + + count = fifo_getCount(pDesc->writeIndex, pDesc->readIndex,pDesc->wrappingValue); + if (count < pDesc->fifoFullValue) + { + retValue = ((t_shared_addr)pDesc + sizeof(t_nmf_fifo_desc) + (pDesc->writeIndex*(pDesc->elemSize<<1))); + } + + return retValue; +} + +PUBLIC t_shared_addr fifo_getNextElemToReadPointer(t_nmf_fifo_arm_desc *pArmFifo) +{ + t_shared_addr retValue = 0; + t_nmf_fifo_desc *pDesc; + t_uint16 count; + + if ((NULL == pArmFifo) || (NULL == (pDesc = pArmFifo->fifoDesc))) + return 0; + + count = fifo_getCount(pDesc->writeIndex, pDesc->readIndex,pDesc->wrappingValue); + if (count != 0) + { + retValue = ((t_shared_addr)pDesc+ sizeof(t_nmf_fifo_desc) + (pDesc->readIndex*(pDesc->elemSize<<1))); + } + + return retValue; +} + +PUBLIC void fifo_acknowledgeRead(t_nmf_fifo_arm_desc *pArmFifo) +{ + t_nmf_fifo_desc *pDesc = pArmFifo->fifoDesc; + + pDesc->readIndex = fifo_incrementIndex(pDesc->readIndex, pDesc->wrappingValue); +} + +PUBLIC void fifo_acknowledgeWrite(t_nmf_fifo_arm_desc *pArmFifo) +{ + t_nmf_fifo_desc *pDesc = pArmFifo->fifoDesc; + + pDesc->writeIndex = fifo_incrementIndex(pDesc->writeIndex, pDesc->wrappingValue); +} + +PUBLIC void fifo_coms_acknowledgeWriteAndInterruptGeneration(t_nmf_fifo_arm_desc *pArmFifo) +{ + t_nmf_fifo_desc *pDesc = pArmFifo->fifoDesc; + + fifo_acknowledgeWrite(pArmFifo); + //Be sure before generate irq that fifo has been updated + OSAL_mb(); + cm_SEM_GenerateIrq[pArmFifo->poperCoreId](pArmFifo->poperCoreId, pDesc->semId); + //cm_SEM_Take[pArmFifo->poperCoreId](pArmFifo->poperCoreId, pDesc->semId); + //cm_SEM_GiveWithInterruptGeneration[pArmFifo->poperCoreId](pArmFifo->poperCoreId, pDesc->semId); +} + +PUBLIC t_cm_error fifo_params_setSharedField(t_nmf_fifo_arm_desc *pArmFifo, t_uint32 sharedFieldIndex, t_shared_field value) +{ + pArmFifo->extendedField[sharedFieldIndex] = value; + + return CM_OK; +} + diff --git a/drivers/staging/nmf-cm/cm/engine/communication/inc/communication.h b/drivers/staging/nmf-cm/cm/engine/communication/inc/communication.h new file mode 100644 index 00000000000..53ab87b7096 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/communication/inc/communication.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Components Management internal methods - Communication part. + * + */ +#ifndef __INC_NMF_COM +#define __INC_NMF_COM + +#include +#include +#include + +#include + +extern t_dsp_memory_type_id comsLocation; +extern t_dsp_memory_type_id paramsLocation; +extern t_dsp_memory_type_id extendedFieldLocation; + +PUBLIC t_cm_error cm_COM_Init(t_nmf_coms_location comsLocation); +PUBLIC t_cm_error cm_COM_AllocateMpc(t_nmf_core_id coreId); +PUBLIC void cm_COM_InitMpc(t_nmf_core_id coreId); +PUBLIC void cm_COM_FreeMpc(t_nmf_core_id coreId); + +PUBLIC t_cm_error cm_PushEventTrace(t_nmf_fifo_arm_desc*, t_event_params_handle h, t_uint32 methodIndex, t_uint32 isTrace); +PUBLIC t_cm_error cm_PushEvent(t_nmf_fifo_arm_desc *pArmFifo, t_event_params_handle h, t_uint32 methodIndex); +PUBLIC void cm_AcknowledgeEvent(t_nmf_fifo_arm_desc *pArmFifo); +PUBLIC t_event_params_handle cm_AllocEvent(t_nmf_fifo_arm_desc *pArmFifo); + +/*! + * \internal + * \brief Definition of custom value for userTHIS parameter of PostDfc OSAL call + * + * This value is used as 1st parameter of a pPostDfc call to indicate that a given interrupt is linked to an internal Component Manager event + */ +#define NMF_INTERNAL_USERTHIS ((void*)MASK_ALL32) + +typedef void (*t_callback_method)(t_nmf_core_id coreId, t_event_params_handle pParam); + +#endif /* __INC_NMF_COM */ diff --git a/drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h b/drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h new file mode 100644 index 00000000000..db426845a82 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Communication Component Manager API type. + */ +#ifndef COMMUNICATION_TYPE_H_ +#define COMMUNICATION_TYPE_H_ + +#include + + +/*! + * \brief Buffer type used for (un)marshalling parameters. + * + * This buffer type is used for (un)marshalling paramaters. It can either be a + * shared memory buffer (ESRAM or SDRAM) or a pure host software memory (stack). + + * \ingroup CM_ENGINE_API + */ +typedef t_uint16 *t_event_params_handle; + +/*! + * \brief Component manager handle to Host -> MPC communication. + * + * \ingroup CM_ENGINE_API + */ +typedef t_uint32 t_cm_bf_host2mpc_handle; + +/*! + * \brief Component manager handle to MPC -> Host communication. + * + * \ingroup CM_ENGINE_API + */ +typedef t_uint32 t_cm_bf_mpc2host_handle; + +/*! + * \brief Component manager proxy handle to MPC -> Host skeleton context. + * + * \ingroup CM_ENGINE_API + */ +typedef t_uint32 t_nmf_mpc2host_handle; + +/*! + * @defgroup t_nmf_coms_location t_nmf_coms_location + * \brief Definition of the location of the internal CM communication objects + * + * @{ + * \ingroup CM_ENGINE_API + */ +typedef t_uint8 t_nmf_coms_location; //!< Fake enumeration type +#define COMS_IN_ESRAM ((t_nmf_coms_location)0) //!< All coms objects (coms and params fifos) will be in embedded RAM +#define COMS_IN_SDRAM ((t_nmf_coms_location)1) //!< All coms objects (coms and params fifos) will be in external RAM +/* @} */ + +#endif /*COMMUNICATION_TYPE_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c b/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c new file mode 100644 index 00000000000..8f48f02afc2 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c @@ -0,0 +1,326 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#include +#include "../inc/communication.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define ARM_DSP_EVENT_FIFO_SIZE 16 + +t_dsp_memory_type_id comsLocation; +t_dsp_memory_type_id paramsLocation; +t_dsp_memory_type_id extendedFieldLocation; + +#define __DEBUG + +#ifdef __DEBUG +PRIVATE volatile t_uint32 armdspCounter = 0; +PRIVATE volatile t_uint32 armdspIrqCounter = 0; +PRIVATE volatile t_uint32 dsparmCounter = 0; +PRIVATE volatile t_uint32 dsparmIrqCounter = 0; +#endif /* __DEBUG */ + +t_nmf_fifo_arm_desc* mpc2mpcComsFifoId[NB_CORE_IDS][NB_CORE_IDS]; + +PRIVATE const t_callback_method internalHostJumptable[] = { + processAsyncAcknowledge, + processAsyncAcknowledge, + processAsyncAcknowledge, + processSyncAcknowledge, + processAsyncAcknowledge, + processAsyncAcknowledge, + processAsyncAcknowledge, + processSyncAcknowledge, + processAsyncAcknowledge, + processSyncAcknowledge, + processSyncAcknowledge +}; + +PUBLIC t_cm_error cm_COM_Init(t_nmf_coms_location _comsLocation) +{ + t_nmf_core_id coreId, localCoreId; + + /* + * Configure the default location of coms and params fifo (configuration by user) */ + switch(_comsLocation) + { + case COMS_IN_SDRAM: + comsLocation = SDRAM_EXT16; + paramsLocation = SDRAM_EXT16; + extendedFieldLocation = SDRAM_EXT24; + break; + case COMS_IN_ESRAM: + comsLocation = ESRAM_EXT16; + paramsLocation = ESRAM_EXT16; + extendedFieldLocation = ESRAM_EXT24; + break; + default: CM_ASSERT(0); + } + + for (coreId = ARM_CORE_ID; coreId < NB_CORE_IDS; coreId++) + { + for (localCoreId = ARM_CORE_ID; localCoreId < NB_CORE_IDS; localCoreId++) + { + mpc2mpcComsFifoId[coreId][localCoreId] = NULL; + } + } + + return CM_OK; +} + +PUBLIC t_cm_error cm_COM_AllocateMpc(t_nmf_core_id coreId) +{ + t_nmf_core_id localCoreId; + + /* + * Allocation of the coms fifo with neighbor MPCs + * if they are already initialized (known through initializedCoresMask) + */ + for (localCoreId = ARM_CORE_ID; localCoreId < NB_CORE_IDS; localCoreId++) + { + if (localCoreId == coreId) continue; /* no coms fifo with itself ;) */ + if(cm_DSP_GetState(localCoreId)->state != MPC_STATE_BOOTED) continue; + + /* + * coms fifo from other initialized MPCs to the given one + */ + if (mpc2mpcComsFifoId[coreId][localCoreId] != NULL) continue; /* coms fifo already allocated */ + + mpc2mpcComsFifoId[coreId][localCoreId] = fifo_alloc( + coreId, localCoreId, + EVENT_ELEM_SIZE_IN_BYTE/2, ARM_DSP_EVENT_FIFO_SIZE, + 0, comsLocation, extendedFieldLocation, cm_DSP_GetState(coreId)->domainEE + ); + if (mpc2mpcComsFifoId[coreId][localCoreId] == NULL) + goto oom; + + /* + * coms fifo from the given MPC to the other initialized ones + */ + if (mpc2mpcComsFifoId[localCoreId][coreId] != NULL) continue; /* coms fifo already allocated */ + + mpc2mpcComsFifoId[localCoreId][coreId] = fifo_alloc( + localCoreId, coreId, + EVENT_ELEM_SIZE_IN_BYTE/2, ARM_DSP_EVENT_FIFO_SIZE, + 0, comsLocation, extendedFieldLocation, cm_DSP_GetState(coreId)->domainEE + ); + if (mpc2mpcComsFifoId[localCoreId][coreId] == NULL) + goto oom; + } + + return CM_OK; +oom: + cm_COM_FreeMpc(coreId); + return CM_NO_MORE_MEMORY; +} + +PUBLIC void cm_COM_InitMpc(t_nmf_core_id coreId) +{ + // Here we assume that attribute are in XRAM, thus we don't need memory type + t_uint32* toNeighborsComsFifoIdSharedVar[NB_CORE_IDS]; + t_uint32* fromNeighborsComsFifoIdSharedVar[NB_CORE_IDS]; + + t_nmf_core_id localCoreId; + + /* + * Initialization of the core identifier of a given Executive Engine + * Used into communication scheme so the init is done here, will be moved MAY BE into EE loading module!!! + */ + cm_writeAttribute(cm_EEM_getExecutiveEngine(coreId)->instance, "semaphores/myCoreId", coreId); + + /* + * Initialization of the coms fifo with the Host for the given coreId + */ + for (localCoreId = FIRST_MPC_ID/* NOT ARM*/; localCoreId <= LAST_CORE_ID; localCoreId++) + { + // Note: This loop will also include coreId in order to fill + if(cm_DSP_GetState(localCoreId)->state != MPC_STATE_BOOTED) continue;/* no coms fifo initialisation with not booted MPC */ + + toNeighborsComsFifoIdSharedVar[localCoreId] = (t_uint32*)cm_getAttributeHostAddr(cm_EEM_getExecutiveEngine(localCoreId)->instance, "comms/toNeighborsComsFifoId"); + + fromNeighborsComsFifoIdSharedVar[localCoreId] = (t_uint32*)cm_getAttributeHostAddr(cm_EEM_getExecutiveEngine(localCoreId)->instance, "comms/fromNeighborsComsFifoId"); + } + + toNeighborsComsFifoIdSharedVar[coreId][ARM_CORE_ID] = mpc2mpcComsFifoId[coreId][ARM_CORE_ID]->dspAdress; + fromNeighborsComsFifoIdSharedVar[coreId][ARM_CORE_ID] = mpc2mpcComsFifoId[ARM_CORE_ID][coreId]->dspAdress; + + for (localCoreId = FIRST_MPC_ID/* NOT ARM*/; localCoreId <= LAST_CORE_ID; localCoreId++) + { + if (localCoreId == coreId) continue; /* no coms fifo with itself ;) */ + if(cm_DSP_GetState(localCoreId)->state != MPC_STATE_BOOTED) continue;/* no coms fifo initialisation with not booted MPC */ + + toNeighborsComsFifoIdSharedVar[coreId][localCoreId] = mpc2mpcComsFifoId[coreId][localCoreId]->dspAdress; + fromNeighborsComsFifoIdSharedVar[localCoreId][coreId] = mpc2mpcComsFifoId[coreId][localCoreId]->dspAdress; + + fromNeighborsComsFifoIdSharedVar[coreId][localCoreId] = mpc2mpcComsFifoId[localCoreId][coreId]->dspAdress; + toNeighborsComsFifoIdSharedVar[localCoreId][coreId] = mpc2mpcComsFifoId[localCoreId][coreId]->dspAdress; + } +} + +PUBLIC void cm_COM_FreeMpc(t_nmf_core_id coreId) +{ + t_nmf_core_id localCoreId; + + for (localCoreId = ARM_CORE_ID; localCoreId < NB_CORE_IDS; localCoreId++) + { + /* + * Free coms fifo from other initialized MPCs to the given one + */ + if ( mpc2mpcComsFifoId[coreId][localCoreId] != NULL) + { + fifo_free(mpc2mpcComsFifoId[coreId][localCoreId]); + mpc2mpcComsFifoId[coreId][localCoreId] = NULL; + } + + /* + * Free coms fifo from the given MPC to the other initialized ones + */ + if ( mpc2mpcComsFifoId[localCoreId][coreId] != NULL) + { + fifo_free(mpc2mpcComsFifoId[localCoreId][coreId]); + mpc2mpcComsFifoId[localCoreId][coreId] = NULL; + } + } +} + +PUBLIC t_event_params_handle cm_AllocEvent(t_nmf_fifo_arm_desc *pArmFifo) + +{ + t_uint32 retValue; + + //migration impacts the ARM-side address of the fifoDesc, + //thus translate the fifo desc adress systematically. + pArmFifo->fifoDesc = (t_nmf_fifo_desc*)cm_migration_translate(pArmFifo->dspAddressInfo.segmentType, (t_shared_addr)pArmFifo->fifoDescShadow); + + retValue = fifo_getAndAckNextElemToWritePointer(pArmFifo); + + return (t_event_params_handle)retValue; +} + +PUBLIC void cm_AcknowledgeEvent(t_nmf_fifo_arm_desc *pArmFifo) +{ + fifo_acknowledgeRead(pArmFifo); +} + +PUBLIC t_cm_error cm_PushEventTrace(t_nmf_fifo_arm_desc *pArmFifo, t_event_params_handle h, t_uint32 methodIndex, t_uint32 isTrace) +{ + t_uint32 retValue; + + retValue = fifo_getNextElemToWritePointer(mpc2mpcComsFifoId[ARM_CORE_ID][pArmFifo->poperCoreId]); + + if(retValue != 0x0) { + t_shared_field *pEvent = (t_shared_field *)retValue; + +#ifdef __DEBUG + armdspCounter++; +#endif /* __DEBUG */ + + pEvent[EVENT_ELEM_METHOD_IDX] = (t_shared_addr)methodIndex; + pEvent[EVENT_ELEM_PARAM_IDX] = pArmFifo->dspAdress + (((t_cm_logical_address)h - (t_cm_logical_address)pArmFifo->fifoDesc) >> 1); //note byte to half-word conversion + pEvent[EVENT_ELEM_EXTFIELD_IDX] = pArmFifo->fifoDesc->extendedField; + + if (isTrace) + { + cm_TRC_traceCommunication( + TRACE_COMMUNICATION_COMMAND_SEND, + ARM_CORE_ID, + pArmFifo->poperCoreId); + } + fifo_coms_acknowledgeWriteAndInterruptGeneration(mpc2mpcComsFifoId[ARM_CORE_ID][pArmFifo->poperCoreId]); + + return CM_OK; + } + + ERROR("CM_MPC_NOT_RESPONDING: FIFO COM full '%s'\n", 0, 0, 0, 0, 0, 0); + return CM_MPC_NOT_RESPONDING; +} + +PUBLIC t_cm_error cm_PushEvent(t_nmf_fifo_arm_desc *pArmFifo, t_event_params_handle h, t_uint32 methodIndex) +{ + return cm_PushEventTrace(pArmFifo,h,methodIndex,1); +} + +static void cmProcessMPCFifo(t_nmf_core_id coreId) +{ + t_shared_field *pEvent; + + while((pEvent = (t_shared_field *)fifo_getNextElemToReadPointer(mpc2mpcComsFifoId[coreId][ARM_CORE_ID])) != NULL) + { + t_event_params_handle pParamsAddr; + t_shared_field *pParamsFifoESFDesc; + + pParamsAddr = (t_event_params_handle)cm_DSP_ConvertDspAddressToHostLogicalAddress( + coreId, + pEvent[EVENT_ELEM_PARAM_IDX]); + pParamsFifoESFDesc = (t_shared_field *)pEvent[EVENT_ELEM_EXTFIELD_IDX]; +#ifdef __DEBUG + dsparmCounter++; +#endif /* __DEBUG */ + + if(pParamsFifoESFDesc[EXTENDED_FIELD_BCTHIS_OR_TOP] == (t_shared_field)NMF_INTERNAL_USERTHIS) + { + internalHostJumptable[pEvent[EVENT_ELEM_METHOD_IDX]](coreId, pParamsAddr); + } + else + { + cm_TRC_traceCommunication( + TRACE_COMMUNICATION_COMMAND_RECEIVE, + ARM_CORE_ID, + coreId); + + OSAL_PostDfc( + pParamsFifoESFDesc[EXTENDED_FIELD_BCTHIS_OR_TOP], + pEvent[EVENT_ELEM_METHOD_IDX], + pParamsAddr, + pParamsFifoESFDesc[EXTENDED_FIELD_BCDESC]); + } + + // [Pwr] mpc2hostComsFifoId value is checked to support the case where + // CM_PostCleanUpAndFlush method is called under interrupt context + // -> mpc2hostComsFifoId can be released. + if (mpc2mpcComsFifoId[coreId][ARM_CORE_ID] != NULL) + fifo_acknowledgeRead(mpc2mpcComsFifoId[coreId][ARM_CORE_ID]); + else + break; + } +} + +PUBLIC EXPORT_SHARED void CM_ProcessMpcEvent(t_nmf_core_id coreId) +{ +#ifdef __DEBUG + dsparmIrqCounter++; +#endif /* __DEBUG */ + + if (coreId != ARM_CORE_ID) + { + /* Acknowledge DSP communication interrupt */ + cm_DSP_AcknowledgeDspIrq(coreId, DSP2ARM_IRQ_0); + + cmProcessMPCFifo(coreId); + } + else + { + while((coreId = cm_HSEM_GetCoreIdFromIrqSrc()) <= LAST_MPC_ID) + cmProcessMPCFifo(coreId); + } +} + diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/bind.h b/drivers/staging/nmf-cm/cm/engine/component/inc/bind.h new file mode 100644 index 00000000000..325703e3367 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/bind.h @@ -0,0 +1,443 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + * \brief Binding Factories internal API. + * + * \defgroup BF_COMMON Binding factories: Common API + * \defgroup BF_PRIMITIVE Binding Factories: Primitive API + * \defgroup BF_TRACE Binding Factories: Trace API + * \defgroup BF_ASYNCHRONOUS Binding Factories: Asynchronous API + * \defgroup BF_DISTRIBUTED Binding Factories: Distributed API + */ +#ifndef __INC_CM_BIND_H +#define __INC_CM_BIND_H + +#include +#include +#include + +/** + * \internal + * \ingroup BF_COMMON + * + * \brief Identification number of prefedined Binding Factories + */ +typedef enum { + BF_SYNCHRONOUS, //!< Intra-DSP Synchronous Binding Factory Identifier + BF_TRACE, //!< Intra-DSP trace synchronous Binding Factory Identifier + BF_ASYNCHRONOUS, //!< Intra-DSP Asynchronous Binding Factory Identifier + BF_DSP2HOST, //!< DSP to Host Binding Factory Identifier + BF_HOST2DSP, //!< Host to DSP Binding Factory Identifier + BF_DSP2DSP, //!< DSP to DSP Binding Factory Identifier +} t_bf_info_ID; + +/*! + * \internal + * \brief Description of a provided interface + * + * \ingroup COMPONENT_INTERNAL + */ +typedef struct _t_interface_reference { + const t_component_instance *instance; //!< Component instance that provide this interface + t_uint8 provideIndex; //!< Index of the interface in the provide array + t_uint8 collectionIndex;//!< Index in the collection if provided interface is a collection + t_bf_info_ID bfInfoID; //!< Identification of BF used for creating binding + void* bfInfo; //!< Storage of the binding factory info +} t_interface_reference; + +/** + * \internal + * \ingroup BF_COMMON + * + * Make some basic sanity check for a client: + * - component stopped + * - Interface really required + * + * \param[in] client The client component instance handle. + * \param[in] requiredItfClientName The client required interface name + * \param[out] requiredItf return the required interface (avoid user searching) + */ +t_cm_error cm_checkValidClient( + const t_component_instance* client, + const char* requiredItfClientName, + t_interface_require_description *itfRequire, + t_bool *bindable); +/** + * \internal + * \ingroup BF_COMMON + * + * Make some basic sanity check for a server: + * - Interface really provided + * + * \param[in] server The server component instance handle. + * \param[in] providedItfServerName The server provided interface name + * \param[out] itf return the provided interface (avoid user searching) + */ +t_cm_error cm_checkValidServer( + const t_component_instance* server, + const char* providedItfServerName, + t_interface_provide_description *itfProvide); + +/** + * \internal + * \ingroup BF_COMMON + * + * Make some basic sanity check for a binding: + * - Sanity check for a server + * - Sanity check for a client (and potentially wait initialisation) + * - Provided and required interface matches + * + * \param[in] client The client component instance handle + * \param[in] requiredItfClientName The client required interface name + * \param[in] server The server component instance handle + * \param[in] providedItfServerName The server provided interface name + * \param[out] requiredItf return the required interface (avoid user searching) + * \param[out] itf return the provided interface (avoid user searching) + */ +t_cm_error cm_checkValidBinding( + const t_component_instance* client, + const char* requiredItfClientName, + const t_component_instance* server, + const char* requiredItfServerName, + t_interface_require_description *itfRequire, + t_interface_provide_description *itfProvide, + t_bool *bindable); + +/** + * \internal + * \ingroup BF_COMMON + * + * Make some basic sanity check for each unbinding: + * - Interface really required + * - Component stopped + * + * \param[in] client The client component instance handle + * \param[in] requiredItfClientName The client required interface name + * \param[out] itfRequire return the previously binded required interface (avoid user searching) + * \param[out] itfProvide return the previously binded provided interface (avoid user searching) + * \param[out] bfInfoID return the binding factory identifiant which done the previously bind + * \param[out] bfInfo return the binding factory information which done the previously bind + */ +t_cm_error cm_checkValidUnbinding( + const t_component_instance* client, + const char* requiredItfClientName, + t_interface_require_description *itfRequire, + t_interface_provide_description *itfProvide); + +/** + * \internal + * \ingroup BF_PRIMITIVE + * + * Create a primitive binding between a client to a server interface. + * + * \param[in] itfRequire The client required interface description + * \param[in] itfProvide The server provided interface description + */ +t_cm_error cm_bindInterface( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide); + +/** + * \internal + * \ingroup BF_PRIMITIVE + * + * Unbind a previously binded client. + * + * \param[in] itfRequire The client required interafce description + */ +void cm_unbindInterface( + const t_interface_require_description *itfRequire); + +/** + * \internal + * \ingroup BF_PRIMITIVE + * + * Get a server interface previouly binded to a client + * + * \param[in] client The client component instance handle + * \param[in] requiredItfClientName The client required interface name + * \param[out] itf The server interface + */ +t_cm_error cm_lookupInterface( + const t_interface_require_description *itfRequire, + t_interface_provide_description *itfProvide); + +/** + * \internal + * \ingroup BF_PRIMITIVE + * + * Create a void binding. + * + * \param[in] client The client component instance handle + * \param[in] requiredItfClientName The client required interface name + */ +t_cm_error cm_bindInterfaceToVoid( + const t_interface_require_description *itfRequire); + +/** + * \internal + * \ingroup BF_TRACE + * + * Trace synchronous binding factory Information + */ +typedef struct { + t_component_instance *traceInstance; //!< Trace binding component instance +} t_trace_bf_info; + +/** + * \internal + * \ingroup BF_TRACE + * + * Create a traced binding between a client to a server interface. + * + * \param[in] itfRequire The client required interface description + * \param[in] itfProvide The server provided interface description + */ +t_cm_error cm_bindInterfaceTrace( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide, + t_elfdescription *elfhandleTrace); + +/** + * \internal + * \ingroup BF_TRACE + * + * Unbind a previously binded client. + * + * \param[in] itfRequire The client required interafce description + */ +void cm_unbindInterfaceTrace( + const t_interface_require_description *itfRequire, + t_trace_bf_info *bfInfo); + + +/** + * \internal + * \ingroup BF_ASYNCHRONOUS + * + * Asynchronous binding factory Information + */ +typedef struct { + t_component_instance *eventInstance; //!< Event binding component instance + t_memory_handle dspfifoHandle; //!< Memory handle of allocated event fifo (pass to the event binding component) +} t_async_bf_info; + +/** + * \internal + * \ingroup BF_ASYNCHRONOUS + * + * Create a asynchronous binding between a client to a server interface. + * \param[in] client The client component instance handle + * \param[in] requiredItfClientName The client required interface name + * \param[in] itf The server interface + * \param[in] fifosize Number of waited event in the fifo + */ +t_cm_error cm_bindInterfaceAsynchronous( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide, + t_uint32 fifosize, + t_dsp_memory_type_id dspEventMemType, + t_elfdescription *elfhandleEvent); +/** + * \internal + * \ingroup BF_ASYNCHRONOUS + * + * Destroy a asynchronous binding between a client to a server interface. + * \param[in] itfRequire the required interface + */ +void cm_unbindInterfaceAsynchronous( + const t_interface_require_description *itfRequire, + t_async_bf_info *bfInfo); + +/** + * \internal + * \ingroup BF_DISTRIBUTED + * + * Stub information in distributed binding factory (client side) + */ +typedef struct { + t_component_instance *stubInstance; //!< Stub +} t_dspstub_bf_info; + +/** + * \internal + * \ingroup BF_DISTRIBUTED + * + * Skeleton information in distributed binding factory (server side) + */ +typedef struct { + t_component_instance *skelInstance; //!< Skeleton binding component instance + t_memory_handle dspfifoHandle; //!< Memory handle of allocated event fifo (pass to the event binding component) +} t_dspskel_bf_info; + +/** + * \internal + * \ingroup BF_DISTRIBUTED + * + * Host to DSP distributed binding factory Information + */ +typedef struct { + t_dspskel_bf_info dspskeleton; //!< Information about the DSP skeleton (server side) + t_nmf_fifo_arm_desc* fifo; //!< Handle of the fifo params + t_nmf_client_id clientId; //!< Client ID of the host client +} t_host2mpc_bf_info; + +/* + * Table of instantiated of host2mpc bindings + */ +extern t_nmf_table Host2MpcBindingTable; /**< list (table) of host2mpc bindings */ + +/** + * \internal + * \ingroup BF_DISTRIBUTED + * + * Create a Host to DSP distributed binding between a host client interface to a server interface. + * (Not manage in the same way as distributed binding since the Host programming model is not component aware). + * \param[in] itfServer The server interface + * \param[in] fifosize Number of waited event in the fifo + * \param[in] dspEventMemType The type of memory to use + * \param[in] bfInfo info structure + */ +t_cm_error cm_bindComponentFromCMCore( + const t_interface_provide_description *itfProvide, + t_uint32 fifosize, + t_dsp_memory_type_id dspEventMemType, + t_elfdescription *elfhandleSkeleton, + t_host2mpc_bf_info **bfInfo); + +/** + * \internal + * \ingroup BF_DISTRIBUTED + * + * Destroy a Host to DSP distributed binding between a host client interface to a server interface. + * \param[in] bfInfo The Host to DSP distributed binding factory information + */ +void cm_unbindComponentFromCMCore( + t_host2mpc_bf_info *bfInfo); + +/** + * \internal + * \ingroup BF_DISTRIBUTED + * + * DSP to Host distributed binding factory Information + */ +typedef struct { + t_dspstub_bf_info dspstub; //!< Information about the DSP stub (client side) + t_nmf_fifo_arm_desc* fifo; //!< Handle of the fifo params + t_uint32 context; +} t_mpc2host_bf_info; + +/** + * \internal + * \ingroup BF_DISTRIBUTED + * + * Create a DSP to Host distributed binding between a client interface to a host server interface. + * (Not manage in the same way as distributed binding since the Host programming model is not component aware). + * \param[in] client The client component instance handle + * \param[in] requiredItfClientName The client required interface name + * \param[in] itfref The host server interface to be called + * \param[in] fifosize Number of waited event in the fifo + */ +t_cm_error cm_bindComponentToCMCore( + const t_interface_require_description *itfRequire, + t_uint32 fifosize, + t_uint32 context, + t_elfdescription *elfhandleStub, + t_mpc2host_bf_info ** bfInfo); + +/** + * \internal + * \ingroup BF_DISTRIBUTED + * + * Destroy a DSP to Host distributed binding between a client interface to a server interface. + * \param[in] itfRequire The required interface + * \param[out] upLayerThis The 'THIS' context of upper layer + */ +void cm_unbindComponentToCMCore( + const t_interface_require_description *itfRequire, + t_mpc2host_bf_info *bfInfo); + +/** + * \internal + * \ingroup BF_DISTRIBUTED + * + * Asynchronous distributed binding factory Information + */ +typedef struct { + t_nmf_fifo_arm_desc* fifo; //!< Handle of the fifo params + t_dspstub_bf_info dspstub; //!< Information about the DSP stub (client side) + t_dspskel_bf_info dspskeleton; //!< Information about the DSP skeleton (server side) +} t_mpc2mpc_bf_info; + +/** + * \internal + * \ingroup BF_DISTRIBUTED + * + * Create a asynchronous distributed binding between a client interface to a server interface. + * \param[in] client The client component instance handle + * \param[in] requiredItfClientName The client required interface name + * \param[in] itf The server interface + * \param[in] fifosize Number of waited event in the fifo + */ +t_cm_error cm_bindInterfaceDistributed( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide, + t_uint32 fifosize, + t_dsp_memory_type_id dspEventMemType, + t_elfdescription *elfhandleSkeleton, + t_elfdescription *elfhandleStub); + +/** + * \internal + * \ingroup BF_DISTRIBUTED + * + * Destroy a asynchronous distributed binding between a client interface to a server interface. + * \param[in] itfRequire The required interface + */ +void cm_unbindInterfaceDistributed( + const t_interface_require_description *itfRequire, + t_mpc2mpc_bf_info *bfInfo); + +/** + * \internal + * + * Bind a static interrupt to server provide interface name. + * \param[in] coreId The core to which component is loaded + * \param[in] interruptLine Interrupt line number to use + * \param[in] server Server instance that provide interrupt service + * \param[in] providedItfServerName Interface name hat provide interrupt service + */ +t_cm_error cm_bindInterfaceStaticInterrupt( + const t_nmf_core_id coreId, + const int interruptLine, + const t_component_instance *server, + const char* providedItfServerName); + +/** + * \internal + * + * Unbind a static interrupt. + * \param[in] coreId The core to which component is loaded + * \param[in] interruptLine Interrupt line number to use + */ +t_cm_error cm_unbindInterfaceStaticInterrupt( + const t_nmf_core_id coreId, + const int interruptLine); + +void cm_destroyRequireInterface(t_component_instance* component, t_nmf_client_id clientId); +void cm_registerSingletonBinding( + t_component_instance* component, + t_interface_require_description* itfRequire, + t_interface_provide_description* itfProvide, + t_nmf_client_id clientId); +t_bool cm_unregisterSingletonBinding( + t_component_instance* component, + t_interface_require_description* itfRequire, + t_interface_provide_description* itfProvide, + t_nmf_client_id clientId); + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h b/drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h new file mode 100644 index 00000000000..35571dde06d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Components Component Manager API type. + * + * \defgroup COMPONENT CM Components API + * \ingroup CM_USER_API + */ + +#ifndef COMPONENT_TYPE_H_ +#define COMPONENT_TYPE_H_ + +#include +#include + +/*! + * @defgroup t_nmf_ee_priority t_nmf_ee_priority + * \brief Identification of the execution engine priority and sub priority. + * @{ + * \ingroup COMPONENT + */ +typedef t_uint32 t_nmf_ee_priority; //!< Fake enumeration type + +#define NMF_SCHED_BACKGROUND ((t_nmf_ee_priority)0) //!< Background priority +#define NMF_SCHED_NORMAL ((t_nmf_ee_priority)1) //!< Normal priority +#define NMF_SCHED_URGENT ((t_nmf_ee_priority)2) //!< Urgent priority +/* @} */ + + +/*! + * \brief Identification of host component returned during introspection + * + * \ingroup COMPONENT_INTROSPECTION + */ +#define NMF_HOST_COMPONENT ((t_cm_instance_handle)0xFFFFFFFF) + +/*! + * \brief Identification of void component returned during introspection + * + * \ingroup COMPONENT_INTROSPECTION + */ +#define NMF_VOID_COMPONENT ((t_cm_instance_handle)0xFFFFFFFE) + + +/*! + * @defgroup t_nmf_ee_priority t_nmf_ee_priority + * \brief Identification of the execution engine priority and sub priority. + * @{ + * \ingroup COMPONENT + */ +typedef t_uint8 t_cm_require_state; //!< Fake enumeration type + +#define CM_REQUIRE_STATIC ((t_cm_require_state)0) //!< Required interface is static +#define CM_REQUIRE_OPTIONAL ((t_cm_require_state)1) //!< Required interface is optional +#define CM_REQUIRE_COLLECTION ((t_cm_require_state)2) //!< Required interface is a collection + +/* @} */ + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/description.h b/drivers/staging/nmf-cm/cm/engine/component/inc/description.h new file mode 100644 index 00000000000..b7d3c34654d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/description.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#ifndef __INC_CM_COMPONENT_DESCRIPTION_H +#define __INC_CM_COMPONENT_DESCRIPTION_H + +#include +#include + +#include + +/*! + * \internal + * \brief Description of an interface + * \ingroup COMPONENT_INTERNAL + */ +typedef struct _t_interface_description { + t_dup_char type; //!< Type of the interface + t_uint16 referenceCounter; //!< Number of template referencing the interface + t_uint8 methodNumber; //!< Number of method in the interfaces + struct _t_interface_description* next; + t_dup_char methodNames[]; //!< Array of method names +} t_interface_description; + +/*! + * \internal + * \brief Description of a variable memory on a collection index + * \ingroup COMPONENT_INTERNAL + */ +typedef struct { + t_uint32 offset; //!< Offset in the memory + const t_elfmemory *memory; //!< Memory +} t_memory_reference; + +/*! + * \internal + * \brief Description of a required interface on a collection index + * \ingroup COMPONENT_INTERNAL + */ +typedef struct { + t_uint32 numberOfClient; //!< Number of interface descriptor really connected to this interface + t_memory_reference *memories; /*!< Memory where each interface reference descriptor resides + \note memories[numberOfClient] */ +} t_interface_require_index; + +/*! + * \internal + * \brief Description of a required interface + * \ingroup COMPONENT_INTERNAL + */ +typedef struct { + t_dup_char name; //!< Name of the interface + t_interface_description *interface; //!< Description of the interface + t_uint8 requireTypes; //!< Mask of t_elf_interface_require_type + t_uint8 collectionSize; //!< Size of the collection (1 if not a collection) + t_interface_require_index *indexes; /*!< Require information for each collection index + \note indexes[collectionSize] */ +} t_interface_require; + +/*! + * \internal + * \brief Description of a provided interface method on a collection index + * \ingroup COMPONENT_INTERNAL + */ +typedef struct { + t_uint32 methodAddresses; //!< Address of each method ; Available only when template loaded + t_memory_reference memory; //!< Memory of the method +} t_interface_provide_index; + +/*! + * \internal + * \brief Description of a provided interface + * \ingroup COMPONENT_INTERNAL + */ +typedef struct { + t_dup_char name; //!< Name of the interface + t_interface_description *interface; //!< Description of the interface + t_uint8 provideTypes; //!< Mask of t_elf_interface_provide_type + t_uint8 interruptLine; //!< Interrupt line if interrupt (0 if not) + t_uint8 collectionSize; //!< Size of the collection (1 if not a collection) + t_interface_provide_index **indexes; //!< Provide information for each collection index +} t_interface_provide; + +/*! + * \internal + * \brief Description of a attribute + * \ingroup COMPONENT_INTERNAL + */ +typedef struct { + t_dup_char name; //!< Name of the attribute + t_memory_reference memory; //!< Memory where the attribute reside +} t_attribute; + +/*! + * \internal + * \brief Description of a property + * \ingroup COMPONENT_INTERNAL + */ +typedef struct { + t_dup_char name; //!< Name of this attribute + t_dup_char value; //!< String of the value +} t_property; + + + + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/dspevent.h b/drivers/staging/nmf-cm/cm/engine/component/inc/dspevent.h new file mode 100644 index 00000000000..bb47363c0ae --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/dspevent.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef __INC_DSP_EVENT +#define __INC_DSP_EVENT + +#include +#include +#include + +/* value should be size of t_remote_event in mmdsp word */ +#define DSP_REMOTE_EVENT_SIZE_IN_DSPWORD 5 + +t_cm_error dspevent_createDspEventFifo( + const t_component_instance *pComp, + const char* nameOfTOP, + t_uint32 fifoNbElem, + t_uint32 fifoElemSizeInWord, + t_dsp_memory_type_id dspEventMemType, + t_memory_handle *pHandle); +void dspevent_destroyDspEventFifo(t_memory_handle handle); + +#endif /* __INC_DSP_EVENT */ diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/initializer.h b/drivers/staging/nmf-cm/cm/engine/component/inc/initializer.h new file mode 100644 index 00000000000..b4416f3ce20 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/initializer.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef __INC_NMF_INITIALIZER +#define __INC_NMF_INITIALIZER + +#include +#include +#include + +PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId); +PUBLIC t_cm_error cm_COMP_CallService(int serviceIndex, t_component_instance *pComp, t_uint32 methodAddress); +PUBLIC void cm_COMP_INIT_Close(t_nmf_core_id coreId); +PUBLIC t_cm_error cm_COMP_UpdateStack(t_nmf_core_id coreId, t_uint32 stackSize); +PUBLIC t_cm_error cm_COMP_ULPForceWakeup(t_nmf_core_id coreId); +PUBLIC t_cm_error cm_COMP_ULPAllowSleep(t_nmf_core_id coreId); +PUBLIC t_cm_error cm_COMP_InstructionCacheLock(t_nmf_core_id coreId, t_uint32 mmdspAddr, t_uint32 mmdspSize); +PUBLIC t_cm_error cm_COMP_InstructionCacheUnlock(t_nmf_core_id coreId, t_uint32 mmdspAddr, t_uint32 mmdspSize); + + +PUBLIC void processAsyncAcknowledge(t_nmf_core_id coreId, t_event_params_handle pParam); +PUBLIC void processSyncAcknowledge(t_nmf_core_id coreId, t_event_params_handle pParam); + +#endif /* __INC_NMF_INITIALIZER */ diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/instance.h b/drivers/staging/nmf-cm/cm/engine/component/inc/instance.h new file mode 100644 index 00000000000..1bef76501de --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/instance.h @@ -0,0 +1,220 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Components Management internal methods - Instance API. + * + */ +#ifndef __INC_CM_INSTANCE_H +#define __INC_CM_INSTANCE_H + +#include +#include +#include +#include +#include + +/*---------------------------------------------------------------------------- + * Component Instance API. + *----------------------------------------------------------------------------*/ +struct _t_interface_reference; + +/*! + * \internal + * \brief Component life cycle state + * + * \ingroup COMPONENT_INTERNAL + */ +typedef enum { + STATE_NONE, + STATE_STOPPED, + STATE_RUNNABLE, + // STATE_DESTROYED identified when component remove from component list +} t_component_state; + +struct t_client_of_singleton +{ + struct t_client_of_singleton *next; + t_nmf_client_id clientId; + t_uint16 numberOfInstance; + t_uint16 numberOfStart; + t_uint16 numberOfBind; +}; + +/*! + * \internal + * \brief Description of a component instance + * + * \ingroup COMPONENT_INTERNAL + */ +typedef struct t_component_instance { + t_dup_char pathname; //!< Path Name of this component in the components architecture + + t_component_state state; //!< Component state + t_nmf_ee_priority priority; //!< Executive engine component priority + t_component_template *template; //!< Component template + + t_uint32 thisAddress; //!< Cached value of cm_DSP_GetDspAddress(component->memories[data], &thisAddress); + + t_memory_handle memories[NUMBER_OF_MMDSP_MEMORY]; //!u.p.requires) + type == targets[interface_index][collection_index] */ + + t_uint16 providedItfUsedCount; //!< Use count to reference the number of components binded to this once, ie count the number of provided interfaces in use + t_cm_instance_handle instance; //!< index of this component within the ComponentTable + t_cm_domain_id domainId; //!< Domain where the component has been installed + + struct t_client_of_singleton *clientOfSingleton; //!< Client of singleton list +} t_component_instance; + +t_component_template* cm_lookupTemplate(t_nmf_core_id dspId, t_dup_char str); + +/*! + * \internal + * \brief Load a component template. + * + * ... + * + * \param[in] templateName name of the template to load + * \param[in] coreId DSP where template must be loaded + * \praem[in] pRepComponent Pointer to the component entry stored in the Component Cache Repository + * \param[in, out] template reference to put the loaded template (null if first instance) + * + * \exception CM_COMPONENT_NOT_FOUND + * \exception CM_NO_MORE_MEMORY + * + * \return exception number. + * + * \warning For Component manager use only. + * \ingroup COMPONENT_INTERNAL + */ +t_cm_error cm_loadComponent( + t_dup_char templateName, + t_cm_domain_id domainId, + t_elfdescription* elfhandle, + t_component_template **reftemplate); + +/*! + * \internal + * \brief Unload a component template. + * + * ... + * + * \param[in] template template to be unloaded + * \praem[in] Private memories that has been created from component binary file + * + * \return exception number. + * + * \warning For Component manager use only. + * \ingroup COMPONENT_INTERNAL + */ +t_cm_error cm_unloadComponent( + t_component_template *template); + +/*! + * \internal + * \brief Instantiate a component. + * + * \ingroup COMPONENT_INTERNAL + */ +t_cm_error cm_instantiateComponent(const char* templateName, + t_cm_domain_id domainId, + t_nmf_ee_priority priority, + const char* pathName, + t_elfdescription *elfhandle, + t_component_instance** refcomponent); + +struct t_client_of_singleton* cm_getClientOfSingleton(t_component_instance* component, t_bool createdIfNotExist, t_nmf_client_id clientId); + +/*! + * \internal + * \brief Start a component. + * + * \ingroup COMPONENT_INTERNAL + */ +t_cm_error cm_startComponent(t_component_instance* component, t_nmf_client_id clientId); + +/*! + * \internal + * \brief Stop a component. + * + * \ingroup COMPONENT_INTERNAL + */ +t_cm_error cm_stopComponent(t_component_instance* component, t_nmf_client_id clientId); + +/*! + * \internal + */ +typedef enum { + DESTROY_NORMAL, + DESTROY_WITHOUT_CHECK, + DESTROY_WITHOUT_CHECK_CALL +} t_destroy_state; + +/*! + * \internal + * \brief Destroy a component instance. + * + * \ingroup COMPONENT_INTERNAL + */ +t_cm_error cm_destroyInstance(t_component_instance* component, t_destroy_state forceDestroy); + +/*! + * \internal + * \brief Destroy a component instance. + * + * \ingroup COMPONENT_INTERNAL + */ +t_cm_error cm_destroyInstanceForClient(t_component_instance* component, t_destroy_state forceDestroy, t_nmf_client_id clientId); + +/*! + * \internal + * \brief + * + * \ingroup COMPONENT_INTERNAL + */ +void cm_delayedDestroyComponent(t_component_instance *component); + +/*! + * \internal + * \brief + * + * \ingroup COMPONENT_INTERNAL + */ +t_component_instance *cm_lookupComponent(const t_cm_instance_handle hdl); + +/*! + * \internal + * \brief + * + * \ingroup COMPONENT_INTERNAL + */ +t_bool cm_isComponentOnCoreId(t_nmf_core_id coreId); + +/*! + * \internal + * \brief + * + * \ingroup COMPONENT_INTERNAL + */ +t_cm_error cm_COMP_Init(void); + +/*! + * \internal + * \brief + * + * \ingroup COMPONENT_INTERNAL + */ +void cm_COMP_Destroy(void); + +/* + * Table of instantiated components. + */ +extern t_nmf_table ComponentTable; /**< list (table) of components */ +#define componentEntry(i) ((t_component_instance *)ComponentTable.entries[i]) +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/introspection.h b/drivers/staging/nmf-cm/cm/engine/component/inc/introspection.h new file mode 100644 index 00000000000..cfb55c91779 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/introspection.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Components Management internal methods - Introspection. + * + */ +#ifndef __INC_CM_INTROSPECTION_H +#define __INC_CM_INTROSPECTION_H + +#include + +/*! + * \internal + * \brief Description of a required interface reference + * + * \ingroup COMPONENT_INTERNAL + */ +typedef struct { + const t_component_instance *client; //!< Component that provide this interface + t_uint8 requireIndex; //!< Index of the interface in the require array + t_uint8 collectionIndex; //!< Index in the collection if required interface is a collection + const char* origName; //!< Name of the component interface +} t_interface_require_description; + +/*! + * \internal + * \brief Description of a provided interface + * + * \ingroup COMPONENT_INTERNAL + */ +typedef struct { + const t_component_instance *server; //!< Component that provide this interface + t_uint8 provideIndex; //!< Index of the interface in the provide array + t_uint8 collectionIndex; //!< Index in the collection if provided interface is a collection + const char* origName; //!< Name of the component interface +} t_interface_provide_description; + + +/*! + * \internal + * \brief Get property of a component. + * + * \ingroup COMPONENT_INTERNAL + */ +t_cm_error cm_getComponentProperty( + const t_component_instance *component, + const char *propName, + char value[MAX_PROPERTY_VALUE_LENGTH], + t_uint32 valueLength); + + +t_dsp_address cm_getAttributeMpcAddress( + const t_component_instance *component, + const char *attrName); + +t_cm_logical_address cm_getAttributeHostAddr( + const t_component_instance *component, + const char *attrName); + +t_uint32 cm_readAttributeNoError( + const t_component_instance *component, + const char *attrName); + +t_cm_error cm_readAttribute( + const t_component_instance *component, + const char *attrName, + t_uint32 *value); + +t_cm_error cm_writeAttribute( + const t_component_instance *component, + const char *attrName, + t_uint32 value); + +/*! + * \internal + * \brief Get internal component symbol + * + * \ingroup COMPONENT_INTERNAL + */ +t_dsp_address cm_getFunction( + const t_component_instance* component, + const char* interfaceName, + const char* methodName); + +/*! + * \internal + * \brief Get interface provided by a component instance. + * + * \ingroup COMPONENT_INTERNAL + */ +t_cm_error cm_getProvidedInterface(const t_component_instance* server, + const char* itfName, + t_interface_provide_description *itfProvide); + +/*! + * \internal + * \brief Get interface required by a component instance. + * + * \ingroup COMPONENT_INTERNAL + */ +t_cm_error cm_getRequiredInterface(const t_component_instance* server, + const char* itfName, + t_interface_require_description *itfRequire); + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/nmfheaderabi.h b/drivers/staging/nmf-cm/cm/engine/component/inc/nmfheaderabi.h new file mode 100644 index 00000000000..59d2186f157 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/nmfheaderabi.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief NMF component description ABI + * + * \defgroup NMF_HEADER NMF Component Description ABI + * The NMF component description ABI is stored in the nmf_segment in the ELF component file. + * The NMF component description section start by the t_elf_component_header structure. + * + * \warning The format of this section is not fixed and is able to be changed without concerting. + * \note You can use the nmfHeaderVersion to check if the format has changed. + * \note Each pointers in this section is relative to the beginning of the section and must be relocated before used. + * \ingroup NMF_ABI + */ +#ifndef __INC_CM_NMF_HEADERABI_H +#define __INC_CM_NMF_HEADERABI_H + +#include + +/*! + * \brief Description of a interface + * \ingroup NMF_HEADER + */ +typedef struct { + char *type; //!< Type of this Interface + t_uint8 methodNumber; //!< Number of method in the interfaces + t_uint8 reserved1, reserved2, reserved3; + char *methodNames[]; //!< Array of method names +} t_elf_interface_description; + +/*! + * \brief Description of required interface type (value could be combinated) + * \ingroup NMF_HEADER + */ +typedef enum { + COLLECTION_REQUIRE = 1, //!< Required interface is a collection + OPTIONAL_REQUIRE = 2, //!< Required interface if optional + STATIC_REQUIRE = 4, //!< Required interface is static + VIRTUAL_REQUIRE = 8, //!< Required interface is virtual (only for introspection purpose) + INTRINSEC_REQUIRE = 16 //!< Required interface is intrinsec (bind automatically done by runtime) +} t_elf_interface_require_type; + +/*! + * \brief Description of a required interface on a collection index + * \ingroup NMF_HEADER + */ +typedef struct { + t_uint32 numberOfClient; //!< Number of interface descriptor really connected to this interface + t_uint32 symbols[1]; /*!< Symbol of the real name of the attribute + \note Real type symbols[numberOfClient] + \note Use relocation in order to get symbol information */ +} t_elf_interface_require_index; + +/*! + * \brief Description of an interface required + * \ingroup NMF_HEADER + */ +typedef struct { + char *name; //!< name of the interface: offset in string segment + t_uint8 requireTypes; //!< Mask of t_elf_interface_require_type + t_uint8 collectionSize; //!< Size of the collection (1 if not a collection) + t_uint8 reserved1, reserved2; + t_elf_interface_description *interface; //!< Interface description + t_elf_interface_require_index indexes[]; /*!< Require information for each collection index + \note Real type: indexes[collectionSize], + available only if not static interface */ +} t_elf_required_interface; + +/*! + * \brief Description of provided interface type (value could be combinated) + * \ingroup NMF_HEADER + */ +typedef enum { + COLLECTION_PROVIDE = 1, //!< Provided interface is a collection + VIRTUAL_PROVIDE = 2 //!< Provided interface is virtual (only for introspection purpose) +} t_elf_interface_provide_type; + +/*! + * \brief Description of an interface provided + * \ingroup NMF_HEADER + */ +typedef struct { + char* name; //!< name of the interface: offset in string segment + t_uint8 provideTypes; //!< Mask of t_elf_interface_provide_type + t_uint8 interruptLine; //!< Interrupt line if interrupt (0 if not) + t_uint8 collectionSize; //!< Size of the collection (1 if not a collection) + t_uint8 reserved1; + t_elf_interface_description *interface; //!< Interface description + t_uint32 methodSymbols[]; /*!< Symbol of the real name of methods of the interface for each collection index + \note Real type: methodSymbols[collectionSize][methodNumber] + \note Use relocation in order to get symbol information*/ +} t_elf_provided_interface; + +/*! + * \brief Description of an attribute + * \ingroup NMF_HEADER + */ +typedef struct { + char* name; //!< Name of this attribute + t_uint32 symbols; /*!< Symbol of the real name of the attribute + \note Use relocation in order to get symbol information */ +} t_elf_attribute; + +/*! + * \brief Description of an property + * \ingroup NMF_HEADER + */ +typedef struct { + char* name; //!< Name of this attribute + char* value; //!< String of the value +} t_elf_property; + +#define MAGIC_COMPONENT 0x123 //!< Magic Number for a component \ingroup NMF_HEADER +#define MAGIC_SINGLETON 0x321 //!< Magic Number for a singleton component \ingroup NMF_HEADER +#define MAGIC_FIRMWARE 0x456 //!< Magic Number for Execution Engine Component \ingroup NMF_HEADER + +/*! + * \brief Description of a ELF component header + * + * The NMF component description section start by this structure. + * + * \ingroup NMF_HEADER + */ +typedef struct { + t_uint32 magic; //!< Magic Number + t_uint32 nmfVersion; //!< Version of the NMF Header + + char* templateName; //!< Name of the component template + + t_uint32 LCCConstruct; //!< Life cycle Constructor offset + t_uint32 LCCStart; //!< Life cycle Starter offset + t_uint32 LCCStop; //!< Life cycle Stopper offset + t_uint32 LCCDestroy; //!< Life cycle Destructer offset + + t_uint32 minStackSize; //!< Minimum stack size + + t_uint32 attributeNumber;//!< Number of attributes + t_elf_attribute *attributes; //!< Array of attributes (be careful, this reference must be relocated before use) + + t_uint32 propertyNumber; //!< Number of properties + t_elf_property *properties; //!< Array of properties (be careful, this reference must be relocated before use) + + t_uint32 provideNumber; //!< Number of interfaces provided + t_elf_provided_interface *provides; //!< Array of interfaces provided (be careful, this reference must be relocated before use) + + t_uint32 requireNumber; //!< Array of interfaces required + t_elf_required_interface *requires; //!< Array of interfaces required (be careful, this reference must be relocated before use) + +} t_elf_component_header; + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/template.h b/drivers/staging/nmf-cm/cm/engine/component/inc/template.h new file mode 100644 index 00000000000..3e1a2c001e4 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/template.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Components Management internal methods - Template API. + * + * \defgroup COMPONENT_INTERNAL Private component instances API + */ +#ifndef __INC_CM_TEMPLATE_H +#define __INC_CM_TEMPLATE_H + +#include +#include +#include +#include + + +/*! + * \internal + * \brief Class of a component + * \ingroup COMPONENT_INTERNAL + */ +typedef enum { + COMPONENT, //!< Primitive component + SINGLETON, //!< Singleton component + FIRMWARE, //!< Firmware composite component +} t_component_classe; + +/*! + * \internal + * \brief Description of delayed relocation + * \ingroup COMPONENT_INTERNAL + */ +typedef struct _t_function_relocation { + t_dup_char symbol_name; + t_uint32 type; + char *reloc_addr; + struct _t_function_relocation *next; +} t_function_relocation; + +struct t_component_instance; + +/*! + * \internal + * \brief Description of a component template + * \ingroup COMPONENT_INTERNAL + */ +typedef struct _t_component_template { + t_dup_char name; //!< Template name (a.k.a component type) + + t_component_classe classe; //!< Class of the component + //TODO, juraj, remove dspId + t_nmf_core_id dspId; //!< Reference on DSP where template is loaded + + t_uint8 numberOfInstance; //!< Number of same instance (or singleton copy) create from this template + + t_uint8 propertyNumber; //!< Number of properties in this template + t_uint8 attributeNumber; //!< Number of attributes in this template + t_uint8 provideNumber; //!< Number of interface provided by this template + t_uint8 requireNumber; //!< Number of interface required by this template + + t_uint32 LCCConstructAddress; //!< Life cycle Constructor address + t_uint32 LCCStartAddress; //!< Life cycle Starter address + t_uint32 LCCStopAddress; //!< Life cycle Stopper address + t_uint32 LCCDestroyAddress; //!< Life cycle Destructer address + + t_uint32 minStackSize; //!< Minimum stack size + + t_memory_handle memories[NUMBER_OF_MMDSP_MEMORY]; //!< Reference in different memory where datas are (YES, we fix implementation to MMDSP) + const t_elfmemory *thisMemory; //!< Memory used to determine this + const t_elfmemory *codeMemory; //!< Memory used to determine code + + t_function_relocation *delayedRelocation; //!< List of reference that can't been relocatable while appropritae binding done. + + t_property *properties; //!< Array of properties in this template + t_attribute *attributes; //!< Array of attributes in this template + t_interface_provide *provides; //!< Array of interface provided by this template + t_interface_require *requires; //!< Array of interface required by this template + + t_bool descriptionAssociatedWithTemplate; + + struct _t_component_template *prev, *next; + struct t_component_instance *singletonIfAvaliable; +} t_component_template; + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/binder.c b/drivers/staging/nmf-cm/cm/engine/component/src/binder.c new file mode 100644 index 00000000000..8586fdfcbc8 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/src/binder.c @@ -0,0 +1,1310 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include "../inc/bind.h" +#include "../inc/dspevent.h" +#include +#include +#include + +#include +#include + +#include + +#define CM_IT_NAME_MAX_LENGTH 8 + +t_nmf_table Host2MpcBindingTable; /**< list (table) of host2mpc bindings */ + +static void cm_fillItName(int interruptLine, char *itName); +static t_uint16 getNumberOfBind(t_component_instance* component); + +/* + * Bind virtual interface, here we assume that: + * - client component require this interface as last one and without collection, + * - server component provide only this interface and without collection. + * Fixed in loader.c. + */ +static void cm_bindVirtualInterface( + t_component_instance* client, + const t_component_instance* server) { + t_interface_require_description itfRequire; + + if(cm_getRequiredInterface(client, "coms", &itfRequire) == CM_OK) + { + t_interface_reference* itfRef = client->interfaceReferences[itfRequire.requireIndex]; + + /* + * Memorise this reference + */ + itfRef->provideIndex = 0; + itfRef->collectionIndex = 0; + itfRef->instance = server; + itfRef->bfInfoID = (t_bf_info_ID)0; + itfRef->bfInfo = (void*)-1; // TODO + } + else + { + ERROR("Internal Error in cm_bindVirtualInterface\n", 0, 0, 0, 0, 0, 0); + } +} + +static void cm_unbindVirtualInterface( + t_component_instance* client) { + t_interface_require_description itfRequire; + + if(cm_getRequiredInterface(client, "coms", &itfRequire) == CM_OK) + { + t_interface_reference* itfRef = client->interfaceReferences[itfRequire.requireIndex]; + itfRef->instance = NULL; + } + else + { + ERROR("Internal Error in cm_unbindVirtualInterface\n", 0, 0, 0, 0, 0, 0); + } +} + +/* + * Bind component + */ +static void cm_bindLowLevelInterface( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfLocalBC, /* On the same DSP */ + t_bf_info_ID bfInfoID, void* bfInfo) +{ + const t_component_instance* client = itfRequire->client; + t_component_instance* server = (t_component_instance*)itfLocalBC->server; + t_interface_require *require = &client->template->requires[itfRequire->requireIndex]; + t_interface_provide* provide = &server->template->provides[itfLocalBC->provideIndex]; + int k, j; + + if(require->indexes != NULL) + { + t_interface_require_index *requireindex = &require->indexes[itfRequire->collectionIndex]; + + for(k = 0; k < requireindex->numberOfClient; k++) { + t_uint32 *hostAddr; + + hostAddr = (t_uint32*)( + cm_DSP_GetHostLogicalAddress(client->memories[requireindex->memories[k].memory->id]) + + requireindex->memories[k].offset * requireindex->memories[k].memory->memEntSize); + + LOG_INTERNAL(2, "Fill ItfRef %s.%s mem=%s Off=%x @=%x\n", + client->pathname, require->name, + requireindex->memories[k].memory->memoryName, + requireindex->memories[k].offset, + hostAddr, 0); + + /* + * Fill the interface references. We start by This then methods in order to keep + * Unbinded panic as long as possible and not used method with wrong This. This is + * relevent only for optional since we must go in stop state before rebinding other + * required interface. + * + * Direct write to DSP memory without go through DSP abstraction since we know we are in 24bits + */ + // Write THIS reference into the Data field of the interface reference + // Write the interface methods reference + + if(((t_uint32)hostAddr & 0x7) == 0 && require->interface->methodNumber > 0) + { + // We are 64word byte aligned, combine this write with first method + *(volatile t_uint64*)hostAddr = + ((t_uint64)server->thisAddress << 0) | + ((t_uint64)provide->indexes[itfLocalBC->collectionIndex][0].methodAddresses << 32); + hostAddr += 2; + j = 1; + } + else + { + // We are not, write this which will align us + *hostAddr++ = (t_uint32)server->thisAddress; + j = 0; + } + + // Word align copy + for(; j < require->interface->methodNumber - 1; j+=2) { + *(volatile t_uint64*)hostAddr = + ((t_uint64)provide->indexes[itfLocalBC->collectionIndex][j].methodAddresses << 0) | + ((t_uint64)provide->indexes[itfLocalBC->collectionIndex][j+1].methodAddresses << 32); + hostAddr += 2; + } + + // Last word align if required + if(j < require->interface->methodNumber) + *hostAddr = provide->indexes[itfLocalBC->collectionIndex][j].methodAddresses; + } + } + else + { + t_function_relocation *reloc = client->template->delayedRelocation; + while(reloc != NULL) { + for(j = 0; j < provide->interface->methodNumber; j++) + { + if(provide->interface->methodNames[j] == reloc->symbol_name) { + cm_ELF_performRelocation( + reloc->type, + reloc->symbol_name, + provide->indexes[itfLocalBC->collectionIndex][j].methodAddresses, + reloc->reloc_addr); + break; + } + } + + reloc = reloc -> next; + } + } + + /* + * Memorise this reference + */ + { + t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; + + itfRef->provideIndex = itfLocalBC->provideIndex; + itfRef->collectionIndex = itfLocalBC->collectionIndex; + itfRef->instance = itfLocalBC->server; + itfRef->bfInfoID = bfInfoID; + itfRef->bfInfo = bfInfo; + + /* + * Do not count binding from EE (ie interrupt line), as this will prevent + * cm_destroyInstance() of server to succeed (interrupt line bindings are + * destroyed after the check in cm_destroyInstance() + */ + if (client->template->classe != FIRMWARE) + server->providedItfUsedCount++; + } +} + +static void cm_registerLowLevelInterfaceToConst( + const t_interface_require_description *itfRequire, + const t_component_instance* targetInstance) +{ + const t_component_instance* client = itfRequire->client; + + /* + * Memorise this no reference + */ + { + t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; + + // This is an unbind from a true component (not to void) + // Do not count bindings from EE (ie interrupt line) + if ((targetInstance == NULL) + && (client->template->classe != FIRMWARE) + && (itfRef->instance != (t_component_instance *)NMF_VOID_COMPONENT) + && (itfRef->instance != NULL)) + { + ((t_component_instance*)itfRef->instance)->providedItfUsedCount--; + } + + itfRef->instance = targetInstance; + itfRef->bfInfoID = BF_SYNCHRONOUS; // Just to memorize no Binding component used and unbind ToVoid happy ;-). + } +} + +static void cm_bindLowLevelInterfaceToConst( + const t_interface_require_description *itfRequire, + const t_dsp_address functionAddress, + const t_component_instance* targetInstance) { + const t_component_instance* client = itfRequire->client; + t_interface_require *require = &client->template->requires[itfRequire->requireIndex]; + int j, k; + + + // If DSP is off/panic/... -> write nothing + if( + require->indexes != NULL + && cm_DSP_GetState(client->template->dspId)->state == MPC_STATE_BOOTED) + { + t_interface_require_index *requireindex = &require->indexes[itfRequire->collectionIndex]; + + for(k = 0; k < requireindex->numberOfClient; k++) { + t_uint32 *hostAddr; + + hostAddr = (t_uint32*)( + cm_DSP_GetHostLogicalAddress(client->memories[requireindex->memories[k].memory->id]) + + requireindex->memories[k].offset * requireindex->memories[k].memory->memEntSize); + + /* + * Fill the interface references. We start by Methods then This in order to swith to + * Unbinded panic as fast as possible and not used method with wrong This. This is + * relevent only for optional since we must go in stop state before rebinding other + * required interface. + * + * Direct write to DSP memory without go through DSP abstraction since we know we are in 24bits + */ + /* + * Write THIS reference into the Data field of the interface reference + * Hack for simplifying debug just to keep THIS reference with caller one + * (could be removed if __return_address MMDSP intrinsec provided by compiler). + */ + // Write the interface methods reference + + if(((t_uint32)hostAddr & 0x7) == 0 && require->interface->methodNumber > 0) + { + // We are 64word byte aligned, combine this write with first method + *(volatile t_uint64*)hostAddr = + ((t_uint64)client->thisAddress << 0) | + ((t_uint64)functionAddress << 32); + hostAddr += 2; + j = 1; + } + else + { + // We are not, write this which will align us + *hostAddr++ = (t_uint32)client->thisAddress; + j = 0; + } + + // Word align copy + for(; j < require->interface->methodNumber - 1; j+=2) { + *(volatile t_uint64*)hostAddr = + ((t_uint64)functionAddress << 0) | + ((t_uint64)functionAddress << 32); + hostAddr += 2; + } + + // Last word align if required + if(j < require->interface->methodNumber) + *hostAddr = functionAddress; + } + } + + cm_registerLowLevelInterfaceToConst(itfRequire, targetInstance); +} + +/* + * Bind User component though primitive binding factory + */ +t_cm_error cm_bindInterface( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide) { + + LOG_INTERNAL(1, "\n##### Bind Synchronous %s/%x.%s -> %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server, itfProvide->origName); + + cm_bindLowLevelInterface( + itfRequire, + itfProvide, + BF_SYNCHRONOUS, NULL); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, + itfRequire->client, itfProvide->server, + itfRequire->client->template->requires[itfRequire->requireIndex].name, + itfProvide->server->template->provides[itfProvide->provideIndex].name); + + return CM_OK; +} + +/* + * + */ +void cm_unbindInterface( + const t_interface_require_description *itfRequire) { + + LOG_INTERNAL(1, "\n##### UnBind synchronous %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_SYNCHRONOUS, + itfRequire->client, NULL, + itfRequire->client->template->requires[itfRequire->requireIndex].name, + NULL); + + cm_bindLowLevelInterfaceToConst(itfRequire, + 0x0, + NULL); +} + +/* + * + */ +t_cm_error cm_bindInterfaceToVoid( + const t_interface_require_description *itfRequire) { + LOG_INTERNAL(1, "\n##### Bind %s/%x.%s -> Void #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_bindLowLevelInterfaceToConst(itfRequire, + cm_EEM_getExecutiveEngine(itfRequire->client->template->dspId)->voidAddr, + (t_component_instance*)NMF_VOID_COMPONENT); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, + itfRequire->client, NULL, + itfRequire->client->template->requires[itfRequire->requireIndex].name, + NULL); + + return CM_OK; +} +/* + * Find the server and its interface inded to a given required interface for a given component + */ +t_cm_error cm_lookupInterface( + const t_interface_require_description *itfRequire, + t_interface_provide_description *itfProvide) { + const t_component_instance* client = itfRequire->client; + t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; + + if(itfRef->instance != NULL) + { + itfProvide->server = itfRef->instance; + itfProvide->provideIndex = itfRef->provideIndex; + itfProvide->collectionIndex = itfRef->collectionIndex; + + return CM_OK; + } else { + itfProvide->server = NULL; + return CM_INTERFACE_NOT_BINDED; + } +} + +/* + * + */ +t_cm_error cm_bindInterfaceTrace( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide, + t_elfdescription *elfhandleTrace) +{ + t_interface_require *require = &itfRequire->client->template->requires[itfRequire->requireIndex]; + t_interface_require_description bcitfRequire; + t_interface_provide_description bcitfProvide; + t_trace_bf_info *bfInfo; + t_cm_error error; + + LOG_INTERNAL(1, "\n##### Bind Synchronous Trace %s/%x.%s -> %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server, itfProvide->origName); + + /* Allocate aynchronous binding factory information */ + bfInfo = (t_trace_bf_info*)OSAL_Alloc(sizeof(t_trace_bf_info)); + if(bfInfo == 0) + return CM_NO_MORE_MEMORY; + + /* + * Instantiate related trace on dsp + */ + { + char traceTemplateName[4 + MAX_INTERFACE_TYPE_NAME_LENGTH + 1]; + + cm_StringCopy(traceTemplateName,"_tr.", sizeof(traceTemplateName)); + cm_StringConcatenate(traceTemplateName, require->interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + + if ((error = cm_instantiateComponent( + traceTemplateName, + itfRequire->client->domainId, + itfProvide->server->priority, + traceDup, + elfhandleTrace, + &bfInfo->traceInstance)) != CM_OK) { + OSAL_Free(bfInfo); + return (error == CM_COMPONENT_NOT_FOUND)?CM_BINDING_COMPONENT_NOT_FOUND : error; + } + } + + /* Bind event to server interface (Error must not occure) */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->traceInstance, "target", &bcitfRequire) == CM_OK); + + cm_bindLowLevelInterface(&bcitfRequire, itfProvide, BF_SYNCHRONOUS, NULL); + + /* Get the event interface (Error must not occure) */ + CM_ASSERT(cm_getProvidedInterface(bfInfo->traceInstance, "target", &bcitfProvide) == CM_OK); + + /* Bind client to event (Error must not occure) */ + cm_bindLowLevelInterface(itfRequire, &bcitfProvide, BF_TRACE, bfInfo); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, + itfRequire->client, itfProvide->server, + itfRequire->client->template->requires[itfRequire->requireIndex].name, + itfProvide->server->template->provides[itfProvide->provideIndex].name); + + return CM_OK; +} + +void cm_unbindInterfaceTrace( + const t_interface_require_description *itfRequire, + t_trace_bf_info *bfInfo) +{ + t_interface_require_description traceitfRequire; + + LOG_INTERNAL(1, "\n##### UnBind trace synchronous %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_SYNCHRONOUS, + itfRequire->client, NULL, + itfRequire->client->template->requires[itfRequire->requireIndex].name, + NULL); + + /* Unbind Client from Event Binding Component */ + cm_bindLowLevelInterfaceToConst(itfRequire, 0x0, NULL); + + /* Unbind explicitly Event from Server Binding Component */ + /* This is mandatory to fix the providedItfUsedCount of the server */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->traceInstance, "target", &traceitfRequire) == CM_OK); + + cm_registerLowLevelInterfaceToConst(&traceitfRequire, NULL); + + /* Destroy Event Binding Component */ + cm_destroyInstance(bfInfo->traceInstance, DESTROY_WITHOUT_CHECK); + + /* Free BF info */ + OSAL_Free(bfInfo); +} + + +/* + * + */ +t_cm_error cm_bindInterfaceAsynchronous( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide, + t_uint32 fifosize, + t_dsp_memory_type_id dspEventMemType, + t_elfdescription *elfhandleEvent) { + t_interface_require *require = &itfRequire->client->template->requires[itfRequire->requireIndex]; + t_interface_require_description eventitfRequire; + t_interface_provide_description eventitfProvide; + t_async_bf_info *bfInfo; + t_cm_error error; + + LOG_INTERNAL(1, "\n##### Bind Asynchronous %s/%x.%s -> %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server, itfProvide->origName); + + /* Allocate aynchronous binding factory information */ + bfInfo = (t_async_bf_info*)OSAL_Alloc(sizeof(t_async_bf_info)); + if(bfInfo == 0) + return CM_NO_MORE_MEMORY; + + /* + * Instantiate related event on dsp + */ + { + char eventTemplateName[4 + MAX_INTERFACE_TYPE_NAME_LENGTH + 1]; + + cm_StringCopy(eventTemplateName,"_ev.", sizeof(eventTemplateName)); + cm_StringConcatenate(eventTemplateName, require->interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + + if ((error = cm_instantiateComponent( + eventTemplateName, + itfRequire->client->domainId, + itfProvide->server->priority, + eventDup, + elfhandleEvent, + &bfInfo->eventInstance)) != CM_OK) { + OSAL_Free(bfInfo); + return (error == CM_COMPONENT_NOT_FOUND)?CM_BINDING_COMPONENT_NOT_FOUND : error; + } + } + + /* + * Initialize the event component + */ + { + unsigned int size; + + // Get fifo elem size (which was store in TOP by convention) + size = cm_readAttributeNoError(bfInfo->eventInstance, "TOP"); + LOG_INTERNAL(3, "DspEvent Fifo element size = %d\n", size, 0, 0, 0, 0, 0); + + // Allocate fifo + if ((error = dspevent_createDspEventFifo(bfInfo->eventInstance, + "TOP", + fifosize, size, + dspEventMemType, + &bfInfo->dspfifoHandle)) != CM_OK) + { + cm_destroyInstance(bfInfo->eventInstance, DESTROY_WITHOUT_CHECK); + OSAL_Free(bfInfo); + return error; + } + } + + /* Bind event to server interface (Error must not occure) */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->eventInstance, "target", &eventitfRequire) == CM_OK); + + cm_bindLowLevelInterface(&eventitfRequire, itfProvide, BF_SYNCHRONOUS, NULL); + + /* Get the event interface (Error must not occure) */ + CM_ASSERT(cm_getProvidedInterface(bfInfo->eventInstance, "target", &eventitfProvide) == CM_OK); + + /* Bind client to event (Error must not occure) */ + cm_bindLowLevelInterface(itfRequire, &eventitfProvide, BF_ASYNCHRONOUS, bfInfo); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, + itfRequire->client, itfProvide->server, + itfRequire->client->template->requires[itfRequire->requireIndex].name, + itfProvide->server->template->provides[itfProvide->provideIndex].name); + + return CM_OK; +} + +void cm_unbindInterfaceAsynchronous( + const t_interface_require_description *itfRequire, + t_async_bf_info *bfInfo) +{ + t_interface_require_description eventitfRequire; + + LOG_INTERNAL(1, "\n##### UnBind asynchronous %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, + itfRequire->client, NULL, + itfRequire->client->template->requires[itfRequire->requireIndex].name, + NULL); + + /* Unbind Client from Event Binding Component */ + cm_bindLowLevelInterfaceToConst(itfRequire, 0x0, NULL); + + /* Unbind explicitly Event from Server Binding Component */ + /* This is mandatory to fix the providedItfUsedCount of the server */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->eventInstance, "target", &eventitfRequire) == CM_OK); + + cm_registerLowLevelInterfaceToConst(&eventitfRequire, NULL); + + /* Destroy Event fifo */ + dspevent_destroyDspEventFifo(bfInfo->dspfifoHandle); + + /* Destroy Event Binding Component */ + cm_destroyInstance(bfInfo->eventInstance, DESTROY_WITHOUT_CHECK); + + /* Free BF info */ + OSAL_Free(bfInfo); +} + +/*! + * Create Shared FIFO and set stub and skeleton to it + */ +PRIVATE t_cm_error cm_createParamsFifo(t_component_instance *stub, + t_component_instance *skeleton, + t_cm_domain_id domainId, + t_uint32 fifosize, + t_nmf_fifo_arm_desc **fifo, + t_uint32 *fifoElemSize, + t_uint32 bcDescSize) +{ + t_nmf_core_id stubcore = (stub != NULL) ?(stub->template->dspId): ARM_CORE_ID; + t_nmf_core_id skelcore = (skeleton != NULL) ?(skeleton->template->dspId) : ARM_CORE_ID; + t_component_instance *bcnotnull = (stub != NULL) ? stub : skeleton; + int _fifoelemsize; + + CM_ASSERT(bcnotnull != NULL); + + /* Get fifo param elem size (which was store in FIFO by convention) */ + _fifoelemsize = cm_readAttributeNoError(bcnotnull, "FIFO"); + LOG_INTERNAL(3, "Fifo Params element size = %d\n", _fifoelemsize, 0, 0, 0, 0, 0); + if(fifoElemSize != NULL) + *fifoElemSize = _fifoelemsize; + + /* Allocation of the fifo params */ + *fifo = fifo_alloc(stubcore, skelcore, _fifoelemsize, fifosize, 1+bcDescSize, paramsLocation, extendedFieldLocation, domainId); /* 1+nbMethods fro hostBCThis_or_TOP space */ + if(*fifo == NULL) + return CM_NO_MORE_MEMORY; + + if(stub != NULL) + { + /* Set stub FIFO attribute (Error mut not occure) */ + cm_writeAttribute(stub, "FIFO", (*fifo)->dspAdress); + + LOG_INTERNAL(2, " FIFO param %x:%x\n", *fifo, (*fifo)->dspAdress, 0, 0, 0, 0); + } + + if(skeleton != NULL) + { + /* Set Skeleton FIFO attribute (Error mut not occure) */ + cm_writeAttribute(skeleton, "FIFO", (*fifo)->dspAdress); + + LOG_INTERNAL(2, " FIFO param %x:%x\n", *fifo, (*fifo)->dspAdress, 0, 0, 0, 0); + } + + return CM_OK; +} +/** + * + */ +static void cm_destroyParamsFifo(t_nmf_fifo_arm_desc *fifo) { + fifo_free(fifo); +} + +/*! + * Create DSP skeleton + */ +PRIVATE t_cm_error cm_createDSPSkeleton( + const t_interface_provide_description *itfProvide, + t_uint32 fifosize, + t_dsp_memory_type_id dspEventMemType, //INTERNAL_XRAM24 + t_elfdescription *elfhandleSkeleton, + t_dspskel_bf_info *bfInfo) +{ + t_interface_provide *provide = &itfProvide->server->template->provides[itfProvide->provideIndex]; + t_interface_require_description skelitfRequire; + t_cm_error error; + unsigned int fifoeventsize = 0; + + /* Instantiate related stub on dsp */ + { + char stubTemplateName[4 + MAX_INTERFACE_TYPE_NAME_LENGTH + 1]; + + cm_StringCopy(stubTemplateName,"_sk.", sizeof(stubTemplateName)); + cm_StringConcatenate(stubTemplateName, provide->interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + + if ((error = cm_instantiateComponent( + stubTemplateName, + itfProvide->server->domainId, + itfProvide->server->priority, + skeletonDup, + elfhandleSkeleton, + &bfInfo->skelInstance)) != CM_OK) { + return ((error == CM_COMPONENT_NOT_FOUND)?CM_BINDING_COMPONENT_NOT_FOUND:error); + } + } + + /* Get fifo elem size (which was store in TOP by convention) */ + fifoeventsize = cm_readAttributeNoError(bfInfo->skelInstance, "TOP"); + LOG_INTERNAL(3, "DspEvent Fifo element size = %d\n", fifoeventsize, 0, 0, 0, 0, 0); + + /* Allocation of the itf event dsp fifo */ + if ((error = dspevent_createDspEventFifo( + bfInfo->skelInstance, + "TOP", + fifosize, + fifoeventsize, + dspEventMemType, + &bfInfo->dspfifoHandle)) != CM_OK) + { + cm_destroyInstance(bfInfo->skelInstance, DESTROY_WITHOUT_CHECK); + return error; + } + + /* Bind stub to server component (Error must not occure) */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->skelInstance, "target", &skelitfRequire) == CM_OK); + + cm_bindLowLevelInterface(&skelitfRequire, itfProvide, BF_SYNCHRONOUS, NULL); + + return CM_OK; +} + +/** + * Destroy DSP Skeleton + */ +PRIVATE t_cm_error cm_destroyDSPSkeleton(t_dspskel_bf_info *bfInfo) { + t_interface_require_description skelitfRequire; + + /* Unbind explicitly stub from server component (Error must not occure) */ + /* This is mandatory to fix the providedItfUsedCount of the server */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->skelInstance, "target", &skelitfRequire) == CM_OK); + + cm_registerLowLevelInterfaceToConst(&skelitfRequire, NULL); + + /* Destroy Event fifo */ + dspevent_destroyDspEventFifo(bfInfo->dspfifoHandle); + + /* Destroy Event Binding Component */ + return cm_destroyInstance(bfInfo->skelInstance, DESTROY_WITHOUT_CHECK); +} + +/* + * + */ +t_cm_error cm_bindComponentFromCMCore( + const t_interface_provide_description *itfProvide, + t_uint32 fifosize, + t_dsp_memory_type_id dspEventMemType, + t_elfdescription *elfhandleSkeleton, + t_host2mpc_bf_info **bfInfo) { + t_interface_provide *provide = &itfProvide->server->template->provides[itfProvide->provideIndex]; + t_dsp_offset shareVarOffset; + t_cm_error error; + + LOG_INTERNAL(1, "\n##### Bind HOST -> %s/%x.%s #####\n", + itfProvide->server->pathname, itfProvide->server, itfProvide->origName, 0, 0, 0); + + /* Allocate host2dsp binding factory information */ + *bfInfo = (t_host2mpc_bf_info*)OSAL_Alloc(sizeof(t_host2mpc_bf_info)); + if((*bfInfo) == 0) + return CM_NO_MORE_MEMORY; + + /* Create the Skeleton */ + if ((error = cm_createDSPSkeleton(itfProvide, + fifo_normalizeDepth(fifosize), /* We SHALL create DSP Skeleton before creating the Params Fifo, but we need in advance the real depth of this fifo */ + dspEventMemType, + elfhandleSkeleton, + &(*bfInfo)->dspskeleton)) != CM_OK) + { + OSAL_Free((*bfInfo)); + return error; + } + + /* Create the FIFO Params */ + if ((error = cm_createParamsFifo(NULL, + (*bfInfo)->dspskeleton.skelInstance, + itfProvide->server->domainId, + fifosize, + &(*bfInfo)->fifo, + NULL, + provide->interface->methodNumber)) != CM_OK) + { + cm_destroyDSPSkeleton(&(*bfInfo)->dspskeleton); + OSAL_Free((*bfInfo)); + return error; + } + + /* Set Target info in FIFO param to TOP */ + shareVarOffset = cm_getAttributeMpcAddress((*bfInfo)->dspskeleton.skelInstance, "TOP"); + + /* + * Set Target info in FIFO param to armThis + * Should not return any error + */ + fifo_params_setSharedField((*bfInfo)->fifo, 0, (t_shared_field)shareVarOffset /* ArmBCThis_or_TOP */); + + /* Initialise FIFO Param bcDesc with Skeleton methods */ + { + int i; + t_component_instance *skel = (*bfInfo)->dspskeleton.skelInstance; + for (i=0; i < provide->interface->methodNumber; i++) + { + /* should not return error */ + fifo_params_setSharedField( + (*bfInfo)->fifo, + 1+i, + skel->template->provides[0].indexes[0][i].methodAddresses + ); + } + } + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, + ARM_TRACE_COMPONENT, itfProvide->server, + NULL, + itfProvide->server->template->provides[itfProvide->provideIndex].name); + + return CM_OK; +} + +void cm_unbindComponentFromCMCore( + t_host2mpc_bf_info* bfInfo) { + t_component_instance *skel = bfInfo->dspskeleton.skelInstance; + t_interface_reference* itfProvide = &skel->interfaceReferences[0][0]; + t_interface_provide *provide = &itfProvide->instance->template->provides[itfProvide->provideIndex]; + + LOG_INTERNAL(1, "\n##### UnBind HOST -> %s/%x.%s #####\n", + itfProvide->instance->pathname, itfProvide->instance, provide->name, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, + ARM_TRACE_COMPONENT, itfProvide->instance, + NULL, + itfProvide->instance->template->provides[itfProvide->provideIndex].name); + + // Destroy FIFO params + cm_destroyParamsFifo(bfInfo->fifo); + + // Destory Skeleton + cm_destroyDSPSkeleton(&bfInfo->dspskeleton); + + // Free BF info (which contains bcDecr(==dspfct) and arm This) + OSAL_Free(bfInfo); +} + +/** + * Create DSP Stub + */ +PRIVATE t_cm_error cm_createDSPStub( + const t_interface_require_description *itfRequire, + const char* itfType, + t_dspstub_bf_info* bfInfo, + t_elfdescription *elfhandleStub, + t_interface_provide_description *itfstubProvide) { + t_cm_error error; + + /* + * Instantiate related skel on dsp + */ + { + char skelTemplateName[4 + MAX_INTERFACE_TYPE_NAME_LENGTH + 1]; + + cm_StringCopy(skelTemplateName, "_st.", sizeof(skelTemplateName)); + cm_StringConcatenate(skelTemplateName, itfType, MAX_INTERFACE_TYPE_NAME_LENGTH); + + if ((error = cm_instantiateComponent( + skelTemplateName, + itfRequire->client->domainId, + itfRequire->client->priority, + stubDup, + elfhandleStub, + &bfInfo->stubInstance)) != CM_OK) { + return (error == CM_COMPONENT_NOT_FOUND)?CM_BINDING_COMPONENT_NOT_FOUND : error; + } + } + + /* Get the internal component that serve this interface (Error must not occure) */ + (void)cm_getProvidedInterface(bfInfo->stubInstance, "source", itfstubProvide); + + return CM_OK; +} + +PRIVATE t_cm_error cm_destroyDSPStub( + const t_interface_require_description *itfRequire, + t_dspstub_bf_info* bfInfo) { + + /* Unbind Client from Event Binding Component */ + cm_bindLowLevelInterfaceToConst(itfRequire, + 0x0, + NULL); + + /* Destroy Event Binding Component */ + return cm_destroyInstance(bfInfo->stubInstance, DESTROY_WITHOUT_CHECK); +} +/* + * + */ +t_cm_error cm_bindComponentToCMCore( + const t_interface_require_description *itfRequire, + t_uint32 fifosize, + t_uint32 context, + t_elfdescription *elfhandleStub, + t_mpc2host_bf_info ** bfInfo) { + t_interface_require *require = &itfRequire->client->template->requires[itfRequire->requireIndex]; + t_interface_provide_description itfstubProvide; + t_cm_error error; + t_uint32 fifoelemsize; + + LOG_INTERNAL(1, "\n##### Bind %s/%x.%s -> HOST #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + /* Allocate dsp2host binding factory information */ + *bfInfo = (t_mpc2host_bf_info*)OSAL_Alloc(sizeof(t_mpc2host_bf_info)); + if(*bfInfo == 0) + return CM_NO_MORE_MEMORY; + (*bfInfo)->context = context; + + if ((error = cm_createDSPStub(itfRequire, + require->interface->type, + &(*bfInfo)->dspstub, + elfhandleStub, + &itfstubProvide)) != CM_OK) + { + OSAL_Free(*bfInfo); + return error; + } + + /* Create the FIFO Params */ + if ((error = cm_createParamsFifo( + (*bfInfo)->dspstub.stubInstance, + NULL, + itfRequire->client->domainId, + fifosize, + &(*bfInfo)->fifo, + &fifoelemsize, + 1)) != CM_OK) /* 1 => we used first field as max params size */ + { + cm_destroyDSPStub(itfRequire, &(*bfInfo)->dspstub); + OSAL_Free(*bfInfo); + return error; + } + + /* Bind client to stub component (Error must not occure) */ + cm_bindLowLevelInterface(itfRequire, &itfstubProvide, BF_DSP2HOST, *bfInfo); + + /* Bind stub component to host (virtual bind) */ + cm_bindVirtualInterface((*bfInfo)->dspstub.stubInstance, (t_component_instance*)NMF_HOST_COMPONENT); + + /* + * Set Target info in FIFO param to armThis + * Initialise FIFO Param bcDesc with Jumptable + * Should not return any error + */ + fifo_params_setSharedField((*bfInfo)->fifo, 0, (t_shared_field)context /* ArmBCThis_or_TOP */); + fifo_params_setSharedField((*bfInfo)->fifo, 1, (t_shared_field)fifoelemsize * 2/* bcDescRef */); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, + itfRequire->client, ARM_TRACE_COMPONENT, + itfRequire->client->template->requires[itfRequire->requireIndex].name, + NULL); + + return error; +} + +void cm_unbindComponentToCMCore( + const t_interface_require_description *itfRequire, + t_mpc2host_bf_info *bfInfo) +{ + LOG_INTERNAL(1, "\n##### UnBind %s/%x.%s -> HOST #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, + itfRequire->client, ARM_TRACE_COMPONENT, + itfRequire->client->template->requires[itfRequire->requireIndex].name, + NULL); + + /* Unbind virtual interface coms */ + cm_unbindVirtualInterface(bfInfo->dspstub.stubInstance); + + // Destroy FIFO params + cm_destroyParamsFifo(bfInfo->fifo); + + // Destroy DSP Stub + cm_destroyDSPStub(itfRequire, &bfInfo->dspstub); + + /* Free BF info */ + OSAL_Free(bfInfo); +} + +/*! + * + */ +t_cm_error cm_bindInterfaceDistributed( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide, + t_uint32 fifosize, + t_dsp_memory_type_id dspEventMemType, + t_elfdescription *elfhandleSkeleton, + t_elfdescription *elfhandleStub) { + t_interface_require *require = &itfRequire->client->template->requires[itfRequire->requireIndex]; + t_interface_provide_description itfstubProvide; + t_cm_error error; + t_mpc2mpc_bf_info *bfInfo; + t_dsp_offset shareVarOffset; + + LOG_INTERNAL(1, "\n##### Bind Distributed %s/%x.%s -> %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server, itfProvide->origName); + + /* Allocate aynchronous binding factory information */ + bfInfo = (t_mpc2mpc_bf_info*)OSAL_Alloc(sizeof(t_mpc2mpc_bf_info)); + if(bfInfo == 0) + return CM_NO_MORE_MEMORY; + + /* Create the Skeleton */ + if ((error = cm_createDSPSkeleton(itfProvide, + fifo_normalizeDepth(fifosize), /* We SHALL create DSP Skeleton before creating the Params Fifo, but we need in advance the real depth of this fifo */ + dspEventMemType, + elfhandleSkeleton, + &bfInfo->dspskeleton)) != CM_OK) + { + OSAL_Free(bfInfo); + return error; + } + + // Create DSP Stub + if ((error = cm_createDSPStub(itfRequire, + require->interface->type, + &bfInfo->dspstub, + elfhandleStub, + &itfstubProvide)) != CM_OK) + { + cm_destroyDSPSkeleton(&bfInfo->dspskeleton); + OSAL_Free(bfInfo); + return error; + } + + /* Bind client to stub component (Error must not occure) */ + cm_bindLowLevelInterface(itfRequire, &itfstubProvide, BF_DSP2DSP, bfInfo); + + /* Create the FIFO Params */ + if ((error = cm_createParamsFifo( + bfInfo->dspstub.stubInstance, + bfInfo->dspskeleton.skelInstance, + itfProvide->server->domainId, + fifosize, + &bfInfo->fifo, + NULL, + require->interface->methodNumber)) != CM_OK) + { + cm_destroyDSPStub(itfRequire, &bfInfo->dspstub); + cm_destroyDSPSkeleton(&bfInfo->dspskeleton); + OSAL_Free(bfInfo); + return error; + } + + /* Bind stub component to host (virtual bind) */ + cm_bindVirtualInterface(bfInfo->dspstub.stubInstance, bfInfo->dspskeleton.skelInstance); + + /* Set Target info in FIFO param to TOP */ + shareVarOffset = cm_getAttributeMpcAddress(bfInfo->dspskeleton.skelInstance, "TOP"); + + /* + * Set Target info in FIFO param to armThis + * Should not return any error + */ + fifo_params_setSharedField(bfInfo->fifo, 0, (t_shared_field)shareVarOffset /* ArmBCThis_or_TOP */); + + /* Initialise FIFO Param bcDesc with Skeleton methods */ + { + int i; + t_component_instance *skel = bfInfo->dspskeleton.skelInstance; + for (i=0; i < require->interface->methodNumber; i++) + { + /* should not return error */ + fifo_params_setSharedField( + bfInfo->fifo, + 1+i, + skel->template->provides[0].indexes[0][i].methodAddresses + ); + } + } + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, + itfRequire->client, itfProvide->server, + itfRequire->client->template->requires[itfRequire->requireIndex].name, + itfProvide->server->template->provides[itfProvide->provideIndex].name); + + return CM_OK; +} + +/*! + * + */ +void cm_unbindInterfaceDistributed( + const t_interface_require_description *itfRequire, + t_mpc2mpc_bf_info *bfInfo) +{ + LOG_INTERNAL(1, "\n##### UnBind distributed %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, + itfRequire->client, NULL, + itfRequire->client->template->requires[itfRequire->requireIndex].name, + NULL); + + /* Unbind virtual interface */ + cm_unbindVirtualInterface(bfInfo->dspstub.stubInstance); + + // Destroy FIFO params + cm_destroyParamsFifo(bfInfo->fifo); + + // Destroy DSP Stub + cm_destroyDSPStub(itfRequire, &bfInfo->dspstub); + + // Destory DSP Skeleton + cm_destroyDSPSkeleton(&bfInfo->dspskeleton); + + // Destroy BF Info + OSAL_Free(bfInfo); +} + +t_cm_error cm_bindInterfaceStaticInterrupt( + const t_nmf_core_id coreId, + const int interruptLine, + const t_component_instance *server, + const char* providedItfServerName +) +{ + char requiredItfClientName[CM_IT_NAME_MAX_LENGTH]; + t_component_instance *client = cm_EEM_getExecutiveEngine(coreId)->instance; + t_interface_require_description itfRequire; + t_interface_provide_description itfProvide; + t_cm_error error; + + //build it[%d] name + if (interruptLine < 0 || interruptLine > 255) {return CM_OUT_OF_LIMITS;} + cm_fillItName(interruptLine, requiredItfClientName); + + //do binding + if ((error = cm_getRequiredInterface(client,requiredItfClientName,&itfRequire)) != CM_OK) {return error;} + if ((error = cm_getProvidedInterface(server,providedItfServerName,&itfProvide)) != CM_OK) {return error;} + if((error = cm_bindInterface(&itfRequire, &itfProvide)) != CM_OK) {return error;} + + return CM_OK; +} + +t_cm_error cm_unbindInterfaceStaticInterrupt( + const t_nmf_core_id coreId, + const int interruptLine +) +{ + char requiredItfClientName[CM_IT_NAME_MAX_LENGTH]; + t_component_instance *client = cm_EEM_getExecutiveEngine(coreId)->instance; + t_interface_require_description itfRequire; + t_cm_error error; + + //build it[%d] name + if (interruptLine < 0 || interruptLine > 255) {return CM_OUT_OF_LIMITS;} + cm_fillItName(interruptLine, requiredItfClientName); + + //do unbinding + if ((error = cm_getRequiredInterface(client,requiredItfClientName,&itfRequire)) != CM_OK) {return error;} + cm_unbindInterface(&itfRequire); + + return CM_OK; +} + +void cm_destroyRequireInterface(t_component_instance* component, t_nmf_client_id clientId) +{ + int i, j; + + /* + * Special code for SINGLETON handling + */ + if(component->template->classe == SINGLETON) + { + if(getNumberOfBind(component) > 0) + return; + } + + for(i = 0; i < component->template->requireNumber; i++) + { + int nb = component->template->requires[i].collectionSize; + for(j = 0; j < nb; j++) + { + if(component->interfaceReferences[i][j].instance != NULL) + { + t_interface_reference* itfRef = &component->interfaceReferences[i][j]; + t_interface_require_description itfRequire; + + itfRequire.client = component; + itfRequire.requireIndex = i; + itfRequire.collectionIndex = j; + itfRequire.origName = component->template->requires[i].name; + + switch (itfRef->bfInfoID) { + case BF_SYNCHRONOUS: + /* Error ignored as it is always OK */ + cm_unbindInterface(&itfRequire); + break; + case BF_TRACE: + cm_unbindInterfaceTrace(&itfRequire, + (t_trace_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); + break; + case BF_ASYNCHRONOUS: + cm_unbindInterfaceAsynchronous(&itfRequire, + (t_async_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); + break; + case BF_DSP2HOST: + /* This 'mpc2host handle' is provided by the host at OS Integration level. + It must then be handled and released in OS specific part. + */ + cm_unbindComponentToCMCore(&itfRequire, + (t_mpc2host_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); + break; + case BF_HOST2DSP: + /* These bindings are from CM Core to DSP, they are not listed + here and must be handles/freed by host at OS Integration level + */ + break; + case BF_DSP2DSP: + cm_unbindInterfaceDistributed(&itfRequire, + (t_mpc2mpc_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); + break; + default: + break; + } + } + } + } +} + +void cm_registerSingletonBinding( + t_component_instance* component, + t_interface_require_description* itfRequire, + t_interface_provide_description* itfProvide, + t_nmf_client_id clientId) +{ + if(component->template->classe == SINGLETON) + { + struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); + if(cl != NULL) + cl->numberOfBind++; + + if(itfProvide != NULL) + LOG_INTERNAL(1, " -> Singleton[%d] : Register binding %s/%x.%s -> %s/%x\n", + clientId, + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server); + else + LOG_INTERNAL(1, " -> Singleton[%d] : Register binding %s/%x.%s -> ARM/VOID\n", + clientId, + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0); + } +} + +t_bool cm_unregisterSingletonBinding( + t_component_instance* component, + t_interface_require_description* itfRequire, + t_interface_provide_description* itfProvide, + t_nmf_client_id clientId) +{ + if(component->template->classe == SINGLETON) + { + struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); + if(cl != NULL) + cl->numberOfBind--; + + if(itfProvide->server == (t_component_instance *)NMF_VOID_COMPONENT) + LOG_INTERNAL(1, " -> Singleton[%d] : Unregister binding %s/%x.%s -> ARM/VOID\n", + clientId, + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0); + else if(itfProvide->server == NULL) + LOG_INTERNAL(1, " -> Singleton[%d] : Unregister binding %s/%x.%s -> ?? \n", + clientId, + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0); + else + LOG_INTERNAL(1, " -> Singleton[%d] : Unregister binding %s/%x.%s -> %s/%x\n", + clientId, + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server); + + if(getNumberOfBind(component) == 0) + { + LOG_INTERNAL(1, " -> Singleton[%d] : All required of %s/%x logically unbound, perform physical unbind\n", + clientId, itfRequire->client->pathname, itfRequire->client, 0, 0, 0); + + (void)cm_EEM_ForceWakeup(component->template->dspId); + + // This is the last binding unbind all !!! + cm_destroyRequireInterface(component, clientId); + + cm_EEM_AllowSleep(component->template->dspId); + } + else if(itfProvide->server != NULL) + { + t_interface_require* itfReq; + itfReq = &itfRequire->client->template->requires[itfRequire->requireIndex]; + if((itfReq->requireTypes & OPTIONAL_REQUIRE) != 0x0) + return TRUE; + } + + return FALSE; + } + + return TRUE; +} + +static t_uint16 getNumberOfBind(t_component_instance* component) +{ + t_uint16 bindNumber = 0; + struct t_client_of_singleton* cur = component->clientOfSingleton; + + for( ; cur != NULL ; cur = cur->next) + { + bindNumber += cur->numberOfBind; + } + + return bindNumber; +} + +static void cm_fillItName(int interruptLine, char *itName) +{ + int divider = 10000; + + *itName++ = 'i'; + *itName++ = 't'; + *itName++ = '['; + + // Find first significant divider + while(divider > interruptLine) + divider /= 10; + + // Compute number + do + { + *itName++ = "0123456789"[interruptLine / divider]; + interruptLine %= divider; + divider /= 10; + } while(divider != 0); + + *itName++ = ']'; + *itName++ = '\0'; +} diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c b/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c new file mode 100644 index 00000000000..b141064c1c1 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c @@ -0,0 +1,205 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include "../inc/bind.h" +#include + +#include + +t_cm_error cm_checkValidClient( + const t_component_instance* client, + const char* requiredItfClientName, + t_interface_require_description *itfRequire, + t_bool *bindable) { + t_cm_error error; + + // Component LC state check + if (NULL == client) + return CM_INVALID_COMPONENT_HANDLE; + + // Check if the requiredItfClientName is required by client component + if ((error = cm_getRequiredInterface(client, requiredItfClientName, itfRequire)) != CM_OK) + return error; + + // Check required interface not already binded + { + t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; + + if(itfRef->instance != (t_component_instance*)NULL) + { + if(client->template->classe == SINGLETON) + { + // Singleton is immutable thus we can't rebind it, nevertheless it's not an issue + *bindable = FALSE; + return CM_OK; + } + else + { + t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; + + if(itfRef->instance == (const t_component_instance*)NMF_VOID_COMPONENT) + ERROR("CM_INTERFACE_ALREADY_BINDED(): Component (%s<%s>.s) already bound to VOID\n", + client->pathname, client->template->name, requiredItfClientName, 0, 0, 0); + else + ERROR("CM_INTERFACE_ALREADY_BINDED(): Component (%s<%s>.s) already bound to another server (%s<%s>.%s)\n", + client->pathname, client->template->name, requiredItfClientName, + itfRef->instance->pathname, itfRef->instance->template->name, itfRef->instance->template->provides[itfRef->provideIndex].name); + return CM_INTERFACE_ALREADY_BINDED; + } + } + } + + // Delayed Component LC state check done only if not optional required interface or intrinsic one that has been solved by loader + { + t_interface_require* itfReq = &client->template->requires[itfRequire->requireIndex]; + + if((itfReq->requireTypes & (OPTIONAL_REQUIRE | INTRINSEC_REQUIRE)) == 0) { + if(client->state == STATE_RUNNABLE) + return CM_COMPONENT_NOT_STOPPED; + } + } + + *bindable = TRUE; + + return CM_OK; +} + +t_cm_error cm_checkValidServer( + const t_component_instance* server, + const char* providedItfServerName, + t_interface_provide_description *itfProvide) { + t_cm_error error; + + // Check if the components are initialized + //if (server->state == STATE_INSTANCIATED) + // return CM_COMPONENT_NOT_INITIALIZED; + if(NULL == server) + return CM_INVALID_COMPONENT_HANDLE; + + // Check if the providedItfServerName is provided by server component + if((error = cm_getProvidedInterface(server, providedItfServerName, itfProvide)) != CM_OK) + return error; + + return CM_OK; +} + +t_cm_error cm_checkValidBinding( + const t_component_instance* client, + const char* requiredItfClientName, + const t_component_instance* server, + const char* providedItfServerName, + t_interface_require_description *itfRequire, + t_interface_provide_description *itfProvide, + t_bool *bindable) { + t_interface_require *require; + t_interface_provide *provide; + t_cm_error error; + + // Check Server + if((error = cm_checkValidServer(server, providedItfServerName, itfProvide)) != CM_OK) + return error; + + // Check Client + if((error = cm_checkValidClient(client, requiredItfClientName, itfRequire, bindable)) != CM_OK) + return error; + + // If this is a singleton which has been already bound check that next binding is at the same server + if(*bindable == FALSE + && client->template->classe == SINGLETON) + { + t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; + while( itfRef->instance != server + || itfRef->provideIndex != itfProvide->provideIndex + || itfRef->collectionIndex != itfProvide->collectionIndex ) + { + if(itfRef->instance == (const t_component_instance*)NMF_VOID_COMPONENT) + { + ERROR("CM_INTERFACE_ALREADY_BINDED(): Singleton (%s<%s>.s) already bound to VOID\n", + client->pathname, client->template->name, requiredItfClientName, 0, 0, 0); + return CM_INTERFACE_ALREADY_BINDED; + } + else if(itfRef->bfInfoID == BF_ASYNCHRONOUS || itfRef->bfInfoID == BF_TRACE) + { + t_interface_require_description eventitfRequire; + CM_ASSERT(cm_getRequiredInterface(itfRef->instance, "target", &eventitfRequire) == CM_OK); + itfRef = &itfRef->instance->interfaceReferences[eventitfRequire.requireIndex][eventitfRequire.collectionIndex]; + + // Go to see client of event if the same + } + else + { + ERROR("CM_INTERFACE_ALREADY_BINDED(): Singleton (%s<%s>.s) already bound to different server (%s<%s>.%s)\n", + client->pathname, client->template->name, requiredItfClientName, + itfRef->instance->pathname, itfRef->instance->template->name, itfRef->instance->template->provides[itfRef->provideIndex].name); + return CM_INTERFACE_ALREADY_BINDED; + } + } + } + + // Check if provided and required type matches + require = &client->template->requires[itfRequire->requireIndex]; + provide = &server->template->provides[itfProvide->provideIndex]; + if(require->interface != provide->interface) + { + ERROR("CM_ILLEGAL_BINDING(%s, %s)\n", require->interface->type, provide->interface->type, 0, 0, 0, 0); + return CM_ILLEGAL_BINDING; + } + + // Check if static required interface binded to singleton component + if((require->requireTypes & STATIC_REQUIRE) && + (server->template->classe != SINGLETON)) + { + ERROR("CM_ILLEGAL_BINDING(): Can't bind static required interface to not singleton component\n", + 0, 0, 0, 0, 0, 0); + return CM_ILLEGAL_BINDING; + } + + return CM_OK; +} + +t_cm_error cm_checkValidUnbinding( + const t_component_instance* client, + const char* requiredItfClientName, + t_interface_require_description *itfRequire, + t_interface_provide_description *itfProvide) { + t_cm_error error; + t_interface_require* itfReq; + + // Component LC state check + if (NULL == client) + return CM_INVALID_COMPONENT_HANDLE; + + // Check if the requiredItfClientName is required by client component + if ((error = cm_getRequiredInterface(client, requiredItfClientName, itfRequire)) != CM_OK) + return error; + + itfReq = &client->template->requires[itfRequire->requireIndex]; + + // Check if the requiredItfClientName is required by client component + if ((error = cm_lookupInterface(itfRequire, itfProvide)) != CM_OK) + { + // We allow to unbind optional required of singleton even if not binded, since it could have been unbound previously but we don't + // want to break bind singleton reference counter + if((client->template->classe == SINGLETON) && + (itfReq->requireTypes & OPTIONAL_REQUIRE) != 0x0) + return CM_OK; + + return error; + } + + // Singleton is immutable, don't unbind it + if(client->template->classe == SINGLETON) + return CM_OK; + + /* if interface is optionnal then allow unbinding even if not stop */ + if((itfReq->requireTypes & OPTIONAL_REQUIRE) == 0x0) + { + if(client->state == STATE_RUNNABLE) + return CM_COMPONENT_NOT_STOPPED; + } + + return CM_OK; +} + diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c b/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c new file mode 100644 index 00000000000..07d20d0266e --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c @@ -0,0 +1,1297 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +/* + * Component mangement wrapping. + */ +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_InstantiateComponent( + const char* templateName, + t_cm_domain_id domainId, + t_nmf_client_id clientId, + t_nmf_ee_priority priority, + const char localName[MAX_COMPONENT_NAME_LENGTH], + const char *dataFile, + t_cm_instance_handle *instance) { + t_cm_error error; + t_nmf_core_id coreId; + t_component_instance *comp; + t_elfdescription *elfhandle = NULL; + + OSAL_LOCK_API(); + + /* + * Load Elf File + */ + if(dataFile != NULL && + (error = cm_ELF_CheckFile( + dataFile, + TRUE, + &elfhandle)) != CM_OK) + goto out; + + //only allow instantiation in non-scratch domains (ie. DOMAIN_NORMAL)! + if ((error = cm_DM_CheckDomainWithClient(domainId, DOMAIN_NORMAL, clientId)) != CM_OK) + goto out; + + coreId = cm_DM_GetDomainCoreId(domainId); + + if(coreId < FIRST_MPC_ID || coreId > LAST_CORE_ID) + { + error = CM_INVALID_PARAMETER; + goto out; + } + + if ((error = cm_CFG_CheckMpcStatus(coreId)) != CM_OK) + goto out; + + if ((error = cm_EEM_ForceWakeup(coreId)) != CM_OK) + goto out; + + error = cm_instantiateComponent( + templateName, + domainId, + priority, + localName, + elfhandle, + &comp); + if(error == CM_OK) + *instance = comp->instance; + + cm_EEM_AllowSleep(coreId); + +out: + cm_ELF_CloseFile(TRUE, elfhandle); + + OSAL_UNLOCK_API(); + + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_StartComponent( + t_cm_instance_handle instance, + t_nmf_client_id clientId) { + t_cm_error error; + t_component_instance *component; + + OSAL_LOCK_API(); + + component = cm_lookupComponent(instance); + if (NULL == component) + error = CM_INVALID_COMPONENT_HANDLE; + else + { + error = cm_startComponent(component, clientId); + } + + OSAL_UNLOCK_API(); + + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_StopComponent( + t_cm_instance_handle instance, + t_nmf_client_id clientId) { + t_cm_error error; + t_component_instance *component; + + OSAL_LOCK_API(); + + component = cm_lookupComponent(instance); + if (NULL == component) + error = CM_INVALID_COMPONENT_HANDLE; + else + { + error = cm_stopComponent(component, clientId); + } + + OSAL_UNLOCK_API(); + + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_DestroyComponent( + t_cm_instance_handle instance, + t_nmf_client_id clientId) +{ + t_cm_error error; + t_component_instance *component; + + OSAL_LOCK_API(); + + component = cm_lookupComponent(instance); + if (NULL == component) + { + error = CM_INVALID_COMPONENT_HANDLE; + } + else + { + t_nmf_core_id coreId = component->template->dspId; + + (void)cm_EEM_ForceWakeup(coreId); + + error = cm_destroyInstanceForClient(component, DESTROY_NORMAL, clientId); + + cm_CFG_ReleaseMpc(coreId); + + cm_EEM_AllowSleep(coreId); + } + + OSAL_UNLOCK_API(); + + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_FlushComponents(t_nmf_client_id clientId) +{ + t_cm_error error = CM_OK; + t_component_instance *instance; + t_uint32 i; + + if (clientId == 0) + return CM_INVALID_PARAMETER; + + OSAL_LOCK_API(); + + // We don't know exactly where components will be, wake up everybody !! + (void)cm_EEM_ForceWakeup(SVA_CORE_ID); + (void)cm_EEM_ForceWakeup(SIA_CORE_ID); + + /* Destroy all host2mpc bindings */ + for (i=0; iclientId == clientId)) { + cm_delEntry(&Host2MpcBindingTable, i); + OSAL_UNLOCK_COM(); + cm_unbindComponentFromCMCore(bfInfo); + } else + OSAL_UNLOCK_COM(); + } + + /* First, stop all remaining components for this client */ + for (i=0; itemplate->classe == FIRMWARE) || + /* Skip all binding components */ + (cm_StringCompare(instance->template->name, "_ev.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_st.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_sk.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_tr.", 4) == 0)) + continue; + + /* + * Special code for SINGLETON handling + */ + if(instance->template->classe == SINGLETON) + { + struct t_client_of_singleton* cl = cm_getClientOfSingleton(instance, FALSE, clientId); + if(cl == NULL) + continue; + + cl->numberOfStart = 1; // == 1 since it will go to 0 in cm_stopComponent + cl->numberOfInstance = 1; // == 1 since it will go to 0 in cm_destroyInstanceForClient + cl->numberOfBind = 0; // == 0 since we don't want anymore binding for this component + } + else if(domainDesc[instance->domainId].client != clientId) + /* Skip all components not belonging to our client */ + continue; + + // Stop the component + error = cm_stopComponent(instance, clientId); + if (error != CM_OK && error != CM_COMPONENT_NOT_STARTED) + LOG_INTERNAL(0, "Error stopping component %s/%x (%s, error=%d, client=%u)\n", instance->pathname, instance, instance->template->name, error, clientId, 0); + + // Destroy dependencies + cm_destroyRequireInterface(instance, clientId); + } + + /* Destroy all remaining components for this client */ + for (i=0; itemplate->classe == FIRMWARE) || + /* Skip all binding components */ + (cm_StringCompare(instance->template->name, "_ev.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_st.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_sk.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_tr.", 4) == 0)) { + continue; + } + + + /* + * Special code for SINGLETON handling + */ + if(instance->template->classe == SINGLETON) + { + struct t_client_of_singleton* cl = cm_getClientOfSingleton(instance, FALSE, clientId); + if(cl == NULL) + continue; + } + else if(domainDesc[instance->domainId].client != clientId) + /* Skip all components not belonging to our client */ + continue; + + + // Destroy the component + error = cm_destroyInstanceForClient(instance, DESTROY_WITHOUT_CHECK, clientId); + + if (error != CM_OK) + { + /* FIXME : add component name instance in log message but need to make a copy before cm_flushComponent() + * because it's no more available after. + */ + LOG_INTERNAL(0, "Error flushing component (error=%d, client=%u)\n", error, clientId, 0, 0, 0, 0); + } + } + + cm_CFG_ReleaseMpc(SVA_CORE_ID); + cm_CFG_ReleaseMpc(SIA_CORE_ID); + + cm_EEM_AllowSleep(SVA_CORE_ID); + cm_EEM_AllowSleep(SIA_CORE_ID); + + OSAL_UNLOCK_API(); + + return error; +} + +/* + * Component binding wrapping. + */ +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponent( + const t_cm_instance_handle clientInstance, + const char* requiredItfClientName, + const t_cm_instance_handle serverInstance, + const char* providedItfServerName, + t_bool traced, + t_nmf_client_id clientId, + const char *dataFileTrace) { + t_interface_require_description itfRequire; + t_interface_provide_description itfProvide; + t_bool bindable; + t_cm_error error; + t_component_instance *client, *server; + t_elfdescription *elfhandleTrace = NULL; + + OSAL_LOCK_API(); + + /* + * Load Elf File + */ + if(dataFileTrace != NULL && + (error = cm_ELF_CheckFile( + dataFileTrace, + TRUE, + &elfhandleTrace)) != CM_OK) + goto out; + + client = cm_lookupComponent(clientInstance); + server = cm_lookupComponent(serverInstance); + // Sanity check + if((error = cm_checkValidBinding(client, requiredItfClientName, + server, providedItfServerName, + &itfRequire, &itfProvide, &bindable)) != CM_OK) + goto out; + + // Check that client and server component run on same DSP + if (itfRequire.client->template->dspId != itfProvide.server->template->dspId) + { + error = CM_ILLEGAL_BINDING; + goto out; + } + + // Check if we really need to bind + if(bindable) + { + if ((error = cm_EEM_ForceWakeup(itfRequire.client->template->dspId)) != CM_OK) + goto out; + + /* + * Synchronous binding, so no binding component + */ + if(traced) + error = cm_bindInterfaceTrace(&itfRequire, &itfProvide, elfhandleTrace); + else + error = cm_bindInterface(&itfRequire, &itfProvide); + + cm_EEM_AllowSleep(itfRequire.client->template->dspId); + } + + cm_registerSingletonBinding(client, &itfRequire, &itfProvide, clientId); + +out: + cm_ELF_CloseFile(TRUE, elfhandleTrace); + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponent( + const t_cm_instance_handle clientInstance, + const char* requiredItfClientName, + t_nmf_client_id clientId) { + t_interface_require_description itfRequire; + t_interface_provide_description itfProvide; + t_bf_info_ID bfInfoID; + t_cm_error error; + t_component_instance *client; + + OSAL_LOCK_API(); + + client = cm_lookupComponent(clientInstance); + // Sanity check + if((error = cm_checkValidUnbinding(client, requiredItfClientName, + &itfRequire, &itfProvide)) != CM_OK) + goto out; + + // Check if this is a Primitive binding + bfInfoID = itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfoID; + if(bfInfoID != BF_SYNCHRONOUS && bfInfoID != BF_TRACE) + { + error = CM_ILLEGAL_UNBINDING; + goto out; + } + + // Check if we really need to unbind + if(cm_unregisterSingletonBinding(client, &itfRequire, &itfProvide, clientId)) + { + (void)cm_EEM_ForceWakeup(itfRequire.client->template->dspId); + + if(bfInfoID == BF_SYNCHRONOUS) + cm_unbindInterface(&itfRequire); + else + cm_unbindInterfaceTrace( + &itfRequire, + (t_trace_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); + + cm_EEM_AllowSleep(itfRequire.client->template->dspId); + + error = CM_OK; + } + +out: + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentToVoid( + const t_cm_instance_handle clientInstance, + const char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH], + t_nmf_client_id clientId) +{ + t_interface_require_description itfRequire; + t_bool bindable; + t_cm_error error; + t_component_instance *client; + + OSAL_LOCK_API(); + + client = cm_lookupComponent(clientInstance); + // Check invalid binding + if((error = cm_checkValidClient(client, requiredItfClientName, + &itfRequire, &bindable)) != CM_OK) + goto out; + + // Check if we really need to bind + if(bindable) + { + if ((error = cm_EEM_ForceWakeup(itfRequire.client->template->dspId)) != CM_OK) + goto out; + + error = cm_bindInterfaceToVoid(&itfRequire); + + cm_EEM_AllowSleep(itfRequire.client->template->dspId); + } + + cm_registerSingletonBinding(client, &itfRequire, NULL, clientId); + +out: + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentAsynchronous( + const t_cm_instance_handle clientInstance, + const char* requiredItfClientName, + const t_cm_instance_handle serverInstance, + const char* providedItfServerName, + t_uint32 fifosize, + t_cm_mpc_memory_type eventMemType, + t_nmf_client_id clientId, + const char *dataFileSkeletonOrEvent, + const char *dataFileStub) { + t_interface_require_description itfRequire; + t_interface_provide_description itfProvide; + t_dsp_memory_type_id dspEventMemType; + t_bool bindable; + t_cm_error error; + t_component_instance *client, *server; + t_elfdescription *elfhandleSkeletonOrEvent = NULL; + t_elfdescription *elfhandleStub = NULL; + + OSAL_LOCK_API(); + + /* + * Load Elf File + */ + if(dataFileSkeletonOrEvent != NULL && + (error = cm_ELF_CheckFile( + dataFileSkeletonOrEvent, + TRUE, + &elfhandleSkeletonOrEvent)) != CM_OK) + goto out; + if(dataFileStub != NULL && + (error = cm_ELF_CheckFile( + dataFileStub, + TRUE, + &elfhandleStub)) != CM_OK) + goto out; + + client = cm_lookupComponent(clientInstance); + server = cm_lookupComponent(serverInstance); + // Check invalid binding + if((error = cm_checkValidBinding(client, requiredItfClientName, + server, providedItfServerName, + &itfRequire, &itfProvide, &bindable)) != CM_OK) + goto out; + + switch(eventMemType) + { + case CM_MM_MPC_TCM24_X: + dspEventMemType = INTERNAL_XRAM24; + break; + case CM_MM_MPC_ESRAM24: + dspEventMemType = ESRAM_EXT24; + break; + case CM_MM_MPC_SDRAM24: + dspEventMemType = SDRAM_EXT24; + break; + default: + error = CM_INVALID_PARAMETER; + goto out; + } + + // Check if we really need to bind + if(bindable) + { + // Create the binding and bind it to the client (or all sub-components clients ....) + if (itfRequire.client->template->dspId != itfProvide.server->template->dspId) + { + if ((error = cm_EEM_ForceWakeup(itfRequire.client->template->dspId)) != CM_OK) + goto out; + if ((error = cm_EEM_ForceWakeup(itfProvide.server->template->dspId)) != CM_OK) + { + cm_EEM_AllowSleep(itfRequire.client->template->dspId); + goto out; + } + + // This is a distribute communication + error = cm_bindInterfaceDistributed( + &itfRequire, + &itfProvide, + fifosize, + dspEventMemType, + elfhandleSkeletonOrEvent, + elfhandleStub); + + cm_EEM_AllowSleep(itfRequire.client->template->dspId); + cm_EEM_AllowSleep(itfProvide.server->template->dspId); + } + else + { + if ((error = cm_EEM_ForceWakeup(itfRequire.client->template->dspId)) != CM_OK) + goto out; + + // This is a acynchronous communication + error = cm_bindInterfaceAsynchronous( + &itfRequire, + &itfProvide, + fifosize, + dspEventMemType, + elfhandleSkeletonOrEvent); + + cm_EEM_AllowSleep(itfRequire.client->template->dspId); + } + } + + cm_registerSingletonBinding(client, &itfRequire, &itfProvide, clientId); + +out: + cm_ELF_CloseFile(TRUE, elfhandleSkeletonOrEvent); + cm_ELF_CloseFile(TRUE, elfhandleStub); + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentAsynchronous( + const t_cm_instance_handle instance, + const char* requiredItfClientName, + t_nmf_client_id clientId) { + t_interface_require_description itfRequire; + t_interface_provide_description itfProvide; + t_bf_info_ID bfInfoID; + t_cm_error error; + t_component_instance *client; + + OSAL_LOCK_API(); + + client = cm_lookupComponent(instance); + // Sanity check + if((error = cm_checkValidUnbinding(client, requiredItfClientName, + &itfRequire, &itfProvide)) != CM_OK) + goto out; + + bfInfoID = itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfoID; + + // Check if we really need to unbind + if(cm_unregisterSingletonBinding(client, &itfRequire, &itfProvide, clientId)) + { + // Check if this is a Asynchronous binding + if(bfInfoID == BF_DSP2DSP) + { + t_nmf_core_id clientDsp = itfRequire.client->template->dspId; + t_nmf_core_id serverDsp = itfProvide.server->template->dspId; + + (void)cm_EEM_ForceWakeup(clientDsp); + (void)cm_EEM_ForceWakeup(serverDsp); + + cm_unbindInterfaceDistributed( + &itfRequire, + (t_mpc2mpc_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); + + cm_EEM_AllowSleep(clientDsp); + cm_EEM_AllowSleep(serverDsp); + + error = CM_OK; + } + else if(bfInfoID == BF_ASYNCHRONOUS) + { + t_nmf_core_id clientDsp = itfRequire.client->template->dspId; + + (void)cm_EEM_ForceWakeup(clientDsp); + + cm_unbindInterfaceAsynchronous( + &itfRequire, + (t_async_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); + + cm_EEM_AllowSleep(clientDsp); + + error = CM_OK; + } + else + error = CM_ILLEGAL_UNBINDING; + } + + out: + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentFromCMCore( + const t_cm_instance_handle server, + const char* providedItfServerName, + t_uint32 fifosize, + t_cm_mpc_memory_type eventMemType, + t_cm_bf_host2mpc_handle *bfHost2mpcHdl, + t_nmf_client_id clientId, + const char *dataFileSkeleton) { + t_interface_provide_description itfProvide; + t_dsp_memory_type_id dspEventMemType; + t_cm_error error; + t_component_instance* component; + t_host2mpc_bf_info *bfInfo; + t_elfdescription *elfhandleSkeleton = NULL; + + OSAL_LOCK_API(); + + /* + * Load Elf File + */ + if(dataFileSkeleton != NULL && + (error = cm_ELF_CheckFile( + dataFileSkeleton, + TRUE, + &elfhandleSkeleton)) != CM_OK) + goto out; + + component = cm_lookupComponent(server); + // Check server validity + if((error = cm_checkValidServer(component, providedItfServerName, + &itfProvide)) != CM_OK) + goto out; + + if ((error = cm_EEM_ForceWakeup(itfProvide.server->template->dspId)) != CM_OK) + goto out; + + switch(eventMemType) + { + case CM_MM_MPC_TCM24_X: + dspEventMemType = INTERNAL_XRAM24; + break; + case CM_MM_MPC_ESRAM24: + dspEventMemType = ESRAM_EXT24; + break; + case CM_MM_MPC_SDRAM24: + dspEventMemType = SDRAM_EXT24; + break; + default: + goto out; + } + + error = cm_bindComponentFromCMCore(&itfProvide, + fifosize, + dspEventMemType, + elfhandleSkeleton, + &bfInfo); + + cm_EEM_AllowSleep(itfProvide.server->template->dspId); + +out: + cm_ELF_CloseFile(TRUE, elfhandleSkeleton); + OSAL_UNLOCK_API(); + + if (error == CM_OK) { + bfInfo->clientId = clientId; + OSAL_LOCK_COM(); + *bfHost2mpcHdl = cm_addEntry(&Host2MpcBindingTable, bfInfo); + if (*bfHost2mpcHdl == 0) + error = CM_NO_MORE_MEMORY; + OSAL_UNLOCK_COM(); + + if (error != CM_OK) { + OSAL_LOCK_API(); + (void)cm_EEM_ForceWakeup(itfProvide.server->template->dspId); + cm_unbindComponentFromCMCore(bfInfo); + cm_EEM_AllowSleep(itfProvide.server->template->dspId); + OSAL_UNLOCK_API(); + } + } + + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentFromCMCore( + t_cm_bf_host2mpc_handle bfHost2mpcId) { + t_host2mpc_bf_info* bfInfo; + t_nmf_core_id coreId; + + OSAL_LOCK_COM(); + bfInfo = cm_lookupEntry(&Host2MpcBindingTable, bfHost2mpcId); + if (bfInfo) + cm_delEntry(&Host2MpcBindingTable, bfHost2mpcId & INDEX_MASK); + OSAL_UNLOCK_COM(); + if (NULL == bfInfo) + return CM_INVALID_PARAMETER; + + OSAL_LOCK_API(); + + // Check if this is a DSP to Host binding + //if(bfInfo->id != BF_HOST2DSP) + // return CM_ILLEGAL_UNBINDING; + coreId = bfInfo->dspskeleton.skelInstance->template->dspId; + + (void)cm_EEM_ForceWakeup(coreId); + + cm_unbindComponentFromCMCore(bfInfo); + + cm_EEM_AllowSleep(coreId); + + OSAL_UNLOCK_API(); + return CM_OK; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentToCMCore( + const t_cm_instance_handle instance, + const char *requiredItfClientName, + t_uint32 fifosize, + t_nmf_mpc2host_handle upLayerThis, + const char *dataFileStub, + t_cm_bf_mpc2host_handle *mpc2hostId, + t_nmf_client_id clientId) { + t_interface_require_description itfRequire; + t_bool bindable; + t_cm_error error; + t_component_instance* client; + t_elfdescription *elfhandleStub = NULL; + + OSAL_LOCK_API(); + + /* + * Load Elf File + */ + if(dataFileStub != NULL && + (error = cm_ELF_CheckFile( + dataFileStub, + TRUE, + &elfhandleStub)) != CM_OK) + goto out; + + client = cm_lookupComponent(instance); + // Check invalid binding + if((error = cm_checkValidClient(client, requiredItfClientName, + &itfRequire, &bindable)) != CM_OK) + goto out; + + // Check if we really need to bind + if(bindable) + { + if ((error = cm_EEM_ForceWakeup(itfRequire.client->template->dspId)) != CM_OK) + goto out; + + error = cm_bindComponentToCMCore( + &itfRequire, + fifosize, + upLayerThis, + elfhandleStub, + (t_mpc2host_bf_info**)mpc2hostId); + + cm_EEM_AllowSleep(itfRequire.client->template->dspId); + } + + cm_registerSingletonBinding(client, &itfRequire, NULL, clientId); + +out: + cm_ELF_CloseFile(TRUE, elfhandleStub); + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentToCMCore( + const t_cm_instance_handle instance, + const char *requiredItfClientName, + t_nmf_mpc2host_handle *upLayerThis, + t_nmf_client_id clientId) { + t_interface_require_description itfRequire; + t_interface_provide_description itfProvide; + t_cm_error error; + t_mpc2host_bf_info *bfInfo; + t_component_instance* client; + + OSAL_LOCK_API(); + + client = cm_lookupComponent(instance); + // Sanity check + if((error = cm_checkValidUnbinding(client, requiredItfClientName, + &itfRequire, &itfProvide)) != CM_OK) + goto out; + + // Check if this is a DSP to Host binding + if(itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfoID != BF_DSP2HOST) + { + error = CM_ILLEGAL_UNBINDING; + goto out; + } + + bfInfo = (t_mpc2host_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo; + + // Get client information + *upLayerThis = bfInfo->context; + + // Check if we really need to unbind + if(cm_unregisterSingletonBinding(client, &itfRequire, &itfProvide, clientId)) + { + (void)cm_EEM_ForceWakeup(itfRequire.client->template->dspId); + + cm_unbindComponentToCMCore(&itfRequire, bfInfo); + + cm_EEM_AllowSleep(itfRequire.client->template->dspId); + + error = CM_OK; + } +out: + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_event_params_handle CM_ENGINE_AllocEvent(t_cm_bf_host2mpc_handle host2mpcId) { + t_host2mpc_bf_info* bfInfo; + t_event_params_handle eventHandle; + + OSAL_LOCK_COM(); + bfInfo = cm_lookupEntry(&Host2MpcBindingTable, host2mpcId); + if (NULL == bfInfo) { + OSAL_UNLOCK_COM(); + return NULL; + } + + if(bfInfo->dspskeleton.skelInstance->interfaceReferences[0][0].instance->state != STATE_RUNNABLE) { + ERROR("CM_COMPONENT_NOT_STARTED: Call interface before start component %s<%s>\n", + bfInfo->dspskeleton.skelInstance->pathname, + bfInfo->dspskeleton.skelInstance->template->name, 0, 0, 0, 0); + } + + eventHandle = cm_AllocEvent(bfInfo->fifo); + + OSAL_UNLOCK_COM(); + + return eventHandle; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_PushEvent(t_cm_bf_host2mpc_handle host2mpcId, t_event_params_handle h, t_uint32 methodIndex) { + t_host2mpc_bf_info* bfInfo; + t_cm_error error; + + OSAL_LOCK_COM(); + bfInfo = cm_lookupEntry(&Host2MpcBindingTable, host2mpcId); + if (NULL == bfInfo) { + OSAL_UNLOCK_COM(); + return CM_INVALID_PARAMETER; + } + error = cm_PushEvent(bfInfo->fifo, h, methodIndex); + OSAL_UNLOCK_COM(); + + return error; +} + +PUBLIC EXPORT_SHARED void CM_ENGINE_AcknowledgeEvent(t_cm_bf_mpc2host_handle mpc2hostId) { + t_mpc2host_bf_info* bfInfo = (t_mpc2host_bf_info*)mpc2hostId; + + //t_dsp2host_bf_info* bfInfo = (t_host2mpc_bf_info*)mpc2hostId; + OSAL_LOCK_COM(); + cm_AcknowledgeEvent(bfInfo->fifo); + OSAL_UNLOCK_COM(); +} + +/* + * Get a reference on a given attribute of a given component + */ +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_ReadComponentAttribute( + const t_cm_instance_handle instance, + const char* attrName, + t_uint24 *attrValue) +{ + t_cm_error error; + t_component_instance* component; + + OSAL_LOCK_API(); + + component = cm_lookupComponent(instance); + if (NULL == component) + error = CM_INVALID_COMPONENT_HANDLE; + else + { + if ((error = cm_EEM_ForceWakeup(component->template->dspId)) != CM_OK) + goto out; + + // t_uint24 -> t_uint32 possible since we know it same size + error = cm_readAttribute(component, attrName, (t_uint32*)attrValue); + + cm_EEM_AllowSleep(component->template->dspId); + } + +out: + OSAL_UNLOCK_API(); + return error; +} + +/*=============================================================================== + * Introspection API + *===============================================================================*/ +/* + * Component + */ +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentListHeader( + const t_nmf_client_id client, + t_cm_instance_handle *headerComponent) { + t_uint32 i; + + OSAL_LOCK_API(); + + *headerComponent = 0; + for (i=0; i < ComponentTable.idxMax; i++) { + if ((componentEntry(i) != NULL) && + (componentEntry(i)->template->classe != FIRMWARE) && + (domainDesc[componentEntry(i)->domainId].client == client)) { + *headerComponent = ENTRY2HANDLE(componentEntry(i), i);; + break; + } + } + + OSAL_UNLOCK_API(); + + return CM_OK; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentListNext( + const t_nmf_client_id client, + const t_cm_instance_handle prevComponent, + t_cm_instance_handle *nextComponent){ + t_cm_error error; + t_uint32 i = prevComponent & INDEX_MASK; + + OSAL_LOCK_API(); + + // Sanity check + if ((i >= ComponentTable.idxMax) + || (((unsigned int)componentEntry(i) << INDEX_SHIFT) != (prevComponent & ~INDEX_MASK))) + error = CM_INVALID_COMPONENT_HANDLE; + else { + *nextComponent = 0; + for (i++; i < ComponentTable.idxMax; i++) { + if ((componentEntry(i) != NULL) && + (componentEntry(i)->template->classe != FIRMWARE) && + (domainDesc[componentEntry(i)->domainId].client == client)) { + *nextComponent = ENTRY2HANDLE(componentEntry(i), i);; + break; + } + } + + error = CM_OK; + } + + OSAL_UNLOCK_API(); + + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentDescription( + const t_cm_instance_handle instance, + char *templateName, + t_uint32 templateNameLength, + t_nmf_core_id *coreId, + char *localName, + t_uint32 localNameLength, + t_nmf_ee_priority *priority) { + t_component_instance *comp; + t_cm_error error; + + OSAL_LOCK_API(); + + comp = cm_lookupComponent(instance); + // Sanity check + if (NULL == comp) { + error = CM_INVALID_COMPONENT_HANDLE; + } else { + cm_StringCopy( + templateName, + comp->template->name, + templateNameLength); + *coreId = comp->template->dspId; + cm_StringCopy( + localName, + comp->pathname, + localNameLength); + if (priority) + *priority = comp->priority; + error = CM_OK; + } + + OSAL_UNLOCK_API(); + + return error; +} + +/* + * Require interface + */ +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterfaceNumber( + const t_cm_instance_handle instance, + t_uint8 *numberRequiredInterfaces) { + t_component_instance *comp; + t_cm_error error; + + OSAL_LOCK_API(); + + comp = cm_lookupComponent(instance); + // Sanity check + if (NULL == comp) { + error = CM_INVALID_COMPONENT_HANDLE; + } else { + *numberRequiredInterfaces = comp->template->requireNumber; + + error = CM_OK; + } + + OSAL_UNLOCK_API(); + + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterface( + const t_cm_instance_handle instance, + const t_uint8 index, + char *itfName, + t_uint32 itfNameLength, + char *itfType, + t_uint32 itfTypeLength, + t_cm_require_state *requireState, + t_sint16 *collectionSize) { + t_component_instance *comp; + t_cm_error error; + + OSAL_LOCK_API(); + + comp = cm_lookupComponent(instance); + // Sanity check + if (NULL == comp) { + error = CM_INVALID_COMPONENT_HANDLE; + } else if(index >= comp->template->requireNumber) { + error = CM_NO_SUCH_REQUIRED_INTERFACE; + } else { + cm_StringCopy( + itfName, + comp->template->requires[index].name, + itfNameLength); + cm_StringCopy( + itfType, + comp->template->requires[index].interface->type, + itfTypeLength); + if(comp->template->requires[index].requireTypes & COLLECTION_REQUIRE) + *collectionSize = comp->template->requires[index].collectionSize; + else + *collectionSize = -1; + + if(requireState != NULL) { + *requireState = 0; + if(comp->template->requires[index].requireTypes & COLLECTION_REQUIRE) + *requireState |= CM_REQUIRE_COLLECTION; + if(comp->template->requires[index].requireTypes & OPTIONAL_REQUIRE) + *requireState |= CM_REQUIRE_OPTIONAL; + if(comp->template->requires[index].requireTypes & STATIC_REQUIRE) + *requireState |= CM_REQUIRE_STATIC; + } + + error = CM_OK; + } + + OSAL_UNLOCK_API(); + + return error; +} +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterfaceBinding( + const t_cm_instance_handle instance, + const char *itfName, + t_cm_instance_handle *server, + char *serverItfName, + t_uint32 serverItfNameLength) { + t_component_instance *comp; + t_interface_require_description itfRequire; + t_interface_provide_description itfProvide; + t_cm_error error; + + OSAL_LOCK_API(); + + comp = cm_lookupComponent(instance); + // Sanity check + if(NULL == comp) { + error = CM_INVALID_COMPONENT_HANDLE; + } else if ((error = cm_getRequiredInterface(comp, itfName, &itfRequire)) != CM_OK) { + // Check if the requiredItfClientName is required by client component + } else if ((error = cm_lookupInterface(&itfRequire, &itfProvide)) != CM_OK) { + // Check if the requiredItfClientName is required by client component + } else { + if ((t_cm_instance_handle)itfProvide.server == NMF_HOST_COMPONENT + || (t_cm_instance_handle)itfProvide.server == NMF_VOID_COMPONENT) + *server = (t_cm_instance_handle)itfProvide.server; + else + *server = itfProvide.server->instance; + if(*server == NMF_HOST_COMPONENT) { + cm_StringCopy( + serverItfName, + "unknown", + serverItfNameLength); + } else if(*server == NMF_VOID_COMPONENT) { + cm_StringCopy( + serverItfName, + "void", + serverItfNameLength); + } else if(*server != 0) { + cm_StringCopy( + serverItfName, + itfProvide.server->template->provides[itfProvide.provideIndex].name, + serverItfNameLength); + if(itfProvide.server->template->provides[itfProvide.provideIndex].provideTypes & COLLECTION_PROVIDE) { + int len = cm_StringLength(serverItfName, serverItfNameLength); + serverItfName[len++] = '['; + if(itfProvide.collectionIndex >= 100) + serverItfName[len++] = '0' + (itfProvide.collectionIndex / 100); + if(itfProvide.collectionIndex >= 10) + serverItfName[len++] = '0' + ((itfProvide.collectionIndex % 100) / 10); + serverItfName[len++] = '0' + (itfProvide.collectionIndex % 10); + serverItfName[len++] = ']'; + serverItfName[len] = 0; + } + } + + error = CM_OK; + } + + OSAL_UNLOCK_API(); + + return error; +} + +/* + * Provide interface + */ +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentProvidedInterfaceNumber( + const t_cm_instance_handle instance, + t_uint8 *numberProvidedInterfaces) { + t_component_instance *comp; + t_cm_error error; + + OSAL_LOCK_API(); + + comp = cm_lookupComponent(instance); + // Sanity check + if (NULL == comp) { + error = CM_INVALID_COMPONENT_HANDLE; + } else { + *numberProvidedInterfaces = comp->template->provideNumber; + + error = CM_OK; + } + + OSAL_UNLOCK_API(); + + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentProvidedInterface( + const t_cm_instance_handle instance, + const t_uint8 index, + char *itfName, + t_uint32 itfNameLength, + char *itfType, + t_uint32 itfTypeLength, + t_sint16 *collectionSize) { + t_component_instance *comp; + t_cm_error error; + + OSAL_LOCK_API(); + + comp = cm_lookupComponent(instance); + // Sanity check + if (NULL == comp) { + error = CM_INVALID_COMPONENT_HANDLE; + } else if(index >= comp->template->provideNumber) { + error = CM_NO_SUCH_PROVIDED_INTERFACE; + } else { + cm_StringCopy( + itfName, + comp->template->provides[index].name, + itfNameLength); + cm_StringCopy( + itfType, + comp->template->provides[index].interface->type, + itfTypeLength); + if(comp->template->provides[index].provideTypes & COLLECTION_PROVIDE) + *collectionSize = comp->template->provides[index].collectionSize; + else + *collectionSize = -1; + + error = CM_OK; + } + + OSAL_UNLOCK_API(); + + return error; +} + +/* + * Component Property + */ +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentPropertyNumber( + const t_cm_instance_handle instance, + t_uint8 *numberProperties) { + t_component_instance *comp; + t_cm_error error; + + OSAL_LOCK_API(); + + comp = cm_lookupComponent(instance); + // Sanity check + if (NULL == comp) { + error = CM_INVALID_COMPONENT_HANDLE; + } else { + *numberProperties = comp->template->propertyNumber; + + error = CM_OK; + } + + OSAL_UNLOCK_API(); + + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentPropertyName( + const t_cm_instance_handle instance, + const t_uint8 index, + char *propertyName, + t_uint32 propertyNameLength) { + t_component_instance *comp; + t_cm_error error; + + OSAL_LOCK_API(); + + comp = cm_lookupComponent(instance); + // Sanity check + if (NULL == comp) { + error = CM_INVALID_COMPONENT_HANDLE; + } else if(index >= comp->template->propertyNumber) { + error = CM_NO_SUCH_PROPERTY; + } else { + cm_StringCopy( + propertyName, + comp->template->properties[index].name, + propertyNameLength); + + error = CM_OK; + } + + OSAL_UNLOCK_API(); + + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentPropertyValue( + const t_cm_instance_handle instance, + const char *propertyName, + char *propertyValue, + t_uint32 propertyValueLength) +{ + t_component_instance *comp; + t_cm_error error; + + OSAL_LOCK_API(); + + comp = cm_lookupComponent(instance); + if (NULL == comp) + error = CM_INVALID_COMPONENT_HANDLE; + else + { + error = cm_getComponentProperty( + comp, + propertyName, + propertyValue, + propertyValueLength); + + if(error == CM_NO_SUCH_PROPERTY) + ERROR("CM_NO_SUCH_PROPERTY(%s, %s)\n", comp->pathname, propertyName, 0, 0, 0, 0); + } + + OSAL_UNLOCK_API(); + + return error; +} diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c b/drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c new file mode 100644 index 00000000000..0c055c7f6f9 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include +#include +#include +#include +#include "../inc/dspevent.h" + + +#define DSP_REMOTE_EVENT_SIZE_IN_BYTE (4*DSP_REMOTE_EVENT_SIZE_IN_DSPWORD) +#define DSP_REMOTE_EVENT_NEXT_FIELD_OFFSET 0 +#define DSP_REMOTE_EVENT_REACTION_FIELD_OFFSET 1 +#define DSP_REMOTE_EVENT_THIS_FIELD_OFFSET 2 +#define DSP_REMOTE_EVENT_PRIORITY_FIELD_OFFSET 3 +#define DSP_REMOTE_EVENT_DATA_FIELD_OFFSET 4 + +t_cm_error dspevent_createDspEventFifo( + const t_component_instance *pComp, + const char* nameOfTOP, + t_uint32 fifoNbElem, + t_uint32 fifoElemSizeInWord, + t_dsp_memory_type_id dspEventMemType, + t_memory_handle *pHandle) +{ + t_uint32 dspElementAddr; + t_uint32 *elemAddr32; + int i; + + // Allocate fifo + *pHandle = cm_DM_Alloc(pComp->domainId, dspEventMemType, fifoNbElem*fifoElemSizeInWord, CM_MM_ALIGN_2WORDS, TRUE); + if(*pHandle == INVALID_MEMORY_HANDLE) + return CM_NO_MORE_MEMORY; + + cm_DSP_GetDspAddress(*pHandle, &dspElementAddr); + + elemAddr32 = (t_uint32*)cm_DSP_GetHostLogicalAddress(*pHandle); + + LOG_INTERNAL(2, "\n##### FIFO (dsp event): ARM=0x%x DSP=0x%x\n", elemAddr32, dspElementAddr, 0, 0, 0, 0); + + // Read attribute addr (we assume that variable in XRAM) + cm_writeAttribute(pComp, nameOfTOP, dspElementAddr); + + // Initialise the linked list (next...) + for (i = 0; i < fifoNbElem - 1; i++) + { + dspElementAddr += fifoElemSizeInWord; + + /* Write next field */ + *elemAddr32 = dspElementAddr; + /* Write THIS field & priority field */ + *(volatile t_uint64*)&elemAddr32[DSP_REMOTE_EVENT_THIS_FIELD_OFFSET] = + ((t_uint64)pComp->thisAddress | (((t_uint64)pComp->priority) << 32)); + + elemAddr32 += fifoElemSizeInWord; + } + + /* Last element: Write next field */ + *elemAddr32 = 0x0 /* NULL */; + /* Last element: Write THIS field & priority field */ + *(volatile t_uint64*)&elemAddr32[DSP_REMOTE_EVENT_THIS_FIELD_OFFSET] = + ((t_uint64)pComp->thisAddress | (((t_uint64)pComp->priority) << 32)); + + return CM_OK; +} + + + +void dspevent_destroyDspEventFifo(t_memory_handle handle) +{ + (void)cm_DM_Free(handle, TRUE); +} diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c new file mode 100644 index 00000000000..7391669419e --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c @@ -0,0 +1,329 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "../inc/dspevent.h" +#include "../inc/initializer.h" + +// Since now due to semaphore use call is synchrone so we only need a fifo size of three +// (due to updateStack + (InstructionCacheLock or InstructionCacheUnlock)) +#define DEFAULT_INITIALIZER_FIFO_SIZE 3 + +/* private prototype */ +PRIVATE t_cm_error cm_COMP_generic(t_nmf_core_id coreId, t_event_params_handle paramArray, t_uint32 paramNumber, t_uint32 serviceIndex); + +/* + * This module is tightly coupled with cm_DSP_components one (communication/initializer) + */ +static struct { + t_nmf_fifo_arm_desc* downlinkFifo; + t_nmf_fifo_arm_desc* uplinkFifo; + t_memory_handle dspfifoHandle; + t_nmf_osal_sem_handle fifoSemHandle; +} initializerDesc[NB_CORE_IDS]; + +PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId) +{ + t_uint32 i; + t_cm_error error; + t_component_instance *ee; + t_dsp_offset sharedVarOffset; + t_interface_provide_description itfProvide; + t_interface_provide* provide; + + ee = cm_EEM_getExecutiveEngine(coreId)->instance; + + // Get interface description + if((error = cm_getProvidedInterface(ee, "service", &itfProvide)) != CM_OK) + return error; + provide = &ee->template->provides[itfProvide.provideIndex]; + + + if ((error = dspevent_createDspEventFifo( + ee, "comms/TOP", + DEFAULT_INITIALIZER_FIFO_SIZE, + DSP_REMOTE_EVENT_SIZE_IN_DSPWORD, + INTERNAL_XRAM24, + &initializerDesc[coreId].dspfifoHandle)) != CM_OK) + return error; + + /* create fifo semaphore */ + initializerDesc[coreId].fifoSemHandle = OSAL_CreateSemaphore(DEFAULT_INITIALIZER_FIFO_SIZE); + if (initializerDesc[coreId].fifoSemHandle == 0) { + dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle); + return CM_NO_MORE_MEMORY; + } + + /* static armTHis initialisation */ + /* + * In the two next fifo_alloc call (1+n) means that we want to manage the hostThis_or_TOP and one method for each params fifos */ + initializerDesc[coreId].downlinkFifo = + fifo_alloc(ARM_CORE_ID, coreId, + INIT_COMPONENT_CMD_SIZE, DEFAULT_INITIALIZER_FIFO_SIZE, + (1+provide->interface->methodNumber), paramsLocation, extendedFieldLocation, cm_DSP_GetState(coreId)->domainEE); + if (initializerDesc[coreId].downlinkFifo == NULL) + { + OSAL_DestroySemaphore(initializerDesc[coreId].fifoSemHandle); + dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle); + return CM_NO_MORE_MEMORY; + } + + initializerDesc[coreId].uplinkFifo = + fifo_alloc(coreId, ARM_CORE_ID, + INIT_COMPONENT_ACK_SIZE, DEFAULT_INITIALIZER_FIFO_SIZE, + (1), paramsLocation, extendedFieldLocation, cm_DSP_GetState(coreId)->domainEE); /* 1 is mandatory to compute internally the indexMask */ + /* this statement is acceptable only written by skilled man ;) */ + /* We don't used bcDescRef, since we assume that we don't need params size */ + if (initializerDesc[coreId].uplinkFifo == NULL) + { + OSAL_DestroySemaphore(initializerDesc[coreId].fifoSemHandle); + fifo_free(initializerDesc[coreId].downlinkFifo); + dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle); + return CM_NO_MORE_MEMORY; + } + + cm_writeAttribute(ee, "comms/FIFOcmd", initializerDesc[coreId].downlinkFifo->dspAdress); + + cm_writeAttribute(ee, "comms/FIFOack", initializerDesc[coreId].uplinkFifo->dspAdress); + + sharedVarOffset = cm_getAttributeMpcAddress(ee, "comms/TOP"); + + /* HOST->DSP ParamsFifo extended fields initialisation */ + fifo_params_setSharedField( + initializerDesc[coreId].downlinkFifo, + 0, + (t_shared_field)sharedVarOffset /* TOP DSP Address */ + ); + for(i=0; iinterface->methodNumber; i++) + { + fifo_params_setSharedField( + initializerDesc[coreId].downlinkFifo, + i + 1, + provide->indexes[itfProvide.collectionIndex][i].methodAddresses); + } + + /* DSP->HOST ParamsFifo extended fields initialisation */ + fifo_params_setSharedField( + initializerDesc[coreId].uplinkFifo, + 0, + (t_shared_field)NMF_INTERNAL_USERTHIS + ); + + return CM_OK; +} + + +PUBLIC t_cm_error cm_COMP_CallService( + int serviceIndex, + t_component_instance *pComp, + t_uint32 methodAddress) { + t_cm_error error; + t_uint16 params[INIT_COMPONENT_CMD_SIZE]; + t_bool isSynchronous = (serviceIndex == NMF_CONSTRUCT_SYNC_INDEX || + serviceIndex == NMF_START_SYNC_INDEX || + serviceIndex == NMF_DESTROY_INDEX)?TRUE:FALSE; + + params[INIT_COMPONENT_CMD_HANDLE_INDEX] = (t_uint16)((unsigned int)pComp & 0xFFFF); + params[INIT_COMPONENT_CMD_HANDLE_INDEX+1] = (t_uint16)((unsigned int)pComp >> 16); + params[INIT_COMPONENT_CMD_THIS_INDEX] = (t_uint16)(pComp->thisAddress & 0xFFFF); + params[INIT_COMPONENT_CMD_THIS_INDEX+1] = (t_uint16)(pComp->thisAddress >> 16); + params[INIT_COMPONENT_CMD_METHOD_INDEX] = (t_uint16)(methodAddress & 0xFFFF); + params[INIT_COMPONENT_CMD_METHOD_INDEX+1] = (t_uint16)(methodAddress >> 16); + + error = cm_COMP_generic(pComp->template->dspId, params, sizeof(params) / sizeof(t_uint16), serviceIndex); + + if (isSynchronous == TRUE && error == CM_OK) { + if (OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) + error = CM_MPC_NOT_RESPONDING; + } + + return error; +} + +PUBLIC void cm_COMP_INIT_Close(t_nmf_core_id coreId) +{ + unsigned int i; + + /* wait for semaphore to be sure it would not be touch later on */ + /* in case of timeout we break and try to clean everythink */ + for(i = 0; i < DEFAULT_INITIALIZER_FIFO_SIZE; i++) { + if (OSAL_SEMAPHORE_WAIT_TIMEOUT(initializerDesc[coreId].fifoSemHandle) != SYNC_OK) + break; + } + + /* destroy semaphore */ + OSAL_DestroySemaphore(initializerDesc[coreId].fifoSemHandle); + + /* Unallocate initializerDesc[index].uplinkFifo */ + /* (who is used in this particular case to store dummy (with no data space (only descriptor)) DSP->HOST params fifo */ + fifo_free(initializerDesc[coreId].uplinkFifo); + + /* Unallocate initializerDesc[index].downlinkFifo */ + fifo_free(initializerDesc[coreId].downlinkFifo); + + /* Unallocate initializerDesc[index].dspfifoHandle */ + dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle); +} + +PUBLIC void processAsyncAcknowledge(t_nmf_core_id coreId, t_event_params_handle pParam) +{ + cm_AcknowledgeEvent(initializerDesc[coreId].uplinkFifo); + + OSAL_SemaphorePost(initializerDesc[coreId].fifoSemHandle,1); +} + +PUBLIC void processSyncAcknowledge(t_nmf_core_id coreId, t_event_params_handle pParam) +{ + cm_AcknowledgeEvent(initializerDesc[coreId].uplinkFifo); + + OSAL_SemaphorePost(initializerDesc[coreId].fifoSemHandle,1); + OSAL_SemaphorePost(semHandle,1); +} + +PUBLIC t_cm_error cm_COMP_UpdateStack( + t_nmf_core_id coreId, + t_uint32 stackSize +) +{ + t_uint16 params[2]; + + // Marshall parameter + params[0] = (t_uint16)((unsigned int)stackSize & 0xFFFF); + params[1] = (t_uint16)((unsigned int)stackSize >> 16); + + return cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_UPDATE_STACK); +} + +PUBLIC t_cm_error cm_COMP_ULPForceWakeup( + t_nmf_core_id coreId +) +{ + t_cm_error error; + + error = cm_COMP_generic(coreId, NULL, 0, NMF_ULP_FORCEWAKEUP); + + if (error == CM_OK) { + if (OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) + error = CM_MPC_NOT_RESPONDING; + } + + return error; +} + +PUBLIC t_cm_error cm_COMP_ULPAllowSleep( + t_nmf_core_id coreId +) +{ + return cm_COMP_generic(coreId, NULL, 0, NMF_ULP_ALLOWSLEEP); +} + +PUBLIC t_cm_error cm_COMP_InstructionCacheLock( + t_nmf_core_id coreId, + t_uint32 mmdspAddr, + t_uint32 mmdspSize +) +{ + t_uint16 params[4]; + t_uint32 startAddr = cm_DSP_GetState(coreId)->locked_offset; + int way; + + for(way = 1; startAddr < mmdspAddr + mmdspSize; startAddr += MMDSP_CODE_CACHE_WAY_SIZE, way++) + { + if(mmdspAddr < startAddr + MMDSP_CODE_CACHE_WAY_SIZE) + { + t_cm_error error; + + // Marshall parameter + params[0] = (t_uint16)((unsigned int)startAddr & 0xFFFF); + params[1] = (t_uint16)((unsigned int)startAddr >> 16); + params[2] = (t_uint16)((unsigned int)way & 0xFFFF); + params[3] = (t_uint16)((unsigned int)way >> 16); + + if((error = cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_LOCK_CACHE)) != CM_OK) + return error; + } + } + + return CM_OK; +} + +PUBLIC t_cm_error cm_COMP_InstructionCacheUnlock( + t_nmf_core_id coreId, + t_uint32 mmdspAddr, + t_uint32 mmdspSize +) +{ + t_uint16 params[2]; + t_uint32 startAddr = cm_DSP_GetState(coreId)->locked_offset; + int way; + + for(way = 1; startAddr < mmdspAddr + mmdspSize; startAddr += MMDSP_CODE_CACHE_WAY_SIZE, way++) + { + if(mmdspAddr < startAddr + MMDSP_CODE_CACHE_WAY_SIZE) + { + t_cm_error error; + + // Marshall parameter + params[0] = (t_uint16)((unsigned int)way & 0xFFFF); + params[1] = (t_uint16)((unsigned int)way >> 16); + + if((error = cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_UNLOCK_CACHE)) != CM_OK) + return error; + } + } + + return CM_OK; +} + +/* private method */ +PRIVATE t_cm_error cm_COMP_generic( + t_nmf_core_id coreId, + t_event_params_handle paramArray, + t_uint32 paramNumber, + t_uint32 serviceIndex +) +{ + t_event_params_handle _xyuv_data; + t_cm_error error; + t_uint32 i; + + // wait for an event in fifo + if (OSAL_SEMAPHORE_WAIT_TIMEOUT(initializerDesc[coreId].fifoSemHandle) != SYNC_OK) + return CM_MPC_NOT_RESPONDING; + + // AllocEvent + if((_xyuv_data = cm_AllocEvent(initializerDesc[coreId].downlinkFifo)) == NULL) + { + ERROR("CM_INTERNAL_FIFO_OVERFLOW: service FIFO full\n", 0, 0, 0, 0, 0, 0); + error = CM_INTERNAL_FIFO_OVERFLOW; + goto unlock; + } + + // Copy param + for(i=0;i for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include + +#include +#include +#include + +#include + + +t_nmf_table ComponentTable; /**< list (table) of components */ + +static t_uint32 cm_getMaxStackValue(t_component_instance *pComponent); +static t_uint16 getNumberOfInstance(t_component_instance* component); +static t_uint16 getNumberOfStart(t_component_instance* component); + + +t_cm_error cm_COMP_Init(void) { + t_cm_error error; + error = cm_initTable(&ComponentTable); + if (error == CM_OK) + error = cm_initTable(&Host2MpcBindingTable); + return error; +} + +void cm_COMP_Destroy(void) { + cm_destroyTable(&ComponentTable); + cm_destroyTable(&Host2MpcBindingTable); +} + +/** cm_addComponent - Add an internal handler to the list + * + * 1. Increase the size of the list if it's full + * 2. Search an empty entry + * 3. Add the element to the list + * 4. Compute and return the "user handle" (= t_cm_instance_handle) + */ +static t_cm_instance_handle cm_addComponent(t_component_instance *comp) +{ + OSAL_DisableServiceMessages(); + comp->instance = cm_addEntry(&ComponentTable, comp); + OSAL_EnableServiceMessages(); + + return comp->instance; +} + +/** cm_delComponent - remove the given component from the list + * + * 1. Check if the handle is valid + * 2. Search the entry and free it + */ +static void cm_delComponent(t_component_instance *comp) +{ + if (comp == NULL) + return; + + OSAL_DisableServiceMessages(); + cm_delEntry(&ComponentTable, comp->instance & INDEX_MASK); + OSAL_EnableServiceMessages(); +} + +/** cm_lookupComponent - search the component corresponding to + * the component instance. + * + * 1. Check if the instance is valid + * 2. Return a pointer to the component + */ +t_component_instance *cm_lookupComponent(const t_cm_instance_handle hdl) +{ + return cm_lookupEntry(&ComponentTable, hdl); +} + +static void cm_DestroyComponentMemory(t_component_instance *component) +{ + int i; + + /* + * Remove instance from list + */ + cm_delComponent(component); + + /* + * Destroy instance + */ + { + struct t_client_of_singleton* cur = component->clientOfSingleton; + + for( ; cur != NULL ; ) + { + struct t_client_of_singleton* tmp = cur; + cur = cur->next; + + OSAL_Free(tmp); + } + } + + for(i = 0; i < component->template->requireNumber; i++) + { + OSAL_Free(component->interfaceReferences[i]); + } + + cm_StringRelease(component->pathname); + + cm_ELF_FreeInstance(component->template->dspId, component->template->memories, component->memories); + + cm_unloadComponent(component->template); + OSAL_Free(component); +} + +/** + * Non-Require: + * - MMDSP could be sleep (Since we access it only through HSEM) + */ +void cm_delayedDestroyComponent(t_component_instance *component) { + int i; + + /* + * Remove component from load map here + */ + cm_DSPABI_RemoveLoadMap( + component->domainId, + component->template->name, + component->memories, + component->pathname, + component); + + // Generate XTI/STM trace + cm_TRC_traceLoadMap(TRACE_COMPONENT_COMMAND_REMOVE, component); + + /* + * disconnect interrupt handler if needed + */ + for(i = 0; i < component->template->provideNumber; i++) + { + if(component->template->provides[i].interruptLine) + { + cm_unbindInterfaceStaticInterrupt(component->template->dspId, component->template->provides[i].interruptLine); + } + } + + /* + * Update dsp stack size if needed + */ + if (component->template->minStackSize > MIN_STACK_SIZE) + { + if (cm_EEM_isStackUpdateNeed(component->template->dspId, component->priority, FALSE, component->template->minStackSize)) + { + t_uint32 newStackValue; + t_uint32 maxComponentStackSize; + + maxComponentStackSize = cm_getMaxStackValue(component); + cm_EEM_UpdateStack(component->template->dspId, component->priority, maxComponentStackSize, &newStackValue); + if (cm_DSP_GetState(component->template->dspId)->state == MPC_STATE_BOOTED) + cm_COMP_UpdateStack(component->template->dspId, newStackValue); + } + } + + cm_DestroyComponentMemory(component); +} + +/** + * Pre-Require: + * - MMDSP wakeup (when loading in TCM) + */ +t_cm_error cm_instantiateComponent(const char* templateName, + t_cm_domain_id domainId, + t_nmf_ee_priority priority, + const char* pathName, + t_elfdescription *elfhandle, + t_component_instance** refcomponent) +{ + t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId); + t_dup_char templateNameDup; + t_component_template* template; + t_component_instance *component; + /* coverity[var_decl] */ + t_cm_error error; + int i, j, k; + + *refcomponent = NULL; + + templateNameDup = cm_StringDuplicate(templateName); + if(templateNameDup == NULL) + return CM_NO_MORE_MEMORY; + + /* + * Lookup in template list + */ + template = cm_lookupTemplate(coreId, templateNameDup); + if(template != NULL) + { + if(template->classe == SINGLETON) + { + // Return same handle for singleton component + struct t_client_of_singleton* cl; + + cm_StringRelease(templateNameDup); + + cl = cm_getClientOfSingleton(template->singletonIfAvaliable, TRUE, domainDesc[domainId].client); + if(cl == NULL) + return CM_NO_MORE_MEMORY; + cl->numberOfInstance++; + + *refcomponent = template->singletonIfAvaliable; + LOG_INTERNAL(1, "##### Singleton : New handle of %s/%x component on %s provItf=%d#####\n", + template->singletonIfAvaliable->pathname, template->singletonIfAvaliable, cm_getDspName(coreId), + template->singletonIfAvaliable->providedItfUsedCount, 0, 0); + return CM_OK; + } + } + + // Get the dataFile (identity if already pass as parameter) + if((elfhandle = cm_REP_getComponentFile(templateNameDup, elfhandle)) == NULL) + { + cm_StringRelease(templateNameDup); + return CM_COMPONENT_NOT_FOUND; + } + + // Load template + if((error = cm_loadComponent(templateNameDup, domainId, elfhandle, &template)) != CM_OK) + { + cm_StringRelease(templateNameDup); + return error; + } + + // templateNameDup no more used, release it + cm_StringRelease(templateNameDup); + + // Allocated component + component = (t_component_instance*)OSAL_Alloc_Zero( + sizeof(t_component_instance) + + sizeof(t_interface_reference*) * template->requireNumber); + if(component == NULL) + { + cm_unloadComponent(template); + return CM_NO_MORE_MEMORY; + } + + component->interfaceReferences = (t_interface_reference**)((char*)component + sizeof(t_component_instance)); + component->template = template; + + /* + * Update linked list + */ + if (cm_addComponent(component) == 0) { + cm_unloadComponent(template); + OSAL_Free(component); + return CM_NO_MORE_MEMORY; + } + + // NOTE: From here use cm_DestroyComponentMemory + + component->pathname = pathName ? cm_StringDuplicate(pathName) : cm_StringReference(anonymousDup); + if(component->pathname == NULL) + { + cm_DestroyComponentMemory(component); + return CM_NO_MORE_MEMORY; + } + + LOG_INTERNAL(1, "\n##### Instantiate %s/%x (%s) component on %s at priority %d #####\n", component->pathname, component, template->name, cm_getDspName(coreId), priority, 0); + + if((error = cm_ELF_LoadInstance(domainId, elfhandle, template->memories, component->memories)) != CM_OK) + { + cm_DestroyComponentMemory(component); + return error; + } + + if((error = cm_ELF_relocatePrivateSegments( + component->memories, + elfhandle, + template)) != CM_OK) + { + cm_DestroyComponentMemory(component); + return error; + } + + cm_ELF_FlushInstance(coreId, template->memories, component->memories); + + /* + * Create a new component instance + */ + component->domainId = domainId; + component->priority = priority; + component->thisAddress = 0xFFFFFFFF; + component->state = STATE_NONE; + + if(component->template->classe == SINGLETON) + { // Return same handle for singleton component + struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, TRUE, domainDesc[domainId].client); + if(cl == NULL) + { + cm_DestroyComponentMemory(component); + return CM_NO_MORE_MEMORY; + } + + cl->numberOfInstance = 1; + template->singletonIfAvaliable = component; + } + + if(component->memories[template->thisMemory->id] != INVALID_MEMORY_HANDLE) + cm_DSP_GetDspAddress(component->memories[template->thisMemory->id], &component->thisAddress); + else { + // In case of singleton or component without data + component->thisAddress = 0; + } + + /* + * Create empty required interfaces array and set method interface to Panic + */ + for(i = 0; i < template->requireNumber; i++) // For all required interface + { + component->interfaceReferences[i] = + (t_interface_reference*)OSAL_Alloc_Zero(sizeof(t_interface_reference) * template->requires[i].collectionSize); + if(component->interfaceReferences[i] == NULL) + { + cm_DestroyComponentMemory(component); + return CM_NO_MORE_MEMORY; + } + + for(j = 0; j < template->requires[i].collectionSize; j++) // ... and for each index in collection (set THIS&method for each client) + { + component->interfaceReferences[i][j].instance = NULL; + component->interfaceReferences[i][j].bfInfoID = BF_SYNCHRONOUS; // Just to memorize no Binding component used and unbind ToVoid happy ;-). + + if(template->classe == COMPONENT && template->requires[i].indexes != NULL) + { + // If component, fill THIS to itself to detect UNBINDED panic with rigth DSP + t_interface_require_index *requireindex = &template->requires[i].indexes[j]; + for(k = 0; k < requireindex->numberOfClient; k++) + { + t_uint32 *hostAddr; + + hostAddr = (t_uint32*)( + cm_DSP_GetHostLogicalAddress( + component->memories[requireindex->memories[k].memory->id]) + + requireindex->memories[k].offset * requireindex->memories[k].memory->memEntSize); + *hostAddr++ = (t_uint32)component->thisAddress; + } + } + } + } + + /* + * Inform debugger about new component + */ + if ((error = cm_DSPABI_AddLoadMap( + domainId, + template->name, + component->pathname, + component->memories, + component)) != CM_OK) + { + cm_DestroyComponentMemory(component); + return error; + } + + // Generate XTI/STM trace + cm_TRC_traceLoadMap(TRACE_COMPONENT_COMMAND_ADD, component); + + // NOTE: From here use cm_delayedDestroyComponent + + /* + * Relocate interrupt if this is an interrupt + */ + for(i = 0; i < template->provideNumber; i++) + { + if(template->provides[i].interruptLine) + { + if ((error = cm_bindInterfaceStaticInterrupt(coreId, + template->provides[i].interruptLine, + component, + template->provides[i].name)) != CM_OK) + { + cm_delayedDestroyComponent(component); + return error; + } + } + } + + /* + * For first instance of a component; Update ee stack size if needed + */ + if(template->classe != FIRMWARE && template->numberOfInstance == 1 && template->minStackSize > MIN_STACK_SIZE) + { + t_uint32 newStackValue; + + if (cm_EEM_isStackUpdateNeed(template->dspId, priority, TRUE, template->minStackSize)) + { + error = cm_EEM_UpdateStack(template->dspId, priority, template->minStackSize, &newStackValue); + if (error != CM_OK) + { + cm_delayedDestroyComponent(component); + return error; + } + cm_COMP_UpdateStack(template->dspId, newStackValue); + } + } + + + /* + * For component or first instance + */ + if(template->classe == SINGLETON || template->classe == COMPONENT) + { + /* + * Call init function generated by the compiler (one per .elf) + */ + LOG_INTERNAL(2, "constructor call(s) <%s>\n", template->name, 0, 0, 0, 0, 0); + if (cm_DSP_GetState(template->dspId)->state != MPC_STATE_BOOTED) + { + cm_delayedDestroyComponent(component); + return CM_MPC_NOT_RESPONDING; + } + else if ((error = cm_COMP_CallService( + (priority > cm_EEM_getExecutiveEngine(coreId)->instance->priority)?NMF_CONSTRUCT_SYNC_INDEX:NMF_CONSTRUCT_INDEX, + component, + template->LCCConstructAddress)) != CM_OK) + { + if (error == CM_MPC_NOT_RESPONDING) + ERROR("CM_MPC_NOT_RESPONDING: can't call constructor '%s'\n", component->pathname, 0, 0, 0, 0, 0); + cm_delayedDestroyComponent(component); + return error; + } + } + else + { + /* be sure everything is write into memory, not required elsewhere since will be done by cm_COMP_CallService */ + OSAL_mb(); + } + + // For firmware; Directly switch to STARTED state, don't need to start it + if (template->classe == FIRMWARE) + component->state = STATE_RUNNABLE; + else + component->state = STATE_STOPPED; + + *refcomponent = component; + return CM_OK; +} + +struct t_client_of_singleton* cm_getClientOfSingleton(t_component_instance* component, t_bool createdIfNotExist, t_nmf_client_id clientId) +{ + struct t_client_of_singleton* cur = component->clientOfSingleton; + + for( ; cur != NULL ; cur = cur->next) + { + if(cur->clientId == clientId) + { + return cur; + } + } + + //if(createdIfNotExist) + { + cur = OSAL_Alloc(sizeof(struct t_client_of_singleton)); + if(cur != NULL) + { + cur->clientId = clientId; + cur->next = component->clientOfSingleton; + cur->numberOfBind = 0; + cur->numberOfInstance= 0; + cur->numberOfStart = 0; + component->clientOfSingleton = cur; + } + } + return cur; +} + +/** + * Non-Require: + * - MMDSP could be sleep (Since we access it only through HSEM) + */ +t_cm_error cm_startComponent(t_component_instance* component, t_nmf_client_id clientId) +{ + t_cm_error error; + char value[MAX_PROPERTY_VALUE_LENGTH]; + int i; + + /* + * Special code for SINGLETON handling + */ + if(component->template->classe == SINGLETON) + { + struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); + if(cl != NULL) + cl->numberOfStart++; + // A singleton could be started twice, thus start it only if first client starter + if(getNumberOfStart(component) > 1) + return CM_OK; + + // Fall through and start really the singleton. + } + + if(component->state == STATE_RUNNABLE) + return CM_COMPONENT_NOT_STOPPED; + + // CM_ASSERT component->state == STATE_STOPPED + + /* + * Check that all required binding have been binded! + */ + for(i = 0; i < component->template->requireNumber; i++) + { + int nb = component->template->requires[i].collectionSize, j; + for(j = 0; j < nb; j++) + { + if(component->interfaceReferences[i][j].instance == NULL && + (component->template->requires[i].requireTypes & (OPTIONAL_REQUIRE | INTRINSEC_REQUIRE)) == 0) + { + ERROR("CM_REQUIRE_INTERFACE_UNBINDED: Required interface '%s'.'%s' binded\n", component->pathname, component->template->requires[i].name, 0, 0, 0, 0); + return CM_REQUIRE_INTERFACE_UNBINDED; + } + } + } + + component->state = STATE_RUNNABLE; + + /* + * Power on, HW resources if required + */ + if(cm_getComponentProperty( + component, + "hardware", + value, + sizeof(value)) == CM_OK) + { + // The PRCMU seem not supporting the transition of asking HW IP on while DSP in retention + // -> Thus force wake up of the MMDSP before asking the transition + if ((error = cm_EEM_ForceWakeup(component->template->dspId)) != CM_OK) + return error; + + error = cm_PWR_EnableMPC(MPC_PWR_HWIP, component->template->dspId); + + cm_EEM_AllowSleep(component->template->dspId); + + if(error != CM_OK) + return error; + } + + /* + * Call starter if available + */ + if(component->template->LCCStartAddress != 0) + { + if (cm_DSP_GetState(component->template->dspId)->state != MPC_STATE_BOOTED) + { + return CM_MPC_NOT_RESPONDING; + } + else if ((error = cm_COMP_CallService( + (component->priority > cm_EEM_getExecutiveEngine(component->template->dspId)->instance->priority)?NMF_START_SYNC_INDEX:NMF_START_INDEX, + component, + component->template->LCCStartAddress)) != CM_OK) + { + if (error == CM_MPC_NOT_RESPONDING) + ERROR("CM_MPC_NOT_RESPONDING: can't call starter '%s'\n", component->pathname, 0, 0, 0, 0, 0); + return error; + } + } + + return CM_OK; +} + +/** + * Non-Require: + * - MMDSP could be sleep (Since we access it only through HSEM) + */ +t_cm_error cm_stopComponent(t_component_instance* component, t_nmf_client_id clientId) +{ + char value[MAX_PROPERTY_VALUE_LENGTH]; + t_cm_error error = CM_OK; + + /* + * Special code for SINGLETON handling + */ + if(component->template->classe == SINGLETON) + { + struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); + if(cl != NULL) + cl->numberOfStart--; + // A singleton could be started twice, thus stop it only if no more client starter + if(getNumberOfStart(component) > 0) + return CM_OK; + + // Fall through and stop really the singleton. + } + + /* + * Component life cycle sanity check + */ + if(component->state == STATE_STOPPED) + return CM_COMPONENT_NOT_STARTED; + + // CM_ASSERT component->state == STATE_RUNNABLE + component->state = STATE_STOPPED; + + if (cm_DSP_GetState(component->template->dspId)->state != MPC_STATE_BOOTED) + { + error = CM_MPC_NOT_RESPONDING; + } + else + { + /* + * Call stopper if available + */ + if(component->template->LCCStopAddress != 0) + { + if ((error = cm_COMP_CallService( + NMF_STOP_INDEX, + component, + component->template->LCCStopAddress)) != CM_OK) + { + if (error == CM_MPC_NOT_RESPONDING) + ERROR("CM_MPC_NOT_RESPONDING: can't call stopper '%s'\n", component->pathname, 0, 0, 0, 0, 0); + } + } + } + + /* + * Power on, HW resources if required + */ + if(cm_getComponentProperty( + component, + "hardware", + value, + sizeof(value)) == CM_OK) + { + cm_PWR_DisableMPC(MPC_PWR_HWIP, component->template->dspId); + } + + return error; +} + +t_cm_error cm_destroyInstance(t_component_instance* component, t_destroy_state forceDestroy) +{ + int i, j; + + LOG_INTERNAL(1, "\n##### Destroy %s/%x (%s) component on %s #####\n", + component->pathname, component, component->template->name, cm_getDspName(component->template->dspId), 0, 0); + + /* + * Component life cycle sanity check; do it only when destroying last reference. + */ + if(forceDestroy == DESTROY_NORMAL) + { + if (component->state == STATE_RUNNABLE) + return CM_COMPONENT_NOT_STOPPED; + + // CM_ASSERT component->state == STATE_STOPPED + + // Check that all required binding have been unbound! + for(i = 0; i < component->template->requireNumber; i++) + { + int nb = component->template->requires[i].collectionSize; + for(j = 0; j < nb; j++) + { + if(component->interfaceReferences[i][j].instance != NULL) + { + ERROR("CM_COMPONENT_NOT_UNBINDED: Required interface %s/%x.%s still binded\n", + component->pathname, component, component->template->requires[i].name, 0, 0, 0); + return CM_COMPONENT_NOT_UNBINDED; + } + } + } + + // Check that all provided bindings have been unbound! + if (component->providedItfUsedCount != 0) + { + unsigned idx; + + ERROR("CM_COMPONENT_NOT_UNBINDED: Still %d binding to %s/%x provided interface\n", + component->providedItfUsedCount, component->pathname, component, 0, 0, 0); + + /* Find which interface is still bound to gracefully print an error message */ + for (idx=0; idxtemplate->requireNumber; i++) + { + for (j = 0; j < componentEntry(idx)->template->requires[i].collectionSize; j++) + { + if(componentEntry(idx)->interfaceReferences[i][j].instance == component + && component->template->provides[componentEntry(idx)->interfaceReferences[i][j].provideIndex].interruptLine == 0) + { + ERROR(" -> %s/%x.%s still used by %s/%x.%s\n", + component->pathname, component, + component->template->provides[componentEntry(idx)->interfaceReferences[i][j].provideIndex].name, + componentEntry(idx)->pathname, + componentEntry(idx), + componentEntry(idx)->template->requires[i].name); + } + } + } + } + + return CM_COMPONENT_NOT_UNBINDED; + } + } + + // Sanity check finished, here, we will do the JOB whatever error + + if (cm_DSP_GetState(component->template->dspId)->state == MPC_STATE_BOOTED) + { + /* + * Call destroy if available + */ + /* Call the destructor only if we don't want to force the destruction */ + if(forceDestroy != DESTROY_WITHOUT_CHECK_CALL && component->template->LCCDestroyAddress != 0) + { + if (cm_COMP_CallService( + NMF_DESTROY_INDEX, + component, + component->template->LCCDestroyAddress) != CM_OK) + { + ERROR("CM_MPC_NOT_RESPONDING: can't call destroy '%s'\n", component->pathname, 0, 0, 0, 0, 0); + } + } + } + + cm_delayedDestroyComponent(component); + + return CM_OK; +} + +/** + * Pre-Require: + * - MMDSP wakeup (when accessing loadmap) + */ +t_cm_error cm_destroyInstanceForClient(t_component_instance* component, t_destroy_state forceDestroy, t_nmf_client_id clientId) +{ + /* + * Special code for SINGLETON handling + */ + if(component->template->classe == SINGLETON) + { + struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); + int nbinstance; + if(cl != NULL) + cl->numberOfInstance--; + + // A singleton could be instantiate twice, thus destroy it only if no more client constructor + nbinstance = getNumberOfInstance(component); + if(nbinstance > 0) + { + LOG_INTERNAL(1, "##### Singleton : Delete handle of %s/%x (%s) component on %s [%d] provItf=%d #####\n", + component->pathname, component, component->template->name, cm_getDspName(component->template->dspId), + nbinstance, component->providedItfUsedCount); + return CM_OK; + } + + // Fall through + } + + return cm_destroyInstance(component, forceDestroy); +} + + +static t_uint32 cm_getMaxStackValue(t_component_instance *pComponent) +{ + t_nmf_executive_engine_id executiveEngineId = cm_EEM_getExecutiveEngine(pComponent->template->dspId)->executiveEngineId; + t_uint32 res = MIN_STACK_SIZE; + unsigned int i; + + for (i=0; itemplate->dspId == componentEntry(i)->template->dspId) && + (executiveEngineId == SYNCHRONOUS_EXECUTIVE_ENGINE || componentEntry(i)->priority == pComponent->priority)) + { + if (componentEntry(i)->template->minStackSize > res) + res = componentEntry(i)->template->minStackSize; + } + } + + return res; +} + +static t_uint16 getNumberOfInstance(t_component_instance* component) +{ + t_uint16 instanceNumber = 0; + struct t_client_of_singleton* cur = component->clientOfSingleton; + + for( ; cur != NULL ; cur = cur->next) + { + instanceNumber += cur->numberOfInstance; + } + + return instanceNumber; +} + +static t_uint16 getNumberOfStart(t_component_instance* component) +{ + t_uint16 startNumber = 0; + struct t_client_of_singleton* cur = component->clientOfSingleton; + + for( ; cur != NULL ; cur = cur->next) + { + startNumber += cur->numberOfStart; + } + + return startNumber; +} diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c b/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c new file mode 100644 index 00000000000..a4e0a01a242 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c @@ -0,0 +1,325 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include + +/* + * + */ +t_cm_error cm_getComponentProperty( + const t_component_instance *component, + const char *propName, + char value[MAX_PROPERTY_VALUE_LENGTH], + t_uint32 valueLength){ + t_component_template* template = component->template; + int i; + + for(i = 0; i < template->propertyNumber; i++) { + if(cm_StringCompare(template->properties[i].name, propName, MAX_PROPERTY_NAME_LENGTH) == 0) { + cm_StringCopy( + value, + template->properties[i].value, + valueLength); + return CM_OK; + } + } + + return CM_NO_SUCH_PROPERTY; +} + +/** + * + */ +static t_attribute* cm_getAttributeDescriptor( + const t_component_instance *component, + const char *attrName) +{ + int i; + + for(i = 0; i < component->template->attributeNumber; i++) + { + if(cm_StringCompare(component->template->attributes[i].name, attrName, MAX_ATTRIBUTE_NAME_LENGTH) == 0) + { + return &component->template->attributes[i]; + } + } + + return NULL; +} + +t_dsp_address cm_getAttributeMpcAddress( + const t_component_instance *component, + const char *attrName) +{ + t_attribute* attribute; + t_uint32 dspAddress; + + if((attribute = cm_getAttributeDescriptor(component, attrName)) == NULL) + return 0x0; + + cm_DSP_GetDspAddress(component->memories[attribute->memory.memory->id], &dspAddress); + + return (dspAddress + + attribute->memory.offset); +} + +t_cm_logical_address cm_getAttributeHostAddr( + const t_component_instance *component, + const char *attrName) +{ + t_attribute* attribute; + + if((attribute = cm_getAttributeDescriptor(component, attrName)) == NULL) + return 0x0; + + // TODO JPF: component->template->attributes[i].memory.offset could be converted in byte during load + return cm_DSP_GetHostLogicalAddress(component->memories[attribute->memory.memory->id]) + + attribute->memory.offset * attribute->memory.memory->memEntSize; +} + + +t_cm_error cm_readAttribute( + const t_component_instance* component, + const char* attrName, + t_uint32* value) +{ + t_attribute* attribute; + t_cm_logical_address hostAddr; + + if((attribute = cm_getAttributeDescriptor(component, attrName)) == NULL) + { + ERROR("CM_NO_SUCH_ATTRIBUTE(%s, %s)\n", component->pathname, attrName, 0, 0, 0, 0); + return CM_NO_SUCH_ATTRIBUTE; + } + + // TODO JPF: component->template->attributes[i].memory.offset could be converted in byte during load + hostAddr = cm_DSP_GetHostLogicalAddress(component->memories[attribute->memory.memory->id]) + + attribute->memory.offset * attribute->memory.memory->memEntSize; + + if(attribute->memory.memory->memEntSize != 2) + *value = *((t_uint32 *)hostAddr) & ~MASK_BYTE3; + else + *value = *((t_uint16 *)hostAddr); + + LOG_INTERNAL(3, "cm_readAttribute: [%s:%s, %x]=%x\n", + component->pathname, attrName, hostAddr, *value, 0, 0); + + return CM_OK; +} + +t_uint32 cm_readAttributeNoError( + const t_component_instance* component, + const char* attrName) +{ + t_uint32 value; + + if(cm_readAttribute(component, attrName, &value) != CM_OK) + value = 0; + + return value; +} + +t_cm_error cm_writeAttribute( + const t_component_instance* component, + const char* attrName, + t_uint32 value) +{ + t_attribute* attribute; + t_cm_logical_address hostAddr; + + if((attribute = cm_getAttributeDescriptor(component, attrName)) == NULL) + { + ERROR("CM_NO_SUCH_ATTRIBUTE(%s, %s)\n", component->pathname, attrName, 0, 0, 0, 0); + return CM_NO_SUCH_ATTRIBUTE; + } + + // TODO JPF: component->template->attributes[i].memory.offset could be converted in byte during load + hostAddr = cm_DSP_GetHostLogicalAddress(component->memories[attribute->memory.memory->id]) + + attribute->memory.offset * attribute->memory.memory->memEntSize; + + if(attribute->memory.memory->memEntSize != 2) + *((t_uint32 *)hostAddr) = value & ~MASK_BYTE3; + else + *((t_uint16 *)hostAddr) = value; + + /* be sure attribute is write into memory */ + OSAL_mb(); + + LOG_INTERNAL(3, "cm_writeAttribute: [%s:%s, %x]=%x\n", + component->pathname, attrName, hostAddr, value, 0, 0); + + return CM_OK; +} + + +/** + * + */ +t_dsp_address cm_getFunction( + const t_component_instance* component, + const char* interfaceName, + const char* methodName) +{ + t_interface_provide_description itfProvide; + t_interface_provide* provide; + t_cm_error error; + int i; + + // Get interface description + if((error = cm_getProvidedInterface(component, interfaceName, &itfProvide)) != CM_OK) + return error; + + provide = &component->template->provides[itfProvide.provideIndex]; + + for(i = 0; i < provide->interface->methodNumber; i++) + { + if(cm_StringCompare(provide->interface->methodNames[i], methodName, MAX_INTERFACE_METHOD_NAME_LENGTH) == 0) + { + return provide->indexes[itfProvide.collectionIndex][i].methodAddresses; + } + } + + return 0x0; +} + +/** + * + */ +PRIVATE t_uint8 compareItfName(const char* simplename, const char* complexname, int *collectionIndex) { + int i; + + // Search if simplename is a prefix of complexname ?? + for(i = 0; simplename[i] != 0; i++) { + if(simplename[i] != complexname[i]) + return 1; // NO + } + + // YES + if(complexname[i] == '[') { + // This is a collection + int value = 0; + i++; + if(complexname[i] < '0' || complexname[i] > '9') { + return 1; + } + for(; complexname[i] >= '0' && complexname[i] <= '9'; i++) { + value = value * 10 + (complexname[i] - '0'); + } + if(complexname[i++] != ']') + return 1; + *collectionIndex = value; + } else + *collectionIndex = -1; + + if(complexname[i] != 0) { + // Complexe name has not been fully parsed -> different name + return 1; + } + + return 0; +} + + +/** + * + */ +PUBLIC t_cm_error cm_getProvidedInterface(const t_component_instance* server, + const char* itfName, + t_interface_provide_description *itfProvide){ + int i; + + for(i = 0; i < server->template->provideNumber; i++) + { + int collectionIndex; + if(compareItfName(server->template->provides[i].name, itfName, &collectionIndex) == 0) + { + t_interface_provide *provide = &server->template->provides[i]; + if(collectionIndex >= 0) + { + if(! (provide->provideTypes & COLLECTION_PROVIDE)) { + ERROR("CM_NO_SUCH_PROVIDED_INTERFACE(%s, %s)\n", + server->pathname, itfName, 0, 0, 0, 0); + goto out; + } + if(collectionIndex >= provide->collectionSize) { + ERROR("CM_NO_SUCH_PROVIDED_INTERFACE(%s, %s): out of range [0..%d[\n", + server->pathname, itfName, provide->collectionSize, + 0, 0, 0); + goto out; + } + } + else + { + if(provide->provideTypes & COLLECTION_PROVIDE) { + ERROR("CM_NO_SUCH_PROVIDED_INTERFACE(%s, %s): interface is a collection [0..%d[\n", + server->pathname, itfName, provide->collectionSize, + 0, 0, 0); + goto out; + } + collectionIndex = 0; + } + itfProvide->provideIndex = i; + itfProvide->server = server; + itfProvide->collectionIndex = collectionIndex; + itfProvide->origName = itfName; + return CM_OK; + } + } + + ERROR("CM_NO_SUCH_PROVIDED_INTERFACE(%s, %s)\n", server->pathname, itfName, 0, 0, 0, 0); +out: + itfProvide->provideIndex = 0; + itfProvide->server = NULL; + itfProvide->collectionIndex = 0; + itfProvide->origName = NULL; + return CM_NO_SUCH_PROVIDED_INTERFACE; +} + +/** + * + */ +t_cm_error cm_getRequiredInterface(const t_component_instance* client, + const char* itfName, + t_interface_require_description *itfRequire){ + int i; + + for(i = 0; i < client->template->requireNumber; i++) { + int collectionIndex; + if(compareItfName(client->template->requires[i].name, itfName, &collectionIndex) == 0) { + t_interface_require *require = &client->template->requires[i]; + if(collectionIndex >= 0) { + if(! (require->requireTypes & COLLECTION_REQUIRE)) { + ERROR("CM_NO_SUCH_REQUIRED_INTERFACE(%s, %s)\n", + client->pathname, itfName, 0, 0, 0, 0); + return CM_NO_SUCH_REQUIRED_INTERFACE; + } + if(collectionIndex >= require->collectionSize) { + ERROR("CM_NO_SUCH_REQUIRED_INTERFACE(%s, %s): out of range [0..%d[\n", + client->pathname, itfName, require->collectionSize, + 0, 0, 0); + return CM_NO_SUCH_REQUIRED_INTERFACE; + } + } else { + if(require->requireTypes & COLLECTION_REQUIRE) { + ERROR("CM_NO_SUCH_REQUIRED_INTERFACE(%s, %s): interface is a collection [0..%d[\n", + client->pathname, itfName, require->collectionSize, + 0, 0, 0); + return CM_NO_SUCH_REQUIRED_INTERFACE; + } + collectionIndex = 0; + } + itfRequire->client = client; + itfRequire->requireIndex = i; + itfRequire->collectionIndex = collectionIndex; + itfRequire->origName = itfName; + return CM_OK; + } + } + + ERROR("CM_NO_SUCH_REQUIRED_INTERFACE(%s, %s)\n", client->pathname, itfName, 0, 0, 0, 0); + return CM_NO_SUCH_REQUIRED_INTERFACE; +} diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/loader.c b/drivers/staging/nmf-cm/cm/engine/component/src/loader.c new file mode 100644 index 00000000000..762f74c4479 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/src/loader.c @@ -0,0 +1,338 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include +#include + +#include +#include +#include + +void START(void); +void END(char*); + +#define NHASH 79 //Use a prime number! +#define MULT 17 + +static t_component_template *templates[NB_CORE_IDS][NHASH]; + +static unsigned int templateHash(const char *str) +{ + unsigned int h = 0; + for(; *str; str++) + h = MULT * h + *str; + return h % NHASH; +} + +static void templateAdd(t_component_template *template) +{ + unsigned int h = templateHash(template->name); + + if(templates[template->dspId][h] != NULL) + templates[template->dspId][h]->prev = template; + template->next = templates[template->dspId][h]; + template->prev = NULL; + templates[template->dspId][h] = template; +} + +static void templateRemove(t_component_template *template) +{ + unsigned int h = templateHash(template->name); + + if(template->prev != NULL) + template->prev->next = template->next; + if(template->next != NULL) + template->next->prev = template->prev; + if(template == templates[template->dspId][h]) + templates[template->dspId][h] = template->next; +} + + +t_component_template* cm_lookupTemplate(t_nmf_core_id dspId, t_dup_char str) +{ + t_component_template *template; + + for(template = templates[dspId][templateHash(str)]; template != NULL; template = template->next) + { + if(str == template->name) + return template; + } + + return NULL; +} + +t_bool cm_isComponentOnCoreId(t_nmf_core_id coreId) { + t_uint32 i; + + for(i = 0; i < NHASH; i++) + { + if ((templates[coreId][i] != NULL) + && (templates[coreId][i]->classe != FIRMWARE)) // Skip firmware + return TRUE; + } + + return FALSE; +} + + +static t_dsp_address MemoryToDspAdress(t_component_template *template, t_memory_reference *memory) +{ + if(memory->memory == NULL) + return (t_dsp_address)memory->offset; + else + { + t_dsp_address address; + + cm_DSP_GetDspAddress(template->memories[memory->memory->id], &address); + + return (t_dsp_address)(address + memory->offset); + } +} + +/* + * Method callback + */ +t_uint32 cm_resolvSymbol( + void* context, + t_uint32 type, + t_dup_char symbolName, + char* reloc_addr) +{ + t_component_template *template = (t_component_template*)context; + t_component_instance* ee = cm_EEM_getExecutiveEngine(template->dspId)->instance; + int i, j; + + // Search if this method is provided by EE and resolve it directly + for(i = 0; i < ee->template->provideNumber; i++) + { + t_interface_provide* provide = &ee->template->provides[i]; + + for(j = 0; j < provide->interface->methodNumber; j++) + { + if(provide->interface->methodNames[j] == symbolName) + { + return provide->indexes[0][j].methodAddresses; // Here we assume no collection provided !! + } + } + } + + // Lookup if the method is statically required, ands delay relocation when bind occur + for(i = 0; i < template->requireNumber; i++) + { + if((template->requires[i].requireTypes & STATIC_REQUIRE) == 0) + continue; + + for(j = 0; j < template->requires[i].interface->methodNumber; j++) + { + if(template->requires[i].interface->methodNames[j] == symbolName) + { + t_function_relocation* delayedRelocation = (t_function_relocation*)OSAL_Alloc(sizeof(t_function_relocation)); + if(delayedRelocation == NULL) + return 0xFFFFFFFE; + + delayedRelocation->type = type; + delayedRelocation->symbol_name = cm_StringReference(symbolName); + delayedRelocation->reloc_addr = reloc_addr; + delayedRelocation->next = template->delayedRelocation; + template->delayedRelocation = delayedRelocation; + + return 0xFFFFFFFF; + } + } + } + + //Symbol not found + return 0x0; +} + +/* + * Template Management + */ +t_cm_error cm_loadComponent( + t_dup_char templateName, + t_cm_domain_id domainId, + t_elfdescription* elfhandle, + t_component_template **reftemplate) +{ + t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId); + t_cm_error error; + int i, j, k; + + /* + * Allocate new component template if first instance + */ + if(*reftemplate == NULL) + { + t_component_template *template; + + LOG_INTERNAL(1, "\n##### Load template %s on %s #####\n", templateName, cm_getDspName(coreId), 0, 0, 0, 0); + + /* + * Sanity check + */ + if(elfhandle->foundedTemplateName != templateName) + { + ERROR("CM_INVALID_ELF_FILE: template name %s != %s\n", templateName, elfhandle->foundedTemplateName, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; + } + + // Alloc & Reset variable in order to use unloadComponent either with partial constructed template + *reftemplate = template = (t_component_template*)OSAL_Alloc_Zero(sizeof(t_component_template)); + if(template == NULL) + return CM_NO_MORE_MEMORY; + template->name = cm_StringReference(elfhandle->foundedTemplateName); + + // Get information from elfhandle + template->descriptionAssociatedWithTemplate = elfhandle->temporaryDescription; + template->requireNumber = elfhandle->requireNumber; + template->requires = elfhandle->requires; + template->attributeNumber = elfhandle->attributeNumber; + template->attributes = elfhandle->attributes; + template->propertyNumber = elfhandle->propertyNumber; + template->properties = elfhandle->properties; + template->provideNumber = elfhandle->provideNumber; + template->provides = elfhandle->provides; + if(template->descriptionAssociatedWithTemplate) + { + elfhandle->requires = NULL; + elfhandle->attributes = NULL; + elfhandle->properties = NULL; + elfhandle->provides = NULL; + } + + // Compute simple information + template->numberOfInstance = 1; + template->dspId = coreId; + LOG_INTERNAL(3, "load<%x> = %s\n", (int)template, template->name, 0, 0, 0, 0); + switch(elfhandle->magicNumber) { + case MAGIC_COMPONENT: + template->classe = COMPONENT; + break; + case MAGIC_SINGLETON: + template->classe = SINGLETON; + break; + case MAGIC_FIRMWARE: + template->classe = FIRMWARE; + break; + } + template->minStackSize = elfhandle->minStackSize; + + /* + * Load shared memory from file + */ + // START(); + if((error = cm_ELF_LoadTemplate(domainId, elfhandle, template->memories)) != CM_OK) + goto out; + MMDSP_serializeMemories(elfhandle->instanceProperty, &template->codeMemory, &template->thisMemory); + // END("cm_ELF_LoadTemplate"); + + /* + * Copy LCC functions information + * Since MMDSP require Constructor & Destructor (for cache flush and debug purpose) to be called + * either if not provided by user for allowing defered breakpoint, we use Void method if not provided. + */ + template->LCCConstructAddress = MemoryToDspAdress(template, &elfhandle->memoryForConstruct); + template->LCCStartAddress = MemoryToDspAdress(template, &elfhandle->memoryForStart); + template->LCCStopAddress = MemoryToDspAdress(template, &elfhandle->memoryForStop); + template->LCCDestroyAddress = MemoryToDspAdress(template, &elfhandle->memoryForDestroy); + if(template->LCCConstructAddress == 0 && template->classe != FIRMWARE) + template->LCCConstructAddress = cm_EEM_getExecutiveEngine(coreId)->voidAddr; + + // Compute provide methodIndex + for(i = 0; i < template->provideNumber; i++) + { + for(j = 0; j < template->provides[i].collectionSize; j++) + { + for(k = 0; k < template->provides[i].interface->methodNumber; k++) + { + template->provides[i].indexes[j][k].methodAddresses = + MemoryToDspAdress(template, &template->provides[i].indexes[j][k].memory); + + LOG_INTERNAL(2, " [%d, %d] method '%s' @ %x\n", + j, k, template->provides[i].interface->methodNames[k], template->provides[i].indexes[j][k].methodAddresses, 0, 0); + } + } + } + + /* + * TODO + + if((error = elfhandle->errorOccured) != CM_OK) + goto out; + */ + + // START(); + if(template->classe != FIRMWARE) + { + if((error = cm_ELF_relocateSharedSegments( + template->memories, + elfhandle, + template)) != CM_OK) + goto out; + } + // END("cm_ELF_relocateSharedSegments"); + + cm_ELF_FlushTemplate(coreId, template->memories); + + templateAdd(template); + + return CM_OK; + out: + cm_unloadComponent(template); + return error; + } + else + { + (*reftemplate)->numberOfInstance++; + } + + return CM_OK; +} + +PUBLIC t_cm_error cm_unloadComponent( + t_component_template *template) +{ + /* + * Destroy template if last instance + */ + if(--template->numberOfInstance == 0) { + t_function_relocation* reloc; + + LOG_INTERNAL(3, "unload<%s>\n", template->name, 0, 0, 0, 0, 0); + + templateRemove(template); + + // Free delayedRelocation + reloc = template->delayedRelocation; + while(reloc != NULL) + { + t_function_relocation *tofree = reloc; + reloc = reloc->next; + cm_StringRelease(tofree->symbol_name); + OSAL_Free(tofree); + } + + if(template->descriptionAssociatedWithTemplate) + { + cm_ELF_ReleaseDescription( + template->requireNumber, template->requires, + template->attributeNumber, template->attributes, + template->propertyNumber, template->properties, + template->provideNumber, template->provides); + } + + // Free shared memories + cm_ELF_FreeTemplate(template->dspId, template->memories); + + cm_StringRelease(template->name); + + OSAL_Free(template); + } + + return CM_OK; +} + diff --git a/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration.h b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration.h new file mode 100644 index 00000000000..7156769bb2d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef __INC_CONFIGURATION_H_ +#define __INC_CONFIGURATION_H_ + +#include +#include +#include +#include + +/******************************************************************************/ +/************************ FUNCTIONS PROTOTYPES ********************************/ +/******************************************************************************/ + +PUBLIC t_cm_error cm_CFG_ConfigureMediaProcessorCore(t_nmf_core_id coreId, + t_nmf_executive_engine_id executiveEngineId, + t_nmf_semaphore_type_id semaphoreTypeId, t_uint8 nbYramBanks, + const t_cm_system_address *mediaProcessorMappingBaseAddr, + const t_cm_domain_id eeDomain, + t_dsp_allocator_desc* sdramCodeAllocId, + t_dsp_allocator_desc* sdramDataAllocId + ); + +PUBLIC t_cm_error cm_CFG_AddMpcSdramSegment(const t_nmf_memory_segment *pDesc, + const char *memoryname, t_dsp_allocator_desc **allocDesc); + +PUBLIC t_cm_error cm_CFG_CheckMpcStatus(t_nmf_core_id coreId); + +void cm_CFG_ReleaseMpc(t_nmf_core_id coreId); + +PUBLIC t_cm_error cm_CFG_GetRequiredExecutiveEngineComponentNames( + char fileList[][MAX_INTERFACE_TYPE_NAME_LENGTH], t_uint32 listSize); + +#endif /* __INC_CONFIGURATION_H_ */ diff --git a/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_status.h b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_status.h new file mode 100644 index 00000000000..0c75b9c49b0 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_status.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef __INC_CONFIGSTATUS_H_ +#define __INC_CONFIGSTATUS_H + +#include +#include + +/* + * Variable to active intensive check + * + * \ingroup CM_CONFIGURATION_API + */ +extern t_sint32 cmIntensiveCheckState; + +/* + * Variable to active trace level + * + * \ingroup CM_CONFIGURATION_API + */ +extern t_sint32 cm_debug_level; + +/* + * Variable to active error break + * + * \ingroup CM_CONFIGURATION_API + */ +extern t_sint32 cm_error_break; + +/* + * Variable to activate Ulp + * + * \ingroup CM_CONFIGURATION_API + */ +extern t_bool cmUlpEnable; + +extern t_dup_char anonymousDup, eventDup, skeletonDup, stubDup, traceDup; + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h new file mode 100644 index 00000000000..abfe452cf78 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Configuration Component Manager API type. + */ +#ifndef CONFIGURATION_TYPE_H +#define CONFIGURATION_TYPE_H + +#include + +/*! + * @defgroup t_cm_cmd_id t_cm_cmd_id + * \brief Definition of the command ID + * \ingroup CM_CONFIGURATION_API + * + * CM_CMD_XXX designates the command ID used by the \ref CM_SetMode routine. + * + * \remarks Other command IDs are not yet implemented. + */ + +typedef t_uint32 t_cm_cmd_id; //!< Fake enumeration type \ingroup t_cm_cmd_id +#define CM_CMD_SYNC ((t_cm_cmd_id)0x01) //!< Synchronize on-going operations (no parameter) \ingroup t_cm_cmd_id + +#define CM_CMD_WARM_RESET ((t_cm_cmd_id)0x02) //!< Reset a part of the CM-engine (parameter indicates the part which must be reseted) \ingroup t_cm_cmd_id + +#define CM_CMD_PWR_MGR ((t_cm_cmd_id)0x10) //!< Enable/Disable the internal power management module (0=Disable, 1=Enable) \ingroup t_cm_cmd_id + +#define CM_CMD_DBG_MODE ((t_cm_cmd_id)0x40) //!< Enable/Disable DEBUG mode, Pwr Mgr is also disabled (0=Disable, 1=Enable) \ingroup t_cm_cmd_id + +#define CM_CMD_TRACE_ON ((t_cm_cmd_id)0x41) //!< Enable STM/XTI tracing and force network resetting and dumping \note Since MPC trace will be usable, you can enable them if not \ingroup t_cm_cmd_id +#define CM_CMD_TRACE_OFF ((t_cm_cmd_id)0x42) //!< Disable STM/XTI tracing \note Since MPC trace will not be usable, you can also disable them \ingroup t_cm_cmd_id + +#define CM_CMD_MPC_TRACE_ON ((t_cm_cmd_id)0x50) //!< Enable MPC STM/XTI tracing (param == coreId). \note This command is not execute if execution engine not started on the coreId \ingroup t_cm_cmd_id +#define CM_CMD_MPC_TRACE_OFF ((t_cm_cmd_id)0x51) //!< Disable MPC STM/XTI tracing (param == coreId) This is the default configuration. \note This command is not execute if execution engine not started on the coreId \ingroup t_cm_cmd_id + +#define CM_CMD_MPC_PRINT_OFF ((t_cm_cmd_id)0x52) //!< Set to OFF the level of MPC traces (param == coreId) \note This command is not execute if execution engine not started on the coreId \ingroup t_cm_cmd_id +#define CM_CMD_MPC_PRINT_ERROR ((t_cm_cmd_id)0x53) //!< Set to ERROR the level of MPC traces param == coreId) \note This command is not execute if execution engine not started on the coreId \ingroup t_cm_cmd_id +#define CM_CMD_MPC_PRINT_WARNING ((t_cm_cmd_id)0x54) //!< Set to WARNING the level of MPC traces param == coreId) \note This command is not execute if execution engine not started on the coreId \ingroup t_cm_cmd_id +#define CM_CMD_MPC_PRINT_INFO ((t_cm_cmd_id)0x55) //!< Set to INFO the level of MPC traces (param == coreId) \note This command is not execute if execution engine not started on the coreId This is the default configuration. \ingroup t_cm_cmd_id +#define CM_CMD_MPC_PRINT_VERBOSE ((t_cm_cmd_id)0x56) //!< Set to VERBOSE the level of MPC traces param == coreId) \note This command is not execute if execution engine not started on the coreId \ingroup t_cm_cmd_id + +/*! + * \brief Define the level of internal CM log traces + * + * Define the level of internal CM log traces (-1 to 3) + * -# -1 all internal LOG/ERROR traces are disabled + * -# 0 all internal LOG traces are disabled (default/reset value) + * -# 1, 2, 3 Most and most + * + * \ingroup t_cm_cmd_id + */ +#define CM_CMD_TRACE_LEVEL ((t_cm_cmd_id)0x80) + +/*! + * \brief Enable/Disable intensive internal check + * + * Enable/Disable intensive internal check (0=Disable, 1=Enable): + * - Component handle checking + * + * Must be used during the integration phase (additional process is time consuming). + * + * \ingroup t_cm_cmd_id + */ +#define CM_CMD_INTENSIVE_CHECK ((t_cm_cmd_id)0x100) + +/*! + * \brief Enable/Disable ulp mode + * + * Enable/Disable Ultra Low Power mode. + * + * \ingroup t_cm_cmd_id + */ +#define CM_CMD_ULP_MODE_ON ((t_cm_cmd_id)0x111) //!< Enable ULP mode \ingroup t_cm_cmd_id +#define CM_CMD_ULP_MODE_OFF ((t_cm_cmd_id)0x110) //!< Deprecated (must be removed in 2.10) !!! + +#endif /* CONFIGURATION_TYPE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration.c b/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration.c new file mode 100644 index 00000000000..f3242af5da8 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +t_sint32 cmIntensiveCheckState = 0; +t_sint32 cm_debug_level = 1; +t_sint32 cm_error_break = 0; +t_bool cmUlpEnable = FALSE; + + +#define MAX_EE_NAME_LENGTH 32 +typedef struct { + char eeName[MAX_EE_NAME_LENGTH]; + t_nmf_executive_engine_id executiveEngineId; + t_uint32 EEmemoryCount; +} t_cfg_mpc_desc; + +static t_cfg_mpc_desc cfgMpcDescArray[NB_CORE_IDS]; + +PUBLIC t_cm_error cm_CFG_ConfigureMediaProcessorCore( + t_nmf_core_id coreId, + t_nmf_executive_engine_id executiveEngineId, + t_nmf_semaphore_type_id semaphoreTypeId, + t_uint8 nbYramBanks, + const t_cm_system_address *mediaProcessorMappingBaseAddr, + const t_cm_domain_id eeDomain, + t_dsp_allocator_desc *sdramCodeAllocDesc, + t_dsp_allocator_desc *sdramDataAllocDesc) +{ + /* Process requested configuration (save it) */ + cfgMpcDescArray[coreId].EEmemoryCount = 0; + cfgMpcDescArray[coreId].executiveEngineId = executiveEngineId; + /* Build Executive Engine Name */ + switch(executiveEngineId) + { + case SYNCHRONOUS_EXECUTIVE_ENGINE: + cm_StringCopy(cfgMpcDescArray[coreId].eeName, "synchronous_", MAX_EE_NAME_LENGTH); + break; + case HYBRID_EXECUTIVE_ENGINE: + cm_StringCopy(cfgMpcDescArray[coreId].eeName, "hybrid_", MAX_EE_NAME_LENGTH); + break; + } + + switch(semaphoreTypeId) + { + case LOCAL_SEMAPHORES: + cm_StringConcatenate(cfgMpcDescArray[coreId].eeName, "lsem", MAX_EE_NAME_LENGTH); + break; + case SYSTEM_SEMAPHORES: + cm_StringConcatenate(cfgMpcDescArray[coreId].eeName, "hsem", MAX_EE_NAME_LENGTH); + break; + } + + cm_SEM_InitMpc(coreId, semaphoreTypeId); + + return cm_DSP_Add(coreId, nbYramBanks, mediaProcessorMappingBaseAddr, eeDomain, sdramCodeAllocDesc, sdramDataAllocDesc); +} + +// TODO JPF: Move in dsp.c +PUBLIC t_cm_error cm_CFG_AddMpcSdramSegment(const t_nmf_memory_segment *pDesc, const char* memoryname, t_dsp_allocator_desc **allocDesc) +{ + t_dsp_allocator_desc *desc; + if ( (pDesc == NULL) || + ((pDesc->systemAddr.logical & CM_MM_ALIGN_64BYTES) != 0) ) + return CM_INVALID_PARAMETER; + + //TODO, juraj, the right place and way to do this? + desc = (t_dsp_allocator_desc*)OSAL_Alloc(sizeof (t_dsp_allocator_desc)); + if (desc == 0) + return CM_NO_MORE_MEMORY; + + desc->allocDesc = cm_MM_CreateAllocator(pDesc->size, 0, memoryname); + if (desc->allocDesc == 0) { + OSAL_Free(desc); + return CM_NO_MORE_MEMORY; + } + desc->baseAddress = pDesc->systemAddr; + desc->referenceCounter = 0; + + *allocDesc = desc; + + return CM_OK; +} + +PUBLIC t_cm_error cm_CFG_CheckMpcStatus(t_nmf_core_id coreId) +{ + t_cm_error error; + + if (cm_DSP_GetState(coreId)->state == MPC_STATE_BOOTABLE) + { + /* Allocate coms fifo for a given MPC */ + if ((error = cm_COM_AllocateMpc(coreId)) != CM_OK) + return error; + + /* Launch EE */ + if ((error = cm_EEM_Init(coreId, + cfgMpcDescArray[coreId].eeName, + cfgMpcDescArray[coreId].executiveEngineId)) != CM_OK) + { + cm_COM_FreeMpc(coreId); + return error; + } + + /* Initialize coms fifo for a given MPC */ + cm_COM_InitMpc(coreId); + + /* Initialisation of the dedicated communication channel for component initialization */ + if((error = cm_COMP_INIT_Init(coreId)) != CM_OK) + { + cm_EEM_Close(coreId); + cm_COM_FreeMpc(coreId); + return error; + } + + cfgMpcDescArray[coreId].EEmemoryCount = cm_PWR_GetMPCMemoryCount(coreId); + + if(cmUlpEnable) + { + // We have finish boot, allow MMDSP to go in auto idle + cm_EEM_AllowSleep(coreId); + } + } + + if (cm_DSP_GetState(coreId)->state != MPC_STATE_BOOTED) + return CM_MPC_NOT_INITIALIZED; + + return CM_OK; +} + +void cm_CFG_ReleaseMpc(t_nmf_core_id coreId) +{ + t_uint32 memoryCount = cm_PWR_GetMPCMemoryCount(coreId); + + // If No more memory and no more component (to avoid switch off in case of component using no memory) + if( + cm_PWR_GetMode() == NORMAL_PWR_MODE && + memoryCount != 0 /* Just to see if there is something */ && + memoryCount == cfgMpcDescArray[coreId].EEmemoryCount && + cm_isComponentOnCoreId(coreId) == FALSE) + { + LOG_INTERNAL(1, "\n##### Shutdown %s #####\n", cm_getDspName(coreId), 0, 0, 0, 0, 0); + + (void)cm_EEM_ForceWakeup(coreId); + + /* remove ee from load map here */ + cm_COMP_INIT_Close(coreId); + cm_EEM_Close(coreId); + cm_COM_FreeMpc(coreId); + + cfgMpcDescArray[coreId].EEmemoryCount = 0; // For debug purpose + } +} + +/****************************************************************************/ +/* NAME: cm_CFG_GetRequiredExecutiveEngineComponentNames( */ +/* char *fileList[], */ +/* t_uint32 *listSize */ +/* ) */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: retrieves the names of the required Executive Engine */ +/* component(s) to load. */ +/****************************************************************************/ +PUBLIC t_cm_error cm_CFG_GetRequiredExecutiveEngineComponentNames( + char fileList[][MAX_INTERFACE_TYPE_NAME_LENGTH], + t_uint32 listSize) +{ + t_nmf_core_id coreId; + t_uint32 nb=0; + + for (coreId = ARM_CORE_ID; coreId <= LAST_CORE_ID; coreId++) + { + if ((cm_DSP_GetState(coreId)->state == MPC_STATE_BOOTABLE) + && (cm_REP_lookupComponent(cfgMpcDescArray[coreId].eeName, NULL) != CM_OK)) + { + /* Check if we didn't already register this name in the list */ + int j, present=0; + for (j=0; j= listSize) + return CM_NO_MORE_MEMORY; + cm_StringCopy(fileList[nb], cfgMpcDescArray[coreId].eeName, MAX_EE_NAME_LENGTH); + nb++; + } + } + return CM_OK; +} + diff --git a/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration_wrapper.c b/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration_wrapper.c new file mode 100644 index 00000000000..34789752b7d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration_wrapper.c @@ -0,0 +1,301 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +t_dup_char anonymousDup, eventDup, skeletonDup, stubDup, traceDup; + +PUBLIC t_cm_error CM_ENGINE_Init( + const t_nmf_hw_mapping_desc *pNmfHwMappingDesc, + const t_nmf_config_desc *pNmfConfigDesc + ) +{ + t_cm_error error; + + // The purpose of that is just to not free/unfree some String frequently used + anonymousDup = cm_StringDuplicate("anonymous"); + eventDup = cm_StringDuplicate("event"); + skeletonDup = cm_StringDuplicate("skeleton"); + stubDup = cm_StringDuplicate("stub"); + traceDup = cm_StringDuplicate("trace"); + + if (( + error = cm_OSAL_Init() + ) != CM_OK) { return error; } + + if (( + error = cm_COMP_Init() + ) != CM_OK) { return error; } + + if (( + error = cm_PWR_Init() + ) != CM_OK) { return error; } + + cm_TRC_traceReset(); + + if (( + error = cm_DM_Init() + ) != CM_OK) {return error; } + + if (( + error = cm_SEM_Init(&pNmfHwMappingDesc->hwSemaphoresMappingBaseAddr) + ) != CM_OK) { return error; } + + if ((error = cm_COM_Init(pNmfConfigDesc->comsLocation)) != CM_OK) + return error; + + cm_DSP_Init(&pNmfHwMappingDesc->esramDesc); + + return CM_OK; +} + +PUBLIC void CM_ENGINE_Destroy(void) +{ + t_component_instance *instance; + t_cm_error error; + t_uint32 i; + + /* PP: Well, on Linux (and probably on Symbian too), this is called when driver is removed + * => the module (driver) can't be removed if there are some pending clients + * => all remaining components should have been destroyed in CM_ENGINE_FlushClient() + * => So, if we found some components here, we are in BIG trouble ... + */ + /* First, stop all remaining components */ + for (i=0; idomainId].client; + LOG_INTERNAL(0, "Found a remaining component %s (%s) when destroying the CM !!!\n", instance->pathname, instance->template->name, 0, 0, 0, 0); + if (/* skip EE */ + (instance->template->classe == FIRMWARE) || + /* Skip all binding components */ + (cm_StringCompare(instance->template->name, "_ev.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_st.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_sk.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_tr.", 4) == 0)) + continue; + + /* + * Special code for SINGLETON handling + */ + if(instance->template->classe == SINGLETON) + { + struct t_client_of_singleton* cl = instance->clientOfSingleton; + + clientId = instance->clientOfSingleton->clientId; + for( ; cl != NULL ; cl = cl->next) + { + if(cl == instance->clientOfSingleton) + { + cl->numberOfStart = 1; // == 1 since it will go to 0 in cm_stopComponent + cl->numberOfInstance = 1; // == 1 since it will go to 0 in cm_destroyInstanceForClient + } + else + { + cl->numberOfStart = 0; + cl->numberOfInstance = 0; + } + cl->numberOfBind = 0; + } + } + + // Stop the component + error = cm_stopComponent(instance, clientId); + if (error != CM_OK && error != CM_COMPONENT_NOT_STARTED) + LOG_INTERNAL(0, "Error stopping component %s/%x (%s, error=%d, client=%u)\n", instance->pathname, instance, instance->template->name, error, clientId, 0); + + // Destroy dependencies + cm_destroyRequireInterface(instance, clientId); + } + + /* Destroy all remaining components */ + for (i=0; idomainId].client; + + if (/* skip EE */ + (instance->template->classe == FIRMWARE) || + /* Skip all binding components */ + (cm_StringCompare(instance->template->name, "_ev.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_st.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_sk.", 4) == 0) || + (cm_StringCompare(instance->template->name, "_tr.", 4) == 0)) { + continue; + } + + if(instance->template->classe == SINGLETON) + { + clientId = instance->clientOfSingleton->clientId; + } + + // Destroy the component + error = cm_destroyInstanceForClient(instance, DESTROY_WITHOUT_CHECK, clientId); + + if (error != CM_OK) + { + /* FIXME : add component name instance in log message but need to make a copy before cm_flushComponent() + * because it's no more available after. + */ + LOG_INTERNAL(0, "Error flushing component (error=%d, client=%u)\n", error, clientId, 0, 0, 0, 0); + } + } + + /* This will power off all ressources and destroy EE */ + cm_PWR_SetMode(NORMAL_PWR_MODE); + cm_DSP_Destroy(); + cm_DM_Destroy(); + /* Nothing to do about SEM */ + //cm_MM_Destroy(); + cm_REP_Destroy(); + cm_COMP_Destroy(); + cm_OSAL_Destroy(); + + cm_StringRelease(traceDup); + cm_StringRelease(stubDup); + cm_StringRelease(skeletonDup); + cm_StringRelease(eventDup); + cm_StringRelease(anonymousDup); +} + +PUBLIC t_cm_error CM_ENGINE_ConfigureMediaProcessorCore( + t_nmf_core_id coreId, + t_nmf_executive_engine_id executiveEngineId, + t_nmf_semaphore_type_id semaphoreTypeId, + t_uint8 nbYramBanks, + const t_cm_system_address *mediaProcessorMappingBaseAddr, + const t_cm_domain_id eeDomain, + const t_cfg_allocator_id sdramCodeAllocId, + const t_cfg_allocator_id sdramDataAllocId + ) +{ + return cm_CFG_ConfigureMediaProcessorCore( + coreId, + executiveEngineId, + semaphoreTypeId, + nbYramBanks, + mediaProcessorMappingBaseAddr, + eeDomain, + (t_dsp_allocator_desc*)sdramCodeAllocId, + (t_dsp_allocator_desc*)sdramDataAllocId + ); +} + +PUBLIC t_cm_error CM_ENGINE_AddMpcSdramSegment( + const t_nmf_memory_segment *pDesc, + t_cfg_allocator_id *id, + const char *memoryname + ) +{ + return cm_CFG_AddMpcSdramSegment(pDesc, memoryname == NULL ? "" : memoryname, (t_dsp_allocator_desc**)id); +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_SetMode(t_cm_cmd_id aCmdID, t_sint32 aParam) +{ + t_cm_error error = CM_OK; + int i; + + OSAL_LOCK_API(); + + switch(aCmdID) { + case CM_CMD_DBG_MODE: + cm_PWR_SetMode(( aParam==1 ) ? DISABLE_PWR_MODE : NORMAL_PWR_MODE); + switch(cm_PWR_GetMode()) + { + case NORMAL_PWR_MODE: + // Release the MPC (which will switch it off if no more used) + for (i=FIRST_MPC_ID; i for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief DSP abstraction layer + * + * \defgroup DSP_INTERNAL Private DSP Abstraction Layer API. + * + */ +#ifndef __INC_CM_DSP_H +#define __INC_CM_DSP_H + +#include +#include +#include +#include +#include +#include + + +#define SxA_NB_BLOCK_RAM 8 /*32kworks (24-bit) */ + +#define SxA_LOCKED_WAY 1 + +/* + * Type defintion to handle dsp offset in word + */ +typedef t_uint32 t_dsp_offset; + +typedef t_uint32 t_dsp_address; + +typedef enum { + DSP2ARM_IRQ_0, + DSP2ARM_IRQ_1 +} t_mpc2host_irq_num; + +typedef enum { + ARM2DSP_IRQ_0, + ARM2DSP_IRQ_1, + ARM2DSP_IRQ_2, + ARM2DSP_IRQ_3 +} t_host2mpc_irq_num; + +typedef enum { + INTERNAL_XRAM24 = 0, /* 24-bit XRAM */ + INTERNAL_XRAM16 = 1, /* 16-bit XRAM */ + INTERNAL_YRAM24 = 2, /* 24-bit YRAM */ + INTERNAL_YRAM16 = 3, /* 16-bit YRAM */ + SDRAM_EXT24 = 4, /* 24-bit external "X" memory */ + SDRAM_EXT16 = 5, /* 16-bit external "X" memory */ + ESRAM_EXT24 = 6, /* ESRAM24 */ + ESRAM_EXT16 = 7, /* ESRAM16 */ + SDRAM_CODE = 8, /* Program memory */ + ESRAM_CODE = 9, /* ESRAM code */ + LOCKED_CODE = 10, /* For way locking */ + NB_DSP_MEMORY_TYPE, + DEFAULT_DSP_MEM_TYPE = MASK_ALL16 +} t_dsp_memory_type_id; + +typedef struct { + t_cm_allocator_desc *allocDesc; + t_cm_system_address baseAddress; + t_uint32 referenceCounter; +} t_dsp_allocator_desc; + +typedef struct { + t_cm_system_address base; + t_uint32 size; +} t_dsp_segment; + +typedef enum { +#if defined(__STN_8500) && (__STN_8500 > 10) + SDRAM_CODE_EE, + SDRAM_CODE_USER, + SDRAM_DATA_EE, + SDRAM_DATA_USER, + NB_MIGRATION_SEGMENT, + ESRAM_CODE_EE = NB_MIGRATION_SEGMENT, + ESRAM_CODE_USER, + ESRAM_DATA_EE, + ESRAM_DATA_USER, +#else + SDRAM_CODE_EE, + SDRAM_DATA_EE, + ESRAM_CODE_EE, + ESRAM_DATA_EE, +#endif + NB_DSP_SEGMENT_TYPE +} t_dsp_segment_type; + +typedef struct { + t_dsp_segment_type segmentType; + t_uint32 baseOffset; +} t_dsp_address_info; + +typedef enum { + MPC_STATE_UNCONFIGURED, + MPC_STATE_BOOTABLE, + MPC_STATE_BOOTED, + MPC_STATE_PANIC, +} t_dsp_state; + +typedef struct { + t_dsp_state state; + t_uint8 nbYramBank; + t_cm_domain_id domainEE; + t_dsp_allocator_desc *allocator[NB_DSP_MEMORY_TYPE]; + t_dsp_segment segments[NB_DSP_SEGMENT_TYPE]; + t_uint32 yram_offset; + t_uint32 yram_size; + t_uint32 locked_offset; + t_uint32 locked_size; +} t_dsp_desc; + +typedef struct { + t_nmf_core_id coreId; + t_dsp_memory_type_id memType; // Index in MPC desc allocator + t_cm_allocator_desc *alloc; +} t_dsp_chunk_info; + +PUBLIC const t_dsp_desc* cm_DSP_GetState(t_nmf_core_id coreId); +PUBLIC void cm_DSP_SetStatePanic(t_nmf_core_id coreId); + +PUBLIC void cm_DSP_Init(const t_nmf_memory_segment *pEsramDesc); +PUBLIC void cm_DSP_Destroy(void); + +/*! + * \brief Initialize the memory segments management of a given MPC + * + * \param[in] coreId Identifier of the DSP to initialize + * \param[in] pDspMapDesc DSP mapping into host space + * \param[in] memConf configuration of the DSP memories (standalone or shared) + * + * \retval t_cm_error + * + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_error cm_DSP_Add(t_nmf_core_id coreId, + t_uint8 nbYramBanks, + const t_cm_system_address *pDspMapDesc, + const t_cm_domain_id eeDomain, + t_dsp_allocator_desc *sdramCodeAllocDesc, + t_dsp_allocator_desc *sdramDataAllocDesc); + + + +/*! + * \brief Configure a given Media Processor Core + * + * This routine programs the configuration (caches, ahb wrapper, ...) registers of a given MPC. + * + * \param[in] coreId Identifier of the DSP to initialize + * + * \retval t_cm_error + * + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_error cm_DSP_Boot(t_nmf_core_id coreId); + +/*! + * \brief Boot a given DSP + * + * This routine allows after having initialized and loaded the EE into a given DSP to start it (boot it) + * + * \param[in] coreId identifier of the DSP to boot + * \param[in] panicReasonOffset offset of panic reason which will pass to NONE_PANIC when DSP booted. + * + * \retval t_cm_error + * + * \ingroup DSP_INTERNAL + */ +PUBLIC void cm_DSP_ConfigureAfterBoot(t_nmf_core_id coreId); + +PUBLIC void cm_DSP_Start(t_nmf_core_id coreId); + +PUBLIC void cm_DSP_Stop(t_nmf_core_id coreId); + +/*! + * \brief Shutdown a given DSP + * + * This routine allows to stop and shutdown a given DSP + * + * \param[in] coreId identifier of the DSP to shutdown + * + * \retval t_cm_error + * + * \ingroup DSP_INTERNAL + */ +PUBLIC void cm_DSP_Shutdown(t_nmf_core_id coreId); + +PUBLIC t_uint32 cm_DSP_ReadXRamWord(t_nmf_core_id coreId, t_uint32 dspOffset); +PUBLIC void cm_DSP_WriteXRamWord(t_nmf_core_id coreId, t_uint32 dspOffset, t_uint32 value); + +/*! + * \brief Convert a Dsp address (offset inside a given DSP memory segment) into the host address (logical) + * + * \param[in] coreId identifier of the given DSP + * \param[in] dspAddress dsp address to be converted + * \param[in] memType memory type identifier + * + * \retval t_cm_logical_address + * + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_logical_address cm_DSP_ConvertDspAddressToHostLogicalAddress(t_nmf_core_id coreId, t_shared_addr dspAddress); + +/*! + * \brief Acknowledge the local interrupt of a given DSP (when not using HW semaphore mechanisms) + * + * \param[in] coreId identifier of the given DSP + * \param[in] irqNum irq identifier + * + * \retval void + * + * \ingroup DSP_INTERNAL + */ +PUBLIC void cm_DSP_AcknowledgeDspIrq(t_nmf_core_id coreId, t_mpc2host_irq_num irqNum); + + +/* + * Memory Management API routines + */ + +/*! + * \brief Retrieve DSP information for a memory chunk. + * + * This function retrieves information stored in user-data of the allocated chunk. + * See also \ref{t_dsp_chunk_info}. + * + * \param[in] memHandle Handle to the allocated chunk. + * \param[out] info Dsp information structure. + * + * \ingroup DSP_INTERNAL + */ +PUBLIC void cm_DSP_GetDspChunkInfo(t_memory_handle memHandle, t_dsp_chunk_info *info); + +/*! + * \brief Get memory allocator for a given memory type on a DSP. + * + * \param[in] coreId Dsp identifier. + * \param[in] memType Memory type identifier. + * + * \retval reference to the allocator descriptor (or null) + * + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_allocator_desc* cm_DSP_GetAllocator(t_nmf_core_id coreId, t_dsp_memory_type_id memType); + +/*! + * \brief Get DSP internal memory (TCM) information for allocation. + * + * For DSP-internal memories (TCMX, Y 16/24), return the offset and size of the allocation zone (for domain + * mechanism) and the allocation memory type. + * + * \param[in] coreId Dsp identifier. + * \param[in] memType Memory type identifier. + * \param[out] mem_info Memory information structure. + * + * \retval CM_OK + * + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_error cm_DSP_GetInternalMemoriesInfo(t_cm_domain_id domainId, t_dsp_memory_type_id memType, + t_uint32 *offset, t_uint32 *size); + + +/*! + * \brief Convert word size to byte size. + * + * \param[in] memType Memory type identifier. + * \param[in] wordSize Word size to be converted. + * + * \retval Byte size. + * + * \ingroup DSP_INTERNAL + */ +PUBLIC t_uint32 cm_DSP_ConvertSize(t_dsp_memory_type_id memType, t_uint32 wordSize); + +/*! + * \brief Provide the Memory status of a given memory type for a given DSP + * + * \param[in] coreId dsp identifier. + * \param[in] memType Type of memory. + * \param[out] pStatus requested memory status + * + * \retval t_cm_error + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_error cm_DSP_GetAllocatorStatus(t_nmf_core_id coreId, t_dsp_memory_type_id memType, t_uint32 offset, t_uint32 size, t_cm_allocator_status *pStatus); + +/*! + * \brief Provide DSP memory host shared address + * + * \param[in] memHandle Allocated block handle + * \param[out] pAddr Returned system address. + * + * \retval t_cm_error + * \ingroup DSP_INTERNAL + */ +PUBLIC void cm_DSP_GetHostSystemAddress( t_memory_handle memHandle, t_cm_system_address *pAddr); + +/*! + * \brief Get physical address of a memory chunk. + * + * \param[in] memHandle Memory handle. + * + * \retval Physical address. + * + * \ingroup DSP_INTERNAL + */ +PUBLIC t_physical_address cm_DSP_GetPhysicalAdress(t_memory_handle memHandle); + +/*! + * \brief Return Logical Address of an allocated memory chunk. + * + * \param[in] memHandle Allocated chunk handle + * \retval t_cm_error + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_logical_address cm_DSP_GetHostLogicalAddress(t_memory_handle memHandle); + +/*! + * \brief Provide DSP memory DSP address (offset inside a given DSP memory segment) + * + * \param[in] memHandle Allocated block handle + * \param[out] dspAddress allocated block address seen by the given DSP + * + * \retval t_cm_error + * \ingroup DSP_INTERNAL + */ +PUBLIC void cm_DSP_GetDspAddress(t_memory_handle handle, t_uint32 *pDspAddress); + +/*! + * \brief Return the adress of the DSP base associated to the memory type. + * Caution, this information is valid only in normal state (not when migrated). + * + * \param[in] coreId DSP Identifier. + * \param[in] memType Type of memory. + * \param[out] pAddr Base address. + * + * \retval t_cm_error + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_error cm_DSP_GetDspBaseAddress(t_nmf_core_id coreId, t_dsp_memory_type_id memType, t_cm_system_address *pAddr); + +/*! + * \brief Return DSP memory handle offset (offset inside a given DSP memory) + * + * \param[in] coreId dsp identifier. + * \param[in] memType Type of memory. + * \param[in] memHandle Allocated block handle + * + * \retval t_uint32: Offset of memory handle inside memory + * \ingroup DSP_INTERNAL + */ +PUBLIC t_uint32 cm_DSP_GetDspMemoryHandleOffset( + t_nmf_core_id coreId, + t_dsp_memory_type_id dspMemType, + t_memory_handle memHandle); + +/*! + * \brief Provide DSP memory handle size + * + * \param[in] memHandle Allocated block handle + * \param[out] pDspSize Size of the given memory handle + + * + * \retval t_cm_error + * \ingroup DSP_INTERNAL + */ +PUBLIC void cm_DSP_GetDspMemoryHandleSize(t_memory_handle memHandle, t_uint32 *pDspSize); + +/*! + * \brief Resize xram allocator to reserve spave for stack. + * + * \param[in] coreId dsp identifier. + * \param[in] newStackSize New required stack size. + + * + * \retval t_cm_error + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_error cm_DSP_setStackSize(t_nmf_core_id coreId, t_uint32 newStackSize); + +/*! + * \brief Allow to know if nbYramBanks parameter is valid for coreId. This api is need since use of nbYramBanks + * is deferred. + * + * \param[in] coreId dsp identifier. + * \param[in] nbYramBanks number of yramBanks to use. + * + * \retval t_cm_error + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_error cm_DSP_IsNbYramBanksValid(t_nmf_core_id coreId, t_uint8 nbYramBanks); + +/*! + * \brief Allow to know stack base address according to coreId and nbYramBanks use. + * + * \param[in] coreId dsp identifier. + * \param[in] nbYramBanks number of yramBanks to use. + * + * \retval t_uint32 return stack address + * \ingroup DSP_INTERNAL + */ +PUBLIC t_uint32 cm_DSP_getStackAddr(t_nmf_core_id coreId); + +/*! + * \brief For a give dsp adress return the offset from the hardware base that the adress is relative to. + * + * \param[in] coreId DSP identifier. + * \param[in] adr DSP address. + * \param[out] info Info structure containing (hw base id, offset) + * + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_error cm_DSP_GetDspDataAddressInfo(t_nmf_core_id coreId, t_uint32 adr, t_dsp_address_info *info); + +/*! + * \brief Modify the mapping of a code hardware base. Used for memory migration. + * + * The function calculates the new hardware base so that in the DSP address-space, + * the source address will be mapped to the destination address. + * + * \param[in] coreId DSP Identifier. + * \param[in] hwSegment Identifier of the hardware segment (thus hardware base). + * \param[in] src Source address + * \param[in] dst Destination address + * + * \retval t_cm_error + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_error cm_DSP_updateCodeBase(t_nmf_core_id coreId, t_dsp_segment_type hwSegment, t_cm_system_address src, t_cm_system_address dst); + +/*! + * \brief Modify the mapping of a data hardware base. Used for memory migration. + * + * The function calculates the new hardware base so that in the DSP address-space, + * the source address will be mapped to the destination address. + * + * \param[in] coreId DSP Identifier. + * \param[in] hwSegment Identifier of the hardware segment (thus hardware base). + * \param[in] src Source address + * \param[in] dst Destination address + * + * \retval t_cm_error + * \ingroup DSP_INTERNAL + */ +PUBLIC t_cm_error cm_DSP_updateDataBase(t_nmf_core_id coreId, t_dsp_segment_type hwSegment, t_cm_system_address src, t_cm_system_address dst); + +#endif /* __INC_CM_DSP_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/dsp/inc/semaphores_dsp.h b/drivers/staging/nmf-cm/cm/engine/dsp/inc/semaphores_dsp.h new file mode 100644 index 00000000000..1bb1c34cced --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/dsp/inc/semaphores_dsp.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef __INC_CM_SEMAPHORES_DSP_H +#define __INC_CM_SEMAPHORES_DSP_H + +#include +#include + +PUBLIC void cm_DSP_SEM_Take(t_nmf_core_id coreId, t_semaphore_id semId); +PUBLIC void cm_DSP_SEM_Give(t_nmf_core_id coreId, t_semaphore_id semId); +PUBLIC void cm_DSP_SEM_GenerateIrq(t_nmf_core_id coreId, t_semaphore_id semId); +PUBLIC void cm_DSP_AssertDspIrq(t_nmf_core_id coreId, t_host2mpc_irq_num irqNum); + +PUBLIC void cm_DSP_AcknowledgeDspIrq(t_nmf_core_id coreId, t_mpc2host_irq_num irqNum); + +#endif /* __INC_CM_SEMAPHORES_DSP_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h b/drivers/staging/nmf-cm/cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h new file mode 100644 index 00000000000..0ddc71d2c4f --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h @@ -0,0 +1,959 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef __INC_MMDSP_HWP_H +#define __INC_MMDSP_HWP_H + +#include + +#define MMDSP_NB_BLOCK_RAM 8 +#define MMDSP_RAM_BLOCK_SIZE 4096 /* 0x1000 */ +#define MMDSP_NB_TIMER 3 +#define MMDSP_NB_BIT_SEM 8 +#define MMDSP_NB_DMA_IF 8 +#define MMDSP_NB_DMA_CTRL 4 +#define MMDSP_NB_ITREMAP_REG 32 + +#define MMDSP_INSTRUCTION_WORD_SIZE (sizeof(t_uint64)) +#define MMDSP_ICACHE_LINE_SIZE_IN_INST (4) +#define MMDSP_ICACHE_LINE_SIZE (MMDSP_ICACHE_LINE_SIZE_IN_INST * MMDSP_INSTRUCTION_WORD_SIZE) + +#define MMDSP_DATA_WORD_SIZE (3) +#define MMDSP_DATA_WORD_SIZE_IN_HOST_SPACE (sizeof(t_uint32)) +#define MMDSP_DATA_WORD_SIZE_IN_EXT24 (sizeof(t_uint32)) +#define MMDSP_DATA_WORD_SIZE_IN_EXT16 (sizeof(t_uint16)) +#define MMDSP_DCACHE_LINE_SIZE_IN_WORDS (8) +#define MMDSP_DCACHE_LINE_SIZE (MMDSP_DCACHE_LINE_SIZE_IN_WORDS * sizeof(t_uint32)) + +#define MMDSP_NB_IO 16 + +#define MMDSP_CODE_CACHE_WAY_SIZE 256 + +//#define MMDSP_ESRAM_DSP_BASE_ADDR 0xE0000 /* 64-bit words */ +//#define MMDSP_DATA24_DSP_BASE_ADDR 0x10000 +//#define MMDSP_DATA16_DSP_BASE_ADDR 0x800000 +//#define MMDSP_MMIO_DSP_BASE_ADDR 0xF80000 + +/* Specified according MMDSP & ELF convention */ +/* Note: Here we assume that ESRAM is less than 2MB */ +#define SDRAMTEXT_BASE_ADDR 0x00000000 +#define ESRAMTEXT_BASE_ADDR 0x000E0000 + +#define SDRAMMEM24_BASE_ADDR 0x00010000 +#define ESRAMMEM24_BASE_ADDR 0x00600000 /* ELF == 0x00400000 TODO: Update it in MMDSP ELF compiler */ +#define SDRAMMEM16_BASE_ADDR 0x00800000 +#define ESRAMMEM16_BASE_ADDR 0x00D80000 /* ELF == 0x00BC0000 TODO: Update it in MMDSP ELF compiler */ + +#define MMIO_BASE_ADDR 0x00F80000 + +/* + * Definition of indirect host registers + */ +#define IHOST_ICACHE_FLUSH_REG 0x0 +#define IHOST_ICACHE_FLUSH_CMD_ENABLE (t_uint64)MASK_BIT0 +#define IHOST_ICACHE_FLUSH_ALL_ENTRIES_CMD (t_uint64)0x0 +#if 0 +#define IHOST_ICACHE_INVALID_ALL_UNLOCKED_L2_LINES_CMD (t_uint64)0x8 +#define IHOST_ICACHE_INVALID_ALL_LOCKED_L2_LINES_CMD (t_uint64)0xA +#define IHOST_ICACHE_UNLOCK_ALL_LOCKED_L2_LINES_CMD (t_uint64)0xC +#define IHOST_ICACHE_LOCK_ALL_WAYS_LESSER_THAN_LOCK_V_CMD (t_uint64)0xE +#else +#define IHOST_ICACHE_INVALID_ALL_UNLOCKED_L2_LINES_CMD (t_uint64)0x10 +#define IHOST_ICACHE_INVALID_ALL_LOCKED_L2_LINES_CMD (t_uint64)0x12 +#define IHOST_ICACHE_UNLOCK_ALL_LOCKED_L2_LINES_CMD (t_uint64)0x14 +#define IHOST_ICACHE_LOCK_ALL_WAYS_LESSER_THAN_LOCK_V_CMD (t_uint64)0x16 +#define IHOST_ICACHE_FLUSH_BY_SERVICE (t_uint64)0x18 +#define IHOST_ICACHE_FLUSH_OUTSIDE_RANGE (t_uint64)0x1A +#endif + +#define IHOST_ICACHE_LOCK_V_REG 0x1 + +#define IHOST_ICACHE_MODE_REG 0x2 +#define IHOST_ICACHE_MODE_PERFMETER_ON (t_uint64)MASK_BIT0 +#define IHOST_ICACHE_MODE_PERFMETER_OFF (t_uint64)0x0 +#define IHOST_ICACHE_MODE_L2_CACHE_ON (t_uint64)MASK_BIT1 +#define IHOST_ICACHE_MODE_L2_CACHE_OFF (t_uint64)0x0 +#define IHOST_ICACHE_MODE_L1_CACHE_ON (t_uint64)MASK_BIT2 +#define IHOST_ICACHE_MODE_L1_CACHE_OFF (t_uint64)0x0 +#define IHOST_ICACHE_MODE_FILL_MODE_ON (t_uint64)MASK_BIT3 +#define IHOST_ICACHE_MODE_FILL_MODE_OFF (t_uint64)0x0 + +#define IHOST_CLEAR_PERFMETER_REG 0x3 +#define IHOST_CLEAR_PERFMETER_ON (t_uint64)0x1 +#define IHOST_CLEAR_PERFMETER_OFF (t_uint64)0x0 + +#define IHOST_PERF_HIT_STATUS_REG 0x4 + +#define IHOST_PERF_MISS_STATUS_REG 0x5 + +#define IHOST_FILL_START_WAY_REG 0x6 +#define IHOST_FILL_START_ADDR_VALUE_SHIFT 0U +#define IHOST_FILL_WAY_NUMBER_SHIFT 20U + +#define IHOST_PRG_BASE_ADDR_REG 0x7 +#define IHOST_PRG_BASE1_ADDR_SHIFT 0 +#define IHOST_PRG_BASE2_ADDR_SHIFT 32 + +#if defined(__STN_8500) && (__STN_8500>10) +#define IHOST_PRG_BASE_34_ADDR_REG 0x1A +#define IHOST_PRG_BASE3_ADDR_SHIFT 0 +#define IHOST_PRG_BASE4_ADDR_SHIFT 32 +#endif + +#if defined(__STN_8815) /* __STN_8815 */ +#define IHOST_PRG_AHB_CONF_REG 0x8 +#define IHOST_PRG_AHB_LOCKED_SHIFT 0U +#define IHOST_PRG_AHB_PROT_SHIFT 1U + +#define AHB_LOCKED_ON (t_uint64)1 +#define AHB_LOCKED_OFF (t_uint64)0 + +#define AHB_PROT_USER (t_uint64)0 +#define AHB_PROT_PRIVILEGED (t_uint64)MASK_BIT0 +#define AHB_PROT_NONBUFFERABLE (t_uint64)0 +#define AHB_PROT_BUFFERABLE (t_uint64)MASK_BIT1 +#define AHB_PROT_NONCACHEABLE (t_uint64)0 +#define AHB_PROT_CACHEABLE (t_uint64)MASK_BIT2 + + +#define IHOST_DATA_AHB_CONF_REG 0x9 +#define IHOST_DATA_AHB_LOCKED_SHIFT 0U +#define IHOST_DATA_AHB_PROT_SHIFT 1U +#else /* def __STN_8820 or __STN_8500 */ +#define IHOST_STBUS_ID_CONF_REG 0x8 +#define SAA_STBUS_ID 176 /* = 0xB0 */ +#define SVA_STBUS_ID 4 /* = 0x4 */ +#define SIA_STBUS_ID 180 /* = 0xB4 */ + +#define IHOST_STBUF_CONF_REG 0x9 /* RESERVED */ +#endif /* __STN_8820 or __STN_8500 */ + +#define IHOST_DATA_EXT_BUS_BASE_REG 0xA +#define IHOST_DATA_EXT_BUS_BASE_16_SHIFT 32ULL +#define IHOST_DATA_EXT_BUS_BASE_24_SHIFT 0ULL + +#define IHOST_EXT_MMIO_BASE_DATA_EXT_BUS_TOP_REG 0xB +#define IHOST_EXT_MMIO_DATA_EXT_BUS_TOP_SHIFT 0ULL +#define IHOST_EXT_MMIO_BASE_ADDR_SHIFT 32ULL + +#define IHOST_DATA_EXT_BUS_BASE2_REG 0xC +#define IHOST_DATA_EXT_BUS_BASE2_16_SHIFT 32ULL +#define IHOST_DATA_EXT_BUS_BASE2_24_SHIFT 0ULL + +#if defined(__STN_8500) && (__STN_8500>10) + +#define IHOST_DATA_EXT_BUS_BASE3_REG 0x1B +#define IHOST_DATA_EXT_BUS_BASE3_16_SHIFT 32ULL +#define IHOST_DATA_EXT_BUS_BASE3_24_SHIFT 0ULL + +#define IHOST_DATA_EXT_BUS_BASE4_REG 0x1C +#define IHOST_DATA_EXT_BUS_BASE4_16_SHIFT 32ULL +#define IHOST_DATA_EXT_BUS_BASE4_24_SHIFT 0ULL + +#endif + +#define IHOST_ICACHE_STATE_REG 0xD +#define IHOST_ICACHE_STATE_RESET 0x0 +#define IHOST_ICACHE_STATE_INITAGL2 0x1 +#define IHOST_ICACHE_STATE_READY_TO_START 0x2 +#define IHOST_ICACHE_STATE_WAIT_FOR_MISS 0x3 +#define IHOST_ICACHE_STATE_FILLDATARAM0 0x4 +#define IHOST_ICACHE_STATE_FILLDATARAM1 0x5 +#define IHOST_ICACHE_STATE_FILLDATARAM2 0x6 +#define IHOST_ICACHE_STATE_FILLDATARAM3 0x7 +#define IHOST_ICACHE_STATE_FLUSH 0x8 +#define IHOST_ICACHE_STATE_FILL_INIT 0x9 +#define IHOST_ICACHE_STATE_FILL_LOOP 0xA +#define IHOST_ICACHE_STATE_FILL_LOOP0 0xB +#define IHOST_ICACHE_STATE_FILL_LOOP1 0xC +#define IHOST_ICACHE_STATE_FILL_LOOP2 0xD +#define IHOST_ICACHE_STATE_FILL_LOOP3 0xE +#define IHOST_ICACHE_STATE_FILL_END 0xF +#define IHOST_ICACHE_STATE_SPECIFIC_FLUSH_R 0x10 +#define IHOST_ICACHE_STATE_SPECIFIC_FLUSH_W 0x11 +#define IHOST_ICACHE_STATE_SPECIFIC_FLUSH_END 0x12 +#define IHOST_ICACHE_STATE_OTHERS 0x1F + +#define IHOST_EN_EXT_BUS_TIMEOUT_REG 0xE +#define IHOST_TIMEOUT_ENABLE 1ULL +#define IHOST_TIMEOUT_DISABLE 0ULL + +#define IHOST_DATA2_1624_XA_BASE_REG 0xF +#define IHOST_DATA2_24_XA_BASE_SHIFT 0ULL +#define IHOST_DATA2_16_XA_BASE_SHIFT 32ULL +#if defined(__STN_8500) && (__STN_8500>10) +#define IHOST_DATA3_24_XA_BASE_SHIFT 8ULL +#define IHOST_DATA3_16_XA_BASE_SHIFT 40ULL +#define IHOST_DATA4_24_XA_BASE_SHIFT 16ULL +#define IHOST_DATA4_16_XA_BASE_SHIFT 48ULL +#endif + +#define IHOST_PERFMETERS_MODE_REG 0x10 + +#if defined(__STN_8815) /* __STN_8815 */ +#define IHOST_EXT_MMIO_AHB_CONF_REG 0x11 +#define IHOST_EXT_MMIO_AHB_LOCKED_SHIFT 0U +#define IHOST_EXT_MMIO_AHB_PROT_SHIFT 1U +#else /* def __STN_8820 or __STN_8500 */ +#define IHOST_EXT_MMIO_STBS_CONF_REG 0x11 /* RESERVED */ +#endif /* __STN_8820 or __STN_8500 */ + +#define IHOST_PRG_BASE_SEL_REG 0x12 +#define IHOST_PRG_BASE_SEL_OFF (t_uint64)0 +#define IHOST_PRG_BASE_SEL_ON (t_uint64)1 + +#define IHOST_PRG_BASE2_ACTIV_REG 0x13 +#define IHOST_PRG_BASE2_ACTIV_OFF (t_uint64)0 +#if defined(__STN_8500) && (__STN_8500>10) +/* TODO : for the moment just divide mmdsp in fix 4 spaces */ + #define IHOST_PRG_BASE2_ACTIV_ON (t_uint64)((((t_uint64)0xf0000>>10)<<48) | (((t_uint64)0xe0000>>10)<<32) | (((t_uint64)0x70000>>10)<<16) | 1) +#else + #define IHOST_PRG_BASE2_ACTIV_ON (t_uint64)1 +#endif + +#define IHOST_DATA_EXT_BUS_TOP_16_24_REG 0x14 +#define IHOST_DATA_EXT_BUS_TOP_24_SHIFT 0ULL +#define IHOST_DATA_EXT_BUS_TOP_16_SHIFT 32ULL + +#define IHOST_DATA_TOP_16_24_CHK_REG 0x16 +#define IHOST_DATA_TOP_16_24_CHK_OFF (t_uint64)0 +#define IHOST_DATA_TOP_16_24_CHK_ON (t_uint64)1 + +#define IHOST_EXT_BUS_TOP2_16_24_REG 0x15 +#define IHOST_DATA_EXT_BUS_TOP2_24_SHIFT 0ULL +#define IHOST_DATA_EXT_BUS_TOP2_16_SHIFT 32ULL + +#if defined(__STN_8500) && (__STN_8500>10) + +#define IHOST_EXT_BUS_TOP3_16_24_REG 0x1D +#define IHOST_DATA_EXT_BUS_TOP3_24_SHIFT 0ULL +#define IHOST_DATA_EXT_BUS_TOP3_16_SHIFT 32ULL + +#define IHOST_EXT_BUS_TOP4_16_24_REG 0x1E +#define IHOST_DATA_EXT_BUS_TOP4_24_SHIFT 0ULL +#define IHOST_DATA_EXT_BUS_TOP4_16_SHIFT 32ULL + +#endif + +#define IHOST_DATA_BASE2_ACTIV_REG 0x17 +#define IHOST_DATA_BASE2_ACTIV_OFF (t_uint64)0 +#define IHOST_DATA_BASE2_ACTIV_ON (t_uint64)1 + +#define IHOST_INST_BURST_SZ_REG 0x18 +#define IHOST_INST_BURST_SZ_ALWAYS_1_LINE (t_uint64)0x0 +#define IHOST_INST_BURST_SZ_ALWAYS_2_LINES (t_uint64)0x1 +#define IHOST_INST_BURST_SZ_AUTO (t_uint64)0x2 /* 2 lines for SDRAM [0, 0xE0000[, 1 line for ESRAM [0xE0000, 0xFFFFF] */ + +#define IHOST_ICACHE_END_CLEAR_REG 0x19 +#define IHOST_ICACHE_START_CLEAR_REG IHOST_FILL_START_WAY_REG + +/* + * Definition of value of the ucmd register + */ +#define MMDSP_UCMD_WRITE 0 +#define MMDSP_UCMD_READ 4 +#define MMDSP_UCMD_CTRL_STATUS_ACCESS 0x10 // (MASK_BIT4 | !MASK_BIT3 | !MASK_BIT0) +#define MMDSP_UCMD_DECREMENT_ADDR MASK_BIT5 +#define MMDSP_UCMD_INCREMENT_ADDR MASK_BIT1 + +/* + * Definition of value of the ubkcmd register + */ +#define MMDSP_UBKCMD_EXT_CODE_MEM_ACCESS_ENABLE MASK_BIT3 +#define MMDSP_UBKCMD_EXT_CODE_MEM_ACCESS_DISABLE 0 + +/* + * Definition of value of the clockcmd register + */ +#define MMDSP_CLOCKCMD_STOP_CLOCK MASK_BIT0 +#define MMDSP_CLOCKCMD_START_CLOCK 0 + +/* + * Definition of macros used to access indirect addressed host register + */ +#define WRITE_INDIRECT_HOST_REG(pRegs, addr, value64) \ +{ \ + (pRegs)->host_reg.emul_uaddrl = addr; \ + (pRegs)->host_reg.emul_uaddrm = 0; \ + (pRegs)->host_reg.emul_uaddrh = 0; \ + (pRegs)->host_reg.emul_udata[0] = ((value64 >> 0ULL) & MASK_BYTE0); \ + (pRegs)->host_reg.emul_udata[1] = ((value64 >> 8ULL) & MASK_BYTE0); \ + (pRegs)->host_reg.emul_udata[2] = ((value64 >> 16ULL) & MASK_BYTE0); \ + (pRegs)->host_reg.emul_udata[3] = ((value64 >> 24ULL) & MASK_BYTE0); \ + (pRegs)->host_reg.emul_udata[4] = ((value64 >> 32ULL) & MASK_BYTE0); \ + (pRegs)->host_reg.emul_udata[5] = ((value64 >> 40ULL) & MASK_BYTE0); \ + (pRegs)->host_reg.emul_udata[6] = ((value64 >> 48ULL) & MASK_BYTE0); \ + (pRegs)->host_reg.emul_udata[7] = ((value64 >> 56ULL) & MASK_BYTE0); \ + (pRegs)->host_reg.emul_ucmd = (MMDSP_UCMD_CTRL_STATUS_ACCESS | MMDSP_UCMD_WRITE); \ +} + +#define READ_INDIRECT_HOST_REG(pRegs, addr, value64) \ +{ \ + (pRegs)->host_reg.emul_udata[0] = 0; \ + (pRegs)->host_reg.emul_udata[1] = 0; \ + (pRegs)->host_reg.emul_udata[2] = 0; \ + (pRegs)->host_reg.emul_udata[3] = 0; \ + (pRegs)->host_reg.emul_udata[4] = 0; \ + (pRegs)->host_reg.emul_udata[5] = 0; \ + (pRegs)->host_reg.emul_udata[6] = 0; \ + (pRegs)->host_reg.emul_udata[7] = 0; \ + (pRegs)->host_reg.emul_uaddrl = addr; \ + (pRegs)->host_reg.emul_uaddrm = 0; \ + (pRegs)->host_reg.emul_uaddrh = 0; \ + (pRegs)->host_reg.emul_ucmd = (MMDSP_UCMD_CTRL_STATUS_ACCESS | MMDSP_UCMD_READ); \ + value64 = (((t_uint64)((pRegs)->host_reg.emul_udata[0])) << 0ULL) | \ + (((t_uint64)((pRegs)->host_reg.emul_udata[1])) << 8ULL) | \ + (((t_uint64)((pRegs)->host_reg.emul_udata[2])) << 16ULL) | \ + (((t_uint64)((pRegs)->host_reg.emul_udata[3])) << 24ULL) | \ + (((t_uint64)((pRegs)->host_reg.emul_udata[4])) << 32ULL) | \ + (((t_uint64)((pRegs)->host_reg.emul_udata[5])) << 40ULL) | \ + (((t_uint64)((pRegs)->host_reg.emul_udata[6])) << 48ULL) | \ + (((t_uint64)((pRegs)->host_reg.emul_udata[7])) << 56ULL); \ +} + +/* Common type to handle 64-bit modulo field in 32-bit mode */ +typedef struct { + t_uint32 value; + t_uint32 dummy; +} t_mmdsp_field_32; + +typedef struct { + t_uint16 value; + t_uint16 dummy; +} t_mmdsp_field_16; + +/* DCache registers */ +#define DCACHE_MODE_ENABLE MASK_BIT0 +#define DCACHE_MODE_DISABLE 0 +#define DCACHE_MODE_DIVIDE_PER_2 MASK_BIT1 +#define DCACHE_MODE_DIVIDE_PER_4 MASK_BIT2 +#define DCACHE_MODE_CHECK_TAG_ENABLE MASK_BIT3 +#define DCACHE_MODE_CHECK_TAG_DISABLE 0 +#define DCACHE_MODE_FORCE_LOCK_MODE MASK_BIT4 +#define DCACHE_MODE_LOCK_BIT MASK_BIT5 + +#define DCACHE_CONTROL_PREFETCH_LINE MASK_BIT0 +#define DCACHE_CONTROL_NON_BLOCKING_REFILL 0 +#define DCACHE_CONTROL_FAST_READ_DISABLE MASK_BIT1 +#define DCACHE_CONTROL_FAST_READ_ENABLE 0 +#define DCACHE_CONTROL_ON_FLY_FILL_ACCESS_OFF MASK_BIT2 +#define DCACHE_CONTROL_ON_FLY_FILL_ACCESS_ON 0 +#define DCACHE_CONTROL_BURST_1_WRAP8 MASK_BIT3 +#define DCACHE_CONTROL_BURST_2_WRAP4 0 +#define DCACHE_CONTROL_NOT_USE_DATA_BUFFER MASK_BIT4 +#define DCACHE_CONTROL_USE_DATA_BUFFER 0 +#define DCACHE_CONTROL_WRITE_POSTING_ENABLE MASK_BIT5 +#define DCACHE_CONTROL_WRITE_POSTING_DISABLE 0 + +#define DCACHE_CMD_NOP 0 +#define DCACHE_CMD_DISCARD_WAY 2 //see Dcache_way reg +#define DCACHE_CMD_DISCARD_LINE 3 //see Dcache_line reg +#define DCACHE_CMD_FREE_WAY 4 //see Dcache_way reg +#define DCACHE_CMD_FREE_LINE 5 //see Dchache_line reg +#define DCACHE_CMD_FLUSH 7 + +#define DCACHE_STATUS_CURRENT_WAY_MASK (MASK_BIT2 | MASK_BIT1 | MASK_BIT0) +#define DCACHE_STATUS_TAG_HIT_MASK MASK_BIT3 +#define DCACHE_STATUS_TAG_LOCKED_MASK MASK_BIT4 +#define DCACHE_STATUS_PROTECTION_ERROR_MASK MASK_BIT5 + +#define DCACHE_CPTRSEL_COUNTER_1_MASK (MASK_BIT3 | MASK_BIT2 | MASK_BIT1 | MASK_BIT0) +#define DCACHE_CPTRSEL_COUNTER_1_SHIFT 0 +#define DCACHE_CPTRSEL_COUNTER_2_MASK (MASK_BIT7 | MASK_BIT6 | MASK_BIT5 | MASK_BIT4) +#define DCACHE_CPTRSEL_COUNTER_2_SHIFT 4 +#define DCACHE_CPTRSEL_COUNTER_3_MASK (MASK_BIT11 | MASK_BIT10 | MASK_BIT9 | MASK_BIT8) +#define DCACHE_CPTRSEL_COUNTER_3_SHIFT 8 +#define DCACHE_CPTRSEL_XBUS_ACCESS_TO_CACHE_RAM 1 +#define DCACHE_CPTRSEL_CACHE_HIT 2 +#define DCACHE_CPTRSEL_LINE_MATCH 3 +#define DCACHE_CPTRSEL_XBUS_WS 4 +#define DCACHE_CPTRSEL_EXTMEM_WS 5 +#define DCACHE_CPTRSEL_CACHE_READ 6 +#define DCACHE_CPTRSEL_CACHE_WRITE 7 +#define DCACHE_CPTRSEL_TAG_HIT_READ 8 +#define DCACHE_CPTRSEL_TAG_LOCKED_ACCESS 9 +#define DCACHE_CPTRSEL_TAG_MEM_READ_CYCLE 10 +#define DCACHE_CPTRSEL_TAG_MEM_WRITE_CYCLE 11 + + +typedef volatile struct { + t_uint16 padding_1[5]; + t_uint16 mode; + t_uint16 control; + t_uint16 way; + t_uint16 line; + t_uint16 command; + t_uint16 status; + t_uint16 cptr1l; + t_uint16 cptr1h; + t_uint16 cptr2l; + t_uint16 cptr2h; + t_uint16 cptr3l; + t_uint16 cptr3h; + t_uint16 cptrsel; + t_uint16 flush_base_lsb; /* only on STn8820 and STn8500 */ + t_uint16 flush_base_msb; /* only on STn8820 and STn8500 */ + t_uint16 flush_top_lsb; /* only on STn8820 and STn8500 */ + t_uint16 flush_top_msb; /* only on STn8820 and STn8500 */ + t_uint16 padding_2[10]; +} t_mmdsp_dcache_regs_16; + +typedef volatile struct { + t_uint32 padding_1[5]; + t_uint32 mode; + t_uint32 control; + t_uint32 way; + t_uint32 line; + t_uint32 command; + t_uint32 status; + t_uint32 cptr1l; + t_uint32 cptr1h; + t_uint32 cptr2l; + t_uint32 cptr2h; + t_uint32 cptr3l; + t_uint32 cptr3h; + t_uint32 cptrsel; + t_uint32 flush_base_lsb; /* only on STn8820 and STn8500 */ + t_uint32 flush_base_msb; /* only on STn8820 and STn8500 */ + t_uint32 flush_top_lsb; /* only on STn8820 and STn8500 */ + t_uint32 flush_top_msb; /* only on STn8820 and STn8500 */ + t_uint32 padding_2[10]; +} t_mmdsp_dcache_regs_32; + +/* TIMER Registers */ +typedef volatile struct { + t_mmdsp_field_16 timer_msb; + t_mmdsp_field_16 timer_lsb; +} t_mmdsp_timer_regs_16; + +typedef volatile struct { + t_mmdsp_field_32 timer_msb; + t_mmdsp_field_32 timer_lsb; +} t_mmdsp_timer_regs_32; + + +/* DMA interface Registers */ +typedef volatile struct { + t_uint16 arm_dma_sreq; /* dma0: 5e800, dma1: +0x20 ...*/ + t_uint16 arm_dma_breq; /* ... 5e802 */ + t_uint16 arm_dma_lsreq; /* ... 5e804 */ + t_uint16 arm_dma_lbreq; + t_uint16 arm_dma_maskit; + t_uint16 arm_dma_it; + t_uint16 arm_dma_auto; + t_uint16 arm_dma_lauto; + t_uint16 dma_reserved[8]; +} t_mmdsp_dma_if_regs_16; + +typedef volatile struct { + t_uint32 arm_dma_sreq; /* dma0: 3a800, dma1: +0x40 ...*/ + t_uint32 arm_dma_breq; /* ... 3a804 */ + t_uint32 arm_dma_lsreq; /* ... 3a808 */ + t_uint32 arm_dma_lbreq; + t_uint32 arm_dma_maskit; + t_uint32 arm_dma_it; + t_uint32 arm_dma_auto; + t_uint32 arm_dma_lauto; + t_uint32 dma_reserved[8]; +} t_mmdsp_dma_if_regs_32; + +/* MMDSP DMA controller Registers */ +typedef volatile struct { + t_uint16 dma_ctrl; /* dma0: 0x5d400, dma1: +0x10 ... */ + t_uint16 dma_int_base; /* ... 0x5d402 */ + t_uint16 dma_int_length; /* ... 0x5d404 */ + t_uint16 dma_ext_baseh; + t_uint16 dma_ext_basel; + t_uint16 dma_count; + t_uint16 dma_ext_length; + t_uint16 dma_it_status; +} t_mmdsp_dma_ctrl_regs_16; + +typedef volatile struct { + t_uint32 dma_ctrl; /* dma0: 0x3a800, dma1: +0x20 ... */ + t_uint32 dma_int_base; /* ... 0x3a804 */ + t_uint32 dma_int_length; /* ... 0x3a808 */ + t_uint32 dma_ext_baseh; + t_uint32 dma_ext_basel; + t_uint32 dma_count; + t_uint32 dma_ext_length; + t_uint32 dma_it_status; +} t_mmdsp_dma_ctrl_regs_32; + +/* IO registers */ +typedef volatile struct { + t_mmdsp_field_16 io_bit[MMDSP_NB_IO]; + t_mmdsp_field_16 io_lsb; + t_mmdsp_field_16 io_msb; + t_mmdsp_field_16 io_all; + t_mmdsp_field_16 io_en; +} t_mmdsp_io_regs_16; + +typedef volatile struct { + t_mmdsp_field_32 io_bit[MMDSP_NB_IO]; + t_mmdsp_field_32 io_lsb; + t_mmdsp_field_32 io_msb; + t_mmdsp_field_32 io_all; + t_mmdsp_field_32 io_en; +} t_mmdsp_io_regs_32; + +/* HOST Registers bit mapping */ +#define HOST_GATEDCLK_ITREMAP MASK_BIT0 +#define HOST_GATEDCLK_SYSDMA MASK_BIT1 +#define HOST_GATEDCLK_INTEG_REGS MASK_BIT2 +#define HOST_GATEDCLK_TIMER_GPIO MASK_BIT3 +#define HOST_GATEDCLK_XBUSDMA MASK_BIT4 +#define HOST_GATEDCLK_STACKCTRL MASK_BIT5 +#define HOST_GATEDCLK_ITC MASK_BIT6 + +/* Only for STn8820 and STn8500 */ +#define HOST_PWR_DBG_MODE MASK_BIT0 +#define HOST_PWR_DC_STATUS (MASK_BIT1 | MASK_BIT2 | MASK_BIT3 | MASK_BIT4 | MASK_BIT5) +#define HOST_PWR_DE_STATUS MASK_BIT6 +#define HOST_PWR_STOV_STATUS MASK_BIT7 + +/* HOST Registers */ +typedef volatile struct { + t_uint16 ident; /*0x...60000*/ + t_uint16 identx[4]; /*0x...60002..8*/ + t_uint16 r5; /*0x...6000a*/ + t_uint16 r6; /*0x...6000c*/ + t_uint16 inte[2]; /*0x...6000e..10*/ + t_uint16 intx[2]; /*0x...60012..14*/ + t_uint16 int_ris[2]; /*0x...60016..18*/ + t_uint16 intpol; /*0x...6001a*/ + t_uint16 pwr; /*0x...6001c*/ /* only on STn8820 and STn8500 */ + t_uint16 gatedclk; /*0x...6001e*/ + t_uint16 softreset; /*0x...60020*/ + t_uint16 int_icr[2]; /*0x...60022..24*/ + t_uint16 cmd[4]; /*0x...60026..2c*/ + t_uint16 RESERVED4; + t_uint16 int_mis0; /*0x...60030*/ + t_uint16 RESERVED5; + t_uint16 RESERVED6; + t_uint16 RESERVED7; + t_uint16 i2cdiv; /*0x...60038*/ + t_uint16 int_mis1; /*0x...6003a*/ + t_uint16 RESERVED8; + t_uint16 RESERVED9; + t_uint16 emul_udata[8]; /*0x...60040..4e*/ + t_uint16 emul_uaddrl; /*0x...60050*/ + t_uint16 emul_uaddrm; /*0x...60052*/ + t_uint16 emul_ucmd; /*0x...60054*/ + t_uint16 emul_ubkcmd; /*0x...60056*/ + t_uint16 emul_bk2addl; /*0x...60058*/ + t_uint16 emul_bk2addm; /*0x...6005a*/ + t_uint16 emul_bk2addh; /*0x...6005c*/ + t_uint16 emul_mdata[3]; /*0x...6005e..62*/ + t_uint16 emul_maddl; /*0x...60064*/ + t_uint16 emul_maddm; /*0x...60066*/ + t_uint16 emul_mcmd; /*0x...60068*/ + t_uint16 emul_maddh; /*0x...6006a*/ + t_uint16 emul_uaddrh; /*0x...6006c*/ + t_uint16 emul_bk_eql; /*0x...6006e*/ + t_uint16 emul_bk_eqh; /*0x...60070*/ + t_uint16 emul_bk_combi; /*0x...60072*/ + t_uint16 emul_clockcmd; /*0x...60074*/ + t_uint16 emul_stepcmd; /*0x...60076*/ + t_uint16 emul_scanreg; /*0x...60078*/ + t_uint16 emul_breakcountl; /*0x...6007a*/ + t_uint16 emul_breakcounth; /*0x...6007c*/ + t_uint16 emul_forcescan; /*0x...6007e*/ + t_uint16 user_area[(0x200 - 0x80)>>1]; +} t_mmdsp_host_regs_16; + +typedef volatile struct { + t_uint32 ident; /*0x...60000*/ + t_uint32 identx[4]; /*0x...60004..10*/ + t_uint32 r5; /*0x...60014*/ + t_uint32 r6; /*0x...60018*/ + t_uint32 inte[2]; /*0x...6001c..20*/ + t_uint32 intx[2]; /*0x...60024..28*/ + t_uint32 int_ris[2]; /*0x...6002c..30*/ + t_uint32 intpol; /*0x...60034*/ + t_uint32 pwr; /*0x...60038*/ /* only on STn8820 and STn8500 */ + t_uint32 gatedclk; /*0x...6003c*/ + t_uint32 softreset; /*0x...60040*/ + t_uint32 int_icr[2]; /*0x...60044..48*/ + t_uint32 cmd[4]; /*0x...6004c..58*/ + t_uint32 RESERVED4; + t_uint32 int_mis0; /*0x...60060*/ + t_uint32 RESERVED5; + t_uint32 RESERVED6; + t_uint32 RESERVED7; + t_uint32 i2cdiv; /*0x...60070*/ + t_uint32 int_mis1; /*0x...60074*/ + t_uint32 RESERVED8; + t_uint32 RESERVED9; + t_uint32 emul_udata[8]; /*0x...60080..9c*/ + t_uint32 emul_uaddrl; /*0x...600a0*/ + t_uint32 emul_uaddrm; /*0x...600a4*/ + t_uint32 emul_ucmd; /*0x...600a8*/ + t_uint32 emul_ubkcmd; /*0x...600ac*/ + t_uint32 emul_bk2addl; /*0x...600b0*/ + t_uint32 emul_bk2addm; /*0x...600b4*/ + t_uint32 emul_bk2addh; /*0x...600b8*/ + t_uint32 emul_mdata[3]; /*0x...600bc..c4*/ + t_uint32 emul_maddl; /*0x...600c8*/ + t_uint32 emul_maddm; /*0x...600cc*/ + t_uint32 emul_mcmd; /*0x...600d0*/ + t_uint32 emul_maddh; /*0x...600d4*/ + t_uint32 emul_uaddrh; /*0x...600d8*/ + t_uint32 emul_bk_eql; /*0x...600dc*/ + t_uint32 emul_bk_eqh; /*0x...600e0*/ + t_uint32 emul_bk_combi; /*0x...600e4*/ + t_uint32 emul_clockcmd; /*0x...600e8*/ + t_uint32 emul_stepcmd; /*0x...600ec*/ + t_uint32 emul_scanreg; /*0x...600f0*/ + t_uint32 emul_breakcountl; /*0x...600f4*/ + t_uint32 emul_breakcounth; /*0x...600f8*/ + t_uint32 emul_forcescan; /*0x...600fc*/ + t_uint32 user_area[(0x400 - 0x100)>>2]; +} t_mmdsp_host_regs_32; + +/* MMIO blocks */ +#if defined(__STN_8820) || defined(__STN_8500) +typedef volatile struct { + t_uint16 RESERVED1[(0xD400-0x8000)>>1]; + + t_mmdsp_dma_ctrl_regs_16 dma_ctrl[MMDSP_NB_DMA_CTRL]; + + t_uint16 RESERVED2[(0xD800-0xD440)>>1]; + + t_mmdsp_dcache_regs_16 dcache; + + t_uint16 RESERVED3[(0xE000-0xD840)>>1]; + + t_mmdsp_io_regs_16 io; + + t_uint16 RESERVED4[(0x60-0x50)>>1]; + + t_mmdsp_timer_regs_16 timer[MMDSP_NB_TIMER]; + + t_uint16 RESERVED5[(0x410-0x78)>>1]; + + t_mmdsp_field_16 sem[MMDSP_NB_BIT_SEM]; + + t_uint16 RESERVED6[(0x450-0x430)>>1]; + + t_mmdsp_field_16 ipen; + t_uint16 itip_0; + t_uint16 itip_1; + t_uint16 itip_2; + t_uint16 itip_3; + t_uint16 itop_0; + t_uint16 itop_1; + t_uint16 itop_2; + t_uint16 itop_3; + t_uint16 RESERVED7[(0x8a-0x64)>>1]; + t_uint16 itip_4; + t_uint16 itop_4; + + t_uint16 RESERVED8[(0x7e0-0x48e)>>1]; + + t_mmdsp_field_16 id[4]; + t_mmdsp_field_16 idp[4]; + + t_mmdsp_dma_if_regs_16 dma_if[MMDSP_NB_DMA_IF]; + + t_uint16 RESERVED9[(0xC00-0x900)>>1]; + + t_mmdsp_field_16 emu_unit_maskit; + t_mmdsp_field_16 RESERVED[3]; + t_mmdsp_field_16 config_data_mem; + t_mmdsp_field_16 compatibility; + + t_uint16 RESERVED10[(0xF000-0xEC18)>>1]; + + t_uint16 stbus_if_config; + t_uint16 stbus_if_mode; + t_uint16 stbus_if_status; + t_uint16 stbus_if_security; + t_uint16 stbus_if_flush; + t_uint16 stbus_reserved; + t_uint16 stbus_if_priority; + t_uint16 stbus_msb_attribut; + + t_uint16 RESERVED11[(0xFC00-0xF010)>>1]; + + t_mmdsp_field_16 itremap_reg[MMDSP_NB_ITREMAP_REG]; + t_mmdsp_field_16 itmsk_l_reg; + t_mmdsp_field_16 itmsk_h_reg; + + t_uint16 RESERVED12[(0xfc9c - 0xfc88)>>1]; + + t_mmdsp_field_16 itmemo_l_reg; + t_mmdsp_field_16 itmeme_h_reg; + + t_uint16 RESERVED13[(0xfd00 - 0xfca4)>>1]; + + t_mmdsp_field_16 itremap1_reg[MMDSP_NB_ITREMAP_REG]; + + t_uint16 RESERVED14[(0x60000 - 0x5fd80)>>1]; +} t_mmdsp_mmio_regs_16; + + +typedef volatile struct { + t_uint32 RESERVED1[(0xa800)>>2]; + + t_mmdsp_dma_ctrl_regs_32 dma_ctrl[MMDSP_NB_DMA_CTRL]; + + t_uint32 RESERVED2[(0xb000-0xa880)>>2]; + + t_mmdsp_dcache_regs_32 dcache; + + t_uint32 RESERVED3[(0xc000-0xb080)>>2]; + + t_mmdsp_io_regs_32 io; + + t_uint32 RESERVED4[(0xc0-0xa0)>>2]; + + t_mmdsp_timer_regs_32 timer[MMDSP_NB_TIMER]; + + t_uint32 RESERVED5[(0x820-0x0f0)>>2]; + + t_mmdsp_field_32 sem[MMDSP_NB_BIT_SEM]; + + t_uint32 RESERVED6[(0x8a0-0x860)>>2]; + + t_mmdsp_field_32 ipen; + t_uint32 itip_0; + t_uint32 itip_1; + t_uint32 itip_2; + t_uint32 itip_3; + t_uint32 itop_0; + t_uint32 itop_1; + t_uint32 itop_2; + t_uint32 itop_3; + t_uint32 RESERVED7[(0x914-0x8c8)>>2]; + t_uint32 itip_4; + t_uint32 itop_4; + + t_uint32 RESERVED8[(0xcfc0-0xc91c)>>2]; + + t_mmdsp_field_32 id[4]; + t_mmdsp_field_32 idp[4]; + + t_mmdsp_dma_if_regs_32 dma_if[MMDSP_NB_DMA_IF]; + + t_uint32 RESERVED9[(0x800-0x200)>>2]; + + t_mmdsp_field_32 emu_unit_maskit; + t_mmdsp_field_32 RESERVED[3]; + t_mmdsp_field_32 config_data_mem; + t_mmdsp_field_32 compatibility; + + t_uint32 RESERVED10[(0xE000-0xD830)>>2]; + + t_uint32 stbus_if_config; + t_uint32 stbus_if_mode; + t_uint32 stbus_if_status; + t_uint32 stbus_if_security; + t_uint32 stbus_if_flush; + t_uint32 stbus_reserved; + t_uint32 stbus_if_priority; + t_uint32 stbus_msb_attribut; + + t_uint32 RESERVED11[(0xF800-0xE020)>>2]; + + t_mmdsp_field_32 itremap_reg[MMDSP_NB_ITREMAP_REG]; + t_mmdsp_field_32 itmsk_l_reg; + t_mmdsp_field_32 itmsk_h_reg; + + t_uint32 RESERVED12[(0xf938 - 0xf910)>>2]; + + t_mmdsp_field_32 itmemo_l_reg; + t_mmdsp_field_32 itmeme_h_reg; + + t_uint32 RESERVED13[(0xfa00 - 0xf948)>>2]; + + t_mmdsp_field_32 itremap1_reg[MMDSP_NB_ITREMAP_REG]; + + t_uint32 RESERVED14[(0x40000 - 0x3fb00)>>2]; +} t_mmdsp_mmio_regs_32; +#endif /* __STN_8820 or __STN_8500 */ + +#ifdef __STN_8815 +typedef volatile struct { + t_uint16 RESERVED1[(0xD400-0x8000)>>1]; + + t_mmdsp_dma_ctrl_regs_16 dma_ctrl[MMDSP_NB_DMA_CTRL]; + + t_uint16 RESERVED2[(0xD800-0xD440)>>1]; + + t_mmdsp_dcache_regs_16 dcache; + + t_uint16 RESERVED3[(0xE000-0xD840)>>1]; + + t_mmdsp_io_regs_16 io; + + t_uint16 RESERVED4[(0x60-0x50)>>1]; + + t_mmdsp_timer_regs_16 timer[MMDSP_NB_TIMER]; + + t_uint16 RESERVED5[(0x410-0x78)>>1]; + + t_mmdsp_field_16 sem[MMDSP_NB_BIT_SEM]; + + t_uint16 RESERVED6[(0x450-0x430)>>1]; + + t_mmdsp_field_16 ipen; + t_uint16 itip_0; + t_uint16 itip_1; + t_uint16 itip_2; + t_uint16 itip_3; + t_uint16 itop_0; + t_uint16 itop_1; + t_uint16 itop_2; + t_uint16 itop_3; + t_uint16 RESERVED7[(0x8a-0x64)>>1]; + t_uint16 itip_4; + t_uint16 itop_4; + + t_uint16 RESERVED8[(0x7e0-0x48e)>>1]; + + t_mmdsp_field_16 id[4]; + t_mmdsp_field_16 idp[4]; + + t_mmdsp_dma_if_regs_16 dma_if[MMDSP_NB_DMA_IF]; + + t_uint16 RESERVED9[(0xC00-0x900)>>1]; + + t_mmdsp_field_16 emu_unit_maskit; + t_mmdsp_field_16 RESERVED[3]; + t_mmdsp_field_16 config_data_mem; + t_mmdsp_field_16 compatibility; + + t_uint16 RESERVED10[(0xF000-0xEC18)>>1]; + + t_uint16 ahb_if_config; + t_uint16 ahb_if_mode; + t_uint16 ahb_if_status; + t_uint16 ahb_if_security; + t_uint16 ahb_if_flush; + + t_uint16 RESERVED11[(0xFC00-0xF00A)>>1]; + + t_mmdsp_field_16 itremap_reg[MMDSP_NB_ITREMAP_REG]; + t_mmdsp_field_16 itmsk_l_reg; + t_mmdsp_field_16 itmsk_h_reg; + + t_uint16 RESERVED12[(0xfc9c - 0xfc88)>>1]; + + t_mmdsp_field_16 itmemo_l_reg; + t_mmdsp_field_16 itmeme_h_reg; + + t_uint16 RESERVED13[(0xfd00 - 0xfca4)>>1]; + + t_mmdsp_field_16 itremap1_reg[MMDSP_NB_ITREMAP_REG]; + + t_uint16 RESERVED14[(0x60000 - 0x5fd80)>>1]; +} t_mmdsp_mmio_regs_16; + + +typedef volatile struct { + t_uint32 RESERVED1[(0xa800)>>2]; + + t_mmdsp_dma_ctrl_regs_32 dma_ctrl[MMDSP_NB_DMA_CTRL]; + + t_uint32 RESERVED2[(0xb000-0xa880)>>2]; + + t_mmdsp_dcache_regs_32 dcache; + + t_uint32 RESERVED3[(0xc000-0xb080)>>2]; + + t_mmdsp_io_regs_32 io; + + t_uint32 RESERVED4[(0xc0-0xa0)>>2]; + + t_mmdsp_timer_regs_32 timer[MMDSP_NB_TIMER]; + + t_uint32 RESERVED5[(0x820-0x0f0)>>2]; + + t_mmdsp_field_32 sem[MMDSP_NB_BIT_SEM]; + + t_uint32 RESERVED6[(0x8a0-0x860)>>2]; + + t_mmdsp_field_32 ipen; + t_uint32 itip_0; + t_uint32 itip_1; + t_uint32 itip_2; + t_uint32 itip_3; + t_uint32 itop_0; + t_uint32 itop_1; + t_uint32 itop_2; + t_uint32 itop_3; + t_uint32 RESERVED7[(0x914-0x8c8)>>2]; + t_uint32 itip_4; + t_uint32 itop_4; + + t_uint32 RESERVED8[(0xcfc0-0xc91c)>>2]; + + t_mmdsp_field_32 id[4]; + t_mmdsp_field_32 idp[4]; + + t_mmdsp_dma_if_regs_32 dma_if[MMDSP_NB_DMA_IF]; + + t_uint32 RESERVED9[(0x800-0x200)>>2]; + + t_mmdsp_field_32 emu_unit_maskit; + t_mmdsp_field_32 RESERVED[3]; + t_mmdsp_field_32 config_data_mem; + t_mmdsp_field_32 compatibility; + + t_uint32 RESERVED10[(0xE000-0xD830)>>2]; + + t_uint32 ahb_if_config; + t_uint32 ahb_if_mode; + t_uint32 ahb_if_status; + t_uint32 ahb_if_security; + t_uint32 ahb_if_flush; + + t_uint32 RESERVED11[(0xF800-0xE014)>>2]; + + t_mmdsp_field_32 itremap_reg[MMDSP_NB_ITREMAP_REG]; + t_mmdsp_field_32 itmsk_l_reg; + t_mmdsp_field_32 itmsk_h_reg; + + t_uint32 RESERVED12[(0xf938 - 0xf910)>>2]; + + t_mmdsp_field_32 itmemo_l_reg; + t_mmdsp_field_32 itmeme_h_reg; + + t_uint32 RESERVED13[(0xfa00 - 0xf948)>>2]; + + t_mmdsp_field_32 itremap1_reg[MMDSP_NB_ITREMAP_REG]; + + t_uint32 RESERVED14[(0x40000 - 0x3fb00)>>2]; +} t_mmdsp_mmio_regs_32; +#endif /* __STN_8815 */ + +/* Smart xx Accelerator memory map */ +typedef volatile struct { + t_uint32 mem24[MMDSP_NB_BLOCK_RAM*MMDSP_RAM_BLOCK_SIZE]; /* 0x0000 -> 0x20000 */ + + t_uint32 RESERVED1[(0x30000 - 0x20000)>>2]; + + t_mmdsp_mmio_regs_32 mmio_32; + + t_uint16 mem16[MMDSP_NB_BLOCK_RAM*MMDSP_RAM_BLOCK_SIZE]; /* 0x40000 -> 0x50000 */ + + t_uint32 RESERVED2[(0x58000 - 0x50000)>>2]; + + t_mmdsp_mmio_regs_16 mmio_16; + + t_mmdsp_host_regs_16 host_reg; + /* + union host_reg { + t_mmdsp_host_regs_16 reg16; + t_mmdsp_host_regs_32 reg32; + }; + */ +} t_mmdsp_hw_regs; + +#endif // __INC_MMDSP_HWP_H diff --git a/drivers/staging/nmf-cm/cm/engine/dsp/mmdsp/inc/mmdsp_macros.h b/drivers/staging/nmf-cm/cm/engine/dsp/mmdsp/inc/mmdsp_macros.h new file mode 100644 index 00000000000..b8911d27609 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/dsp/mmdsp/inc/mmdsp_macros.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef __INC_MMDSP_DSP_MACROS +#define __INC_MMDSP_DSP_MACROS + +#include + +#define MMDSP_ENABLE_WRITE_POSTING(pRegs) \ +{ \ + (pRegs)->mmio_16.dcache.control |= DCACHE_CONTROL_WRITE_POSTING_ENABLE; \ +} + +#define MMDSP_FLUSH_DCACHE(pRegs) \ +{ /* Today, only full cache flush (clear all the ways) */ \ + (pRegs)->mmio_16.dcache.command = DCACHE_CMD_FLUSH; \ +} + +#define MMDSP_FLUSH_DCACHE_BY_SERVICE(pRegs, startAddr, endAddr) + +#define MMDSP_FLUSH_ICACHE(pRegs) \ +{ /* Flush the Instruction cache */ \ + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_ICACHE_FLUSH_REG, (IHOST_ICACHE_FLUSH_ALL_ENTRIES_CMD | IHOST_ICACHE_FLUSH_CMD_ENABLE)); \ +} + +#ifndef __STN_8810 +#define MMDSP_FLUSH_ICACHE_BY_SERVICE(pRegs, startAddr, endAddr) \ +{ /* Flush the Instruction cache by service */ \ + /*t_uint64 start_clear_addr = startAddr & ~(MMDSP_ICACHE_LINE_SIZE_IN_INST - 1);*/ \ + t_uint64 start_clear_addr = (startAddr)>>2; \ + t_uint64 end_clear_addr = ((endAddr) + MMDSP_ICACHE_LINE_SIZE_IN_INST) & ~(MMDSP_ICACHE_LINE_SIZE_IN_INST - 1); \ + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_ICACHE_START_CLEAR_REG, start_clear_addr); \ + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_ICACHE_END_CLEAR_REG, end_clear_addr); \ + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_ICACHE_FLUSH_REG, (IHOST_ICACHE_FLUSH_BY_SERVICE | IHOST_ICACHE_FLUSH_CMD_ENABLE)); \ +} +#else +#define MMDSP_FLUSH_ICACHE_BY_SERVICE(pRegs, startAddr, endAddr) {(void)pRegs; (void)startAddr; (void)endAddr; } +#endif + +#define MMDSP_RESET_CORE(pRegs) \ +{ /* Assert DSP core soft reset */ \ + (pRegs)->host_reg.softreset = 1; \ +} + +#define MMDSP_START_CORE(pRegs) \ +{ \ + /* Enable external memory access (set bit 3 of ubkcmd) */ \ + (pRegs)->host_reg.emul_ubkcmd |= MMDSP_UBKCMD_EXT_CODE_MEM_ACCESS_ENABLE; \ + \ + /* Start core clock */ \ + (pRegs)->host_reg.emul_clockcmd = MMDSP_CLOCKCMD_START_CLOCK; \ +} + +#define MMDSP_STOP_CORE(pRegs) \ +{ \ + /* Disable external memory access (reset bit 3 of ubkcmd) */ \ + (pRegs)->host_reg.emul_ubkcmd = MMDSP_UBKCMD_EXT_CODE_MEM_ACCESS_DISABLE; \ + \ + /* Stop core clock */ \ + (pRegs)->host_reg.emul_clockcmd = MMDSP_CLOCKCMD_STOP_CLOCK; \ +} + +#define MMDSP_ASSERT_IRQ(pRegs, irqNum) \ +{ \ + (pRegs)->host_reg.cmd[irqNum] = 1; \ +} + +#define MMDSP_ACKNOWLEDGE_IRQ(pRegs, irqNum) \ +{ \ + volatile t_uint16 dummy; \ + dummy =(pRegs)->host_reg.intx[irqNum]; \ +} + +#define MMDSP_WRITE_XWORD(pRegs, offset, value) \ +{ \ + (pRegs)->mem24[offset] = value; \ +} + +#define MMDSP_READ_XWORD(pRegs, offset) (pRegs)->mem24[offset] + +#endif /* __INC_MMDSP_DSP_MACROS */ diff --git a/drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c b/drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c new file mode 100644 index 00000000000..de4ea3b7ba5 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c @@ -0,0 +1,1074 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +static t_dsp_allocator_desc esramDesc; +static t_dsp_desc mpcDesc[NB_CORE_IDS]; +static t_mmdsp_hw_regs *pMmdspRegs[NB_CORE_IDS]; + +struct s_base_descr +{ + t_uint32 startAddress[2 /* DSP16 = 0, DSP24 = 1*/]; + t_dsp_segment_type segmentType; +}; + +#if defined(__STN_8500) && (__STN_8500 > 10) + +#define DATA_BASE_NUMBER 4 + +// In bytes +#define SDRAM_CODE_SPACE_SPLIT 0x8000 +#define ESRAM_CODE_SPACE_SPLIT 0x4000 +#define SDRAM_DATA_SPACE_SPLIT 0x40000 // This is the modulo constraint of mmdsp +#define ESRAM_DATA_SPACE_SPLIT 0x40000 + +// In MMDSP word +static const struct s_base_descr DATA_ADDRESS_BASE[DATA_BASE_NUMBER + 1 /* For guard */] = { + {{SDRAMMEM16_BASE_ADDR, SDRAMMEM24_BASE_ADDR}, SDRAM_DATA_EE}, + {{SDRAMMEM16_BASE_ADDR + (SDRAM_DATA_SPACE_SPLIT / 2), SDRAMMEM24_BASE_ADDR + (SDRAM_DATA_SPACE_SPLIT / 4)}, SDRAM_DATA_USER}, + {{ESRAMMEM16_BASE_ADDR, ESRAMMEM24_BASE_ADDR}, ESRAM_DATA_EE}, + {{ESRAMMEM16_BASE_ADDR + (ESRAM_DATA_SPACE_SPLIT / 2), ESRAMMEM24_BASE_ADDR + (ESRAM_DATA_SPACE_SPLIT / 4)}, ESRAM_DATA_USER}, + {{MMIO_BASE_ADDR, SDRAMMEM16_BASE_ADDR}, NB_DSP_SEGMENT_TYPE /* Not used*/} +}; + +#else + +#define DATA_BASE_NUMBER 2 + +// In MMDSP word +static const struct s_base_descr DATA_ADDRESS_BASE[DATA_BASE_NUMBER + 1 /* For guard */] = { + {{SDRAMMEM16_BASE_ADDR, SDRAMMEM24_BASE_ADDR}, SDRAM_DATA_EE}, + {{ESRAMMEM16_BASE_ADDR, ESRAMMEM24_BASE_ADDR}, ESRAM_DATA_EE}, + {{MMIO_BASE_ADDR, SDRAMMEM16_BASE_ADDR}, NB_DSP_SEGMENT_TYPE /* Not used*/} +}; + +#endif + +#if defined(__STN_8500) && (__STN_8500 > 10) +// In word +static const t_uint32 CODE_ADDRESS_BASE[4] = { + SDRAMTEXT_BASE_ADDR, + SDRAMTEXT_BASE_ADDR + (SDRAM_CODE_SPACE_SPLIT / 8), + ESRAMTEXT_BASE_ADDR, + ESRAMTEXT_BASE_ADDR + (ESRAM_CODE_SPACE_SPLIT / 8) +}; +#endif + +static void arm_Init(void); +static t_cm_error mmdsp_Init(const t_cm_system_address *dspSystemAddr, + t_uint8 nbXramBlocks, t_uint8 nbYramBlocks, + t_dsp_allocator_desc *sdramCodeDesc, + t_dsp_allocator_desc *sdramDataDesc, + t_cm_domain_id eeDomain, + t_dsp_desc *pDspDesc, + t_mmdsp_hw_regs **pRegs); +static t_cm_error mmdsp_Configure(t_nmf_core_id coreId, t_mmdsp_hw_regs *pRegs, const t_dsp_desc *pDspDesc); +static t_cm_error mmdsp_ConfigureAfterBoot(t_nmf_core_id coreId, t_uint8 nbXramBlocks, t_uint8 nbYramBlocks); +static void cm_DSP_SEM_Init(t_nmf_core_id coreId); + +PUBLIC const t_dsp_desc* cm_DSP_GetState(t_nmf_core_id coreId) +{ + return &mpcDesc[coreId]; +} +PUBLIC void cm_DSP_SetStatePanic(t_nmf_core_id coreId) +{ + mpcDesc[coreId].state = MPC_STATE_PANIC; +} + +PUBLIC void cm_DSP_Init(const t_nmf_memory_segment *pEsramDesc) +{ + t_nmf_core_id coreId; + int i; + + /* Create esram desc */ + esramDesc.allocDesc = cm_MM_CreateAllocator(pEsramDesc->size, 0, "esram"); + esramDesc.baseAddress = pEsramDesc->systemAddr; + esramDesc.referenceCounter = 1; // Don't free it with destroy mechanism + + /* Create ARM */ + arm_Init(); + + mpcDesc[ARM_CORE_ID].state = MPC_STATE_BOOTED; + + /* Reset MPC configuration */ + for (coreId = FIRST_MPC_ID; coreId <= LAST_CORE_ID; coreId++) + { + mpcDesc[coreId].state = MPC_STATE_UNCONFIGURED; + + for(i = 0; i < NB_DSP_MEMORY_TYPE; i++) + mpcDesc[coreId].allocator[i] = NULL; + } + +} + +PUBLIC void cm_DSP_Destroy(void) +{ + t_nmf_core_id coreId; + int i; + + for (coreId = ARM_CORE_ID; coreId <= LAST_CORE_ID; coreId++) + { + for(i = 0; i < NB_DSP_MEMORY_TYPE; i++) + { + if (mpcDesc[coreId].allocator[i] != NULL) + { + if(--mpcDesc[coreId].allocator[i]->referenceCounter == 0) + { + cm_MM_DeleteAllocator(mpcDesc[coreId].allocator[i]->allocDesc); + + OSAL_Free(mpcDesc[coreId].allocator[i]); + } + } + } + } + + cm_MM_DeleteAllocator(esramDesc.allocDesc); +} + + +PUBLIC t_cm_error cm_DSP_Add(t_nmf_core_id coreId, + t_uint8 nbYramBanks, + const t_cm_system_address *pDspMapDesc, + const t_cm_domain_id eeDomain, + t_dsp_allocator_desc *sdramCodeAllocDesc, + t_dsp_allocator_desc *sdramDataAllocDesc) +{ + t_cm_error error; + + /* checking nbYramBanks is valid */ + if (nbYramBanks >= SxA_NB_BLOCK_RAM) + return CM_MPC_INVALID_CONFIGURATION; + + if((error = cm_DM_CheckDomain(eeDomain, DOMAIN_NORMAL)) != CM_OK) + return error; + + mpcDesc[coreId].domainEE = eeDomain; + mpcDesc[coreId].nbYramBank = nbYramBanks; + mpcDesc[coreId].state = MPC_STATE_BOOTABLE; + + return mmdsp_Init( + pDspMapDesc, + SxA_NB_BLOCK_RAM, /* nb of data tcm bank minus one (reserved for cache) */ + nbYramBanks, + sdramCodeAllocDesc, + sdramDataAllocDesc, + eeDomain, + &mpcDesc[coreId], + &pMmdspRegs[coreId] + ); +} + +PUBLIC t_cm_error cm_DSP_Boot(t_nmf_core_id coreId) +{ + t_cm_error error; + + // Enable the associated power domain + if((error = cm_PWR_EnableMPC(MPC_PWR_CLOCK, coreId)) != CM_OK) + return error; + + cm_SEM_PowerOn[coreId](coreId); + + if((error = mmdsp_Configure( + coreId, + pMmdspRegs[coreId], + &mpcDesc[coreId])) != CM_OK) + { + cm_PWR_DisableMPC(MPC_PWR_CLOCK, coreId); + } + + // Put it in auto idle mode ; it's the default in Step 2 of power implementation + if((error = cm_PWR_EnableMPC(MPC_PWR_AUTOIDLE, coreId)) != CM_OK) + return error; + + return error; +} + +/* + * This method is required since MMDSP C bootstrap set some value that must be set differently !!! + */ +PUBLIC void cm_DSP_ConfigureAfterBoot(t_nmf_core_id coreId) +{ + mpcDesc[coreId].state = MPC_STATE_BOOTED; + + mmdsp_ConfigureAfterBoot(coreId, SxA_NB_BLOCK_RAM, mpcDesc[coreId].nbYramBank); + + cm_DSP_SEM_Init(coreId); +} + +PUBLIC void cm_DSP_Stop(t_nmf_core_id coreId) +{ + MMDSP_STOP_CORE(pMmdspRegs[coreId]); + + { + volatile t_uint32 loopme = 0xfff; + while(loopme--) ; + } +} + +PUBLIC void cm_DSP_Start(t_nmf_core_id coreId) +{ + MMDSP_START_CORE(pMmdspRegs[coreId]); + + { + volatile t_uint32 loopme = 0xfff; + while(loopme--) ; + } +} + +PUBLIC void cm_DSP_Shutdown(t_nmf_core_id coreId) +{ + MMDSP_FLUSH_DCACHE(pMmdspRegs[coreId]); + MMDSP_FLUSH_ICACHE(pMmdspRegs[coreId]); + + // Due to a hardware bug that breaks MTU when DSP are powered off, don't do that + // on mop500_ed for now +#if !defined(__STN_8500) || (__STN_8500 > 10) + MMDSP_RESET_CORE(pMmdspRegs[coreId]); + { + volatile t_uint32 loopme = 0xfff; + while(loopme--) ; + } + MMDSP_STOP_CORE(pMmdspRegs[coreId]); + { + volatile t_uint32 loopme = 0xfff; + while(loopme--) ; + } +#endif + + mpcDesc[coreId].state = MPC_STATE_BOOTABLE; + + cm_SEM_PowerOff[coreId](coreId); + + cm_PWR_DisableMPC(MPC_PWR_AUTOIDLE, coreId); + cm_PWR_DisableMPC(MPC_PWR_CLOCK, coreId); +} + +PUBLIC t_uint32 cm_DSP_ReadXRamWord(t_nmf_core_id coreId, t_uint32 dspOffset) +{ + t_uint32 value; + + value = pMmdspRegs[coreId]->mem24[dspOffset]; + + LOG_INTERNAL(3, "cm_DSP_ReadXRamWord: [%x]=%x\n", + dspOffset, value, + 0, 0, 0, 0); + + return value; +} + + +PUBLIC void cm_DSP_WriteXRamWord(t_nmf_core_id coreId, t_uint32 dspOffset, t_uint32 value) +{ + LOG_INTERNAL(3, "cm_DSP_WriteXRamWord: [%x]<-%x\n", + dspOffset, value, + 0, 0, 0, 0); + + pMmdspRegs[coreId]->mem24[dspOffset] = value; +} + +static void cm_DSP_SEM_Init(t_nmf_core_id coreId) +{ + pMmdspRegs[coreId]->mmio_16.sem[1].value = 1; +} + +PUBLIC void cm_DSP_SEM_Take(t_nmf_core_id coreId, t_semaphore_id semId) +{ + /* take semaphore */ + while(pMmdspRegs[coreId]->mmio_16.sem[1].value) ; +} + +PUBLIC void cm_DSP_SEM_Give(t_nmf_core_id coreId, t_semaphore_id semId) +{ + /* release semaphore */ + pMmdspRegs[coreId]->mmio_16.sem[1].value = 1; +} + +PUBLIC void cm_DSP_SEM_GenerateIrq(t_nmf_core_id coreId, t_semaphore_id semId) +{ + MMDSP_ASSERT_IRQ(pMmdspRegs[coreId], ARM2DSP_IRQ_0); +} + + +PUBLIC void cm_DSP_AssertDspIrq(t_nmf_core_id coreId, t_host2mpc_irq_num irqNum) +{ + MMDSP_ASSERT_IRQ(pMmdspRegs[coreId], irqNum); + return; +} + +PUBLIC void cm_DSP_AcknowledgeDspIrq(t_nmf_core_id coreId, t_mpc2host_irq_num irqNum) +{ + MMDSP_ACKNOWLEDGE_IRQ(pMmdspRegs[coreId], irqNum); + return; +} + +//TODO, juraj, cleanup INTERNAL_XRAM vs INTERNAL_XRAM16/24 +static const t_uint32 dspMemoryTypeId2OffsetShifter[NB_DSP_MEMORY_TYPE] = +{ + 2, /* INTERNAL_XRAM24: Internal X memory but seen by host as 32-bit memory */ + 2, /* INTERNAL_XRAM16: Internal X memory but seen by host as 16-bit memory */ + 2, /* INTERNAL_YRAM24: Internal Y memory but seen by host as 32-bit memory */ + 2, /* INTERNAL_YRAM16: Internal Y memory but seen by host as 16-bit memory */ + 2, /* SDRAM_EXT24: 24-bit external "X" memory */ + 1, /* SDRAM_EXT16: 16-bit external "X" memory */ + 2, /* ESRAM_EXT24: ESRAM24 */ + 1, /* ESRAM_EXT16: ESRAM16 */ + 3, /* SDRAM_CODE: Program memory */ + 3, /* ESRAM_CODE: ESRAM code */ + 3, /* LOCKED_CODE: ESRAM code */ +}; + +//TODO, juraj, use these values in mmdsp_Configure +static const t_uint32 dspMemoryTypeId2DspAddressOffset[NB_DSP_MEMORY_TYPE] = +{ + 0, /* INTERNAL_XRAM24 */ + 0, /* INTERNAL_XRAM16 */ + 0, /* INTERNAL_YRAM24 */ + 0, /* INTERNAL_YRAM16 */ + SDRAMMEM24_BASE_ADDR, /* SDRAM_EXT24: 24-bit external "X" memory */ + SDRAMMEM16_BASE_ADDR, /* SDRAM_EXT16: 16-bit external "X" memory */ + ESRAMMEM24_BASE_ADDR, /* ESRAM_EXT24: ESRAM24 */ + ESRAMMEM16_BASE_ADDR, /* ESRAM_EXT16: ESRAM16 */ + SDRAMTEXT_BASE_ADDR, /* SDRAM_CODE: Program memory */ + ESRAMTEXT_BASE_ADDR, /* ESRAM_CODE: ESRAM code */ + SDRAMTEXT_BASE_ADDR, /* ESRAM_CODE: ESRAM code */ +}; + +PUBLIC t_cm_allocator_desc* cm_DSP_GetAllocator(t_nmf_core_id coreId, t_dsp_memory_type_id memType) +{ + return mpcDesc[coreId].allocator[memType] ? mpcDesc[coreId].allocator[memType]->allocDesc : NULL; +} + +PUBLIC void cm_DSP_GetDspChunkInfo(t_memory_handle memHandle, t_dsp_chunk_info *info) +{ + t_uint16 userData; + + cm_MM_GetMemoryHandleUserData(memHandle, &userData, &info->alloc); + + info->coreId = (t_nmf_core_id) ((userData >> SHIFT_BYTE1) & MASK_BYTE0); + info->memType = (t_dsp_memory_type_id)((userData >> SHIFT_BYTE0) & MASK_BYTE0); +} + +PUBLIC t_cm_error cm_DSP_GetInternalMemoriesInfo(t_cm_domain_id domainId, t_dsp_memory_type_id memType, + t_uint32 *offset, t_uint32 *size) +{ + t_nmf_core_id coreId = domainDesc[domainId].domain.coreId; + + switch(memType) + { + case INTERNAL_XRAM24: + case INTERNAL_XRAM16: + *offset = 0; + *size = mpcDesc[coreId].yram_offset; + break; + case INTERNAL_YRAM24: + case INTERNAL_YRAM16: + *offset = mpcDesc[coreId].yram_offset; + *size = mpcDesc[coreId].yram_size; + break; + case LOCKED_CODE: + *offset = mpcDesc[coreId].locked_offset; + *size = mpcDesc[coreId].locked_size; + break; + case SDRAM_EXT24: + case SDRAM_EXT16: + *offset = domainDesc[domainId].domain.sdramData.offset; + *size = domainDesc[domainId].domain.sdramData.size; + break; + case ESRAM_EXT24: + case ESRAM_EXT16: + *offset = domainDesc[domainId].domain.esramData.offset; + *size = domainDesc[domainId].domain.esramData.size; + break; + case SDRAM_CODE: + *offset = domainDesc[domainId].domain.sdramCode.offset; + *size = domainDesc[domainId].domain.sdramCode.size; + + // update domain size to take into account .locked section + if(*offset + *size > mpcDesc[coreId].locked_offset) + *size = mpcDesc[coreId].locked_offset - *offset; + break; + case ESRAM_CODE: + *offset = domainDesc[domainId].domain.esramCode.offset; + *size = domainDesc[domainId].domain.esramCode.size; + break; + default: + //return CM_INVALID_PARAMETER; + //params are checked at the level above, so this should never occur + ERROR("Invalid memType\n",0,0,0,0,0,0); + *offset = 0; + *size = 0; + CM_ASSERT(0); + } + + return CM_OK; +} + + +PUBLIC t_uint32 cm_DSP_ConvertSize(t_dsp_memory_type_id memType, t_uint32 wordSize) +{ + return wordSize << dspMemoryTypeId2OffsetShifter[memType]; +} + +PUBLIC t_cm_logical_address cm_DSP_ConvertDspAddressToHostLogicalAddress(t_nmf_core_id coreId, t_shared_addr dspAddress) +{ + t_dsp_address_info info; + cm_DSP_GetDspDataAddressInfo(coreId, dspAddress, &info); + return mpcDesc[coreId].segments[info.segmentType].base.logical + info.baseOffset; +} + +PUBLIC t_cm_error cm_DSP_GetAllocatorStatus(t_nmf_core_id coreId, t_dsp_memory_type_id dspMemType, t_uint32 offset, t_uint32 size, t_cm_allocator_status *pStatus) +{ + t_cm_error error; + + if(mpcDesc[coreId].allocator[dspMemType] == NULL) + return CM_UNKNOWN_MEMORY_HANDLE; + + error = cm_MM_GetAllocatorStatus(cm_DSP_GetAllocator(coreId, dspMemType), offset, size, pStatus); + if (error != CM_OK) + return error; + + // complete status with stack sizes, for all dsps + //NOTE, well, surely this isn't very clean, as dsp and memory allocator are different things .. + { + t_uint8 i; + for (i = 0; i < NB_CORE_IDS; i++) { + //*(pStatus->stack[i].sizes) = *(eeState[i].currentStackSize); + pStatus->stack[i].sizes[0] = eeState[i].currentStackSize[0]; + pStatus->stack[i].sizes[1] = eeState[i].currentStackSize[1]; + pStatus->stack[i].sizes[2] = eeState[i].currentStackSize[2]; + } + } + + // Change bytes to words + pStatus->global.accumulate_free_memory = pStatus->global.accumulate_free_memory >> dspMemoryTypeId2OffsetShifter[dspMemType]; + pStatus->global.accumulate_used_memory = pStatus->global.accumulate_used_memory >> dspMemoryTypeId2OffsetShifter[dspMemType]; + pStatus->global.maximum_free_size = pStatus->global.maximum_free_size >> dspMemoryTypeId2OffsetShifter[dspMemType]; + pStatus->global.minimum_free_size = pStatus->global.minimum_free_size >> dspMemoryTypeId2OffsetShifter[dspMemType]; + + return error; +} + +PUBLIC void cm_DSP_GetHostSystemAddress(t_memory_handle memHandle, t_cm_system_address *pAddr) +{ + t_dsp_chunk_info chunk_info; + t_uint32 offset; //in bytes + + cm_DSP_GetDspChunkInfo(memHandle, &chunk_info); + + offset = cm_MM_GetOffset(memHandle); + + /* MMDSP mem16 array is very specific to host access, so .... */ + /* We compute by hand the Host System address to take into account the specifities of the mmdsp mem16 array */ + /* 1 dsp word = 2 host bytes AND mem16 array is "exported" by MMDSP External Bus wrapper at the 0x40000 offet */ + if (chunk_info.memType == INTERNAL_XRAM16 || chunk_info.memType == INTERNAL_YRAM16) { + offset = (offset >> 1) + FIELD_OFFSET(t_mmdsp_hw_regs, mem16); + } + + //TODO, juraj, calculate correct value here - based on segments desc etc.. + pAddr->logical = mpcDesc[chunk_info.coreId].allocator[chunk_info.memType]->baseAddress.logical + offset; + pAddr->physical = mpcDesc[chunk_info.coreId].allocator[chunk_info.memType]->baseAddress.physical + offset; +} + + +PUBLIC t_physical_address cm_DSP_GetPhysicalAdress(t_memory_handle memHandle) +{ + t_cm_system_address addr; + cm_DSP_GetHostSystemAddress(memHandle, &addr); + return addr.physical; +} + +PUBLIC t_cm_logical_address cm_DSP_GetHostLogicalAddress(t_memory_handle memHandle) +{ + t_cm_system_address addr; + cm_DSP_GetHostSystemAddress(memHandle, &addr); + return addr.logical; +} + +PUBLIC void cm_DSP_GetDspAddress(t_memory_handle memHandle, t_uint32 *pDspAddress) +{ + t_dsp_chunk_info chunk_info; + + cm_DSP_GetDspChunkInfo(memHandle, &chunk_info); + + *pDspAddress = + (cm_MM_GetOffset(memHandle) >> dspMemoryTypeId2OffsetShifter[chunk_info.memType]) + + dspMemoryTypeId2DspAddressOffset[chunk_info.memType]; +} + +PUBLIC t_cm_error cm_DSP_GetDspBaseAddress(t_nmf_core_id coreId, t_dsp_memory_type_id memType, t_cm_system_address *pAddr) +{ + cm_migration_check_state(coreId, STATE_NORMAL); + *pAddr = mpcDesc[coreId].allocator[memType]->baseAddress; + return CM_OK; +} + +PUBLIC void cm_DSP_GetDspMemoryHandleSize(t_memory_handle memHandle, t_uint32 *pDspSize) +{ + t_dsp_chunk_info chunk_info; + cm_DSP_GetDspChunkInfo(memHandle, &chunk_info); + *pDspSize = cm_MM_GetSize(memHandle) >> dspMemoryTypeId2OffsetShifter[chunk_info.memType]; +} + +PUBLIC t_cm_error cm_DSP_setStackSize(t_nmf_core_id coreId, t_uint32 newStackSize) +{ + t_uint8 nbXramBanks; + t_uint32 xramSize; + + /* compute size of xram allocator */ + nbXramBanks = SxA_NB_BLOCK_RAM - mpcDesc[coreId].nbYramBank; + + /* check first that required stack size is less then xram memory ....*/ + if (newStackSize >= nbXramBanks * 4 * ONE_KB) + return CM_NO_MORE_MEMORY; + + /* compute new xram allocator size */ + xramSize = nbXramBanks * 4 * ONE_KB - newStackSize; + + /* try to resize it */ + return cm_MM_ResizeAllocator(cm_DSP_GetAllocator(coreId, INTERNAL_XRAM24), + xramSize << dspMemoryTypeId2OffsetShifter[INTERNAL_XRAM24]); +} + +PUBLIC t_cm_error cm_DSP_IsNbYramBanksValid(t_nmf_core_id coreId, t_uint8 nbYramBanks) +{ + /* we use one bank for cache */ + t_uint8 nbOfRamBanksWithCacheReserved = SxA_NB_BLOCK_RAM; + + /* we want to keep at least one bank of xram */ + if (nbYramBanks < nbOfRamBanksWithCacheReserved) {return CM_OK;} + else {return CM_MPC_INVALID_CONFIGURATION;} +} + +PUBLIC t_uint32 cm_DSP_getStackAddr(t_nmf_core_id coreId) +{ + /* we use one bank for cache */ + //t_uint8 nbOfRamBanksWithCacheReserved = SxA_NB_BLOCK_RAM; + /* */ + //return ((nbOfRamBanksWithCacheReserved * MMDSP_RAM_BLOCK_SIZE * MMDSP_DATA_WORD_SIZE_IN_HOST_SPACE) - mpcDesc[coreId].yram_offset); + return mpcDesc[coreId].yram_offset / MMDSP_DATA_WORD_SIZE_IN_HOST_SPACE; +} + +static void arm_Init(void) +{ + mpcDesc[ARM_CORE_ID].allocator[INTERNAL_XRAM24] = 0; + mpcDesc[ARM_CORE_ID].allocator[INTERNAL_XRAM16] = 0; + + mpcDesc[ARM_CORE_ID].allocator[INTERNAL_YRAM24] = 0; + mpcDesc[ARM_CORE_ID].allocator[INTERNAL_YRAM16] = 0; + + mpcDesc[ARM_CORE_ID].allocator[SDRAM_CODE] = 0; + mpcDesc[ARM_CORE_ID].allocator[ESRAM_CODE] = 0; + + mpcDesc[ARM_CORE_ID].allocator[SDRAM_EXT16] = 0; + mpcDesc[ARM_CORE_ID].allocator[SDRAM_EXT24] = 0; + + mpcDesc[ARM_CORE_ID].allocator[ESRAM_EXT16] = &esramDesc; + mpcDesc[ARM_CORE_ID].allocator[ESRAM_EXT16]->referenceCounter++; + mpcDesc[ARM_CORE_ID].allocator[ESRAM_EXT24] = &esramDesc; + mpcDesc[ARM_CORE_ID].allocator[ESRAM_EXT24]->referenceCounter++; +} + +static void _init_Segment( + t_dsp_segment *seg, + const t_cm_system_address base, const t_uint32 arm_offset, + const t_uint32 size) +{ + seg->base.logical = base.logical + arm_offset; + seg->base.physical = base.physical + arm_offset; + seg->size = size; +} + +static t_cm_error mmdsp_Init( + const t_cm_system_address *dspSystemAddr, + t_uint8 nbXramBlocks, t_uint8 nbYramBlocks, + t_dsp_allocator_desc *sdramCodeDesc, + t_dsp_allocator_desc *sdramDataDesc, + t_cm_domain_id eeDomain, + t_dsp_desc *pDspDesc, + t_mmdsp_hw_regs **pRegs) +{ + t_cm_system_address xramSysAddr; + t_uint32 sizeInBytes; + + /* Initialize reference on hw ressources */ + *pRegs = (t_mmdsp_hw_regs *) dspSystemAddr->logical; + + /* Initialize memory segments management */ + xramSysAddr.logical = (t_cm_logical_address)(((t_mmdsp_hw_regs *)dspSystemAddr->logical)->mem24); + xramSysAddr.physical = (t_cm_physical_address)(((t_mmdsp_hw_regs *)dspSystemAddr->physical)->mem24); + + /* The last (x)ram block will be used by cache, so ... */ + /* And the NB_YRAM_BLOCKS last available block(s) will be used as YRAM */ + + /* XRAM*/ + pDspDesc->allocator[INTERNAL_XRAM16] = pDspDesc->allocator[INTERNAL_XRAM24] = (t_dsp_allocator_desc*)OSAL_Alloc(sizeof (t_dsp_allocator_desc)); + if (pDspDesc->allocator[INTERNAL_XRAM24] == NULL) + return CM_NO_MORE_MEMORY; + + pDspDesc->allocator[INTERNAL_XRAM24]->allocDesc = cm_MM_CreateAllocator( + ((nbXramBlocks-nbYramBlocks)*MMDSP_RAM_BLOCK_SIZE)*MMDSP_DATA_WORD_SIZE_IN_HOST_SPACE, + 0, + "XRAM"); + pDspDesc->allocator[INTERNAL_XRAM24]->baseAddress = xramSysAddr; + pDspDesc->allocator[INTERNAL_XRAM24]->referenceCounter = 2; + + /* YRAM */ + pDspDesc->allocator[INTERNAL_YRAM16] = pDspDesc->allocator[INTERNAL_YRAM24] = (t_dsp_allocator_desc*)OSAL_Alloc(sizeof (t_dsp_allocator_desc)); + if (pDspDesc->allocator[INTERNAL_YRAM24] == 0) { + OSAL_Free(pDspDesc->allocator[INTERNAL_XRAM24]); + return CM_NO_MORE_MEMORY; + } + + pDspDesc->allocator[INTERNAL_YRAM24]->allocDesc = cm_MM_CreateAllocator( + (nbYramBlocks*MMDSP_RAM_BLOCK_SIZE)*MMDSP_DATA_WORD_SIZE_IN_HOST_SPACE, + ((nbXramBlocks-nbYramBlocks)*MMDSP_RAM_BLOCK_SIZE)*MMDSP_DATA_WORD_SIZE_IN_HOST_SPACE, + "YRAM"); + pDspDesc->allocator[INTERNAL_YRAM24]->baseAddress = xramSysAddr; /* use xram base address but offset is not null */ + pDspDesc->allocator[INTERNAL_YRAM24]->referenceCounter = 2; + + pDspDesc->yram_offset = ((nbXramBlocks-nbYramBlocks)*MMDSP_RAM_BLOCK_SIZE)*MMDSP_DATA_WORD_SIZE_IN_HOST_SPACE; + pDspDesc->yram_size = (nbYramBlocks*MMDSP_RAM_BLOCK_SIZE)*MMDSP_DATA_WORD_SIZE_IN_HOST_SPACE; + + /* SDRAM & ESRAM */ + pDspDesc->allocator[SDRAM_CODE] = sdramCodeDesc; + pDspDesc->allocator[SDRAM_CODE]->referenceCounter++; + pDspDesc->allocator[ESRAM_CODE] = &esramDesc; + pDspDesc->allocator[ESRAM_CODE]->referenceCounter++; + + /* LOCKED CODE at end of SDRAM code*/ + pDspDesc->allocator[LOCKED_CODE] = sdramCodeDesc; + pDspDesc->allocator[LOCKED_CODE]->referenceCounter++; + + pDspDesc->locked_offset = cm_MM_GetAllocatorSize(pDspDesc->allocator[SDRAM_CODE]->allocDesc) - MMDSP_CODE_CACHE_WAY_SIZE * 8 * SxA_LOCKED_WAY; + pDspDesc->locked_size = MMDSP_CODE_CACHE_WAY_SIZE * 8 * SxA_LOCKED_WAY; + + /* Data_16/24 memory management */ + pDspDesc->allocator[SDRAM_EXT16] = sdramDataDesc; + pDspDesc->allocator[SDRAM_EXT16]->referenceCounter++; + pDspDesc->allocator[SDRAM_EXT24] = sdramDataDesc; + pDspDesc->allocator[SDRAM_EXT24]->referenceCounter++; + + pDspDesc->allocator[ESRAM_EXT16] = &esramDesc; + pDspDesc->allocator[ESRAM_EXT16]->referenceCounter++; + pDspDesc->allocator[ESRAM_EXT24] = &esramDesc; + pDspDesc->allocator[ESRAM_EXT24]->referenceCounter++; + + sizeInBytes = cm_MM_GetAllocatorSize(pDspDesc->allocator[SDRAM_CODE]->allocDesc); +#if defined(__STN_8500) && (__STN_8500 > 10) + _init_Segment(&pDspDesc->segments[SDRAM_CODE_EE], + pDspDesc->allocator[SDRAM_CODE]->baseAddress, + domainDesc[eeDomain].domain.sdramCode.offset, + domainDesc[eeDomain].domain.sdramCode.size); + _init_Segment(&pDspDesc->segments[SDRAM_CODE_USER], + pDspDesc->allocator[SDRAM_CODE]->baseAddress, + domainDesc[eeDomain].domain.sdramCode.offset + domainDesc[eeDomain].domain.sdramCode.size, + sizeInBytes - domainDesc[eeDomain].domain.sdramCode.size); +#else + _init_Segment(&pDspDesc->segments[SDRAM_CODE_EE], + pDspDesc->allocator[SDRAM_CODE]->baseAddress, + 0x0, + sizeInBytes); +#endif + + sizeInBytes = cm_MM_GetAllocatorSize(pDspDesc->allocator[ESRAM_CODE]->allocDesc); +#if defined(__STN_8500) && (__STN_8500 > 10) + _init_Segment(&pDspDesc->segments[ESRAM_CODE_EE], + pDspDesc->allocator[ESRAM_CODE]->baseAddress, + domainDesc[eeDomain].domain.esramCode.offset, + domainDesc[eeDomain].domain.esramCode.size); + _init_Segment(&pDspDesc->segments[ESRAM_CODE_USER], + pDspDesc->allocator[ESRAM_CODE]->baseAddress, + domainDesc[eeDomain].domain.esramCode.offset + domainDesc[eeDomain].domain.esramCode.size, + sizeInBytes - domainDesc[eeDomain].domain.esramCode.size); +#else + _init_Segment(&pDspDesc->segments[ESRAM_CODE_EE], + pDspDesc->allocator[ESRAM_CODE]->baseAddress, + 0x0, + sizeInBytes); +#endif + + //the difference in the following code is the segment size used to calculate the top!! + sizeInBytes = cm_MM_GetAllocatorSize(pDspDesc->allocator[SDRAM_EXT16]->allocDesc); +#if defined(__STN_8500) && (__STN_8500 > 10) + _init_Segment(&pDspDesc->segments[SDRAM_DATA_EE], + pDspDesc->allocator[SDRAM_EXT16]->baseAddress, + domainDesc[eeDomain].domain.sdramData.offset, + domainDesc[eeDomain].domain.sdramData.size); + _init_Segment(&pDspDesc->segments[SDRAM_DATA_USER], + pDspDesc->allocator[SDRAM_EXT16]->baseAddress, + domainDesc[eeDomain].domain.sdramData.offset + domainDesc[eeDomain].domain.sdramData.size, + sizeInBytes - domainDesc[eeDomain].domain.sdramData.size); +#else + _init_Segment(&pDspDesc->segments[SDRAM_DATA_EE], + pDspDesc->allocator[SDRAM_EXT16]->baseAddress, + 0x0, + sizeInBytes); +#endif + + sizeInBytes = cm_MM_GetAllocatorSize(pDspDesc->allocator[ESRAM_EXT16]->allocDesc); +#if defined(__STN_8500) && (__STN_8500 > 10) + _init_Segment(&pDspDesc->segments[ESRAM_DATA_EE], + pDspDesc->allocator[ESRAM_EXT16]->baseAddress, + domainDesc[eeDomain].domain.esramData.offset, + domainDesc[eeDomain].domain.esramData.size); + _init_Segment(&pDspDesc->segments[ESRAM_DATA_USER], + pDspDesc->allocator[ESRAM_EXT16]->baseAddress, + domainDesc[eeDomain].domain.esramData.offset + domainDesc[eeDomain].domain.esramData.size, + sizeInBytes - domainDesc[eeDomain].domain.esramData.size); +#else + _init_Segment(&pDspDesc->segments[ESRAM_DATA_EE], + pDspDesc->allocator[ESRAM_EXT16]->baseAddress, + 0x0, + sizeInBytes); +#endif + + return CM_OK; +} + +//TODO, juraj, reuse cm_DSP_UpdateBase functions +static t_cm_error mmdsp_Configure(t_nmf_core_id coreId, t_mmdsp_hw_regs *pRegs, const t_dsp_desc *pDspDesc) +{ + t_uint64 regValue; + static const t_uint64 coreId2stbusId[NB_CORE_IDS] = + { + 0, /* ARM_CORE_ID no meaning */ + SVA_STBUS_ID, /* SVA_CORE_ID */ + SIA_STBUS_ID /* SIA_CORE_ID */ + }; + + //t_cm_system_address sysAddr; + //t_cm_size sizeInBytes; + + /* Stop core (stop clock) */ + MMDSP_RESET_CORE(pRegs); + { + volatile t_uint32 loopme = 0xfff; + while(loopme--) ; + } + MMDSP_STOP_CORE(pRegs); + { + volatile t_uint32 loopme = 0xfff; + while(loopme--) ; + } + +#if 0 + /* Reset DSP internal memory (xram) */ + { + t_uint32 *pSrc = (t_uint32 *)(pRegs->mem24); + t_uint32 tcmSize; + int i; + cm_MM_GetAllocatorSize(pDspDesc->allocator[INTERNAL_XRAM], &sizeInBytes); + tcmSize = sizeInBytes; + cm_MM_GetAllocatorSize(pDspDesc->allocator[INTERNAL_YRAM], &sizeInBytes); + tcmSize += sizeInBytes; + for (i = 0; i < (tcmSize/sizeof(t_uint32)); i++) + *(pSrc++) = 0; + } +#endif + + /* Configure all blocks as X only, except the Y ones (MOVED TO mmdsp_InitAfterBoot()) */ + + /* __STN_8815 --> __STN_8820 or __STN_8500 */ + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_STBUS_ID_CONF_REG, coreId2stbusId[coreId]); + + /* Configure External Bus timeout reg */ + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_EN_EXT_BUS_TIMEOUT_REG, IHOST_TIMEOUT_ENABLE); + + /* Program memory management */ +#if defined(__STN_8500) && (__STN_8500 > 10) + { + const t_uint32 r0 = CODE_ADDRESS_BASE[1] >> 10; + const t_uint32 r1 = CODE_ADDRESS_BASE[2] >> 10; + const t_uint32 r2 = CODE_ADDRESS_BASE[3] >> 10; + const t_uint32 sdram0 = pDspDesc->segments[SDRAM_CODE_EE].base.physical; + const t_uint32 sdram1 = pDspDesc->segments[SDRAM_CODE_USER].base.physical; + const t_uint32 esram0 = pDspDesc->segments[ESRAM_CODE_EE].base.physical; + const t_uint32 esram1 = pDspDesc->segments[ESRAM_CODE_USER].base.physical; + + /* Bases for first two segments, going to sdram */ + regValue = ((t_uint64)(sdram1) << IHOST_PRG_BASE2_ADDR_SHIFT) + (t_uint64)sdram0; + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_PRG_BASE_ADDR_REG, regValue); + + /* Bases for second two segments, going to esram */ + regValue = ((t_uint64)(esram1) << IHOST_PRG_BASE4_ADDR_SHIFT) + (t_uint64)esram0; + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_PRG_BASE_34_ADDR_REG, regValue); + + /* Split mmdsp program adress-space and activate the mechanism */ + regValue = (t_uint64)((t_uint64)(r2) << 48 | (t_uint64)(r1) <<32 | (t_uint64)(r0) << 16 | 1); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_PRG_BASE2_ACTIV_REG, regValue); + } +#else + { + const t_uint32 sdram0 = pDspDesc->segments[SDRAM_CODE_EE].base.physical; + const t_uint32 esram0 = pDspDesc->segments[ESRAM_CODE_EE].base.physical; + + regValue = (t_uint64)sdram0 | ( ((t_uint64)esram0) << IHOST_PRG_BASE2_ADDR_SHIFT ); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_PRG_BASE_ADDR_REG, regValue); + + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_PRG_BASE2_ACTIV_REG, IHOST_PRG_BASE2_ACTIV_ON); + } +#endif + + /* Data_16/24 memory management */ +#if defined(__STN_8500) && (__STN_8500 > 10) + /* Segments 1 and 2 for 16/24 map to sdram continuously */ + /* Base 1 */ + regValue = (((t_uint64)pDspDesc->segments[SDRAM_DATA_EE].base.physical) << IHOST_DATA_EXT_BUS_BASE_24_SHIFT) | + (((t_uint64)pDspDesc->segments[SDRAM_DATA_EE].base.physical) << IHOST_DATA_EXT_BUS_BASE_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA_EXT_BUS_BASE_REG, regValue); + /* Top 1 */ + regValue = (((t_uint64)(pDspDesc->segments[SDRAM_DATA_EE].base.physical + pDspDesc->segments[SDRAM_DATA_EE].size - 1)) << IHOST_DATA_EXT_BUS_TOP_24_SHIFT) | + (((t_uint64)(pDspDesc->segments[SDRAM_DATA_EE].base.physical + pDspDesc->segments[SDRAM_DATA_EE].size - 1)) << IHOST_DATA_EXT_BUS_TOP_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA_EXT_BUS_TOP_16_24_REG, regValue); + + /* Base 2 */ + regValue = (((t_uint64)pDspDesc->segments[SDRAM_DATA_USER].base.physical) << IHOST_DATA_EXT_BUS_BASE2_24_SHIFT) | + (((t_uint64)pDspDesc->segments[SDRAM_DATA_USER].base.physical) << IHOST_DATA_EXT_BUS_BASE2_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA_EXT_BUS_BASE2_REG, regValue); + /* Top 2 */ + regValue = (((t_uint64)(pDspDesc->segments[SDRAM_DATA_USER].base.physical + pDspDesc->segments[SDRAM_DATA_USER].size - 1)) << IHOST_DATA_EXT_BUS_TOP2_24_SHIFT) | + (((t_uint64)(pDspDesc->segments[SDRAM_DATA_USER].base.physical + pDspDesc->segments[SDRAM_DATA_USER].size - 1)) << IHOST_DATA_EXT_BUS_TOP2_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_EXT_BUS_TOP2_16_24_REG, regValue); + + /* Segments 3 and 4 for 16/24 map to esram continuously */ + /* Base 3 */ + regValue = (((t_uint64)pDspDesc->segments[ESRAM_DATA_EE].base.physical) << IHOST_DATA_EXT_BUS_BASE3_24_SHIFT) | + (((t_uint64)pDspDesc->segments[ESRAM_DATA_EE].base.physical) << IHOST_DATA_EXT_BUS_BASE3_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA_EXT_BUS_BASE3_REG, regValue); + /* Top 3 */ + regValue = (((t_uint64)(pDspDesc->segments[ESRAM_DATA_EE].base.physical + pDspDesc->segments[ESRAM_DATA_EE].size - 1)) << IHOST_DATA_EXT_BUS_TOP3_24_SHIFT) | + (((t_uint64)(pDspDesc->segments[ESRAM_DATA_EE].base.physical + pDspDesc->segments[ESRAM_DATA_EE].size - 1)) << IHOST_DATA_EXT_BUS_TOP3_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_EXT_BUS_TOP3_16_24_REG, regValue); + + /* Base 4 */ + regValue = (((t_uint64)pDspDesc->segments[ESRAM_DATA_USER].base.physical) << IHOST_DATA_EXT_BUS_BASE4_24_SHIFT) | + (((t_uint64)pDspDesc->segments[ESRAM_DATA_USER].base.physical) << IHOST_DATA_EXT_BUS_BASE4_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA_EXT_BUS_BASE4_REG, regValue); + /* Top 4 */ + regValue = (((t_uint64)(pDspDesc->segments[ESRAM_DATA_USER].base.physical + pDspDesc->segments[ESRAM_DATA_USER].size - 1)) << IHOST_DATA_EXT_BUS_TOP4_24_SHIFT) | + (((t_uint64)(pDspDesc->segments[ESRAM_DATA_USER].base.physical + pDspDesc->segments[ESRAM_DATA_USER].size - 1)) << IHOST_DATA_EXT_BUS_TOP4_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_EXT_BUS_TOP4_16_24_REG, regValue); + + /* Define base 2 thresholds/offset (1MB for each up segment) */ + regValue = ((t_uint64)DATA_ADDRESS_BASE[1].startAddress[1]>>SHIFT_HALFWORD1)<< IHOST_DATA2_24_XA_BASE_SHIFT; + regValue |= ((t_uint64)DATA_ADDRESS_BASE[1].startAddress[0]>>SHIFT_HALFWORD1)<< IHOST_DATA2_16_XA_BASE_SHIFT; + + /* Define base 3 thresholds/offset (1MB for each up segment) */ + regValue |= ((t_uint64)DATA_ADDRESS_BASE[2].startAddress[1]>>SHIFT_HALFWORD1)<< IHOST_DATA3_24_XA_BASE_SHIFT; + regValue |= ((t_uint64)DATA_ADDRESS_BASE[2].startAddress[0]>>SHIFT_HALFWORD1)<< IHOST_DATA3_16_XA_BASE_SHIFT; + + /* Define base 4 thresholds/offset (1MB for each up segment) */ + regValue |= ((t_uint64)DATA_ADDRESS_BASE[3].startAddress[1]>>SHIFT_HALFWORD1)<< IHOST_DATA4_24_XA_BASE_SHIFT; + regValue |= ((t_uint64)DATA_ADDRESS_BASE[3].startAddress[0]>>SHIFT_HALFWORD1)<< IHOST_DATA4_16_XA_BASE_SHIFT; + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA2_1624_XA_BASE_REG, regValue); + +#else + /* Program data24/16 base 1 */ + regValue = (((t_uint64)pDspDesc->segments[SDRAM_DATA_EE].base.physical) << IHOST_DATA_EXT_BUS_BASE_24_SHIFT) | + (((t_uint64)pDspDesc->segments[SDRAM_DATA_EE].base.physical) << IHOST_DATA_EXT_BUS_BASE_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA_EXT_BUS_BASE_REG, regValue); + + /* Program data24/16 top 1 */ + regValue = (((t_uint64)(pDspDesc->segments[SDRAM_DATA_EE].base.physical + pDspDesc->segments[SDRAM_DATA_EE].size - 1)) << IHOST_DATA_EXT_BUS_TOP_24_SHIFT) | + (((t_uint64)(pDspDesc->segments[SDRAM_DATA_EE].base.physical + pDspDesc->segments[SDRAM_DATA_EE].size - 1)) << IHOST_DATA_EXT_BUS_TOP_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA_EXT_BUS_TOP_16_24_REG, regValue); + + /* Program data24/16 base 2 */ + regValue = (((t_uint64)pDspDesc->segments[ESRAM_DATA_EE].base.physical) << IHOST_DATA_EXT_BUS_BASE2_24_SHIFT) | + (((t_uint64)pDspDesc->segments[ESRAM_DATA_EE].base.physical) << IHOST_DATA_EXT_BUS_BASE2_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA_EXT_BUS_BASE2_REG, regValue); + + /* Program data24/16 top 2 */ + regValue = (((t_uint64)(pDspDesc->segments[ESRAM_DATA_EE].base.physical + pDspDesc->segments[ESRAM_DATA_EE].size - 1)) << IHOST_DATA_EXT_BUS_TOP2_24_SHIFT) | + (((t_uint64)(pDspDesc->segments[ESRAM_DATA_EE].base.physical + pDspDesc->segments[ESRAM_DATA_EE].size - 1)) << IHOST_DATA_EXT_BUS_TOP2_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_EXT_BUS_TOP2_16_24_REG, regValue); + + /* Define base 2 thresholds/offset (1MB for each up segment) */ + regValue = ((t_uint64)(DATA_ADDRESS_BASE[1].startAddress[1]>>SHIFT_HALFWORD1))<< IHOST_DATA2_24_XA_BASE_SHIFT; // Top address minus ONE_MB => 256KW (24/32-bit) + regValue |= ((t_uint64)(DATA_ADDRESS_BASE[1].startAddress[0]>>SHIFT_HALFWORD1))<< IHOST_DATA2_16_XA_BASE_SHIFT; // Top address minus ONE_MB => 512KW (16-bit) + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA2_1624_XA_BASE_REG, regValue); +#endif + + /* Enable top check */ + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA_TOP_16_24_CHK_REG, IHOST_DATA_TOP_16_24_CHK_ON); + + /* Enable both bases */ + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_DATA_BASE2_ACTIV_REG, IHOST_DATA_BASE2_ACTIV_ON); + + /* MMIO management */ + regValue = (((t_uint64)STM_BASE_ADDR) << IHOST_EXT_MMIO_BASE_ADDR_SHIFT) | + (((t_uint64)DMA_CTRL_END_ADDR) << IHOST_EXT_MMIO_DATA_EXT_BUS_TOP_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_EXT_MMIO_BASE_DATA_EXT_BUS_TOP_REG, regValue); + + /* Configure Icache */ + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_INST_BURST_SZ_REG, IHOST_INST_BURST_SZ_AUTO); + + regValue = (t_uint64)(IHOST_ICACHE_MODE_PERFMETER_OFF | IHOST_ICACHE_MODE_L2_CACHE_ON | + IHOST_ICACHE_MODE_L1_CACHE_ON | IHOST_ICACHE_MODE_FILL_MODE_OFF); + WRITE_INDIRECT_HOST_REG(pRegs, IHOST_ICACHE_MODE_REG, regValue); + + return CM_OK; +} + +PUBLIC t_cm_error cm_DSP_updateCodeBase( + t_nmf_core_id coreId, + t_dsp_segment_type hwSegment, + t_cm_system_address src, + t_cm_system_address dst + ) +{ +#if defined(__STN_8500) && (__STN_8500 > 10) + t_mmdsp_hw_regs *pRegs = pMmdspRegs[coreId]; + t_uint32 offset = src.physical - mpcDesc[coreId].segments[hwSegment].base.physical; + t_cm_system_address base; + t_uint32 altBase = 0; + t_uint64 regValue = 0; + t_uint8 reg = 0; + + base.physical = dst.physical - offset; + base.logical = dst.logical - offset; + + switch(hwSegment) { + case SDRAM_CODE_EE: + altBase = mpcDesc[coreId].segments[SDRAM_CODE_USER].base.physical; + regValue = ((t_uint64)(altBase) << IHOST_PRG_BASE2_ADDR_SHIFT) + (t_uint64)base.physical; + reg = IHOST_PRG_BASE_ADDR_REG; + break; + case SDRAM_CODE_USER: + altBase = mpcDesc[coreId].segments[SDRAM_CODE_EE].base.physical; + regValue = ((t_uint64)(base.physical) << IHOST_PRG_BASE2_ADDR_SHIFT) + (t_uint64)altBase; + reg = IHOST_PRG_BASE_ADDR_REG; + break; + case ESRAM_CODE_EE: + altBase = mpcDesc[coreId].segments[ESRAM_CODE_USER].base.physical; + regValue = ((t_uint64)(altBase) << IHOST_PRG_BASE4_ADDR_SHIFT) + (t_uint64)base.physical; + reg = IHOST_PRG_BASE_34_ADDR_REG; + break; + case ESRAM_CODE_USER: + altBase = mpcDesc[coreId].segments[ESRAM_CODE_EE].base.physical; + regValue = ((t_uint64)(base.physical) << IHOST_PRG_BASE4_ADDR_SHIFT) + (t_uint64)altBase; + reg = IHOST_PRG_BASE_34_ADDR_REG; + break; + default: + CM_ASSERT(0); + } + + LOG_INTERNAL(1, "##### DSP Code Base Update [%d]: 0x%x -> 0x%x (0x%x)\n", + hwSegment, mpcDesc[coreId].segments[hwSegment].base.physical, base.physical, base.logical, 0, 0); + + WRITE_INDIRECT_HOST_REG(pRegs, reg, regValue); + + mpcDesc[coreId].segments[hwSegment].base = base; +#endif + return CM_OK; +} + +PUBLIC t_cm_error cm_DSP_updateDataBase( + t_nmf_core_id coreId, + t_dsp_segment_type hwSegment, + t_cm_system_address src, + t_cm_system_address dst + ) +{ +#if defined(__STN_8500) && (__STN_8500 > 10) + t_mmdsp_hw_regs *pRegs = pMmdspRegs[coreId]; + t_uint32 offset = src.physical - mpcDesc[coreId].segments[hwSegment].base.physical; + t_cm_system_address base; + t_uint32 size = mpcDesc[coreId].segments[hwSegment].size; //in bytes + t_uint64 regValue; + t_uint8 reg = 0; + t_uint8 top = 0; + + base.physical = dst.physical - offset; + base.logical = dst.logical - offset; + + switch(hwSegment) { + case SDRAM_DATA_EE: + reg = IHOST_DATA_EXT_BUS_BASE_REG; + top = IHOST_DATA_EXT_BUS_TOP_16_24_REG; + break; + case SDRAM_DATA_USER: + reg = IHOST_DATA_EXT_BUS_BASE2_REG; + top = IHOST_EXT_BUS_TOP2_16_24_REG; + break; + case ESRAM_DATA_EE: + reg = IHOST_DATA_EXT_BUS_BASE3_REG; + top = IHOST_EXT_BUS_TOP3_16_24_REG; + break; + case ESRAM_DATA_USER: + reg = IHOST_DATA_EXT_BUS_BASE4_REG; + top = IHOST_EXT_BUS_TOP4_16_24_REG; + break; + default: + CM_ASSERT(0); + } + + LOG_INTERNAL(1, "##### DSP Data Base Update [%d]: 0x%x -> 0x%x (0x%x)\n", + hwSegment, mpcDesc[coreId].segments[hwSegment].base.physical, base.physical, base.logical, 0, 0); + + /* Program data24/16 base */ + regValue = (((t_uint64)(base.physical)) << IHOST_DATA_EXT_BUS_BASE2_24_SHIFT) | + (((t_uint64)(base.physical)) << IHOST_DATA_EXT_BUS_BASE2_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, reg, regValue); + + /* Program data24/16 top */ + regValue = (((t_uint64)(base.physical + size - 1)) << IHOST_DATA_EXT_BUS_TOP2_24_SHIFT) | + (((t_uint64)(base.physical + size - 1)) << IHOST_DATA_EXT_BUS_TOP2_16_SHIFT); + WRITE_INDIRECT_HOST_REG(pRegs, top, regValue); + + mpcDesc[coreId].segments[hwSegment].base = base; +#endif + return CM_OK; +} + +PUBLIC t_cm_error cm_DSP_GetDspDataAddressInfo(t_nmf_core_id coreId, t_uint32 addr, t_dsp_address_info *info) +{ + t_uint32 i, j; + + for(j = 0; j < 2; j++) + { + for(i = 0; i < DATA_BASE_NUMBER; i++) + { + if(DATA_ADDRESS_BASE[i].startAddress[j] <= addr && addr < DATA_ADDRESS_BASE[i + 1].startAddress[j]) + { + info->segmentType = DATA_ADDRESS_BASE[i].segmentType; + info->baseOffset = (addr - DATA_ADDRESS_BASE[i].startAddress[j]) * (2 + j * 2); + + return CM_OK; + } + } + } + + CM_ASSERT(0); + //return CM_INVALID_PARAMETER; +} + +static t_cm_error mmdsp_ConfigureAfterBoot(t_nmf_core_id coreId, t_uint8 nbXramBlocks, t_uint8 nbYramBlocks) +{ + /* Configure all blocks as X only, except the Y ones */ + pMmdspRegs[coreId]->mmio_16.config_data_mem.value = (t_uint16)(~(((1U << nbYramBlocks) - 1) << (nbXramBlocks-nbYramBlocks))); + +#if defined(__STN_8500) && (__STN_8500 > 10) + /* enable write posting */ + MMDSP_ENABLE_WRITE_POSTING(pMmdspRegs[coreId]); +#endif + + return CM_OK; +} + + diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/bfd.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/bfd.h new file mode 100644 index 00000000000..2bccf9c073b --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/bfd.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf bfd relocation. + * + * \defgroup ELFLOADER MMDSP ELF loader. + */ +#ifndef __INC_CM_ELF_BFD_H +#define __INC_CM_ELF_BFD_H + +#include + +/* + * Relocation spcification + */ +enum complain_overflow +{ + /* Do not complain on overflow. */ + complain_overflow_dont, + + /* Complain if the bitfield overflows, whether it is considered + as signed or unsigned. */ + complain_overflow_bitfield, + + /* Complain if the value overflows when considered as signed + number. */ + complain_overflow_signed, + + /* Complain if the value overflows when considered as an + unsigned number. */ + complain_overflow_unsigned +}; + +struct reloc_howto_struct +{ + /* The type field has mainly a documentary use - the back end can + do what it wants with it, though normally the back end's + external idea of what a reloc number is stored + in this field. For example, a PC relative word relocation + in a coff environment has the type 023 - because that's + what the outside world calls a R_PCRWORD reloc. */ + unsigned int type; + + /* The value the final relocation is shifted right by. This drops + unwanted data from the relocation. */ + unsigned int rightshift; + + /* The size of the item to be relocated. This is *not* a + power-of-two measure. To get the number of bytes operated + on by a type of relocation, use bfd_get_reloc_size. */ + int size; + + /* The number of bits in the item to be relocated. This is used + when doing overflow checking. */ + unsigned int bitsize; + + /* Notes that the relocation is relative to the location in the + data section of the addend. The relocation function will + subtract from the relocation value the address of the location + being relocated. */ + t_uint64 pc_relative; + + /* The bit position of the reloc value in the destination. + The relocated value is left shifted by this amount. */ + unsigned int bitpos; + + /* What type of overflow error should be checked for when + relocating. */ + enum complain_overflow complain_on_overflow; + + void (*special_function)(void); + + /* The textual name of the relocation type. */ + char *name; + + /* Some formats record a relocation addend in the section contents + rather than with the relocation. For ELF formats this is the + distinction between USE_REL and USE_RELA (though the code checks + for USE_REL == 1/0). The value of this field is TRUE if the + addend is recorded with the section contents; when performing a + partial link (ld -r) the section contents (the data) will be + modified. The value of this field is FALSE if addends are + recorded with the relocation (in arelent.addend); when performing + a partial link the relocation will be modified. + All relocations for all ELF USE_RELA targets should set this field + to FALSE (values of TRUE should be looked on with suspicion). + However, the converse is not true: not all relocations of all ELF + USE_REL targets set this field to TRUE. Why this is so is peculiar + to each particular target. For relocs that aren't used in partial + links (e.g. GOT stuff) it doesn't matter what this is set to. */ + char partial_inplace; + + /* src_mask selects the part of the instruction (or data) to be used + in the relocation sum. If the target relocations don't have an + addend in the reloc, eg. ELF USE_REL, src_mask will normally equal + dst_mask to extract the addend from the section contents. If + relocations do have an addend in the reloc, eg. ELF USE_RELA, this + field should be zero. Non-zero values for ELF USE_RELA targets are + bogus as in those cases the value in the dst_mask part of the + section contents should be treated as garbage. */ + t_uint64 src_mask; + + /* dst_mask selects which parts of the instruction (or data) are + replaced with a relocated value. */ + t_uint64 dst_mask; + + /* When some formats create PC relative instructions, they leave + the value of the pc of the place being relocated in the offset + slot of the instruction, so that a PC relative relocation can + be made just by adding in an ordinary offset (e.g., sun3 a.out). + Some formats leave the displacement part of an instruction + empty (e.g., m88k bcs); this flag signals the fact. */ + char pcrel_offset; +}; + +#define HOWTO(C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ + { (unsigned) C, R, S, B, P, BI, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC } + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/common.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/common.h new file mode 100644 index 00000000000..c51845d5f96 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/common.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf common definition. + */ +#ifndef __INC_CM_ELF_COMMON_H +#define __INC_CM_ELF_COMMON_H + +#include +#include +#include +#include +#include +#include + + +#define MAX_SEGMENT 20 // Just in order to not allocate them dynamically + +struct XXElf; + +/** + * \brief Structure used as database of pushed component. + */ +typedef struct { + t_instance_property instanceProperty; + t_uint32 magicNumber; //!< Magic Number + t_dup_char foundedTemplateName; + t_uint32 minStackSize; //!< Minimum stack size + + struct XXElf *ELF; + + t_elfSegment segments[NUMBER_OF_MMDSP_MEMORY]; + + t_bool temporaryDescription; + + t_memory_reference memoryForConstruct; + t_memory_reference memoryForStart; + t_memory_reference memoryForStop; + t_memory_reference memoryForDestroy; + + t_uint8 requireNumber; //!< Number of interface required by this template + t_uint8 attributeNumber; //!< Number of attributes in this template + t_uint8 propertyNumber; //!< Number of properties in this template + t_uint8 provideNumber; //!< Number of interface provided by this template + + t_interface_require *requires; //!< Array of interface required by this template + t_attribute *attributes; //!< Array of attributes in this template + t_property *properties; //!< Array of properties in this template + t_interface_provide *provides; //!< Array of interface provided by this template + +} t_elfdescription; + +/** + * \brief Temporary structure used as database when pushing component. + */ +typedef struct +{ + const char *elfdata; + const char *sectionData[50]; // YES it must be dynamic, but i'm tired. + + t_bool isExecutable; + + t_sint32 nmfSectionIndex; + const void *relaNmfSegment, *relaNmfSegmentEnd; + const void *relaNmfSegmentSymbols; + const char *relaNmfSegmentStrings; + + const t_elf_component_header*elfheader; + + +} t_tmp_elfdescription; + + +t_cm_error ELF64_LoadComponent( + t_uint16 e_machine, + const char *elfdata, + t_elfdescription **elfhandlePtr, + t_tmp_elfdescription *elftmp); +t_cm_error ELF64_ComputeSegment( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp); + +void ELF64_UnloadComponent( + t_elfdescription *elfhandle); + +t_cm_error ELF64_loadSegment( + t_elfdescription *elfhandle, + t_memory_handle *memory, + t_memory_property property); +t_cm_error ELF64_relocateSegments( + t_memory_handle *memories, + t_elfdescription *elf, + t_memory_property property, + void *cbContext); +t_cm_error ELF64_getRelocationMemory( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp, + t_uint32 offsetInNmf, + t_memory_reference *memory); + +const t_elfmemory* MMDSP_getMappingById(t_memory_id memId); +const t_elfmemory* MMDSP_getMappingByName(const char* sectionName, t_instance_property property); +void MMDSP_serializeMemories(t_instance_property property, + const t_elfmemory** codeMemory, const t_elfmemory** thisMemory); +void MMDSP_copySection(t_uint32 origAddr, t_uint32 remoteAddr, t_uint32 sizeInByte); +void MMDSP_bzeroSection(t_uint32 remoteAddr, t_uint32 sizeInByte); +void MMDSP_loadedSection(t_nmf_core_id coreId, t_memory_id memId, t_memory_handle handle); +void MMDSP_unloadedSection(t_nmf_core_id coreId, t_memory_id memId, t_memory_handle handle); + +void MMDSP_copyCode(t_uint64 * remoteAddr64, const char* origAddr, int nb); +void MMDSP_copyData24(t_uint32 * remoteAddr32, const char* origAddr, int nb); +void MMDSP_copyData16(t_uint16 * remoteAddr16, const char* origAddr, int nb); + +t_uint32 cm_resolvSymbol( + void* context, + t_uint32 type, + t_dup_char symbolName, + char* reloc_addr); + + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/elfabi.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/elfabi.h new file mode 100644 index 00000000000..cbcc6db3b9b --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/elfabi.h @@ -0,0 +1,539 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#ifndef _CM_ELF_H +#define _CM_ELF_H 1 + +typedef t_uint16 Elf32_Half; +typedef t_uint16 Elf64_Half; + +typedef t_uint32 Elf32_Word; +typedef t_sint32 Elf32_Sword; +typedef t_uint32 Elf64_Word; +typedef t_sint32 Elf64_Sword; + +typedef t_uint64 Elf32_Xword; +typedef t_sint64 Elf32_Sxword; +typedef t_uint64 Elf64_Xword; +typedef t_sint64 Elf64_Sxword; + +typedef t_uint32 Elf32_Addr; +typedef t_uint64 Elf64_Addr; + +typedef t_uint32 Elf32_Off; +typedef t_uint64 Elf64_Off; + +typedef t_uint16 Elf32_Section; +typedef t_uint16 Elf64_Section; + +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + + +/********************************************* + * Header + *********************************************/ +#define EI_NIDENT (16) //!< Size of e_ident[] + +#define EI_MAG0 0 //!< File identification +#define ELFMAG0 0x7f + +#define EI_MAG1 1 //!< File identification +#define ELFMAG1 'E' + +#define EI_MAG2 2 //!< File identification +#define ELFMAG2 'L' + +#define EI_MAG3 3 //!< File identification +#define ELFMAG3 'F' + +#define EI_CLASS 4 //!< File class +#define ELFCLASSNONE 0 //!< Invalid class +#define ELFCLASS32 1 //!< 32-bit objects +#define ELFCLASS64 2 //!< 64-bit objects + +#define EI_DATA 5 //!< Data encoding +#define ELFDATANONE 0 //!< Invalid data encoding +#define ELFDATA2LSB 1 //!< 2's complement, little endian +#define ELFDATA2MSB 2 //!< 2's complement, big endian + +#define EI_VERSION 6 //!< File version + +#define EI_OSABI 7 //!< OS ABI identification +#define ELFOSABI_NONE 0 //!< No extension +#define ELFOSABI_HPUX 1 //!< HP-UX +#define ELFOSABI_NETBSD 2 //!< NetBSD +#define ELFOSABI_LINUX 3 //!< Linux +#define ELFOSABI_SOLARIS 6 //!< Sun Solaris +#define ELFOSABI_AIX 7 //!< AIX +#define ELFOSABI_IRIX 8 //!< IRIX +#define ELFOSABI_FREEBSD 9 //!< FreeBSD +#define ELFOSABI_TRU64 10 //!< Compaq TRU64 UNIX +#define ELFOSABI_MODESTO 11 //!< Novell Modesto +#define ELFOSABI_OPENBSD 12 //!< Open BSD +#define ELFOSABI_OPENVMS 13 //!< Open VMS +#define ELFOSABI_NSK 14 //!< HP Non-Stop-Kernel + +#define EI_ABIVERSION 8 //!< ABI version + +#define EI_PAD 9 //!< Start of padding byte + + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; //!< The initial bytes mark the file as an object file and provide machine-independent data with which to decode and interpret the file's contents + Elf32_Half e_type; //!< This member identifies the object file type + Elf32_Half e_machine; //!< This member's value specifies the required architecture for an individual file + Elf32_Word e_version; //!< This member identifies the object file version + Elf32_Addr e_entry; //!< This member gives the virtual address to which the system first transfers control, thus starting the process + Elf32_Off e_phoff; //!< This member holds the program header table's file offset in bytes + Elf32_Off e_shoff; //!< This member holds the section header table's file offset in bytes + Elf32_Word e_flags; //!< This member holds processor-specific flags associated with the file + Elf32_Half e_ehsize; //!< This member holds the ELF header's size in bytes + Elf32_Half e_phentsize; //!< This member holds the size in bytes of one entry in the file's program header table; all entries are the same size + Elf32_Half e_phnum; //!< This member holds the number of entries in the program header table + Elf32_Half e_shentsize; //!< This member holds a section header's size in bytes + Elf32_Half e_shnum; //!< This member holds the number of entries in the section header table + Elf32_Half e_shstrndx; //!< This member holds the section header table index of the entry associated with the section name string table +} Elf32_Ehdr; //!< 32bit Entry Header + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; //!< The initial bytes mark the file as an object file and provide machine-independent data with which to decode and interpret the file's contents + Elf64_Half e_type; //!< This member identifies the object file type + Elf64_Half e_machine; //!< This member's value specifies the required architecture for an individual file + Elf64_Word e_version; //!< This member identifies the object file version + Elf64_Addr e_entry; //!< This member gives the virtual address to which the system first transfers control, thus starting the process + Elf64_Off e_phoff; //!< This member holds the program header table's file offset in bytes + Elf64_Off e_shoff; //!< This member holds the section header table's file offset in bytes + Elf64_Word e_flags; //!< This member holds processor-specific flags associated with the file + Elf64_Half e_ehsize; //!< This member holds the ELF header's size in bytes + Elf64_Half e_phentsize; //!< This member holds the size in bytes of one entry in the file's program header table; all entries are the same size + Elf64_Half e_phnum; //!< This member holds the number of entries in the program header table + Elf64_Half e_shentsize; //!< This member holds a section header's size in bytes + Elf64_Half e_shnum; //!< This member holds the number of entries in the section header table + Elf64_Half e_shstrndx; //!< This member holds the section header table index of the entry associated with the section name string table +} Elf64_Ehdr; //!< 64bit Entry Header + +/* + * e_type + */ +#define ET_NONE 0 //!< No file type +#define ET_REL 1 //!< Relocatable file +#define ET_EXEC 2 //!< Executable file +#define ET_DYN 3 //!< Shared object file +#define ET_CORE 4 //!< Core file +#define ET_LOOS 0xfe00 //!< Operating system-specific +#define ET_HIOS 0xfeff //!< Operating system-specific +#define ET_LOPROC 0xff00 //!< Processor-specific +#define ET_HIPROC 0xffff //!< Processor-specific + +/* + * e_machine + */ +#define EM_NONE 0 //!< No machine +#define EM_M32 1 //!< AT&T WE 32100 +#define EM_SPARC 2 //!< SUN SPARC +#define EM_386 3 //!< Intel 80386 +#define EM_68K 4 //!< Motorola 68000 +#define EM_88K 5 //!< Motorola 88000 +#define EM_860 7 //!< Intel 80860 +#define EM_MIPS 8 //!< MIPS I architecture +#define EM_S370 9 //!< IBM System/370 +#define EM_MIPS_RS3_LE 10 //!< MIPS R3000 little-endian +#define EM_PARISC 15 //!< HPPA +#define EM_VPP500 17 //!< Fujitsu VPP500 +#define EM_SPARC32PLUS 18 //!< Enhanced instruction set SPARC +#define EM_960 19 //!< Intel 80960 +#define EM_PPC 20 //!< PowerPC +#define EM_PPC64 21 //!< 64-bit PowerPC +#define EM_S390 22 //!< IBM System/390 Processor +#define EM_V800 36 //!< NEC V800 +#define EM_FR20 37 //!< Fujitsu FR20 +#define EM_RH32 38 //!< TRW RH-32 +#define EM_RCE 39 //!< Motorola RCE +#define EM_ARM 40 //!< Advanced RISC Machines ARM +#define EM_FAKE_ALPHA 41 //!< Digital Alpha +#define EM_SH 42 //!< Hitachi SH +#define EM_SPARCV9 43 //!< SPARC Version 9 +#define EM_TRICORE 44 //!< Siemens TriCore embedded processor +#define EM_ARC 45 //!< Argonaut RISC Core, Argonaut Technologies Inc +#define EM_H8_300 46 //!< Hitachi H8/300 +#define EM_H8_300H 47 //!< Hitachi H8/300H +#define EM_H8S 48 //!< Hitachi H8S +#define EM_H8_500 49 //!< Hitachi H8/500 +#define EM_IA_64 50 //!< Intel IA-64 processor architecture +#define EM_MIPS_X 51 //!< Stanford MIPS-X +#define EM_COLDFIRE 52 //!< Motorola ColdFire +#define EM_68HC12 53 //!< Motorola M68HC12 +#define EM_MMA 54 //!< Fujitsu MMA Multimedia Accelerator +#define EM_PCP 55 //!< Siemens PCP +#define EM_NCPU 56 //!< Sony nCPU embedded RISC processor +#define EM_NDR1 57 //!< Denso NDR1 microprocessor +#define EM_STARCORE 58 //!< Motorola Start*Core processor +#define EM_ME16 59 //!< Toyota ME16 processor +#define EM_ST100 60 //!< STMicroelectronics ST100 processor +#define EM_TINYJ 61 //!< Advanced Logic Corp. TinyJ embedded processor family +#define EM_X86_64 62 //!< AMD x86-64 architecture +#define EM_PDSP 63 //!< Sony DSP Processor +#define EM_PDP10 64 //!< Digital Equipment Corp. PDP-10 +#define EM_PDP11 65 //!< Digital Equipment Corp. PDP-11 +#define EM_FX66 66 //!< Siemens FX66 microcontroller +#define EM_ST9PLUS 67 //!< STMicroelectronics ST9+ 8/16 bit microcontroller +#define EM_ST7 68 //!< STMicroelectronics ST7 8-bit microcontroller +#define EM_68HC16 69 //!< Motorola MC68HC16 Microcontroller +#define EM_68HC11 70 //!< Motorola MC68HC11 Microcontroller +#define EM_68HC08 71 //!< Motorola MC68HC08 Microcontroller +#define EM_68HC05 72 //!< Motorola MC68HC05 Microcontroller +#define EM_SVX 73 //!< Silicon Graphics SVx +#define EM_ST19 74 //!< STMicroelectronics ST19 8-bit microcontroller +#define EM_VAX 75 //!< Digital VAX +#define EM_CRIS 76 //!< Axis Communications 32-bit embedded processor +#define EM_JAVELIN 77 //!< Infifineon Technologies 32-bit embedded processor +#define EM_FIREPATH 78 //!< Element 14 64-bit DSP Processor +#define EM_ZSP 79 //!< LSI Logic 16-bit DSP Processor +#define EM_MMIX 80 //!< Donald Knuth's educational 64-bit processor +#define EM_HUANY 81 //!< Harvard University machine-independent object files +#define EM_PRISM 82 //!< SiTera Prism +#define EM_AVR 83 //!< Atmel AVR 8-bit microcontroller +#define EM_FR30 84 //!< Fujitsu FR30 +#define EM_D10V 85 //!< Mitsubishi D10V +#define EM_D30V 86 //!< Mitsubishi D30V +#define EM_V850 87 //!< NEC v850 +#define EM_M32R 88 //!< Mitsubishi M32R +#define EM_MN10300 89 //!< Matsushita MN10300 +#define EM_MN10200 90 //!< Matsushita MN10200 +#define EM_PJ 91 //!< picoJava +#define EM_OPENRISC 92 //!< OpenRISC 32-bit embedded processor +#define EM_ARC_A5 93 //!< ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5) +#define EM_XTENSA 94 //!< Tensilica Xtensa Architecture +#define EM_VIDEOCORE 95 //!< Alphamosaic VideoCore processor +#define EM_TMM_GPP 96 //!< Thompson Multimedia General Purpose Processor +#define EM_NS32K 97 //!< National Semiconductor 32000 series +#define EM_TPC 98 //!< Tenor Network TPC processor +#define EM_SNP1K 99 //!< Trebia SNP 1000 processor +#define EM_ST200 100 //!< STMicroelectronics (www.st.com) ST200 microcontroller +#define EM_IP2K 101 //!< Ubicom IP2xxx microcontroller family +#define EM_MAX 102 //!< MAX Processor +#define EM_CR 103 //!< National Semiconductor CompactRISC microprocessor +#define EM_F2MC16 104 //!< Fujitsu F2MC16 +#define EM_MSP430 105 //!< Texaxas Instruments embedded microcontroller msp430 +#define EM_BLACKFIN 106 //!< Analog Devices Blackfin (DSP) processor +#define EM_SE_C33 107 //!< S1C33 Family of Seiko Epspson processors +#define EM_SEP 108 //!< Sharp embedded microprocessor +#define EM_ARCA 109 //!< Arca RISC Microprocessor +#define EM_UNICORE 110 //!< Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University +#define EM_EXCESS 111 //!< eXcess: 16/32/64-bit configurable embedded CPU +#define EM_DXP 112 //!< Icera Semiconductor Inc. Deep Execution Processor +#define EM_ALTERA_NIOS2 113 //!< Altera Nios II soft-core processor +#define EM_CRX 114 //!< National Semiconductor CompactRISC CRX microprocessor +#define EM_XGATE 115 //!< Motorola XGATE embedded processor +#define EM_C166 116 //!< Infifineon C16x/XC16x processor +#define EM_M16C 117 //!< Renesas M16C series microprocessors +#define EM_DSPIC30F 118 //!< Microchip Technology dsPIC30F Digital Signal Controller +#define EM_CE 119 //!< Freescale Communication Engine RISC core +#define EM_M32C 120 //!< Renesas M32C series microprocessors +#define EM_TSK3000 131 //!< Altium TSK3000 core +#define EM_RS08 132 //!< Freescale RS08 embedded processor +#define EM_ECOG2 134 //!< Cyan Technology eCOG2 microprocessor +#define EM_SCORE7 135 //!< Sunplus S+core7 RISC processor +#define EM_DSP24 136 //!< New Japan Radio (NJR) 24-bit DSP Processor +#define EM_VIDEOCORE3 137 //!< Broadcom VideoCore III processor +#define EM_LATTICEMICO32 138 //!< RISC processor for Lattice FPGA architecture +#define EM_SE_C17 139 //!< Seiko Epspson C17 family +#define EM_TI_C6000 140 //!< The Texaxas Instruments TMS320C6000 DSP family +#define EM_TI_C2000 141 //!< The Texaxas Instruments TMS320C2000 DSP family +#define EM_TI_C5500 142 //!< The Texaxas Instruments TMS320C55x DSP family +#define EM_MMDSP_PLUS 160 //!< STMicroelectronics 64bit VLIW Data Signal Processor +#define EM_CYPRESS_M8C 161 //!< Cypress M8C microprocessor +#define EM_R32C 162 //!< Renesas R32C series microprocessors +#define EM_TRIMEDIA 163 //!< NXP Semiconductors TriMedia architecture family +#define EM_QDSP6 164 //!< QUALCOMM DSP6 Processor +#define EM_8051 165 //!< Intel 8051 and variants +#define EM_STXP7X 166 //!< STMicroelectronics STxP7x family of configurable and extensible RISC processors +#define EM_NDS32 167 //!< Andes Technology compact code size embedded RISC processor family +#define EM_ECOG1 168 //!< Cyan Technology eCOG1X family +#define EM_ECOG1X 168 //!< Cyan Technology eCOG1X family +#define EM_MAXQ30 169 //!< Dallas Semiconductor MAXQ30 Core Micro-controllers +#define EM_XIMO16 170 //!< New Japan Radio (NJR) 16-bit DSP Processor +#define EM_MANIK 171 //!< M2000 Reconfigurable RISC Microprocessor +#define EM_CRAYNV2 172 //!< Cray Inc. NV2 vector architecture +#define EM_RX 173 //!< Renesas RX family +#define EM_METAG 174 //!< Imagination Technologies META processor architecture +#define EM_MCST_ELBRUS 175 //!< MCST Elbrus general purpose hardware architecture +#define EM_ECOG16 176 //!< Cyan Technology eCOG16 family +#define EM_CR16 177 //!< National Semiconductor CompactRISC CR16 16-bit microprocessor +#define EM_ETPU 178 //!< Freescale Extended Time Processing Unit +#define EM_SLE9X 179 //!< Infifineon Technologies SLE9X core +#define EM_AVR32 185 //!< Atmel Corporation 32-bit microprocessor family +#define EM_STM8 186 //!< STMicroeletronics STM8 8-bit microcontroller +#define EM_TILE64 187 //!< Tilera TILE64 multicore architecture family +#define EM_TILEPRO 188 //!< Tilera TILEPro multicore architecture family +#define EM_MICROBLAZE 189 //!< Xilinx MicroBlaze 32-bit RISC soft processor core +#define EM_CUDA 190 //!< NVIDIA CUDA architecture +#define EM_TILEGX 191 //!< Tilera TILE-Gx multicore architecture family + +/* + * e_version (version) + */ +#define EV_NONE 0 //!< Invalid version +#define EV_CURRENT 1 //!< Current version + + +/********************************************* + * Section + *********************************************/ +typedef struct +{ + Elf32_Word sh_name; //!< This member specifies the name of the section + Elf32_Word sh_type; //!< This member categorizes the section's contents and semantics + Elf32_Word sh_flags; //!< Sections support 1-bit flags that describe miscellaneous attributes + Elf32_Addr sh_addr; //!< If the section will appear in the memory image of a process, this member gives the address at which the section's first byte should reside + Elf32_Off sh_offset; //!< This member's value gives the byte offset from the beginning of the file to the first byte in the section + Elf32_Word sh_size; //!< This member gives the section's size in bytes + Elf32_Word sh_link; //!< This member holds a section header table index link, whose interpretation depends on the section type + Elf32_Word sh_info; //!< This member holds extra information, whose interpretation depends on the section type + Elf32_Word sh_addralign; //!< Some sections have address alignment constraints + Elf32_Word sh_entsize; //!< Some sections hold a table of fixed-size entries, such as a symbol table +} Elf32_Shdr; //!< 32bit Section header + +typedef struct +{ + Elf64_Word sh_name; //!< This member specifies the name of the section + Elf64_Word sh_type; //!< This member categorizes the section's contents and semantics + Elf64_Xword sh_flags; //!< Sections support 1-bit flags that describe miscellaneous attributes + Elf64_Addr sh_addr; //!< If the section will appear in the memory image of a process, this member gives the address at which the section's first byte should reside + Elf64_Off sh_offset; //!< This member's value gives the byte offset from the beginning of the file to the first byte in the section + Elf64_Xword sh_size; //!< This member gives the section's size in bytes + Elf64_Word sh_link; //!< This member holds a section header table index link, whose interpretation depends on the section type + Elf64_Word sh_info; //!< This member holds extra information, whose interpretation depends on the section type + Elf64_Xword sh_addralign; //!< Some sections have address alignment constraints + Elf64_Xword sh_entsize; //!< Some sections hold a table of fixed-size entries, such as a symbol table +} Elf64_Shdr; //!< 64bit Section header + +/* + * Special Section Indexes + */ +#define SHN_UNDEF 0 //!< This value marks an undefined, missing, irrelevant, or otherwise meaningless section reference +#define SHN_LORESERVE 0xff00 //!< This value specifies the lower bound of the range of reserved indexes +#define SHN_LOPROC 0xff00 //!< Values in this inclusive range are reserved for processor-specific semantics +#define SHN_HIPROC 0xff1f //!< Values in this inclusive range are reserved for processor-specific semantics +#define SHN_LOOS 0xff20 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define SHN_HIOS 0xff3f //!< Values in this inclusive range are reserved for operating system-specific semantics +#define SHN_ABS 0xfff1 //!< This value specifies absolute values for the corresponding reference +#define SHN_COMMON 0xfff2 //!< Symbols defined relative to this section are common symbols +#define SHN_XINDEX 0xffff //!< This value is an escape value +#define SHN_HIRESERVE 0xffff //!< This value specifies the upper bound of the range of reserved indexes + +/* + * sh_type + */ +#define SHT_NULL 0 //!< This value marks the section header as inactive +#define SHT_PROGBITS 1 //!< The section holds information defined by the program +#define SHT_SYMTAB 2 //!< These sections hold a symbol table +#define SHT_STRTAB 3 //!< The section holds a string table +#define SHT_RELA 4 //!< The section holds relocation entries with explicit addends, such as type Elf32_Rela for the 32-bit class of object files or type Elf64_Rela for the 64-bit class of object files +#define SHT_HASH 5 //!< The section holds a symbol hash table +#define SHT_DYNAMIC 6 //!< The section holds information for dynamic linking +#define SHT_NOTE 7 //!< The section holds information that marks the file in some way +#define SHT_NOBITS 8 //!< A section of this type occupies no space in the file but otherwise resembles SHT_PROGBITS +#define SHT_REL 9 //!< The section holds relocation entries without explicit addends, such as type Elf32_Rel for the 32-bit class of object files or type Elf64_Rel for the 64-bit class of object files +#define SHT_SHLIB 10 //!< This section type is reserved but has unspecified semantics +#define SHT_DYNSYM 11 //!< +#define SHT_INIT_ARRAY 14 //!< This section contains an array of pointers to initialization functions +#define SHT_FINI_ARRAY 15 //!< This section contains an array of pointers to termination functions +#define SHT_PREINIT_ARRAY 16 //!< This section contains an array of pointers to functions that are invoked before all other initialization functions +#define SHT_GROUP 17 //!< This section defines a section group +#define SHT_SYMTAB_SHNDX 18 //!< This section is associated with a section of type SHT_SYMTAB and is required if any of the section header indexes referenced by that symbol table contain the escape value SHN_XINDEX +#define SHT_LOOS 0x60000000 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define SHT_HIOS 0x6fffffff //!< Values in this inclusive range are reserved for operating system-specific semantics +#define SHT_LOPROC 0x70000000 //!< Values in this inclusive range are reserved for processor-specific semantics +#define SHT_HIPROC 0x7fffffff //!< Values in this inclusive range are reserved for processor-specific semantics +#define SHT_LOUSER 0x80000000 //!< This value specifies the upper bound of the range of indexes reserved for application programs +#define SHT_HIUSER 0x8fffffff //!< This value specifies the upper bound of the range of indexes reserved for application programs + +/* + * sh_flags + */ +#define SHF_WRITE 0x1 //!< The section contains data that should be writable during process execution +#define SHF_ALLOC 0x2 //!< The section occupies memory during process execution +#define SHF_EXECINSTR 0x4 //!< The section contains executable machine instructions +#define SHF_MERGE 0x10 //!< The data in the section may be merged to eliminate duplication +#define SHF_STRINGS 0x20 //!< The data elements in the section consist of null-terminated character strings +#define SHF_INFO_LINK 0x40 //!< The sh_info field of this section header holds a section header table index +#define SHF_LINK_ORDER 0x80 //!< This flag adds special ordering requirements for link editors +#define SHF_OS_NONCONFORMING 0x100 //!< This section requires special OS-specific processing (beyond the standard linking rules) to avoid incorrect behavior +#define SHF_GROUP 0x200 //!< This section is a member (perhaps the only one) of a section group +#define SHF_TLS 0x400 //!< This section holds Thread-Local Storage, meaning that each separate execution flow has its own distinct instance of this data +#define SHF_MASKOS 0x0ff00000 //!< All bits included in this mask are reserved for operating system-specific semantics +#define SHF_MASKPROC 0xf0000000 //!< All bits included in this mask are reserved for processor-specific semantics + + +/********************************************* + * Symbol + *********************************************/ +typedef struct +{ + Elf32_Word st_name; //!< This member holds an index into the object file's symbol string table, which holds the character representations of the symbol names + Elf32_Addr st_value; //!< This member gives the value of the associated symbol + Elf32_Word st_size; //!< Many symbols have associated sizes + unsigned char st_info; //!< This member specifies the symbol's type and binding attributes + unsigned char st_other; //!< This member currently specifies a symbol's visibility + Elf32_Section st_shndx; //!< Every symbol table entry is defined in relation to some section +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; //!< This member holds an index into the object file's symbol string table, which holds the character representations of the symbol names + unsigned char st_info; //!< This member specifies the symbol's type and binding attributes + unsigned char st_other; //!< This member currently specifies a symbol's visibility + Elf64_Section st_shndx; //!< Every symbol table entry is defined in relation to some section + Elf64_Addr st_value; //!< This member gives the value of the associated symbol + Elf64_Xword st_size; //!< Many symbols have associated sizes +} Elf64_Sym; + +/* + * st_info + */ +#define ELF32_ST_BIND(i) ((i)>>4) +#define ELF32_ST_TYPE(i) ((i)&0xf) +#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + +#define ELF64_ST_BIND(i) ((i)>>4) +#define ELF64_ST_TYPE(i) ((i)&0xf) +#define ELF64_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) + + +/* st_info (symbol binding) */ +#define STB_LOCAL 0 //!< Local symbols are not visible outside the object file containing their definition +#define STB_GLOBAL 1 //!< Global symbols are visible to all object files being combined +#define STB_WEAK 2 //!< Weak symbols resemble global symbols, but their definitions have lower precedence +#define STB_LOOS 10 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define STB_HIOS 12 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define STB_LOPROC 13 //!< Values in this inclusive range are reserved for processor-specific semantics +#define STB_HIPROC 15 //!< Values in this inclusive range are reserved for processor-specific semantics + +/* st_info (symbol type) */ +#define STT_NOTYPE 0 //!< The symbol's type is not specified +#define STT_OBJECT 1 //!< The symbol is associated with a data object, such as a variable, an array, and so on +#define STT_FUNC 2 //!< The symbol is associated with a function or other executable code +#define STT_SECTION 3 //!< The symbol is associated with a section +#define STT_FILE 4 //!< Conventionally, the symbol's name gives the name of the source file associated with the object file +#define STT_COMMON 5 //!< The symbol labels an uninitialized common block +#define STT_TLS 6 //!< The symbol specifies a Thread-Local Storage entity +#define STT_LOOS 10 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define STT_HIOS 12 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define STT_LOPROC 13 //!< Values in this inclusive range are reserved for processor-specific semantics +#define STT_HIPROC 15 //!< Values in this inclusive range are reserved for processor-specific semantics + +/* + * st_other + */ +#define ELF32_ST_VISIBILITY(o) ((o)&0x3) +#define ELF64_ST_VISIBILITY(o) ((o)&0x3) + + +#define STV_DEFAULT 0 //!< The visibility of symbols with the STV_DEFAULT attribute is as specified by the symbol's binding type +#define STV_INTERNAL 1 //!< A symbol defined in the current component is protected if it is visible in other components but not preemptable, meaning that any reference to such a symbol from within the defining component must be resolved to the definition in that component, even if there is a definition in another component that would preempt by the default rules +#define STV_HIDDEN 2 //!< A symbol defined in the current component is hidden if its name is not visible to other components +#define STV_PROTECTED 3 //!< The meaning of this visibility attribute may be defined by processor supplements to further constrain hidden symbols + + +/********************************************* + * Relocation + *********************************************/ +typedef struct +{ + Elf32_Addr r_offset; //!< This member gives the location at which to apply the relocation action + Elf32_Word r_info; //!< This member gives both the symbol table index with respect to which the relocation must be made, and the type of relocation to apply +} Elf32_Rel; //!< 32bits Relocation Entries + +typedef struct +{ + Elf64_Addr r_offset; //!< This member gives the location at which to apply the relocation action + Elf64_Xword r_info; //!< This member gives both the symbol table index with respect to which the relocation must be made, and the type of relocation to apply +} Elf64_Rel; //!< 32bits Relocation Entries + +typedef struct +{ + Elf32_Addr r_offset; //!< This member gives the location at which to apply the relocation action + Elf32_Word r_info; //!< This member gives both the symbol table index with respect to which the relocation must be made, and the type of relocation to apply + Elf32_Sword r_addend; //!< This member specifies a constant addend used to compute the value to be stored into the relocatable field +} Elf32_Rela; //!< 32bits Relocation Addend Entries + +typedef struct +{ + Elf64_Addr r_offset; //!< This member gives the location at which to apply the relocation action + Elf64_Xword r_info; //!< This member gives both the symbol table index with respect to which the relocation must be made, and the type of relocation to apply + Elf64_Sxword r_addend; //!< This member specifies a constant addend used to compute the value to be stored into the relocatable field +} Elf64_Rela; //!< 32bits Relocation Addend Entries + + +/* + * r_info + */ +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) + +#define ELF64_R_SYM(i) ((i)>>32) +#define ELF64_R_TYPE(i) ((i)&0xffffffffL) +#define ELF64_R_INFO(s,t) (((s)<<32)+((t)&0xffffffffL)) + + + +/********************************************* + * Program + *********************************************/ +typedef struct +{ + Elf32_Word p_type; //!< This member tells what kind of segment this array element describes or how to interpret the array element's information + Elf32_Off p_offset; //!< This member gives the offset from the beginning of the file at which the first byte of the segment resides + Elf32_Addr p_vaddr; //!< This member gives the virtual address at which the first byte of the segment resides in memory + Elf32_Addr p_paddr; //!< On systems for which physical addressing is relevant, this member is reserved for the segment's physical address + Elf32_Word p_filesz; //!< This member gives the number of bytes in the file image of the segment; it may be zero + Elf32_Word p_memsz; //!< This member gives the number of bytes in the memory image of the segment; it may be zero + Elf32_Word p_flags; //!< This member gives flags relevant to the segment + Elf32_Word p_align; //!< As ``Program Loading'' describes in this chapter of the processor supplement, loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size +} Elf32_Phdr; //!< 32bits Program header + +typedef struct +{ + Elf64_Word p_type; //!< This member tells what kind of segment this array element describes or how to interpret the array element's information + Elf64_Word p_flags; //!< This member gives flags relevant to the segment + Elf64_Off p_offset; //!< This member gives the offset from the beginning of the file at which the first byte of the segment resides + Elf64_Addr p_vaddr; //!< This member gives the virtual address at which the first byte of the segment resides in memory + Elf64_Addr p_paddr; //!< On systems for which physical addressing is relevant, this member is reserved for the segment's physical address + Elf64_Xword p_filesz; //!< This member gives the number of bytes in the file image of the segment; it may be zero + Elf64_Xword p_memsz; //!< This member gives the number of bytes in the memory image of the segment; it may be zero + Elf64_Xword p_align; //!< As ``Program Loading'' describes in this chapter of the processor supplement, loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size +} Elf64_Phdr; //!< 64bits Program header + +/* + * p_type + */ +#define PT_NULL 0 //!< The array element is unused; other members' values are undefined +#define PT_LOAD 1 //!< The array element specifies a loadable segment, described by p_filesz and p_memsz +#define PT_DYNAMIC 2 //!< The array element specifies dynamic linking information +#define PT_INTERP 3 //!< The array element specifies the location and size of a null-terminated path name to invoke as an interpreter +#define PT_NOTE 4 //!< The array element specifies the location and size of auxiliary information +#define PT_SHLIB 5 //!< This segment type is reserved but has unspecified semantics +#define PT_PHDR 6 //!< The array element, if present, specifies the location and size of the program header table itself, both in the file and in the memory image of the program +#define PT_TLS 7 //!< The array element specifies the Thread-Local Storage template +#define PT_LOOS 0x60000000 //!< Values in this inclusive range are reserved for operating system-specific semantics +#define PT_HIOS 0x6fffffff //!< Values in this inclusive range are reserved for operating system-specific semantics +#define PT_LOPROC 0x70000000 //!< Values in this inclusive range are reserved for processor-specific semantics +#define PT_HIPROC 0x7fffffff //!< Values in this inclusive range are reserved for processor-specific semantics + +/* + * p_flags + */ +#define PF_X (1 << 0) //!< Execute +#define PF_W (1 << 1) //!< Write +#define PF_R (1 << 2) //!< Read +#define PF_MASKOS 0x0ff00000 //!< Unspecified +#define PF_MASKPROC 0xf0000000 //!< Unspecified + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h new file mode 100644 index 00000000000..564086db26c --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h @@ -0,0 +1,123 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf loder internal methods. + * + * \defgroup ELFLOADER MMDSP ELF loader. + */ +#ifndef __INC_CM_ELFLOADER_H +#define __INC_CM_ELFLOADER_H + +#include + +/*! + * \internal + * \brief ELF Parsing & checking + * \ingroup ELFLOADER + */ +t_cm_error cm_ELF_CheckFile( + const char *elfdata, + t_bool temporaryDescription, + t_elfdescription **elfhandlePtr); + +void cm_ELF_ReleaseDescription( + t_uint32 requireNumber, t_interface_require *requires, + t_uint32 attributeNumber, t_attribute *attributes, + t_uint32 propertyNumber, t_property *properties, + t_uint32 provideNumber, t_interface_provide *provides); + +/*! + * \internal + * \brief ELF closing + * \ingroup ELFLOADER + */ +void cm_ELF_CloseFile( + t_bool temporaryDescription, + t_elfdescription *elfhandle); + +/*! + * \internal + * \brief Load a component template shared memories. + * + * \note In case of error, part of memory could have been allocated and must be free by calling cm_DSPABI_FreeTemplate. + */ +t_cm_error cm_ELF_LoadTemplate( + t_cm_domain_id domainId, + t_elfdescription *elfhandle, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]); + +/*! + * \internal + * \brief Clean cache memory of a component template shared code. + */ +void cm_ELF_FlushTemplate( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]); + +void cm_ELF_FlushInstance( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]); + +/*! + * \internal + * \brief Load a component instance private memories. + * + * \note In case of error, part of memory could have been allocated and must be free by calling cm_DSPABI_FreeInstance. + */ +t_cm_error cm_ELF_LoadInstance( + t_cm_domain_id domainId, + t_elfdescription *elfhandle, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]); + +void cm_ELF_FreeInstance( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]); +void cm_ELF_FreeTemplate( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]); + + +t_cm_error cm_ELF_relocateSharedSegments( + t_memory_handle *memories, + t_elfdescription *elfhandle, + void *cbContext); +t_cm_error cm_ELF_relocatePrivateSegments( + t_memory_handle *memories, + t_elfdescription *elfhandle, + void *cbContext); +void cm_ELF_performRelocation( + t_uint32 type, + const char *symbol_name, + t_uint32 symbol_addr, + char *reloc_addr); +t_cm_error cm_ELF_GetMemory( + t_elfdescription *elf, + t_tmp_elfdescription *elftmp, + t_uint32 address, + t_memory_purpose purpose, + t_memory_reference *memory); + + +#include + +t_cm_error cm_DSPABI_AddLoadMap( + t_cm_domain_id domainId, + const char* templateName, + const char* localname, + t_memory_handle *memories, + void *componentHandle); +t_cm_error cm_DSPABI_RemoveLoadMap( + t_cm_domain_id domainId, + const char* templateName, + t_memory_handle *memories, + const char* localname, + void *componentHandle); + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/memory.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/memory.h new file mode 100644 index 00000000000..9eab94f173c --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/memory.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf memory. + */ +#ifndef __INC_CM_ELF_MEMORY_H +#define __INC_CM_ELF_MEMORY_H + +#include + +/** + * \brief Memory identifier + */ +typedef t_uint8 t_memory_id; + +/** + * \brief Memory property + */ +typedef enum { + MEM_FOR_MULTIINSTANCE, + MEM_FOR_SINGLETON, + MEM_FOR_LAST +} t_instance_property; + +/** + * \brief Memory prupose (for processor with different address space for code and data/ + */ +typedef enum { + MEM_CODE, + MEM_DATA +} t_memory_purpose; + +/** + * \brief Memory property + */ +typedef enum { + MEM_PRIVATE, + MEM_SHARABLE, +} t_memory_property; + +/** + * \brief Elf memory mapping description + */ +typedef struct +{ + t_memory_id id; + t_dsp_memory_type_id dspMemType; + t_uint32 startAddr; + t_cm_memory_alignment memAlignement; + t_memory_property property; + t_memory_purpose purpose; + t_uint8 fileEntSize; + t_uint8 memEntSize; + char* memoryName; +} t_elfmemory; + +#define NUMBER_OF_MMDSP_MEMORY 15 + +/* + * \brief Elf segment description + */ +typedef struct { + // Data in Bytes + t_uint32 sumSize; + t_bool sumSizeSetted; + t_cm_logical_address hostAddr; // Valid only if section Load in memory + t_uint32 maxAlign; + // Data in word + t_uint32 mpcAddr; // Valid only if section Load in memory +} t_elfSegment; + + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h new file mode 100644 index 00000000000..78b00388802 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf writer internal methods. + * + * \defgroup LOADMAP MMDSP ELF writer (a linker in fact). + */ +#ifndef __INC_CM_LOADMAP_H +#define __INC_CM_LOADMAP_H + +#include + +/* + * Align with loadmap : + * https://codex.cro.st.com/wiki/index.php?pagename=Specification%2FLoadmap%2Fv1.2&group_id=310 + */ +#define LOADMAP_MAGIC_NUMBER 0xFBBF + +#define LOADMAP_VERSION_MSB 1 +#define LOADMAP_VERSION_LSB 2 + +struct LoadMapItem +{ + const char* pSolibFilename; // Filename of shared library object + void* pAddrProg; // Load address of program section + void* pAddrEmbProg; // Load address of embedded program section + void* pThis; // Data base address of component instance + void* pARMThis; // ARM component debug ID + const char* pComponentName; // Pretty name of the component instance, NULL if none. + struct LoadMapItem* pNextItem;// Pointer on the next list item, NULL if last one. + void* pXROM; // Start address of XROM + void* pYROM; // Start address of YROM + + void* memHandle; // handle of allocated memory for this structure and name, local field not use by mmdsp +}; + +struct LoadMapHdr +{ + t_uint16 nMagicNumber; // Equal to 0xFBBF. + t_uint16 nVersion; // The version of the load map format. + t_uint32 nRevision; // A counter incremented at each load map list modification. + struct LoadMapItem* pFirstItem;// Pointer on the first item, NULL if no shared library loaded. +}; + +#endif /* __INC_CM_LOADMAP_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp.h new file mode 100644 index 00000000000..1662def6c1a --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief MMDSP elf. + */ +#ifndef __INC_CM_ELF_MMDSP_H +#define __INC_CM_ELF_MMDSP_H + +#include + +#define CODE_MEMORY_INDEX 0 +#define ECODE_MEMORY_INDEX 7 + +#define XROM_MEMORY_INDEX 1 +#define YROM_MEMORY_INDEX 2 +#define PRIVATE_DATA_MEMORY_INDEX 8 +#define SHARE_DATA_MEMORY_INDEX 1 + +/* + * Relocation + */ +#define R_MMDSP_IMM16 5 +#define R_MMDSP_IMM20_16 6 +#define R_MMDSP_IMM20_4 7 +#define R_MMDSP_24 13 + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/mpcal.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/mpcal.h new file mode 100644 index 00000000000..718b7f61ceb --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/mpcal.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief MPC Abraction Layer. + * + * \defgroup MPCAL MPC Abraction Layer. + */ +#ifndef __INC_CM_DSP_MPCAL_H +#define __INC_CM_DSP_MPCAL_H + +#include +#include + +#include + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/reloc.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/reloc.h new file mode 100644 index 00000000000..b38be48d689 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/reloc.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Elf relocation. + */ +#ifndef __INC_CM_ELF_RELOC_H +#define __INC_CM_ELF_RELOC_H + + +void MMDSP_performRelocation( + t_uint32 type, + const char* symbol_name, + t_uint32 symbol_addr, + char* reloc_addr, + const char* inPlaceAddr, + t_uint32 reloc_offset); + +/* + * + * Return: + * 0x0 returned if symbol not found + * 0xFFFFFFFE returned if out of memory + * 0xFFFFFFFF returned if symbol found in static required binding + */ +typedef t_uint32 (*CBresolvSymbol)( + void* context, + t_uint32 type, + const char* symbolName, + char* reloc_addr); + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c new file mode 100644 index 00000000000..2e0f5928ffd --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elf64.c @@ -0,0 +1,47 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include + +#include +#include + +typedef Elf64_Half ElfXX_Half; +typedef Elf64_Word ElfXX_Word; +typedef Elf64_Addr ElfXX_Addr; +typedef Elf64_Off ElfXX_Off; + +typedef Elf64_Xword ElfXX_Xword; + +typedef Elf64_Ehdr ElfXX_Ehdr; +typedef Elf64_Shdr ElfXX_Shdr; +typedef Elf64_Sym ElfXX_Sym; +typedef Elf64_Rela ElfXX_Rela; + +#undef ELFXX_R_SYM +#define ELFXX_R_SYM ELF64_R_SYM +#undef ELFXX_R_TYPE +#define ELFXX_R_TYPE ELF64_R_TYPE +#undef ELFXX_R_INFO +#define ELFXX_R_INFO ELF64_R_INFO + +// TODO Here we assume big endian (MMDSP !) +static Elf64_Half swapHalf(Elf64_Half half) +{ + return (Elf64_Half)swap16(half); +} + +static Elf64_Word swapWord(Elf64_Word word) +{ + return (Elf64_Word)swap32(word); +} + +static Elf64_Xword swapXword(Elf64_Xword xword) +{ + return (Elf64_Xword)swap64(xword); +} + +#include "elfxx.c" diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c new file mode 100644 index 00000000000..2efe6edbf69 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c @@ -0,0 +1,749 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include +#include +#include + +//#include + +#include +#include +#include +#include + +static void* getElfHeaderReference(t_tmp_elfdescription *elftmp, void* hdrref) +{ + if(hdrref != NULL) + return (void*)((int)swap32((t_uint32)hdrref) + (int)elftmp->elfheader); + else + return NULL; +} + +static t_dup_char copyElfString(t_tmp_elfdescription *elftmp, char* idx) +{ + return cm_StringDuplicate((char*)getElfHeaderReference(elftmp, (void*)idx)); +} + +static t_cm_error getMemoryOffset( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp, + t_memory_purpose purpose, + const t_uint32 *addressInNmf, + t_memory_reference *memory) { + + if(elftmp->isExecutable) { + return cm_ELF_GetMemory(elfhandle, elftmp, + swap32(*addressInNmf), + purpose, + memory); + } else { + return ELF64_getRelocationMemory(elfhandle, elftmp, + (t_uint32)addressInNmf - (t_uint32)elftmp->elfheader, + memory); + } +} + +static t_cm_error getAdressForExecutableOffsetElsewhere( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp, + const t_uint32 *addressInNmf, + t_memory_reference *memory) { + t_uint32 address; + + address = swap32(*addressInNmf); + if(address == 0xFFFFFFFF) + { + memory->offset = 0x0; + memory->memory = NULL; + return CM_OK; + } + + if(elftmp->isExecutable) + { + memory->offset = address; + memory->memory = NULL; + return CM_OK; + } + + // Error log in elfhandle by previous call will be check in loadTemplate + return ELF64_getRelocationMemory(elfhandle, elftmp, + (t_uint32)addressInNmf - (t_uint32)elftmp->elfheader, + memory); +} + +/* + * Interface Management + */ +static t_interface_description* interfaceList = NULL; + +static t_interface_description* getInterfaceDescription(t_tmp_elfdescription *elftmp, t_elf_interface_description* elfitf) { + t_dup_char itfType; + t_interface_description* itf; + int i; + + itfType = copyElfString(elftmp, elfitf->type); + if(itfType == NULL) + return NULL; + + // Search if interfane already loaded + for(itf = interfaceList; itf != NULL; itf = itf->next) { + if(itf->type == itfType) { + // TODO Sanity check + + itf->referenceCounter++; + cm_StringRelease(itfType); + return itf; + } + } + + // Create a new interface if not exists + itf = (t_interface_description*)OSAL_Alloc_Zero(sizeof(t_interface_description) + sizeof(char*) * (elfitf->methodNumber /*- 1*/)); + if(itf == NULL) + goto out_itf_type; + itf->referenceCounter = 1; + itf->type = itfType; + itf->methodNumber = elfitf->methodNumber; + for(i = 0; i < itf->methodNumber; i++) { + itf->methodNames[i] = copyElfString(elftmp, elfitf->methodNames[i]); + if(itf->methodNames[i] == NULL) + goto out_method; + } + + // Put it in Top + itf->next = interfaceList; + interfaceList = itf; + + return itf; + +out_method: + for(i = 0; i < itf->methodNumber; i++) + cm_StringRelease(itf->methodNames[i]); + OSAL_Free(itf); +out_itf_type: + cm_StringRelease(itfType); + return NULL; +} + +static void releaseInterfaceDescription(t_interface_description* itf) { + if(itf == NULL) + return; + + if(--itf->referenceCounter == 0) { + int i; + + // Remove it from list + if(interfaceList == itf) { + interfaceList = interfaceList->next; + } else { + t_interface_description* prev = interfaceList; + while(prev->next != itf) + prev = prev->next; + prev->next = itf->next; + } + + // Destroy interface description + for(i = 0; i < itf->methodNumber; i++) { + cm_StringRelease(itf->methodNames[i]); + } + cm_StringRelease(itf->type); + OSAL_Free(itf); + } +} + + +t_cm_error cm_ELF_CheckFile( + const char *elfdata, + t_bool temporaryDescription, + t_elfdescription **elfhandlePtr) +{ + t_elfdescription *elfhandle; + t_tmp_elfdescription elftmp; + t_cm_error error; + t_uint32 version; + t_uint32 compatibleVersion; + int i, j, k; + + /* + * Sanity check + */ + if (elfdata[EI_MAG0] != ELFMAG0 || + elfdata[EI_MAG1] != ELFMAG1 || + elfdata[EI_MAG2] != ELFMAG2 || + elfdata[EI_MAG3] != ELFMAG3 || + elfdata[EI_CLASS] != ELFCLASS64) + { + ERROR("CM_INVALID_ELF_FILE: component file is not a MMDSP ELF file\n", 0, 0, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; + } + + /* + * Create elf data + */ + if((error = ELF64_LoadComponent(EM_MMDSP_PLUS, elfdata, elfhandlePtr, &elftmp)) != CM_OK) + return error; + + elfhandle = *elfhandlePtr; + + elfhandle->temporaryDescription = temporaryDescription; + + version = swap32(elftmp.elfheader->nmfVersion); + + compatibleVersion = (VERSION_MAJOR(version) == VERSION_MAJOR(NMF_VERSION)); + if(compatibleVersion) + { + switch(VERSION_MINOR(NMF_VERSION)) + { + case 10: // Compatible with 2.9, 2.10 + compatibleVersion = + (VERSION_MINOR(version) == 9) || + (VERSION_MINOR(version) == 10); + break; + default: // Strict compatibility 2.x == 2.x + compatibleVersion = (VERSION_MINOR(version) == VERSION_MINOR(NMF_VERSION)); + } + } + + if(! compatibleVersion) + { + ERROR("CM_INVALID_ELF_FILE: incompatible version for Component %d.%d.x != CM:%d.%d.x\n", + VERSION_MAJOR(version), VERSION_MINOR(version), + VERSION_MAJOR(NMF_VERSION), VERSION_MINOR(NMF_VERSION), 0, 0); + error = CM_INVALID_ELF_FILE; + goto onerror; + } + + + /* + * Commented since to many noise !!!! + if(VERSION_PATCH(version) != VERSION_PATCH(NMF_VERSION)) + { + WARNING("CM_INVALID_ELF_FILE: incompatible version, Component:%d.%d.%d != CM:%d.%d.%d\n", + VERSION_MAJOR(version), VERSION_MINOR(version), VERSION_PATCH(version), + VERSION_MAJOR(NMF_VERSION), VERSION_MINOR(NMF_VERSION), VERSION_PATCH(NMF_VERSION)); + } + */ + + if((error = ELF64_ComputeSegment(elfhandle, &elftmp)) != CM_OK) + goto onerror; + + // + elfhandle->foundedTemplateName = copyElfString(&elftmp, elftmp.elfheader->templateName); + if(elfhandle->foundedTemplateName == NULL) + goto oom; + elfhandle->minStackSize = swap32(elftmp.elfheader->minStackSize); + + // Get Life-cycle memory + if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCConstruct, &elfhandle->memoryForConstruct)) != CM_OK) + goto onerror; + if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCStart, &elfhandle->memoryForStart)) != CM_OK) + goto onerror; + if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCStop, &elfhandle->memoryForStop)) != CM_OK) + goto onerror; + if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, &elftmp.elfheader->LCCDestroy, &elfhandle->memoryForDestroy)) != CM_OK) + goto onerror; + + // Copy attributes information + elfhandle->attributeNumber = swap32(elftmp.elfheader->attributeNumber); + if(elfhandle->attributeNumber > 0) + { + elfhandle->attributes = + (t_attribute*)OSAL_Alloc_Zero(sizeof(t_attribute) * elfhandle->attributeNumber); + if(elfhandle->attributes == NULL) + goto oom; + + if(elfhandle->attributeNumber > 0) + { + t_elf_attribute *attributes = (t_elf_attribute*)getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->attributes); + + for(i = 0; i < elfhandle->attributeNumber; i++) + { + elfhandle->attributes[i].name = copyElfString(&elftmp, attributes[i].name); + if(elfhandle->attributes[i].name == NULL) + goto oom; + + if((error = getMemoryOffset(elfhandle, &elftmp, + MEM_DATA, + &attributes[i].symbols, + &elfhandle->attributes[i].memory)) != CM_OK) + goto onerror; + LOG_INTERNAL(2, " attribute %s mem=%s offset=%x\n", + elfhandle->attributes[i].name, + elfhandle->attributes[i].memory.memory->memoryName, + elfhandle->attributes[i].memory.offset, + 0, 0, 0); + } + } + } + + // Copy properties information + elfhandle->propertyNumber = swap32(elftmp.elfheader->propertyNumber); + if(elfhandle->propertyNumber > 0) + { + elfhandle->properties = + (t_property*)OSAL_Alloc_Zero(sizeof(t_property) * elfhandle->propertyNumber); + if(elfhandle->properties == NULL) + goto oom; + + if(elfhandle->propertyNumber > 0) + { + t_elf_property *properties = (t_elf_property*)getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->properties); + + for(i = 0; i < elfhandle->propertyNumber; i++) + { + elfhandle->properties[i].name = copyElfString(&elftmp, properties[i].name); + if(elfhandle->properties[i].name == NULL) + goto oom; + + elfhandle->properties[i].value = copyElfString(&elftmp, properties[i].value); + if(elfhandle->properties[i].value == NULL) + goto oom; + + LOG_INTERNAL(3, " property %s = %s\n", + elfhandle->properties[i].name, + elfhandle->properties[i].value, + 0, 0, 0, 0); + } + } + } + + // Copy requires information + elfhandle->requireNumber = swap32(elftmp.elfheader->requireNumber); + if(elfhandle->requireNumber > 0) + { + char *ref = getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->requires); + + elfhandle->requires = (t_interface_require*)OSAL_Alloc_Zero(sizeof(t_interface_require) * elfhandle->requireNumber); + if(elfhandle->requires == NULL) + goto oom; + + for(i = 0; i < elfhandle->requireNumber; i++) + { + t_elf_required_interface *require = (t_elf_required_interface*)ref; + t_elf_interface_description *interface = (t_elf_interface_description*)getElfHeaderReference(&elftmp, (void*)require->interface); + + elfhandle->requires[i].name = copyElfString(&elftmp, require->name); + if(elfhandle->requires[i].name == NULL) + goto oom; + + elfhandle->requires[i].requireTypes = require->requireTypes; + elfhandle->requires[i].collectionSize = require->collectionSize; + elfhandle->requires[i].interface = getInterfaceDescription(&elftmp, interface); + if(elfhandle->requires[i].interface == NULL) + goto oom; + + LOG_INTERNAL(2, " require %s <%s> %x\n", + elfhandle->requires[i].name, + elfhandle->requires[i].interface->type, + elfhandle->requires[i].requireTypes, 0, 0, 0); + CM_ASSERT(elfhandle->requires[i].collectionSize != 0); + + ref += sizeof(t_elf_required_interface); + + if((elfhandle->requires[i].requireTypes & VIRTUAL_REQUIRE) == 0 && + (elfhandle->requires[i].requireTypes & STATIC_REQUIRE) == 0) + { + elfhandle->requires[i].indexes = + (t_interface_require_index*)OSAL_Alloc_Zero(sizeof(t_interface_require_index) * elfhandle->requires[i].collectionSize); + if(elfhandle->requires[i].indexes == NULL) + goto oom; + + for(j = 0; j < elfhandle->requires[i].collectionSize; j++) + { + t_elf_interface_require_index* index = (t_elf_interface_require_index*)ref; + + elfhandle->requires[i].indexes[j].numberOfClient = swap32(index->numberOfClient); + if(elfhandle->requires[i].indexes[j].numberOfClient != 0) + { + elfhandle->requires[i].indexes[j].memories = + (t_memory_reference*)OSAL_Alloc(sizeof(t_memory_reference) * elfhandle->requires[i].indexes[j].numberOfClient); + if(elfhandle->requires[i].indexes[j].memories == NULL) + goto oom; + + for(k = 0; k < elfhandle->requires[i].indexes[j].numberOfClient; k++) { + if((error = getMemoryOffset(elfhandle,&elftmp, + MEM_DATA, + &index->symbols[k], + &elfhandle->requires[i].indexes[j].memories[k])) != CM_OK) + goto onerror; + LOG_INTERNAL(2, " [%d, %d] mem=%s offset=%x\n", + j, k, + elfhandle->requires[i].indexes[j].memories[k].memory->memoryName, + elfhandle->requires[i].indexes[j].memories[k].offset, + 0, 0); + } + } + + ref += sizeof(index->numberOfClient) + elfhandle->requires[i].indexes[j].numberOfClient * sizeof(index->symbols[0]); + } + } + } + } + + // Copy provides informations + elfhandle->provideNumber = swap32(elftmp.elfheader->provideNumber); + if(elfhandle->provideNumber != 0) + { + elfhandle->provides = + (t_interface_provide*)OSAL_Alloc_Zero(sizeof(t_interface_provide) * elfhandle->provideNumber); + if(elfhandle->provides == NULL) + goto oom; + + if(elfhandle->provideNumber > 0) + { + char *ref = getElfHeaderReference(&elftmp, (void*)elftmp.elfheader->provides); + + for(i = 0; i < elfhandle->provideNumber; i++) + { + t_elf_provided_interface *provide = (t_elf_provided_interface*)ref; + t_elf_interface_description *interface = (t_elf_interface_description*)getElfHeaderReference(&elftmp, (void*)provide->interface); + + elfhandle->provides[i].name = copyElfString(&elftmp, provide->name); + if(elfhandle->provides[i].name == NULL) + goto oom; + + elfhandle->provides[i].provideTypes = provide->provideTypes; + elfhandle->provides[i].interruptLine = provide->interruptLine; + elfhandle->provides[i].collectionSize = provide->collectionSize; + elfhandle->provides[i].interface = getInterfaceDescription(&elftmp, interface); + if(elfhandle->provides[i].interface == NULL) + goto oom; + + LOG_INTERNAL(2, " provide %s <%s>\n", + elfhandle->provides[i].name, + elfhandle->provides[i].interface->type, + 0,0, 0, 0); + CM_ASSERT(elfhandle->provides[i].collectionSize != 0); + + ref += sizeof(t_elf_required_interface); + + { + t_uint32 *methodSymbols = (t_uint32*)ref; + + elfhandle->provides[i].indexes = (t_interface_provide_index**)OSAL_Alloc_Zero( + sizeof(t_interface_provide_index*) * elfhandle->provides[i].collectionSize); + if(elfhandle->provides[i].indexes == NULL) + goto oom; + + if(elfhandle->provides[i].interface->methodNumber != 0) + { + for(j = 0; j < elfhandle->provides[i].collectionSize; j++) + { + elfhandle->provides[i].indexes[j] = (t_interface_provide_index*)OSAL_Alloc( + sizeof(t_interface_provide_index) * elfhandle->provides[i].interface->methodNumber); + if(elfhandle->provides[i].indexes[j] == NULL) + goto oom; + + for(k = 0; k < elfhandle->provides[i].interface->methodNumber; k++) + { + if((error = getAdressForExecutableOffsetElsewhere(elfhandle, &elftmp, + methodSymbols++, + &elfhandle->provides[i].indexes[j][k].memory)) != CM_OK) + goto onerror; + + if(elfhandle->provides[i].indexes[j][k].memory.memory != NULL) + LOG_INTERNAL(2, " [%d, %d] method '%s' mem=%s offset=%x\n", + j, k, + elfhandle->provides[i].interface->methodNames[k], + elfhandle->provides[i].indexes[j][k].memory.memory->memoryName, + elfhandle->provides[i].indexes[j][k].memory.offset, + 0); + else + LOG_INTERNAL(2, " [%d, %d] method '%s' address=%x\n", + j, k, + elfhandle->provides[i].interface->methodNames[k], + elfhandle->provides[i].indexes[j][k].memory.offset, + 0, 0); + } + } + } + + ref += elfhandle->provides[i].collectionSize * elfhandle->provides[i].interface->methodNumber * sizeof(methodSymbols[0]); + } + } + } + } + + return CM_OK; + +oom: + error = CM_NO_MORE_MEMORY; +onerror: + cm_ELF_CloseFile(temporaryDescription, elfhandle); + *elfhandlePtr = NULL; + return error; +} + +void cm_ELF_ReleaseDescription( + t_uint32 requireNumber, t_interface_require *requires, + t_uint32 attributeNumber, t_attribute *attributes, + t_uint32 propertyNumber, t_property *properties, + t_uint32 provideNumber, t_interface_provide *provides) +{ + int i, j; + + // Free provides (Number set when array allocated) + if(provides != NULL) + { + for(i = 0; i < provideNumber; i++) + { + if(provides[i].indexes != NULL) + { + for(j = 0; j < provides[i].collectionSize; j++) + { + OSAL_Free(provides[i].indexes[j]); + } + OSAL_Free(provides[i].indexes); + } + releaseInterfaceDescription(provides[i].interface); + cm_StringRelease(provides[i].name); + } + OSAL_Free(provides); + } + + // Free requires (Number set when array allocated) + if(requires != NULL) + { + for(i = 0; i < requireNumber; i++) + { + if(requires[i].indexes != 0) + { + for(j = 0; j < requires[i].collectionSize; j++) + { + OSAL_Free(requires[i].indexes[j].memories); + } + OSAL_Free(requires[i].indexes); + } + releaseInterfaceDescription(requires[i].interface); + cm_StringRelease(requires[i].name); + } + OSAL_Free(requires); + } + + // Free properties (Number set when array allocated) + if(properties != NULL) + { + for(i = 0; i < propertyNumber; i++) + { + cm_StringRelease(properties[i].value); + cm_StringRelease(properties[i].name); + } + OSAL_Free(properties); + } + + // Free Attributes (Number set when array allocated) + if(attributes != NULL) + { + for(i = 0; i < attributeNumber; i++) + { + cm_StringRelease(attributes[i].name); + } + OSAL_Free(attributes); + } +} + +void cm_ELF_CloseFile( + t_bool temporaryDescription, + t_elfdescription *elfhandle) +{ + if(elfhandle == NULL) + return; + + if(temporaryDescription && ! elfhandle->temporaryDescription) + return; + + // Release description if not moved to template + cm_ELF_ReleaseDescription( + elfhandle->requireNumber, elfhandle->requires, + elfhandle->attributeNumber, elfhandle->attributes, + elfhandle->propertyNumber, elfhandle->properties, + elfhandle->provideNumber, elfhandle->provides); + + cm_StringRelease(elfhandle->foundedTemplateName); + + ELF64_UnloadComponent(elfhandle); +} + + +static t_cm_error allocSegment( + t_cm_domain_id domainId, + t_elfdescription *elfhandle, + t_memory_handle memories[NUMBER_OF_MMDSP_MEMORY], + t_memory_property property) { + t_memory_id memId; + const t_elfmemory *thisMemory; //!< Memory used to determine this + const t_elfmemory *codeMemory; //!< Memory used to determine code + + MMDSP_serializeMemories(elfhandle->instanceProperty, &codeMemory, &thisMemory); + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + const t_elfmemory* mapping; + + if(elfhandle->segments[memId].sumSize == 0x0) + continue; + + mapping = MMDSP_getMappingById(memId); + + if( + (mapping->property == property && elfhandle->instanceProperty != MEM_FOR_SINGLETON) || + (property == MEM_SHARABLE && elfhandle->instanceProperty == MEM_FOR_SINGLETON) ) + { + // Allocate segment + memories[memId] = cm_DM_Alloc(domainId, mapping->dspMemType, + elfhandle->segments[memId].sumSize / mapping->fileEntSize, + mapping->memAlignement, TRUE); + + if(memories[memId] == INVALID_MEMORY_HANDLE) + { + ERROR("CM_NO_MORE_MEMORY(%s): %x too big\n", mapping->memoryName, elfhandle->segments[memId].sumSize / mapping->fileEntSize, 0, 0, 0, 0); + return CM_NO_MORE_MEMORY; + } + + // Get reference in memory + elfhandle->segments[memId].hostAddr = cm_DSP_GetHostLogicalAddress(memories[memId]); + + cm_DSP_GetDspAddress(memories[memId], &elfhandle->segments[memId].mpcAddr); + + // Log it + LOG_INTERNAL(1, "\t%s%s: 0x%x..+0x%x (0x%x)\n", + mapping->memoryName, + (thisMemory == mapping) ? "(THIS)" : "", + elfhandle->segments[memId].mpcAddr, + elfhandle->segments[memId].sumSize / mapping->fileEntSize, + elfhandle->segments[memId].hostAddr, 0); + } + else if(property == MEM_PRIVATE) // Since we allocate private segment, if not allocate, it's a share one + { + // In order to allow further relocation based on cached address like mpcAddr & hostAddr, + // initialize them also ! + + // Get reference in memory + elfhandle->segments[memId].hostAddr = cm_DSP_GetHostLogicalAddress(memories[memId]); + + cm_DSP_GetDspAddress(memories[memId], &elfhandle->segments[memId].mpcAddr); + } + } + + return CM_OK; +} + +/* + * Note: in case of error, part of memory could have been allocated and must be free by calling cm_DSPABI_FreeTemplate + */ +t_cm_error cm_ELF_LoadTemplate( + t_cm_domain_id domainId, + t_elfdescription *elfhandle, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]) +{ + t_cm_error error; + + if((error = allocSegment(domainId, elfhandle, sharedMemories, MEM_SHARABLE)) != CM_OK) + return error; + + // Load each readonly segment + if((error = ELF64_loadSegment(elfhandle, sharedMemories, MEM_SHARABLE)) != CM_OK) + return error; + + return CM_OK; +} + +t_cm_error cm_ELF_LoadInstance( + t_cm_domain_id domainId, + t_elfdescription *elfhandle, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]) +{ + t_memory_id memId; + t_cm_error error; + + // Erase whole memories to make free in case of error + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + privateMemories[memId] = sharedMemories[memId]; + } + + if((error = allocSegment(domainId, elfhandle, privateMemories, MEM_PRIVATE)) != CM_OK) + return error; + + // Load each writable memory + if((error = ELF64_loadSegment(elfhandle, privateMemories, MEM_PRIVATE)) != CM_OK) + return error; + + return CM_OK; +} + +void cm_ELF_FlushTemplate( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]) +{ + t_memory_id memId; + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + if(sharedMemories[memId] != INVALID_MEMORY_HANDLE) + MMDSP_loadedSection( + coreId, memId, + sharedMemories[memId]); + } +} + +void cm_ELF_FlushInstance( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]) +{ + t_memory_id memId; + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + if(privateMemories[memId] != INVALID_MEMORY_HANDLE && privateMemories[memId] != sharedMemories[memId]) + MMDSP_loadedSection( + coreId, memId, + privateMemories[memId]); + } +} + +void cm_ELF_FreeInstance( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]) +{ + t_memory_id memId; + + if(privateMemories == NULL) + return; + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + if(privateMemories[memId] != INVALID_MEMORY_HANDLE && privateMemories[memId] != sharedMemories[memId]) + { + MMDSP_unloadedSection(coreId, memId, privateMemories[memId]); + cm_DM_Free(privateMemories[memId], TRUE); + } + } +} + +void cm_ELF_FreeTemplate( + t_nmf_core_id coreId, + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]) +{ + t_memory_id memId; + + if(sharedMemories == NULL) + return; + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + if(sharedMemories[memId] != INVALID_MEMORY_HANDLE) + { + MMDSP_unloadedSection(coreId, memId, sharedMemories[memId]); + cm_DM_Free(sharedMemories[memId], TRUE); + } + } +} diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c new file mode 100644 index 00000000000..452d0f1b175 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c @@ -0,0 +1,575 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include + +#include + +#include +#include +#include + +#include + +static const t_elfmemory mmdspMemories[NUMBER_OF_MMDSP_MEMORY] = { + {0, SDRAM_CODE, SDRAMTEXT_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_CODE, 8, 8, "SDRAM_CODE"}, /* 0: Program memory */ + {1, INTERNAL_XRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "XROM"}, /* 1: Internal X memory */ + {2, INTERNAL_YRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "YROM"}, /* 2: Y memory */ + {3, SDRAM_EXT24, SDRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "SDR0M24"}, /* 5: SDRAM24 */ + {4, SDRAM_EXT16, SDRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 2, "SDROM16"}, /* 6: SDRAM16 */ + {5, ESRAM_EXT24, ESRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 4, "ESROM24"}, /* 8: ESRAM24 */ + {6, ESRAM_EXT16, ESRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_DATA, 3, 2, "ESROM16"}, /* 9: ESRAM16 */ + {7, ESRAM_CODE, ESRAMTEXT_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_CODE, 8, 8, "ESRAM_CODE"}, /*10: ESRAM code */ + {8, INTERNAL_XRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "XRAM"}, /* 1: Internal X memory */ + {9, INTERNAL_YRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "YRAM"}, /* 2: Y memory */ + {10, SDRAM_EXT24, SDRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "SDRAM24"}, /* 5: SDRAM24 */ + {11, SDRAM_EXT16, SDRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 2, "SDRAM16"}, /* 6: SDRAM16 */ + {12, ESRAM_EXT24, ESRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "ESRAM24"}, /* 8: ESRAM24 */ + {13, ESRAM_EXT16, ESRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 2, "ESRAM16"}, /* 9: ESRAM16 */ + {14, LOCKED_CODE, SDRAMTEXT_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_CODE, 8, 8, "LOCKED_CODE"}, /* : .locked */ +}; + +#define MAX_ELFSECTIONNAME 10 +struct memoryMapping { + char *elfSectionName; + t_uint32 memoryIndex[MEM_FOR_LAST]; // memoryIndex[t_instance_property] +}; + +static const struct memoryMapping mappingmem0[] = { + {"mem0.0", {0, 0}}, + {"mem0.1", {0, 0}}, + {"mem0.2", {0, 0}} +}; +static const struct memoryMapping mappingmem10 = + {"mem10", {7, 7}}; +static const struct memoryMapping mappinglocked = + {".locked", {14, 14}}; +static const struct memoryMapping mappingmem1[] = { + {"", {0xff, 0xff}}, + {"mem1.1", {1, 1}}, + {"mem1.2", {8, 1}}, + {"mem1.3", {1, 1}}, + {"mem1.4", {8, 1}}, + {"mem1.stack", {8, 1}} +}; +static const struct memoryMapping mappingmem2[] = { + {"", {0xff, 0xff}}, + {"mem2.1", {2, 2}}, + {"mem2.2", {9, 2}}, + {"mem2.3", {2, 2}}, + {"mem2.4", {9, 2}} +}; +static const struct memoryMapping mappingmem5[] = { + {"", {0xff, 0xff}}, + {"mem5.1", {3, 3}}, + {"mem5.2", {10, 3}}, + {"mem5.3", {3, 3}}, + {"mem5.4", {10, 3}} +}; +static const struct memoryMapping mappingmem6[] = { + {"", {0xff, 0xff}}, + {"mem6.1", {4, 4}}, + {"mem6.2", {11, 4}}, + {"mem6.3", {4, 4}}, + {"mem6.4", {11, 4}} +}; +static const struct memoryMapping mappingmem8[] = { + {"", {0xff, 0xff}}, + {"mem8.1", {5, 5}}, + {"mem8.2", {12, 5}}, + {"mem8.3", {5, 5}}, + {"mem8.4", {12, 5}} +}; +static const struct memoryMapping mappingmem9[] = { + {"", {0xff, 0xff}}, + {"mem9.1", {6, 6}}, + {"mem9.2", {13, 6}}, + {"mem9.3", {6, 6}}, + {"mem9.4", {13, 6}} +}; + +static const struct { + const struct memoryMapping* mapping; + unsigned int number; +} hashMappings[10] = { + {mappingmem0, sizeof(mappingmem0) / sizeof(mappingmem0[0])}, + {mappingmem1, sizeof(mappingmem1) / sizeof(mappingmem1[0])}, + {mappingmem2, sizeof(mappingmem2) / sizeof(mappingmem2[0])}, + {0x0, 0}, + {0x0, 0}, + {mappingmem5, sizeof(mappingmem5) / sizeof(mappingmem5[0])}, + {mappingmem6, sizeof(mappingmem6) / sizeof(mappingmem6[0])}, + {0x0, 0}, + {mappingmem8, sizeof(mappingmem8) / sizeof(mappingmem8[0])}, + {mappingmem9, sizeof(mappingmem9) / sizeof(mappingmem9[0])}, +}; + +const t_elfmemory* MMDSP_getMappingById(t_memory_id memId) +{ + return &mmdspMemories[memId]; +} + +const t_elfmemory* MMDSP_getMappingByName(const char* sectionName, t_instance_property property) +{ + if(sectionName[0] == 'm' && sectionName[1] == 'e' && sectionName[2] == 'm') + { + if(sectionName[4] == '.') + { + if(sectionName[5] >= '0' && sectionName[5] <= '9') + { + if(sectionName[3] >= '0' && sectionName[3] <= '9') + { + unsigned int m, sm; + + m = sectionName[3] - '0'; + sm = sectionName[5] - '0'; + if(sm < hashMappings[m].number) + return &mmdspMemories[hashMappings[m].mapping[sm].memoryIndex[property]]; + } + } else if(sectionName[3] == '1' && sectionName[5] == 's') + return &mmdspMemories[mappingmem1[5].memoryIndex[property]]; + } + else if(sectionName[3] == '1' && sectionName[4] == '0') + return &mmdspMemories[mappingmem10.memoryIndex[property]]; + } + else if(sectionName[0] == '.' && sectionName[1] == 'l' && sectionName[2] == 'o' && sectionName[3] == 'c' && + sectionName[4] == 'k' && sectionName[5] == 'e' && sectionName[6] == 'd') + { + return &mmdspMemories[mappinglocked.memoryIndex[property]]; + } + + return NULL; +} + +void MMDSP_serializeMemories(t_instance_property property, + const t_elfmemory** codeMemory, const t_elfmemory** thisMemory) { + // Return meory reference + *codeMemory = &mmdspMemories[0]; + if(property == MEM_FOR_SINGLETON) + { + *thisMemory = &mmdspMemories[1]; + } + else + { + *thisMemory = &mmdspMemories[8]; + } +} + +void MMDSP_copyCode(t_uint64 * remoteAddr64, const char* origAddr, int nb) +{ + int m; + + // Linux allow unaligned access +#ifdef LINUX + t_uint64 *origAddr64 = (t_uint64*)origAddr; +#else + __packed t_uint64 *origAddr64 = (__packed t_uint64*)origAddr; +#endif + + for (m = 0; m < nb; m += 8) + { + *remoteAddr64++ = swap64(*origAddr64++); + } +} + +void MMDSP_copyData24(t_uint32 * remoteAddr32, const char* origAddr, int nb) +{ + int m; + + for (m = 0; m < nb; m+=4) + { + t_uint32 value1; + + value1 = (*origAddr++ << 16); + value1 |= (*origAddr++ << 8); + value1 |= (*origAddr++ << 0); + *remoteAddr32++ = value1; + } +} + +void MMDSP_copyData16(t_uint16 * remoteAddr16, const char* origAddr, int nb) +{ + int m; + + for (m = 0; m < nb; m+=2) + { + t_uint16 value1; + + origAddr++; // Skip this byte (which is put in elf file for historical reason) + value1 = (*origAddr++ << 8); + value1 |= (*origAddr++ << 0); + *remoteAddr16++ = value1; + } +} + +#if 0 +__asm void MMDSP_copyCode(void* dst, const void* src, int nb) +{ + PUSH {r4-r8, lr} + SUBS r2,r2,#0x20 + BCC l4 + +l5 + SETEND BE + LDR r4, [r1], #0x4 + LDR r3, [r1], #0x4 + LDR r6, [r1], #0x4 + LDR r5, [r1], #0x4 + LDR r8, [r1], #0x4 + LDR r7, [r1], #0x4 + LDR lr, [r1], #0x4 + LDR r12, [r1], #0x4 + + SETEND LE + STM r0!,{r3-r8,r12, lr} + SUBS r2,r2,#0x20 + BCS l5 + +l4 + LSLS r12,r2,#28 + + SETEND BE + LDRCS r4, [r1], #0x4 + LDRCS r3, [r1], #0x4 + LDRCS r6, [r1], #0x4 + LDRCS r5, [r1], #0x4 + SETEND LE + STMCS r0!,{r3-r6} + + SETEND BE + LDRMI r4, [r1], #0x4 + LDRMI r3, [r1], #0x4 + SETEND LE + STMMI r0!,{r3-r4} + + POP {r4-r8, pc} +} +#endif + +#ifdef LINUX +static void PLD5(int r) +{ + asm volatile ( + "PLD [r0, #0x20] \n\t" + "PLD [r0, #0x40] \n\t" + "PLD [r0, #0x60] \n\t" + "PLD [r0, #0x80] \n\t" + "PLD [r0, #0xA0]" ); +} + +static void PLD1(int r) +{ + asm volatile ( + "PLD [r0, #0xC0]" ); +} +#else /* Symbian, Think -> We assume ARMCC */ +static __asm void PLD5(int r) +{ + PLD [r0, #0x20] + PLD [r0, #0x40] + PLD [r0, #0x60] + PLD [r0, #0x80] + PLD [r0, #0xA0] + + bx lr +} + +static __asm void PLD1(int r) +{ + PLD [r0, #0xC0] + + bx lr +} +#endif + +#if 0 +__asm void COPY(void* dst, const void* src, int nb) +{ + PUSH {r4-r8, lr} + SUBS r2,r2,#0x20 + BCC l4a + PLD [r1, #0x20] + PLD [r1, #0x40] + PLD [r1, #0x60] + PLD [r1, #0x80] + PLD [r1, #0xA0] + +l5a + PLD [r1, #0xC0] + LDM r1!,{r3-r8,r12,lr} + STM r0!,{r3-r8,r12,lr} + SUBS r2,r2,#0x20 + BCS l5a + +l4a + LSLS r12,r2,#28 + LDMCS r1!,{r3,r4,r12,lr} + STMCS r0!,{r3,r4,r12,lr} + LDMMI r1!,{r3,r4} + STMMI r0!,{r3,r4} + POP {r4-r8,lr} + LSLS r12,r2,#30 + LDRCS r3,[r1],#4 + STRCS r3,[r0],#4 + BXEQ lr +l6b + LSLS r2,r2,#31 + LDRHCS r3,[r1],#2 + LDRBMI r2,[r1],#1 + STRHCS r3,[r0],#2 + STRBMI r2,[r0],#1 + BX lr +} +#endif + + +void MMDSP_copySection(t_uint32 origAddr, t_uint32 remoteAddr, t_uint32 sizeInByte) { + t_uint32 endAddr = remoteAddr + sizeInByte; + + PLD5(origAddr); + + // Align on 32bits + if((remoteAddr & 0x3) != 0) + { + *(t_uint16*)remoteAddr = *(t_uint16*)origAddr; + remoteAddr += sizeof(t_uint16); + origAddr += sizeof(t_uint16); + } + + // Align on 64bits + if((remoteAddr & 0x7) != 0 && (remoteAddr <= endAddr - sizeof(t_uint32))) + { + *(t_uint32*)remoteAddr = *(t_uint32*)origAddr; + remoteAddr += sizeof(t_uint32); + origAddr += sizeof(t_uint32); + } + + // 64bits burst access + for(; remoteAddr <= endAddr - sizeof(t_uint64); remoteAddr += sizeof(t_uint64), origAddr += sizeof(t_uint64)) + { + PLD1(origAddr); + *(volatile t_uint64*)remoteAddr = *(t_uint64*)origAddr; + } + + // Remain 32bits access + if(remoteAddr <= endAddr - sizeof(t_uint32)) + { + *(t_uint32*)remoteAddr = *(t_uint32*)origAddr; + remoteAddr += sizeof(t_uint32); + origAddr += sizeof(t_uint32); + } + + // Remain 16bits access + if(remoteAddr <= endAddr - sizeof(t_uint16)) + *(t_uint16*)remoteAddr = *(t_uint16*)origAddr; +} + + +void MMDSP_bzeroSection(t_uint32 remoteAddr, t_uint32 sizeInByte) { + t_uint32 endAddr = remoteAddr + sizeInByte; + + // Align on 32bits + if((remoteAddr & 0x3) != 0) + { + *(t_uint16*)remoteAddr = 0; + remoteAddr += sizeof(t_uint16); + } + + // Align on 64bits + if((remoteAddr & 0x7) != 0 && (remoteAddr <= endAddr - sizeof(t_uint32))) + { + *(t_uint32*)remoteAddr = 0; + remoteAddr += sizeof(t_uint32); + } + + // 64bits burst access + for(; remoteAddr <= endAddr - sizeof(t_uint64); remoteAddr += sizeof(t_uint64)) + *(volatile t_uint64*)remoteAddr = 0ULL; + + // Remain 32bits access + if(remoteAddr <= endAddr - sizeof(t_uint32)) + { + *(t_uint32*)remoteAddr = 0; + remoteAddr += sizeof(t_uint32); + } + + // Remain 16bits access + if(remoteAddr <= endAddr - sizeof(t_uint16)) + *(t_uint16*)remoteAddr = 0; +} + +void MMDSP_loadedSection(t_nmf_core_id coreId, t_memory_id memId, t_memory_handle handle) +{ + if(mmdspMemories[memId].purpose == MEM_CODE) + { + OSAL_CleanDCache(cm_DSP_GetHostLogicalAddress(handle), cm_MM_GetSize(handle)); + } + + if(memId == LOCKED_CODE) + { + t_uint32 DspAddress, DspSize; + + cm_DSP_GetDspMemoryHandleSize(handle, &DspSize); + cm_DSP_GetDspAddress(handle, &DspAddress); + + cm_COMP_InstructionCacheLock(coreId, DspAddress, DspSize); + } +} + +void MMDSP_unloadedSection(t_nmf_core_id coreId, t_memory_id memId, t_memory_handle handle) +{ + if(memId == LOCKED_CODE) + { + t_uint32 DspAddress, DspSize; + + cm_DSP_GetDspMemoryHandleSize(handle, &DspSize); + cm_DSP_GetDspAddress(handle, &DspAddress); + + cm_COMP_InstructionCacheUnlock(coreId, DspAddress, DspSize); + } + +} + +static struct reloc_howto_struct elf64_mmdsp_howto_table[] = +{ + HOWTO (R_MMDSP_IMM20_16, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 8, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + 0x0, /* special_function */ + "R_MMDSP_IMM20_16", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0000000000ffff00, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* A 4-bit absolute relocation for splitted 20 bits immediate, shifted by 56 */ + + HOWTO (R_MMDSP_IMM20_4, /* type */ + 16, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 4, /* bitsize */ + FALSE, /* pc_relative */ + 56, /* bitpos */ + complain_overflow_dont, /* complain_on_overflow */ + 0x0, /* special_function */ + "R_MMDSP_IMM20_4", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0f00000000000000LL, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_MMDSP_24, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0x0, /* special_function */ + "R_MMDSP_24", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_MMDSP_IMM16, /* type */ + 0, /* rightshift */ + 4, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 8, /* bitpos */ + complain_overflow_bitfield, /* complain_on_overflow */ + 0x0, /* special_function */ + "R_MMDSP_IMM16", /* name */ + FALSE, /* partial_inplace */ + 0x0, /* src_mask */ + 0x0000000000ffff00, /* dst_mask */ + FALSE), /* pcrel_offset */ +}; + +static const char* lastInPlaceAddr = 0; +static long long lastInPlaceValue; + +void MMDSP_performRelocation( + t_uint32 type, + const char* symbol_name, + t_uint32 symbol_addr, + char* reloc_addr, + const char* inPlaceAddr, + t_uint32 reloc_offset) { + int i; + + for(i = 0; i < sizeof(elf64_mmdsp_howto_table) / sizeof(elf64_mmdsp_howto_table[0]); i++) + { + struct reloc_howto_struct* howto = &elf64_mmdsp_howto_table[i]; + if(howto->type == type) + { + t_uint64 relocation; + + LOG_INTERNAL(2, "reloc '%s:0x%x' type %s at 0x%x (0x%x)\n", + symbol_name ? symbol_name : "??", symbol_addr, + howto->name, + reloc_offset, reloc_addr, 0); + + relocation = symbol_addr; + + if (howto->pc_relative) { + // Not handle yet + } + + if (howto->complain_on_overflow != complain_overflow_dont) { + // Not handle yet + } + + relocation >>= howto->rightshift; + + relocation <<= howto->bitpos; + +#define DOIT(x) \ + x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask)) + + switch (howto->size) { + case 2: { + long x = *(long*)inPlaceAddr; + + // CM_ASSERT(*(long*)inPlaceAddr == *(long*)reloc_addr); + + DOIT (x); + *(long*)reloc_addr = x; + } + break; + case 4: { + long long x; + if(lastInPlaceAddr == inPlaceAddr) + { + x = lastInPlaceValue; + } + else + { + // CM_ASSERT(*(__packed long long*)inPlaceAddr == *(long long*)reloc_addr); + x = *(long long*)inPlaceAddr; + lastInPlaceAddr = inPlaceAddr; + } + + DOIT (x); + *(long long*)reloc_addr = lastInPlaceValue = x; + } + break; + default: + CM_ASSERT(0); + } + + return; + } + } + + ERROR("Relocation type %d not supported for '%s'\n", type, symbol_name, 0, 0, 0, 0); +} diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfrelocate.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfrelocate.c new file mode 100644 index 00000000000..b08ac6a361e --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfrelocate.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include +#include +#include +#include + +t_cm_error cm_ELF_relocateSharedSegments( + t_memory_handle *memories, + t_elfdescription *elfhandle, + void *cbContext) +{ + return ELF64_relocateSegments( + memories, + elfhandle, + MEM_SHARABLE, + cbContext); +} + +t_cm_error cm_ELF_relocatePrivateSegments( + t_memory_handle *memories, + t_elfdescription *elfhandle, + void *cbContext) +{ + return ELF64_relocateSegments( + memories, + elfhandle, + MEM_PRIVATE, + cbContext); +} + +void cm_ELF_performRelocation( + t_uint32 type, + const char* symbol_name, + t_uint32 symbol_addr, + char* reloc_addr) +{ + MMDSP_performRelocation( + type, + symbol_name, + symbol_addr, + reloc_addr, + reloc_addr, + 0xBEEF); + + OSAL_CleanDCache((t_uint32)reloc_addr, 8); +} + +t_cm_error cm_ELF_GetMemory( + t_elfdescription *elf, + t_tmp_elfdescription *elftmp, + t_uint32 address, + t_memory_purpose purpose, + t_memory_reference *memory) { + t_memory_id memId; + + for(memId = 0; memId < NUMBER_OF_MMDSP_MEMORY; memId++) + { + const t_elfmemory* mem = MMDSP_getMappingById(memId); + + if(mem->purpose == purpose && // Memory correspond + elf->segments[mem->id].sumSize != 0 && // Segment allocated + (elf->segments[mem->id].mpcAddr <= address) && + (address < elf->segments[mem->id].mpcAddr + elf->segments[mem->id].sumSize / mem->fileEntSize)) { + memory->memory = mem; + memory->offset = address - elf->segments[mem->id].mpcAddr; + return CM_OK; + } + } + + ERROR("Memory %x,%d not found\n", address, purpose, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; +} diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c new file mode 100644 index 00000000000..4a2976a6bc1 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfxx.c @@ -0,0 +1,591 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include + +#include +#include + + +static t_uint32 max(t_uint32 a, t_uint32 b) +{ + return (a >= b) ? a : b; +} +/* +static t_uint32 min(t_uint32 a, t_uint32 b) +{ + return (a <= b) ? a : b; +} +*/ + +struct XXrelocation +{ + t_uint32 st_value; + ElfXX_Half st_shndx; + Elf64_Sxword r_addend; + t_uint32 OffsetInElf; + t_uint32 type; + + t_dup_char symbol_name; // Valid only if st_shndx == SHN_UNDEF +}; + +struct XXSection { + ElfXX_Word sh_type; /* Section type */ + t_uint32 sh_size; /* Section size in bytes */ + ElfXX_Word sh_info; /* Additional section information */ + ElfXX_Word sh_link; /* Link to another section */ + t_uint32 sh_addralign; /* Some sections have address alignment constraints */ + t_uint32 sh_addr; /* Section addr */ + ElfXX_Xword sh_flags; /* Section flags */ + + const char *data; + t_uint32 trueDataSize; /* Valid if different from sh_size */ + const char *sectionName; + + t_uint32 offsetInSegment; + const t_elfmemory *meminfo; + + t_uint32 relocationNumber; + struct XXrelocation *relocations; +}; + +struct XXElf { + t_uint32 e_shnum; + struct XXSection sectionss[1]; +}; + +t_cm_error ELF64_LoadComponent( + t_uint16 e_machine, + const char *elfdata, + t_elfdescription **elfhandlePtr, + t_tmp_elfdescription *elftmp) +{ + t_elfdescription *elfhandle; + const ElfXX_Ehdr *header = (ElfXX_Ehdr*)elfdata; + const ElfXX_Shdr *sections; + const char *strings; + struct XXElf* ELF; + int i, nb; + + elftmp->elfdata = elfdata; + + /* Sanity check */ + if (swapHalf(header->e_machine) != e_machine) + { + ERROR("This is not a executable for such MPC\n", 0, 0, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; + } + + // Cache elf file informations + nb = swapHalf(header->e_shnum); + elftmp->isExecutable = (swapHalf(header->e_type) == ET_EXEC); + + elfhandle = (t_elfdescription*)OSAL_Alloc_Zero( + sizeof(t_elfdescription) + sizeof(struct XXElf) + sizeof(struct XXSection) * (nb - 1)); + if(elfhandle == NULL) + return CM_NO_MORE_MEMORY; + + ELF = elfhandle->ELF = (struct XXElf*)(elfhandle + 1); + + ELF->e_shnum = nb; + + sections = (ElfXX_Shdr*)&elfdata[swapXword(header->e_shoff)]; + // Compute and swap section infromation + for(i = 0; i < ELF->e_shnum; i++) + { + ELF->sectionss[i].sh_type = swapWord(sections[i].sh_type); + ELF->sectionss[i].sh_info = swapWord(sections[i].sh_info); + ELF->sectionss[i].sh_link = swapWord(sections[i].sh_link); + ELF->sectionss[i].sh_size = (t_uint32)swapXword(sections[i].sh_size); + ELF->sectionss[i].sh_addralign = (t_uint32)swapXword(sections[i].sh_addralign); + ELF->sectionss[i].sh_addr = (t_uint32)swapXword(sections[i].sh_addr); + ELF->sectionss[i].sh_flags = swapXword(sections[i].sh_flags); + + elftmp->sectionData[i] = &elfdata[(t_uint32)swapXword(sections[i].sh_offset)]; + } + + /* + * search nmf_segment + */ + strings = elftmp->sectionData[swapHalf(header->e_shstrndx)]; + for(i = 0; i < ELF->e_shnum; i++) + { + ELF->sectionss[i].sectionName = &strings[swapWord(sections[i].sh_name)]; + + // Found nmf_segment to see if it's + if(cm_StringCompare("nmf_segment", ELF->sectionss[i].sectionName, 11) == 0) { + elftmp->nmfSectionIndex = i; + elftmp->elfheader = (const t_elf_component_header*)elftmp->sectionData[i]; + } + } + + if(elftmp->nmfSectionIndex == 0) + { + ERROR("This is not a NMF component\n", 0, 0, 0, 0, 0, 0); + goto invalid; + } + + /* + * Determine component type + */ + elfhandle->magicNumber = swap32(elftmp->elfheader->magic); + switch(elfhandle->magicNumber) { + case MAGIC_COMPONENT: + elfhandle->instanceProperty = MEM_FOR_MULTIINSTANCE; + break; + case MAGIC_SINGLETON: + case MAGIC_FIRMWARE: + elfhandle->instanceProperty = MEM_FOR_SINGLETON; + break; + } + + // Copy content + for(i = 0; i < ELF->e_shnum; i++) + { + ELF->sectionss[i].meminfo = MMDSP_getMappingByName( + ELF->sectionss[i].sectionName, + elfhandle->instanceProperty); + + if(ELF->sectionss[i].meminfo != NULL) + ELF->sectionss[i].trueDataSize = (ELF->sectionss[i].sh_size / ELF->sectionss[i].meminfo->fileEntSize) * ELF->sectionss[i].meminfo->memEntSize; + + if(ELF->sectionss[i].sh_size != 0 && + ELF->sectionss[i].sh_type == SHT_PROGBITS && + (ELF->sectionss[i].sh_flags & SHF_ALLOC) != 0) + { + const char* elfAddr = elftmp->sectionData[i]; + + ELF->sectionss[i].data = OSAL_Alloc(ELF->sectionss[i].trueDataSize); + if(ELF->sectionss[i].data == NULL) + goto oom; + + if(ELF->sectionss[i].meminfo->purpose == MEM_CODE) + { + MMDSP_copyCode( + (t_uint64*)ELF->sectionss[i].data, + elfAddr, + ELF->sectionss[i].trueDataSize); + } + else if(ELF->sectionss[i].meminfo->purpose == MEM_DATA && + // Always 3 for data ELF->sectionss[i].meminfo->fileEntSize == 3 && + ELF->sectionss[i].meminfo->memEntSize == 4) + { + MMDSP_copyData24( + (t_uint32*)ELF->sectionss[i].data, + elfAddr, + ELF->sectionss[i].trueDataSize); + } + else if(ELF->sectionss[i].meminfo->purpose == MEM_DATA && + // Always 3 for data ELF->sectionss[i].meminfo->fileEntSize == 3 && + ELF->sectionss[i].meminfo->memEntSize == 2) + { + MMDSP_copyData16( + (t_uint16*)ELF->sectionss[i].data, + elfAddr, + ELF->sectionss[i].trueDataSize); + } + else + CM_ASSERT(0); + } + } + + // Copy relocation + // Loop on all relocation section + for(i=0; i < ELF->e_shnum; i++) + { + int sh_info; + + // Does this section is a relocation table (only RELA supported) + if((ELF->sectionss[i].sh_type != SHT_RELA) || + ELF->sectionss[i].sh_size == 0) continue; + + // Copy only relocation for loaded section + sh_info = ELF->sectionss[i].sh_info; + if(ELF->sectionss[sh_info].meminfo != NULL) + { + const ElfXX_Sym* symtab; + const char* strtab; + ElfXX_Rela* rel_start; + int n; + + ELF->sectionss[sh_info].relocationNumber = ELF->sectionss[i].sh_size / sizeof(ElfXX_Rela); + ELF->sectionss[sh_info].relocations = (struct XXrelocation*)OSAL_Alloc_Zero(sizeof(struct XXrelocation) * ELF->sectionss[sh_info].relocationNumber); + if(ELF->sectionss[sh_info].relocations == NULL) + goto oom; + + symtab = (ElfXX_Sym *)elftmp->sectionData[ELF->sectionss[i].sh_link]; + strtab = elftmp->sectionData[ELF->sectionss[ELF->sectionss[i].sh_link].sh_link]; + rel_start = (ElfXX_Rela*)elftmp->sectionData[i]; + for(n = 0; n < ELF->sectionss[sh_info].relocationNumber; n++, rel_start++) + { + struct XXrelocation* relocation = &ELF->sectionss[sh_info].relocations[n]; + ElfXX_Xword r_info = swapXword(rel_start->r_info); + int strtab_index = ELFXX_R_SYM(r_info); + const char* symbol_name = &strtab[swapWord(symtab[strtab_index].st_name)]; + + relocation->st_shndx = swapHalf(symtab[strtab_index].st_shndx); + relocation->st_value = (t_uint32)swapXword(symtab[strtab_index].st_value); + relocation->r_addend = swapXword(rel_start->r_addend); + relocation->OffsetInElf = (t_uint32)swapXword(rel_start->r_offset) / ELF->sectionss[sh_info].meminfo->fileEntSize; + relocation->type = ELFXX_R_TYPE(r_info); + + switch(relocation->st_shndx) { + case SHN_UNDEF: + relocation->symbol_name = cm_StringDuplicate(symbol_name + 1); /* Remove '_' prefix */ + if(relocation->symbol_name == NULL) + goto oom; + break; + case SHN_COMMON: + ERROR("SHN_COMMON not handle for %s\n", symbol_name, 0, 0, 0, 0, 0); + goto invalid; + } + } + } + } + + *elfhandlePtr = elfhandle; + return CM_OK; +invalid: + ELF64_UnloadComponent(elfhandle); + return CM_INVALID_ELF_FILE; +oom: + ELF64_UnloadComponent(elfhandle); + return CM_NO_MORE_MEMORY; +} + +t_cm_error ELF64_ComputeSegment( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp) +{ + struct XXElf* ELF = elfhandle->ELF; + int i; + + for(i = 0; i < ELF->e_shnum; i++) + { + ELF->sectionss[i].offsetInSegment = 0xFFFFFFFF; + + if(ELF->sectionss[i].sh_type == SHT_PROGBITS || ELF->sectionss[i].sh_type == SHT_NOBITS) { + // This is a loadable memory (memory size could be zero since we can have symbol on it)... + const t_elfmemory* meminfo = ELF->sectionss[i].meminfo; + + if(meminfo != NULL) { + // Which correspond to MPC memory + + if(elftmp->isExecutable) + { + if(! elfhandle->segments[meminfo->id].sumSizeSetted) + { + CM_ASSERT(ELF->sectionss[i].sh_addr >= meminfo->startAddr * meminfo->fileEntSize); + + elfhandle->segments[meminfo->id].sumSizeSetted = TRUE; + elfhandle->segments[meminfo->id].sumSize = ELF->sectionss[i].sh_addr - meminfo->startAddr * meminfo->fileEntSize; + } + else + CM_ASSERT(elfhandle->segments[meminfo->id].sumSize == ELF->sectionss[i].sh_addr - meminfo->startAddr * meminfo->fileEntSize); + } + else + { + while(elfhandle->segments[meminfo->id].sumSize % ELF->sectionss[i].sh_addralign != 0) + elfhandle->segments[meminfo->id].sumSize++; + } + + elfhandle->segments[meminfo->id].maxAlign = max(elfhandle->segments[meminfo->id].maxAlign, ELF->sectionss[i].sh_addralign); + ELF->sectionss[i].offsetInSegment = elfhandle->segments[meminfo->id].sumSize / meminfo->fileEntSize; + elfhandle->segments[meminfo->id].sumSize += ELF->sectionss[i].sh_size; + } + } else if(ELF->sectionss[i].sh_type == SHT_RELA && ELF->sectionss[i].sh_info == elftmp->nmfSectionIndex) { + int secsym = ELF->sectionss[i].sh_link; + elftmp->relaNmfSegment = (ElfXX_Rela*)elftmp->sectionData[i]; + elftmp->relaNmfSegmentEnd = (ElfXX_Rela*)((t_uint32)elftmp->relaNmfSegment + ELF->sectionss[i].sh_size); + elftmp->relaNmfSegmentSymbols = (ElfXX_Sym*)elftmp->sectionData[secsym]; + elftmp->relaNmfSegmentStrings = elftmp->sectionData[ELF->sectionss[secsym].sh_link]; + } + } + + return CM_OK; +} + +void ELF64_UnloadComponent( + t_elfdescription *elfhandle) +{ + struct XXElf* ELF = elfhandle->ELF; + int i, n; + + for(i = 0; i < ELF->e_shnum; i++) + { + if(ELF->sectionss[i].relocations != NULL) + { + for(n = 0; n < ELF->sectionss[i].relocationNumber; n++) + cm_StringRelease(ELF->sectionss[i].relocations[n].symbol_name); + OSAL_Free(ELF->sectionss[i].relocations); + } + + OSAL_Free((void*)ELF->sectionss[i].data); + } + OSAL_Free(elfhandle); +} + +t_cm_error ELF64_loadSegment( + t_elfdescription *elfhandle, + t_memory_handle *memory, + t_memory_property property) +{ + struct XXElf* ELF = elfhandle->ELF; + int i; + + /* + * Copy ELF data in this segment + */ + for(i = 0; i < ELF->e_shnum; i++) + { + const t_elfmemory* mapping = ELF->sectionss[i].meminfo; + + if(mapping == NULL) + continue; + if((! (ELF->sectionss[i].sh_flags & SHF_ALLOC)) || (ELF->sectionss[i].sh_size == 0)) + continue; + + // This is a loadable memory ... + if( + (mapping->property == property && elfhandle->instanceProperty != MEM_FOR_SINGLETON) || + (property == MEM_SHARABLE && elfhandle->instanceProperty == MEM_FOR_SINGLETON) ) + { + // Where memory exist and waited share/private correspond + t_uint32 remoteData = elfhandle->segments[mapping->id].hostAddr + + ELF->sectionss[i].offsetInSegment * mapping->memEntSize; + + if(ELF->sectionss[i].sh_type != SHT_NOBITS) + { + LOG_INTERNAL(2, "loadSection(%s, 0x%x, 0x%x, 0x%08x)\n", + ELF->sectionss[i].sectionName, remoteData, ELF->sectionss[i].trueDataSize, + (t_uint32)ELF->sectionss[i].data, 0, 0); + + MMDSP_copySection((t_uint32)ELF->sectionss[i].data, remoteData, ELF->sectionss[i].trueDataSize); + } + else + { + LOG_INTERNAL(2, "bzeroSection(%s, 0x%x, 0x%x)\n", + ELF->sectionss[i].sectionName, remoteData, ELF->sectionss[i].trueDataSize, 0, 0, 0); + + MMDSP_bzeroSection(remoteData, ELF->sectionss[i].trueDataSize); + } + } + } + + return CM_OK; +} + + + +static const t_elfmemory* getSectionAddress( + t_memory_handle *memories, + t_elfdescription *elfhandle, + t_uint32 sectionIdx, + t_uint32 *sectionOffset, + t_cm_logical_address *sectionAddr) { + struct XXElf* ELF = elfhandle->ELF; + const t_elfmemory* mapping = ELF->sectionss[sectionIdx].meminfo; + + if(mapping != NULL) { + *sectionOffset = (elfhandle->segments[mapping->id].mpcAddr + + ELF->sectionss[sectionIdx].offsetInSegment); + + *sectionAddr = (t_cm_logical_address)(elfhandle->segments[mapping->id].hostAddr + + ELF->sectionss[sectionIdx].offsetInSegment * mapping->memEntSize); + } + + return mapping; +} + +static t_uint32 getSymbolAddress( + t_memory_handle *memories, + t_elfdescription *elfhandle, + t_uint32 symbolSectionIdx, + t_uint32 symbolOffet) { + struct XXElf* ELF = elfhandle->ELF; + const t_elfmemory* mapping = ELF->sectionss[symbolSectionIdx].meminfo; + + if(mapping == NULL) + return 0xFFFFFFFF; + // CM_ASSERT(elfhandle->segments[mapping->id].sumSize != 0); + // CM_ASSERT(elfhandle->sections[symbolSectionIdx].offsetInSegment != 0xFFFFFFFF); + + return elfhandle->segments[mapping->id].mpcAddr + + ELF->sectionss[symbolSectionIdx].offsetInSegment + + symbolOffet; +} + +#if 0 +t_bool ELFXX_getSymbolLocation( + const t_mpcal_memory *mpcalmemory, + t_elfdescription *elf, + char *symbolName, + const t_elfmemory **memory, + t_uint32 *offset) { + const ElfXX_Ehdr *header = (ElfXX_Ehdr*)elf->elfdata; + const ElfXX_Shdr *sections = (ElfXX_Shdr*)&elf->elfdata[swapXword(header->e_shoff)]; + const char *strings = &elf->elfdata[swapXword(sections[swapHalf(header->e_shstrndx)].sh_offset)]; + int len = cm_StringLength(symbolName, 256); // TO BE FIXED + int i; + + for(i = 0; i < ELF->e_shnum; i++) + { + ElfXX_Sym* symtab; + const char* strtab; + unsigned int size, j; + + if(ELF->sectionss[i].sh_type != SHT_SYMTAB && ELF->sectionss[i].sh_type != SHT_DYNSYM) continue; + + // Section is a symbol table + symtab = (ElfXX_Sym*)&elf->elfdata[swapXword(sections[i].sh_offset)]; + strtab = &elf->elfdata[swapXword(sections[swapWord(sections[i].sh_link)].sh_offset)]; + size = ELF->sectionss[i].sh_size / (unsigned int)swapXword(sections[i].sh_entsize); + + for(j = 0; j < size; j++) { + const char* foundName = &strtab[swapWord(symtab[j].st_name)]; + + if(cm_StringCompare(symbolName, foundName, len) == 0) { + if(swapHalf(symtab[j].st_shndx) != SHN_UNDEF) { + int sectionIdx = (int)swapHalf(symtab[j].st_shndx); + ElfXX_Xword sh_flags = swapXword(sections[sectionIdx].sh_flags); + + *memory = mpcalmemory->getMappingByName(&strings[swapWord(sections[sectionIdx].sh_name)], + sh_flags & SHF_WRITE ? MEM_RW : (sh_flags & SHF_EXECINSTR ? MEM_X : MEM_RO)); + *offset = (t_uint32)swapXword(symtab[j].st_value); + + return 1; + } + } + } + } + return 0; +} +#endif + +t_cm_error ELF64_relocateSegments( + t_memory_handle *memories, + t_elfdescription *elfhandle, + t_memory_property property, + void *cbContext) { + struct XXElf* ELF = elfhandle->ELF; + int sec, n; + + // Loop on all relocation section + for(sec=0; sec < ELF->e_shnum; sec++) + { + t_cm_logical_address sectionAddr = 0; + t_uint32 sectionOffset = 0; + const t_elfmemory* mapping; + + if(ELF->sectionss[sec].relocations == NULL) + continue; + + // Relocate only section in memory + mapping = getSectionAddress(memories, + elfhandle, + sec, + §ionOffset, + §ionAddr); + if(mapping == NULL) + continue; + + if( + (mapping->property == property && elfhandle->instanceProperty != MEM_FOR_SINGLETON) || + (property == MEM_SHARABLE && elfhandle->instanceProperty == MEM_FOR_SINGLETON) ) + { + LOG_INTERNAL(2, "relocSection(%s)\n", ELF->sectionss[sec].sectionName, 0, 0, 0, 0, 0); + + for(n = 0; n < ELF->sectionss[sec].relocationNumber; n++) + { + struct XXrelocation* relocation = &ELF->sectionss[sec].relocations[n]; + t_uint32 symbol_addr; + char* relocAddr = (char*)(sectionAddr + relocation->OffsetInElf * mapping->memEntSize); + + switch(relocation->st_shndx) { + case SHN_ABS: // Absolute external reference + symbol_addr = relocation->st_value; + break; + case SHN_UNDEF: // External reference + // LOG_INTERNAL(0, "cm_resolvSymbol(%d, %s)\n", relocation->type, relocation->symbol_name, 0,0, 0, 0); + symbol_addr = cm_resolvSymbol(cbContext, + relocation->type, + relocation->symbol_name, + relocAddr); + if(symbol_addr == 0x0) { // Not defined symbol + ERROR("Symbol %s not found\n", relocation->symbol_name, 0, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; + } else if(symbol_addr == 0xFFFFFFFE) { // OOM + return CM_NO_MORE_MEMORY; + } else if(symbol_addr == 0xFFFFFFFF) { // Defined inside static binding + continue; + } + break; + default: // Internal reference in loaded section + symbol_addr = getSymbolAddress( + memories, + elfhandle, + (t_uint32)relocation->st_shndx, + relocation->st_value); + if(symbol_addr == 0xFFFFFFFF) { + ERROR("Symbol in section %s+%d not loaded\n", + ELF->sectionss[relocation->st_shndx].sectionName, + relocation->st_value, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; + } + break; + } + + symbol_addr += relocation->r_addend; + + MMDSP_performRelocation( + relocation->type, + relocation->symbol_name, + symbol_addr, + relocAddr, + ELF->sectionss[sec].data + relocation->OffsetInElf * mapping->memEntSize, + sectionOffset + relocation->OffsetInElf); + } + } + } + + return CM_OK; +} + +t_cm_error ELF64_getRelocationMemory( + t_elfdescription *elfhandle, + t_tmp_elfdescription *elftmp, + t_uint32 offsetInNmf, + t_memory_reference *memory) { + struct XXElf* ELF = elfhandle->ELF; + const ElfXX_Rela* rel_start; + const ElfXX_Sym* relaNmfSegmentSymbols = (ElfXX_Sym*)elftmp->relaNmfSegmentSymbols; + + for(rel_start = (ElfXX_Rela*)elftmp->relaNmfSegment; rel_start < (ElfXX_Rela*)elftmp->relaNmfSegmentEnd; rel_start++) + { + if((t_uint32)swapXword(rel_start->r_offset) == offsetInNmf) + { + int strtab_index = ELFXX_R_SYM(swapXword(rel_start->r_info)); + int sectionIdx = (int)swapHalf(relaNmfSegmentSymbols[strtab_index].st_shndx); + + memory->memory = ELF->sectionss[sectionIdx].meminfo; + + if(memory->memory != NULL) { + memory->offset = ( + ELF->sectionss[sectionIdx].offsetInSegment + // Offset in Segment + (t_uint32)swapXword(relaNmfSegmentSymbols[strtab_index].st_value) + // Offset in Elf Section + (t_uint32)swapXword(rel_start->r_addend)); // Addend + + return CM_OK; + } else { + const char* symbol_name = &elftmp->relaNmfSegmentStrings[swapWord(relaNmfSegmentSymbols[strtab_index].st_name)]; + ERROR("Symbol %s not found\n", symbol_name, 0, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; + } + } + } + + ERROR("Unknown relocation error\n", 0, 0, 0, 0, 0, 0); + return CM_INVALID_ELF_FILE; +} diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c new file mode 100644 index 00000000000..0853e2d25b5 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c @@ -0,0 +1,287 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#define LOADMAP_SEMAPHORE_USE_NB 7 + +static t_memory_handle headerHandle[NB_CORE_IDS] = {INVALID_MEMORY_HANDLE, }; +static struct LoadMapHdr *headerAddresses[NB_CORE_IDS] = {0, }; +static t_uint32 headerOffsets[NB_CORE_IDS] = {0, }; + +t_cm_error cm_DSPABI_AddLoadMap( + t_cm_domain_id domainId, + const char* templateName, + const char* localname, + t_memory_handle *memories, + void *componentHandle) +{ + t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId); + + if (headerHandle[coreId] == 0) /* Create loadmap header */ + { + headerHandle[coreId] = cm_DM_Alloc(domainId, SDRAM_EXT16, + sizeof(struct LoadMapHdr)/2, CM_MM_ALIGN_2WORDS, TRUE); + if (headerHandle[coreId] == INVALID_MEMORY_HANDLE) + return CM_NO_MORE_MEMORY; + + headerAddresses[coreId] = (struct LoadMapHdr*)cm_DSP_GetHostLogicalAddress(headerHandle[coreId]); + + headerAddresses[coreId]->nMagicNumber = LOADMAP_MAGIC_NUMBER; + headerAddresses[coreId]->nVersion = (LOADMAP_VERSION_MSB<<8)|(LOADMAP_VERSION_LSB); + headerAddresses[coreId]->nRevision = 0; + headerAddresses[coreId]->pFirstItem = 0; + + //Register Header into XRAM:2 + cm_DSP_GetDspAddress(headerHandle[coreId], &headerOffsets[coreId]); + cm_DSP_WriteXRamWord(coreId, 2, headerOffsets[coreId]); + } + + // update Header nRevision field + headerAddresses[coreId]->nRevision++; + + /* + * Build loadmap entry + */ + { + t_memory_handle handle; + struct LoadMapItem* pItem; + t_uint32 dspentry; + unsigned char* pos; + t_uint32 fnlen, lnlen; + t_uint32 fnlenaligned, lnlenaligned; + t_uint32 address; + t_uint32 postStringLength; + int i; + + postStringLength = cm_StringLength(".elf", 16); + fnlenaligned = fnlen = cm_StringLength(templateName, MAX_COMPONENT_FILE_PATH_LENGTH) + postStringLength + 2; + if((fnlenaligned % 2) != 0) fnlenaligned++; + lnlenaligned = lnlen = cm_StringLength(localname, MAX_TEMPLATE_NAME_LENGTH); + if((lnlenaligned % 2) != 0) lnlenaligned++; + + // Allocate new loap map + handle = cm_DM_Alloc(domainId, SDRAM_EXT16, + sizeof(struct LoadMapItem)/2 + (1 + fnlenaligned/2) + (1 + lnlenaligned/2), + CM_MM_ALIGN_2WORDS, TRUE); + if (handle == INVALID_MEMORY_HANDLE) + return CM_NO_MORE_MEMORY; + + pItem = (struct LoadMapItem*)cm_DSP_GetHostLogicalAddress(handle); + cm_DSP_GetDspAddress(handle, &dspentry); + + // Link this new loadmap with the previous one + if(headerAddresses[coreId]->pFirstItem == NULL) + headerAddresses[coreId]->pFirstItem = (struct LoadMapItem *)dspentry; + else + { + struct LoadMapItem* curItem; + + curItem = headerAddresses[coreId]->pFirstItem; + curItem = (struct LoadMapItem*)(((t_uint32)curItem - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + while(curItem->pNextItem != NULL) + { + curItem = curItem->pNextItem; + curItem = (struct LoadMapItem*)(((t_uint32)curItem - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + } + curItem->pNextItem = (struct LoadMapItem *)dspentry; + } + + // DSP Address of the string at the end of the load map + pos = (unsigned char*)pItem + sizeof(struct LoadMapItem); + + /* + * Set SolibFilename address information + * -> string = "./origfilename" + */ + pItem->pSolibFilename = (char*)(dspentry + sizeof(struct LoadMapItem) / 2); + *(t_uint16*)pos = fnlen; + pos += 2; + *pos++ = '.'; + *pos++ = '\\'; + for(i = 0; i < fnlen - 2 - postStringLength; i++) + { + *pos++ = (templateName[i] == '.') ? '\\' : templateName[i]; + } + *pos++ = '.'; + *pos++ = 'e'; + *pos++ = 'l'; + *pos++ = 'f'; + // add padding if needed + if ((t_uint32)pos & 1) + *pos++ = '\0'; + + /* + * Set Component Name address information + */ + if (lnlen != 0) + { + pItem->pComponentName = (char*)(dspentry + sizeof(struct LoadMapItem) / 2 + 1 + fnlenaligned / 2); + + *(t_uint16*)pos = lnlen; + pos += 2; + for(i = 0; i < lnlenaligned; i++) + { + // If not aligned null ending copied + *pos++ = localname[i]; + } + } + else + { + pItem->pComponentName = 0; + } + + /* + * Set PROG information + */ + if(memories[CODE_MEMORY_INDEX] == INVALID_MEMORY_HANDLE) + address = 0; + else + cm_DSP_GetDspAddress(memories[CODE_MEMORY_INDEX], &address); + pItem->pAddrProg = (void*)address; + + /* + * Set ERAMCODE information + */ + if(memories[ECODE_MEMORY_INDEX] == INVALID_MEMORY_HANDLE) + address = 0; + else + cm_DSP_GetDspAddress(memories[ECODE_MEMORY_INDEX], &address); + pItem->pAddrEmbProg = (void*)address; + + /* + * Set THIS information + */ + if(memories[PRIVATE_DATA_MEMORY_INDEX] != INVALID_MEMORY_HANDLE) { + // Standard component + cm_DSP_GetDspAddress(memories[PRIVATE_DATA_MEMORY_INDEX], &address); + } else if(memories[SHARE_DATA_MEMORY_INDEX] != INVALID_MEMORY_HANDLE) { + // Singleton component where data are shared (simulate THIS with shared memory) + cm_DSP_GetDspAddress(memories[SHARE_DATA_MEMORY_INDEX], &address); + } else { + // Component without data (take unique identifier -> arbitrary take host component handle) + address = (t_uint32)componentHandle; + } + pItem->pThis = (void*)address; + + /* + * Set ARM THIS information + */ + pItem->pARMThis = componentHandle; + + /* + * Set Link to null (end of list) + */ + pItem->pNextItem = 0; + + /* + * Set XROM information + */ + if(memories[XROM_MEMORY_INDEX] == INVALID_MEMORY_HANDLE) + address = 0; + else + cm_DSP_GetDspAddress(memories[XROM_MEMORY_INDEX], &address); + pItem->pXROM = (void*)address; + + /* + * Set YROM information + */ + if(memories[YROM_MEMORY_INDEX] == INVALID_MEMORY_HANDLE) + address = 0; + else + cm_DSP_GetDspAddress(memories[YROM_MEMORY_INDEX], &address); + pItem->pYROM = (void*)address; + + /* + * Set memory handle (not used externally) + */ + pItem->memHandle = (void*)handle; + } + + OSAL_mb(); + + return CM_OK; +} + +t_cm_error cm_DSPABI_RemoveLoadMap( + t_cm_domain_id domainId, + const char* templateName, + t_memory_handle *memories, + const char* localname, + void *componentHandle) +{ + struct LoadMapItem* curItem, **prevItemReference; + t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId); + + CM_ASSERT (headerHandle[coreId] != INVALID_MEMORY_HANDLE); + + /* parse list until we find this */ + prevItemReference = &headerAddresses[coreId]->pFirstItem; + curItem = *prevItemReference; + while(curItem != NULL) + { + curItem = (struct LoadMapItem*)(((t_uint32)curItem - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + + if(curItem->pARMThis == componentHandle) + break; + + prevItemReference = &curItem->pNextItem; + curItem = *prevItemReference; + } + + + // Remove component from loadmap if founded + if(curItem != NULL) + { + /* take local semaphore */ + cm_DSP_SEM_Take(coreId,LOADMAP_SEMAPHORE_USE_NB); + + /* remove element from list */ + *prevItemReference = curItem->pNextItem; + + /* update nRevision field in header */ + headerAddresses[coreId]->nRevision++; + + /* If this is the last item, deallocate !!! */ + if(headerAddresses[coreId]->pFirstItem == NULL) + { + // Deallocate memory + cm_DM_Free(headerHandle[coreId], TRUE); + headerHandle[coreId] = INVALID_MEMORY_HANDLE; + + //Register Header into XRAM:2 + cm_DSP_WriteXRamWord(coreId, 2, 0); + } + + /* deallocate memory */ + cm_DM_Free((t_memory_handle)curItem->memHandle, TRUE); + + /* be sure memory is updated before releasing local semaphore */ + OSAL_mb(); + + /* release local semaphore */ + cm_DSP_SEM_Give(coreId,LOADMAP_SEMAPHORE_USE_NB); + } + else + { + ERROR("Component not in LoadMap %s, memory corruption????\n", localname, 0, 0, 0, 0, 0); + } + + return CM_OK; +} diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c b/drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c new file mode 100644 index 00000000000..93d910a5ed6 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/mpcal.c @@ -0,0 +1,6 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h new file mode 100644 index 00000000000..3f995982088 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef __INC_EE_MGT_H +#define __INC_EE_MGT_H + +#include +#include + +typedef struct { + t_component_instance *instance; + t_nmf_executive_engine_id executiveEngineId; + t_uint32 currentStackSize[NMF_SCHED_URGENT + 1]; + t_uint32 voidAddr; + t_uint32 traceState; + t_uint32 printLevel; + t_uint32 nbOfForceWakeup; +} t_ee_state; + +//TODO, juraj, this should be done more properly, like accessor method, instead making this global variable.. +extern t_ee_state eeState[NB_CORE_IDS]; + +/******************************************************************************/ +/************************ FUNCTIONS PROTOTYPES ********************************/ +/******************************************************************************/ + +PUBLIC t_cm_error cm_EEM_Init(t_nmf_core_id coreId, const char *eeName, t_nmf_executive_engine_id executiveEngineId); +PUBLIC void cm_EEM_Close(t_nmf_core_id coreId); +PUBLIC t_uint32 cm_EEM_isStackUpdateNeed(t_nmf_core_id coreId, t_nmf_ee_priority priority, t_uint32 isInstantiate, t_uint32 needMinStackSize); +PUBLIC t_cm_error cm_EEM_UpdateStack(t_nmf_core_id coreId, t_nmf_ee_priority priority, t_uint32 needMinStackSize, t_uint32 *pNewStackValue); +PUBLIC t_ee_state* cm_EEM_getExecutiveEngine(t_nmf_core_id coreId); +PUBLIC void cm_EEM_setTraceMode(t_nmf_core_id coreId, t_uint32 state); +PUBLIC void cm_EEM_setPrintLevel(t_nmf_core_id coreId, t_uint32 level); +t_cm_error cm_EEM_ForceWakeup(t_nmf_core_id coreId); +void cm_EEM_AllowSleep(t_nmf_core_id coreId); + +#endif /* __INC_EE_MGT_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c new file mode 100644 index 00000000000..14889ec6e4d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c @@ -0,0 +1,349 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*----------------------------------------------------------------------------* + * This module provides functions that allow to manage DSPs' Firmwares. * + ******************************************************************************/ + + +/******************************************************************* Includes + ****************************************************************************/ + +#include "../inc/executive_engine_mgt.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +t_ee_state eeState[NB_CORE_IDS]; + +/****************************************************************** Functions + ****************************************************************************/ + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetExecutiveEngineHandle( + t_cm_domain_id domainId, + t_cm_instance_handle *executiveEngineHandle) +{ + t_nmf_core_id coreId; + + if (cm_DM_CheckDomain(domainId, DOMAIN_NORMAL) != CM_OK) { + return CM_INVALID_DOMAIN_HANDLE; + } + + coreId = cm_DM_GetDomainCoreId(domainId); + //in case someone ask for ee on component manager !!!! + if (coreId == ARM_CORE_ID) {*executiveEngineHandle = 0;} + else {*executiveEngineHandle = eeState[coreId].instance->instance;} + + return CM_OK; +} + +PUBLIC t_cm_error cm_EEM_Init( + t_nmf_core_id coreId, + const char *eeName, + t_nmf_executive_engine_id executiveEngineId) +{ + t_rep_component *pRepComponent; + t_cm_error error; + t_uint32 i; + + eeState[coreId].instance = (t_component_instance *)0; + eeState[coreId].executiveEngineId = executiveEngineId; + for(i = NMF_SCHED_BACKGROUND; i < NMF_SCHED_URGENT + 1;i++) + { + eeState[coreId].currentStackSize[i] = MIN_STACK_SIZE; + } + + // Try to load component file + if((error = cm_REP_lookupComponent(eeName, &pRepComponent)) != CM_OK) + { + if (error == CM_COMPONENT_NOT_FOUND) + ERROR("CM_COMPONENT_NOT_FOUND: Execution Engine %s\n", eeName, 0, 0, 0, 0, 0); + return error; + } + + // Set to 1 during bootstrap since MMDSP forceWakeup is to one also in order to not go in idle state + // while configuration not finish !!! + eeState[coreId].nbOfForceWakeup = 1; + + if ((error = cm_DSP_Boot(coreId)) != CM_OK) + return error; + + if((error = cm_instantiateComponent( + eeName, + cm_DSP_GetState(coreId)->domainEE, + NMF_SCHED_URGENT, + eeName, + pRepComponent->elfhandle, + &eeState[coreId].instance)) != CM_OK) + { + cm_DSP_Shutdown(coreId); + return error; + } + + /* Get Void Function */ + eeState[coreId].voidAddr = cm_getFunction(eeState[coreId].instance, "helper", "Void"); + + /* allocate xram space for stack */ + if (executiveEngineId == SYNCHRONOUS_EXECUTIVE_ENGINE) + { + error = cm_DSP_setStackSize(coreId, MIN_STACK_SIZE); + } + else + { + error = cm_DSP_setStackSize(coreId, (NMF_SCHED_URGENT + 1) * MIN_STACK_SIZE); + } + if (error != CM_OK) + { + cm_delayedDestroyComponent(eeState[coreId].instance); + eeState[coreId].instance = (t_component_instance *)0; + cm_DSP_Shutdown(coreId); + return error; + } + + /* allocate sdram memory to share perfmeters data */ + error = cm_PFM_allocatePerfmeterDataMemory(coreId, cm_DSP_GetState(coreId)->domainEE); + if (error != CM_OK) { + cm_delayedDestroyComponent(eeState[coreId].instance); + eeState[coreId].instance = (t_component_instance *)0; + cm_DSP_Shutdown(coreId); + return error; + } + + /* set initial stack value */ + cm_writeAttribute(eeState[coreId].instance, "rtos/scheduler/topOfStack", cm_DSP_getStackAddr(coreId)); + + /* set myCoreId for trace */ + cm_writeAttribute(eeState[coreId].instance, "xti/myCoreId", coreId - 1); + +#if defined(__STN_8500) && (__STN_8500 > 10) + /* set myCoreId for prcmu if exist */ + cm_writeAttribute(eeState[coreId].instance, "sleep/prcmu/myCoreId", coreId + 1); +#endif + + /* go go go ... */ + cm_DSP_Start(coreId); + + /* Waiting for End Of Boot */ + //TODO : remove infinite while loop + //TODO : to be paranoiac, add a read to serviceReasonOffset before starting core and check value is MPC_SERVICE_BOOT as it should be + { + while(cm_readAttributeNoError(eeState[coreId].instance, "rtos/commonpart/serviceReason") == MPC_SERVICE_BOOT) + { + volatile t_uint32 i; + for (i=0; i < 1000; i++); + } + } + + /* set some attributes after boot to avoid being erase by mmdsp boot */ + cm_writeAttribute(eeState[coreId].instance, "xti/traceActive", eeState[coreId].traceState); + cm_writeAttribute(eeState[coreId].instance, "rtos/commonpart/printLevel", eeState[coreId].printLevel); + + cm_DSP_ConfigureAfterBoot(coreId); + + return CM_OK; +} + +/****************************************************************************/ +/* NAME: cm_EEM_Close */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: Inform us that ee for coreId has been destroyed */ +/* */ +/* PARAMETERS: id: dsp identifier */ +/* */ +/* RETURN: none */ +/* */ +/****************************************************************************/ +PUBLIC void cm_EEM_Close(t_nmf_core_id coreId) +{ + cm_DSP_setStackSize(coreId, 0); + cm_delayedDestroyComponent(eeState[coreId].instance); + eeState[coreId].instance = (t_component_instance *)0; + cm_PFM_deallocatePerfmeterDataMemory(coreId); + + cm_DSP_Shutdown(coreId); +} + +/****************************************************************************/ +/* NAME: cm_EEM_isStackUpdateNeed( */ +/* t_nmf_core_id id, */ +/* t_nmf_ee_priority priority, */ +/* t_uint32 isInstantiate, */ +/* t_uint32 needMinStackSize */ +/* ) */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: Return a boolean to inform if a ee stack size update is need*/ +/* when instantiate or destroying a component */ +/****************************************************************************/ +PUBLIC t_uint32 cm_EEM_isStackUpdateNeed( + t_nmf_core_id coreId, + t_nmf_ee_priority priority, + t_uint32 isInstantiate, + t_uint32 needMinStackSize) +{ + /* in case of SYNCHRONOUS_EXECUTIVE_ENGINE we only use currentStackSize[NMF_SCHED_BACKGROUND] */ + if (eeState[coreId].executiveEngineId == SYNCHRONOUS_EXECUTIVE_ENGINE) {priority = NMF_SCHED_BACKGROUND;} + if (isInstantiate) + { + if (needMinStackSize > eeState[coreId].currentStackSize[priority]) {return TRUE;} + } + else + { + if (needMinStackSize == eeState[coreId].currentStackSize[priority]) {return TRUE;} + } + + return FALSE; +} + +/****************************************************************************/ +/* NAME: cm_EEM_UpdateStack( */ +/* t_nmf_core_id id, */ +/* t_nmf_ee_priority priority, */ +/* t_uint32 needMinStackSize, */ +/* t_uint32 *pNewStackValue */ +/* ) */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: If cm_EEM_isStackUpdateNeed() has return true then caller */ +/* must inform EEM about new stack value for priority. */ +/* cm_EEM_UpdateStack() will return new global stack size to */ +/* provide to ee. */ +/****************************************************************************/ +PUBLIC t_cm_error cm_EEM_UpdateStack( + t_nmf_core_id coreId, + t_nmf_ee_priority priority, + t_uint32 needMinStackSize, + t_uint32 *pNewStackValue) +{ + t_cm_error error; + t_uint32 recoveryStackSize = eeState[coreId].currentStackSize[priority]; + t_uint32 i; + + /* in case of SYNCHRONOUS_EXECUTIVE_ENGINE we only use currentStackSize[NMF_SCHED_BACKGROUND] */ + if (eeState[coreId].executiveEngineId == SYNCHRONOUS_EXECUTIVE_ENGINE) {priority = NMF_SCHED_BACKGROUND;} + eeState[coreId].currentStackSize[priority] = needMinStackSize; + if (eeState[coreId].executiveEngineId == SYNCHRONOUS_EXECUTIVE_ENGINE) {*pNewStackValue = needMinStackSize;} + else + { + *pNewStackValue = 0; + for(i = NMF_SCHED_BACKGROUND; i < NMF_SCHED_URGENT + 1;i++) + { + *pNewStackValue += eeState[coreId].currentStackSize[i]; + } + } + + /* try to increase size of stack by modifying xram allocator size */ + error = cm_DSP_setStackSize(coreId, *pNewStackValue); + if (error != CM_OK) { + eeState[coreId].currentStackSize[priority] = recoveryStackSize; + } else { + LOG_INTERNAL(1, "\n##### Stack update: size=%d, prio=%d on %s #####\n", *pNewStackValue, priority, cm_getDspName(coreId), 0, 0, 0); + } + + return error; +} + +/****************************************************************************/ +/* NAME: t_nmf_executive_engine_id( */ +/* t_nmf_core_id id */ +/* ) */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: return executive engine load on id core. */ +/****************************************************************************/ +PUBLIC t_ee_state * cm_EEM_getExecutiveEngine(t_nmf_core_id coreId) +{ + return &eeState[coreId]; +} + +/****************************************************************************/ +/* NAME: cm_EEM_setTraceMode( */ +/* t_nmf_core_id id, */ +/* t_uint32 state */ +/* ) */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: activate/deactivate trace for ee running on id. In case ee */ +/* is not yet load then information is store. */ +/****************************************************************************/ +PUBLIC void cm_EEM_setTraceMode(t_nmf_core_id coreId, t_uint32 state) +{ + eeState[coreId].traceState = state; + if (eeState[coreId].instance) + { + if(cm_EEM_ForceWakeup(coreId) == CM_OK) + { + cm_writeAttribute(eeState[coreId].instance, "xti/traceActive", eeState[coreId].traceState); + + cm_EEM_AllowSleep(coreId); + } + } +} + +/****************************************************************************/ +/* NAME: cm_EEM_setPrintLevel( */ +/* t_nmf_core_id id, */ +/* t_uint32 level */ +/* ) */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: set print level for ee running on id. In case ee */ +/* is not yet load then information is store. */ +/****************************************************************************/ +PUBLIC void cm_EEM_setPrintLevel(t_nmf_core_id coreId, t_uint32 level) +{ + eeState[coreId].printLevel = level; + if (eeState[coreId].instance) + { + if(cm_EEM_ForceWakeup(coreId) == CM_OK) + { + cm_writeAttribute(eeState[coreId].instance, "rtos/commonpart/printLevel", eeState[coreId].printLevel); + + cm_EEM_AllowSleep(coreId); + } + } +} + +t_cm_error cm_EEM_ForceWakeup(t_nmf_core_id coreId) +{ + if(eeState[coreId].nbOfForceWakeup++ == 0) + { + t_cm_error error; + + LOG_INTERNAL(2, "ARM: Try to wake up\n", 0, 0, 0, 0, 0, 0); + + if (cm_DSP_GetState(coreId)->state != MPC_STATE_BOOTED) + { + return CM_MPC_NOT_RESPONDING; + } + else if ((error = cm_COMP_ULPForceWakeup(coreId)) != CM_OK) + { + if (error == CM_MPC_NOT_RESPONDING) { + ERROR("CM_MPC_NOT_RESPONDING: DSP %s can't be wakeup'ed\n", cm_getDspName(coreId), 0, 0, 0, 0, 0); + cm_DSP_SetStatePanic(coreId); + } + return error; + } + } + return CM_OK; +} + +void cm_EEM_AllowSleep(t_nmf_core_id coreId) +{ + if(--eeState[coreId].nbOfForceWakeup == 0) + { + LOG_INTERNAL(2, "ARM: Allow sleep\n", 0, 0, 0, 0, 0, 0); + + if (cm_DSP_GetState(coreId)->state != MPC_STATE_BOOTED) + { + } + else if (cm_COMP_ULPAllowSleep(coreId) != CM_OK) + { + ERROR("CM_MPC_NOT_RESPONDING: DSP %s can't be allow sleep'ed\n", cm_getDspName(coreId), 0, 0, 0, 0, 0); + } + } +} diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/chunk_mgr.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/chunk_mgr.h new file mode 100644 index 00000000000..340301a9259 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/chunk_mgr.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef CHUNK_MGR_H_ +#define CHUNK_MGR_H_ + +#include +#include + +t_cm_error allocChunkPool(void); +t_cm_error fillChunkPool(void); +void freeChunkPool(void); + +/***************************************************************************/ +/* + * allocChunk + * param current : Pointer on chunck to free + * + * Add a chunk in the chunck list + * + */ +/***************************************************************************/ +t_cm_chunk* allocChunk(void); + +/***************************************************************************/ +/* + * freeChunk + * param current : Pointer on chunck to free + * + * Remove a chunk in the chunck list + * + */ +/***************************************************************************/ +void freeChunk(t_cm_chunk *chunk); + +#endif /*CHUNK_MGR_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h new file mode 100644 index 00000000000..bf75915c259 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h @@ -0,0 +1,154 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/***************************************************************************/ +/* file : domain.h + * author : NMF team + * version : 1.0 + * + * brief : NMF domain definitions + */ +/***************************************************************************/ + +#ifndef DOMAIN_H_ +#define DOMAIN_H_ + +#include +#include +#include +#include + +/*! + * \brief Domain type. + * \internal + * \ingroup CM_DOMAIN_API + */ +typedef enum { + DOMAIN_ANY = 0, + DOMAIN_NORMAL, + DOMAIN_SCRATCH_PARENT, + DOMAIN_SCRATCH_CHILD +} t_cm_domain_type; + +/*! + * \brief Domain descriptor. Holds offsets for all memory types present in the system. + * \internal + * \ingroup CM_DOMAIN_API + */ +typedef struct { + t_cm_domain_memory domain; // the actual memory ranges + t_cm_domain_type type; // domain type + t_uint32 refcount; // reference counter for scratch domain dependencies + t_nmf_client_id client; // client id for cleaning + + union { + struct { + t_memory_handle handle; // memory handle of the allocated chunk the covers the esram-data scratch region + } parent; + struct { + t_cm_allocator_desc *alloc; //allocator descriptor for the scratch domain + t_cm_domain_id parent_ref; //parent domain reference + } child; + } scratch; +} t_cm_domain_desc; + +#ifdef DEBUG +#define DOMAIN_DEBUG(handle) \ + handle = handle & ~0xc0; +#else +#define DOMAIN_DEBUG(handle) +#endif + +/*! + * \brief Domain descriptor array. + */ +extern t_cm_domain_desc domainDesc[]; + +typedef struct { + t_cm_domain_id parentId; + t_cm_domain_id domainId; + t_cm_allocator_desc *allocDesc; +} t_cm_domain_scratch_desc; + +extern t_cm_domain_scratch_desc domainScratchDesc[]; + +typedef struct { + t_cm_system_address sdramCode; + t_cm_system_address sdramData; + t_cm_system_address esramCode; + t_cm_system_address esramData; +} t_cm_domain_info; + +/*! + * \brief Init of the domain subsystem. + */ +PUBLIC t_cm_error cm_DM_Init(void); + +/*! + * \brief Clean-up of the domain subsystem. + */ +PUBLIC void cm_DM_Destroy(void); + +/*! + * \brief Domain creation. + * + * Allocates in slot in the domain descriptors array and copies segment infos from the domain + * parameter to the descriptor. The resulting handle is returned via @param handle. + * + * Returns: CM_DOMAIN_INVALID in case of error, otherwise CM_OK. + */ +PUBLIC t_cm_error cm_DM_CreateDomain(const t_nmf_client_id client, const t_cm_domain_memory *domain, t_cm_domain_id *handle); + +/*! + * \brief Scratch (or overlap) domain creation. + * + * Create a scratch domain, ie domain where allocation may overlap. + */ +PUBLIC t_cm_error cm_DM_CreateDomainScratch(const t_nmf_client_id client, const t_cm_domain_id parentId, const t_cm_domain_memory *domain, t_cm_domain_id *handle); + +/* ! + * \brief Retrieve the coreId from a given domain. Utility. + */ +PUBLIC t_nmf_core_id cm_DM_GetDomainCoreId(const t_cm_domain_id domainId); + +/*! + * \brief Destroy all domains belonging to a given client. + */ +PUBLIC t_cm_error cm_DM_DestroyDomains(const t_nmf_client_id client); + +/*! + * \brief Destroy a given domain. + */ +PUBLIC t_cm_error cm_DM_DestroyDomain(t_cm_domain_id handle); + +/*! + * \brief Check if the handle is valid. + */ +PUBLIC t_cm_error cm_DM_CheckDomain(t_cm_domain_id handle, t_cm_domain_type type); +PUBLIC t_cm_error cm_DM_CheckDomainWithClient(t_cm_domain_id handle, t_cm_domain_type type, t_nmf_client_id client); + +/*! + * \brief Memory allocation in a given domain, for a given memory type (see CM_AllocMpcMemory). + */ +PUBLIC t_memory_handle cm_DM_Alloc(t_cm_domain_id domainId, t_dsp_memory_type_id memType, t_uint32 size, t_cm_mpc_memory_alignment memAlignment, t_bool powerOn); + +/*! + * \brief Memory free using a given domain handle + */ +PUBLIC void cm_DM_FreeWithInfo(t_memory_handle memHandle, t_nmf_core_id *coreId, t_dsp_memory_type_id *memType, t_bool powerOff); + +/*! + * \brief Memory free using a given domain handle + */ +PUBLIC void cm_DM_Free(t_memory_handle memHandle, t_bool powerOff); + +/*! + * \brief Wrapper function for CM_GetMpcMemoryStatus. + */ +PUBLIC t_cm_error cm_DM_GetAllocatorStatus(t_cm_domain_id domainId, t_dsp_memory_type_id memType, t_cm_allocator_status *pStatus); + +PUBLIC t_cm_error cm_DM_GetDomainAbsAdresses(t_cm_domain_id domainId, t_cm_domain_info *info); + +#endif /* DOMAIN_H_ */ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h new file mode 100644 index 00000000000..712d077d894 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/***************************************************************************/ +/* file : domain.h + * author : NMF team + * version : 1.0 + * + * brief : NMF domain definitions + */ +/***************************************************************************/ + +#ifndef DOMAIN_TYPE_H_ +#define DOMAIN_TYPE_H_ + +#include +#include + +/*! + * \brief Domain identifier + * \ingroup CM_DOMAIN_API + */ +typedef t_uint8 t_cm_domain_id; + +/*! + * \brief Client identifier + * 0 (zero) is considered as an invalid or 'NO' client identifier + * \ingroup CM_DOMAIN_API + */ +typedef t_uint32 t_nmf_client_id; +// TO BE REMOVED LATER, I guess, when default domains will be removed (PP) +#define NMF_CORE_CLIENT (t_nmf_client_id)-1 +#define NMF_CURRENT_CLIENT (t_nmf_client_id)0 + +typedef struct { + t_uint32 offset; //!< offset relativ to segment start in memory (in bytes) + t_uint32 size; //!< size in bytes of the domain segment +} t_cm_domain_segment; + +/*! + * \brief Domain memory description structure + * \ingroup CM_DOMAIN_API + */ +typedef struct { + t_nmf_core_id coreId; //!< MMDSP Core Id for this domain (used for TCM-X and TCM-Y at instantiate) + t_cm_domain_segment esramCode; //!< ESRAM code segment + t_cm_domain_segment esramData; //!< ESRAM data segment + t_cm_domain_segment sdramCode; //!< SDRAM code segment + t_cm_domain_segment sdramData; //!< SDRAM data segment +} t_cm_domain_memory; + +#define INIT_DOMAIN_SEGMENT {0, 0} +#define INIT_DOMAIN {MASK_ALL8, INIT_DOMAIN_SEGMENT, INIT_DOMAIN_SEGMENT, INIT_DOMAIN_SEGMENT, INIT_DOMAIN_SEGMENT} + + +#endif /* DOMAIN_TYPE_H_ */ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/memory.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/memory.h new file mode 100644 index 00000000000..c6d1fb2dfff --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/memory.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Internal Memory Management API. + * + * \defgroup MEMORY_INTERNAL Private Memory API. + * + */ +#ifndef __INC_MEMORY_H +#define __INC_MEMORY_H + +#include +#include + +#endif /* __INC_MEMORY_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h new file mode 100644 index 00000000000..91246f1ec0e --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h @@ -0,0 +1,152 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Public Component Manager Memory API type. + * + * This file contains the Component Manager API type for manipulating memory. + */ +#ifndef __INC_MEMORY_TYPE_H +#define __INC_MEMORY_TYPE_H + +#include + +/*! + * @defgroup t_cm_mpc_memory_type t_cm_mpc_memory_type + * \brief Definition of symbols used to reference the various type of Media Processor Core adressable memory + * @{ + * \ingroup MEMORY + */ +typedef t_uint8 t_cm_mpc_memory_type; //!< Fake enumeration type +#define CM_MM_MPC_TCM16_X ((t_cm_mpc_memory_type)0) +#define CM_MM_MPC_TCM24_X ((t_cm_mpc_memory_type)1) +#define CM_MM_MPC_ESRAM16 ((t_cm_mpc_memory_type)2) +#define CM_MM_MPC_ESRAM24 ((t_cm_mpc_memory_type)3) +#define CM_MM_MPC_SDRAM16 ((t_cm_mpc_memory_type)4) +#define CM_MM_MPC_SDRAM24 ((t_cm_mpc_memory_type)5) +#define CM_MM_MPC_TCM16_Y ((t_cm_mpc_memory_type)6) +#define CM_MM_MPC_TCM24_Y ((t_cm_mpc_memory_type)7) +#define CM_MM_MPC_TCM16 CM_MM_MPC_TCM16_X +#define CM_MM_MPC_TCM24 CM_MM_MPC_TCM24_X + +/* @} */ + +/*! + * @defgroup t_cm_memory_alignment t_cm_memory_alignment + * \brief Definition of symbols used to constraint the alignment of the allocated memory + * @{ + * \ingroup MEMORY + */ +typedef t_uint16 t_cm_memory_alignment; //!< Fake enumeration type +#define CM_MM_ALIGN_NONE ((t_cm_memory_alignment)0x00000000) +#define CM_MM_ALIGN_BYTE ((t_cm_memory_alignment)CM_MM_ALIGN_NONE) +#define CM_MM_ALIGN_HALFWORD ((t_cm_memory_alignment)0x00000001) +#define CM_MM_ALIGN_WORD ((t_cm_memory_alignment)0x00000003) +#define CM_MM_ALIGN_2WORDS ((t_cm_memory_alignment)0x00000007) +#define CM_MM_ALIGN_16BYTES ((t_cm_memory_alignment)0x0000000F) +#define CM_MM_ALIGN_4WORDS ((t_cm_memory_alignment)0x0000000F) +#define CM_MM_ALIGN_AHB_BURST ((t_cm_memory_alignment)0x0000000F) +#define CM_MM_ALIGN_32BYTES ((t_cm_memory_alignment)0x0000001F) +#define CM_MM_ALIGN_8WORDS ((t_cm_memory_alignment)0x0000001F) +#define CM_MM_ALIGN_64BYTES ((t_cm_memory_alignment)0x0000003F) +#define CM_MM_ALIGN_16WORDS ((t_cm_memory_alignment)0x0000003F) +#define CM_MM_ALIGN_128BYTES ((t_cm_memory_alignment)0x0000007F) +#define CM_MM_ALIGN_32WORDS ((t_cm_memory_alignment)0x0000007F) +#define CM_MM_ALIGN_256BYTES ((t_cm_memory_alignment)0x000000FF) +#define CM_MM_ALIGN_64WORDS ((t_cm_memory_alignment)0x000000FF) +#define CM_MM_ALIGN_512BYTES ((t_cm_memory_alignment)0x000001FF) +#define CM_MM_ALIGN_128WORDS ((t_cm_memory_alignment)0x000001FF) +#define CM_MM_ALIGN_1024BYTES ((t_cm_memory_alignment)0x000003FF) +#define CM_MM_ALIGN_256WORDS ((t_cm_memory_alignment)0x000003FF) +#define CM_MM_ALIGN_2048BYTES ((t_cm_memory_alignment)0x000007FF) +#define CM_MM_ALIGN_512WORDS ((t_cm_memory_alignment)0x000007FF) +#define CM_MM_ALIGN_4096BYTES ((t_cm_memory_alignment)0x00000FFF) +#define CM_MM_ALIGN_1024WORDS ((t_cm_memory_alignment)0x00000FFF) +#define CM_MM_ALIGN_65536BYTES ((t_cm_memory_alignment)0x0000FFFF) +#define CM_MM_ALIGN_16384WORDS ((t_cm_memory_alignment)0x0000FFFF) +/* @} */ + +/*! + * @defgroup t_cm_mpc_memory_alignment t_cm_mpc_memory_alignment + * \brief Definition of symbols used to constraint the alignment of the allocated mpc memory + * @{ + * \ingroup MEMORY + */ +typedef t_uint16 t_cm_mpc_memory_alignment; //!< Fake enumeration type +#define CM_MM_MPC_ALIGN_NONE ((t_cm_mpc_memory_alignment)0x00000000) +#define CM_MM_MPC_ALIGN_HALFWORD ((t_cm_mpc_memory_alignment)0x00000001) +#define CM_MM_MPC_ALIGN_WORD ((t_cm_mpc_memory_alignment)0x00000003) +#define CM_MM_MPC_ALIGN_2WORDS ((t_cm_mpc_memory_alignment)0x00000007) +#define CM_MM_MPC_ALIGN_4WORDS ((t_cm_mpc_memory_alignment)0x0000000F) +#define CM_MM_MPC_ALIGN_8WORDS ((t_cm_mpc_memory_alignment)0x0000001F) +#define CM_MM_MPC_ALIGN_16WORDS ((t_cm_mpc_memory_alignment)0x0000003F) +#define CM_MM_MPC_ALIGN_32WORDS ((t_cm_mpc_memory_alignment)0x0000007F) +#define CM_MM_MPC_ALIGN_64WORDS ((t_cm_mpc_memory_alignment)0x000000FF) +#define CM_MM_MPC_ALIGN_128WORDS ((t_cm_mpc_memory_alignment)0x000001FF) +#define CM_MM_MPC_ALIGN_256WORDS ((t_cm_mpc_memory_alignment)0x000003FF) +#define CM_MM_MPC_ALIGN_512WORDS ((t_cm_mpc_memory_alignment)0x000007FF) +#define CM_MM_MPC_ALIGN_1024WORDS ((t_cm_mpc_memory_alignment)0x00000FFF) +#define CM_MM_MPC_ALIGN_65536BYTES ((t_cm_mpc_memory_alignment)0x0000FFFF) +#define CM_MM_MPC_ALIGN_16384WORDS ((t_cm_mpc_memory_alignment)0x0000FFFF) +/* @} */ + +/*! + * \brief Identifier of a memory handle + * \ingroup MEMORY + */ +typedef t_uint32 t_cm_memory_handle; + +/*! + * \brief Description of a memory segment + * + * <=> allocable addressable space + * \ingroup MEMORY + */ +typedef struct { + t_cm_system_address systemAddr; //!< Logical AND physical segment start address + t_uint32 size; //!< segment size (in bytes) +} t_nmf_memory_segment; +#define INIT_MEMORY_SEGMENT {{0, 0}, 0} + +/*! + * \brief Definition of structure used for an allocator status + * \ingroup MEMORY + */ +typedef struct +{ + struct { + t_uint32 size; //!< size of the allocator + /* Block counters */ + t_uint16 used_block_number; //!< used block number + t_uint16 free_block_number; //!< free block number + + /* Free memory min/max */ + t_uint32 maximum_free_size; //!< maximum free size + t_uint32 minimum_free_size; //!< minimum free size + + /* Accumulation of free and used memory */ + t_uint32 accumulate_free_memory; //!< accumulate free memory + t_uint32 accumulate_used_memory; //!< accumulate used memory + } global; + + struct { + t_uint32 size; //!< size of the domain + t_uint32 maximum_free_size; //!< maximum free size in the given domain + t_uint32 minimum_free_size; //!< minimum free size in the given domain + t_uint32 accumulate_free_memory; //all free memory of the given domain + t_uint32 accumulate_used_memory; //all used memory of the given domain + } domain; + + struct { + t_uint32 sizes[3]; + } stack[NB_CORE_IDS]; + +} t_cm_allocator_status; + +#endif /* __INC_MEMORY_TYPE_H */ + diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/migration.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/migration.h new file mode 100644 index 00000000000..824d25374b3 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/migration.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Migration API. + * + * \defgroup + * + */ +#ifndef __INC_MIGRATION_H +#define __INC_MIGRATION_H + +#include +#include + +typedef enum { + STATE_MIGRATED = 1, + STATE_NORMAL = 0, +} t_cm_migration_state; + +PUBLIC t_cm_error cm_migrate(const t_cm_domain_id srcShared, const t_cm_domain_id src, const t_cm_domain_id dst); + +PUBLIC t_cm_error cm_unmigrate(void); + +PUBLIC t_uint32 cm_migration_translate(t_dsp_segment_type segmentType, t_uint32 addr); + +PUBLIC void cm_migration_check_state(t_nmf_core_id coreId, t_cm_migration_state expected); + +#endif /* __INC_MIGRATION_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h new file mode 100644 index 00000000000..e639c94cb46 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h @@ -0,0 +1,262 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + * + * \note: In this module, we assume that parameters were checked !! + */ +#ifndef __REMOTE_ALLOCATOR_H_ +#define __REMOTE_ALLOCATOR_H_ + +/* + * Include + */ +#include +#include + + +/* + * Description of the memory block status + */ +typedef enum { + MEM_USED = 0, /* Memory block is used */ + MEM_FREE = 1 /* Memory block is free */ +} t_mem_status; + +/* + * Chunk structure. + */ +struct cm_allocator_desc; +typedef struct chunk_struct +{ + /* Double linked list of chunks */ + struct chunk_struct *prev; + struct chunk_struct *next; + + /* Double linked list of free memory */ + struct chunk_struct *prev_free_mem; + struct chunk_struct *next_free_mem; + + /* Offset of the block memory */ + t_uint32 offset; + + /* Size of the block memory */ + t_cm_size size; + + /* Status of the block memory */ + t_mem_status status; + + /* User data */ + t_uint16 userData; + + /* Alloc debug info*/ + t_uint32 domainId; + + /* Alloc desc backlink */ + struct cm_allocator_desc *alloc; +} t_cm_chunk; + +/*! + * \brief Identifier of an internal memory handle + * \ingroup MEMORY_INTERNAL + */ +typedef t_cm_chunk* t_memory_handle; + +#define INVALID_MEMORY_HANDLE ((t_cm_chunk*)NULL) + + +/* + * Context structure + */ +#define BINS 63 + +//TODO, juraj, add memType to alloc struct ? +typedef struct cm_allocator_desc { + const char *pAllocName; /* Name of the allocator */ + t_uint32 size; /* Size of the allocator */ + t_cm_chunk *chunks; /* Array of chunk */ + t_cm_chunk *free_mem_chunks[BINS]; /* List of free memory */ + struct cm_allocator_desc* next; /* List of allocator */ +} t_cm_allocator_desc; + +int bin_index(unsigned int sz); + +/* + * Functions + */ +/*! + * \brief Create a new allocator for a piece of memory (hw mapped (xram, yram)) + * Any further allocation into this piece of memory will return an offset inside it. + * (a constant offset value can be added to this offset) + * + * \retval t_cm_allocator_desc* new memory allocator identifier + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC t_cm_allocator_desc* cm_MM_CreateAllocator( + t_cm_size size, //!< [in] Size of the addressable space in bytes + t_uint32 offset, //!< [in] Constant offset to add to each allocated block base address + const char* name //!< [in] Name of the allocator + ); + +/*! + * \brief Free a memory allocator descriptor + * + * \retval t_cm_error + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC t_cm_error cm_MM_DeleteAllocator( + t_cm_allocator_desc* alloc //!< [in] Identifier of the memory allocator to be freed + ); + + +/*! + * \brief Resize an allocator to the size value. + * + * \retval t_cm_error + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC t_cm_error cm_MM_ResizeAllocator( + t_cm_allocator_desc* alloc, //!< [in] Identifier of the memory allocator used to allocate the piece of memory + t_cm_size size //!< [in] Size of the addressable space in allocDesc granularity + ); + +/*! + * \brief Check validity of a user handle + */ +t_cm_error cm_MM_getValidMemoryHandle(t_cm_memory_handle handle, t_memory_handle* validHandle); + +/*! + * \brief Wrapper routine to allocate some memory into a given allocator + * + * \retval t_memory_handle handle on the new allocated piece of memory + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC t_memory_handle cm_MM_Alloc( + t_cm_allocator_desc* alloc, //!< [in] Identifier of the memory allocator + t_cm_size size, //!< [in] Size of the addressable space + t_cm_memory_alignment memAlignment, //!< [in] Alignment constraint + t_uint32 seg_offset, //!< [in] Offset of range where allocating + t_uint32 seg_size, //!< [in] Size of range where allocating + t_uint32 domainId + ); + + +/*! + * \brief Routine to reallocate memory for a given handle + * + * Routine to reallocate memory for a given handle. The chunk can be extended or shrinked in both + * directions - top and bottom, depending on the offset and size arguments. + * + * \retval t_memory_handle handle on the reallocated piece of memory + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC t_memory_handle cm_MM_Realloc( + t_cm_allocator_desc* alloc, + const t_cm_size size, + const t_uint32 offset, + const t_cm_memory_alignment memAlignment, + const t_memory_handle handle); +/*! + * \brief Frees the allocated chunk + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC void cm_MM_Free( + t_cm_allocator_desc* alloc, //!< [in] Identifier of the memory allocator + t_memory_handle memHandle //!< [in] Memory handle to free + ); + + +/*! + * \brief Get the allocator status + * + * \param[in] alloc Identifier of the memory allocator + * \param[out] pStatus Status of the allocator + * + * \retval t_cm_error + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC t_cm_error cm_MM_GetAllocatorStatus(t_cm_allocator_desc* alloc, t_uint32 offset, t_uint32 size, t_cm_allocator_status *pStatus); + +/*! + * \brief Returns the offset into a given memory allocator of an allocated piece of memory + * + * \param[in] memHandle handle on the given memory + * + * \retval t_uint32 offset into the given memory allocator + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC t_uint32 cm_MM_GetOffset(t_memory_handle memHandle); + + +/*! + * \brief Returns the size in word size for a given memory allocator of an allocated piece of memory + * + * \param[in] memHandle handle on the given memory + * + * \retval t_uint32 size in wordsize for the given memory allocator + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC t_uint32 cm_MM_GetSize(t_memory_handle memHandle); + +/*! + * \brief Returns the size in bytes for a given memory allocator + * + * \param[in] allocDesc Identifier of the memory allocator + * \retval size + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC t_uint32 cm_MM_GetAllocatorSize(t_cm_allocator_desc* allocDesc); + + +/*! + * \brief Set the user data of an allocated piece of memory + * + * \param[in] memHandle handle on the given memory + * \param[in] userData UsedData of the given memory piece + * + * \retval t_cm_error + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC void cm_MM_SetMemoryHandleUserData (t_memory_handle memHandle, t_uint16 userData); + + +/*! + * \brief Return the user data of an allocated piece of memory + * + * \param[in] memHandle handle on the given memory + * \param[out] pUserData returned UsedData of the given memory piece + * + * \retval t_cm_error + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC void cm_MM_GetMemoryHandleUserData(t_memory_handle memHandle, t_uint16 *pUserData, t_cm_allocator_desc **alloc); + +/*! + * \brief Dump chunkd in the range of [start:end] + * + * \param[in] alloc Allocator descriptor + * \param[in] start Range start + * \param[in] end Range end + * + * \retval void + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC void cm_MM_DumpMemory(t_cm_allocator_desc* alloc, t_uint32 start, t_uint32 end); + +#endif /* _REMOTE_ALLOCATOR_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator_utils.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator_utils.h new file mode 100644 index 00000000000..ce99e4d7a94 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator_utils.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef REMOTE_ALLOCATOR_UTILS_H_ +#define REMOTE_ALLOCATOR_UTILS_H_ + +#include +#include + +typedef enum { + FREE_CHUNK_BEFORE, + FREE_CHUNK_AFTER, +} t_mem_split_position; + + +PUBLIC void updateFreeList(t_cm_allocator_desc* alloc, t_cm_chunk* chunk); + +PUBLIC void linkChunk(t_cm_chunk* prev,t_cm_chunk* add); +PUBLIC void unlinkChunk(t_cm_allocator_desc* alloc,t_cm_chunk* current); + +PUBLIC void unlinkFreeMem(t_cm_allocator_desc* alloc,t_cm_chunk* current); +PUBLIC void linkFreeMemBefore(t_cm_chunk* add, t_cm_chunk* next); +PUBLIC void linkFreeMemAfter(t_cm_chunk* prev,t_cm_chunk* add); + +PUBLIC void mergeChunk(t_cm_allocator_desc* alloc,t_cm_chunk *c,t_cm_chunk *destroy); +PUBLIC t_cm_chunk* splitChunk(t_cm_allocator_desc* alloc, t_cm_chunk *chunk, t_uint32 offset, t_mem_split_position position); + +#endif /*REMOTE_ALLOCATOR_UTILS_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/chunk_mgr.c b/drivers/staging/nmf-cm/cm/engine/memory/src/chunk_mgr.c new file mode 100644 index 00000000000..26c00cdeb77 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/chunk_mgr.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * Include + */ +#include +#include "../inc/chunk_mgr.h" +#include + +#define CHUNKS_PER_PAGE 500 +#define CHUNK_THRESOLD 5 + +struct t_page_chuncks { + struct t_page_chuncks *nextPage; + // unsigned int freeChunkInPage; + t_cm_chunk chunks[CHUNKS_PER_PAGE]; +}; + +static struct t_page_chuncks *firstPage; + +static unsigned int freeChunks; +static t_cm_chunk *firstFreeChunk; + +t_cm_chunk* allocChunk() +{ + t_cm_chunk* chunk = firstFreeChunk; + + firstFreeChunk = chunk->next; + + chunk->next_free_mem = 0; + chunk->prev_free_mem = 0; + chunk->prev = 0; + chunk->next = 0; + chunk->status = MEM_FREE; + // chunk->offset = 0; + // chunk->size = 0; + // chunk->alloc = 0; + // chunk->userData = 0; + + freeChunks--; + + return chunk; +} + +void freeChunk(t_cm_chunk* chunk) +{ + // Link chunk in free list + chunk->next = firstFreeChunk; + firstFreeChunk = chunk; + + // Increase counter + freeChunks++; +} + +t_cm_error allocChunkPool(void) +{ + struct t_page_chuncks* newPage; + int i; + + newPage = (struct t_page_chuncks*)OSAL_Alloc(sizeof(struct t_page_chuncks)); + if(newPage == NULL) + return CM_NO_MORE_MEMORY; + + // Link page + newPage->nextPage = firstPage; + firstPage = newPage; + + // Put chunk in free list + for(i = 0; i < CHUNKS_PER_PAGE; i++) + freeChunk(&newPage->chunks[i]); + + return CM_OK; +} + +t_cm_error fillChunkPool(void) +{ + if(freeChunks < CHUNK_THRESOLD) + return allocChunkPool(); + + return CM_OK; +} + +void freeChunkPool(void) +{ + while(firstPage != NULL) + { + struct t_page_chuncks* tofree = firstPage; + firstPage = firstPage->nextPage; + OSAL_Free(tofree); + } +} diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/domain.c b/drivers/staging/nmf-cm/cm/engine/memory/src/domain.c new file mode 100644 index 00000000000..61cb25b39ec --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/domain.c @@ -0,0 +1,590 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * domain_memory structure is all we need + */ +#define MAX_USER_DOMAIN_NB 64 +#define MAX_SCRATCH_DOMAIN_NB 16 + +t_cm_domain_desc domainDesc[MAX_USER_DOMAIN_NB]; +t_cm_domain_scratch_desc domainScratchDesc[MAX_SCRATCH_DOMAIN_NB]; + +static t_cm_allocator_desc *cm_DM_getAllocator(t_cm_domain_id domainId, t_dsp_memory_type_id memType); +static void cm_DM_DomainError(const t_cm_domain_id parentId, const t_nmf_client_id client); + +#define INIT_DOMAIN_STRUCT(domainDesc) do { \ + domainDesc.client = 0; \ + domainDesc.type = DOMAIN_NORMAL; \ + domainDesc.refcount = 0; \ + domainDesc.domain.coreId = MASK_ALL8; \ + domainDesc.domain.esramCode.offset = 0; \ + domainDesc.domain.esramCode.size = 0; \ + domainDesc.domain.esramData.offset = 0; \ + domainDesc.domain.esramData.size = 0; \ + domainDesc.domain.sdramCode.offset = 0; \ + domainDesc.domain.sdramCode.size = 0; \ + domainDesc.domain.sdramData.offset = 0; \ + domainDesc.domain.sdramData.size = 0; \ + domainDesc.scratch.parent.handle = 0; \ + domainDesc.scratch.child.alloc = 0; \ + domainDesc.scratch.child.parent_ref = 0; \ + } while (0) + +#define FIND_DOMAIN_ID(domainId) \ + { \ + domainId = 0; \ + while (domainDesc[domainId].client != 0 && domainId < MAX_USER_DOMAIN_NB) { \ + domainId++; \ + } \ + if (domainId >= MAX_USER_DOMAIN_NB) { \ + return CM_INTERNAL_DOMAIN_OVERFLOW; \ + } \ + } + +#define FIND_SCRATCH_DOMAIN_ID(domainId) \ + { \ + domainId = 0; \ + while (domainScratchDesc[domainId].allocDesc != 0 && domainId < MAX_SCRATCH_DOMAIN_NB) { \ + domainId++; \ + } \ + if (domainId >= MAX_SCRATCH_DOMAIN_NB) { \ + return CM_INTERNAL_DOMAIN_OVERFLOW; \ + } \ + } + +PUBLIC t_cm_error cm_DM_CheckDomain(t_cm_domain_id handle, t_cm_domain_type type) +{ + if ((handle <= 3) + || (handle >= MAX_USER_DOMAIN_NB)) { //remember, domain[0-3] are reserved + return CM_INVALID_DOMAIN_HANDLE; + } + + if (domainDesc[handle].client == 0) { + return CM_INVALID_DOMAIN_HANDLE; + } + + if (type != DOMAIN_ANY) { + if (domainDesc[handle].type != type) { + return CM_INVALID_DOMAIN_HANDLE; + } + } + + return CM_OK; +} + +PUBLIC t_cm_error cm_DM_CheckDomainWithClient(t_cm_domain_id handle, t_cm_domain_type type, t_nmf_client_id client) +{ + t_cm_error error; + + if((error = cm_DM_CheckDomain(handle, type)) != CM_OK) + return error; + +#ifdef CHECK_TO_BE_REACTIVATED_IN_2_11 + if(domainDesc[handle].client != client) + { + ERROR("CM_DOMAIN_VIOLATION: domain %d created by client %d not usable by client %d.", handle, domainDesc[handle].client, client, 0, 0, 0); + return CM_DOMAIN_VIOLATION; + } +#endif + + return CM_OK; +} + +PUBLIC t_cm_error cm_DM_Init(void) +{ + t_cm_error error; + + int i = 0; + for(i = 0; i < MAX_USER_DOMAIN_NB; i++) { + INIT_DOMAIN_STRUCT(domainDesc[i]); + } + + //domains[0-3] are reserved - allows to catch some cases of incorrect usage, + //especially when user uses coreId instead of domainId, ie id = 1, 2, 3 + domainDesc[0].client = NMF_CORE_CLIENT; + domainDesc[1].client = NMF_CORE_CLIENT; + domainDesc[2].client = NMF_CORE_CLIENT; + domainDesc[3].client = NMF_CORE_CLIENT; + + for(i = 0; i < MAX_SCRATCH_DOMAIN_NB; i++) { + domainScratchDesc[i].domainId = 0; + domainScratchDesc[i].parentId = 0; + domainScratchDesc[i].allocDesc = 0; + } + + // Alloc twice for having comfortable chunk + if((error = allocChunkPool()) != CM_OK) + return error; + if((error = allocChunkPool()) != CM_OK) + { + freeChunkPool(); + return error; + } + + return CM_OK; +} + +PUBLIC void cm_DM_Destroy(void) +{ + //cm_DM_Init(); + freeChunkPool(); +} + +PUBLIC t_nmf_core_id cm_DM_GetDomainCoreId(const t_cm_domain_id domainId) +{ + + return domainDesc[domainId].domain.coreId; +} + +#if 0 +static t_uint32 cm_DM_isSegmentOverlaping(const t_cm_domain_segment *d0, const t_cm_domain_segment *d1) +{ + t_uint32 min0 = d0->offset; + t_uint32 max0 = d0->offset + d0->size; + t_uint32 min1 = d1->offset; + t_uint32 max1 = d1->offset + d1->size; + + if ( (min0 < min1) && (min1 < max0) ){ /* min0 < min1 < max0 OR min1 in [min0:max0] */ + return 1; + } + if ( (min1 < min0) && (min0 <= max1) ){ /* min1 < min0 < max0 OR min0 in [min1:max1] */ + return 1; + } + + return 0; +} +{ + ... + + t_uint32 i; + //check non-overlapp with other domains + for (i = 0; i < MAX_USER_DOMAIN_NB; i++) { + if (domainDesc[i].client != 0) { + if (cm_DM_isSegmentOverlaping(&domainDesc[i].domain.esramData, &domain->esramData)) { + return CM_DOMAIN_OVERLAP; + } + /* + if (cm_DM_isSegmentOverlaping(&domainDesc[i].domain.esramData, &domain->esramData)) { + return CM_DOMAIN_OVERLAP; + } + */ + } + } + + ... +} +#endif + +PUBLIC t_cm_error cm_DM_CreateDomain(const t_nmf_client_id client, const t_cm_domain_memory *domain, t_cm_domain_id *handle) +{ + t_cm_domain_id domainId; + FIND_DOMAIN_ID(domainId); + + if (client == 0) + return CM_INVALID_PARAMETER; + + if (domain->coreId > LAST_CORE_ID) + return CM_INVALID_DOMAIN_DEFINITION; + + //FIXME, juraj, check invalid domain definition + domainDesc[domainId].client = client; + domainDesc[domainId].domain = *domain; + + *handle = domainId; + + return CM_OK; +} + +//TODO, juraj, add assert to cm_MM_GetOffset(), if domain is scratch parent +PUBLIC t_cm_error cm_DM_CreateDomainScratch(const t_nmf_client_id client, const t_cm_domain_id parentId, const t_cm_domain_memory *domain, t_cm_domain_id *handle) +{ + t_cm_error error; + t_memory_handle memhandle; + t_cm_allocator_desc *alloc; + t_uint32 parentMin, parentMax; + t_uint32 scratchMin, scratchMax; + + /* check if the parent domain exists */ + /* parent could be DOMAIN_NORMAL (1st call) or DOMAIN_SCRATCH_PARENT (other calls) */ + if ((error = cm_DM_CheckDomain(parentId, DOMAIN_ANY)) != CM_OK) { + return error; + } + + parentMin = domainDesc[parentId].domain.esramData.offset; + parentMax = domainDesc[parentId].domain.esramData.offset + domainDesc[parentId].domain.esramData.size; + scratchMin = domain->esramData.offset; + scratchMax = domain->esramData.offset + domain->esramData.size; + /* check if the scratch domain respects the parent domain (esram data only )*/ + if ( (parentMin > scratchMin) || (parentMax < scratchMax) ) { + return CM_INVALID_DOMAIN_DEFINITION; + } + + /* create the scratch domain */ + if ((error = cm_DM_CreateDomain(client, domain, handle)) != CM_OK) { + return error; + } + + /* check if this is the first scratch domain */ + if (domainDesc[parentId].scratch.parent.handle == 0) { + /* 1st scratch domain */ + t_cm_domain_segment tmp; + + /* reserve the zone for the scratch domain */ + tmp = domainDesc[parentId].domain.esramData; + domainDesc[parentId].domain.esramData = domain->esramData; + memhandle = cm_DM_Alloc(parentId, ESRAM_EXT16, domain->esramData.size / 2, CM_MM_ALIGN_NONE, FALSE); //note byte to 16bit-word conversion + domainDesc[parentId].domain.esramData = tmp; + if (memhandle == 0) { + cm_DM_DestroyDomain(*handle); + cm_DM_DomainError(parentId, client); + return CM_NO_MORE_MEMORY; + } + + domainDesc[parentId].type = DOMAIN_SCRATCH_PARENT; + domainDesc[parentId].refcount = 0; //reinit the refcount + domainDesc[parentId].scratch.parent.handle = memhandle; + + } else { + /* nth scratch domain */ + t_uint32 i; + t_uint32 oldMin = domainDesc[parentId].domain.esramData.offset + domainDesc[parentId].domain.esramData.offset; + t_uint32 oldMax = 0; + + /* compute the new scratch zone size */ + for(i = 0; i < MAX_USER_DOMAIN_NB; i++) { + if ((domainDesc[i].type == DOMAIN_SCRATCH_CHILD) && (domainDesc[i].scratch.child.parent_ref == parentId)) { + /* ok, here we have a scratch domain created from the same child domain */ + t_uint32 min = domainDesc[i].domain.esramData.offset; + t_uint32 max = domainDesc[i].domain.esramData.offset + domainDesc[i].domain.esramData.size; + + oldMin = (min < oldMin)?min:oldMin; + oldMax = (max > oldMax)?max:oldMax; + } + } + + /* resize the scratch zone */ + if ((oldMin > scratchMin) || (oldMax < scratchMax)) { + t_uint32 newMin = (oldMin > scratchMin)?scratchMin:oldMin; + t_uint32 newMax = (oldMax < scratchMax)?scratchMax:oldMax; + t_uint16 userData; + + /* save user data lost during realloc, user data do not change */ + cm_MM_GetMemoryHandleUserData(domainDesc[parentId].scratch.parent.handle, &userData, 0); + memhandle = cm_MM_Realloc(cm_DM_getAllocator(parentId, ESRAM_EXT16), newMax - newMin, newMin, + CM_MM_MPC_ALIGN_NONE, domainDesc[parentId].scratch.parent.handle); + if (memhandle == 0) { + /* failed to extend the zone */ + cm_DM_DestroyDomain(*handle); + cm_DM_DomainError(parentId, client); + return CM_NO_MORE_MEMORY; + } + + cm_MM_SetMemoryHandleUserData(memhandle, userData); + domainDesc[parentId].scratch.parent.handle = memhandle; + } + } + + /* create esram-data allocator in the scratch domain */ + alloc = cm_MM_CreateAllocator(domainDesc[*handle].domain.esramData.size, + domainDesc[*handle].domain.esramData.offset, + "scratch"); + + domainDesc[*handle].type = DOMAIN_SCRATCH_CHILD; + domainDesc[*handle].scratch.child.parent_ref = parentId; + domainDesc[*handle].scratch.child.alloc = alloc; + domainDesc[parentId].refcount++; + + return error; +} + +PUBLIC t_cm_error cm_DM_DestroyDomains(const t_nmf_client_id client) +{ + t_cm_domain_id handle; + t_cm_error error, status=CM_OK; + + for (handle=0; handledomainEE) + // return CM_INVALID_DOMAIN_HANDLE; + + /* loop all components and check if there are still components instantiated with this handle */ + //actually this check is redundant with the usage counters as component instantiations allocate memory + for (i=0; idomainId == handle) { + return CM_ILLEGAL_DOMAIN_OPERATION; + } + } + + //perform check based on usage counters + if (domainDesc[handle].refcount != 0) { + return CM_ILLEGAL_DOMAIN_OPERATION; + } + + if (domainDesc[handle].type == DOMAIN_SCRATCH_PARENT) { + return CM_ILLEGAL_DOMAIN_OPERATION; //parent destroyed implicitly with the last scratch + } else if (domainDesc[handle].type == DOMAIN_SCRATCH_CHILD) { + t_cm_allocator_status status; + t_cm_domain_id parentId = domainDesc[handle].scratch.child.parent_ref; + + cm_MM_GetAllocatorStatus(domainDesc[handle].scratch.child.alloc, 0, 0xffff, &status); + if (status.global.accumulate_used_memory != 0) { + //something is still allocated + return CM_ILLEGAL_DOMAIN_OPERATION; + } + + domainDesc[parentId].refcount--; + cm_MM_DeleteAllocator(domainDesc[handle].scratch.child.alloc); //returns no error + + if (domainDesc[parentId].refcount == 0) { + /* last scratch domain */ + cm_DM_Free(domainDesc[parentId].scratch.parent.handle, FALSE); + domainDesc[parentId].scratch.parent.handle = 0; + domainDesc[parentId].type = DOMAIN_NORMAL; + } else { + /* other child scratch domains exist, check if the reserved zone needs resize, ie reduce */ + + t_uint32 i; + /* init oldMin and oldMax to values we are sure will get overwritten below */ + t_uint32 oldMin = 0xffffffff; + t_uint32 oldMax = 0x0; + t_uint32 scratchMin = domainDesc[handle].domain.esramData.offset; + t_uint32 scratchMax = domainDesc[handle].domain.esramData.offset + domainDesc[handle].domain.esramData.size; + t_memory_handle memhandle; + + /* compute the remaining reserved zone size */ + for(i = 0; i < MAX_USER_DOMAIN_NB; i++) { + if (i == handle) + continue; //do not consider the current domain to be destroyed later in this function + if ((domainDesc[i].type == DOMAIN_SCRATCH_CHILD) && (domainDesc[i].scratch.child.parent_ref == parentId)) { + /* ok, here we have a scratch domain created from the same child domain */ + t_uint32 min = domainDesc[i].domain.esramData.offset; + t_uint32 max = domainDesc[i].domain.esramData.offset + domainDesc[i].domain.esramData.size; + + oldMin = (min < oldMin)?min:oldMin; + oldMax = (max > oldMax)?max:oldMax; + } + } + + /* resize the scratch zone */ + if ((oldMin > scratchMin) || (oldMax < scratchMax)) { + t_uint16 userData; + + /* save user data lost during realloc, user data do not change */ + cm_MM_GetMemoryHandleUserData(domainDesc[parentId].scratch.parent.handle, &userData, 0); + memhandle = cm_MM_Realloc(cm_DM_getAllocator(parentId, ESRAM_EXT16), oldMax - oldMin, oldMin, + CM_MM_MPC_ALIGN_NONE, domainDesc[parentId].scratch.parent.handle); + CM_ASSERT(memhandle); //the realloc shouldn't fail.. + + cm_MM_SetMemoryHandleUserData(memhandle, userData); + domainDesc[parentId].scratch.parent.handle = memhandle; + } + } + } + + //reset the domain desc + INIT_DOMAIN_STRUCT(domainDesc[handle]); + + return CM_OK; +} + +/* + * - if the domainId is scratch parent, all allocations are done as in normal domains + * - if the domainId is scratch child + * if allocation type is esram, retrieve the allocator from the domainDesc + * else allocation is done as for normal domain + * - if the domainId is normal, allocator is retrieved from mpcDesc via cm_DSP_GetAllocator() + */ +static t_cm_allocator_desc *cm_DM_getAllocator(t_cm_domain_id domainId, t_dsp_memory_type_id memType) +{ + t_cm_allocator_desc *alloc = 0; + + if ((domainDesc[domainId].type == DOMAIN_SCRATCH_CHILD) + && ((memType == ESRAM_EXT16) || (memType == ESRAM_EXT24))) { + alloc = domainDesc[domainId].scratch.child.alloc; + } else { + alloc = cm_DSP_GetAllocator(domainDesc[domainId].domain.coreId, memType); + } + + return alloc; +} + +void START(void); +void END(const char*); + +//TODO, juraj, alloc would need to return finer errors then 0 +PUBLIC t_memory_handle cm_DM_Alloc(t_cm_domain_id domainId, t_dsp_memory_type_id memType, t_uint32 wordSize, t_cm_mpc_memory_alignment memAlignment, t_bool powerOn) +{ + t_nmf_core_id coreId = domainDesc[domainId].domain.coreId; + t_memory_handle handle; + t_cm_allocator_desc *alloc; + t_uint32 offset; + t_uint32 size; + + cm_DSP_GetInternalMemoriesInfo(domainId, memType, &offset, &size); + + if ((alloc = cm_DM_getAllocator(domainId, memType)) == 0) { + return 0; + } + + handle = cm_MM_Alloc(alloc, + cm_DSP_ConvertSize(memType, wordSize), + (t_cm_memory_alignment) memAlignment, + offset, size, domainId); + + if(handle != INVALID_MEMORY_HANDLE) + { + cm_MM_SetMemoryHandleUserData(handle, (coreId << SHIFT_BYTE1) | (memType << SHIFT_BYTE0)); + + if (powerOn) { + // [Pwr] The associated power domain can be enabled only after the Alloc request. + // Associated MPC memory chunk is not accessed (Remote allocator feature) + cm_PWR_EnableMemory( + coreId, + memType, + /* + * Compute physical address based on cm_DSP_GetHostSystemAddress but in optimized way + * -> See it for information + * -> Note TCM memory is not correctly compute, but it's not used + */ + cm_DSP_GetState(coreId)->allocator[memType]->baseAddress.physical + cm_MM_GetOffset(handle), + cm_MM_GetSize(handle)); + } + } + + return handle; +} + +PUBLIC void cm_DM_FreeWithInfo(t_memory_handle memHandle, t_nmf_core_id *coreId, t_dsp_memory_type_id *memType, t_bool powerOff) +{ + t_dsp_chunk_info chunk_info; + + cm_DSP_GetDspChunkInfo(memHandle, &chunk_info); + + if (powerOff) { + cm_PWR_DisableMemory( + chunk_info.coreId, + chunk_info.memType, + cm_DSP_GetPhysicalAdress(memHandle), + cm_MM_GetSize(memHandle)); + } + + cm_MM_Free(chunk_info.alloc, memHandle); + + *coreId = chunk_info.coreId; + *memType = chunk_info.memType; +} + +PUBLIC void cm_DM_Free(t_memory_handle memHandle, t_bool powerOff) +{ + t_nmf_core_id coreId; + t_dsp_memory_type_id memType; + + cm_DM_FreeWithInfo(memHandle, &coreId, &memType, powerOff); +} + +PUBLIC t_cm_error cm_DM_GetAllocatorStatus(t_cm_domain_id domainId, t_dsp_memory_type_id memType, t_cm_allocator_status *pStatus) +{ + t_cm_error error; + t_uint32 dOffset; + t_uint32 dSize; + + //TODO, scratch + error = cm_DM_CheckDomain(domainId, DOMAIN_ANY); + if (error != CM_OK) { + return error; + } + + cm_DSP_GetInternalMemoriesInfo(domainId, memType, &dOffset, &dSize); + + return cm_DSP_GetAllocatorStatus(domainDesc[domainId].domain.coreId, memType, + dOffset, dSize, pStatus); +} + +//WARNING: this function is only correct *before* migration! because +//the computation of absolute adresses of a domain is based on the allocator for the given +//segment (this is hidden in cm_DSP_GetDspBaseAddress and this info is not valid +//after migration (non-contiguous address-space from the ARM-side) +PUBLIC t_cm_error cm_DM_GetDomainAbsAdresses(t_cm_domain_id domainId, t_cm_domain_info *info) +{ + t_cm_error error; + t_nmf_core_id coreId = domainDesc[domainId].domain.coreId; + + cm_migration_check_state(coreId, STATE_NORMAL); + + error = cm_DM_CheckDomain(domainId, DOMAIN_NORMAL); + if (error != CM_OK) { + return error; + } + + cm_DSP_GetDspBaseAddress(coreId, SDRAM_CODE, &info->sdramCode); + cm_DSP_GetDspBaseAddress(coreId, ESRAM_CODE, &info->esramCode); + cm_DSP_GetDspBaseAddress(coreId, SDRAM_EXT24, &info->sdramData); + cm_DSP_GetDspBaseAddress(coreId, ESRAM_EXT24, &info->esramData); + + info->sdramCode.physical += domainDesc[domainId].domain.sdramCode.offset; + info->sdramCode.logical += domainDesc[domainId].domain.sdramCode.offset; + info->esramCode.physical += domainDesc[domainId].domain.esramCode.offset; + info->esramCode.logical += domainDesc[domainId].domain.esramCode.offset; + info->sdramData.physical += domainDesc[domainId].domain.sdramData.offset; + info->sdramData.logical += domainDesc[domainId].domain.sdramData.offset; + info->esramData.physical += domainDesc[domainId].domain.esramData.offset; + info->esramData.logical += domainDesc[domainId].domain.esramData.offset; + + return CM_OK; +} + +static void cm_DM_DomainError(const t_cm_domain_id parentId, const t_nmf_client_id client) +{ + int i; + LOG_INTERNAL(0, "NMF_DEBUG_SCRATCH failed to allocate domain (client %u): 0x%08x -> 0x%08x\n", + client, + domainDesc[parentId].domain.esramData.offset, + domainDesc[parentId].domain.esramData.offset + domainDesc[parentId].domain.esramData.size, + 0, 0, 0); + for(i = 0; i < MAX_USER_DOMAIN_NB; i++) { + if (domainDesc[i].type == DOMAIN_SCRATCH_CHILD) { + LOG_INTERNAL(0, "NMF_DEBUG_SCRATCH scratch domain %d allocated (client %u): 0x%08x -> 0x%08x\n", + i, domainDesc[i].client, + domainDesc[i].domain.esramData.offset, + domainDesc[i].domain.esramData.offset + domainDesc[i].domain.esramData.size, + 0, 0); + } + } + cm_MM_DumpMemory(cm_DM_getAllocator(parentId, ESRAM_EXT16), + domainDesc[parentId].domain.esramData.offset, + domainDesc[parentId].domain.esramData.offset + domainDesc[parentId].domain.esramData.size); +} + diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/domain_wrapper.c b/drivers/staging/nmf-cm/cm/engine/memory/src/domain_wrapper.c new file mode 100644 index 00000000000..ec305812f15 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/domain_wrapper.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include +#include +#include + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_CreateMemoryDomain( + const t_nmf_client_id client, + const t_cm_domain_memory *domain, + t_cm_domain_id *handle + ) +{ + t_cm_error error; + + OSAL_LOCK_API(); + error = cm_DM_CreateDomain(client, domain, handle); + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_CreateMemoryDomainScratch( + const t_nmf_client_id client, + const t_cm_domain_id parentId, + const t_cm_domain_memory *domain, + t_cm_domain_id *handle + ) +{ + t_cm_error error; + + OSAL_LOCK_API(); + error = cm_DM_CreateDomainScratch(client, parentId, domain, handle); + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_DestroyMemoryDomain( + t_cm_domain_id handle) +{ + t_cm_error error; + + OSAL_LOCK_API(); + error = cm_DM_DestroyDomain(handle); + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_FlushMemoryDomains( + t_nmf_client_id client) +{ + t_cm_error error; + + OSAL_LOCK_API(); + error = cm_DM_DestroyDomains(client); + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetDomainCoreId(const t_cm_domain_id domainId, t_nmf_core_id *coreId) +{ + t_cm_error error; + OSAL_LOCK_API(); + //TODO, scratch + error = cm_DM_CheckDomain(domainId, DOMAIN_NORMAL); + if (error != CM_OK) { + OSAL_UNLOCK_API(); + return error; + } + + *coreId = cm_DM_GetDomainCoreId(domainId); + OSAL_UNLOCK_API(); + return CM_OK; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_Migrate(const t_cm_domain_id srcShared, const t_cm_domain_id src, const t_cm_domain_id dst) +{ + t_cm_error error; + OSAL_LOCK_API(); + error = cm_migrate(srcShared, src, dst); + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_Unmigrate(void) +{ + t_cm_error error; + OSAL_LOCK_API(); + error = cm_unmigrate(); + OSAL_UNLOCK_API(); + return error; +} diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c b/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c new file mode 100644 index 00000000000..15961aea516 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c @@ -0,0 +1,243 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include +#include +#include +#include + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_AllocMpcMemory( + t_cm_domain_id domainId, + t_nmf_client_id clientId, + t_cm_mpc_memory_type memType, + t_cm_size size, + t_cm_mpc_memory_alignment memAlignment, + t_cm_memory_handle *pHandle + ) +{ + t_dsp_memory_type_id dspMemType; + + switch(memType) + { + case CM_MM_MPC_TCM16_X: + dspMemType = INTERNAL_XRAM16; + break; + case CM_MM_MPC_TCM24_X: + dspMemType = INTERNAL_XRAM24; + break; + case CM_MM_MPC_TCM16_Y: + dspMemType = INTERNAL_YRAM16; + break; + case CM_MM_MPC_TCM24_Y: + dspMemType = INTERNAL_YRAM24; + break; +#ifndef __STN_8810 + case CM_MM_MPC_ESRAM16: + dspMemType = ESRAM_EXT16; + break; + case CM_MM_MPC_ESRAM24: + dspMemType = ESRAM_EXT24; + break; +#endif /* ndef __STN_8810 */ + case CM_MM_MPC_SDRAM16: + dspMemType = SDRAM_EXT16; + break; + case CM_MM_MPC_SDRAM24: + dspMemType = SDRAM_EXT24; + break; + default: + return CM_INVALID_PARAMETER; + } + + OSAL_LOCK_API(); + { + t_cm_error error; + error = cm_DM_CheckDomainWithClient(domainId, DOMAIN_ANY, clientId); + if (error != CM_OK) { + OSAL_UNLOCK_API(); + return error; + } + } + + switch(memAlignment) { + case CM_MM_MPC_ALIGN_NONE : + case CM_MM_MPC_ALIGN_HALFWORD : + case CM_MM_MPC_ALIGN_WORD : + case CM_MM_MPC_ALIGN_2WORDS : + case CM_MM_MPC_ALIGN_4WORDS : + case CM_MM_MPC_ALIGN_8WORDS : + case CM_MM_MPC_ALIGN_16WORDS : + case CM_MM_MPC_ALIGN_32WORDS : + case CM_MM_MPC_ALIGN_64WORDS : + case CM_MM_MPC_ALIGN_128WORDS : + case CM_MM_MPC_ALIGN_256WORDS : + case CM_MM_MPC_ALIGN_512WORDS : + case CM_MM_MPC_ALIGN_1024WORDS : + case CM_MM_MPC_ALIGN_65536BYTES : + //case CM_MM_MPC_ALIGN_16384WORDS : maps to the same value as above + break; + default: + OSAL_UNLOCK_API(); + return CM_INVALID_PARAMETER; + } + + /* in case we allocate in tcm x be sure ee is load before */ + if ( memType == CM_MM_MPC_TCM16_X || memType == CM_MM_MPC_TCM24_X || + memType == CM_MM_MPC_TCM16_Y || memType == CM_MM_MPC_TCM24_Y ) + { + t_cm_error error; + if ((error = cm_CFG_CheckMpcStatus(cm_DM_GetDomainCoreId(domainId))) != CM_OK) + { + OSAL_UNLOCK_API(); + return error; + } + } + + /* alloc memory */ + *pHandle = (t_cm_memory_handle)cm_DM_Alloc(domainId, dspMemType, size, memAlignment, TRUE); + if(*pHandle == (t_cm_memory_handle)INVALID_MEMORY_HANDLE) + { + OSAL_UNLOCK_API(); + return CM_NO_MORE_MEMORY; + } + + OSAL_UNLOCK_API(); + return CM_OK; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_FreeMpcMemory(t_cm_memory_handle handle) +{ + t_cm_error error; + t_memory_handle validHandle; + t_nmf_core_id coreId; + t_dsp_memory_type_id memType; + + OSAL_LOCK_API(); + + if((error = cm_MM_getValidMemoryHandle(handle, &validHandle)) != CM_OK) + { + OSAL_UNLOCK_API(); + return error; + } + + cm_DM_FreeWithInfo(validHandle, &coreId, &memType, TRUE); + + /* in case we allocate in tcm x be sure ee is load before */ + if ( memType == INTERNAL_XRAM16 || memType == INTERNAL_XRAM24 || + memType == INTERNAL_YRAM16 || memType == INTERNAL_YRAM24 ) + { + cm_CFG_ReleaseMpc(coreId); + } + + OSAL_UNLOCK_API(); + return CM_OK; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemorySystemAddress(t_cm_memory_handle handle, t_cm_system_address *pSystemAddress) +{ + t_cm_error error; + t_memory_handle validHandle; + + OSAL_LOCK_API(); + + if((error = cm_MM_getValidMemoryHandle(handle, &validHandle)) != CM_OK) + { + OSAL_UNLOCK_API(); + return error; + } + + cm_DSP_GetHostSystemAddress(validHandle, pSystemAddress); + + OSAL_UNLOCK_API(); + return CM_OK; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryMpcAddress(t_cm_memory_handle handle, t_uint32 *pDspAddress) +{ + t_cm_error error; + t_memory_handle validHandle; + + OSAL_LOCK_API(); + + if((error = cm_MM_getValidMemoryHandle(handle, &validHandle)) != CM_OK) + { + OSAL_UNLOCK_API(); + return error; + } + + cm_DSP_GetDspAddress(validHandle, pDspAddress); + + OSAL_UNLOCK_API(); + return CM_OK; +} + +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemorySize( + t_cm_memory_handle handle, + t_uint32 *pSize) +{ + t_cm_error error; + t_memory_handle validHandle; + + OSAL_LOCK_API(); + + if((error = cm_MM_getValidMemoryHandle(handle, &validHandle)) != CM_OK) + { + OSAL_UNLOCK_API(); + return error; + } + + *pSize = validHandle->size; + + OSAL_UNLOCK_API(); + return CM_OK; +} + + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryStatus(t_nmf_core_id coreId, t_cm_mpc_memory_type memType, t_cm_allocator_status *pStatus) +{ + t_dsp_memory_type_id dspMemType; + t_cm_error error; + + switch(memType) + { + case CM_MM_MPC_TCM16_X: + dspMemType = INTERNAL_XRAM16; + break; + case CM_MM_MPC_TCM24_X: + dspMemType = INTERNAL_XRAM24; + break; + case CM_MM_MPC_TCM16_Y: + dspMemType = INTERNAL_YRAM16; + break; + case CM_MM_MPC_TCM24_Y: + dspMemType = INTERNAL_YRAM24; + break; +#ifndef __STN_8810 + case CM_MM_MPC_ESRAM16: + dspMemType = ESRAM_EXT16; + break; + case CM_MM_MPC_ESRAM24: + dspMemType = ESRAM_EXT24; + break; +#endif /* ndef __STN_8810 */ + case CM_MM_MPC_SDRAM16: + dspMemType = SDRAM_EXT16; + break; + case CM_MM_MPC_SDRAM24: + dspMemType = SDRAM_EXT24; + break; + default: + return CM_INVALID_PARAMETER; + } + + OSAL_LOCK_API(); + error = cm_DSP_GetAllocatorStatus(coreId, dspMemType, 0, 0, pStatus); + OSAL_UNLOCK_API(); + + return error; +} + diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/migration.c b/drivers/staging/nmf-cm/cm/engine/memory/src/migration.c new file mode 100644 index 00000000000..35813a56bf2 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/migration.c @@ -0,0 +1,391 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#if defined(__STN_8500) && (__STN_8500 > 10) + +typedef enum { + CM_MIGRATION_OK = 0, + CM_MIGRATION_INVALID_ARGUMENT = 1, + CM_MIGRATION_ERROR = 2, +} t_cm_migration_error; + +extern t_nmf_fifo_arm_desc* mpc2mpcComsFifoId[NB_CORE_IDS][NB_CORE_IDS]; + +/*! + * \brief Data structure representing a segment to migrate + * + * segment: + * - used to determine which mmdsp-hw base is to be updated, index in mpcDesc->segments[] structure + * * this is hard-coded in cm_migrate(), could be computed (would be nice) LIMITATION + * srcAdr.physical: + * - new base setting + * * computed from the src domain in cm_DM_GetAbsAdresses() which uses the start of the allocator for the memory + * this is a LIMITATION, as this information is valid only before migration + * srcAdr.logical: + * - cm_MemCopy() + * * computed as srcAdr.logical + * dstAdr.physical: see srcAdr.physical + * dstAdr.logical: see srcAdr.logical + * size: + * - cm_MemCopy() + * - setting the top when new base is set + */ +typedef struct { + t_dsp_segment_type segment; //!< the link to the segment type + t_cm_system_address srcAdr; //!< source address + t_cm_system_address dstAdr; //!< destination address + t_uint32 size; //!< size of the segment +} t_cm_migration_segment; + +/*! + * \brief Internal data structure 1/ during migration, and 2/ between migration and unmigration calls + * + * all needed information are computed before calling _cm_migration_move() + */ +typedef struct { + t_cm_migration_state state; //!< migration state + t_nmf_core_id coreId; //!< migration only on one mpc + t_cm_migration_segment segments[NB_MIGRATION_SEGMENT]; //!< segments to migrate (selected on migration_move) + t_memory_handle handles[NB_MIGRATION_SEGMENT]; //!< memory handles for destination chunks allocated prior migration +} t_cm_migration_internal_state; + +static t_cm_migration_internal_state migrationState = {STATE_NORMAL, }; + +static t_cm_error _cm_migration_initSegment( + t_dsp_segment_type dspSegment, + t_cm_system_address *srcAdr, + t_uint32 size, + t_cm_domain_id dst, + t_cm_migration_internal_state *info + ) +{ + t_cm_system_address dstAdr; + t_cm_migration_segment *segment = &info->segments[dspSegment]; + t_memory_handle handle; + + handle = cm_DM_Alloc(dst, ESRAM_EXT16, size >> 1, CM_MM_ALIGN_AHB_BURST, TRUE); //note: byte to half-word conversion + if (handle == 0) { + return CM_NO_MORE_MEMORY; + } + + info->handles[dspSegment] = handle; + + cm_DSP_GetHostSystemAddress(handle, &dstAdr); + + segment->segment = dspSegment; //this is redundant and could be avoided by recoding move(), but nice to have for debug + segment->size = size; + segment->srcAdr = *srcAdr; + segment->dstAdr = dstAdr; + + return CM_OK; +} + +static void _cm_migration_releaseSegment(t_cm_migration_internal_state *info, t_dsp_segment_type segId) +{ + cm_DM_Free(info->handles[segId], TRUE); +} + +static t_cm_migration_error _cm_migration_release(t_cm_migration_internal_state *info) +{ + t_uint32 i = 0; + for (i = 0; i < NB_MIGRATION_SEGMENT; i++) { + cm_DM_Free(info->handles[i], TRUE); + } + + return CM_MIGRATION_OK; +} + +#define SEGMENT_START(seg) \ + seg.offset + +#define SEGMENT_END(seg) \ + seg.offset + seg.size + +static t_cm_error _cm_migration_check( + const t_cm_domain_id srcShared, + const t_cm_domain_id src, + const t_cm_domain_id dst, + t_cm_migration_internal_state *info + ) +{ + t_cm_error error = CM_OK; + t_cm_domain_info domainInfoSrc; + t_cm_domain_info domainInfoShared; + t_cm_domain_desc *domainEE; + t_cm_domain_desc *domainShared; + t_nmf_core_id coreId = cm_DM_GetDomainCoreId(src); + + //coreIds in src, srcShared and dst match + if (!((domainDesc[src].domain.coreId == domainDesc[srcShared].domain.coreId) + && (domainDesc[src].domain.coreId == domainDesc[dst].domain.coreId))) { + return CM_INVALID_PARAMETER; + } + + //check srcShared starts at 0 + //FIXME, juraj, today EE code is in SDRAM, but this is flexible, so must find out where EE is instantiated + if (domainDesc[srcShared].domain.sdramCode.offset != 0x0) { + return CM_INVALID_PARAMETER; + } + + //check srcShared contains EE domain + domainEE = &domainDesc[cm_DSP_GetState(coreId)->domainEE]; + domainShared = &domainDesc[srcShared]; + if ((SEGMENT_START(domainEE->domain.esramCode) < SEGMENT_START(domainShared->domain.esramCode)) + ||(SEGMENT_END(domainEE->domain.esramCode) > SEGMENT_END(domainShared->domain.esramCode)) + ||(SEGMENT_START(domainEE->domain.esramData) < SEGMENT_START(domainShared->domain.esramData)) + ||(SEGMENT_END(domainEE->domain.esramData) > SEGMENT_END(domainShared->domain.esramData)) + ||(SEGMENT_START(domainEE->domain.sdramCode) < SEGMENT_START(domainShared->domain.sdramCode)) + ||(SEGMENT_END(domainEE->domain.sdramCode) > SEGMENT_END(domainShared->domain.sdramCode)) + ||(SEGMENT_START(domainEE->domain.sdramData) < SEGMENT_START(domainShared->domain.sdramData)) + ||(SEGMENT_END(domainEE->domain.sdramData) > SEGMENT_END(domainShared->domain.sdramData)) + ) { + return CM_INVALID_PARAMETER; + } + + info->coreId = coreId; + cm_DM_GetDomainAbsAdresses(srcShared, &domainInfoShared); + cm_DM_GetDomainAbsAdresses(src, &domainInfoSrc); + + if ((error = _cm_migration_initSegment(SDRAM_CODE_EE, &domainInfoShared.sdramCode, + domainDesc[srcShared].domain.sdramCode.size, dst, info)) != CM_OK) + goto _migration_error1; + if ((error = _cm_migration_initSegment(SDRAM_CODE_USER, &domainInfoSrc.sdramCode, + domainDesc[src].domain.sdramCode.size, dst, info)) != CM_OK) + goto _migration_error2; + if ((error = _cm_migration_initSegment(SDRAM_DATA_EE, &domainInfoShared.sdramData, + domainDesc[srcShared].domain.sdramData.size, dst, info)) != CM_OK) + goto _migration_error3; + if ((error = _cm_migration_initSegment(SDRAM_DATA_USER, &domainInfoSrc.sdramData, + domainDesc[src].domain.sdramData.size, dst, info)) != CM_OK) + goto _migration_error4; + return error; + +_migration_error4: _cm_migration_releaseSegment(info, SDRAM_DATA_EE); +_migration_error3: _cm_migration_releaseSegment(info, SDRAM_CODE_USER); +_migration_error2: _cm_migration_releaseSegment(info, SDRAM_CODE_EE); +_migration_error1: + OSAL_Log("Couldn't allocate memory for migration\n", 0, 0, 0, 0, 0, 0); + return CM_NO_MORE_MEMORY; +} + +typedef t_cm_error (*updateBase_t)(t_nmf_core_id, t_dsp_segment_type, t_cm_system_address, t_cm_system_address); + +static t_cm_migration_error _cm_migration_move( + t_nmf_core_id coreId, + t_cm_migration_segment *seg, + updateBase_t updateBase, + char* name + ) +{ + LOG_INTERNAL(1, "##### Migration %s: 0x%x -> 0x%x\n", name, seg->srcAdr.logical, seg->dstAdr.logical, 0, 0, 0); + cm_MemCopy((void*)seg->dstAdr.logical, (void*)seg->srcAdr.logical, seg->size); + updateBase(coreId, seg->segment, seg->srcAdr, seg->dstAdr); + cm_MemSet((void*)seg->srcAdr.logical, 0xdead, seg->size); //for debug, to be sure that we have actually moved the code and bases + + return CM_MIGRATION_OK; +} + +static t_cm_migration_error _cm_migration_update_internal( + t_cm_migration_internal_state *info, + t_cm_migration_state state + ) +{ + t_nmf_fifo_arm_desc *pArmFifo; + + migrationState.state = state; + + switch(state) { + case STATE_MIGRATED: + //move fifos + pArmFifo = mpc2mpcComsFifoId[ARM_CORE_ID][info->coreId]; + pArmFifo->fifoDesc = (t_nmf_fifo_desc*)cm_migration_translate(pArmFifo->dspAddressInfo.segmentType, (t_shared_addr)pArmFifo->fifoDescShadow); + pArmFifo = mpc2mpcComsFifoId[info->coreId][ARM_CORE_ID]; + pArmFifo->fifoDesc = (t_nmf_fifo_desc*)cm_migration_translate(pArmFifo->dspAddressInfo.segmentType, (t_shared_addr)pArmFifo->fifoDescShadow); + break; + + case STATE_NORMAL: + //move fifos + pArmFifo = mpc2mpcComsFifoId[ARM_CORE_ID][info->coreId]; + pArmFifo->fifoDesc = pArmFifo->fifoDescShadow; + pArmFifo = mpc2mpcComsFifoId[info->coreId][ARM_CORE_ID]; + pArmFifo->fifoDesc = pArmFifo->fifoDescShadow; + break; + + default: + OSAL_Log("unknown state", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + + return CM_MIGRATION_OK; +} + +PUBLIC t_cm_error cm_migrate(const t_cm_domain_id srcShared, const t_cm_domain_id src, const t_cm_domain_id dst) +{ + t_cm_migration_error mError; + t_cm_error error; + + if ((error = _cm_migration_check(srcShared, src, dst, &migrationState)) != CM_OK) { + return error; + } + + /* stop DSP execution */ + cm_DSP_Stop(migrationState.coreId); + + /* migrate EE and FX */ + mError = _cm_migration_move(migrationState.coreId, &migrationState.segments[SDRAM_CODE_EE], cm_DSP_updateCodeBase, "code"); + if (mError) { + OSAL_Log("EE code migration failed", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + mError = _cm_migration_move(migrationState.coreId, &migrationState.segments[SDRAM_DATA_EE], cm_DSP_updateDataBase, "data"); + if (mError) { + OSAL_Log("EE data migration failed", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + /* migrate user domain */ + mError = _cm_migration_move(migrationState.coreId, &migrationState.segments[SDRAM_CODE_USER], cm_DSP_updateCodeBase, "code"); + if (mError) { + OSAL_Log("User code migration failed", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + mError = _cm_migration_move(migrationState.coreId, &migrationState.segments[SDRAM_DATA_USER], cm_DSP_updateDataBase, "data"); + if (mError) { + OSAL_Log("User data migration failed", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + /* update CM internal structures */ + mError = _cm_migration_update_internal(&migrationState, STATE_MIGRATED); + if (mError) { + OSAL_Log("Update internal data failed", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + + /* Be sure everything has been write before restarting mmdsp */ + OSAL_mb(); + + /* resume DSP execution */ + cm_DSP_Start(migrationState.coreId); + + return CM_OK; +} + +static void _cm_migration_swapSegments( + t_cm_migration_segment *segment + ) +{ + t_cm_system_address tmp; + tmp = segment->dstAdr; + segment->dstAdr = segment->srcAdr; + segment->srcAdr = tmp; +} + +PUBLIC t_cm_error cm_unmigrate(void) +{ + t_cm_migration_error merror; + + if (migrationState.state != STATE_MIGRATED) + return CM_INVALID_PARAMETER; //TODO, juraj, define a proper error for this migration case + + cm_DSP_Stop(migrationState.coreId); + + _cm_migration_swapSegments(&migrationState.segments[SDRAM_CODE_EE]); + _cm_migration_swapSegments(&migrationState.segments[SDRAM_DATA_EE]); + _cm_migration_swapSegments(&migrationState.segments[SDRAM_CODE_USER]); + _cm_migration_swapSegments(&migrationState.segments[SDRAM_DATA_USER]); + + merror = _cm_migration_move(migrationState.coreId, &migrationState.segments[SDRAM_CODE_EE], cm_DSP_updateCodeBase, "code"); + if (merror) { + OSAL_Log("EE code unmigration failed", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + merror = _cm_migration_move(migrationState.coreId, &migrationState.segments[SDRAM_DATA_EE], cm_DSP_updateDataBase, "data"); + if (merror) { + OSAL_Log("EE data unmigration failed", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + merror = _cm_migration_move(migrationState.coreId, &migrationState.segments[SDRAM_CODE_USER], cm_DSP_updateCodeBase, "code"); + if (merror) { + OSAL_Log("User code unmigration failed", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + merror = _cm_migration_move(migrationState.coreId, &migrationState.segments[SDRAM_DATA_USER], cm_DSP_updateDataBase, "data"); + if (merror) { + OSAL_Log("User data unmigration failed", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + + /* update CM internal structures */ + merror = _cm_migration_update_internal(&migrationState, STATE_NORMAL); + if (merror) { + OSAL_Log("Update internal data failed", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + + /* Be sure everything has been write before restarting mmdsp */ + OSAL_mb(); + + cm_DSP_Start(migrationState.coreId); + + /* update CM internal structures */ + merror = _cm_migration_release(&migrationState); + if (merror) { + OSAL_Log("Update internal data failed", 0, 0, 0, 0, 0, 0); + CM_ASSERT(0); + } + + return CM_OK; +} + +// here we make the assumption that the offset doesn't depend from the dsp!! +PUBLIC t_uint32 cm_migration_translate(t_dsp_segment_type segmentType, t_uint32 addr) +{ + //TODO, juraj, save delta instead of recalculating it + t_sint32 offset; + if (migrationState.state == STATE_MIGRATED) { + offset = migrationState.segments[segmentType].dstAdr.logical - migrationState.segments[segmentType].srcAdr.logical; + } else { + offset = 0; + } + return addr + offset; +} + +PUBLIC void cm_migration_check_state(t_nmf_core_id coreId, t_cm_migration_state expected) +{ + CM_ASSERT(migrationState.state == expected); +} + +#else +PUBLIC t_cm_error cm_migrate(const t_cm_domain_id srcShared, const t_cm_domain_id src, const t_cm_domain_id dst) +{ + return CM_OK; +} + +PUBLIC t_cm_error cm_unmigrate(void) +{ + return CM_OK; +} + +PUBLIC t_uint32 cm_migration_translate(t_dsp_segment_type segmentType, t_uint32 addr) +{ + return addr; +} + +PUBLIC void cm_migration_check_state(t_nmf_core_id coreId, t_cm_migration_state expected) +{ + return; +} +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c b/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c new file mode 100644 index 00000000000..3df552aca4d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c @@ -0,0 +1,680 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO  for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * Include + */ +#include "../inc/remote_allocator.h" +#include "../inc/remote_allocator_utils.h" +#include "../inc/chunk_mgr.h" + +#include +#include + +static t_cm_chunk* cm_MM_RA_getLastChunk(t_cm_allocator_desc* alloc); +static void cm_MM_RA_checkAllocator(t_cm_allocator_desc* alloc); +//static void cm_MM_RA_checkAlloc(t_cm_allocator_desc* alloc, t_uint32 size, t_uint32 align, t_uint32 min, t_uint32 max); + +int bin_index(unsigned int sz) { + /* + * 32 bins of size 2 + * 16 bins of size 16 + * 8 bins of size 128 + * 4 bins of size 1024 + * 2 bins of size 8192 + * 1 bin of size what's left + * + */ + return (((sz >> 6) == 0) ? (sz >> 1): // 0 -> 0 .. 31 + ((sz >> 6) <= 4) ? 28 + (sz >> 4): // 64 -> 32 .. 47 + ((sz >> 6) <= 20) ? 46 + (sz >> 7): // 320 -> 48 .. 55 + ((sz >> 6) <= 84) ? 55 + (sz >> 10): // 1344 -> 56 .. 59 + ((sz >> 6) <= 340) ? 59 + (sz >> 13): // 5440 -> 60 .. 61 + 62); // 21824.. +} + +static t_cm_allocator_desc* ListOfAllocators = NULL; + +PUBLIC t_cm_allocator_desc* cm_MM_CreateAllocator(t_cm_size size, t_uint32 offset, const char* name) +{ + t_cm_allocator_desc *alloc; + + CM_ASSERT(fillChunkPool() == CM_OK); + + /* Alloc structure */ + alloc = (t_cm_allocator_desc*)OSAL_Alloc_Zero(sizeof(t_cm_allocator_desc)); + CM_ASSERT(alloc != NULL); + + // Add allocator in list + alloc->next = ListOfAllocators; + ListOfAllocators = alloc; + + /* Create first chunk */ + alloc->chunks = allocChunk(); + + /* assign name */ + alloc->pAllocName = name; + + alloc->chunks->size = size; + alloc->chunks->offset = offset; + alloc->chunks->alloc = alloc; + alloc->free_mem_chunks[bin_index(alloc->chunks->size)] = alloc->chunks; + + alloc->size = size; + + //TODO, juraj, alloc impacts trace format + cm_TRC_traceMemAlloc(TRACE_ALLOCATOR_COMMAND_CREATE, 0, size, name); + + return alloc; +} + +PUBLIC t_cm_error cm_MM_DeleteAllocator(t_cm_allocator_desc *alloc) +{ + t_cm_chunk *chunk, *next_cm_chunk; + + cm_TRC_traceMemAlloc(TRACE_ALLOCATOR_COMMAND_DESTROY, 0, 0, alloc->pAllocName); + + /* Parse all chunks and free them */ + chunk = alloc->chunks; + while(chunk != 0) + { + next_cm_chunk = chunk->next; + unlinkChunk(alloc, chunk); + freeChunk(chunk); + + chunk = next_cm_chunk; + } + + // Remove allocator from the list + if(ListOfAllocators == alloc) + ListOfAllocators = alloc->next; + else { + t_cm_allocator_desc *prev = ListOfAllocators; + while(prev->next != alloc) + prev = prev->next; + prev->next = alloc->next; + } + + + /* Free allocator descriptor */ + OSAL_Free(alloc); + + return CM_OK; +} + +PUBLIC t_cm_error cm_MM_ResizeAllocator(t_cm_allocator_desc *alloc, t_cm_size size) +{ + t_cm_error error; + + /* sanity check */ + if (size == 0) + return CM_INVALID_PARAMETER; + + if((error = fillChunkPool()) != CM_OK) + return error; + + if (size > alloc->size) { + /* ok, increase allocator */ + t_uint32 deltaSize = size - alloc->size; + t_cm_chunk *last = cm_MM_RA_getLastChunk(alloc); + + if (last->status == MEM_FREE) { + /* last chunk is a free one, just increase size */ + unlinkFreeMem(alloc, last); + last->size += deltaSize; + alloc->size += deltaSize; + /* now list of free chunk is potentially no more ordered */ + updateFreeList(alloc, last); + } else { + /* last chunk is a used one, add new free chunk */ + last->size += deltaSize; + splitChunk(alloc, last, last->offset + deltaSize, FREE_CHUNK_AFTER); + alloc->size += deltaSize; + } + } else { + /* reduce allocator */ + t_uint32 deltaSize = alloc->size - size; + t_cm_chunk *last = cm_MM_RA_getLastChunk(alloc); + + /* check if resize is possible */ + if (last->status == MEM_USED) + return CM_NO_MORE_MEMORY; + if (last->size < deltaSize) + return CM_NO_MORE_MEMORY; + + /* ok, rezise can be performed */ + if (last->size == deltaSize) { + t_cm_chunk *prev = last->prev; + + /* remove last free chunk */ + mergeChunk(alloc, prev, last); + prev->size -= deltaSize; + } else { + unlinkFreeMem(alloc, last); + /* reduce size of last free chunk */ + last->size -= deltaSize; + /* now list of free chunk is potentially no more ordered */ + updateFreeList(alloc, last); + } + } + + alloc->size = size; + + if (cmIntensiveCheckState) { + cm_MM_RA_checkAllocator(alloc); + } + + return CM_OK; +} + +t_cm_error cm_MM_getValidMemoryHandle(t_cm_memory_handle handle, t_memory_handle* validHandle) +{ +#ifdef LINUX + /* On linux, there is already a check within the linux part + * => we don't need to check twice */ + *validHandle = (t_memory_handle)handle; + return CM_OK; +#else + t_cm_allocator_desc *alloc = ListOfAllocators; + + for(; alloc != NULL; alloc = alloc->next) + { + t_cm_chunk* chunk = alloc->chunks; + + /* Parse all chunks */ + for(; chunk != NULL; chunk = chunk->next) + { + if(chunk == (t_memory_handle)handle) + { + if(chunk->status == MEM_FREE) + return CM_MEMORY_HANDLE_FREED; + + *validHandle = (t_memory_handle)handle; + + return CM_OK; + } + } + } + + return CM_UNKNOWN_MEMORY_HANDLE; +#endif +} + +//TODO, juraj, add appartenance to allocHandle (of chunk) and degage setUserData +PUBLIC t_memory_handle cm_MM_Alloc( + t_cm_allocator_desc* alloc, + t_cm_size size, + t_cm_memory_alignment memAlignment, + t_uint32 seg_offset, + t_uint32 seg_size, + t_uint32 domainId) +{ + t_cm_chunk* chunk; + t_uint32 aligned_offset; + t_uint32 aligned_end; + t_uint32 seg_end = seg_offset + seg_size; + int i; + + /* Sanity check */ + if ( (size == 0) || (size > seg_size) ) + return INVALID_MEMORY_HANDLE; + + if(fillChunkPool() != CM_OK) + return INVALID_MEMORY_HANDLE; + + /* Get first chunk available for the specific size */ + // Search a list with a free chunk + for(i = bin_index(size); i < BINS; i++) + { + chunk = alloc->free_mem_chunks[i]; + while (chunk != 0) + { + /* Alignment of the lower boundary */ + aligned_offset = ALIGN_VALUE(MAX(chunk->offset, seg_offset), (memAlignment + 1)); + + aligned_end = aligned_offset + size; + + if ((aligned_end <= seg_end) + && aligned_end <= (chunk->offset + chunk->size) + && aligned_offset >= seg_offset + && aligned_offset >= chunk->offset) + goto found; + + chunk = chunk->next_free_mem; + } + } + + return INVALID_MEMORY_HANDLE; + +found: + + /* Remove chunk from free list */ + unlinkFreeMem(alloc, chunk); + + //create an empty chunk before the allocated one + if (chunk->offset < aligned_offset) { + chunk = splitChunk(alloc, chunk, aligned_offset, FREE_CHUNK_BEFORE); + } + //create an empty chunk after the allocated one + if (chunk->offset + chunk->size > aligned_end) { + splitChunk(alloc, chunk, aligned_end, FREE_CHUNK_AFTER); + } + + chunk->status = MEM_USED; + chunk->prev_free_mem = 0; + chunk->next_free_mem = 0; + chunk->domainId = domainId; + + //TODO, juraj, alloc impacts trace format + cm_TRC_traceMem(TRACE_ALLOC_COMMAND_ALLOC, 0, chunk->offset, chunk->size); + + if (cmIntensiveCheckState) { + cm_MM_RA_checkAllocator(alloc); + } + + chunk->alloc = alloc; + return (t_memory_handle) chunk; +} + +//caution - if successfull, the chunk offset will be aligned with seg_offset +//caution++ the offset of the allocated chunk changes implicitly +PUBLIC t_memory_handle cm_MM_Realloc( + t_cm_allocator_desc* alloc, + const t_cm_size size, + const t_uint32 offset, + const t_cm_memory_alignment memAlignment, + const t_memory_handle handle) +{ + t_cm_chunk *chunk = (t_cm_chunk*)handle; + + /* check reallocation is related to this chunk! */ + CM_ASSERT(chunk->offset <= (offset + size)); + CM_ASSERT(offset <= (chunk->offset + chunk->size)); + CM_ASSERT(size); + + /* check if extend low */ + if (offset < chunk->offset) { + /* note: it is enough to check only the previous chunk, + * because adjacent chunks of same status are merged + */ + if ((chunk->prev == 0) + ||(chunk->prev->status != MEM_FREE) + ||(chunk->prev->offset > offset)) { + return INVALID_MEMORY_HANDLE; + } + } + + /* check if extend high, note as above */ + if ( (offset + size) > (chunk->offset + chunk->size)) { + if ((chunk->next == 0) + ||(chunk->next->status != MEM_FREE) + ||( (chunk->next->offset + chunk->next->size) < (offset + size))) { + return INVALID_MEMORY_HANDLE; + } + } + + if(fillChunkPool() != CM_OK) + return INVALID_MEMORY_HANDLE; + + +#if 0 + /* extend low + * all conditions should have been checked + * this must not fail + */ + if (offset < chunk->offset) { + t_cm_chunk *tmp = splitChunk(alloc, chunk->prev, offset, FREE_CHUNK_BEFORE); //tmp = chunk->prev + CM_ASSERT(tmp); + tmp->status = MEM_USED; + tmp->prev->status = MEM_FREE; + mergeChunk(alloc, tmp, chunk); + if ((tmp->prev->prev != 0) + && (tmp->prev->prev->status == MEM_FREE)) { + mergeChunk(alloc, tmp->prev->prev, tmp->prev); + } + chunk = tmp; + } + + /* extend high */ + if ( (offset + size) > (chunk->offset + chunk->size)) { + t_cm_chunk *tmp = splitChunk(alloc, chunk->next, offset + size, FREE_CHUNK_AFTER); //tmp = chunk->next->next + CM_ASSERT(tmp); + tmp->status = MEM_USED; + mergeChunk(alloc, chunk, tmp); + if ((tmp->next->next != 0) + && (tmp->next->next->status == MEM_FREE)) { + mergeChunk(alloc, tmp->next, tmp->next->next); + } + } + + /* reduce top */ + if ((offset + size) < (chunk->offset + chunk->size)) { + t_cm_chunk *tmp = splitChunk(alloc, chunk, offset + size, FREE_CHUNK_AFTER); //tmp = chunk, chunk = result + CM_ASSERT(tmp); + tmp->status = MEM_USED; + tmp->next->status = MEM_FREE; + if ((tmp->next->next != 0) + && (tmp->next->next->status == MEM_FREE)) { + mergeChunk(alloc, tmp->next, tmp->next->next); + } + } + + /* reduce bottom */ + if (offset > chunk->offset) { + t_cm_chunk *tmp = splitChunk(alloc, chunk, offset, FREE_CHUNK_BEFORE); //tmp->next = chunk, tmp = result + CM_ASSERT(tmp); + tmp->status = MEM_USED; + tmp->prev->status = MEM_FREE; + if ((tmp->prev->prev != 0) + &&(tmp->prev->prev->status == MEM_FREE)) { + mergeChunk(alloc, tmp->prev->prev, tmp->prev); + } + chunk = tmp; + } +#else + /* extend low + * all conditions should have been checked + * this must not fail + */ + if (offset < chunk->offset) { + t_uint32 delta = chunk->prev->offset + chunk->prev->size - offset; + CM_ASSERT(chunk->prev->status == MEM_FREE); //TODO, juraj, already checked + unlinkFreeMem(alloc, chunk->prev); + chunk->prev->size -= delta; + chunk->offset -= delta; + chunk->size += delta; + updateFreeList(alloc, chunk->prev); + } + + /* extend high */ + if ( (offset + size) > (chunk->offset + chunk->size)) { + t_uint32 delta = size - chunk->size; + CM_ASSERT(chunk->next->status == MEM_FREE); //TODO, juraj, already checked + unlinkFreeMem(alloc, chunk->next); + chunk->size += delta; + chunk->next->offset += delta; + chunk->next->size -= delta; + updateFreeList(alloc, chunk->next); + } + + /* reduce top */ + if ((offset + size) < (chunk->offset + chunk->size)) { + if (chunk->next->status == MEM_FREE) { + t_uint32 delta = chunk->size - size; + unlinkFreeMem(alloc, chunk->next); + chunk->size -= delta; + chunk->next->offset -= delta; + chunk->next->size += delta; + updateFreeList(alloc, chunk->next); + } else { + t_cm_chunk *tmp = splitChunk(alloc, chunk, offset + size, FREE_CHUNK_AFTER); //tmp = chunk, chunk = result + tmp->status = MEM_USED; + tmp->next->status = MEM_FREE; + } + } + + /* reduce bottom */ + if (offset > chunk->offset) { + if (chunk->prev->status == MEM_FREE) { + t_uint32 delta = offset - chunk->offset; + unlinkFreeMem(alloc, chunk->prev); + chunk->prev->size += delta; + chunk->offset = offset; + chunk->size -= delta; + updateFreeList(alloc, chunk->prev); + } else { + t_cm_chunk *tmp = splitChunk(alloc, chunk, offset, FREE_CHUNK_BEFORE); //tmp->next = chunk, tmp = result + tmp->status = MEM_USED; + tmp->prev->status = MEM_FREE; + } + } +#endif + cm_MM_RA_checkAllocator(alloc); + + return (t_memory_handle)chunk; +} + +PUBLIC void cm_MM_Free(t_cm_allocator_desc* alloc, t_memory_handle memHandle) +{ + t_cm_chunk* chunk = (t_cm_chunk*)memHandle; + + //TODO, juraj, alloc impacts trace format + cm_TRC_traceMem(TRACE_ALLOC_COMMAND_FREE, 0, + chunk->offset, chunk->size); + + /* Update chunk status */ + chunk->status = MEM_FREE; + chunk->domainId = 0x0; + + /* Check if the previous chunk is free */ + if((chunk->prev != 0) && (chunk->prev->status == MEM_FREE)) { + chunk = chunk->prev; //chunk, ie. chunk->next, will be freed + mergeChunk(alloc, chunk, chunk->next); + } + + /* Check if the next chunk is free */ + if((chunk->next != 0) && (chunk->next->status == MEM_FREE)) { + mergeChunk(alloc, chunk, chunk->next); + } + + unlinkFreeMem(alloc, chunk); + updateFreeList(alloc, chunk); + + if (cmIntensiveCheckState) { + cm_MM_RA_checkAllocator(alloc); + } +} + +PUBLIC t_cm_error cm_MM_GetAllocatorStatus(t_cm_allocator_desc* alloc, t_uint32 offset, t_uint32 size, t_cm_allocator_status *pStatus) +{ + t_cm_chunk* chunk = alloc->chunks; + t_uint8 min_free_size_updated = FALSE; + + /* Init status */ + pStatus->global.used_block_number = 0; + pStatus->global.free_block_number = 0; + pStatus->global.maximum_free_size = 0; + pStatus->global.minimum_free_size = 0xFFFFFFFF; + pStatus->global.accumulate_free_memory = 0; + pStatus->global.accumulate_used_memory = 0; + pStatus->global.size = alloc->size; + pStatus->domain.maximum_free_size = 0; + pStatus->domain.minimum_free_size = 0xFFFFFFFF; + pStatus->domain.accumulate_free_memory = 0; + pStatus->domain.accumulate_used_memory = 0; + pStatus->domain.size= size; + + //TODO, juraj, get allocator status for a domain + /* Parse all chunks */ + while(chunk != 0) + { + + /* Chunk is free */ + if (chunk->status == MEM_FREE) { + pStatus->global.free_block_number++; + pStatus->global.accumulate_free_memory += chunk->size; + + /* Check max size */ + if (chunk->size > pStatus->global.maximum_free_size) + { + pStatus->global.maximum_free_size = chunk->size; + } + + /* Check min size */ + if (chunk->size < pStatus->global.minimum_free_size) + { + pStatus->global.minimum_free_size = chunk->size; + min_free_size_updated = TRUE; + } + } else {/* Chunk used */ + pStatus->global.used_block_number++; + pStatus->global.accumulate_used_memory += chunk->size; + } + + chunk = chunk->next; + } + + /* Put max free size to min free size */ + if (min_free_size_updated == FALSE) { + pStatus->global.minimum_free_size = pStatus->global.maximum_free_size; + } + + return CM_OK; +} + +PUBLIC t_uint32 cm_MM_GetOffset(t_memory_handle memHandle) +{ + /* Provide offset */ + return ((t_cm_chunk*)memHandle)->offset; +} + +PUBLIC t_uint32 cm_MM_GetSize(t_memory_handle memHandle) +{ + return ((t_cm_chunk*)memHandle)->size; +} + +PUBLIC t_uint32 cm_MM_GetAllocatorSize(t_cm_allocator_desc* alloc) +{ + return alloc->size; +} + +PUBLIC void cm_MM_SetMemoryHandleUserData(t_memory_handle memHandle, t_uint16 userData) +{ + ((t_cm_chunk*)memHandle)->userData = userData; +} + +PUBLIC void cm_MM_GetMemoryHandleUserData(t_memory_handle memHandle, t_uint16 *pUserData, t_cm_allocator_desc **alloc) +{ + *pUserData = ((t_cm_chunk*)memHandle)->userData; + if (alloc) + *alloc = ((t_cm_chunk*)memHandle)->alloc; +} + +/* + * check free list is ordered + * check all chunks are correctly linked + * check adjacent chunks are not FREE + */ +static void cm_MM_RA_checkAllocator(t_cm_allocator_desc* alloc) +{ + t_cm_chunk *chunk = alloc->chunks; + t_cm_chunk *first = chunk; + t_cm_chunk *last = chunk; + t_uint32 size = 0; + int i; + + while(chunk != 0) { + CM_ASSERT(chunk->alloc == alloc); + + if (chunk->next != 0) { + CM_ASSERT(!((chunk->status == MEM_FREE) && (chunk->next->status == MEM_FREE))); //two free adjacent blocks + CM_ASSERT(chunk->offset < chunk->next->offset); //offsets reverted + last = chunk->next; + } + size += chunk->size; + chunk = chunk->next; + } + + CM_ASSERT(size == alloc->size); + + for(i = 0; i < BINS; i++) + { + chunk = alloc->free_mem_chunks[i]; + while(chunk != 0) { + if (chunk->next_free_mem != 0) { + CM_ASSERT(chunk->size <= chunk->next_free_mem->size); //free list not ordered + } + CM_ASSERT(!(chunk->prev == 0 && (chunk != first))); //chunk not linked properly + CM_ASSERT(!(chunk->next == 0 && (chunk != last))); //chunk not linked property + chunk = chunk->next_free_mem; + } + } +} + +#if 0 +static void cm_MM_RA_checkAlloc(t_cm_allocator_desc* alloc, t_uint32 size, t_uint32 align, t_uint32 min, t_uint32 max) +{ + t_cm_chunk *chunk = alloc->chunks; + + while(chunk != 0) { + if (chunk->status == MEM_USED) { + chunk = chunk->next; + continue; + } + if (chunk->size < size) { + chunk = chunk->next; + continue; + } + + if (min < chunk->offset) { + t_uint32 aligned_offset = ALIGN_VALUE(chunk->offset, align + 1); + t_uint32 aligned_end = aligned_offset + size; + if ((aligned_offset + size <= chunk->offset + chunk->size) + && (chunk->offset + chunk->size <= aligned_end)){ + break; + } + } + + if (min >= chunk->offset) { + t_uint32 aligned_offset = ALIGN_VALUE(min, align + 1); + t_uint32 aligned_end = aligned_offset + size; + if ((aligned_offset + size <= chunk->offset + chunk->size) + && (chunk->offset + chunk->size <= aligned_end)) { + break; + } + } + + chunk = chunk->next; + } + + CM_ASSERT(chunk == 0); +} +#endif + +/***************************************************************************/ +/* + * cm_mm_ra_getLastChunk + * param handle : Handle of the allocator + * return : last + * + * Free all chunk in the allocator + * Free allocator descriptor + * + */ +/***************************************************************************/ +static t_cm_chunk* cm_MM_RA_getLastChunk(t_cm_allocator_desc* alloc) +{ + t_cm_chunk* pChunk = alloc->chunks; + + while(pChunk->next != 0) {pChunk = pChunk->next;} + + return pChunk; +} + +PUBLIC void cm_MM_DumpMemory(t_cm_allocator_desc* alloc, t_uint32 start, t_uint32 end) +{ + t_cm_chunk *chunk = alloc->chunks; + + LOG_INTERNAL(0, "ALLOCATOR Dumping allocator \"%s\" [0x%08x:0x%08x]\n", alloc->pAllocName, start, end, 0, 0, 0); + while(chunk != 0) { + if (((chunk->offset < start) && (chunk->offset + chunk->size > start)) + || ((chunk->offset < end) && (chunk->offset + chunk->size > end)) + || ((chunk->offset > start) && (chunk->offset + chunk->size < end)) + || ((chunk->offset < start) && (chunk->offset + chunk->size > end))) + { + LOG_INTERNAL(0, "ALLOCATOR chunk 0x%08x -> 0x%08x: status:%s, domainId: 0x%x\n", + chunk->offset, + chunk->offset + chunk->size, + chunk->status?"FREE":"USED", + chunk->domainId, 0, 0); + } + chunk = chunk->next; + } +} diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator_utils.c b/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator_utils.c new file mode 100644 index 00000000000..5c19d3e9b5e --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator_utils.c @@ -0,0 +1,270 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include + +/***************************************************************************/ +/* + * linkChunk + * param prev : Pointer on previous chunk where the chunk will be added + * param add : Pointer on chunk to add + * + * Add a chunk in the memory list + * + */ +/***************************************************************************/ +PUBLIC void linkChunk(t_cm_chunk* prev, t_cm_chunk* add) +{ + /* Link previous */ + add->prev = prev; + add->next = prev->next; + + /* Link next */ + if (prev->next != 0) + { + prev->next->prev = add; + } + prev->next = add; +} + +/***************************************************************************/ +/* + * unlinkChunk + * param allocHandle : Allocator handle + * param current : Pointer on chunk to remove + * + * Remove a chunk in the memory list and update first pointer + * + */ +/***************************************************************************/ +PUBLIC void unlinkChunk(t_cm_allocator_desc* alloc ,t_cm_chunk* current) +{ + /* Unlink previous */ + if (current->prev !=0) + { + current->prev->next = current->next; + } + + /* Unlink next */ + if (current->next !=0) + { + current->next->prev= current->prev; + } + + /* Update first pointer */ + if (alloc ->chunks == current) + { + alloc ->chunks = current->next; + } +} + + +/***************************************************************************/ +/* + * unlinkFreeMem() unlinks chunk from free memory double-linked list + * makes the previous and next chunk in the list point to each other.. + * param allocHandle : Allocator handle + * param current : Pointer on chunk to remove + * + * Remove a chunk in the free memory list and update pointer + * + */ +/***************************************************************************/ +PUBLIC void unlinkFreeMem(t_cm_allocator_desc* alloc ,t_cm_chunk* current) +{ + int bin = bin_index(current->size); + + /* unlink previous */ + if (current->prev_free_mem != 0) + { + current->prev_free_mem->next_free_mem = current->next_free_mem; + } + + /* Unlink next */ + if (current->next_free_mem !=0 ) + { + current->next_free_mem->prev_free_mem = current->prev_free_mem; + } + + /* update first free pointer */ + if (alloc->free_mem_chunks[bin] == current) + { + alloc->free_mem_chunks[bin] = current->next_free_mem; + } + + current->prev_free_mem = 0; + current->next_free_mem = 0; +} + +/***************************************************************************/ +/* + * linkFreeMemBefore + * param add : Pointer on chunk to add + * param next : Pointer on next chunk where the chunk will be added before + * + * Add a chunk in the free memory list + * + */ +/***************************************************************************/ +PUBLIC void linkFreeMemBefore(t_cm_chunk* add, t_cm_chunk* next) +{ + /* Link next */ + add->prev_free_mem = next->prev_free_mem; + add->next_free_mem = next; + + /* Link previous */ + if (next->prev_free_mem != 0) + { + next->prev_free_mem->next_free_mem = add; + } + next->prev_free_mem = add; +} + +/***************************************************************************/ +/* + * linkFreeMemAfter + * param add : Pointer on chunk to add + * param prev : Pointer on previous chunk where the chunk will be added after + * + * Add a chunk in the free memory list + * + */ +/***************************************************************************/ +PUBLIC void linkFreeMemAfter(t_cm_chunk* prev,t_cm_chunk* add) +{ + /* Link previous */ + add->prev_free_mem = prev; + add->next_free_mem = prev->next_free_mem; + + /* Link next */ + if (prev->next_free_mem != 0) + { + prev->next_free_mem->prev_free_mem = add; + } + prev->next_free_mem = add; +} + + +/***************************************************************************/ +/* + * updateFreeList + * param allocHandle : Allocator handle + * param offset : Pointer on chunk + * + * Update free memory list, ordered by size + * + */ +/***************************************************************************/ +PUBLIC void updateFreeList(t_cm_allocator_desc* alloc , t_cm_chunk* chunk) +{ + t_cm_chunk* free_chunk; + int bin = bin_index(chunk->size); + + /* check case with no more free block */ + if (alloc->free_mem_chunks[bin] == 0) + { + alloc->free_mem_chunks[bin] = chunk; + return ; + } + + /* order list */ + free_chunk = alloc->free_mem_chunks[bin]; + while ((free_chunk->next_free_mem != 0) && (chunk->size > free_chunk->size)) + { + free_chunk = free_chunk->next_free_mem; + } + + /* Add after free chunk if smaller -> we are the last */ + if(free_chunk->size <= chunk->size) + { + linkFreeMemAfter(free_chunk,chunk); + } + else // This mean that we are smaller + { + linkFreeMemBefore(chunk,free_chunk); + + /* Update first free chunk */ + if (alloc->free_mem_chunks[bin] == free_chunk) + { + alloc->free_mem_chunks[bin] = chunk; + } + } +} + + +/***************************************************************************/ +/* + * mergeChunk + * param allocHandle : Allocator handle + * param merged_chunk : Pointer on merged chunk + * param destroy : Pointer on chunk to destroy + * + * Link and destroy merged chunks + * + */ +/***************************************************************************/ +PUBLIC void mergeChunk(t_cm_allocator_desc* alloc,t_cm_chunk *merged_chunk, t_cm_chunk *destroy) +{ + /* Assign offset to the merged */ + /* assume chunks ordered! + if (merged_chunk->offset > destroy->offset) { + merged_chunk->offset = destroy->offset; + } + */ + + /* Remove chunk */ + unlinkChunk(alloc, destroy); + unlinkFreeMem(alloc, destroy); + + if (merged_chunk->status == MEM_FREE) + unlinkFreeMem(alloc, merged_chunk); + + /* Update size */ + merged_chunk->size += destroy->size; + + if (merged_chunk->status == MEM_FREE) + updateFreeList(alloc, merged_chunk); + + freeChunk(destroy); +} + +/***************************************************************************/ +/* + * splitChunk + * param allocHandle : Allocator handle + * param chunk : Current chunk (modified in place) + * param offset : Offset address of the start memory + * return : New chunk handle or 0 if an error occurs + * + * Create new chunk before/after the current chunk with the size + */ +/***************************************************************************/ +PUBLIC t_cm_chunk* splitChunk(t_cm_allocator_desc* alloc ,t_cm_chunk *chunk, + t_uint32 offset, t_mem_split_position position) +{ + t_cm_chunk *free; + t_cm_chunk *returned; + + t_cm_chunk* new_chunk = allocChunk(); + + if (position == FREE_CHUNK_AFTER) { + returned = chunk; + free = new_chunk; + } else { //FREE_CHUNK_BEFORE + returned = new_chunk; + free = chunk; + } + + new_chunk->offset = offset; + new_chunk->size = chunk->offset + chunk->size - offset; + new_chunk->alloc = alloc; + chunk->size = offset - chunk->offset; + + linkChunk(chunk, new_chunk); + unlinkFreeMem(alloc, free); + updateFreeList(alloc, free); + + return returned; +} diff --git a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h new file mode 100644 index 00000000000..8d95436e796 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h @@ -0,0 +1,471 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \brief OS Adaptation Layer API + * + * \defgroup CM_ENGINE_OSAL_API CM Engine OSAL (Operating System Abstraction Layer) API + * \ingroup CM_ENGINE_MODULE + */ +#ifndef __INC_CM_OSAL_H +#define __INC_CM_OSAL_H + +#include +#include + +/*! + * \brief Identifier of a trace channel (id in [0..255]) + * \ingroup CM_ENGINE_OSAL_API + */ +typedef t_uint8 t_nmf_trace_channel; + +/*! + * \brief Identifier of lock create by OSAL + * \ingroup CM_ENGINE_OSAL_API + */ +typedef t_uint32 t_nmf_osal_sync_handle; + +/*! + * \brief Identifier of semaphore create by OSAL + * \ingroup CM_ENGINE_OSAL_API + */ +typedef t_uint32 t_nmf_osal_sem_handle; + +/*! + * \brief Identifier of semaphore wait error return by semaphore OSAL API + * \ingroup CM_ENGINE_OSAL_API + */ +typedef t_uint8 t_nmf_osal_sync_error; +#define SYNC_ERROR_TIMEOUT ((t_nmf_osal_sync_error)-1) +#define SYNC_OK ((t_nmf_osal_sync_error)0) +#define SEM_TIMEOUT_NORMAL 3000 +#define SEM_TIMEOUT_DEBUG 300000 + +/*! + * \brief Description of the Scheduling part of the OS Adaptation Layer + * + * Goal: Support of uplink communication path (from Media Processors to Host (ARM)) + * + * Post a function call outside of Host CPU Interrupt mode in order to minimize ISR execution time + * \param[in] upLayerTHIS : this one provided by user when calling CM_ENGINE_BindComponentToCMCore() (first field of the interface context) \n + * \param[in] methodIndex : index method to be called \n + * \param[in] anyPtr : internal NMF marshaled parameters block (to be passed as second parameter when calling the previous pSkeleton method) \n + * \param[in] ptrSize : size of anyPtr in bytes \n + * + * Called by: + * - CM_ProcessMpcEvent() call (shall be bound by OS integrator to HSEM IRQ) + * + * \ingroup CM_ENGINE_OSAL_API + */ + +PUBLIC void OSAL_PostDfc( + t_nmf_mpc2host_handle upLayerTHIS, + t_uint32 methodIndex, + t_event_params_handle anyPtr, + t_uint32 ptrSize); + + +/*! + * \brief Description of the Synchronization part of the OS Adaptation Layer + * + * Goal: Use by CM to protect global variable against multiple call. Interrupt and scheduler function are use when + * we take hardware/local semaphore. Scheduler lock functions can have empty implementation but this may + * impact performance (dsp waiting semaphore because host thread was preempted whereas it has already take semaphore + * but not yet release it). + * + * \return handle of the Mutex created + * + * Called by: + * - any CM API call + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC t_nmf_osal_sync_handle OSAL_CreateLock(void); + +/*! + * \brief Description of the Synchronization part of the OS Adaptation Layer + * + * Goal: Use by CM to protect global variable against multiple call. Interrupt and scheduler function are use when + * we take hardware/local semaphore. Scheduler lock functions can have empty implementation but this may + * impact performance (dsp waiting semaphore because host thread was preempted whereas it has already take semaphore + * but not yet release it). + * + * \param[in] handle handle of the Mutex to be locked + * + * Called by: + * - any CM API call + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_Lock( + t_nmf_osal_sync_handle handle); + +/*! + * \brief Description of the Synchronization part of the OS Adaptation Layer + * + * Goal: Use by CM to protect global variable against multiple call. Interrupt and scheduler function are use when + * we take hardware/local semaphore. Scheduler lock functions can have empty implementation but this may + * impact performance (dsp waiting semaphore because host thread was preempted whereas it has already take semaphore + * but not yet release it). + * + * \param[in] handle handle of the Mutex to be unlocked + * + * Called by: + * - any CM API call + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_Unlock( + t_nmf_osal_sync_handle handle); + +/*! + * \brief Description of the Synchronization part of the OS Adaptation Layer + * + * Goal: Use by CM to protect global variable against multiple call. Interrupt and scheduler function are use when + * we take hardware/local semaphore. Scheduler lock functions can have empty implementation but this may + * impact performance (dsp waiting semaphore because host thread was preempted whereas it has already take semaphore + * but not yet release it). + * + * \param[in] handle handle of the Mutex to be destroyed + * + * Called by: + * - any CM API call + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_DestroyLock( + t_nmf_osal_sync_handle handle); + +/*! + * \brief Description of the Synchronization part of the OS Adaptation Layer + * + * Goal: Use by CM to allow to synchronize with code running on mpc side. + * + * \param[in] value : Initial value of semaphore. + * + * \return handle of the Semaphore created + * + * Called by: + * - any CM API call + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC t_nmf_osal_sem_handle OSAL_CreateSemaphore( + t_uint32 value); + +/*! + * \brief Description of the Synchronization part of the OS Adaptation Layer + * + * Goal: Use by CM to allow to synchronize with code running on mpc side. This function can be call under + * Irq context by CM. + * + * \param[in] handle handle of the Semaphore for which we increase value and so potentially wake up thread. + * + * \param[in] aCtx is a hint to indicate to os that we are in a none normal context (e.g under interruption). + * + * Called by: + * - any CM API call + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_SemaphorePost( + t_nmf_osal_sem_handle handle, + t_uint8 aCtx); + +/*! + * \brief Description of the Synchronization part of the OS Adaptation Layer + * + * Goal: Use by CM to allow to synchronize with code running on mpc side. + * + * \param[in] handle of the Semaphore for which we decrease value and so potentially block current thread. + * + * \param[in] timeOutInMs maximun time in ms after which the block thread is wake up. In this case function return SYNC_ERROR_TIMEOUT value. + * + * \return error number: SYNC_ERROR_TIMEOUT in case semaphore is not release withing timeOutInMs. + * + * Called by: + * - any CM API call + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC t_nmf_osal_sync_error OSAL_SemaphoreWaitTimed( + t_nmf_osal_sem_handle handle, + t_uint32 timeOutInMs); + +/*! + * \brief Description of the Synchronization part of the OS Adaptation Layer + * + * Goal: Use by CM to allow to synchronize with code running on mpc side. + * + * \param[in] handle handle of the Semaphore to be destroyed + * + * Called by: + * - any CM API call + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_DestroySemaphore( + t_nmf_osal_sem_handle handle); + +/*! + * \brief Description of the System Memory Allocator part of the OS Adaptation Layer + * + * Goal: Allocate CM some cacheable and bufferable memory (SDRAM) for internal usage \n + * This memory will be accessed only by Host CPU (ARM) + * + * This function provide a simple, general-purpose memory allocation. The + * OSAL_Alloc macro returns a pointer to a block of at least size bytes + * suitably aligned for any use. If there is no available memory, this + * function returns a null pointer. + * + * \param[in] size size in bytes, of memory to be allocated + * \return pointer on the beginning of the allocated memory + * + * Called by: + * - any CM API call + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void* OSAL_Alloc( + t_cm_size size); + +/*! + * \brief Description of the System Memory Allocator part of the OS Adaptation Layer with memory set to zero + * + * Compare to \see OSAL_Alloc, same allocation is done but memory is set with zero before returning. + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void* OSAL_Alloc_Zero( + t_cm_size size); + +/*! + * \brief Description of the System Memory Allocator part of the OS Adaptation Layer + * + * Goal: Free CM some cacheable and bufferable memory (SDRAM) for internal usage \n + * This memory will be accessed only by Host CPU (ARM) + * + * \param[in] pHandle pointer on the begining of the memory previously allocated + * + * Called by: + * - any CM API call + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_Free( + void *pHandle); + +/*! + * \brief Clean data cache in DDR in order to be accessible from peripheral. + * + * This method must be synchronized with MMDSP Code cache attribute. + * Strongly Ordered -> nothing + * Shared device -> dsb + L2 Write buffer drain + * Non cacheable, Bufferable -> dsb + L2 Write buffer drain + * WT or WB -> Flush cache range + dsb + L2 Write buffer drain + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_CleanDCache( + t_uint32 startAddr, //!< [in] Start data address of range to clean + t_uint32 Size //!< [in] Size of range to clean + ); + +/*! + * \brief Flush write buffer. + * + * This method must be synchronized with MMDSP Data cache attribute. + * Strongly Ordered -> nothing + * Shared device -> dsb + L2 Write buffer drain + * Non cacheable, Bufferable -> dsb + L2 Write buffer drain + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_mb(void); + +/*! + * \brief Description of the System Memory part of the OS Adaptation Layer + * + * Goal: Copy some cacheable and bufferable memory (SDRAM) provided by a client to\n + * internal memory. + * + * \param[in] dst : pointer on the begining of the internal memory previously allocated + * \param[in] src : pointer on the begining of the client's memory + * \param[in] size : The size of the data to copy + * + * Called by: + * - CM_ENGINE_PushComponent() + * + * \note This API is mainly provided for the OS were the client application does execute in the same + * address space as the CM. + * For example in Linux or Symbian, the client's address space is userland but the CM execute in + * kernel space. Thus, 'dst' is supposed to be a kernel address but src is supposed to be a user + * space address + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC t_cm_error OSAL_Copy( + void *dst, + const void *src, + t_cm_size size); + +/*! + * \brief Description of the internal log traces configuration of the Component Manager + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_Log( + const char *format, + int param1, + int param2, + int param3, + int param4, + int param5, + int param6); + +/*! + * \brief Generate an OS-Panic. Called in from CM_ASSERT(). + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_Panic(void); + +/*! + * \brief Description of the configuration of the trace features + * + * (trace output itself is provided by user through his custom implementation of the generic APIs) + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_Write64( + t_nmf_trace_channel channel, + t_uint8 isTimestamped, + t_uint64 value); + +/*! + * \brief Power enabling/disabling commands description. + * + * \ingroup CM_ENGINE_OSAL_API + */ +typedef enum +{ + CM_OSAL_POWER_SxA_CLOCK, //!< SxA Power & Clock, firstParam contains Core ID + CM_OSAL_POWER_SxA_AUTOIDLE, //!< SxA AutoIdle, firstParam contains Core ID + CM_OSAL_POWER_SxA_HARDWARE, //!< SxA Hardware Power, firstParam contains Core ID + CM_OSAL_POWER_HSEM, //!< HSEM Power + CM_OSAL_POWER_SDRAM, //!< SDRAM memory, firstParam contains physical resource address, secondParam contains size + CM_OSAL_POWER_ESRAM //!< ESRAM memory, firstParam contains physical resource address, secondParam contains size +} t_nmf_power_resource; + +/*! + * \brief Description of the Power Management part of the OS Adaptation Layer + * + * Use by CM engine to disable a logical power domain (see \ref t_nmf_power_resource) + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_DisablePwrRessource( + t_nmf_power_resource resource, //!< [in] Describe the domain which must be disabled + t_uint32 firstParam, //!< [in] Eventual first parameter to power to disable + t_uint32 secondParam //!< [in] Eventual second parameter to power to disable + ); + +/*! + * \brief Description of the Power Management part of the OS Adaptation Layer + * + * Use by CM engine to enable a logical power domain (see \ref t_nmf_power_resource) + * + * \return + * - \ref CM_OK + * - \ref CM_PWR_NOT_AVAILABLE A specified power domain is not managed (see returned value in aPowerMask) + * + * Called by: + * - any CM API call + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC t_cm_error OSAL_EnablePwrRessource( + t_nmf_power_resource resource, //!< [in] Describing the domains which must be enabled + t_uint32 firstParam, //!< [in] Eventual first parameter to power to disable + t_uint32 secondParam //!< [in] Eventual second parameter to power to disable + ); + + +/*! + * \brief return prcmu timer value. + * + * This is need for perfmeter api (see \ref t_nmf_power_resource) + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC t_uint64 OSAL_GetPrcmuTimer(void); + +/*! + * \brief Disable the service message handling (panic, etc) + * + * It must disable the handling of all service messages + * If a service message is currently handled, it must wait till the end + * of its managment before returning. + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_DisableServiceMessages(void); + +/*! + * \brief Enable the service message handling (panic, etc) + * + * It enables the handling of all service messages + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_EnableServiceMessages(void); + +extern /*const*/ t_nmf_osal_sync_handle lockHandleApi; +extern /*const*/ t_nmf_osal_sync_handle lockHandleCom; +extern /*const*/ t_nmf_osal_sem_handle semHandle; + +/*! + * \brief Take a lock before entering critical section. Can suspend current thread if lock already taken. \n + * Use this macro in api function. For com function use OSAL_LOCK_COM. + * + * \ingroup CM_ENGINE_OSAL_API + */ +#define OSAL_LOCK_API() OSAL_Lock(lockHandleApi) + +/*! + * \brief Release lock before leaving critical section. + * + * \ingroup CM_ENGINE_OSAL_API + */ +#define OSAL_UNLOCK_API() OSAL_Unlock((lockHandleApi)) + +/*! + * \brief Take a lock before entering critical section. Can suspend current thread if lock already taken. \n + * Use this macro in com function. For com function use OSAL_LOCK_API. + * + * \ingroup CM_ENGINE_OSAL_API + */ +#define OSAL_LOCK_COM() OSAL_Lock(lockHandleCom) + +/*! + * \brief Release lock before leaving critical section. + * + * \ingroup CM_ENGINE_OSAL_API + */ +#define OSAL_UNLOCK_COM() OSAL_Unlock((lockHandleCom)) + +/*! + * \brief Go to sleep untill post done on semaphore or timeout expire. In that case SYNC_ERROR_TIMEOUT is return. + * + * \ingroup CM_ENGINE_OSAL_API + */ +#define OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) OSAL_SemaphoreWaitTimed(semHandle, (cm_PWR_GetMode() == NORMAL_PWR_MODE)?SEM_TIMEOUT_NORMAL:SEM_TIMEOUT_DEBUG) + + +/****************/ +/* Generic part */ +/****************/ +t_cm_error cm_OSAL_Init(void); +void cm_OSAL_Destroy(void); + +#endif /* __INC_CM_OSAL_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/src/os_adaptation_layer.c b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/src/os_adaptation_layer.c new file mode 100644 index 00000000000..9beb60dea18 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/src/os_adaptation_layer.c @@ -0,0 +1,39 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include + +t_nmf_osal_sync_handle lockHandleApi; +t_nmf_osal_sync_handle lockHandleCom; +t_nmf_osal_sem_handle semHandle; + +/****************/ +/* Generic part */ +/****************/ +PUBLIC t_cm_error cm_OSAL_Init(void) +{ + + /* create locks */ + lockHandleApi = OSAL_CreateLock(); + if (lockHandleApi == 0) {return CM_INVALID_PARAMETER;} + lockHandleCom = OSAL_CreateLock(); + if (lockHandleCom == 0) {return CM_INVALID_PARAMETER;} + + /* create semaphore */ + semHandle = OSAL_CreateSemaphore(0); + if (semHandle == 0) {return CM_INVALID_PARAMETER;} + + return CM_OK; +} + +PUBLIC void cm_OSAL_Destroy(void) +{ + /* destroy locks */ + OSAL_DestroyLock(lockHandleApi); + OSAL_DestroyLock(lockHandleCom); + + /* destroy semaphore */ + OSAL_DestroySemaphore(semHandle); +} diff --git a/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/mpcload.h b/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/mpcload.h new file mode 100644 index 00000000000..0831f1940ca --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/mpcload.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + */ +#ifndef MPCLOAD_H_ +#define MPCLOAD_H_ + +#include + +/******************************************************************************/ +/************************ FUNCTIONS PROTOTYPES ********************************/ +/******************************************************************************/ + +PUBLIC t_cm_error cm_PFM_allocatePerfmeterDataMemory(t_nmf_core_id coreId, t_cm_domain_id domainId); +PUBLIC void cm_PFM_deallocatePerfmeterDataMemory(t_nmf_core_id coreId); + +#endif /* MPCLOAD_H_ */ diff --git a/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h b/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h new file mode 100644 index 00000000000..78de395acc2 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Public Component Manager Performance Meter API type. + * + * This file contains the Component Manager API type for performance meter. + * + * \defgroup PERFMETER CM Monitoring API + * \ingroup CM_USER_API + */ +#ifndef CM_COMMON_PERFMETER_TYPE_H_ +#define CM_COMMON_PERFMETER_TYPE_H_ + +#include +/*! + * \brief Description of mpc load structure. + * + * This contain mpc load value. + * + * \ingroup PERFMETER + */ +typedef struct { + t_uint64 totalCounter; + t_uint64 loadCounter; +} t_cm_mpc_load_counter; + + +#endif /* CM_COMMON_PERFMETER_TYPE_H_ */ diff --git a/drivers/staging/nmf-cm/cm/engine/perfmeter/src/mpcload.c b/drivers/staging/nmf-cm/cm/engine/perfmeter/src/mpcload.c new file mode 100644 index 00000000000..b157103934d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/perfmeter/src/mpcload.c @@ -0,0 +1,116 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include + +#include +#include + +#define PERFMETER_MAX_RETRIES 32 +#define PERFMETER_DATA_WORD_NB 7 + +/* private type */ +typedef struct { + t_memory_handle perfmeterDataHandle; + t_cm_logical_address perfmeterDataAddr; +} t_mpcLoad; + +/* private globals */ +t_mpcLoad mpcLoad_i[NB_CORE_IDS]; + +/* engine api */ +PUBLIC EXPORT_SHARED t_cm_error CM_GetMpcLoadCounter( + t_nmf_core_id coreId, + t_cm_mpc_load_counter *pMpcLoadCounter +) +{ + t_uint24 data[PERFMETER_DATA_WORD_NB]; + t_uint32 i; + t_uint64 prcmuBeforeAttributes; + t_uint32 retryCounter = 0; + volatile t_uint32 *pData; + + pMpcLoadCounter->totalCounter = 0; + pMpcLoadCounter->loadCounter = 0; + /* check core id is an mpc */ + if (coreId < FIRST_MPC_ID || coreId > LAST_CORE_ID) {return CM_INVALID_PARAMETER;} + + /* check core has been booted */ + pData = (t_uint32 *) mpcLoad_i[coreId].perfmeterDataAddr; + if (pData == NULL) {return CM_OK;} + + do { + prcmuBeforeAttributes = OSAL_GetPrcmuTimer(); + /* get attributes */ + do + { + for(i = 0;i < PERFMETER_DATA_WORD_NB;i++) + data[i] = pData[i]; + } + while(((data[0] & 0xff0000) != (data[1] & 0xff0000) || (data[0] & 0xff0000) != (data[2] & 0xff0000) || + (data[0] & 0xff0000) != (data[3] & 0xff0000) || (data[0] & 0xff0000) != (data[4] & 0xff0000) || + (data[0] & 0xff0000) != (data[5] & 0xff0000) || (data[0] & 0xff0000) != (data[6] & 0xff0000) || + (data[0] & 0xff0000) != (data[6] & 0xff0000)) + && retryCounter-- < PERFMETER_MAX_RETRIES); // check data coherence + if (retryCounter >= PERFMETER_MAX_RETRIES) + return CM_MPC_NOT_RESPONDING; + + /* read forever counter for totalCounter */ + pMpcLoadCounter->totalCounter = OSAL_GetPrcmuTimer(); + } while(pMpcLoadCounter->totalCounter - prcmuBeforeAttributes >= 32); //we loop until it seems we have not be preempt too long (< 1ms) + + /* we got coherent data, use them */ + pMpcLoadCounter->loadCounter = ((data[0] & (t_uint64)0xffff) << 32) + ((data[1] & (t_uint64)0xffff) << 16) + ((data[2] & (t_uint64)0xffff) << 0); + //fix load counter if needed + if ((data[6] & 0xffff) == 1) { + t_uint64 lastEvent; + + lastEvent = ((data[3] & (t_uint64)0xffff) << 32) + ((data[4] & (t_uint64)0xffff) << 16) + ((data[5] & (t_uint64)0xffff) << 0); + pMpcLoadCounter->loadCounter += pMpcLoadCounter->totalCounter - lastEvent; + } + + return CM_OK; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_getMpcLoadCounter( + t_nmf_core_id coreId, + t_cm_mpc_load_counter *pMpcLoadCounter +) +{ + t_cm_error error; + + OSAL_LOCK_API(); + error = CM_GetMpcLoadCounter(coreId, pMpcLoadCounter); + OSAL_UNLOCK_API(); + return error; +} + +/* internal api */ +PUBLIC t_cm_error cm_PFM_allocatePerfmeterDataMemory(t_nmf_core_id coreId, t_cm_domain_id domainId) +{ + t_cm_error error = CM_OK; + t_mpcLoad *pMpcLoad = (t_mpcLoad *) &mpcLoad_i[coreId]; + + pMpcLoad->perfmeterDataHandle = cm_DM_Alloc(domainId, SDRAM_EXT24, PERFMETER_DATA_WORD_NB, CM_MM_ALIGN_WORD, TRUE); + if (pMpcLoad->perfmeterDataHandle == INVALID_MEMORY_HANDLE) + error = CM_NO_MORE_MEMORY; + else { + t_uint32 mmdspAddr; + + pMpcLoad->perfmeterDataAddr = cm_DSP_GetHostLogicalAddress(pMpcLoad->perfmeterDataHandle); + cm_DSP_GetDspAddress(pMpcLoad->perfmeterDataHandle, &mmdspAddr); + cm_writeAttribute(cm_EEM_getExecutiveEngine(coreId)->instance, "rtos/perfmeter/perfmeterDataAddr", mmdspAddr); + } + + return error; +} + +PUBLIC void cm_PFM_deallocatePerfmeterDataMemory(t_nmf_core_id coreId) +{ + mpcLoad_i[coreId].perfmeterDataAddr = 0; + cm_DM_Free(mpcLoad_i[coreId].perfmeterDataHandle, TRUE); +} diff --git a/drivers/staging/nmf-cm/cm/engine/power_mgt/inc/power.h b/drivers/staging/nmf-cm/cm/engine/power_mgt/inc/power.h new file mode 100644 index 00000000000..1ca1b314833 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/power_mgt/inc/power.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Enable a CM power domain by CoreID. + * + * \ingroup COMPONENT_INTERNAL + */ +#ifndef __INC_NMF_POWER +#define __INC_NMF_POWER + +#include +#include +#include + +typedef enum +{ + NORMAL_PWR_MODE = 0x1, //!< Normal mode + DISABLE_PWR_MODE = 0x2 //!< Disable mode - CM Power management is disabled. CM Power domain are always enabled and the EEs are loaded by default +} t_nmf_power_mode; + +PUBLIC t_cm_error cm_PWR_Init(void); +void cm_PWR_SetMode(t_nmf_power_mode aMode); +t_nmf_power_mode cm_PWR_GetMode(void); +t_uint32 cm_PWR_GetMPCMemoryCount(t_nmf_core_id coreId); + +typedef enum +{ + MPC_PWR_CLOCK, + MPC_PWR_AUTOIDLE, + MPC_PWR_HWIP +} t_mpc_power_request; + +PUBLIC t_cm_error cm_PWR_EnableMPC( + t_mpc_power_request request, + t_nmf_core_id coreId); +PUBLIC void cm_PWR_DisableMPC( + t_mpc_power_request request, + t_nmf_core_id coreId); + +PUBLIC t_cm_error cm_PWR_EnableHSEM(void); +PUBLIC void cm_PWR_DisableHSEM(void); + +PUBLIC t_cm_error cm_PWR_EnableMemory( + t_nmf_core_id coreId, + t_dsp_memory_type_id dspMemType, + t_cm_physical_address address, + t_cm_size size); +PUBLIC void cm_PWR_DisableMemory( + t_nmf_core_id coreId, + t_dsp_memory_type_id dspMemType, + t_cm_physical_address address, + t_cm_size size); + + +#endif /* __INC_NMF_POWER */ diff --git a/drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c b/drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c new file mode 100644 index 00000000000..5b206bfb82d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c @@ -0,0 +1,226 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include "../inc/power.h" + +#include +#include +#include +#include + +// ------------------------------------------------------------------------------- +// Compilation flags +// ------------------------------------------------------------------------------- +#define __PWR_DEBUG_TRACE_LEVEL 2 // Debug trave level for CM power module + +// ------------------------------------------------------------------------------- +// Internal counter to store the TCM allocated chunk (by MPC) +// ------------------------------------------------------------------------------- +static t_uint32 _pwrMPCHWIPCountT[NB_CORE_IDS]; + +// ------------------------------------------------------------------------------- +// Internal counter to store the TCM allocated chunk (by MPC) +// ------------------------------------------------------------------------------- +static t_uint32 _pwrMPCMemoryCountT[NB_CORE_IDS]; + + +// ------------------------------------------------------------------------------- +// Internal data to store the global Power Manager mode (see cm_PWR_Init fct) +// ------------------------------------------------------------------------------- +static t_nmf_power_mode _pwrMode = NORMAL_PWR_MODE; + +// ------------------------------------------------------------------------------- +// cm_PWR_Init +// ------------------------------------------------------------------------------- +PUBLIC t_cm_error cm_PWR_Init(void) +{ + int i; + + for (i=0; i for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Component repository internal methods. + * + * \defgroup REPOSITORY_INTERNAL Component repository. + */ +#ifndef __INC_CM_REP_MGT_H +#define __INC_CM_REP_MGT_H + +#include +#include + +/*! + * \brief Identification of a component entry. + * \ingroup REPOSITORY_INTERNAL + */ +typedef struct t_rep_component { + t_dup_char name; + struct t_rep_component *prev; + struct t_rep_component *next; + t_elfdescription *elfhandle; //!< Must be last as data will be stored here +} t_rep_component; + +/*! + * \brief Search a component entry by name. + * + * \param[in] name The name of the component to look for. + * \param[out] component The corresponding component entry in the repository + * + * \retval t_cm_error + * + * \ingroup REPOSITORY_INTERNAL + */ +PUBLIC t_cm_error cm_REP_lookupComponent(const char *name, t_rep_component **component); + +/*! + * \brief Helper method that return the dataFile found in parameter or in the cache + */ +t_elfdescription* cm_REP_getComponentFile(t_dup_char templateName, t_elfdescription* elfhandle); + +/*! + * \brief Destroy the full repository (remove and free all components) + * + * \retval none + * + * \ingroup REPOSITORY_INTERNAL + */ +PUBLIC void cm_REP_Destroy(void); + +#endif /* __INC_CM_REP_MGT_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h b/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h new file mode 100644 index 00000000000..7c41fe1bedb --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Components Component Manager API type. + * + * \defgroup COMPONENT CM Components API + * \ingroup CM_USER_API + */ + +#ifndef REPOSITORY_TYPE_H_ +#define REPOSITORY_TYPE_H_ + +typedef enum +{ + GET_EE_NAME, + BIND_ASYNC, + BIND_TRACE, + BIND_FROMUSER, + BIND_TOUSER +} t_action_to_do; + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c b/drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c new file mode 100644 index 00000000000..c972783db4b --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c @@ -0,0 +1,311 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define NHASH 157 //Use a prime number! +#define MULT 17 + +static t_rep_component *componentCaches[NHASH]; + +static unsigned int repcomponentHash(const char *str) +{ + unsigned int h = 0; + for(; *str; str++) + h = MULT * h + *str; + return h % NHASH; +} + +static void repcomponentAdd(t_rep_component *component) +{ + unsigned int h = repcomponentHash(component->name); + + if(componentCaches[h] != NULL) + componentCaches[h]->prev = component; + component->next = componentCaches[h]; + component->prev = NULL; + componentCaches[h] = component; +} + +static void repcomponentRemove(t_rep_component *component) +{ + unsigned int h = repcomponentHash(component->name); + + if(component->prev != NULL) + component->prev->next = component->next; + if(component->next != NULL) + component->next->prev = component->prev; + if(component == componentCaches[h]) + componentCaches[h] = component->next; +} + + +PUBLIC t_cm_error cm_REP_lookupComponent(const char *name, t_rep_component **component) +{ + t_rep_component *tmp; + + for(tmp = componentCaches[repcomponentHash(name)]; tmp != NULL; tmp = tmp->next) + { + if(cm_StringCompare(name, tmp->name, MAX_TEMPLATE_NAME_LENGTH) == 0) + { + if(component != NULL) + *component = tmp; + return CM_OK; + } + } + + return CM_COMPONENT_NOT_FOUND; +} + +t_elfdescription* cm_REP_getComponentFile(t_dup_char templateName, t_elfdescription* elfhandle) +{ + if(elfhandle == NULL) + { + t_rep_component *pRepComponent; + + for(pRepComponent = componentCaches[repcomponentHash(templateName)]; pRepComponent != NULL; pRepComponent = pRepComponent->next) + { + if(pRepComponent->name == templateName) + return pRepComponent->elfhandle; + } + + return NULL; + } + + return elfhandle; +} + + +PUBLIC void cm_REP_Destroy(void) +{ + t_rep_component *component, *next; + int i; + + for(i = 0; i < NHASH; i++) + { + for (component = componentCaches[i]; component != NULL; component = next) + { + next = component->next; + cm_ELF_CloseFile(FALSE, component->elfhandle); + cm_StringRelease(component->name); + OSAL_Free(component); + } + componentCaches[i] = NULL; + } +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetRequiredComponentFiles( + // IN + t_action_to_do action, + const t_cm_instance_handle client, + const char *requiredItfClientName, + const t_cm_instance_handle server, + const char *providedItfServerName, + // OUT component to be pushed + char fileList[][MAX_INTERFACE_TYPE_NAME_LENGTH], + t_uint32 listSize, + // OUT interface information + char type[MAX_INTERFACE_TYPE_NAME_LENGTH], + t_uint32 *methodNumber) +{ + t_cm_error error; + t_component_instance* compClient, *compServer; + int n; + + OSAL_LOCK_API(); + + // No component required + for(n = 0; n < listSize; n++) + fileList[n][0] = 0; + + compClient = cm_lookupComponent(client); + compServer = cm_lookupComponent(server); + switch(action) + { + case GET_EE_NAME: + /* Get Executive Engine names */ + error = cm_CFG_GetRequiredExecutiveEngineComponentNames(fileList, listSize); + break; + + case BIND_FROMUSER:{ + t_interface_provide_description itfProvide; + + // Check server validity + if((error = cm_checkValidServer(compServer, providedItfServerName, + &itfProvide)) == CM_OK) + { + cm_StringCopy(type, itfProvide.server->template->provides[itfProvide.provideIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + + cm_StringCopy(fileList[0], "_sk.", MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[0], itfProvide.server->template->provides[itfProvide.provideIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + } + } break; + + case BIND_TOUSER: { + /* Get Components names for a BindComponentToCMCore */ + t_interface_require_description itfRequire; + t_bool bindable; + + // Check client validity + if((error = cm_checkValidClient(compClient, requiredItfClientName, + &itfRequire, &bindable)) == CM_OK) + { + cm_StringCopy(type, itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + *methodNumber = itfRequire.client->template->requires[itfRequire.requireIndex].interface->methodNumber; + + cm_StringCopy(fileList[0], "_st.", MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[0], itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + } + }; break; + + case BIND_ASYNC: { + /* Get Components names for an asynchronous binding */ + t_interface_require_description itfRequire; + t_interface_provide_description itfProvide; + t_bool bindable; + + // Check invalid binding + if((error = cm_checkValidBinding(compClient, requiredItfClientName, + compServer, providedItfServerName, + &itfRequire, &itfProvide, &bindable)) == CM_OK) + { + if(compClient->template->dspId != compServer->template->dspId) + { + cm_StringCopy(fileList[0], "_sk.", MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[0], itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + + cm_StringCopy(fileList[1], "_st.", MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[1], itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + } + else + { + cm_StringCopy(fileList[0], "_ev.", MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[0], itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + } + } + }; break; + + case BIND_TRACE: { + /* Get Components names for an asynchronous binding */ + t_interface_require_description itfRequire; + t_interface_provide_description itfProvide; + t_bool bindable; + + // Check invalid binding + if((error = cm_checkValidBinding(compClient, requiredItfClientName, + compServer, providedItfServerName, + &itfRequire, &itfProvide, &bindable)) == CM_OK) + { + cm_StringCopy(fileList[0], "_tr.", MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[0], itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + } + }; break; + + default: + error = CM_OK; + break; + } + + if(error == CM_OK) + { + for(n = 0; n < listSize; n++) + { + t_rep_component *comp; + + // If already loaded, don't ask to load it and put the name to NULL + if (fileList[n][0] != 0 && + cm_REP_lookupComponent(fileList[n], &comp) == CM_OK) + fileList[n][0] = 0; + } + } + + + OSAL_UNLOCK_API(); + return error; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_PushComponent(const char *name, const void *data, t_cm_size size) +{ + t_rep_component *comp; + t_cm_error error; + + OSAL_LOCK_API(); + + if (cm_REP_lookupComponent(name, &comp) == CM_OK) { + /* Component is already there: silently ignore it */ + OSAL_UNLOCK_API(); + return CM_OK; + } + + comp = OSAL_Alloc(sizeof(*comp)); + if (comp == NULL) { + OSAL_UNLOCK_API(); + return CM_NO_MORE_MEMORY; + } + + comp->name = cm_StringDuplicate(name); + if(comp->name == NULL) + { + OSAL_Free(comp); + OSAL_UNLOCK_API(); + return CM_NO_MORE_MEMORY; + } + + if((error = cm_ELF_CheckFile( + data, + FALSE, + &comp->elfhandle)) != CM_OK) { + cm_StringRelease(comp->name); + OSAL_Free(comp); + OSAL_UNLOCK_API(); + return error; + } +/* + if (OSAL_Copy(comp->data, data, size)) { + OSAL_Free(comp); + OSAL_UNLOCK_API(); + return CM_UNKNOWN_MEMORY_HANDLE; + }*/ + + repcomponentAdd(comp); + + OSAL_UNLOCK_API(); + return CM_OK; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_ReleaseComponent (const char *name) +{ + t_rep_component *component; + t_cm_error err; + + OSAL_LOCK_API(); + err = cm_REP_lookupComponent(name , &component); + + if (CM_OK == err) + { + repcomponentRemove(component); + + cm_ELF_CloseFile(FALSE, component->elfhandle); + cm_StringRelease(component->name); + OSAL_Free(component); + } + + OSAL_UNLOCK_API(); + + return err; +} diff --git a/drivers/staging/nmf-cm/cm/engine/semaphores/hw_semaphores/inc/hw_semaphores.h b/drivers/staging/nmf-cm/cm/engine/semaphores/hw_semaphores/inc/hw_semaphores.h new file mode 100644 index 00000000000..bd914195b6d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/semaphores/hw_semaphores/inc/hw_semaphores.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef __INC_HW_SEMA_H_ +#define __INC_HW_SEMA_H_ + +#include +#include +#include + + +/******************************************************************************/ +/************************ FUNCTIONS PROTOTYPES ********************************/ +/******************************************************************************/ + +PUBLIC t_cm_error cm_HSEM_Init(const t_cm_system_address *pSystemAddr); +PUBLIC t_cm_error cm_HSEM_EnableSemIrq(t_semaphore_id semId, t_nmf_core_id toCoreId); +PUBLIC void cm_HSEM_Take(t_nmf_core_id coreId, t_semaphore_id semId); +PUBLIC void cm_HSEM_Give(t_nmf_core_id coreId, t_semaphore_id semId); +PUBLIC void cm_HSEM_GiveWithInterruptGeneration(t_nmf_core_id coreId, t_semaphore_id semId); +PUBLIC void cm_HSEM_GenerateIrq(t_nmf_core_id coreId, t_semaphore_id semId); +PUBLIC t_nmf_core_id cm_HSEM_GetCoreIdFromIrqSrc(void); + +PUBLIC t_cm_error cm_HSEM_PowerOn(t_nmf_core_id coreId); +PUBLIC void cm_HSEM_PowerOff(t_nmf_core_id coreId); + +#endif /* __INC_HW_SEMA_H_ */ diff --git a/drivers/staging/nmf-cm/cm/engine/semaphores/hw_semaphores/src/hw_semaphores.c b/drivers/staging/nmf-cm/cm/engine/semaphores/hw_semaphores/src/hw_semaphores.c new file mode 100644 index 00000000000..932058cd4f2 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/semaphores/hw_semaphores/src/hw_semaphores.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/******************************************************************* Includes + ****************************************************************************/ + +#include "../inc/hw_semaphores.h" +#include +#include +#include +static t_hw_semaphore_regs *pHwSemRegs = (t_hw_semaphore_regs *)0; + +static t_uint32 semaphoreUseCounter = 0; +static t_uint32 imsc[HSEM_MAX_INTR]; +PRIVATE void restoreMask(void); + +/****************************************************************************/ +/* NAME: t_cm_error cm_HSEM_Init(const t_cm_system_address *pSystemAddr) */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: Initialize the HW Semaphores module */ +/* */ +/* PARAMETERS: */ +/* (in) pSystemAddr: system base address of the HW semaphores IP */ +/* */ +/* RETURN: CM_OK always */ +/* */ +/****************************************************************************/ +PUBLIC t_cm_error cm_HSEM_Init(const t_cm_system_address *pSystemAddr) +{ + t_uint8 i; + + pHwSemRegs = (t_hw_semaphore_regs *)pSystemAddr->logical; + + for (i=HSEM_FIRST_INTR; i < HSEM_MAX_INTR; i++) + { + imsc[i] = 0; // Mask all interrupt + } + + return CM_OK; +} + +static void cm_HSEM_ReInit(void) +{ + t_uint8 i; + + pHwSemRegs->icrall = MASK_ALL16; + + for (i=HSEM_FIRST_INTR; i < HSEM_MAX_INTR; i++) + { + pHwSemRegs->it[i].imsc = imsc[i]; + pHwSemRegs->it[i].icr = MASK_ALL16; + } + + for (i=0; i < NUM_HW_SEMAPHORES; i++) + { + pHwSemRegs->sem[i] = 0; + } +} + +/****************************************************************************/ +/* NAME: t_cm_error cm_HSEM_EnableSemIrq( */ +/* t_semaphore_id semId, */ +/* t_nmf_core_id toCoreId */ +/* ) */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: Enable Irq for a given coreId (communication receiver) */ +/* */ +/* PARAMETERS: */ +/* (in) semId: identifier of the semaphore */ +/* (in) toCoreId: identifier of coreId destination of the coms */ +/* */ +/* RETURN: CM_OK always */ +/* */ +/****************************************************************************/ +PUBLIC t_cm_error cm_HSEM_EnableSemIrq(t_semaphore_id semId, t_nmf_core_id toCoreId) +{ + static t_uint32 CoreIdToIntr[NB_CORE_IDS] = {0, 2, 3}; + int i = CoreIdToIntr[toCoreId]; + + imsc[i] |= (1UL << semId); + + // Allow cm_HSEM_EnableSemIrq to be called before real start in order to save power + if(semaphoreUseCounter > 0) + { + pHwSemRegs->it[i].imsc = imsc[i]; + } + + return CM_OK; +} + +/****************************************************************************/ +/* NAME: void cm_HSEM_GenerateIrq(t_semaphore_id semId) */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: Generate an irq toward correct core according to semId */ +/* */ +/* PARAMETERS: */ +/* (in) semId: identifier of the semaphore to handle */ +/* */ +/* RETURN: none */ +/* */ +/****************************************************************************/ +PUBLIC void cm_HSEM_GenerateIrq(t_nmf_core_id coreId, t_semaphore_id semId) +{ + // TODO Move restore in OS BSP or in PRCMU in order to to it only when wake-up, for now do it always !!!!!!!!!!!! + restoreMask(); + + pHwSemRegs->sem[semId] = CORE_ID_2_HW_CORE_ID(ARM_CORE_ID); + pHwSemRegs->sem[semId] = (HSEM_INTRA_MASK|HSEM_INTRB_MASK|HSEM_INTRC_MASK|HSEM_INTRD_MASK); +} + +/****************************************************************************/ +/* NAME: t_nmf_core_id cm_HSEM_GetCoreIdFromIrqSrc(void) */ +/*--------------------------------------------------------------------------*/ +/* DESCRIPTION: Check Masked Interrupt Status to know which semaphore(s) */ +/* have pending interrupt and return the identifier of the given dsp */ +/* */ +/* PARAMETERS: none */ +/* */ +/* RETURN: none */ +/* */ +/****************************************************************************/ +PUBLIC t_nmf_core_id cm_HSEM_GetCoreIdFromIrqSrc(void) +{ + t_uword misValue = pHwSemRegs->it[ARM_CORE_ID].mis; + t_uint32 mask = 1 << FIRST_NEIGHBOR_SEMID(ARM_CORE_ID) /* == 0 here */; + t_nmf_core_id coreId = FIRST_MPC_ID; + + while ((misValue & mask) == 0) + { + mask <<= 1; + + coreId++; + if(coreId > LAST_MPC_ID) + return coreId; + } + + /* Acknowledge Hsem interrupt */ + pHwSemRegs->it[ARM_CORE_ID].icr = mask; + + return coreId; +} + +PUBLIC t_cm_error cm_HSEM_PowerOn(t_nmf_core_id coreId) +{ + if(semaphoreUseCounter++ == 0) + { + cm_PWR_EnableHSEM(); + + cm_HSEM_ReInit(); // HSEM is called one time only when the HSEM is switched ON + } + + return CM_OK; +} + +PUBLIC void cm_HSEM_PowerOff(t_nmf_core_id coreId) +{ + if(--semaphoreUseCounter == 0) + { + cm_PWR_DisableHSEM(); + } +} + +PRIVATE void restoreMask() +{ + t_uint8 i; + + for (i=HSEM_FIRST_INTR; i < HSEM_MAX_INTR; i++) + pHwSemRegs->it[i].imsc = imsc[i]; +} diff --git a/drivers/staging/nmf-cm/cm/engine/semaphores/inc/semaphores.h b/drivers/staging/nmf-cm/cm/engine/semaphores/inc/semaphores.h new file mode 100644 index 00000000000..7636d8e7c9d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/semaphores/inc/semaphores.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/** + * \internal + */ +#ifndef __INC_NMF_SEMAPHORE_H +#define __INC_NMF_SEMAPHORE_H + +#include +#include +#include + +PUBLIC t_cm_error cm_SEM_Init(const t_cm_system_address *pSystemAddr); +PUBLIC t_cm_error cm_SEM_InitMpc(t_nmf_core_id coreId, t_nmf_semaphore_type_id semTypeId); +PUBLIC t_semaphore_id cm_SEM_Alloc(t_nmf_core_id fromCoreId, t_nmf_core_id toCoreId); + +/* Semaphores management virtualized functions */ +extern void (*cm_SEM_GenerateIrq[NB_CORE_IDS])(t_nmf_core_id coreId, t_semaphore_id semId); +extern t_cm_error (*cm_SEM_PowerOn[NB_CORE_IDS])(t_nmf_core_id coreId); +extern void (*cm_SEM_PowerOff[NB_CORE_IDS])(t_nmf_core_id coreId); + +#endif /* __INC_NMF_SEMAPHORE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/semaphores/src/semaphores.c b/drivers/staging/nmf-cm/cm/engine/semaphores/src/semaphores.c new file mode 100644 index 00000000000..daf95355a56 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/semaphores/src/semaphores.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include +#include +#include +#include + +void (*cm_SEM_GenerateIrq[NB_CORE_IDS])(t_nmf_core_id coreId, t_semaphore_id semId); +t_cm_error (*cm_SEM_PowerOn[NB_CORE_IDS])(t_nmf_core_id coreId); +void (*cm_SEM_PowerOff[NB_CORE_IDS])(t_nmf_core_id coreId); + +#define SEM_TYPE_ID_DEFAULT_VALUE ((t_nmf_semaphore_type_id)MASK_ALL32) +static t_nmf_semaphore_type_id semaphoreTypePerCoreId[NB_CORE_IDS]; + +static t_cm_error cm_LSEM_PowerOn(t_nmf_core_id coreId) +{ + return CM_OK; +} + +static void cm_LSEM_PowerOff(t_nmf_core_id coreId) +{ +} + +PUBLIC t_cm_error cm_SEM_Init(const t_cm_system_address *pSystemAddr) +{ + t_nmf_core_id coreId; + + for (coreId = ARM_CORE_ID; coreId < NB_CORE_IDS; coreId++) + { + semaphoreTypePerCoreId[coreId] = SEM_TYPE_ID_DEFAULT_VALUE; + + /* By default, we suppose that we use a full feature NMF ;) */ + cm_SEM_GenerateIrq[coreId] = NULL; + cm_SEM_PowerOn[coreId] = NULL; + cm_SEM_PowerOff[coreId] = NULL; + } + + cm_HSEM_Init(pSystemAddr); + /* if needed local semaphore init will be done coreId per coreId */ + + return CM_OK; +} + +PUBLIC t_cm_error cm_SEM_InitMpc(t_nmf_core_id coreId, t_nmf_semaphore_type_id semTypeId) +{ + if (semaphoreTypePerCoreId[coreId] != SEM_TYPE_ID_DEFAULT_VALUE) + return CM_MPC_ALREADY_INITIALIZED; + + if(semTypeId == SYSTEM_SEMAPHORES) + { + cm_SEM_GenerateIrq[coreId] = cm_HSEM_GenerateIrq; + cm_SEM_PowerOn[coreId] = cm_HSEM_PowerOn; + cm_SEM_PowerOff[coreId] = cm_HSEM_PowerOff; + } + else if (semTypeId == LOCAL_SEMAPHORES) + { + cm_SEM_GenerateIrq[coreId] = cm_DSP_SEM_GenerateIrq; + cm_SEM_PowerOn[coreId] = cm_LSEM_PowerOn; + cm_SEM_PowerOff[coreId] = cm_LSEM_PowerOff; + } + + semaphoreTypePerCoreId[coreId] = semTypeId; + + return CM_OK; +} + +PUBLIC t_semaphore_id cm_SEM_Alloc(t_nmf_core_id fromCoreId, t_nmf_core_id toCoreId) +{ + t_semaphore_id semId; + t_nmf_core_id corex; + + semId = FIRST_NEIGHBOR_SEMID(toCoreId); + for (corex = FIRST_CORE_ID; corex < fromCoreId; corex++) + { + if (corex == toCoreId) + continue; + semId++; + } + + if ( + (toCoreId == ARM_CORE_ID && semaphoreTypePerCoreId[fromCoreId] == SYSTEM_SEMAPHORES) || + (semaphoreTypePerCoreId[toCoreId] == SYSTEM_SEMAPHORES) + ) + { + cm_HSEM_EnableSemIrq(semId, toCoreId); + } + + return semId; +} diff --git a/drivers/staging/nmf-cm/cm/engine/trace/inc/trace.h b/drivers/staging/nmf-cm/cm/engine/trace/inc/trace.h new file mode 100644 index 00000000000..111eaf1324e --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/trace/inc/trace.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Trace facilities management API + * + * \defgroup Trace Facilities + */ +#ifndef __INC_CM_TRACE_H +#define __INC_CM_TRACE_H + +#include +#include + +/*********************/ +/* Log related stuff */ +/*********************/ +#define ERROR(format, param1, param2, param3, param4, param5, param6) \ +do { \ + if (cm_debug_level != -1) \ + OSAL_Log("Error: " format, (int)(param1), (int)(param2), (int)(param3), (int)(param4), (int)(param5), (int)(param6)); \ + while(cm_error_break);\ +} while(0) + +#define WARNING(format, param1, param2, param3, param4, param5, param6) \ +do { \ + if (cm_debug_level != -1) \ + OSAL_Log("Warning: " format, (int)(param1), (int)(param2), (int)(param3), (int)(param4), (int)(param5), (int)(param6)); \ +} while(0) + +#define LOG_INTERNAL(level, format, param1, param2, param3, param4, param5, param6) \ +do { \ + if (level <= cm_debug_level) \ + OSAL_Log((const char *)format, (int)(param1), (int)(param2), (int)(param3), (int)(param4), (int)(param5), (int)(param6)); \ +} while(0) + +/*************************/ +/* Panic related stuff */ +/*************************/ +#define CM_ASSERT(cond) \ +do { \ + if(!(cond)) { OSAL_Log("CM_ASSERT at %s:%d\n", (int)__FILE__, (int)__LINE__, 0, 0, 0, 0); OSAL_Panic(); while(1); } \ +} while (0) + +#endif /* __INC_CM_TRACE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h new file mode 100644 index 00000000000..6ab960b69b2 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#ifndef __INC_CM_XTITRACE_H +#define __INC_CM_XTITRACE_H + +#include + +#include + +extern t_bool cm_trace_enabled; + +/*************************/ +/* Trace related stuff */ +/*************************/ +void cm_TRC_Dump(void); + +void cm_TRC_traceReset(void); + +void cm_TRC_traceLoadMap( + t_nmfTraceComponentCommandDescription cmd, + const t_component_instance* component); + +#define ARM_TRACE_COMPONENT ((const t_component_instance*)0xFFFFFFFF) + +void cm_TRC_traceBinding( + t_nmfTraceBindCommandDescription command, + const t_component_instance* clientComponent, const t_component_instance* serverComponent, + const char *requiredItfName, const char *providedItfName); + +void cm_TRC_traceCommunication( + t_nmfTraceCommunicationCommandDescription command, + t_nmf_core_id coreId, + t_nmf_core_id remoteCoreId); + +void cm_TRC_traceMemAlloc(t_nmfTraceAllocatorCommandDescription command, t_uint8 allocId, t_uint32 memorySize, const char *allocname); + +void cm_TRC_traceMem(t_nmfTraceAllocCommandDescription command, t_uint8 allocId, t_uint32 startAddress, t_uint32 memorySize); + +#endif /* __INC_CM_TRACE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c new file mode 100644 index 00000000000..832b9f28756 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -0,0 +1,222 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include +#include +#include +#include +#include +#include + +#include +#include + + +/* + * Panic + */ +const struct { + char* name; + unsigned int info1:1; + unsigned int PC:1; + unsigned int SP:1; + unsigned int interface:1; +} reason_descrs[] = { + {"NONE_PANIC", 0, 0, 0, 0}, + {"INTERNAL_PANIC", 1, 0, 0, 0}, + {"Reserved Panic", 0, 0, 0, 0}, + {"USER_STACK_OVERFLOW", 0, 1, 1, 0}, + {"SYSTEM_STACK_OVERFLOW", 0, 1, 1, 0}, + {"UNALIGNED_LONG_ACCESS", 0, 1, 0, 0}, + {"EVENT_FIFO_OVERFLOW", 0, 0, 0, 1}, + {"PARAM_FIFO_OVERFLOW", 0, 0, 0, 1}, + {"INTERFACE_NOT_BINDED", 0, 0, 0, 0}, + {"USER_PANIC", 1, 0, 0, 0} +}; + +static t_component_instance* getCorrespondingInstance( + t_panic_reason panicReason, + t_uint32 panicThis, + t_dup_char *itfName, + t_cm_instance_handle *instHandle) { + t_component_instance *instance; + t_uint32 k; + + for (k=0; kthisAddress == panicThis && panicThis == 0) { + *itfName = "Internal NMF service"; + *instHandle = ENTRY2HANDLE(instance, k); + return instance; + } + + for(i = 0; i < instance->template->requireNumber; i++) { + int nb = instance->template->requires[i].collectionSize, j; + for(j = 0; j < nb; j++) { + if(instance->interfaceReferences[i][j].instance != NULL && + instance->interfaceReferences[i][j].instance != (t_component_instance *)NMF_HOST_COMPONENT && + instance->interfaceReferences[i][j].instance != (t_component_instance *)NMF_VOID_COMPONENT && + instance->interfaceReferences[i][j].instance->thisAddress == panicThis) + { + *itfName = instance->template->requires[i].name; + *instHandle = ENTRY2HANDLE(instance, k); + return instance; + } + } + } + } else { + // The component which has generated the panic is the good one. + + if(instance->thisAddress == panicThis) { + *itfName = "?"; + *instHandle = ENTRY2HANDLE(instance, k); + return instance; + } + } + } + + *itfName = "?"; + *instHandle = 0; + return 0; +} + +PUBLIC EXPORT_SHARED t_cm_error CM_ReadMPCString( + t_nmf_core_id coreId, + t_uint32 dspAddress, + char * buffer, + t_uint32 bufferSize) { + + while(--bufferSize > 0) + { + char ch = cm_DSP_ReadXRamWord(coreId, dspAddress++); + if(ch == 0) + break; + + *buffer++ = ch; + }; + + *buffer = 0; + + // Reset panicReason + cm_writeAttribute(cm_EEM_getExecutiveEngine(coreId)->instance, + "rtos/commonpart/serviceReason", MPC_SERVICE_NONE); + + return CM_OK; +} + +/****************/ +/* Generic part */ +/****************/ +PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( + t_nmf_core_id coreId, + t_cm_service_type *srcType, + t_cm_service_description *srcDescr) +{ + t_uint32 serviceReason; + t_component_instance *ee; + + // Acknowledge interrupt (do it before resetting panicReason) + cm_DSP_AcknowledgeDspIrq(coreId, DSP2ARM_IRQ_1); + + ee = cm_EEM_getExecutiveEngine(coreId)->instance; + + // Read panicReason + serviceReason = cm_readAttributeNoError(ee, "rtos/commonpart/serviceReason"); + if(serviceReason == MPC_SERVICE_PRINT) + { + *srcType = CM_MPC_SERVICE_PRINT; + + srcDescr->u.print.dspAddress = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo0"); + srcDescr->u.print.value1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); + srcDescr->u.print.value2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); + } + else if(serviceReason != MPC_SERVICE_NONE) + { + t_uint32 panicThis; + t_dup_char itfName; + t_component_instance *instance; + + *srcType = CM_MPC_SERVICE_PANIC; + srcDescr->u.panic.panicReason = (t_panic_reason)serviceReason; + srcDescr->u.panic.panicSource = MPC_EE; + srcDescr->u.panic.info.mpc.coreid = coreId; + + // Read panicThis + panicThis = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo0"); + + instance = getCorrespondingInstance(srcDescr->u.panic.panicReason, panicThis, &itfName, &srcDescr->u.panic.info.mpc.faultingComponent); + + LOG_INTERNAL(0, "Error: Panic(%s, %s), This=%x", cm_getDspName(coreId), + reason_descrs[srcDescr->u.panic.panicReason].name, (void*)panicThis, 0, 0, 0); + + if(reason_descrs[srcDescr->u.panic.panicReason].interface != 0) + { + LOG_INTERNAL(0, ", interface=%s", itfName, 0, 0, 0, 0, 0); + } + + if(reason_descrs[srcDescr->u.panic.panicReason].info1 != 0) + { + // Info 1 + srcDescr->u.panic.info.mpc.panicInfo1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); + + LOG_INTERNAL(0, ", Info=%x", srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0, 0); + } + + if(reason_descrs[srcDescr->u.panic.panicReason].PC != 0) + { + t_uint32 DspAddress = 0xFFFFFFFF; + t_uint32 DspSize = 0x0; + + // PC need to be read in rtos/commonpart/serviceInfo1 + srcDescr->u.panic.info.mpc.panicInfo1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); + + if(instance != 0) + { + cm_DSP_GetDspAddress(instance->memories[instance->template->codeMemory->id], &DspAddress); + cm_DSP_GetDspMemoryHandleSize(instance->memories[instance->template->codeMemory->id], &DspSize); + } + + if(DspAddress <= srcDescr->u.panic.info.mpc.panicInfo1 && + srcDescr->u.panic.info.mpc.panicInfo1 < (DspAddress + DspSize)) + LOG_INTERNAL(0, ", PC:off=%x ", + srcDescr->u.panic.info.mpc.panicInfo1 - DspAddress, + srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0); + else + LOG_INTERNAL(0, ", PC:", srcDescr->u.panic.info.mpc.panicInfo1, 0, 0, 0, 0, 0); + } + + if(reason_descrs[srcDescr->u.panic.panicReason].SP != 0) + { + srcDescr->u.panic.info.mpc.panicInfo2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); + + LOG_INTERNAL(0, ", SP=%x", srcDescr->u.panic.info.mpc.panicInfo2, 0, 0, 0, 0, 0); + } + + LOG_INTERNAL(0, "\n", 0, 0, 0, 0, 0, 0); + + if(instance != 0) + { + LOG_INTERNAL(0, "Error: Component=%s<%s>\n", + instance->pathname, instance->template->name, 0, 0, 0, 0); + } + + // We don't set rtos/commonpart/serviceReason = MPC_SERVICE_NONE, since we don't want the + // MMDSP to continue execution, and we put in in Panic state + cm_DSP_SetStatePanic(coreId); + } + else + { + *srcType = CM_MPC_SERVICE_NONE; + } + + return CM_OK; +} diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c b/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c new file mode 100644 index 00000000000..ac948c767b4 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include "../inc/trace.h" +#include "../inc/xtitrace.h" +#include +#include +#include +#include + +t_bool cm_trace_enabled = FALSE; + +/* + * STM message dump + */ +#define HEADER(t, s) ((t) | (s << 16)) + +static void writeN(struct t_nmfTraceChannelHeader* header) +{ + t_uint64* data = (t_uint64*)header; + t_uint64 *end = (t_uint64*)(((unsigned int)data) + header->traceSize - sizeof(t_uint64)); + + while(data < end) + { + OSAL_Write64(CM_CHANNEL, 0, *data++); + } + + OSAL_Write64(CM_CHANNEL, 1, *data); +} + +void cm_TRC_Dump(void) +{ + t_uint32 i; + + cm_TRC_traceReset(); + + for (i=0; itemplate->dspId + 1; + trace.componentContext = (t_uint32)component->thisAddress; + trace.componentUserContext = (t_uint32)component; + cm_StringCopy((char*)trace.componentLocalName, component->pathname, MAX_COMPONENT_NAME_LENGTH); + cm_StringCopy((char*)trace.componentTemplateName, component->template->name, MAX_TEMPLATE_NAME_LENGTH); + + writeN((struct t_nmfTraceChannelHeader*)&trace); + + if(command == TRACE_COMPONENT_COMMAND_ADD) + { + struct t_nmfTraceMethod tracemethod; + int i, j, k; + + /* + * Generate method trace + */ + tracemethod.header.v = HEADER(TRACE_TYPE_METHOD, sizeof(tracemethod)); + + tracemethod.domainId = (t_uint16)component->template->dspId + 1; + tracemethod.componentContext = (t_uint32)component->thisAddress; + + for(i = 0; i < component->template->provideNumber; i++) + { + t_interface_provide* provide = &component->template->provides[i]; + + for(j = 0; j < provide->collectionSize; j++) + { + for(k = 0; k < provide->interface->methodNumber; k++) + { + tracemethod.methodId = provide->indexes[j][k].methodAddresses; + + cm_StringCopy((char*)tracemethod.methodName, provide->interface->methodNames[k], MAX_INTERFACE_METHOD_NAME_LENGTH); + + writeN((struct t_nmfTraceChannelHeader*)&tracemethod); + } + } + } + } + } +} + +void cm_TRC_traceBinding( + t_nmfTraceBindCommandDescription command, + const t_component_instance* clientComponent, const t_component_instance* serverComponent, + const char *requiredItfName, const char *providedItfName) +{ + if(cm_trace_enabled) + { + struct t_nmfTraceBind trace; + + trace.header.v = HEADER(TRACE_TYPE_BIND, sizeof(trace)); + + trace.command = (t_uint16)command; + + if(clientComponent == ARM_TRACE_COMPONENT) // ARM + { + trace.clientDomainId = 0x1; + trace.clientComponentContext = 0x0; + } + else + { + trace.clientDomainId = (t_uint16)clientComponent->template->dspId + 1; + trace.clientComponentContext = (t_uint32)clientComponent->thisAddress; + } + if(requiredItfName != NULL) + cm_StringCopy((char*)trace.requiredItfName, requiredItfName, MAX_INTERFACE_NAME_LENGTH); + else + trace.requiredItfName[0] = 0; + + if(serverComponent == NULL) + { // Unbind or VOID + trace.serverDomainId = 0; + trace.serverComponentContext = 0x0; + } + else if(serverComponent == ARM_TRACE_COMPONENT) + { // ARM + trace.serverDomainId = 0x1; + trace.serverComponentContext = 0x0; + } + else + { + trace.serverDomainId = (t_uint16)serverComponent->template->dspId + 1; + trace.serverComponentContext = (t_uint32)serverComponent->thisAddress; + } + if(providedItfName != NULL) + cm_StringCopy((char*)trace.providedItfName, providedItfName, MAX_INTERFACE_NAME_LENGTH); + else + trace.providedItfName[0] = 0; + + writeN((struct t_nmfTraceChannelHeader*)&trace); + } +} + +void cm_TRC_traceCommunication( + t_nmfTraceCommunicationCommandDescription command, + t_nmf_core_id coreId, + t_nmf_core_id remoteCoreId) +{ + if(cm_trace_enabled) + { + struct t_nmfTraceCommunication trace; + + trace.header.v = HEADER(TRACE_TYPE_COMMUNICATION, sizeof(trace)); + + trace.command = (t_uint16)command; + trace.domainId = (t_uint16)coreId + 1; + trace.remoteDomainId = (t_uint16)remoteCoreId + 1; + + writeN((struct t_nmfTraceChannelHeader*)&trace); + } +} + +void cm_TRC_traceMemAlloc(t_nmfTraceAllocatorCommandDescription command, t_uint8 allocId, t_uint32 memorySize, const char *allocname) +{ + if(cm_trace_enabled) + { + struct t_nmfTraceAllocator trace; + + trace.header.v = HEADER(TRACE_TYPE_ALLOCATOR, sizeof(trace)); + + trace.command = (t_uint16)command; + trace.allocId = (t_uint16)allocId; + trace.size = memorySize; + cm_StringCopy((char*)trace.name, allocname, sizeof(trace.name)); + + writeN((struct t_nmfTraceChannelHeader*)&trace); + } +} + +void cm_TRC_traceMem(t_nmfTraceAllocCommandDescription command, t_uint8 allocId, t_uint32 startAddress, t_uint32 memorySize) +{ + if(cm_trace_enabled) + { + struct t_nmfTraceAlloc trace; + + trace.header.v = HEADER(TRACE_TYPE_ALLOC, sizeof(trace)); + + trace.command = (t_uint16)command; + trace.allocId = (t_uint16)allocId; + trace.offset = startAddress; + trace.size = memorySize; + + writeN((struct t_nmfTraceChannelHeader*)&trace); + } +} + diff --git a/drivers/staging/nmf-cm/cm/engine/utils/inc/convert.h b/drivers/staging/nmf-cm/cm/engine/utils/inc/convert.h new file mode 100644 index 00000000000..d6912e58687 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/utils/inc/convert.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Conversion utility methods. + */ +#ifndef H_CM_CONVERTS_MEM +#define H_CM_CONVERTS_MEM + +#include + +/* + * Utils convert methods + */ +const char* cm_getDspName(t_nmf_core_id dsp); + + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/utils/inc/mem.h b/drivers/staging/nmf-cm/cm/engine/utils/inc/mem.h new file mode 100644 index 00000000000..c950a94023d --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/utils/inc/mem.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Memory manipulation. + */ +#ifndef H_CM_UTILS_MEM +#define H_CM_UTILS_MEM + +/* + * Utils libc methods + */ +void cm_MemCopy(void* dest, const void *src, int count); +void cm_MemSet(void *str, int c, int count); + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/utils/inc/string.h b/drivers/staging/nmf-cm/cm/engine/utils/inc/string.h new file mode 100644 index 00000000000..d2b7c0b0823 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/utils/inc/string.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief String manipulation. + */ +#ifndef H_CM_UTILS_STRING +#define H_CM_UTILS_STRING + +#include + +#define MAX_INTERNAL_STRING_LENGTH 2048 + +typedef const char *t_dup_char; + +t_dup_char cm_StringGet(const char* str); +t_dup_char cm_StringReference(t_dup_char str); +t_dup_char cm_StringDuplicate(const char* orig); +void cm_StringRelease(t_dup_char orig); + +/* + * Utils libc methods + */ +void cm_StringCopy(char* dest, const char* src, int count); +int cm_StringCompare(const char* str1, const char* str2, int count); +int cm_StringLength(const char * str, int count); +void cm_StringConcatenate(char* dest, const char* src, int count); +char* cm_StringSearch(const char* str, int c); + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/utils/inc/swap.h b/drivers/staging/nmf-cm/cm/engine/utils/inc/swap.h new file mode 100644 index 00000000000..e4f5acb3010 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/utils/inc/swap.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Swap integer manipulation. + */ +#ifndef H_CM_UTILS_SWAP +#define H_CM_UTILS_SWAP + +#include + +/* + * Swap methods + */ +t_uint16 swap16(t_uint16 x); +t_uint32 swap32(t_uint32 x); +t_uint64 swap64(t_uint64 x); +t_uint32 noswap32(t_uint32 x); + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/utils/inc/table.h b/drivers/staging/nmf-cm/cm/engine/utils/inc/table.h new file mode 100644 index 00000000000..9d9828a81f6 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/utils/inc/table.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/*! + * \internal + * \brief Dynamic table manipulation. + */ +#ifndef H_CM_UTILS_TABLE +#define H_CM_UTILS_TABLE + +#include + +/* + This implement a (generic) dynamic table (the size is dynamic) + to register some pointers of a given kind of elements + + It also allows to compute/convert each kernel pointer registered in the + table to a user handler, that can be checked. + + The "user" handler is composed by the index in this table + (the low INDEX_SHIFT bits) and the low bits of the "local" pointer + shifted by INDEX_SHIFT are stored in the high bits: + + handle bits: 31 ................................ 12 11 ...... 0 + | lower bits of of the local pointer | index | + + This allows a straight translation from a user handle to a local pointer + + a strong check to validate the value of a user handle. + The reverse translation from pointer to a user handle is + slower as it requires an explicit search in the list. + */ + + +/* INDEX_SHIFT determines the index size and thus the max index */ +#define INDEX_SHIFT 12 +#define INDEX_MAX (1UL << INDEX_SHIFT) +#define INDEX_MASK (INDEX_MAX-1) +#define ENTRY2HANDLE(pointer, index) (((unsigned int)pointer << INDEX_SHIFT) | index) +#define TABLE_DEF_SIZE 0x1000 + +typedef struct { + t_uint32 idxNb; /**< number of entries used */ + t_uint32 idxCur; /**< current index: point to next supposed + free entry: used to look for the next + free entry */ + t_uint32 idxMax; /**< index max currently allowed */ + void **entries; /**< table itself */ +} t_nmf_table; + +t_cm_error cm_initTable(t_nmf_table* table); +void cm_destroyTable(t_nmf_table* table); +t_uint32 cm_addEntry(t_nmf_table *table, void *entry); +void cm_delEntry(t_nmf_table *table, t_uint32 idx); +void *cm_lookupEntry(const t_nmf_table *table, const t_uint32 hdl); +t_uint32 cm_lookupHandle(const t_nmf_table *table, const void *entry); + +#endif diff --git a/drivers/staging/nmf-cm/cm/engine/utils/src/convert.c b/drivers/staging/nmf-cm/cm/engine/utils/src/convert.c new file mode 100644 index 00000000000..ad6e097bfe6 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/utils/src/convert.c @@ -0,0 +1,20 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include + +const char* dspNames[NB_CORE_IDS] = { + "ARM", + "SVA", + "SIA" +}; + + +const char* cm_getDspName(t_nmf_core_id dsp) { + return dspNames[dsp]; +} diff --git a/drivers/staging/nmf-cm/cm/engine/utils/src/mem.c b/drivers/staging/nmf-cm/cm/engine/utils/src/mem.c new file mode 100644 index 00000000000..130a044bbf8 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/utils/src/mem.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include + + +/* + * Methods + */ +void cm_MemCopy(void* dest, const void *src, int count) { + char *tmp = (char *) dest, *s = (char *) src; + + while (count--) + *tmp++ = *s++; +} + +void cm_MemSet(void *str, int c, int count) { + char *tmp = (char *)str; + + while (count--) + *tmp++ = c; +} diff --git a/drivers/staging/nmf-cm/cm/engine/utils/src/string.c b/drivers/staging/nmf-cm/cm/engine/utils/src/string.c new file mode 100644 index 00000000000..0ed6fb3a214 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/utils/src/string.c @@ -0,0 +1,229 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + * Shared string manipulation. + * TODO This is a list today, must be a hash later !!!!! + */ +#include +#include + +#include +#include + +#define NHASH 257 //Use a prime number! +#define MULT 17 + +/* + * Data + */ +struct t_linkedstring +{ + struct t_linkedstring *next; + int referencer; + char string[1]; +}; + +static struct t_linkedstring *list[NHASH]; + +#define myoffsetof(st, m) \ + ((int) ( (char *)&((st *)(0))->m - (char *)0 )) + +unsigned int hash(const char *str) +{ + unsigned int h = 0; + for(; *str; str++) + h = MULT * h + *str; + return h % NHASH; +} +/* + * Methods + */ +PRIVATE struct t_linkedstring *lookupString( + const char* str, + struct t_linkedstring *first) +{ + while(first != 0) + { + if(cm_StringCompare(str, first->string, MAX_INTERNAL_STRING_LENGTH) == 0) + break; + first = first->next; + } + + return first; +} + +t_dup_char cm_StringGet(const char* str) +{ + struct t_linkedstring *entry; + + entry = lookupString(str, list[hash(str)]); + CM_ASSERT(entry != 0); + + return (t_dup_char)entry->string; +} + +t_dup_char cm_StringReference(t_dup_char str) +{ + struct t_linkedstring* entry = (struct t_linkedstring*)((t_uint32)str - myoffsetof(struct t_linkedstring, string)); + + // One more referencer + entry->referencer++; + + return (t_dup_char)entry->string; +} + +t_dup_char cm_StringDuplicate(const char* str) +{ + struct t_linkedstring *entry; + unsigned int h; + + h = hash(str); + entry = lookupString(str, list[h]); + if(entry != 0) + { + // One more referencer + entry->referencer++; + } + else + { + // Allocate new entry + entry = (struct t_linkedstring *)OSAL_Alloc(sizeof(struct t_linkedstring)-1 + cm_StringLength(str, MAX_INTERNAL_STRING_LENGTH)+1); + if(entry == NULL) + return NULL; + + entry->referencer = 1; + cm_StringCopy(entry->string, str, MAX_INTERNAL_STRING_LENGTH); + + // Link it in list + entry->next = list[h]; + list[h] = entry; + } + + return (t_dup_char)entry->string; +} + +void cm_StringRelease(t_dup_char str) +{ + if(str != NULL) + { + struct t_linkedstring* entry = (struct t_linkedstring*)((t_uint32)str - myoffsetof(struct t_linkedstring, string)); + + // One less referencer + entry->referencer--; + + if(entry->referencer == 0) + { + int h = hash(entry->string); + + if(list[h] == entry) // This first first one + { + list[h] = entry->next; + } + else + { + struct t_linkedstring *tmp = list[h]; + + // Here we assume that entry is in the list + while(/*tmp != NULL && */tmp->next != entry) + tmp = tmp->next; + + tmp->next = entry->next; + } + OSAL_Free(entry); + } + } +} + +#if 0 +void checkString() +{ + struct t_linkedstring *tmp = list; + + while(tmp != 0) + { + printf(" stay %s %d\n", tmp->string, tmp->referencer); + tmp = tmp->next; + } +} +#endif + +/* + * LibC method + */ +void cm_StringCopy(char* dest, const char *src, int count) +{ + while (count-- && (*dest++ = *src++) != '\0') + /* nothing */ + ; +} +#define DETECTNULL(X) (((X) - 0x01010101) & ~(X) & 0x80808080) + +int cm_StringCompare(const char* str1, const char* str2, int count) +{ + /* If s1 and s2 are word-aligned, compare them a word at a time. */ + if ((((int)str1 & 3) | ((int)str2 & 3)) == 0) + { + unsigned int *a1 = (unsigned int*)str1; + unsigned int *a2 = (unsigned int*)str2; + + while (count >= sizeof (unsigned int) && *a1 == *a2) + { + count -= sizeof (unsigned int); + + /* If we've run out of bytes or hit a null, return zero since we already know *a1 == *a2. */ + if (count == 0 || DETECTNULL (*a1)) + return 0; + + a1++; + a2++; + } + + /* A difference was detected in last few bytes of s1, so search bytewise */ + str1 = (char*)a1; + str2 = (char*)a2; + } + + while (count-- > 0 && *str1 == *str2) + { + /* If we've run out of bytes or hit a null, return zero + since we already know *s1 == *s2. */ + if (count == 0 || *str1 == '\0') + return 0; + str1++; + str2++; + } + + return (*(unsigned char *) str1) - (*(unsigned char *) str2); +} + +int cm_StringLength(const char * str, int count) +{ + const char *sc; + + for (sc = str; count-- && *sc != '\0'; ++sc) + /* nothing */ + ; + return sc - str; +} + +void cm_StringConcatenate(char* dest, const char* src, int count) +{ + while ((*dest) != '\0') + { + dest++; + count--; + } + cm_StringCopy(dest, src, count); +} + +char* cm_StringSearch(const char* str, int c) +{ + for(; *str != (char) c; ++str) + if (*str == '\0') + return 0; + return (char *) str; +} diff --git a/drivers/staging/nmf-cm/cm/engine/utils/src/swap.c b/drivers/staging/nmf-cm/cm/engine/utils/src/swap.c new file mode 100644 index 00000000000..e3e2d536144 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/utils/src/swap.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include + + +/* + * Methods + */ +t_uint16 swap16(t_uint16 x) +{ + return ((x >> 8) | + ((x << 8) & 0xff00U)); +} + +#ifdef LINUX + +#if defined(__STN_8815) /* __STN_8815 -> ARMv5*/ +t_uint32 swap32(t_uint32 x) +{ + asm volatile ( + "EOR r1, r0, r0, ROR #16 \n\t" + "BIC r1, r1, #0xFF0000 \n\t" + "MOV r0, r0, ROR #8 \n\t" + "EOR r0, r0, r1, LSR #8" + : : : "r3" ); + + return x; +} + +t_uint64 swap64(t_uint64 x) +{ + asm volatile ( + "MOV r2, r1 \n\t" + " \n\t" + "EOR r3, r0, r0, ROR #16 \n\t" + "BIC r3, r3, #0xFF0000 \n\t" + "MOV r0, r0, ROR #8 \n\t" + "EOR r1, r0, r3, LSR #8 \n\t" + " \n\t" + "EOR r3, r2, r2, ROR #16 \n\t" + "BIC r3, r3, #0xFF0000 \n\t" + "MOV r2, r2, ROR #8 \n\t" + "EOR r0, r2, r3, LSR #8" + : : : "r3", "r2" ); + + return x; +} +#else /* -> ARMv6 or later */ + +t_uint32 swap32(t_uint32 x) +{ + asm volatile ( + "REV %0, %0" + : "+r"(x) : ); + + return x; +} + +t_uint64 swap64(t_uint64 x) +{ + asm volatile ( + "REV r2, %Q0 \n\t" + "REV %Q0, %R0 \n\t" + "MOV %R0, r2" + : "+&r" (x) : : "r2" ); + + return x; +} + +#endif + +#else /* Symbian, Think -> We assume ARMCC */ + +#if defined(__thumb__) + +t_uint32 swap32(t_uint32 x) +{ + return ((x >> 24) | + ((x >> 8) & 0xff00U) | + ((x << 8) & 0xff0000U) | + ((x << 24) & 0xff000000U)); +} + +t_uint64 swap64(t_uint64 x) +{ + return ((x >> 56) | + ((x >> 40) & 0xff00UL) | + ((x >> 24) & 0xff0000UL) | + ((x >> 8) & 0xff000000UL) | + ((x << 8) & 0xff00000000ULL) | + ((x << 24) & 0xff0000000000ULL) | + ((x << 40) & 0xff000000000000ULL) | + ((x << 56))); +} + +#elif (__TARGET_ARCH_ARM < 6) + +__asm t_uint32 swap32(t_uint32 x) +{ + EOR r1, r0, r0, ROR #16 + BIC r1, r1, #0xFF0000 + MOV r0, r0, ROR #8 + EOR r0, r0, r1, LSR #8 + + BX lr +} + +__asm t_uint64 swap64(t_uint64 x) +{ + MOV r2, r1 + + EOR r3, r0, r0, ROR #16 // Swap low (r0) and store it in high (r1) + BIC r3, r3, #0xFF0000 + MOV r0, r0, ROR #8 + EOR r1, r0, r3, LSR #8 + + EOR r3, r2, r2, ROR #16 // Swap high (r2 = ex r1) and store it in low (r0) + BIC r3, r3, #0xFF0000 + MOV r2, r2, ROR #8 + EOR r0, r2, r3, LSR #8 + + BX lr +} + +#else /* -> ARMv6 or later */ + +__asm t_uint32 swap32(t_uint32 x) +{ + REV r0, r0 + + BX lr +} + +__asm t_uint64 swap64(t_uint64 x) +{ + REV r2, r0 + REV r0, r1 + MOV r1, r2 + + BX lr +} + +#endif + +#endif + +t_uint32 noswap32(t_uint32 x) { + return x; +} + diff --git a/drivers/staging/nmf-cm/cm/engine/utils/src/table.c b/drivers/staging/nmf-cm/cm/engine/utils/src/table.c new file mode 100644 index 00000000000..708396a01b2 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/utils/src/table.c @@ -0,0 +1,155 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +/* + * + */ +#include +#include +#include +#include + +/* + * Methods + */ +t_cm_error cm_initTable(t_nmf_table* table) +{ + table->idxMax = TABLE_DEF_SIZE / sizeof(table->entries); + + table->entries = OSAL_Alloc_Zero(table->idxMax*sizeof(table->entries)); + + if (table->entries == NULL) { + table->idxMax = 0; + return CM_NO_MORE_MEMORY; + } + + return CM_OK; +} + +void cm_destroyTable(t_nmf_table* table) +{ + if (table->idxNb) { + ERROR("Attempt to free non-empty table !!!\n", 0, 0, 0, 0, 0, 0); + return; + } + OSAL_Free(table->entries); + table->idxMax = 0; +} + +static t_cm_error cm_increaseTable(t_nmf_table* table) +{ + t_uint32 new_max; + void *mem; + + if (table->idxMax == INDEX_MASK) { + ERROR("CM_NO_MORE_MEMORY: Maximum table entries reached\n", 0, 0, 0, 0, 0, 0); + return CM_NO_MORE_MEMORY; + } + + new_max = table->idxMax + + TABLE_DEF_SIZE / sizeof(table->entries); + + if (new_max > INDEX_MAX) + new_max = INDEX_MAX; + + mem = OSAL_Alloc(new_max * sizeof(table->entries)); + + if (mem == NULL) { + ERROR("CM_NO_MORE_MEMORY: Unable to allocate memory for a table\n", 0, 0, 0, 0, 0, 0); + return CM_NO_MORE_MEMORY; + } + + cm_MemCopy(mem, table->entries, + table->idxMax*sizeof(table->entries)); + cm_MemSet((void *)((t_uint32) mem + table->idxMax*sizeof(*table->entries)), 0, + (new_max-table->idxMax) * sizeof(*table->entries)); + + OSAL_Free(table->entries); + table->entries = mem; + table->idxMax = new_max; + + return CM_OK; +} + +/** cm_addEntry - Add an local pointer to an element to the list + * + * 1. Increase the size of the list if it's full + * 2. Search an empty entry + * 3. Add the element to the list + * 4. Compute and return the "user handle" + */ +t_uint32 cm_addEntry(t_nmf_table *table, void *entry) +{ + unsigned int i; + t_uint32 hdl = 0; + + if (table->idxNb == table->idxMax) + cm_increaseTable(table); + + for (i = table->idxCur; + table->entries[i] != 0 && i != (table->idxCur-1); + i = (i+1)%table->idxMax); + + if (table->entries[i] == 0) { + table->entries[i] = entry; + table->idxCur = (i+1) % table->idxMax; + table->idxNb++; + hdl = ENTRY2HANDLE(entry, i); + } else + ERROR("No free entry found in table\n", 0, 0, 0, 0, 0, 0); + + return hdl; +} + +/** cm_delEntry - remove the given element from the list + * + * 1. Check if the handle is valid + * 2. Search the entry and free it + */ +void cm_delEntry(t_nmf_table *table, t_uint32 idx) +{ + table->entries[idx] = NULL; + table->idxNb--; +} + +/** cm_lookupEntry - search the entry corresponding to + * the user handle. + * + * 1. Check if the handle is valid + * 2. Return a pointer to the element + */ +void *cm_lookupEntry(const t_nmf_table *table, const t_uint32 hdl) +{ + unsigned int idx = hdl & INDEX_MASK; + + if ((idx >= table->idxMax) + || (((unsigned int)table->entries[idx] << INDEX_SHIFT) != (hdl & ~INDEX_MASK))) + return NULL; + else + return table->entries[idx]; +} + +/** cm_lookupHandle - search the handle corresponding + * to the given element + * + * 1. Check if the handler is valid or is a special handler + * 2. Loop in the table to retrieve the entry matching and return its value + */ +t_uint32 cm_lookupHandle(const t_nmf_table *table, const void *entry) +{ + t_uint32 i; + + /* NULL is an invalid value that must be handle separatly + as it'll match all used/free entries value */ + if (entry == NULL) + return 0; + + for (i=0; i < table->idxMax; i++) { + if (table->entries[i] == entry) + return ENTRY2HANDLE(table->entries[i], i); + } + + return 0; +} diff --git a/drivers/staging/nmf-cm/cm/inc/cm.h b/drivers/staging/nmf-cm/cm/inc/cm.h new file mode 100644 index 00000000000..37ccb36a5ee --- /dev/null +++ b/drivers/staging/nmf-cm/cm/inc/cm.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef __INC_CM_H +#define __INC_CM_H + +#include + +/********************************************************************************/ +/* Component Manager API prototypes */ +/********************************************************************************/ + +/* + * User level wrapper + */ +#include + +#endif /* __INC_CM_H */ diff --git a/drivers/staging/nmf-cm/cm/inc/cm_def.h b/drivers/staging/nmf-cm/cm/inc/cm_def.h new file mode 100644 index 00000000000..dc7a1fdad66 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/inc/cm_def.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +/*! + * \brief Component Manager API. + * + * This file contains the Component Manager API for manipulating components. + * + */ + +#ifndef __INC_CM_DEF_H +#define __INC_CM_DEF_H + +#include +#include + +/*! + * \brief Get the version of the NMF CM engine at runtime + * + * This method should be used to query the version number of the + * NMF Component Manager engine at runtime. This is useful when using + * to check if version of the engine linked with application correspond + * to engine used for development. + * + * Such code can be used to check compatibility: \code + t_uint32 nmfversion; + + // Print NMF version + CM_GetVersion(&nmfversion); + LOG("NMF Version %d-%d-%d\n", + VERSION_MAJOR(nmfversion), + VERSION_MINOR(nmfversion), + VERSION_PATCH(nmfversion)); + if(NMF_VERSION != nmfversion) { + LOG("Error: Incompatible API version %d != %d\n", NMF_VERSION, nmfversion); + EXIT(); + } + * \endcode + * + * \param[out] version Internal hardcoded version (use \ref VERSION_MAJOR, \ref VERSION_MINOR, \ref VERSION_PATCH macros to decode it). + * + * \ingroup CM + */ +PUBLIC IMPORT_SHARED void CM_GetVersion(t_uint32 *version); + +#endif /* __INC_CM_H */ diff --git a/drivers/staging/nmf-cm/cm/inc/cm_macros.h b/drivers/staging/nmf-cm/cm/inc/cm_macros.h new file mode 100644 index 00000000000..2279c204a20 --- /dev/null +++ b/drivers/staging/nmf-cm/cm/inc/cm_macros.h @@ -0,0 +1,148 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +/*! + * \brief Component Manager Macros. + * + * \defgroup CM_MACROS NMF Macros (ANSI C99) + * The Component Manager Macros are provided to ease FromHost interface call and ToHost callback definition. + * \attention These macros are only ANSI C99 compliant (ARM RVCT 2.x/3.x, GNU gcc 4.x, ...) + * \ingroup CM_USER_API + */ + +#ifndef __INC_CM_MACROS_H +#define __INC_CM_MACROS_H + +/* + * The next macros are supported only with C Ansi 99, so.... + */ + +/* + * The Symbian environment dependency, computation which uses an old gnu cpp, + * does not accept "..." parameters. + * However the actual compiler (armcc) does. + * So remove the macro definitions when computing dependencies. + */ +#if ( defined(__CC_ARM) && !defined(__STRICT_ANSI__) ) || !defined(__SYMBIAN32__) + +/* + * Only for skilled eyes ;) + * The following macros are used to implement NMFCALL[VOID] and NMFMETH[VOID] macros in an elegant way + */ +#define WITH_PARAM(...) __VA_ARGS__) +#define WITH_NOPARAM(...) ) + +/*! + * \brief Macro to ease Host to Dsp interface calling + * + * \attention This macro is only ANSI C99 compliant + * + * The NMFCALL macro can be used to call one method of any previously FromHost bounded interface.\n + * From Host side, today, we have no way to mask the multi-instance handling, so + * this macro is provided to ease FromHost interface calling and to avoid any mistake into the THIS parameter passing. + * + * So, any fromHost interface method call like: \code + * itf.method(itf.THIS, param1, param2, ...); + * \endcode + * can be replaced by: \code + * NMFCALL(itf, method)(param1, param2, ...); + * \endcode + * + * \warning Don't forget to use NMFCALLVOID macro when declaring a FromHost interface method having none application parameter, + * else it will lead to erroneous C code expansion + * \see NMFCALLVOID + * \hideinitializer + * \ingroup CM_MACROS + */ +#define NMFCALL(itfHandle, itfMethodName) \ + (itfHandle).itfMethodName((itfHandle).THIS, WITH_PARAM + +/*! + * \brief Macro to ease Host to Dsp interface calling (method without any user parameter) + * + * \attention This macro is only ANSI C99 compliant + * + * The NMFCALLVOID macro can be used to call one method (those without any user parameter) of any previously FromHost bounded interface.\n + * From Host side, today, we have no way to mask the multi-instance handling, so + * this macro is provided to ease FromHost interface calling and to avoid any mistake into the THIS parameter passing. + * + * So, any FromHost interface method call without any application parameter like:\code + * itf.method(itf.THIS); + * \endcode + * can be replaced by: \code + * NMFCALLVOID(itf, method)(); + * \endcode + * \see NMFCALL + * \hideinitializer + * \ingroup CM_MACROS + */ +#define NMFCALLVOID(itfHandle, itfMethodName) \ + (itfHandle).itfMethodName((itfHandle).THIS WITH_NOPARAM + +/*! + * \brief Macro to ease Dsp to Host interface method declaration + * + * \attention This macro definition is only ANSI C99 compliant + * + * The NMFMETH macro can be used to ease the ToHost interface method declaration.\n + * From Host side, today, we have no way to mask the multi-intance handling, so the user shall handle it by hand + * by passing the "component" context as first parameter of each ToHost interface method through the void *THIS parameter. + * This macro could avoid any mistake into the THIS parameter declaration when never used by the user code. + * + * So, any ToHost interface method declaration like:\code + * void mynotify(void *THIS, mytype1 myparam1, mytype2 myparam2, ...) { + * + * } + * \endcode + * can be replaced by: \code + * void NMFMETH(mynotify)(mytype1 myparam1, mytype2 myparam2, ...) { + * + * } + * \endcode + * + * \warning Don't forget to use NMFMETHVOID macro when declaring a ToHost interface method having none application parameter, + * else it will lead to erroneous C code expansion + * + * \see NMFMETHVOID + * \hideinitializer + * \ingroup CM_MACROS + */ +#define NMFMETH(itfMethodName) \ + itfMethodName(void *THIS, WITH_PARAM + +/*! + * \brief Macro to ease Dsp to Host interface method declaration (method without any user parameter) + * + * \attention This macro is only ANSI C99 compliant + * + * The NMFMETHVOID macro can be used to ease the ToHost interface method (those without any user parameter) declaration.\n + * From Host side, today, we have no way to mask the multi-intance handling, so the user shall handle it by hand + * by passing the "component" context as first parameter of each ToHost interface method through the void *THIS parameter. + * This macro could avoid any mistake into the THIS parameter declaration when never used by the user code. + * + * So, any ToHost interface method declaration having none application parameter like:\code + * void mynotify(void *THIS) { + * + * } + * \endcode + * can be replaced by: \code + * void NMFMETHVOID(mynotify)(void) { + * + * } + * \endcode + * + * \see NMFMETH + * \hideinitializer + * \ingroup CM_MACROS + */ +#define NMFMETHVOID(itfMethodName) \ + itfMethodName(void *THIS WITH_NOPARAM + +#endif /* not Symbian environment or compiling with ARMCC and not in strict ANSI */ + +#endif /* __INC_CM_MACROS_H */ + diff --git a/drivers/staging/nmf-cm/cm/inc/cm_type.h b/drivers/staging/nmf-cm/cm/inc/cm_type.h new file mode 100644 index 00000000000..b2f97090a3a --- /dev/null +++ b/drivers/staging/nmf-cm/cm/inc/cm_type.h @@ -0,0 +1,147 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Component Manager types. + * + * This file contains the Component Manager types. + * + * \defgroup CM CM Type Definitions + * \ingroup CM_USER_API + */ +#ifndef _CM_TYPE_H_ +#define _CM_TYPE_H_ + +#include +#include + +#include + +/*! + * @defgroup t_cm_error t_cm_error + * \brief Description of the various errors returned by CM API routines + * @{ + * \ingroup CM + */ +typedef t_nmf_error t_cm_error; //!< Error type returned by CM API routines + +/*********************************************************************************/ +/* WARNING: UPDATE CM_StringError() func each time an error is added/removed !!! */ +/* CM_StringError() is defined twice in: */ +/* nmf_core/host/cm/proxy/common/wrapper/src/wrapper.c */ +/* tests/src/common/nte/src/nte.c */ +/*********************************************************************************/ +#define CM_LAST_ERROR_ID ((t_cm_error)-128) +#define CM_INTEGRATION_ERROR NMF_INTEGRATION_ERROR0 //!< \ref NMF_INTEGRATION_ERROR0 + + /* Communication */ +#define CM_FLUSH_MESSAGE NMF_FLUSH_MESSAGE //!< Message send after call to CM_FlushChannel() +#define CM_BUFFER_OVERFLOW ((t_cm_error)-105) //!< Buffer overflow (interface binding message bigger than buffer) +#define CM_USER_NOT_REGISTERED ((t_cm_error)-104) //!< User not registered +#define CM_NO_MESSAGE NMF_NO_MESSAGE //!< \ref NMF_NO_MESSAGE +#define CM_PARAM_FIFO_OVERFLOW ((t_cm_error)-102) //!< Param fifo overflow +#define CM_INTERNAL_FIFO_OVERFLOW ((t_cm_error)-101) //!< Internal services fifo overflow (not returned to user) +#define CM_MPC_NOT_RESPONDING ((t_cm_error)-100) //!< MPC not responding (either crash, interrupt handler too long, internal NMF fifo coms overflow, ...). + + /* ELF & File system */ +#define CM_FS_ERROR ((t_cm_error)-96) //!< FileSystem error +#define CM_NO_SUCH_FILE ((t_cm_error)-95) //!< No such file or directory +#define CM_INVALID_ELF_FILE ((t_cm_error)-94) //!< File isn't a valid MMDSP ELF file +#define CM_NO_SUCH_BASE ((t_cm_error)-93) //!< The memory base doesn't exist + + /* Introspection */ +#define CM_NO_SUCH_ATTRIBUTE NMF_NO_SUCH_ATTRIBUTE //!< \ref NMF_NO_SUCH_ATTRIBUTE +#define CM_NO_SUCH_PROPERTY NMF_NO_SUCH_PROPERTY //!< \ref NMF_NO_SUCH_PROPERTY + + /* Component Life Cycle */ +#define CM_COMPONENT_NOT_STOPPED NMF_COMPONENT_NOT_STOPPED //!< \ref NMF_COMPONENT_NOT_STOPPED +#define CM_COMPONENT_NOT_UNBINDED ((t_cm_error)-79) //!< Component must be fully unbinded before perform operation +#define CM_COMPONENT_NOT_STARTED ((t_cm_error)-78) //!< Component must be started to perform operation +#define CM_COMPONENT_WAIT_RUNNABLE ((t_cm_error)-76) //!< Component need acknowlegdment of life cycle start function before perform operation +#define CM_REQUIRE_INTERFACE_UNBINDED ((t_cm_error)-75) //!< Required component interfaces must be binded before perform operation +#define CM_INVALID_COMPONENT_HANDLE ((t_cm_error)-74) //!< Try to access a component already destroyed + + /* Binder */ +#define CM_NO_SUCH_PROVIDED_INTERFACE NMF_NO_SUCH_PROVIDED_INTERFACE //!< \ref NMF_NO_SUCH_PROVIDED_INTERFACE +#define CM_NO_SUCH_REQUIRED_INTERFACE NMF_NO_SUCH_REQUIRED_INTERFACE //!< \ref NMF_NO_SUCH_REQUIRED_INTERFACE +#define CM_ILLEGAL_BINDING ((t_cm_error)-62) //!< Client and server interface type mismatch +#define CM_ILLEGAL_UNBINDING ((t_cm_error)-61) //!< Try to unbind component with bad binding Factories +#define CM_INTERFACE_ALREADY_BINDED NMF_INTERFACE_ALREADY_BINDED//!< \ref NMF_INTERFACE_ALREADY_BINDED +#define CM_INTERFACE_NOT_BINDED NMF_INTERFACE_NOT_BINDED //!< \ref NMF_INTERFACE_NOT_BINDED + + /* Loader */ +#define CM_BINDING_COMPONENT_NOT_FOUND ((t_cm_error)-48) //!< Binding Component template name don't exist on components repository (should be generated thanks nkitf tool) +#define CM_COMPONENT_NOT_FOUND ((t_cm_error)-47) //!< Component template name doesn't exist on components repository +#define CM_NO_SUCH_SYMBOL ((t_cm_error)-46) //!< Symbol name doesn't exported by the underlying component +#define CM_COMPONENT_EXIST ((t_cm_error)-45) //!< Component name already exists in the component cache + + /* Fifo management related ones */ +#define CM_FIFO_FULL ((t_cm_error)-40) //!< Fifo is full +#define CM_FIFO_EMPTY ((t_cm_error)-39) //!< Fifo is empty +#define CM_UNKNOWN_FIFO_ID ((t_cm_error)-38) //!< Fifo handle doesn't exist + + /* Memory management related ones */ +#define CM_DOMAIN_VIOLATION ((t_cm_error)-33) //!< Domain violation +#define CM_CREATE_ALLOC_ERROR ((t_cm_error)-32) //!< Error during allocator creation +#define CM_UNKNOWN_MEMORY_HANDLE ((t_cm_error)-31) //!< Handle doesn't exists +#define CM_NO_MORE_MEMORY NMF_NO_MORE_MEMORY //!< \ref NMF_NO_MORE_MEMORY +#define CM_BAD_MEMORY_ALIGNMENT ((t_cm_error)-29) //!< Memory alignment wanted is not correct +#define CM_MEMORY_HANDLE_FREED ((t_cm_error)-28) //!< Handle was alread freed +#define CM_INVALID_DOMAIN_DEFINITION ((t_cm_error)-27) //!< Domain to be created is not correctly defined +#define CM_INTERNAL_DOMAIN_OVERFLOW ((t_cm_error)-26) //!< Internal domain descriptor overflow (too many domains) //TODO, juraj, remove this error +#define CM_INVALID_DOMAIN_HANDLE ((t_cm_error)-25) //!< Invalid domain handle +#define CM_ILLEGAL_DOMAIN_OPERATION ((t_cm_error)-21) //!< Operation on a domain is illegal (like destroy of a domain with referenced components) + + /* Media Processor related ones */ +#define CM_MPC_INVALID_CONFIGURATION ((t_cm_error)-24) //!< Media Processor Core invalid configuration +#define CM_MPC_NOT_INITIALIZED ((t_cm_error)-23) //!< Media Processor Core not yet initialized +#define CM_MPC_ALREADY_INITIALIZED ((t_cm_error)-22) //!< Media Processor Core already initialized +//ERROR 21 is defined above, with the domains + + /* Power Mgt related ones */ +#define CM_PWR_NOT_AVAILABLE ((t_cm_error)-16) //!< No modification of the state of the power input + + /* Common errors */ +#define CM_OUT_OF_LIMITS ((t_cm_error)-3) //!< User reach an internal nmf limits of limits.h file +#define CM_INVALID_PARAMETER NMF_INVALID_PARAMETER //!< \ref NMF_INVALID_PARAMETER +#define CM_NOT_YET_IMPLEMENTED ((t_cm_error)-1) //!< CM API not yet implemented +#define CM_OK NMF_OK //!< \ref NMF_OK + +/** @} */ + +/*! + * \brief Definition of a physical memory address + * \ingroup MEMORY + */ +typedef t_uint32 t_cm_physical_address; + +/*! + * \brief Definition of a logical memory address + * \ingroup MEMORY + */ +typedef t_uint32 t_cm_logical_address; + +/*! + * \brief Definition of a system address into a system with MMU + * \ingroup MEMORY + */ +typedef struct { + t_cm_physical_address physical; //!< Physical memory address + t_cm_logical_address logical; //!< Logical memory address +} t_cm_system_address; +#define INVALID_SYSTEM_ADDRESS {(t_cm_physical_address)MASK_ALL32, (t_cm_logical_address)MASK_ALL32} + + +/*! + * \brief Define a type used to manipulate size of various buffers + * \ingroup MEMORY + */ +typedef t_uint32 t_cm_size; + +#endif /* _CM_TYPE_H_ */ + diff --git a/drivers/staging/nmf-cm/cm_dma.c b/drivers/staging/nmf-cm/cm_dma.c new file mode 100644 index 00000000000..1db5a3cf951 --- /dev/null +++ b/drivers/staging/nmf-cm/cm_dma.c @@ -0,0 +1,178 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * License terms: GNU General Public License (GPL), version 2. + */ + +#include +#include +#include +#include + + #include "cm_dma.h" + + #define CMDMA_LIDX (2) + #define CMDMA_BASE (0x801C0000) + #define CMDMA_REG_LCLA (0x024) + +void __iomem *virtbase = NULL; + +static int cmdma_write_cyclic_list_mem2per( + unsigned int from_addr, + unsigned int to_addr, + unsigned int segments, + unsigned int segmentsize, + unsigned int LOS); + +static int cmdma_write_cyclic_list_per2mem( + unsigned int from_addr, + unsigned int to_addr, + unsigned int segments, + unsigned int segmentsize, + unsigned int LOS); + +int cmdma_setup_relink_area( unsigned int mem_addr, + unsigned int per_addr, + unsigned int segments, + unsigned int segmentsize, + unsigned int LOS, + enum cmdma_type type) +{ + switch (type) { + + case CMDMA_MEM_2_PER: + return cmdma_write_cyclic_list_mem2per( + mem_addr, + per_addr, + segments, + segmentsize, + LOS); + + case CMDMA_PER_2_MEM: + return cmdma_write_cyclic_list_per2mem( + per_addr, + mem_addr, + segments, + segmentsize, + LOS); + + default : + return -EINVAL; + } + } + + static unsigned int cmdma_getlcla( void) { + + if(!virtbase) + virtbase = ioremap(CMDMA_BASE, CMDMA_REG_LCLA + sizeof(int) ); + + return readl(virtbase + CMDMA_REG_LCLA); + } + + static void cmdma_write_relink_params_mem2per ( + int * relink, + unsigned int LOS, + unsigned int nb_element, + unsigned int src_addr, + unsigned int dst_addr, + unsigned int burst_size) { + + relink[0] = (((long)(nb_element & 0xFFFF)) << 16) | + (src_addr & 0xFFFF); + + relink[1] = (((src_addr >> 16) & 0xFFFFUL) << 16) | + (0x1200UL | (LOS << 1) | (burst_size<<10)); + + relink[2] = ((nb_element & 0xFFFF) << 16) | + (dst_addr & 0xFFFF); + + relink[3] = (((dst_addr >> 16) & 0xFFFFUL) << 16 ) | + 0x8201UL | ((LOS+1) << 1) | (burst_size<<10); +} + +static void cmdma_write_relink_params_per2mem ( + int * relink, + unsigned int LOS, + unsigned int nb_element, + unsigned int src_addr, + unsigned int dst_addr, + unsigned int burst_size) { + + relink[0] = (((long)(nb_element & 0xFFFF)) << 16) | + (src_addr & 0xFFFF); + + relink[1] = (((src_addr >> 16) & 0xFFFFUL) << 16) | + (0x8201UL | (LOS << 1) | (burst_size<<10)); + + relink[2] = ((nb_element & 0xFFFF) << 16) | + (dst_addr & 0xFFFF); + + relink[3] = (((dst_addr >> 16) & 0xFFFFUL) << 16 ) | + 0x1200UL | ((LOS+1) << 1) | (burst_size<<10); +} + +static int cmdma_write_cyclic_list_mem2per( + unsigned int from_addr, + unsigned int to_addr, + unsigned int segments, + unsigned int segmentsize, + unsigned int LOS) { + + unsigned int i,j; + int *relink; + + j = LOS; + + for ( i = 0; i < segments; i++) { + relink = phys_to_virt (cmdma_getlcla() + 1024 * CMDMA_LIDX + 8 * j); + + if (i == (segments-1)) + j = LOS; + else + j += 2; + + cmdma_write_relink_params_mem2per ( + relink, + j, + segmentsize / 4, + from_addr, + to_addr, + 0x2); + + from_addr += segmentsize; + } + + return 0; +} + +static int cmdma_write_cyclic_list_per2mem( + unsigned int from_addr, + unsigned int to_addr, + unsigned int segments, + unsigned int segmentsize, + unsigned int LOS) { + + unsigned int i,j; + int *relink; + j = LOS; + + for ( i = 0; i < segments; i++) { + relink = phys_to_virt (cmdma_getlcla() + 1024 * CMDMA_LIDX + 8 * j); + + if (i == (segments-1)) + j = LOS; + else + j += 2; + + cmdma_write_relink_params_per2mem ( + relink, + j, + segmentsize / 4, + from_addr, + to_addr, + 0x2); + + to_addr += segmentsize; + } + + return 0; +} diff --git a/drivers/staging/nmf-cm/cm_dma.h b/drivers/staging/nmf-cm/cm_dma.h new file mode 100644 index 00000000000..6ee4caafeae --- /dev/null +++ b/drivers/staging/nmf-cm/cm_dma.h @@ -0,0 +1,24 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +#ifndef __CMDMA_H +#define __CMDMA_H + +enum cmdma_type { + CMDMA_MEM_2_PER, + CMDMA_PER_2_MEM +}; + +int cmdma_setup_relink_area( + unsigned int mem_addr, + unsigned int per_addr, + unsigned int segments, + unsigned int segmentsize, + unsigned int LOS, + enum cmdma_type type); + +#endif diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c new file mode 100644 index 00000000000..1b5ee111e09 --- /dev/null +++ b/drivers/staging/nmf-cm/cm_service.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Pierre Peiffer for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +/** \file cm_service.c + * + * Nomadik Multiprocessing Framework Linux Driver + * + */ + +#include +#include +#include +#include + +#include + +#include "osal-kernel.h" +#include "cmld.h" +#include "cm_service.h" + +/* Panic managment */ +static void service_tasklet_func(unsigned long); +unsigned long service_tasklet_data = 0; +DECLARE_TASKLET(cmld_service_tasklet, service_tasklet_func, 0); + +void dispatch_service_msg(struct osal_msg *msg) +{ + struct list_head *head, *next; + + /* Note: no lock needed to protect the channel_list to protect against list + changes, as the current tasklet is disabled each time we modify the list */ + list_for_each_safe(head, next, &channel_list) { + struct cm_channel_priv *channelPriv = list_entry(head, struct cm_channel_priv, entry); + struct osal_msg *new_msg; + size_t msg_size; + + if (channelPriv->state == CHANNEL_CLOSED) + continue; + msg_size = sizeof(new_msg->hdr) + sizeof(new_msg->d.srv); + new_msg = kmalloc(msg_size, GFP_ATOMIC); + if (new_msg == NULL) { + pr_err("[CM] %s: can't allocate memory, service" + " message not dispatched !!\n", __func__); + continue; + } + memcpy(new_msg, msg, msg_size); + plist_node_init(&new_msg->msg_entry, 0); + spin_lock_bh(&channelPriv->bh_lock); + plist_add(&new_msg->msg_entry, &channelPriv->messageQueue); + spin_unlock_bh(&channelPriv->bh_lock); + wake_up_interruptible(&channelPriv->waitq); + } +} + +static void service_tasklet_func(unsigned long unused) +{ + t_cm_service_type type; + t_cm_service_description desc; + int i=0; + + do { + if (test_and_clear_bit(i, &service_tasklet_data)) { + CM_getServiceDescription(osalEnv.mpc[i].coreId, &type, &desc); + + switch (type) { + case CM_MPC_SERVICE_PANIC: { + struct osal_msg msg; + + msg.msg_type = MSG_SERVICE; + msg.d.srv.srvType = NMF_SERVICE_PANIC; + msg.d.srv.srvData.panic = desc.u.panic; + + dispatch_service_msg(&msg); + break; + } + case CM_MPC_SERVICE_PRINT: { + char msg[256]; + if (CM_ReadMPCString(osalEnv.mpc[i].coreId, + desc.u.print.dspAddress, msg, + sizeof(msg)) == CM_OK) + printk(msg, desc.u.print.value1, desc.u.print.value2); + break; + } + default: + pr_err("[CM] %s: MPC Service Type %d not supported\n", __func__, type); + } + enable_irq(osalEnv.mpc[i].interrupt1); + } + i = (i+1) % NB_MPC; + } while (service_tasklet_data != 0); +} diff --git a/drivers/staging/nmf-cm/cm_service.h b/drivers/staging/nmf-cm/cm_service.h new file mode 100644 index 00000000000..39582eae573 --- /dev/null +++ b/drivers/staging/nmf-cm/cm_service.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Pierre Peiffer for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +/** \file cm_service.c + * + * Nomadik Multiprocessing Framework Linux Driver + * + */ + +#ifndef CM_SERVICE_H +#define CM_SERVICE_H + +#include + +extern unsigned long service_tasklet_data; +extern struct tasklet_struct cmld_service_tasklet; +void dispatch_service_msg(struct osal_msg *msg); + +#endif diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c new file mode 100644 index 00000000000..d1ad3a1f935 --- /dev/null +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -0,0 +1,1390 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Pierre Peiffer for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +#include +#include +#include +#include +#include "cmioctl.h" +#include "osal-kernel.h" +#include "cmld.h" +#include +#include + +/** Dequeue and free per-process messages for specific binding + * + * \note + * This is only safe if the per process mutex is held when called. + */ +static inline void freeMessages(struct cm_channel_priv* cPriv, t_skelwrapper* binding) +{ + struct osal_msg *this, *next; + + spin_lock_bh(&cPriv->bh_lock); + + /* free any pending messages */ + plist_for_each_entry_safe(this, next, &cPriv->messageQueue, msg_entry) { + if (this->msg_type == MSG_INTERFACE + && this->d.itf.skelwrap == binding) { + plist_del(&this->msg_entry, &cPriv->messageQueue); + kfree(this); + } + } + spin_unlock_bh(&cPriv->bh_lock); +} + +static t_cm_error copy_string_from_user(char *dst, const char __user *src, int len) +{ + int ret; + + ret = strncpy_from_user(dst, src, len); + if (ret < 0) /* -EFAULT */ + return CM_INVALID_PARAMETER; + + if (ret >= len) + return CM_OUT_OF_LIMITS; + + return 0; +} + +inline int cmld_InstantiateComponent(struct cm_process_priv* procPriv, + CM_InstantiateComponent_t __user *param) +{ + CM_InstantiateComponent_t data; + char templateName[MAX_TEMPLATE_NAME_LENGTH]; + char localName[MAX_COMPONENT_NAME_LENGTH]; + char *dataFile = NULL; + + /* Copy all user data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if (data.in.dataFile != NULL) { + dataFile = OSAL_Alloc(data.in.dataFileSize); + if (dataFile == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFile, data.in.dataFile, data.in.dataFileSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + if ((data.out.error = copy_string_from_user(templateName, + data.in.templateName, + sizeof(templateName)))) + goto out; + + if ((data.in.localName != NULL) && + (data.out.error = copy_string_from_user(localName, + data.in.localName, + sizeof(localName)))) + goto out; + + /* Do appropriate CM Engine call */ + data.out.error = CM_ENGINE_InstantiateComponent(templateName, + data.in.domainId, + procPriv->pid, + data.in.priority, + data.in.localName ? localName : NULL, + dataFile, + &data.out.component); + +out: + if (dataFile) + OSAL_Free(dataFile); + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_BindComponentFromCMCore(struct cm_process_priv* procPriv, + CM_BindComponentFromCMCore_t __user *param) +{ + CM_BindComponentFromCMCore_t data; + char providedItfServerName[MAX_INTERFACE_NAME_LENGTH]; + char *dataFileSkeleton = NULL; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(providedItfServerName, + data.in.providedItfServerName, + sizeof(providedItfServerName)))) + goto out; + + if (data.in.dataFileSkeleton != NULL) { + dataFileSkeleton = OSAL_Alloc(data.in.dataFileSkeletonSize); + if (dataFileSkeleton == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFileSkeleton, data.in.dataFileSkeleton, + data.in.dataFileSkeletonSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + data.out.error = CM_ENGINE_BindComponentFromCMCore(data.in.server, + providedItfServerName, + data.in.fifosize, + data.in.eventMemType, + &data.out.host2mpcId, + procPriv->pid, + dataFileSkeleton); +out: + if (dataFileSkeleton) + OSAL_Free(dataFileSkeleton); + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + + return 0; +} + +inline int cmld_UnbindComponentFromCMCore(CM_UnbindComponentFromCMCore_t __user *param) +{ + CM_UnbindComponentFromCMCore_t data; + + /* Copy all user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_UnbindComponentFromCMCore(data.in.host2mpcId); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_BindComponentToCMCore(struct cm_channel_priv* channelPriv, + CM_BindComponentToCMCore_t __user *param) +{ + CM_BindComponentToCMCore_t data; + t_skelwrapper *skelwrapper; + struct cm_process_priv *procPriv = channelPriv->proc; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + char *dataFileStub = NULL; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + /* Do appropriate CM Engine call */ + skelwrapper = (t_skelwrapper *)OSAL_Alloc(sizeof(*skelwrapper)); + if (skelwrapper == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + + if (data.in.dataFileStub != NULL) { + dataFileStub = OSAL_Alloc(data.in.dataFileStubSize); + if (dataFileStub == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFileStub, data.in.dataFileStub, data.in.dataFileStubSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + if ((data.out.error = CM_ENGINE_BindComponentToCMCore( + data.in.client, + requiredItfClientName, + data.in.fifosize, + (t_nmf_mpc2host_handle)skelwrapper, + dataFileStub, + &data.out.mpc2hostId, + procPriv->pid)) != CM_OK) { + OSAL_Free(skelwrapper); + goto out; + } + + skelwrapper->upperLayerThis = data.in.upLayerThis; + skelwrapper->mpc2hostId = data.out.mpc2hostId; + skelwrapper->channelPriv = channelPriv; + mutex_lock(&channelPriv->skelListLock); + list_add(&skelwrapper->entry, &channelPriv->skelList); + mutex_unlock(&channelPriv->skelListLock); +out: + if (dataFileStub != NULL) + OSAL_Free(dataFileStub); + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_UnbindComponentToCMCore(struct cm_process_priv* procPriv, + CM_UnbindComponentToCMCore_t __user *param) +{ + CM_UnbindComponentToCMCore_t data; + t_skelwrapper *skelwrapper; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + data.out.error = CM_ENGINE_UnbindComponentToCMCore( + data.in.client, requiredItfClientName, + (t_nmf_mpc2host_handle*)&skelwrapper, + procPriv->pid); + + if (data.out.error != CM_OK && data.out.error != CM_MPC_NOT_RESPONDING) + goto out; + + data.out.upLayerThis = skelwrapper->upperLayerThis; + + mutex_lock(&skelwrapper->channelPriv->msgQueueLock); + freeMessages(skelwrapper->channelPriv, skelwrapper); + mutex_lock(&skelwrapper->channelPriv->skelListLock); + list_del(&skelwrapper->entry); + mutex_unlock(&skelwrapper->channelPriv->skelListLock); + mutex_unlock(&skelwrapper->channelPriv->msgQueueLock); + OSAL_Free(skelwrapper); +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_BindComponentAsynchronous(struct cm_process_priv* procPriv, + CM_BindComponentAsynchronous_t __user *param) +{ + CM_BindComponentAsynchronous_t data; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + char providedItfServerName[MAX_INTERFACE_NAME_LENGTH]; + char *dataFileSkeletonOrEvent = NULL; + char *dataFileStub = NULL; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + if ((data.out.error = copy_string_from_user(providedItfServerName, + data.in.providedItfServerName, + sizeof(providedItfServerName)))) + goto out; + + if (data.in.dataFileSkeletonOrEvent != NULL) { + dataFileSkeletonOrEvent = + OSAL_Alloc(data.in.dataFileSkeletonOrEventSize); + if (dataFileSkeletonOrEvent == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFileSkeletonOrEvent, data.in.dataFileSkeletonOrEvent, data.in.dataFileSkeletonOrEventSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + if (data.in.dataFileStub != NULL) { + dataFileStub = OSAL_Alloc(data.in.dataFileStubSize); + if (dataFileStub == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFileStub, data.in.dataFileStub, data.in.dataFileStubSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + /* Do appropriate CM Engine call */ + data.out.error = CM_ENGINE_BindComponentAsynchronous(data.in.client, + requiredItfClientName, + data.in.server, + providedItfServerName, + data.in.fifosize, + data.in.eventMemType, + procPriv->pid, + dataFileSkeletonOrEvent, + dataFileStub); + +out: + if (dataFileSkeletonOrEvent != NULL) + OSAL_Free(dataFileSkeletonOrEvent); + if (dataFileStub != NULL) + OSAL_Free(dataFileStub); + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_UnbindComponentAsynchronous(struct cm_process_priv* procPriv, + CM_UnbindComponentAsynchronous_t __user *param) +{ + CM_UnbindComponentAsynchronous_t data; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + + /* Copy all user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + /* Do appropriate CM Engine call */ + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_UnbindComponentAsynchronous(data.in.client, + requiredItfClientName, + procPriv->pid); +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_BindComponent(struct cm_process_priv* procPriv, + CM_BindComponent_t __user *param) +{ + CM_BindComponent_t data; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + char providedItfServerName[MAX_INTERFACE_NAME_LENGTH]; + char *dataFileTrace = NULL; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + if ((data.out.error = copy_string_from_user(providedItfServerName, + data.in.providedItfServerName, + sizeof(providedItfServerName)))) + goto out; + + if (data.in.dataFileTrace != NULL) { + dataFileTrace = OSAL_Alloc(data.in.dataFileTraceSize); + if (dataFileTrace == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFileTrace, data.in.dataFileTrace, + data.in.dataFileTraceSize)) { + data.out.error = CM_INVALID_PARAMETER; + goto out; + } + } + + /* Do appropriate CM Engine call */ + data.out.error = CM_ENGINE_BindComponent(data.in.client, + requiredItfClientName, + data.in.server, + providedItfServerName, + data.in.traced, + procPriv->pid, + dataFileTrace); +out: + if (dataFileTrace != NULL) + OSAL_Free(dataFileTrace); + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_UnbindComponent(struct cm_process_priv* procPriv, + CM_UnbindComponent_t __user *param) +{ + CM_UnbindComponent_t data; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + /* Do appropriate CM Engine call */ + data.out.error = CM_ENGINE_UnbindComponent(data.in.client, + requiredItfClientName, + procPriv->pid); + +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_BindComponentToVoid(struct cm_process_priv* procPriv, + CM_BindComponentToVoid_t __user *param) +{ + CM_BindComponentToVoid_t data; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + data.out.error = CM_ENGINE_BindComponentToVoid(data.in.client, + requiredItfClientName, + procPriv->pid); + +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_DestroyComponent(struct cm_process_priv* procPriv, + CM_DestroyComponent_t __user *param) +{ + CM_DestroyComponent_t data; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_DestroyComponent(data.in.component, + procPriv->pid); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_CreateMemoryDomain(struct cm_process_priv *procPriv, + CM_CreateMemoryDomain_t __user *param) +{ + CM_CreateMemoryDomain_t data; + t_cm_domain_memory domain; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if (copy_from_user(&domain, data.in.domain, sizeof(domain))) + return -EFAULT; + + if (data.in.client == NMF_CURRENT_CLIENT) + data.out.error = CM_ENGINE_CreateMemoryDomain(procPriv->pid, + &domain, + &data.out.handle); + else + data.out.error = CM_ENGINE_CreateMemoryDomain(data.in.client, + &domain, + &data.out.handle); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_CreateMemoryDomainScratch(struct cm_process_priv *procPriv, + CM_CreateMemoryDomainScratch_t __user *param) +{ + CM_CreateMemoryDomainScratch_t data; + t_cm_domain_memory domain; + + /* Copy all user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if (copy_from_user(&domain, data.in.domain, sizeof(domain))) + return -EFAULT; + + data.out.error = CM_ENGINE_CreateMemoryDomainScratch(procPriv->pid, + data.in.parentId, + &domain, + &data.out.handle); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_DestroyMemoryDomain(CM_DestroyMemoryDomain_t __user *param) +{ + CM_DestroyMemoryDomain_t data; + + /* Copy all user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_DestroyMemoryDomain(data.in.domainId); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetDomainCoreId(CM_GetDomainCoreId_t __user *param) +{ + CM_GetDomainCoreId_t data; + + /* Copy all user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_GetDomainCoreId(data.in.domainId, + &data.out.coreId); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_AllocMpcMemory(struct cm_process_priv *procPriv, + CM_AllocMpcMemory_t __user *param) +{ + t_cm_error err; + CM_AllocMpcMemory_t data; + t_cm_memory_handle handle = 0; + struct memAreaDesc_t* memAreaDesc; + t_cm_system_address systemAddress; + t_uint32 mpcAddress; + + /* Copy all user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* Disregard alignment information and force 4kB memory alignment, + in any case (see devnotes.txt) */ + /* PP: Disable this 'force' for now, because of the low amount of + available MPC Memory */ + //data.in.memAlignment = CM_MM_MPC_ALIGN_1024WORDS; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_AllocMpcMemory(data.in.domainId, + procPriv->pid, + data.in.memType, + data.in.size, + data.in.memAlignment, + &handle); + + data.out.pHandle = handle; + + if (data.out.error != CM_OK) + goto out; + + /* Get memory area decriptors in advance + so to fill in list elements right now */ + err = CM_ENGINE_GetMpcMemorySystemAddress(handle, &systemAddress); + if (err != CM_OK) { + pr_err("%s: failed CM_ENGINE_GetMpcMemorySystemAddress (%i)\n", __func__, err); + /* If we can't manage internally this allocated memory latter, it's + better to report the error now. + Free the handle to not let the driver in an inconsistent state */ + CM_ENGINE_FreeMpcMemory(handle); + return -EFAULT; + } + + /* Get MPC address in advance so to fill in list elements right now */ + err = CM_ENGINE_GetMpcMemoryMpcAddress(handle, &mpcAddress); + if (err != CM_OK) { + pr_err("%s: failed CM_ENGINE_GetMpcMemoryMpcAddress (%i)\n", __func__, err); + /* see comments above */ + CM_ENGINE_FreeMpcMemory(handle); + return -EFAULT; + } + + /* Allocate and fill a new memory area descriptor. Add it to the list */ + memAreaDesc = OSAL_Alloc(sizeof(struct memAreaDesc_t)); + if (memAreaDesc == NULL) { + pr_err("%s: failed allocating memAreaDesc\n", __func__); + /* see comments above */ + CM_ENGINE_FreeMpcMemory(handle); + return -ENOMEM; + } + + memAreaDesc->procPriv = procPriv; + memAreaDesc->handle = handle; + memAreaDesc->tid = 0; + memAreaDesc->physAddr = systemAddress.physical; + memAreaDesc->kernelLogicalAddr = systemAddress.logical; + memAreaDesc->userLogicalAddr = 0; + memAreaDesc->mpcPhysAddr = mpcAddress; + memAreaDesc->size = data.in.size * ((data.in.memType % 2) ? 4 : 2); // betzw: set size in bytes for host (ugly version) + atomic_set(&memAreaDesc->count, 0); + + if (lock_process(procPriv)) { + /* may be rather call lock_process_uninterruptible() */ + CM_ENGINE_FreeMpcMemory(handle); + OSAL_Free(memAreaDesc); + return -ERESTARTSYS; + } + list_add(&memAreaDesc->list, &procPriv->memAreaDescList); + unlock_process(procPriv); +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_FreeMpcMemory(struct cm_process_priv *procPriv, + CM_FreeMpcMemory_t __user *param) +{ + CM_FreeMpcMemory_t data; + struct list_head *cursor, *next; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* check that it is actually owned by the process */ + data.out.error = CM_UNKNOWN_MEMORY_HANDLE; + + if (lock_process(procPriv)) + return -ERESTARTSYS; + list_for_each_safe(cursor, next, &procPriv->memAreaDescList){ + struct memAreaDesc_t* curr; + curr = list_entry(cursor, struct memAreaDesc_t, list); + if (curr->handle == data.in.handle){ + if (atomic_read(&curr->count) != 0) { + pr_err("%s: Memory area (phyAddr: %x, size: %d) " + "still in use (count=%d)!\n", __func__, + curr->physAddr, curr->size, + atomic_read(&curr->count)); + data.out.error = CM_INVALID_PARAMETER; + } else { + data.out.error = + CM_ENGINE_FreeMpcMemory(data.in.handle); + if (data.out.error == CM_OK) { + list_del(cursor); + OSAL_Free(curr); + } + } + break; + } + } + unlock_process(procPriv); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetMpcMemoryStatus(CM_GetMpcMemoryStatus_t __user *param) +{ + CM_GetMpcMemoryStatus_t data; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_GetMpcMemoryStatus(data.in.coreId, + data.in.memType, + &data.out.pStatus); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_StartComponent(struct cm_process_priv *procPriv, + CM_StartComponent_t __user *param) +{ + CM_StartComponent_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_StartComponent(data.in.client, + procPriv->pid); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_StopComponent(struct cm_process_priv *procPriv, + CM_StopComponent_t __user *param) +{ + CM_StopComponent_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_StopComponent(data.in.client, + procPriv->pid); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetMpcLoadCounter(CM_GetMpcLoadCounter_t __user *param) +{ + CM_GetMpcLoadCounter_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_getMpcLoadCounter(data.in.coreId, + &data.out.pMpcLoadCounter); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentDescription(struct cm_process_priv *procPriv, + CM_GetComponentDescription_t __user *param) +{ + CM_GetComponentDescription_t data; + char templateName[MAX_TEMPLATE_NAME_LENGTH]; + char localName[MAX_COMPONENT_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentDescription(data.in.component, + templateName, + data.in.templateNameLength, + &data.out.coreId, + localName, + data.in.localNameLength, + &data.out.priority); + + /* Copy results back to userspace */ + if (data.out.error == CM_OK) { + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.templateName, templateName, data.in.templateNameLength)) + return -EFAULT; + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.localName, localName, data.in.localNameLength)) + return -EFAULT; + } + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentListHeader(struct cm_process_priv *procPriv, + CM_GetComponentListHeader_t __user *param) +{ + CM_GetComponentListHeader_t data; + + data.out.error = CM_ENGINE_GetComponentListHeader(procPriv->pid, + &data.out.headerComponent); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentListNext(struct cm_process_priv *procPriv, + CM_GetComponentListNext_t __user *param) +{ + CM_GetComponentListNext_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentListNext(procPriv->pid, + data.in.prevComponent, + &data.out.nextComponent); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentRequiredInterfaceNumber(struct cm_process_priv *procPriv, + CM_GetComponentRequiredInterfaceNumber_t __user *param) +{ + CM_GetComponentRequiredInterfaceNumber_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentRequiredInterfaceNumber(data.in.component, + &data.out.numberRequiredInterfaces); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentRequiredInterface(struct cm_process_priv *procPriv, + CM_GetComponentRequiredInterface_t __user *param) +{ + CM_GetComponentRequiredInterface_t data; + char itfName[MAX_INTERFACE_NAME_LENGTH]; + char itfType[MAX_INTERFACE_TYPE_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentRequiredInterface(data.in.component, + data.in.index, + itfName, + data.in.itfNameLength, + itfType, + data.in.itfTypeLength, + &data.out.requireState, + &data.out.collectionSize); + + /* Copy results back to userspace */ + if (data.out.error == CM_OK) { + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.itfName, itfName, data.in.itfNameLength)) + return -EFAULT; + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.itfType, itfType, data.in.itfTypeLength)) + return -EFAULT; + } + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentRequiredInterfaceBinding(struct cm_process_priv *procPriv, + CM_GetComponentRequiredInterfaceBinding_t __user *param) +{ + CM_GetComponentRequiredInterfaceBinding_t data; + char itfName[MAX_INTERFACE_NAME_LENGTH]; + char serverItfName[MAX_INTERFACE_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + if ((data.out.error = copy_string_from_user(itfName, + data.in.itfName, + sizeof(itfName)))) + goto out; + + data.out.error = CM_ENGINE_GetComponentRequiredInterfaceBinding(data.in.component, + itfName, + &data.out.server, + serverItfName, + data.in.serverItfNameLength); + + /* Copy results back to userspace */ + if (data.out.error != CM_OK) + goto out; + + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.serverItfName, serverItfName, data.in.serverItfNameLength)) + return -EFAULT; +out: + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentProvidedInterfaceNumber(struct cm_process_priv *procPriv, + CM_GetComponentProvidedInterfaceNumber_t __user *param) +{ + CM_GetComponentProvidedInterfaceNumber_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentProvidedInterfaceNumber(data.in.component, + &data.out.numberProvidedInterfaces); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentProvidedInterface(struct cm_process_priv *procPriv, + CM_GetComponentProvidedInterface_t __user *param) +{ + CM_GetComponentProvidedInterface_t data; + char itfName[MAX_INTERFACE_NAME_LENGTH]; + char itfType[MAX_INTERFACE_TYPE_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentProvidedInterface(data.in.component, + data.in.index, + itfName, + data.in.itfNameLength, + itfType, + data.in.itfTypeLength, + &data.out.collectionSize); + + /* Copy results back to userspace */ + if (data.out.error == CM_OK) { + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.itfName, itfName, data.in.itfNameLength)) + return -EFAULT; + /* coverity[tainted_data : FALSE] */ + if (copy_to_user(data.in.itfType, itfType, data.in.itfTypeLength)) + return -EFAULT; + } + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentPropertyNumber(struct cm_process_priv *procPriv, + CM_GetComponentPropertyNumber_t __user *param) +{ + CM_GetComponentPropertyNumber_t data; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentPropertyNumber(data.in.component, + &data.out.numberProperties); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentPropertyName(struct cm_process_priv *procPriv, + CM_GetComponentPropertyName_t __user *param) +{ + CM_GetComponentPropertyName_t data; + char propertyName[MAX_PROPERTY_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_GetComponentPropertyName(data.in.component, + data.in.index, + propertyName, + data.in.propertyNameLength); + + /* Copy results back to userspace */ + /* coverity[tainted_data : FALSE] */ + if ((data.out.error == CM_OK) && + copy_to_user(data.in.propertyName, propertyName, data.in.propertyNameLength)) + return -EFAULT; + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetComponentPropertyValue(struct cm_process_priv *procPriv, + CM_GetComponentPropertyValue_t __user *param) +{ + CM_GetComponentPropertyValue_t data; + char propertyName[MAX_PROPERTY_NAME_LENGTH]; + char propertyValue[MAX_PROPERTY_VALUE_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(propertyName, + data.in.propertyName, + sizeof(propertyName)))) + goto out; + + data.out.error = CM_ENGINE_GetComponentPropertyValue(data.in.component, + propertyName, + propertyValue, + data.in.propertyValueLength); + /* Copy results back to userspace */ + /* coverity[tainted_data : FALSE] */ + if ((data.out.error == CM_OK) && + copy_to_user(data.in.propertyValue, propertyValue, data.in.propertyValueLength)) + return -EFAULT; +out: + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_ReadComponentAttribute(struct cm_process_priv *procPriv, + CM_ReadComponentAttribute_t __user *param) +{ + CM_ReadComponentAttribute_t data; + char attrName[MAX_ATTRIBUTE_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(attrName, + data.in.attrName, + sizeof(attrName)))) + goto out; + + data.out.error = CM_ENGINE_ReadComponentAttribute(data.in.component, + attrName, + &data.out.value); +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetExecutiveEngineHandle(struct cm_process_priv *procPriv, + CM_GetExecutiveEngineHandle_t __user *param) +{ + CM_GetExecutiveEngineHandle_t data; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_GetExecutiveEngineHandle(data.in.domainId, + &data.out.executiveEngineHandle); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_SetMode(CM_SetMode_t __user *param) +{ + CM_SetMode_t data; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_SetMode(data.in.aCmdID, data.in.aParam); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_GetRequiredComponentFiles(struct cm_process_priv *procPriv, + CM_GetRequiredComponentFiles_t __user *param) +{ + CM_GetRequiredComponentFiles_t data; + char components[4][MAX_INTERFACE_TYPE_NAME_LENGTH]; + char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH]; + char providedItfServerName[MAX_INTERFACE_NAME_LENGTH]; + char type[MAX_INTERFACE_TYPE_NAME_LENGTH]; + unsigned int i; + int err; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if (data.in.requiredItfClientName && + (data.out.error = copy_string_from_user(requiredItfClientName, + data.in.requiredItfClientName, + sizeof(requiredItfClientName)))) + goto out; + + if (data.in.providedItfServerName && + (data.out.error = copy_string_from_user(providedItfServerName, + data.in.providedItfServerName, + sizeof(providedItfServerName)))) + goto out; + + data.out.error = CM_ENGINE_GetRequiredComponentFiles(data.in.action, + data.in.client, + requiredItfClientName, + data.in.server, + providedItfServerName, + components, + data.in.listSize, + data.in.type ? type : NULL, + &data.out.methodNumber); + + if (data.out.error) + goto out; + + if (data.in.fileList) { + /* Copy results back to userspace */ + for (i=0; iout, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_Migrate(CM_Migrate_t __user *param) +{ + CM_Migrate_t data; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + data.out.error = CM_ENGINE_Migrate(data.in.srcShared, data.in.src, data.in.dst); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_Unmigrate(CM_Unmigrate_t __user *param) +{ + CM_Unmigrate_t data; + + data.out.error = CM_ENGINE_Unmigrate(); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +int cmld_SetupRelinkArea(CM_SetupRelinkArea_t __user *param) +{ + CM_SetupRelinkArea_t data; + t_cm_system_address systemAddress; + t_uint32 size; + + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + + data.out.error = CM_ENGINE_GetMpcMemorySystemAddress( + data.in.mem_handle, &systemAddress); + + if (data.out.error != CM_OK) + return 0; + + data.out.error = CM_ENGINE_GetMpcMemorySize(data.in.mem_handle, &size); + if (data.out.error != CM_OK) + return 0; + + if (size < data.in.segments * data.in.segmentsize) + { + return -EINVAL; + } + + data.out.error = cmdma_setup_relink_area( + systemAddress.physical, + data.in.peripheral_addr, + data.in.segments, + data.in.segmentsize, + data.in.LOS, + data.in.type); + + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + + return 0; +} + + +inline int cmld_PushComponent(CM_PushComponent_t __user *param) +{ + CM_PushComponent_t data; + char name[MAX_INTERFACE_TYPE_NAME_LENGTH]; + void *dataFile = NULL; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(name, + data.in.name, + sizeof(name)))) + goto out; + + if (data.in.data != NULL) { + dataFile = OSAL_Alloc(data.in.size); + if (dataFile == NULL) { + data.out.error = CM_NO_MORE_MEMORY; + goto out; + } + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(dataFile, data.in.data, data.in.size)) + data.out.error = CM_INVALID_PARAMETER; + else + data.out.error = CM_ENGINE_PushComponent(name, dataFile, + data.in.size); + OSAL_Free(dataFile); + } + +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_ReleaseComponent(CM_ReleaseComponent_t __user *param) +{ + CM_ReleaseComponent_t data; + char name[MAX_INTERFACE_TYPE_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(name, + data.in.name, + sizeof(name)))) + goto out; + + /* coverity[tainted_data : FALSE] */ + data.out.error = CM_ENGINE_ReleaseComponent(name); + +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +inline int cmld_PrivGetMPCMemoryDesc(struct cm_process_priv *procPriv, CM_PrivGetMPCMemoryDesc_t __user *param) +{ + CM_PrivGetMPCMemoryDesc_t data; + struct list_head* cursor; + + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if (lock_process(procPriv)) + return -ERESTARTSYS; + /* Scan the memory descriptors list looking for the requested handle */ + data.out.error = CM_UNKNOWN_MEMORY_HANDLE; + list_for_each(cursor, &procPriv->memAreaDescList) { + struct memAreaDesc_t* curr; + curr = list_entry(cursor, struct memAreaDesc_t, list); + if (curr->handle == data.in.handle) { + data.out.size = curr->size; + data.out.physAddr = curr->physAddr; + data.out.kernelLogicalAddr = curr->kernelLogicalAddr; + data.out.userLogicalAddr = curr->userLogicalAddr; + data.out.mpcPhysAddr = curr->mpcPhysAddr; + data.out.error = CM_OK; + break; + } + } + unlock_process(procPriv); + + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + +int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAddr) +{ + struct list_head* cursor; + struct memAreaDesc_t* curr; + int err = -ENXIO; + + if (lock_process(procPriv)) + return -ERESTARTSYS; + list_for_each(cursor, &procPriv->memAreaDescList) { + curr = list_entry(cursor, struct memAreaDesc_t, list); + if (curr->physAddr == physAddr) { + /* Mark this memory area reserved for a mapping for this thread ID */ + /* It must not be already reserved but this should not happen */ + if (curr->tid) { + pr_err("%s: thread %d can't reseveved memory %x already " + "reserved for %d\n", + __func__, current->pid, physAddr, curr->tid); + err = -EBUSY; + } else { + curr->tid = current->pid; + err = 0; + } + break; + } + } + unlock_process(procPriv); + return err; +} diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h new file mode 100644 index 00000000000..7ca46fc25e8 --- /dev/null +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -0,0 +1,588 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Pierre Peiffer for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +#ifndef __CMIOCTL_H +#define __CMIOCTL_H + +#include +#include +#include +#include +#include +#include +#include +#include "cm_dma.h" + +#define CMLD_DEV_NAME \ + { "cm_control", \ + "cm_channel" \ + } + +/* + * The following structures are used to exchange CM_SYSCALL parameters with + * the driver. There is one structure per ioctl command, ie per CM_SYSCAL. + * Each of them contains: + * - One set of fields placed in a struture 'in' which are all input + * parameters of the syscall (parameters that kernel side must retrieve + * from user space) + * - One set of fields placed in a struture 'out' which contains all output + * parameters of the syscall plus the error code. + * + * NOTE: all pointers to (user) buffer are always placed in struct 'in', including + * buffers used as output parameters; because the pointer itself is considered as + * an input parameter, as it is directly accessed from kernel space. + */ +typedef struct{ + struct { + const char * templateName; + t_cm_domain_id domainId; + t_nmf_ee_priority priority; + const char * localName; + const char *dataFile; + t_uint32 dataFileSize; + } in; + struct { + t_cm_instance_handle component; /** < Output parameter */ + t_cm_error error; + } out; +} CM_InstantiateComponent_t; + +typedef struct { + struct { + t_cm_bf_host2mpc_handle host2mpcId; + t_event_params_handle h; + t_uint32 size; + t_uint32 methodIndex; + } in; + struct { + t_cm_error error; + } out; +} CM_PushEventWithSize_t; + +typedef struct { + struct { + t_cm_instance_handle server; + const char * providedItfServerName; + t_uint32 fifosize; + t_cm_mpc_memory_type eventMemType; + const char *dataFileSkeleton; + t_uint32 dataFileSkeletonSize; + } in; + struct { + t_cm_bf_host2mpc_handle host2mpcId; /** < Output parameter */ + t_cm_error error; + } out; +} CM_BindComponentFromCMCore_t; + +typedef struct { + struct { + t_cm_bf_host2mpc_handle host2mpcId; + } in; + struct { + t_cm_error error; + } out; +} CM_UnbindComponentFromCMCore_t; + +typedef struct { + struct { + t_cm_instance_handle client; + const char *requiredItfClientName; + t_uint32 fifosize; + t_nmf_mpc2host_handle upLayerThis; + const char *dataFileStub; + t_uint32 dataFileStubSize; + } in; + struct { + t_cm_bf_mpc2host_handle mpc2hostId; /** < Output parameter */ + t_cm_error error; + } out; +} CM_BindComponentToCMCore_t; + +typedef struct { + struct { + t_cm_instance_handle client; + const char *requiredItfClientName; + } in; + struct { + t_nmf_mpc2host_handle upLayerThis; /** < Output parameter */ + t_cm_error error; + } out; +} CM_UnbindComponentToCMCore_t; + +typedef struct { + struct { + t_cm_instance_handle component; + } in; + struct { + t_cm_error error; /** < Output parameter */ + } out; /** < Output parameter */ +} CM_DestroyComponent_t; + +typedef struct { + struct { + const t_cm_domain_memory *domain; + t_nmf_client_id client; + } in; + struct { + t_cm_domain_id handle; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; /** < Out parameter */ +} CM_CreateMemoryDomain_t; + +typedef struct { + struct { + t_cm_domain_id parentId; + const t_cm_domain_memory *domain; + } in; + struct { + t_cm_domain_id handle; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; /** < Out parameter */ +} CM_CreateMemoryDomainScratch_t; + +typedef struct { + struct { + t_cm_domain_id domainId; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; /** < Out parameter */ +} CM_DestroyMemoryDomain_t; + +typedef struct { + struct { + t_cm_domain_id domainId; /** < In parameter */ + } in; + struct { + t_nmf_core_id coreId; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; /** < Out parameter */ +} CM_GetDomainCoreId_t; + +typedef struct { + struct { + t_cm_domain_id domainId; + t_cm_mpc_memory_type memType; + t_cm_size size; + t_cm_memory_alignment memAlignment; + } in; + struct { + t_cm_memory_handle pHandle; /** < Output parameter */ + t_cm_error error; + } out; /** < Output parameter */ +} CM_AllocMpcMemory_t; + +typedef struct{ + struct { + t_cm_memory_handle handle; + } in; + struct { + t_cm_error error; + } out; /** < Output parameter */ +} CM_FreeMpcMemory_t; + +typedef struct { + struct { + t_cm_memory_handle handle; + } in; + struct { + t_uint32 size; /** < Out parameter */ + t_uint32 physAddr; /** < Out parameter */ + t_uint32 kernelLogicalAddr; /** < Out parameter */ + t_uint32 userLogicalAddr; /** < Out parameter */ + t_uint32 mpcPhysAddr; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; /** < Output parameter */ +} CM_PrivGetMPCMemoryDesc_t; + +typedef struct { + struct { + t_cm_instance_handle client; + const char *requiredItfClientName; + t_cm_instance_handle server; + const char *providedItfServerName; + t_uint32 fifosize; + t_cm_mpc_memory_type eventMemType; + const char *dataFileSkeletonOrEvent; + t_uint32 dataFileSkeletonOrEventSize; + const char *dataFileStub; + t_uint32 dataFileStubSize; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_BindComponentAsynchronous_t; + +typedef struct { + struct { + t_cm_instance_handle client; + const char* requiredItfClientName; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_UnbindComponentAsynchronous_t; + +typedef struct { + struct { + t_cm_instance_handle client; + const char *requiredItfClientName; + t_cm_instance_handle server; + const char *providedItfServerName; + t_bool traced; + const char *dataFileTrace; + t_uint32 dataFileTraceSize; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_BindComponent_t; + +typedef struct { + struct { + t_cm_instance_handle client; + const char* requiredItfClientName; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_UnbindComponent_t; + +typedef struct { + struct { + t_cm_instance_handle client; + const char* requiredItfClientName; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_BindComponentToVoid_t; + +typedef struct { + struct { + t_cm_instance_handle client; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_StartComponent_t; + +typedef struct { + struct { + t_cm_instance_handle client; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_StopComponent_t; + +typedef struct { + struct { + t_nmf_core_id coreId; + } in; + struct { + t_cm_mpc_load_counter pMpcLoadCounter; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetMpcLoadCounter_t; + +typedef struct { + struct { + t_nmf_core_id coreId; + t_cm_mpc_memory_type memType; + } in; + struct { + t_cm_allocator_status pStatus; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; /** < Out parameter */ +} CM_GetMpcMemoryStatus_t; + +typedef struct { + struct { + t_cm_instance_handle component; + t_uint32 templateNameLength; + t_uint32 localNameLength; + char *templateName; /** < Out parameter */ + char *localName; /** < Out parameter */ + } in; + struct { + t_nmf_core_id coreId; /** < Out parameter */ + t_nmf_ee_priority priority; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; /** < Out parameter */ +} CM_GetComponentDescription_t; + +typedef struct { + struct { + t_cm_instance_handle headerComponent; /** < Output parameter */ + t_cm_error error; /** < Out parameter */ + } out; /** < Out parameter */ +} CM_GetComponentListHeader_t; + +typedef struct { + struct { + t_cm_instance_handle prevComponent; + } in; + struct { + t_cm_instance_handle nextComponent; /** < Output parameter */ + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetComponentListNext_t; + +typedef struct { + struct { + t_cm_instance_handle component; + } in; + struct { + t_uint8 numberRequiredInterfaces; /** < Output parameter */ + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetComponentRequiredInterfaceNumber_t; + +typedef struct { + struct { + t_cm_instance_handle component; + t_uint8 index; + t_uint32 itfNameLength; + t_uint32 itfTypeLength; + char *itfName; /** < Out parameter */ + char *itfType; /** < Out parameter */ + } in; + struct { + t_cm_require_state requireState; /** < Out parameter */ + t_sint16 collectionSize; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetComponentRequiredInterface_t; + +typedef struct { + struct { + t_cm_instance_handle component; + const char *itfName; + t_uint32 serverItfNameLength; + char *serverItfName; /** < Out parameter */ + } in; + struct { + t_cm_instance_handle server; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetComponentRequiredInterfaceBinding_t; + +typedef struct { + struct { + t_cm_instance_handle component; + } in; + struct { + t_uint8 numberProvidedInterfaces; /** < Output parameter */ + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetComponentProvidedInterfaceNumber_t; + +typedef struct { + struct { + t_cm_instance_handle component; + t_uint8 index; + t_uint32 itfNameLength; + t_uint32 itfTypeLength; + char *itfName; /** < Out parameter */ + char *itfType; /** < Out parameter */ + } in; + struct { + t_sint16 collectionSize; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetComponentProvidedInterface_t; + +typedef struct { + struct { + t_cm_instance_handle component; + } in; + struct { + t_uint8 numberProperties; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetComponentPropertyNumber_t; + +typedef struct { + struct { + t_cm_instance_handle component; + const char *attrName; + t_uint8 index; + t_uint32 propertyNameLength; + char *propertyName; /** < Out parameter */ + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetComponentPropertyName_t; + +typedef struct { + struct { + t_cm_instance_handle component; + const char *propertyName; + t_uint32 propertyValueLength; + char *propertyValue; /** < Out parameter */ + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetComponentPropertyValue_t; + +typedef struct { + struct { + t_cm_instance_handle component; + const char *attrName; + } in; + struct { + t_uint32 value; /** < Out parameter */ + t_cm_error error; /** < Out parameter */ + } out; +} CM_ReadComponentAttribute_t; + +typedef struct { + struct { + t_cm_domain_id domainId; + } in; + struct { + t_cm_instance_handle executiveEngineHandle; + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetExecutiveEngineHandle_t; + +typedef struct { + struct { + t_cm_cmd_id aCmdID; + t_sint32 aParam; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_SetMode_t; + +typedef struct { + struct { + t_action_to_do action; + t_cm_instance_handle client; + const char *requiredItfClientName; + t_cm_instance_handle server; + const char *providedItfServerName; + char **fileList; + unsigned int listSize; + char *type; + } in; + struct { + t_uint32 methodNumber; /** < Output parameter */ + t_cm_error error; /** < Out parameter */ + } out; +} CM_GetRequiredComponentFiles_t; + +typedef struct { + struct { + const char *name; + const void *data; + t_cm_size size; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_PushComponent_t; + +typedef struct { + struct { + const char *name; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_ReleaseComponent_t; + +typedef struct { + struct { + t_cm_domain_id srcShared; + t_cm_domain_id src; + t_cm_domain_id dst; + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_Migrate_t; + +typedef struct { + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_Unmigrate_t; + +typedef struct{ + struct { + t_cm_memory_handle mem_handle; + unsigned int peripheral_addr; + unsigned int segments; + unsigned int segmentsize; + unsigned int LOS; + enum cmdma_type type; + } in; + struct { + t_cm_error error; + } out; +} CM_SetupRelinkArea_t; + +#define CM_PUSHEVENTWITHSIZE _IOWR('c', 0, CM_PushEventWithSize_t) +#define CM_GETVERSION _IOR('c', 1, t_uint32) +#define CM_INSTANTIATECOMPONENT _IOWR('c', 2, CM_InstantiateComponent_t) +#define CM_BINDCOMPONENTFROMCMCORE _IOWR('c', 3, CM_BindComponentFromCMCore_t) +#define CM_UNBINDCOMPONENTFROMCMCORE _IOWR('c', 4, CM_UnbindComponentFromCMCore_t) +#define CM_BINDCOMPONENTTOCMCORE _IOWR('c', 5, CM_BindComponentToCMCore_t) +#define CM_UNBINDCOMPONENTTOCMCORE _IOWR('c', 6, CM_UnbindComponentToCMCore_t) +#define CM_DESTROYCOMPONENT _IOWR('c', 7, CM_DestroyComponent_t) +#define CM_CREATEMEMORYDOMAIN _IOWR('c', 8, CM_CreateMemoryDomain_t) +#define CM_CREATEMEMORYDOMAINSCRATCH _IOWR('c', 9, CM_CreateMemoryDomainScratch_t) +#define CM_DESTROYMEMORYDOMAIN _IOWR('c', 10, CM_DestroyMemoryDomain_t) +#define CM_GETDOMAINCOREID _IOWR('c', 11, CM_GetDomainCoreId_t) +#define CM_ALLOCMPCMEMORY _IOWR('c', 12, CM_AllocMpcMemory_t) +#define CM_FREEMPCMEMORY _IOWR('c', 13, CM_FreeMpcMemory_t) +#define CM_BINDCOMPONENTASYNCHRONOUS _IOWR('c', 14, CM_BindComponentAsynchronous_t) +#define CM_UNBINDCOMPONENTASYNCHRONOUS _IOWR('c', 15, CM_UnbindComponentAsynchronous_t) +#define CM_BINDCOMPONENT _IOWR('c', 16, CM_BindComponent_t) +#define CM_UNBINDCOMPONENT _IOWR('c', 17, CM_UnbindComponent_t) +#define CM_BINDCOMPONENTTOVOID _IOWR('c', 18, CM_BindComponentToVoid_t) +#define CM_STARTCOMPONENT _IOWR('c', 19, CM_StartComponent_t) +#define CM_STOPCOMPONENT _IOWR('c', 20, CM_StopComponent_t) +#define CM_GETMPCLOADCOUNTER _IOWR('c', 21, CM_GetMpcLoadCounter_t) +#define CM_GETMPCMEMORYSTATUS _IOWR('c', 22, CM_GetMpcMemoryStatus_t) +#define CM_GETCOMPONENTDESCRIPTION _IOWR('c', 23, CM_GetComponentDescription_t) +#define CM_GETCOMPONENTLISTHEADER _IOWR('c', 24, CM_GetComponentListHeader_t) +#define CM_GETCOMPONENTLISTNEXT _IOWR('c', 25, CM_GetComponentListNext_t) +#define CM_GETCOMPONENTREQUIREDINTERFACENUMBER _IOWR('c', 26, CM_GetComponentRequiredInterfaceNumber_t) +#define CM_GETCOMPONENTREQUIREDINTERFACE _IOWR('c', 27, CM_GetComponentRequiredInterface_t) +#define CM_GETCOMPONENTREQUIREDINTERFACEBINDING _IOWR('c', 28, CM_GetComponentRequiredInterfaceBinding_t) +#define CM_GETCOMPONENTPROVIDEDINTERFACENUMBER _IOWR('c', 29, CM_GetComponentProvidedInterfaceNumber_t) +#define CM_GETCOMPONENTPROVIDEDINTERFACE _IOWR('c', 30, CM_GetComponentProvidedInterface_t) +#define CM_GETCOMPONENTPROPERTYNUMBER _IOWR('c', 31, CM_GetComponentPropertyNumber_t) +#define CM_GETCOMPONENTPROPERTYNAME _IOWR('c', 32, CM_GetComponentPropertyName_t) +#define CM_GETCOMPONENTPROPERTYVALUE _IOWR('c', 33, CM_GetComponentPropertyValue_t) +#define CM_READCOMPONENTATTRIBUTE _IOWR('c', 34, CM_ReadComponentAttribute_t) +#define CM_GETEXECUTIVEENGINEHANDLE _IOWR('c', 35, CM_GetExecutiveEngineHandle_t) +#define CM_SETMODE _IOWR('c', 36, CM_SetMode_t) +#define CM_GETREQUIREDCOMPONENTFILES _IOWR('c', 37, CM_GetRequiredComponentFiles_t) +#define CM_PUSHCOMPONENT _IOWR('c', 38, CM_PushComponent_t) +#define CM_FLUSHCHANNEL _IO('c', 39) +#define CM_MIGRATE _IOWR('c', 40, CM_Migrate_t) +#define CM_UNMIGRATE _IOR('c', 41, CM_Unmigrate_t) +#define CM_RELEASECOMPONENT _IOWR('c', 42, CM_ReleaseComponent_t) +#define CM_SETUPRELINKAREA _IOWR('c', 43, CM_SetupRelinkArea_t) + +#define CM_PRIVGETMPCMEMORYDESC _IOWR('c', 100, CM_PrivGetMPCMemoryDesc_t) +#define CM_PRIVRESERVEMEMORY _IOW('c', 101, unsigned int) +#define CM_PRIV_GETBOARDVERSION _IOR('c', 102, unsigned int) + +enum board_version { + U8500_V1, + U8500_V2 +}; +#endif diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c new file mode 100644 index 00000000000..04433f10f0c --- /dev/null +++ b/drivers/staging/nmf-cm/cmld.c @@ -0,0 +1,1317 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Pierre Peiffer for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +/** \file cmld.c + * + * Nomadik Multiprocessing Framework Linux Driver + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "cmioctl.h" +#include "osal-kernel.h" +#include "cmld.h" +#include "cm_service.h" + +#define CMDRIVER_PATCH_VERSION 106 +#define O_FLUSH 0x1000000 + +static int cmld_major; +static struct cdev cmld_cdev; +static struct class cmld_class = { + .name = "cm", + .owner = THIS_MODULE, +}; +const char *cmld_devname[] = CMLD_DEV_NAME; +static struct device *cmld_dev[ARRAY_SIZE(cmld_devname)]; + +/* List of per process structure (struct cm_process_priv list) */ +LIST_HEAD(process_list); +static DEFINE_MUTEX(process_lock); /* lock used to protect previous list */ +/* List of per channel structure (struct cm_channel_priv list). + A channel == One file descriptor */ +LIST_HEAD(channel_list); +static DEFINE_MUTEX(channel_lock); /* lock used to protect previous list */ + +/* Variables used to manage temporary allocation of ESRAM + reserved for DMA and B2R2 + MCDE */ +/* As of now, the reservation is done in RME */ +static int cfgESRAM_ReserveMCDE = 0; +static int cfgESRAM_ReserveDMA = 0; +static int cfgESRAMDmaSize = 4; /* in Kb */ +static int cfgESRAMMcdeSize = 128; /* in Kb */ +module_param(cfgESRAM_ReserveMCDE, bool, S_IRUGO); +module_param(cfgESRAM_ReserveDMA, bool, S_IRUGO); +module_param(cfgESRAMDmaSize, uint, S_IRUGO); +module_param(cfgESRAMMcdeSize, uint, S_IRUGO); +static t_cm_domain_id dmaDomainId, mcdeDomainId; +static t_cm_memory_handle dmaMemoryHdl, mcdeMemoryHdl; + +static inline struct cm_process_priv *getProcessPriv(void) +{ + struct list_head* head; + struct cm_process_priv *entry; + + mutex_lock(&process_lock); + + /* Look for an entry for the calling process */ + list_for_each(head, &process_list) { + entry = list_entry(head, struct cm_process_priv, entry); + if (entry->pid == current->tgid) { + kref_get(&entry->ref); + goto out; + } + } + mutex_unlock(&process_lock); + + /* Allocate, init and register a new one otherwise */ + entry = OSAL_Alloc(sizeof(*entry)); + if (entry == NULL) + return ERR_PTR(-ENOMEM); + + /* init host2mpcLock */ + mutex_init(&entry->host2mpcLock); + + INIT_LIST_HEAD(&entry->memAreaDescList); + kref_init(&entry->ref); + mutex_init(&entry->mutex); + + entry->pid = current->tgid; + mutex_lock(&process_lock); + list_add(&entry->entry, &process_list); +out: + mutex_unlock(&process_lock); + return entry; +} + +/* Free all messages */ +static inline void freeMessages(struct cm_channel_priv* channelPriv) +{ + struct osal_msg *this, *next; + int warn = 0; + + spin_lock_bh(&channelPriv->bh_lock); + plist_for_each_entry_safe(this, next, &channelPriv->messageQueue, msg_entry) { + plist_del(&this->msg_entry, &channelPriv->messageQueue); + kfree(this); + warn = 1; + } + spin_unlock_bh(&channelPriv->bh_lock); + if (warn) { + pr_err("[CM - PID=%d]: Some remaining" + " message(s) freed\n", current->tgid); + warn = 0; + } +} + +/* Free all pending memory areas and relative descriptors */ +static inline void freeMemHandles(struct cm_process_priv* processPriv) +{ + struct list_head* head, *next; + int warn = 0; + + list_for_each_safe(head, next, &processPriv->memAreaDescList) { + struct memAreaDesc_t* curr; + int err; + curr = list_entry(head, struct memAreaDesc_t, list); + err=CM_ENGINE_FreeMpcMemory(curr->handle); + if (err) + pr_err("[CM - PID=%d]: Error (%d) freeing remaining memory area " + "handle\n", current->tgid, err); + list_del(head); + OSAL_Free(curr); + warn = 1; + } + if (warn) { + pr_err("[CM - PID=%d]: Some remaining memory area " + "handle(s) freed\n", current->tgid); + warn = 0; + } +} + +/* Free any skeleton, called when freeing the process entry */ +static inline void freeSkelList(struct list_head* skelList) +{ + struct list_head* head, *next; + int warn = 0; + + /* No lock held, we know that we are the only and the last user + of the list */ + list_for_each_safe(head, next, skelList) { + t_skelwrapper* curr; + curr = list_entry(head, t_skelwrapper, entry); + list_del(head); + OSAL_Free(curr); + warn = 1; + } + if (warn) + pr_err("[CM - PID=%d]: Some remaining skeleton " + "wrapper(s) freed\n", current->tgid); +} + +/* Free any remaining channels belonging to this process */ +/* Called _only_ when freeing the process entry, once the network constructed by + this process has been destroyed. + See cmld_release() to see why there can be some remaining non-freed channels */ +static inline void freeChannels(struct cm_process_priv* processPriv) +{ + struct list_head* head, *next; + int warn = 0; + + list_for_each_safe(head, next, &channel_list) { + struct cm_channel_priv *channelPriv; + channelPriv = list_entry(head, struct cm_channel_priv, entry); + /* Only channels belonging to this process are concerned */ + if (channelPriv->proc == processPriv) { + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_del(&channelPriv->entry); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + /* Free all remaining messages if any + (normally none, but double check) */ + freeMessages(channelPriv); + + /* Free any pending skeleton wrapper */ + /* Here it's safe, we know that all bindings have been undone */ + freeSkelList(&channelPriv->skelList); + + /* Free the per-channel descriptor */ + OSAL_Free(channelPriv); + } + warn = 1; + } + if (warn) + pr_err("[CM - PID=%d]: Some remaining channel entries " + "freed\n", current->tgid); +} + +/* Free the process priv structure and all related stuff */ +/* Called only when the last ref to this structure is released */ +static void freeProcessPriv(struct kref *ref) +{ + struct cm_process_priv *entry = container_of(ref, struct cm_process_priv, ref); + t_nmf_error err; + + mutex_lock(&process_lock); + list_del(&entry->entry); + mutex_unlock(&process_lock); + + /* Destroy all remaining components */ + err=CM_ENGINE_FlushComponents(entry->pid); + if (err != NMF_OK) + pr_err("[CM - PID=%d]: Error while flushing some remaining" + " components: error=%d\n", current->tgid, err); + + freeChannels(entry); + + /* Free any pending memory areas and relative descriptors */ + freeMemHandles(entry); + + /* Destroy all remaining domains */ + err=CM_ENGINE_FlushMemoryDomains(entry->pid); + if (err != NMF_OK) + pr_err("[CM - PID=%d]: Error while flushing some remaining" + " domains: error=%d\n", current->tgid, err); + + /* Free the per-process descriptor */ + OSAL_Free(entry); +} + +/** Driver's open method + * Allocates per-process resources: private data, wait queue, + * memory area descriptors linked list, message queue. + * + * \return POSIX error code + */ +static int cmld_open(struct inode *inode, struct file *file) +{ + struct cm_process_priv *procPriv = getProcessPriv(); + + if (IS_ERR(procPriv)) + return PTR_ERR(procPriv); + + if (iminor(inode) == 0) + file->private_data = procPriv; + else { + struct cm_channel_priv *channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); + if (channelPriv == NULL) { + kref_put(&procPriv->ref, freeProcessPriv); + return -ENOMEM; + } + + channelPriv->proc = procPriv; + channelPriv->state = CHANNEL_OPEN; + + /* Initialize wait_queue, lists and mutexes */ + init_waitqueue_head(&channelPriv->waitq); + plist_head_init(&channelPriv->messageQueue, &channelPriv->bh_lock); + INIT_LIST_HEAD(&channelPriv->skelList); + spin_lock_init(&channelPriv->bh_lock); + mutex_init(&channelPriv->msgQueueLock); + mutex_init(&channelPriv->skelListLock); + + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_add(&channelPriv->entry, &channel_list); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + file->private_data = channelPriv; // store channel private struct in file descriptor + } + return 0; +} + +/** Driver's release method. + * Frees any per-process pending resource: components, bindings, memory areas. + * + * \return POSIX error code + */ +static int cmld_release(struct inode *inode, struct file *file) +{ + struct cm_process_priv* procPriv; + + BUG_ON(file->private_data == NULL); + + /* The driver must guarantee that all related resources are released. + Thus all these checks below are necessary to release all remaining + resources still linked to this 'client', in case of abnormal process + exit. + => These are error cases ! + In the usual case, nothing should be done except the free of + the cmPriv itself + */ + + if (iminor(inode) != 0) { + struct cm_channel_priv* channelPriv; + channelPriv = file->private_data; + procPriv = channelPriv->proc; + + /* We don't need to synchronize here by using the skelListLock: + the list is only accessed during ioctl() and we can't be here + if an ioctl() is on-going */ + if (list_empty(&channelPriv->skelList)) { + /* There is no pending MPC->HOST binding + => we can quietly delete the channel */ + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_del(&channelPriv->entry); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + /* Free all remaining messages if any */ + freeMessages(channelPriv); + + /* Free the per-channel descriptor */ + OSAL_Free(channelPriv); + } else { + /* Uh: there are still some MPC->HOST binding but we don't have the + required info to unbind them. + => we must keep all skel structures because possibly used in OSAL_PostDfc + (incoming callback msg) */ + /* We flag the channel as closed to discard any new msg that will never be read anyway */ + channelPriv->state = CHANNEL_CLOSED; + + /* Already Free all remaining messages if any, + they will never be read anyway */ + freeMessages(channelPriv); + } + } else + procPriv = file->private_data; + + kref_put(&procPriv->ref, freeProcessPriv); + file->private_data = NULL; + + return 0; +} + +/** Reads Component Manager messages destinated to this process. + * The message is composed by three fields: + * 1) mpc2host handle (distinguishes interfaces) + * 2) methodIndex (distinguishes interface's methods) + * 3) Variable length parameters (method's parameters values) + * + * \note cfr GetEvent() + * \return POSIX error code + */ +static ssize_t cmld_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + int err = 0; + struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); + int msgSize = 0; + struct plist_head* messageQueue; + struct osal_msg* msg; + t_os_message *os_msg = (t_os_message *)buf; + int block = !(file->f_flags & O_NONBLOCK); + + if (iminor(file->f_dentry->d_inode) == 0) + return -ENOSYS; + + BUG_ON(channelPriv == NULL); + messageQueue = &channelPriv->messageQueue; + + if (mutex_lock_killable(&channelPriv->msgQueueLock)) + return -ERESTARTSYS; +wait: + while (plist_head_empty(messageQueue)) { + mutex_unlock(&channelPriv->msgQueueLock); + if (block == 0) + return -EAGAIN; + /* Wait until there is a message to ferry up */ + if (wait_event_interruptible(channelPriv->waitq, ((!plist_head_empty(messageQueue)) || (file->f_flags & O_FLUSH)))) + return -ERESTARTSYS; + if (file->f_flags & O_FLUSH) { + file->f_flags &= ~O_FLUSH; + return 0; + } + if (mutex_lock_killable(&channelPriv->msgQueueLock)) + return -ERESTARTSYS; + } + + /* Pick up the first message from the queue, making sure that the + * hwsem tasklet does not wreak havoc the queue in the meantime + */ + spin_lock_bh(&channelPriv->bh_lock); + msg = plist_first_entry(messageQueue, struct osal_msg, msg_entry); + plist_del(&msg->msg_entry, messageQueue); + spin_unlock_bh(&channelPriv->bh_lock); + + switch (msg->msg_type) { + case MSG_INTERFACE: { + + /* Check if enough space is available */ + msgSize = sizeof(msg->msg_type) + msg->d.itf.ptrSize + sizeof(os_msg->data.itf) - sizeof(os_msg->data.itf.params) ; + if (msgSize > count) { + mutex_unlock(&channelPriv->msgQueueLock); + pr_err("CM: message size bigger than buffer size silently ignored!\n"); + err = -EMSGSIZE; + goto out; + } + + /* Copy to user message type */ + err = put_user(msg->msg_type, &os_msg->type); + if (err) goto ack_evt; + + /* Copy to user the t_nmf_mpc2host_handle */ + err = put_user(msg->d.itf.skelwrap->upperLayerThis, &os_msg->data.itf.THIS); + if (err) goto ack_evt; + + /* The methodIndex */ + err = put_user(msg->d.itf.methodIdx, &os_msg->data.itf.methodIndex); + if (err) goto ack_evt; + + /* And the parameters */ + err = copy_to_user(os_msg->data.itf.params, msg->d.itf.anyPtr, msg->d.itf.ptrSize); + + ack_evt: + /* This call is void */ + /* Note: that we cannot release the lock before having called this function + as acknowledgements MUST be executed in the same order as their + respective messages have arrived! */ + CM_ENGINE_AcknowledgeEvent(msg->d.itf.skelwrap->mpc2hostId); + + mutex_unlock(&channelPriv->msgQueueLock); + break; + } + case MSG_SERVICE: { + mutex_unlock(&channelPriv->msgQueueLock); + msgSize = sizeof(msg->msg_type) + sizeof(msg->d.srv.srvType) + + sizeof(msg->d.srv.srvData); + if (count < msgSize) { + pr_err("CM: service message size bigger than buffer size - silently ignored!\n"); + err = -EMSGSIZE; + } + + /* Copy to user message type */ + err = put_user(msg->msg_type, &os_msg->type); + if (err) goto out; + err = copy_to_user(&os_msg->data.srv, &msg->d.srv, + sizeof(msg->d.srv.srvType) + sizeof(msg->d.srv.srvData)); + break; + } + default: + mutex_unlock(&channelPriv->msgQueueLock); + pr_err("CM: invalid message type %d discarded\n", msg->msg_type); + goto wait; + } +out: + /* Destroy the message */ + kfree(msg); + + return err ? err : msgSize; +} + +/** Part of driver's release method. (ie userspace close()) + * It wakes up all waiter. + * + * \return POSIX error code + */ +static int cmld_flush(struct file *file, fl_owner_t id) +{ + if (iminor(file->f_dentry->d_inode) != 0) { + struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); + //channelPriv->closed = CHANNEL_CLOSED; + file->f_flags |= O_FLUSH; + wake_up_all(&channelPriv->waitq); + } + return 0; +} + +static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct cm_channel_priv *channelPriv = file->private_data; + + switch(cmd) { + /* + * All channel CM SYSCALL + */ + case CM_BINDCOMPONENTTOCMCORE: + return cmld_BindComponentToCMCore(channelPriv, (CM_BindComponentToCMCore_t *)arg); + case CM_FLUSHCHANNEL: + return cmld_flush(file, 0); + default: + pr_err("CM(%s): unsupported command %i\n", __func__, cmd); + return -EINVAL; + } + return 0; +} + +static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + struct cm_process_priv* procPriv = file->private_data; + switch(cmd) { + /* + * All wrapped CM SYSCALL + */ + case CM_INSTANTIATECOMPONENT: + return cmld_InstantiateComponent(procPriv, + (CM_InstantiateComponent_t *)arg); + + case CM_BINDCOMPONENTFROMCMCORE: + return cmld_BindComponentFromCMCore(procPriv, + (CM_BindComponentFromCMCore_t *)arg); + + case CM_UNBINDCOMPONENTFROMCMCORE: + return cmld_UnbindComponentFromCMCore((CM_UnbindComponentFromCMCore_t *)arg); + + case CM_UNBINDCOMPONENTTOCMCORE: + return cmld_UnbindComponentToCMCore(procPriv, (CM_UnbindComponentToCMCore_t *)arg); + + case CM_BINDCOMPONENTASYNCHRONOUS: + return cmld_BindComponentAsynchronous(procPriv, (CM_BindComponentAsynchronous_t *)arg); + + case CM_UNBINDCOMPONENTASYNCHRONOUS: + return cmld_UnbindComponentAsynchronous(procPriv, (CM_UnbindComponentAsynchronous_t *)arg); + + case CM_BINDCOMPONENT: + return cmld_BindComponent(procPriv, (CM_BindComponent_t *)arg); + + case CM_UNBINDCOMPONENT: + return cmld_UnbindComponent(procPriv, (CM_UnbindComponent_t *)arg); + + case CM_BINDCOMPONENTTOVOID: + return cmld_BindComponentToVoid(procPriv, (CM_BindComponentToVoid_t *)arg); + + case CM_DESTROYCOMPONENT: + return cmld_DestroyComponent(procPriv, (CM_DestroyComponent_t *)arg); + + case CM_CREATEMEMORYDOMAIN: + return cmld_CreateMemoryDomain(procPriv, (CM_CreateMemoryDomain_t *)arg); + + case CM_CREATEMEMORYDOMAINSCRATCH: + return cmld_CreateMemoryDomainScratch(procPriv, (CM_CreateMemoryDomainScratch_t *)arg); + + case CM_DESTROYMEMORYDOMAIN: + return cmld_DestroyMemoryDomain((CM_DestroyMemoryDomain_t *)arg); + + case CM_GETDOMAINCOREID: + return cmld_GetDomainCoreId((CM_GetDomainCoreId_t *)arg); + + case CM_ALLOCMPCMEMORY: + return cmld_AllocMpcMemory(procPriv, (CM_AllocMpcMemory_t *)arg); + + case CM_FREEMPCMEMORY: + return cmld_FreeMpcMemory(procPriv, (CM_FreeMpcMemory_t *)arg); + + case CM_GETMPCMEMORYSTATUS: + return cmld_GetMpcMemoryStatus((CM_GetMpcMemoryStatus_t *)arg); + + case CM_STARTCOMPONENT: + return cmld_StartComponent(procPriv, (CM_StartComponent_t *)arg); + + case CM_STOPCOMPONENT: + return cmld_StopComponent(procPriv, (CM_StopComponent_t *)arg); + + case CM_GETMPCLOADCOUNTER: + return cmld_GetMpcLoadCounter((CM_GetMpcLoadCounter_t *)arg); + + case CM_GETCOMPONENTDESCRIPTION: + return cmld_GetComponentDescription(procPriv, (CM_GetComponentDescription_t *)arg); + + case CM_GETCOMPONENTLISTHEADER: + return cmld_GetComponentListHeader(procPriv, (CM_GetComponentListHeader_t *)arg); + + case CM_GETCOMPONENTLISTNEXT: + return cmld_GetComponentListNext(procPriv, (CM_GetComponentListNext_t *)arg); + + case CM_GETCOMPONENTREQUIREDINTERFACENUMBER: + return cmld_GetComponentRequiredInterfaceNumber(procPriv, + (CM_GetComponentRequiredInterfaceNumber_t *)arg); + + case CM_GETCOMPONENTREQUIREDINTERFACE: + return cmld_GetComponentRequiredInterface(procPriv, + (CM_GetComponentRequiredInterface_t *)arg); + + case CM_GETCOMPONENTREQUIREDINTERFACEBINDING: + return cmld_GetComponentRequiredInterfaceBinding(procPriv, + (CM_GetComponentRequiredInterfaceBinding_t *)arg); + + case CM_GETCOMPONENTPROVIDEDINTERFACENUMBER: + return cmld_GetComponentProvidedInterfaceNumber(procPriv, + (CM_GetComponentProvidedInterfaceNumber_t *)arg); + + case CM_GETCOMPONENTPROVIDEDINTERFACE: + return cmld_GetComponentProvidedInterface(procPriv, + (CM_GetComponentProvidedInterface_t *)arg); + + case CM_GETCOMPONENTPROPERTYNUMBER: + return cmld_GetComponentPropertyNumber(procPriv, + (CM_GetComponentPropertyNumber_t *)arg); + + case CM_GETCOMPONENTPROPERTYNAME: + return cmld_GetComponentPropertyName(procPriv, + (CM_GetComponentPropertyName_t *)arg); + + case CM_GETCOMPONENTPROPERTYVALUE: + return cmld_GetComponentPropertyValue(procPriv, + (CM_GetComponentPropertyValue_t *)arg); + + case CM_READCOMPONENTATTRIBUTE: + return cmld_ReadComponentAttribute(procPriv, + (CM_ReadComponentAttribute_t *)arg); + + case CM_GETEXECUTIVEENGINEHANDLE: + return cmld_GetExecutiveEngineHandle(procPriv, + (CM_GetExecutiveEngineHandle_t *)arg); + + case CM_SETMODE: + return cmld_SetMode((CM_SetMode_t *)arg); + + case CM_GETREQUIREDCOMPONENTFILES: + return cmld_GetRequiredComponentFiles(procPriv, + (CM_GetRequiredComponentFiles_t *)arg); + + case CM_MIGRATE: + return cmld_Migrate((CM_Migrate_t *)arg); + + case CM_UNMIGRATE: + return cmld_Unmigrate((CM_Unmigrate_t *)arg); + + case CM_SETUPRELINKAREA: + return cmld_SetupRelinkArea((CM_SetupRelinkArea_t *)arg); + + case CM_PUSHCOMPONENT: + return cmld_PushComponent((CM_PushComponent_t *)arg); + + case CM_RELEASECOMPONENT: + return cmld_ReleaseComponent((CM_ReleaseComponent_t *)arg); + + /* + * NMF CALLS (Host->MPC bindings) + */ + case CM_PUSHEVENTWITHSIZE: { + CM_PushEventWithSize_t data; + t_event_params_handle event; + + /* coverity[tainted_data_argument : FALSE] */ + if (copy_from_user(&data.in, (CM_PushEventWithSize_t*)arg, sizeof(data.in))) + return -EFAULT; + + /* Take the lock to synchronize CM_ENGINE_AllocEvent() + * and CM_ENGINE_PushEvent() + */ + if (mutex_lock_killable(&procPriv->host2mpcLock)) + return -ERESTARTSYS; + + event = CM_ENGINE_AllocEvent(data.in.host2mpcId); + if (event == NULL) { + mutex_unlock(&procPriv->host2mpcLock); + return put_user(CM_PARAM_FIFO_OVERFLOW, + &((CM_PushEventWithSize_t*)arg)->out.error); + } + if (data.in.size != 0) + /* coverity[tainted_data : FALSE] */ + if (copy_from_user(event, data.in.h, data.in.size)) { + mutex_unlock(&procPriv->host2mpcLock); + return -EFAULT; // TODO: what about the already allocated and acknowledged event!?! + } + + data.out.error = CM_ENGINE_PushEvent(data.in.host2mpcId, event, data.in.methodIndex); + mutex_unlock(&procPriv->host2mpcLock); + + /* copy error value back */ + return put_user(data.out.error, &((CM_PushEventWithSize_t*)arg)->out.error); + } + + /* + * All private (internal) commands + */ + case CM_PRIVGETMPCMEMORYDESC: + return cmld_PrivGetMPCMemoryDesc(procPriv, (CM_PrivGetMPCMemoryDesc_t *)arg); + + case CM_PRIVRESERVEMEMORY: + return cmld_PrivReserveMemory(procPriv, arg); + + case CM_GETVERSION: { + t_uint32 nmfversion = NMF_VERSION; + return copy_to_user((void*)arg, &nmfversion, sizeof(nmfversion)); + } + case CM_PRIV_GETBOARDVERSION: + if (cpu_is_u8500v20_or_later()) { + enum board_version v = U8500_V2; + return copy_to_user((void*)arg, &v, sizeof(v)); + } else + return -EINVAL; + + default: { + pr_err("CM(%s): unsupported command %i\n", __func__, cmd); + return -EINVAL; + } + } + + return 0; +} + +/** Driver's ioctl method + * Implements user/kernel crossing for SYSCALL API. + * + * \return POSIX error code + */ +static long cmld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + BUG_ON(filp->private_data == NULL); + + if (iminor(filp->f_dentry->d_inode) == 0) { + return cmld_control_ctl(filp, cmd, arg); + } else { + return cmld_channel_ctl(filp, cmd, arg); + } +} + +/** VMA open callback function + */ +static void cmld_vma_open(struct vm_area_struct* vma) { + struct memAreaDesc_t* curr = (struct memAreaDesc_t*)vma->vm_private_data; + + atomic_inc(&curr->count); +} + +/** VMA close callback function + */ +static void cmld_vma_close(struct vm_area_struct* vma) { + struct memAreaDesc_t* curr = (struct memAreaDesc_t*)vma->vm_private_data; + + atomic_dec(&curr->count); +} + +static struct vm_operations_struct cmld_remap_vm_ops = { + .open = cmld_vma_open, + .close = cmld_vma_close, +}; + +/** mmap implementation. + * Remaps just once. + * + * \return POSIX error code + */ +static int cmld_mmap(struct file* file, struct vm_area_struct* vma) +{ + unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; + struct list_head* listHead; + struct list_head* cursor; + struct cm_process_priv* procPriv = file->private_data; + struct memAreaDesc_t* curr = NULL; + unsigned int vma_size = vma->vm_end-vma->vm_start; + + BUG_ON(procPriv == NULL); + + listHead = &procPriv->memAreaDescList; + + if (lock_process(procPriv)) return -ERESTARTSYS; + /* Make sure the memory area has not already been remapped */ + list_for_each(cursor, listHead) { + curr = list_entry(cursor, struct memAreaDesc_t, list); + /* For now, the user space aligns any requested physaddr to a page-size limit + This is not safe and must be fixed. But this is the only way to + minimize the allocated TCM memory, needed because of low amount of + TCM memory + Another way is to add some more check before doing this mmap() + to allow this mmap, for example. + NOTE: this memory must be first reserved via the CM_PRIVRESERVEMEMORY ioctl() + */ + if ((curr->physAddr&PAGE_MASK) == offset && + curr->tid == current->pid) { + if (curr->userLogicalAddr) { + unlock_process(procPriv); + return -EINVAL; // already mapped! + } + /* reset the thread id value, to not confuse any further mmap() */ + curr->tid = 0; + break; + } + } + + if (cursor == listHead) { + unlock_process(procPriv); + return -EINVAL; // no matching memory area descriptor found! + } + + /* Very, very important to have consistent buffer transition */ + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + vma->vm_flags |= VM_RESERVED | VM_IO | VM_DONTEXPAND | VM_DONTCOPY; + + if (remap_pfn_range(vma, vma->vm_start, offset>>PAGE_SHIFT, + vma_size, vma->vm_page_prot)) { + unlock_process(procPriv); + return -EAGAIN; + } + + /* Offset represents the physical address. + * Update the list entry filling in the logical address assigned to the user + */ + /* + * NOTE: here the useLogicalAddr is page-aligned, but not necessaly the + * phycical address. We mmap() more than originaly requested by the + * user, see in CM User Proxy (file cmsyscallwrapper.c) + */ + curr->userLogicalAddr = vma->vm_start; + + /* increment reference counter */ + atomic_inc(&curr->count); + + unlock_process(procPriv); + + /* set private data structure and callbacks */ + vma->vm_private_data = (void *)curr; + vma->vm_ops = &cmld_remap_vm_ops; + + return 0; +} + +/** MPC Events tasklet + * The parameter is used to know from which interrupts we're comming + * and which core to pass to CM_ProcessMpcEvent(): + * 0 means HSEM => ARM_CORE_ID + * otherwise, it gives the index+1 of MPC within osalEnv.mpc table + */ +static void mpc_events_tasklet_handler(unsigned long core) +{ + /* This serves internal events directly. No propagation to user space. + * Calls OSAL_PostDfc implementation for user interface events */ + if (core == 0) { + CM_ProcessMpcEvent(ARM_CORE_ID); + enable_irq(IRQ_DB8500_HSEM); + } else { + --core; + CM_ProcessMpcEvent(osalEnv.mpc[core].coreId); + enable_irq(osalEnv.mpc[core].interrupt0); + } +} + +/** Hardware semaphore and MPC interrupt handler + * 'data' param is the one given when registering the IRQ hanlder, + * contains the source core (ARM or MPC), and follows the same logic + * as for mpc_events_tasklet_handler() + * This handler is used for all IRQ handling some com (ie HSEM or + * all MPC IRQ line0) + */ +static irqreturn_t mpc_events_irq_handler(int irq, void *data) +{ + unsigned core = (unsigned)data; + + if (core != 0) + --core; + disable_irq_nosync(irq); + tasklet_schedule(&osalEnv.mpc[core].tasklet); + + return IRQ_HANDLED; +} + +/** MPC panic handler + * 'idx' contains the index of the core within the osalEnv.mpc table. + * This handler is used for all MPC IRQ line1 + */ +static irqreturn_t panic_handler(int irq, void *idx) +{ + set_bit((int)idx, &service_tasklet_data); + disable_irq_nosync(irq); + tasklet_schedule(&cmld_service_tasklet); + return IRQ_HANDLED; +} + +/** Driver's operations + */ +static struct file_operations cmld_fops = { + .owner = THIS_MODULE, + .read = cmld_read, + .unlocked_ioctl = cmld_ioctl, + .mmap = cmld_mmap, + .open = cmld_open, + .flush = cmld_flush, + .release = cmld_release, +}; + +/** + * Configure a MPC, called for each MPC to configure + * + * \param i index of the MPC to configure (refer to the index + * of the MPC within the osalEnvironment.mpc table) + * \param dataAllocId allocId of the data segment, passed through each call of + * this function, and initialized at the first call in case + * shared data segment + */ +static int configureMpc(unsigned i, t_cfg_allocator_id *dataAllocId) +{ + int err; + t_cm_system_address mpcSystemAddress; + t_nmf_memory_segment codeSegment, dataSegment; + t_cfg_allocator_id codeAllocId; + t_cm_domain_id eeDomainId; + t_cm_domain_memory eeDomain = INIT_DOMAIN; + char regulator_name[14]; + + getMpcSystemAddress(i, &mpcSystemAddress); + getMpcSdramSegments(i, &codeSegment, &dataSegment); + + /* Create code segment */ + err = CM_ENGINE_AddMpcSdramSegment(&codeSegment, &codeAllocId, "Code"); + if (err != CM_OK) { + pr_err("CM_ENGINE_AddMpcSdramSegment() error code: %d\n", err); + return -EAGAIN; + } + + /* Create data segment + * NOTE: in case of shared data segment, all MPC point to the same data segment + * (see in remapRegions()) and we need to create the segment only at first call. + * => we reuse the same allocId for the following MPCs + */ + if ((osalEnv.mpc[i].sdramDataL != osalEnv.mpc[0].sdramDataL) + || *dataAllocId == -1) { + err = CM_ENGINE_AddMpcSdramSegment(&dataSegment, dataAllocId, "Data"); + if (err != CM_OK) { + pr_err("CM_ENGINE_AddMpcSdramSegment() error code: %d\n", err); + return -EAGAIN; + } + } + + /* create default domain for the given coreId + * this serves for instanciating EE and the LoadMap, only sdram segment is present + * this domain will probably overlap with other user domains + */ + eeDomain.coreId = osalEnv.mpc[i].coreId; + eeDomain.sdramCode.offset = 0x0; + eeDomain.sdramData.offset = 0x0; + eeDomain.sdramCode.size = 0x8000; + eeDomain.sdramData.size = 0x40000; + eeDomain.esramCode.size = 0x4000; + eeDomain.esramData.size = 0x40000; + err = CM_ENGINE_CreateMemoryDomain(NMF_CORE_CLIENT, &eeDomain, &eeDomainId); + if (err != CM_OK) { + pr_err("Create EE domain on %s failed with error code: %d\n", osalEnv.mpc[i].name, err); + return -EAGAIN; + } + + err = CM_ENGINE_ConfigureMediaProcessorCore( + osalEnv.mpc[i].coreId, + osalEnv.mpc[i].eeId, + (cfgSemaphoreTypeHSEM ? SYSTEM_SEMAPHORES : LOCAL_SEMAPHORES), + osalEnv.mpc[i].nbYramBanks, + &mpcSystemAddress, + eeDomainId, + codeAllocId, + *dataAllocId); + + if (err != CM_OK) { + pr_err("CM_ConfigureMediaProcessorCore failed with error code: %d\n", err); + return -EAGAIN; + } + + // Communication channel + if (! cfgSemaphoreTypeHSEM) { + tasklet_init(&osalEnv.mpc[i].tasklet, mpc_events_tasklet_handler, i+1); + err = request_irq(osalEnv.mpc[i].interrupt0, mpc_events_irq_handler, IRQF_DISABLED, osalEnv.mpc[i].name, (void*)(i+1)); + if (err != 0) { + pr_err("CM: request_irq failed to register irq0 %i for %s (%i)\n", osalEnv.mpc[i].interrupt0, osalEnv.mpc[i].name, err); + return err; + } + } + + // Panic channel + err = request_irq(osalEnv.mpc[i].interrupt1, panic_handler, IRQF_DISABLED, osalEnv.mpc[i].name, (void*)i); + if (err != 0) { + pr_err("CM: request_irq failed to register irq1 %i for %s (%i)\n", osalEnv.mpc[i].interrupt1, osalEnv.mpc[i].name, err); + free_irq(osalEnv.mpc[i].interrupt0, (void*)(i+1)); + return err; + } + + // Retrieve the regulators used for this MPCs + sprintf(regulator_name, "%s-mmdsp", osalEnv.mpc[i].name); + osalEnv.mpc[i].mmdsp_regulator = regulator_get(cmld_dev[0], regulator_name); + if (IS_ERR(osalEnv.mpc[i].mmdsp_regulator)) { + long err = PTR_ERR(osalEnv.mpc[i].mmdsp_regulator); + pr_err("CM: Error while retrieving the regulator %s: %ld\n", regulator_name, err); + osalEnv.mpc[i].mmdsp_regulator = NULL; + return err; + } + sprintf(regulator_name, "%s-pipe", osalEnv.mpc[i].name); + osalEnv.mpc[i].pipe_regulator = regulator_get(cmld_dev[0], regulator_name); + if (IS_ERR(osalEnv.mpc[i].pipe_regulator)) { + long err = PTR_ERR(osalEnv.mpc[i].pipe_regulator); + pr_err("CM: Error while retrieving the regulator %s: %ld\n", regulator_name, err); + osalEnv.mpc[i].pipe_regulator = NULL; + return err; + } +#ifdef CONFIG_HAS_WAKELOCK + wake_lock_init(&osalEnv.mpc[i].wakelock, WAKE_LOCK_SUSPEND, osalEnv.mpc[i].name); +#endif + return 0; +} + +/* Free all used MPC irqs and clocks. + * max_mpc allows it to be called from init_module and free + * only the already configured irqs. + */ +static void free_mpc_irqs(int max_mpc) +{ + int i; + for (i=0; i for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef CMLD_H +#define CMLD_H + +#include +#include +#include +#include +#include +#include "cmioctl.h" + +/** Channel state used within the per-channel private structure 'cm_channel_priv' + */ +enum channel_state { + CHANNEL_CLOSED = 0, /**< Channel already closed */ + CHANNEL_OPEN, /**< Channel still open */ +}; + +/** Component Manager per-process private structure + * It is created the first time a process opens /dev/cm0 or /dev/cm1 + */ +struct cm_process_priv +{ + struct kref ref; /**< ref count */ + struct list_head entry; /**< This entry */ + pid_t pid; /**< pid of process owner */ + struct mutex mutex; /**< per process mutex: protect memAreaDescList */ + struct list_head memAreaDescList; /**< memAreaDesc_t list */ + struct mutex host2mpcLock; /**< used to synchronize each AllocEvent + PushEvent */ +}; + +/** Component Manager per-channel private structure + * It is created when a user opens /dev/cm1 + */ +struct cm_channel_priv +{ + enum channel_state state; /**< Channel state */ + struct list_head entry; /**< This entry */ + struct cm_process_priv *proc; /**< Pointer to the owner process structure */ + struct list_head skelList; /**< t_skelwrapper list */ + struct mutex skelListLock; /**< skelList mutex */ + struct plist_head messageQueue; /**< queueelem_t list */ + struct mutex msgQueueLock; /**< lock used to synchronize MPC to HOST bindings + in case of multiple read (see cmld_read comments) */ + spinlock_t bh_lock; /**< lock used to synchronize add/removal of element in/from + the message queue in both user context and tasklet */ + wait_queue_head_t waitq; /**< wait queue used to block read() call */ +}; + +/** Memory area descriptor. + */ +struct memAreaDesc_t { + struct list_head list; /**< Doubly linked list descriptor */ + atomic_t count; /**< Reference counter */ + pid_t tid; /**< tid of the process this area is reserved for */ + t_cm_memory_handle handle; /**< Component Manager handle */ + unsigned int size; /**< Size */ + unsigned int physAddr; /**< Physical address */ + unsigned int kernelLogicalAddr; /**< Logical address as seen by kernel */ + unsigned int userLogicalAddr; /**< Logical address as seen by user */ + unsigned int mpcPhysAddr; /**< Physicaladdress as seen by MPC */ + struct cm_process_priv* procPriv; /**< link to per process private structure */ +}; + +extern struct list_head channel_list; /**< List of all allocated channel structures */ +extern struct list_head process_list; /**< List of all allocated process private structure */ + +/** Lock/unlock per process mutex + * + * \note Must be taken before tasklet_disable (if necessary)! + */ +#define lock_process_uninterruptible(proc) (mutex_lock(&proc->mutex)) +#define lock_process(proc) (mutex_lock_killable(&proc->mutex)) +#define unlock_process(proc) (mutex_unlock(&proc->mutex)) + + + +int cmld_InstantiateComponent(struct cm_process_priv *, CM_InstantiateComponent_t __user *); +int cmld_BindComponentFromCMCore(struct cm_process_priv *, + CM_BindComponentFromCMCore_t __user *); +int cmld_UnbindComponentFromCMCore(CM_UnbindComponentFromCMCore_t __user *); +int cmld_BindComponentToCMCore(struct cm_channel_priv *, CM_BindComponentToCMCore_t __user *); +int cmld_UnbindComponentToCMCore(struct cm_process_priv*, CM_UnbindComponentToCMCore_t __user *); +int cmld_BindComponentAsynchronous(struct cm_process_priv*, CM_BindComponentAsynchronous_t __user *); +int cmld_UnbindComponentAsynchronous(struct cm_process_priv*, CM_UnbindComponentAsynchronous_t __user *); +int cmld_BindComponent(struct cm_process_priv*, CM_BindComponent_t __user *); +int cmld_UnbindComponent(struct cm_process_priv*, CM_UnbindComponent_t __user *); +int cmld_BindComponentToVoid(struct cm_process_priv*, CM_BindComponentToVoid_t __user *); +int cmld_DestroyComponent(struct cm_process_priv*, CM_DestroyComponent_t __user *); +int cmld_CreateMemoryDomain(struct cm_process_priv*, CM_CreateMemoryDomain_t __user *); +int cmld_CreateMemoryDomainScratch(struct cm_process_priv*, CM_CreateMemoryDomainScratch_t __user *); +int cmld_DestroyMemoryDomain(CM_DestroyMemoryDomain_t __user *); +int cmld_GetDomainCoreId(CM_GetDomainCoreId_t __user *); +int cmld_AllocMpcMemory(struct cm_process_priv *, CM_AllocMpcMemory_t __user *); +int cmld_FreeMpcMemory(struct cm_process_priv *, CM_FreeMpcMemory_t __user *); +int cmld_GetMpcMemoryStatus(CM_GetMpcMemoryStatus_t __user *); +int cmld_StartComponent(struct cm_process_priv *, CM_StartComponent_t __user *); +int cmld_StopComponent(struct cm_process_priv *, CM_StopComponent_t __user *); +int cmld_GetMpcLoadCounter(CM_GetMpcLoadCounter_t __user *); +int cmld_GetComponentDescription(struct cm_process_priv *, CM_GetComponentDescription_t __user *); +int cmld_GetComponentListHeader(struct cm_process_priv *, CM_GetComponentListHeader_t __user *); +int cmld_GetComponentListNext(struct cm_process_priv *, CM_GetComponentListNext_t __user *); +int cmld_GetComponentRequiredInterfaceNumber(struct cm_process_priv *, + CM_GetComponentRequiredInterfaceNumber_t __user *); +int cmld_GetComponentRequiredInterface(struct cm_process_priv *, + CM_GetComponentRequiredInterface_t __user *); +int cmld_GetComponentRequiredInterfaceBinding(struct cm_process_priv *, + CM_GetComponentRequiredInterfaceBinding_t __user *); +int cmld_GetComponentProvidedInterfaceNumber(struct cm_process_priv *, + CM_GetComponentProvidedInterfaceNumber_t __user *); +int cmld_GetComponentProvidedInterface(struct cm_process_priv *, + CM_GetComponentProvidedInterface_t __user *); +int cmld_GetComponentPropertyNumber(struct cm_process_priv *, + CM_GetComponentPropertyNumber_t __user *); +int cmld_GetComponentPropertyName(struct cm_process_priv *, CM_GetComponentPropertyName_t __user *); +int cmld_GetComponentPropertyValue(struct cm_process_priv *, CM_GetComponentPropertyValue_t __user *); +int cmld_ReadComponentAttribute(struct cm_process_priv *, CM_ReadComponentAttribute_t __user *); +int cmld_GetExecutiveEngineHandle(struct cm_process_priv *, CM_GetExecutiveEngineHandle_t __user *); +int cmld_SetMode(CM_SetMode_t __user *); +int cmld_GetRequiredComponentFiles(struct cm_process_priv *cmPriv, + CM_GetRequiredComponentFiles_t __user *); +int cmld_Migrate(CM_Migrate_t __user *); +int cmld_Unmigrate(CM_Unmigrate_t __user *); +int cmld_SetupRelinkArea(CM_SetupRelinkArea_t __user *); +int cmld_PushComponent(CM_PushComponent_t __user *); +int cmld_ReleaseComponent(CM_ReleaseComponent_t __user *); +int cmld_PrivGetMPCMemoryDesc(struct cm_process_priv *, CM_PrivGetMPCMemoryDesc_t __user *); +int cmld_PrivReserveMemory(struct cm_process_priv *, unsigned int); +#endif diff --git a/drivers/staging/nmf-cm/configuration.c b/drivers/staging/nmf-cm/configuration.c new file mode 100644 index 00000000000..175b6152b40 --- /dev/null +++ b/drivers/staging/nmf-cm/configuration.c @@ -0,0 +1,115 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Pierre Peiffer for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +/** \file configuration.c + * + * Nomadik Multiprocessing Framework Linux Driver + * + */ + +#include +#include + +#include "osal-kernel.h" + +/* Per-driver environment */ +struct OsalEnvironment osalEnv = +{ + .mpc = { + { + .coreId = SVA_CORE_ID, + .name = "sva", + .baseP = (void*)SVA_BASE_ADDR, + .interrupt0 = IRQ_DB8500_SVA, + .interrupt1 = IRQ_DB8500_SVA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmemCode = NULL, + .hwmemData = NULL, + }, + { + .coreId = SIA_CORE_ID, + .name = "sia", + .baseP = (void*)SIA_BASE_ADDR, + .interrupt0 = IRQ_DB8500_SIA, + .interrupt1 = IRQ_DB8500_SIA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmemCode = NULL, + .hwmemData = NULL, + } + }, + .esram_regulator = { NULL, NULL}, + .dsp_sleep = { + .sia_auto_pm_enable = PRCMU_AUTO_PM_OFF, + .sia_power_on = 0, + .sia_policy = PRCMU_AUTO_PM_POLICY_DSP_OFF_HWP_OFF, + .sva_auto_pm_enable = PRCMU_AUTO_PM_OFF, + .sva_power_on = 0, + .sva_policy = PRCMU_AUTO_PM_POLICY_DSP_OFF_HWP_OFF, + }, + .dsp_idle = { + .sia_auto_pm_enable = PRCMU_AUTO_PM_OFF, + .sia_power_on = 0, + .sia_policy = PRCMU_AUTO_PM_POLICY_DSP_OFF_HWP_OFF, + .sva_auto_pm_enable = PRCMU_AUTO_PM_OFF, + .sva_power_on = 0, + .sva_policy = PRCMU_AUTO_PM_POLICY_DSP_OFF_HWP_OFF, + }, +}; + +module_param_call(cm_debug_level, param_set_int, param_get_int, + &cm_debug_level, S_IWUSR|S_IRUGO); +MODULE_PARM_DESC(cm_debug_level, "Debug level of NMF Core"); + +module_param_call(cm_error_break, param_set_bool, param_get_bool, + &cm_error_break, S_IWUSR|S_IRUGO); +MODULE_PARM_DESC(cm_error_break, "Stop on error (in an infinite loop, for debugging purpose)"); + +module_param_call(cmIntensiveCheckState, param_set_bool, param_get_bool, + &cmIntensiveCheckState, S_IWUSR|S_IRUGO); +MODULE_PARM_DESC(cmIntensiveCheckState, "Add additional intensive checks"); + +DECLARE_MPC_PARAM(SVA, SDRAM_DATA_SIZE, "", 1); + +DECLARE_MPC_PARAM(SIA, 0, "\n\t\t\t(0 means shared with SVA)", 2); + +int cfgCommunicationLocationInSDRAM = 1; +module_param(cfgCommunicationLocationInSDRAM, bool, S_IRUGO); +MODULE_PARM_DESC(cfgCommunicationLocationInSDRAM, "Location of communications (SDRAM or ESRAM)"); + +int cfgSemaphoreTypeHSEM = 1; +module_param(cfgSemaphoreTypeHSEM, bool, S_IRUGO); +MODULE_PARM_DESC(cfgSemaphoreTypeHSEM, "Semaphore used (HSEM or LSEM)"); + +int cfgESRAMSize = ESRAM_SIZE; +module_param(cfgESRAMSize, uint, S_IRUGO); +MODULE_PARM_DESC(cfgESRAMSize, "Size of ESRAM used in the CM (in Kb)"); + +int init_config(void) +{ + if (cfgMpcSDRAMCodeSize_SVA == 0 || cfgMpcSDRAMCodeSize_SIA == 0) { + pr_err("SDRAM code size must be greater than 0\n"); + return -EINVAL; + } + + if (cfgMpcSDRAMDataSize_SVA == 0) { + pr_err("SDRAM data size for SVA must be greater than 0\n"); + return -EINVAL; + } + osalEnv.mpc[SVA].nbYramBanks = cfgMpcYBanks_SVA; + osalEnv.mpc[SVA].eeId = cfgSchedulerTypeHybrid_SVA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; + osalEnv.mpc[SVA].sdramCodeSize = cfgMpcSDRAMCodeSize_SVA * ONE_KB; + osalEnv.mpc[SVA].sdramDataSize = cfgMpcSDRAMDataSize_SVA * ONE_KB; + osalEnv.mpc[SIA].nbYramBanks = cfgMpcYBanks_SIA; + osalEnv.mpc[SIA].eeId = cfgSchedulerTypeHybrid_SIA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; + osalEnv.mpc[SIA].sdramCodeSize = cfgMpcSDRAMCodeSize_SIA * ONE_KB; + osalEnv.mpc[SIA].sdramDataSize = cfgMpcSDRAMDataSize_SIA * ONE_KB; + + return 0; +} diff --git a/drivers/staging/nmf-cm/configuration.h b/drivers/staging/nmf-cm/configuration.h new file mode 100644 index 00000000000..a3bc1ca9063 --- /dev/null +++ b/drivers/staging/nmf-cm/configuration.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Pierre Peiffer for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef CONFIGURATION_H +#define CONFIGURATION_H + +/** Peripherals description. + * Some of these values are taken from kernel header description (which should be the + * right place of these definition); the missing ones are defined here. + */ + +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) +#include +#else +#include +#endif + +/** Nomadik embedded Static RAM base address*/ +#define ESRAM_BASE (U8500_ESRAM_BASE + 0x10000) // V1/V2 config: 0-64k: secure; +#define HWSEM_BASE U8500_HSEM_BASE + +/** SxA base address */ +#define SVA_BASE_ADDR U8500_SVA_BASE +#define SIA_BASE_ADDR U8500_SIA_BASE + +/** Nomadik embedded ram size for CM (in Kb) */ +#define ESRAM_SIZE 576 +enum { + ESRAM_12, + ESRAM_34, + NB_ESRAM, +}; + +/** MPCs */ +enum { + SVA, + SIA, + NB_MPC, +}; +#define COREIDX(id) (id-1) + +/** Base address of shared SDRAM: use upper SDRAM. We reserve a rather */ +#define SDRAM_CODE_SIZE_SVA (2*ONE_KB) +#define SDRAM_CODE_SIZE_SIA (2*ONE_KB) +#define SDRAM_DATA_SIZE (8*ONE_KB) + +extern int cfgCommunicationLocationInSDRAM; +extern int cfgSemaphoreTypeHSEM; +extern int cfgESRAMSize; + +int init_config(void); + +#define DECLARE_MPC_PARAM(mpc, sdramDataSize, extension, ybank) \ + static unsigned int cfgMpcYBanks_##mpc = ybank; \ + module_param(cfgMpcYBanks_##mpc, uint, S_IRUGO); \ + MODULE_PARM_DESC(cfgMpcYBanks_##mpc, "Nb of Y-Ram banks used on " #mpc); \ + \ + static int cfgSchedulerTypeHybrid_##mpc = 1; \ + module_param(cfgSchedulerTypeHybrid_##mpc, bool, S_IRUGO); \ + MODULE_PARM_DESC(cfgSchedulerTypeHybrid_##mpc, "Scheduler used on " #mpc " (Hybrid or Synchronous)"); \ + \ + static unsigned int cfgMpcSDRAMCodeSize_##mpc = SDRAM_CODE_SIZE_##mpc; \ + module_param(cfgMpcSDRAMCodeSize_##mpc, uint, S_IRUGO); \ + MODULE_PARM_DESC(cfgMpcSDRAMCodeSize_##mpc, "Size of code segment on " #mpc " (in Kb)"); \ + \ + static unsigned int cfgMpcSDRAMDataSize_##mpc = sdramDataSize; \ + module_param(cfgMpcSDRAMDataSize_##mpc, uint, S_IRUGO); \ + MODULE_PARM_DESC(cfgMpcSDRAMDataSize_##mpc, "Size of data segment on " #mpc " (in Kb)" extension) + +#endif diff --git a/drivers/staging/nmf-cm/ee/api/ee.h b/drivers/staging/nmf-cm/ee/api/ee.h new file mode 100644 index 00000000000..bde3cee9425 --- /dev/null +++ b/drivers/staging/nmf-cm/ee/api/ee.h @@ -0,0 +1,197 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +/*! + * \defgroup HOSTEE_MODULE Host Execution Engine + */ + +/*! + * \defgroup HOSTEE Host Execution Engine API + * \ingroup HOSTEE_MODULE + */ + +#ifndef HOST_EE_H +#define HOST_EE_H + + +#include + +#include +#include + +#include + +/*! + * \brief Get the version of the NMF Host EE at runtime + * + * This method should be used to query the version number of the + * NMF Component Manager engine at runtime. This is useful when using + * to check if version of the engine linked with application correspond + * to engine used for development. + * + * Such code can be used to check compatibility: \code + t_uint32 nmfversion; + + // Print NMF version + EE_GetVersion(&nmfversion); + LOG("NMF Version %d-%d-%d\n", + VERSION_MAJOR(nmfversion), + VERSION_MINOR(nmfversion), + VERSION_PATCH(nmfversion)); + if(NMF_VERSION != nmfversion) { + LOG("Error: Incompatible API version %d != %d\n", NMF_VERSION, nmfversion); + EXIT(); + } + * \endcode + * + * \param[out] version Internal hardcoded version (use \ref VERSION_MAJOR, \ref VERSION_MINOR, \ref VERSION_PATCH macros to decode it). + * + * \ingroup HOSTEE + */ +PUBLIC IMPORT_SHARED void EE_GetVersion(t_uint32 *version); + +/*! + * \brief Set the mode of the Host EE. + * + * According the (\ref t_ee_cmd_id) value, this routine allows to modify dynamically the behavior of the Host EE. + * + * \param[in] aCmdID Command ID. + * \param[in] aParam Parameter of command ID if required. + * + * \ingroup HOSTEE + */ +PUBLIC IMPORT_SHARED t_nmf_error EE_SetMode(t_ee_cmd_id aCmdID, t_sint32 aParam); + +/*! + * \brief Create a channel for communication between host ee and user. + * + * The purpose of the function is to: + * - create a channel or get a channel, regarding the flag parameter + * + * \param[in] flags Whether the caller want to create a new channel (CHANNEL_PRIVATE) + * or use the shared one (CHANNEL_PRIVATE) (it will be created + * if it does not yet exist) + * \param[out] channel Channel number. + * + * \exception NMF_NO_MORE_MEMORY Not enough memory to create the callback Channel. + * \exception NMF_INVALID_PARAMETER The specified flags is invalid. + * + * \ingroup HOSTEE + */ +PUBLIC IMPORT_SHARED t_nmf_error EE_CreateChannel(t_nmf_channel_flag flags, t_nmf_channel *channel); + +/*! + * \brief Flush a channel to allow user to safely close it. + * + * The purpose of the function is to allow safe call of EE_CloseChannel() later on. Calling + * EE_FlushChannel() will allow a blocking call to EE_GetMessage() to exit with an error + * NMF_FLUSH_MESSAGE. After EE_GetMessage() has exit with such a value user must no more + * call EE_GetMessage() and can safely call EE_CloseChannel() that will destroy channel. + * In case of the share channel EE_FlushChannel() will return false for isFlushMessageGenerated if + * it's internal reference counter is not zero, in that case no NMF_FLUSH_MESSAGE error is return + * by EE_GetMessage() and user can immediatly call EE_CloseChannel(). + * In case user know that no usage of channel is done when he want to destroy channel, call to this api + * is optionnal and user can safely call EE_CloseChannel(). + * + * \param[in] channel Channel number + * \param[out] isFlushMessageGenerated Allow user to know if it must wait for NMF_FLUSH_MESSAGE return + * of EE_GetMessage() before calling EE_CloseChannel() + * + * \exception NMF_INVALID_PARAMETER The specified flags is invalid. + * + * \ingroup HOSTEE + */ +PUBLIC IMPORT_SHARED t_nmf_error EE_FlushChannel(t_nmf_channel channel, t_bool *isFlushMessageGenerated); + +/*! + * \brief Unregister channel + * + * The purpose of the function is to: + * - destroy a channel from the user to the Host ee. + * + * The user must call EE_UserDone() as many time as EE_UserInit(). + * At the last EE_UserDone() call, the channel is closed and definitely destroyed + * All service callback must be unregistered first. + * + * \param[in] channel Channel number: + * + * \ingroup HOSTEE + */ +PUBLIC IMPORT_SHARED t_nmf_error EE_CloseChannel(t_nmf_channel channel); + +/*! + * \brief Register a service callback to this channel. + * + * \param[in] channel The channel on which the callback must be registered. + * \param[in] handler The given callback. + * \param[in] contextHandler The context associated with this callback. + * + * \exception NMF_NO_MORE_MEMORY Not enough memory to associate service with the Channel. + * + * \ingroup HOSTEE + */ +PUBLIC IMPORT_SHARED t_nmf_error EE_RegisterService(t_nmf_channel channel, t_nmf_serviceCallback handler, void *contextHandler); + +/*! + * \brief Unregister a service callback from this channel. + * + * \param[in] channel The channel on which the callback must be registered. + * \param[in] handler The given callback. + * \param[in] contextHandler The context associated with this callback. + * + * \exception NMF_INVALID_PARAMETER The channel or the callback doesn't exist. + * + * \ingroup HOSTEE + */ +PUBLIC IMPORT_SHARED t_nmf_error EE_UnregisterService(t_nmf_channel channel, t_nmf_serviceCallback handler, void *contextHandler); + +/*! + * \brief Unregister a notify callback for this channel. + * + * This method will register a callback that will be call each time a message has + * been push in queue of the channel. + * To unregister your callback just register a null notify. + * + * \param[in] channel The channel on which the callback must be registered. + * \param[in] notify The given callback. + * \param[in] contextHandler The context associated with this callback. + * + * \ingroup HOSTEE + */ +PUBLIC IMPORT_SHARED t_nmf_error EE_RegisterNotify(t_nmf_channel channel, t_nmf_notify notify, void *contextHandler); + +/*! + * \brief Get received message from specified callback channel. + * + * This method can be used to retrieve callback message from Host ee. Returned message could then + * be dispatch through EE_ExecuteMessage. + * + * \param[in] channel The channel from which the message must be retrieved + * \param[out] clientContext client context. + * \param[out] message Reference on buffer to be unmarshalled. The buffer is allocated internally. + * \param[in] blockable Indicate if the call could blocked or not. + * + * \exception NMF_NO_MESSAGE No waited message. + * \exception NMF_INVALID_PARAMETER At least one input parameters is invalid + * + * \ingroup HOSTEE + */ +PUBLIC IMPORT_SHARED t_nmf_error EE_GetMessage(t_nmf_channel channel, void **clientContext, char **message, t_bool blockable); + +/*! + * \brief Execute a message. User callback will be execute. + * + * This method allow the message retrieved through EE_GetMessage to the right user callback. + * + * \param[in] itfref Interface reference. + * \param[in] message Reference on buffer to be unmarshalled. + * + * \ingroup HOSTEE + */ +PUBLIC IMPORT_SHARED void EE_ExecuteMessage(void *itfref, char *message); + +#endif diff --git a/drivers/staging/nmf-cm/ee/api/ee_type.h b/drivers/staging/nmf-cm/ee/api/ee_type.h new file mode 100644 index 00000000000..368cd6d29ba --- /dev/null +++ b/drivers/staging/nmf-cm/ee/api/ee_type.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef HOST_EE_TYPE_H +#define HOST_EE_TYPE_H + +/*! + * \brief Notify callback method type. + * + * \ingroup HOSTEE + */ +typedef void (*t_nmf_notify)(void *contextHandler); + +/*! + * \brief Definition of the command ID type + */ +typedef t_uint32 t_ee_cmd_id; + +/*! + * \brief Definition of the command ID + */ +typedef enum { + EE_CMD_TRACE_ON, //!< Enable tracing and force network resetting and dumping + EE_CMD_TRACE_OFF //!< Disable tracing +} t_ee_cmd_idDescription; + + +#endif diff --git a/drivers/staging/nmf-cm/ee/api/list.idt b/drivers/staging/nmf-cm/ee/api/list.idt new file mode 100644 index 00000000000..a53a39734d8 --- /dev/null +++ b/drivers/staging/nmf-cm/ee/api/list.idt @@ -0,0 +1,18 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef LIST_IDT +#define LIST_IDT + +/* linking elem */ +struct _t_list_link { + struct _t_list_link *pNext; +}; +typedef struct _t_list_link t_list_link; + +#endif + diff --git a/drivers/staging/nmf-cm/ee/api/outnotify.h b/drivers/staging/nmf-cm/ee/api/outnotify.h new file mode 100644 index 00000000000..c88185fac16 --- /dev/null +++ b/drivers/staging/nmf-cm/ee/api/outnotify.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef OUT_IDT +#define OUT_IDT + +typedef void (*t_nmf_notify)(void *contextHandler); + +#endif + diff --git a/drivers/staging/nmf-cm/ee/api/panic.idt b/drivers/staging/nmf-cm/ee/api/panic.idt new file mode 100644 index 00000000000..612dfcc8b4b --- /dev/null +++ b/drivers/staging/nmf-cm/ee/api/panic.idt @@ -0,0 +1,73 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \defgroup NMF_EE_TYPE Execution Engine Common Type Definitions + * \ingroup COMMON + */ + +#ifndef __INC_PANIC_IDT +#define __INC_PANIC_IDT + +/*! + * \brief Panic reason type + * + * For values, see \ref t_panic_reasonDescription. + * + * \ingroup NMF_EE_TYPE + */ +typedef t_uint8 t_panic_reason; + +/*! + * \brief The different panic reasons + * + * \verbatim + * Reason | Information | Behavior + * ------------------------------------------------------------------- + * INTERNAL_PANIC | Not interpreted | Fatal panic, stop MPC + * USER_STACK_OVERFLOW | Faulting address & SPu | Fatal panic, stop MPC + * SYSTEM_STACK_OVERFLOW | Faulting address & SPu | Fatal panic, stop MPC + * UNALIGNED_LONG_ACCESS | Indicative Faulting address & SPu | Fatal panic, stop MPC + * EVENT_FIFO_OVERFLOW | 0 | Abort current task, stop MPC + * PARAM_FIFO_OVERFLOW | 0 | idem + * INTERFACE_NOT_BINDED | 0 | idem + * USER_PANIC | Not interpreted | idem + * UNBIND_INTERRUPT | Interrupt number | Do nothing, just return from interrupt. + * EVENT_FIFO_IN_USE | Destroy event Fifo while event already schedule (only for HostEE) + * \endverbatim + * + * \ingroup NMF_EE_TYPE + */ +typedef enum { + INTERNAL_PANIC = 1, + RESERVED_PANIC = 2, + USER_STACK_OVERFLOW = 3, + SYSTEM_STACK_OVERFLOW = 4, + UNALIGNED_LONG_ACCESS = 5, + EVENT_FIFO_OVERFLOW = 6, + PARAM_FIFO_OVERFLOW = 7, + INTERFACE_NOT_BINDED = 8, + USER_PANIC = 9, + UNBIND_INTERRUPT = 10, + EVENT_FIFO_IN_USE = 11 +} t_panic_reasonDescription; + +/*! + * \brief Define the source of the panic + * + * It indicates the source core of the panic message.\n + * It gives the member to use within \ref t_nmf_panic_data (which is a member of the t_nmf_service_data service data structure). + + * \ingroup NMF_EE_TYPE + */ +typedef enum { + HOST_EE, //!< If the source is the Executive Engine running on the ARM Core + MPC_EE //!< If the source is the Executive Engine running on one of the MPC Core +} t_panic_source; + +#endif diff --git a/drivers/staging/nmf-cm/ee/api/priority.idt b/drivers/staging/nmf-cm/ee/api/priority.idt new file mode 100644 index 00000000000..a276ba57727 --- /dev/null +++ b/drivers/staging/nmf-cm/ee/api/priority.idt @@ -0,0 +1,24 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef PRIORITY_IDT +#define PRIORITY_IDT + +/** + * 0 : background + * 1 : normal + * 2 : urgent + * 3 : + * 4 : CScall + * 5 : CScall + * 6 : IO (not linked with priority ordering) + */ +#define MAX_SCHEDULER_PRIORITY_NUMBER 7 +#define MAX_SCHEDULER_SUBPRIORITY_NUMBER 4 + +#endif + diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h new file mode 100644 index 00000000000..345c8256212 --- /dev/null +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + /*! + * \brief NMF Version. + * + * This file contains the NMF Version. + * + * \defgroup NMF_VERSION NMF Version + * \ingroup COMMON + */ + +#ifndef __INC_NMF_DEF_H +#define __INC_NMF_DEF_H + +/*! + * \brief Current NMF version number + * + * \ingroup NMF_VERSION + */ +#define NMF_VERSION ((2 << 16) | (10 << 8) | (106)) + +/*! + * \brief Get NMF major version corresponding to NMF version number + * \ingroup NMF_VERSION + */ +#define VERSION_MAJOR(version) (((version) >> 16) & 0xFF) +/*! + * \brief Get NMF minor version corresponding to NMF version number + * \ingroup NMF_VERSION + */ +#define VERSION_MINOR(version) (((version) >> 8) & 0xFF) +/*! + * \brief Get NMF patch version corresponding to NMF version number + * \ingroup NMF_VERSION + */ +#define VERSION_PATCH(version) (((version) >> 0) & 0xFF) + +#endif /* __INC_NMF_DEF_H */ diff --git a/drivers/staging/nmf-cm/inc/nmf-limits.h b/drivers/staging/nmf-cm/inc/nmf-limits.h new file mode 100644 index 00000000000..a942e542233 --- /dev/null +++ b/drivers/staging/nmf-cm/inc/nmf-limits.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Common Nomadik Multiprocessing Framework limits definition + * + * This file contains the limit definitions used into NMF. + * + * \warning Don't modify it since it is also hardcoded in tools + * + * \defgroup NMF_LIMITS NMF limits definition + * \ingroup COMMON + */ +#ifndef __INC_NMF_LIMITS_H +#define __INC_NMF_LIMITS_H + +/*! + * \brief Maximum interface name length + * + * Define the maximum interface name length allowed by NMF. + * + * \ingroup NMF_LIMITS + */ +#define MAX_INTERFACE_NAME_LENGTH 32 + +/*! + * \brief Maximum interface method name length + * + * Define the maximum interface method name length allowed by NMF. + * + * \ingroup NMF_LIMITS + */ +#define MAX_INTERFACE_METHOD_NAME_LENGTH 64 + +/*! + * \brief Maximum interface type name length + * + * Define the maximum interface type name length allowed by NMF. + * + * \ingroup NMF_LIMITS + */ +#define MAX_INTERFACE_TYPE_NAME_LENGTH 128 + + +/*! + * \brief Maximum template name length + * + * Define the maximum template name length allowed by NMF. + * + * \ingroup NMF_LIMITS + */ +#define MAX_TEMPLATE_NAME_LENGTH 128 + +/*! + * \brief Maximum component local name length + * + * Define the maximum component local name length inside a composite component allowed by NMF. + * + * \ingroup NMF_LIMITS + */ +#define MAX_COMPONENT_NAME_LENGTH 32 + +/*! + * \brief Maximum property name length + * + * Define the maximum property name length allowed by NMF. + * + * \ingroup NMF_LIMITS + */ +#define MAX_PROPERTY_NAME_LENGTH 32 + +/*! + * \brief Maximum property value length + * + * Define the maximum property value length allowed by NMF. + * + * \ingroup NMF_LIMITS + */ +#define MAX_PROPERTY_VALUE_LENGTH 128 + +/*! + * \brief Maximum attribute name length + * + * Define the maximum attribute name length allowed by NMF. + * + * \ingroup NMF_LIMITS + */ +#define MAX_ATTRIBUTE_NAME_LENGTH 32 + +/*! + * \brief Maximum fifo size allowed for binding component + * + * Define the maximum fifo size allowed for binding component allowed by NMF when calling + * CM_BindComponentFromHost and CM_BindComponentAsynchronous. + * + * \ingroup NMF_LIMITS + */ +#define MAX_COMMUNICATION_FIFO_SIZE 256 + +#define MAX_COMPONENT_FILE_PATH_LENGTH 1024 + +#endif /* __INC_NMF_LIMITS_H */ diff --git a/drivers/staging/nmf-cm/inc/nmf-tracedescription.h b/drivers/staging/nmf-cm/inc/nmf-tracedescription.h new file mode 100644 index 00000000000..9611803b978 --- /dev/null +++ b/drivers/staging/nmf-cm/inc/nmf-tracedescription.h @@ -0,0 +1,324 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief NMF xti/stm trace format description + * + * \defgroup NMF_TRACE_FORMAT NMF xti/stm trace format description + * + * The NMF trace is output by either xti ip on 8815 or stm ip on 8820 and 8500. + * Each type of trace is output on a dedicated channel. Following is a description + * of each of this traces. + * + * Traces have generally a timestamp added by hardware but is not described here. + * \ingroup NMF_ABI + */ +#ifndef TRACE_FORMAT_H_ +#define TRACE_FORMAT_H_ + +#include + +/*! + * \brief XTI/STM Channel where trace are dumped + * + * \note This type is only for defining constants, please not reference it. + * + * \note Ever if this format is able to be generated on same channel, Host EE & CM channel are separated + * in order to avoir concurrency and access STM IP without require mutual exclusion. + * + * \ingroup NMF_TRACE_FORMAT + */ +typedef enum { + MPC_EE_CHANNEL = 100, //!< MPC EE channel (MPC activity) in 32bits bundle + CM_CHANNEL = 101, //!< CM channel (MPC deployment) in 64bits bundle + HOST_EE_CHANNEL = 151 //!< Host EE channel (deployment & activity) in 64bits bundle +} t_nmfTraceChannelDescription; + +/*! + * \brief Message trace type + * + * \note This type is only for defining constants, please not reference it. + * + * \ingroup NMF_TRACE_FORMAT + */ +typedef enum { + TRACE_TYPE_RESET = 1, //!< Reset trace type + TRACE_TYPE_COMPONENT = 2, //!< Component instantiate trace type + TRACE_TYPE_BIND = 3, //!< Component bind trace type + TRACE_TYPE_METHOD = 4, //!< Component method trace type + TRACE_TYPE_ACTIVITY = 5, //!< Activity trace type + TRACE_TYPE_PANIC = 6, //!< Panic trace type + TRACE_TYPE_COMMUNICATION = 7, //!< Communication trace type + TRACE_TYPE_ALLOCATOR = 8, //!< Allocator trace type + TRACE_TYPE_ALLOC = 9, //!< Alloc trace type + TRACE_TYPE_USER = 10 //!< User trace type +} t_nmfTraceTypeDescription; + +#define TRACE_MAJOR_VERSION 1 //!< Current major trace version number \ingroup NMF_TRACE_FORMAT +#define TRACE_MINOR_VERSION 2 //!< Current minor trace version number \ingroup NMF_TRACE_FORMAT + +/*! + * \brief Trace header description. + * + * \note XTI will add 64bits time-stamp in first field of this structure, but not generated by us ! + * + * \ingroup NMF_TRACE_FORMAT + */ +struct t_nmfTraceChannelHeader { + // t_uint64 timeStamp; + t_uint8 traceType; //!< Trace type + t_uint8 reserved; + t_uint16 traceSize; //!< Trace size (depending on trace type description) +}; + +/*! + * \brief Trace header union + * + * The purpose of this is to optimize header setting in one instruction. + * + * \ingroup NMF_TRACE_FORMAT + */ +typedef union { + struct t_nmfTraceChannelHeader s; + t_uint32 v; +} t_nmfTraceChannelHeaderUnion; + + +/*! + * \brief Trace reset description + * + * Inform tools to reset their internal state because network will be dumped new time. + * + * \ingroup NMF_TRACE_FORMAT + */ +struct t_nmfTraceReset { + t_nmfTraceChannelHeaderUnion header; //!< Trace header + + t_uint16 minorVersion; //!< NMF trace format minor version + t_uint16 majorVersion; //!< NMF trace format major version +}; + +/** + * \brief Component instantiation trace command description + * + * \ingroup NMF_TRACE_FORMAT + */ +typedef enum { + TRACE_COMPONENT_COMMAND_ADD = 0x1, + TRACE_COMPONENT_COMMAND_REMOVE = 0x2 +} t_nmfTraceComponentCommandDescription; + + +/*! + * \brief Component instantiation trace description + * + * Component instantiation trace is generated each time an instance of a component is added or removed. + * + * \ingroup NMF_TRACE_FORMAT + */ +struct t_nmfTraceComponent { + t_nmfTraceChannelHeaderUnion header; //!< Trace header + + t_uint16 command; //!< See \ref t_nmfTraceComponentCommandDescription + t_uint16 domainId; //!< In CM: 0x01:Arm | 0x02:SAA | 0x03:SVA | 0x04:SIA, in SMPEE: 0x1 + t_uint32 componentContext; //!< Component context belonging domain (DSP this or ARM class this) + t_uint32 componentUserContext; //!< User friendly component Id belonging the channel (CM handle or ARM class this) + t_uint8 componentLocalName[MAX_COMPONENT_NAME_LENGTH]; //!< local name of component as given by user (null terminated) + t_uint8 componentTemplateName[MAX_TEMPLATE_NAME_LENGTH];//!< template name of component (null terminated) +}; + +/** + * \brief Component binding trace command description + * + * \ingroup NMF_TRACE_FORMAT + */ +typedef enum { + TRACE_BIND_COMMAND_BIND_SYNCHRONOUS = 0x1, + TRACE_BIND_COMMAND_UNBIND_SYNCHRONOUS = 0x2, + TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS = 0x3, + TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS = 0x4 +} t_nmfTraceBindCommandDescription; + +/** + * \brief Component binding trace description + * + * \note clientComponentContext & serverComponentContext take value 0xffffffff when client or server are Component Manager. + * \note serverComponentContext take value 0x00000000 when binding to void. + * + * \ingroup NMF_TRACE_FORMAT + */ +struct t_nmfTraceBind { + t_nmfTraceChannelHeaderUnion header; //!< Trace header + + t_uint16 command; //!< See \ref t_nmfTraceBindCommandDescription + t_uint16 reserved; + t_uint16 clientDomainId; //!< In CM: 0x01:Arm | 0x02:SAA | 0x03:SVA | 0x04:SIA, in SMPEE: 0x1 + t_uint16 serverDomainId; //!< In CM: 0x01:Arm | 0x02:SAA | 0x03:SVA | 0x04:SIA, in SMPEE: 0x1 + t_uint32 clientComponentContext; //!< Component context belonging domain (DSP this or ARM class this) + t_uint32 serverComponentContext; //!< Component context belonging domain (DSP this or ARM class this) + t_uint8 requiredItfName[MAX_INTERFACE_NAME_LENGTH]; //!< Required interface name + t_uint8 providedItfName[MAX_INTERFACE_NAME_LENGTH]; //!< Provided interface name +}; + +/*! + * \brief Component interface method name trace description + * + * For each methods of each interfaces provided by a component, one such trace is dumped. + * + * \ingroup NMF_TRACE_FORMAT + */ +struct t_nmfTraceMethod { + t_nmfTraceChannelHeaderUnion header; //!< Trace header + + t_uint16 domainId; //!< In CM: 0x01:Arm | 0x02:SAA | 0x03:SVA | 0x04:SIA, in SMPEE: 0x1 + t_uint16 reserved; + t_uint32 methodId; //!< Unique Method Id belonging the component + t_uint32 componentContext; //!< Component context belonging domain (DSP this or ARM class this) + t_uint8 methodName[MAX_INTERFACE_METHOD_NAME_LENGTH]; //!< Symbolic method name +}; + +/** + * \brief Activity trace trace command description + * + * \ingroup NMF_TRACE_FORMAT + */ +typedef enum { + TRACE_ACTIVITY_START = 0x1, //!< Start method + TRACE_ACTIVITY_END = 0x2, //!< End method + TRACE_ACTIVITY_POST = 0x3, //!< Post method + TRACE_ACTIVITY_CALL = 0x4, //!< Synchronous call method + TRACE_ACTIVITY_RETURN = 0x5 //!< Synchronous return method +} t_nmfTraceActivityCommandDescription; + +/*! + * \brief Execution Engine scheduling activity trace description + * + * \ingroup NMF_TRACE_FORMAT + */ +struct t_nmfTraceActivity { + t_nmfTraceChannelHeaderUnion header; //!< Trace header + + t_uint16 command; //!< See \ref t_nmfTraceActivityCommandDescription + t_uint16 domainId; //!< In CM: 0x01:Arm | 0x02:SAA | 0x03:SVA | 0x04:SIA + t_uint32 componentContext; //!< Unique component Id (Component Handle for CM, Component this for EE) + t_uint32 methodId; //!< Unique Method Id belonging the component +}; + +/** + * \brief Component instantiation trace command description + * + * \ingroup NMF_TRACE_FORMAT + */ +typedef enum { + TRACE_COMMUNICATION_COMMAND_SEND = 0x1, + TRACE_COMMUNICATION_COMMAND_RECEIVE = 0x2 +} t_nmfTraceCommunicationCommandDescription; + +/** + * \brief Inter-processor communication signaling trace description + * + * Use when trigging interrupt through core. + * + * \note Not used on SMP EE + * + * \ingroup NMF_TRACE_FORMAT + */ +struct t_nmfTraceCommunication { + t_nmfTraceChannelHeaderUnion header; //!< Trace header + + t_uint16 command; //!< See \ref t_nmfTraceCommunicationCommandDescription + t_uint16 reserved_0; + t_uint16 domainId; //!< In CM: 0x01:Arm | 0x02:SAA | 0x03:SVA | 0x04:SIA + t_uint16 remoteDomainId; //!< In CM: 0x01:Arm | 0x02:SAA | 0x03:SVA | 0x04:SIA +}; + +/** + * \brief Component instantiation trace command description + * + * \ingroup NMF_TRACE_FORMAT + */ +typedef enum { + TRACE_ALLOCATOR_COMMAND_CREATE = 0x1, + TRACE_ALLOCATOR_COMMAND_DESTROY = 0x2 +} t_nmfTraceAllocatorCommandDescription; + +/*! + * \brief Panic trace description + * + * \ingroup NMF_TRACE_FORMAT + */ +struct t_nmfTraceAllocator { + t_nmfTraceChannelHeaderUnion header; //!< Trace header + + t_uint16 command; //!< See \ref t_nmfTraceAllocatorCommandDescription + t_uint16 allocId; //!< Memory allocator ID + t_uint32 size; //!< Memory allocator size + t_uint8 name[32]; //!< Memory allocator name +}; + +/** + * \brief Component instantiation trace command description + * + * \ingroup NMF_TRACE_FORMAT + */ +typedef enum { + TRACE_ALLOC_COMMAND_ALLOC = 0x1, + TRACE_ALLOC_COMMAND_FREE = 0x2 +} t_nmfTraceAllocCommandDescription; + +/*! + * \brief Panic trace description + * + * \ingroup NMF_TRACE_FORMAT + */ +struct t_nmfTraceAlloc { + t_nmfTraceChannelHeaderUnion header; //!< Trace header + + t_uint16 command; //!< See \ref t_nmfTraceAllocatorCommandDescription + t_uint16 allocId; //!< Memory allocator ID + t_uint32 offset; //!< Memory chunk offet + t_uint32 size; //!< Memory chunk size +}; + +/*! + * \brief Panic trace description + * + * \ingroup NMF_TRACE_FORMAT + */ +struct t_nmfTracePanic { + t_nmfTraceChannelHeaderUnion header; //!< Trace header + + t_uint16 reason; //!< See \ref t_panic_reason for description + t_uint16 domainId; //!< In CM: 0x01:Arm | 0x02:SAA | 0x03:SVA | 0x04:SIA + t_uint32 componentContext; //!< Unique component Id (Component Handle for CM, Component this for EE) + t_uint32 information1; //!< Reason dependent information 1st + t_uint32 information2; //!< Reason dependent information 2nd +}; + +/*! + * \brief User trace description + * + * \ingroup NMF_TRACE_FORMAT + */ +struct t_nmfTraceUser { + t_nmfTraceChannelHeaderUnion header; //!< Trace header + + t_uint32 key; //!< User key + t_uint16 domainId; //!< In CM: 0x01:Arm | 0x02:SAA | 0x03:SVA | 0x04:SIA + t_uint16 reserved; + t_uint32 componentContext; //!< Unique component Id (Component Handle for CM, Component this for EE) + t_uint32 callerAddress; //!< Unique code address belonging the component +}; + +/* +struct t_nmfTracePower{ + struct t_nmfTraceChannelHeader header; +}; +*/ + +#endif /* TRACE_FORMAT_H_ */ diff --git a/drivers/staging/nmf-cm/inc/nmf_type.idt b/drivers/staging/nmf-cm/inc/nmf_type.idt new file mode 100644 index 00000000000..e8cc4e09946 --- /dev/null +++ b/drivers/staging/nmf-cm/inc/nmf_type.idt @@ -0,0 +1,64 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +#ifndef NMF_TYPE_H_ +#define NMF_TYPE_H_ + +/*! + * \defgroup NMF_COMMON_TYPE NMF Common Type + * \ingroup COMMON + */ + +/*! + * \brief Error type returned by NMF API routines + * + * Possible value describe by \ref t_nmf_errorDescription + * + * \ingroup NMF_COMMON_TYPE + */ +typedef t_sint8 t_nmf_error; + +/*! + * \brief Error type values + * + * \ingroup NMF_COMMON_TYPE + */ +typedef enum { + NMF_OK = 0, //!< No error + NMF_INVALID_PARAMETER = -2, //!< Invalid parameter + NMF_NO_MORE_MEMORY = -30, //!< Out of memory + NMF_INTERFACE_NOT_BINDED = -59, //!< Try to unbind not binded interface + NMF_INTERFACE_ALREADY_BINDED = -60, //!< Try to bind already binded interface + NMF_NO_SUCH_REQUIRED_INTERFACE = -63, //!< Interface name not required by a component + NMF_NO_SUCH_PROVIDED_INTERFACE = -64, //!< Interface name not provided by a component + NMF_COMPONENT_NOT_STOPPED = -80, //!< Component must be stopped to perform operation + NMF_INVALID_COMPONENT_STATE_TRANSITION = -81, //!< Invalid component state transition caused by user action + NMF_NO_SUCH_PROPERTY = -87, //!< Property name doesn't exported by the underlying component + NMF_NO_SUCH_ATTRIBUTE = -88, //!< Attribute name not shared (exported) by a component + NMF_NO_MESSAGE = -103, //!< No message available + NMF_FLUSH_MESSAGE = -106, //!< Message send after call to EE_FlushChannel() + NMF_INTEGRATION_ERROR0 = -112, //!< OS dependent integration Error [-112 -> -121] + NMF_INTEGRATION_ERROR1 = -113, //!< OS dependent integration Error [-112 -> -121] + NMF_INTEGRATION_ERROR2 = -114, //!< OS dependent integration Error [-112 -> -121] + NMF_INTEGRATION_ERROR3 = -115, //!< OS dependent integration Error [-112 -> -121] + NMF_INTEGRATION_ERROR4 = -116, //!< OS dependent integration Error [-112 -> -121] + NMF_INTEGRATION_ERROR5 = -117, //!< OS dependent integration Error [-112 -> -121] + NMF_INTEGRATION_ERROR6 = -118, //!< OS dependent integration Error [-112 -> -121] + NMF_INTEGRATION_ERROR7 = -119, //!< OS dependent integration Error [-112 -> -121] + NMF_INTEGRATION_ERROR8 = -120, //!< OS dependent integration Error [-112 -> -121] + NMF_INTEGRATION_ERROR9 = -121 //!< OS dependent integration Error [-112 -> -121] +} t_nmf_errorDescription; + +/*! + * \brief Define t_nmf_channel type that identify a communication channel between nmf and user. + * + * \ingroup NMF_COMMON_TYPE + */ +typedef t_uint32 t_nmf_channel; + +#endif /* NMF_TYPE_H_ */ diff --git a/drivers/staging/nmf-cm/inc/type.h b/drivers/staging/nmf-cm/inc/type.h new file mode 100644 index 00000000000..d6eafe9aea5 --- /dev/null +++ b/drivers/staging/nmf-cm/inc/type.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/* inc/type.h - Programming Model. + * + * Copyright (c) 2006, 2007, 2008 STMicroelectronics. + * + * Reproduction and Communication of this document is strictly prohibited + * unless specifically authorized in writing by STMicroelectronics. + * + * Written by NMF team. + */ +#ifndef _NMF_TYPE_H_ +#define _NMF_TYPE_H_ + +#include + +PUBLIC IMPORT_SHARED void NMF_LOG(const char* fmt, ...); +PUBLIC IMPORT_SHARED void NMF_PANIC(const char* fmt, ...); + +#define NMF_ASSERT(cond) do { if(!(cond)) NMF_PANIC("NMF_ASSERT at %s:%d\n", (int)__FILE__, (int)__LINE__); } while(0) + +#ifndef EXPORT_NMF_COMPONENT + #define EXPORT_NMF_COMPONENT EXPORT_SHARED +#endif + +#ifndef IMPORT_NMF_COMPONENT + #define IMPORT_NMF_COMPONENT IMPORT_SHARED +#endif + +#endif /* _NMF_TYPE_H_ */ diff --git a/drivers/staging/nmf-cm/inc/typedef.h b/drivers/staging/nmf-cm/inc/typedef.h new file mode 100644 index 00000000000..97af9dec2c2 --- /dev/null +++ b/drivers/staging/nmf-cm/inc/typedef.h @@ -0,0 +1,193 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \defgroup COMMON Common types and definitions + * + * \defgroup NMF_COMMON NMF common definition + * \ingroup COMMON + * + * \defgroup NMF_ABI NMF ABI specification + * \warning This page is not for multimedia developers ! + */ +/*! + * \brief Primitive Type Definition + * + * \defgroup NMF_PRIMITIVE_TYPE Primitive type definition + * \ingroup COMMON + */ + +#ifndef NMF_TYPEDEF_H_ +#define NMF_TYPEDEF_H_ + +#undef PRIVATE +#define PRIVATE static //!< Private macro declaration \ingroup NMF_PRIMITIVE_TYPE + +#undef PUBLIC +#ifdef __cplusplus +#define PUBLIC extern "C" //!< Public macro declaration \ingroup NMF_PRIMITIVE_TYPE +#else +#define PUBLIC extern //!< Public macro declaration \ingroup NMF_PRIMITIVE_TYPE +#endif + +#if defined(__SYMBIAN32__) +/*! + * \brief Declared IMPORT_SHARED to allow dll/shared library creation + * + * \note Value depend on OS. + * + * \ingroup NMF_PRIMITIVE_TYPE + */ + #ifndef IMPORT_SHARED + #define IMPORT_SHARED IMPORT_C + #endif +/*! + * \brief Declared EXPORT_SHARED to allow dll/shared library creation + * + * \note Value depend on OS. + * + * \ingroup NMF_PRIMITIVE_TYPE + */ + #ifndef EXPORT_SHARED + #define EXPORT_SHARED EXPORT_C + #endif +#elif defined(LINUX) + #ifndef IMPORT_SHARED + #define IMPORT_SHARED + #endif + #ifndef EXPORT_SHARED + #define EXPORT_SHARED __attribute__ ((visibility ("default"))) + #endif +#else + #ifndef IMPORT_SHARED + #define IMPORT_SHARED + #endif + + #ifndef EXPORT_SHARED + #define EXPORT_SHARED + #endif +#endif + +/* + * Definition of type that are used by interface. + */ + +typedef unsigned int t_uword; +typedef signed int t_sword; + +#ifdef __flexcc2__ + +typedef unsigned char t_bool; + +#ifdef __mode16__ + +typedef signed char t_sint8; +typedef signed int t_sint16; +typedef signed long t_sint24; +typedef signed long t_sint32; +typedef signed long long t_sint40; +// bigger type are not handle on this mode + +typedef unsigned char t_uint8; +typedef unsigned int t_uint16; +typedef unsigned long t_uint24; +typedef unsigned long t_uint32; +typedef unsigned long long t_uint40; +// bigger type are not handle on this mode + +// shared addr type definition +//typedef __SHARED16 t_uint16 * t_shared_addr; +typedef void * t_shared_field; + +#else /* __mode16__ -> __mode24__ */ + +typedef signed char t_sint8; +typedef signed short t_sint16; +typedef signed int t_sint24; +typedef signed long t_sint32; +typedef signed long t_sint40; +typedef signed long t_sint48; +typedef signed long long t_sint56; + +typedef unsigned char t_uint8; +typedef unsigned short t_uint16; +typedef unsigned int t_uint24; +typedef unsigned long t_uint32; +typedef unsigned long t_uint40; +typedef unsigned long t_uint48; +typedef unsigned long long t_uint56; + +// shared addr type definition +//typedef __SHARED16 t_uint16 * t_shared_addr; +typedef t_uint24 t_shared_field; + +#endif /* MMDSP mode24 */ + +// shared register (ARM world) type definition +#if 0 +typedef struct { + t_uint16 lsb; + t_uint16 msb; +} t_shared_reg; +#endif +typedef t_uint32 t_shared_reg; + +typedef t_uint32 t_physical_address; + +#include + +#else /* __flexcc2__ -> RISC 32 Bits */ + +#ifndef _HCL_DEFS_H +typedef unsigned char t_bool; //!< Boolean primitive type \ingroup NMF_PRIMITIVE_TYPE + +typedef unsigned char t_uint8; //!< Unsigned 8 bits primitive type \ingroup NMF_PRIMITIVE_TYPE +typedef signed char t_sint8; //!< Signed 8 bits primitive type \ingroup NMF_PRIMITIVE_TYPE +typedef unsigned short t_uint16; //!< Unsigned 16 bits primitive type \ingroup NMF_PRIMITIVE_TYPE +typedef signed short t_sint16; //!< Signed 16 bits primitive type \ingroup NMF_PRIMITIVE_TYPE +typedef unsigned long t_uint32; //!< Unsigned 32 bits primitive type \ingroup NMF_PRIMITIVE_TYPE +typedef signed long t_sint32; //!< Signed 32 bits primitive type \ingroup NMF_PRIMITIVE_TYPE +typedef unsigned long long t_uint64; //!< Unsigned 64 bits primitive type \ingroup NMF_PRIMITIVE_TYPE +typedef signed long long t_sint64; //!< Signed 64 bits primitive type \ingroup NMF_PRIMITIVE_TYPE + +typedef t_uint32 t_physical_address; +#endif /* _HCL_DEFS_H */ + +typedef unsigned long t_uint24; +typedef signed long t_sint24; +typedef unsigned long long t_uint48; +typedef signed long long t_sint48; + +// shared addr type definition +typedef t_uint32 t_shared_addr; + +// shared register (ARM world) type definition +typedef t_uint32 t_shared_reg; +typedef t_uint32 t_shared_field; + +#endif /* RISC 32 Bits */ + +/* + * Define boolean type + */ +#undef FALSE +#define FALSE 0 //!< Boolean FALSE value +#undef TRUE +#define TRUE 1 //!< Boolean TRUE value + +#ifndef NULL + #if defined __flexcc2__ || defined __SYMBIAN32__ + #define NULL (0x0) //!< Null type \ingroup NMF_PRIMITIVE_TYPE + #else + #define NULL ((void*)0x0) //!< Null type \ingroup NMF_PRIMITIVE_TYPE + #endif +#endif + +typedef t_uint32 t_nmf_component_handle; + +#endif /* NMF_TYPEDEF_H_ */ diff --git a/drivers/staging/nmf-cm/nmf/inc/channel_type.h b/drivers/staging/nmf-cm/nmf/inc/channel_type.h new file mode 100644 index 00000000000..7d439ebf0cf --- /dev/null +++ b/drivers/staging/nmf-cm/nmf/inc/channel_type.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Common Nomadik Multiprocessing Framework type definition + * + * This file contains the shared between cm and ee type definitions used into NMF for callback. + */ +/*! + * \defgroup _t_nmf_channel_flag t_nmf_channel_flag + * \ingroup NMF_COMMON + */ + +#ifndef __INC_CHANNEL_TYPE_H +#define __INC_CHANNEL_TYPE_H + +#include +#include + +/*! + * \brief Define t_nmf_channel_flag type that allow to control if/how a new communication channel is created. + * \ingroup _t_nmf_channel_flag + */ +typedef t_uint32 t_nmf_channel_flag; + +#define NMF_CHANNEL_SHARED ((t_nmf_channel_flag)0) //!< \ingroup _t_nmf_channel_flag +#define NMF_CHANNEL_PRIVATE ((t_nmf_channel_flag)1) //!< \ingroup _t_nmf_channel_flag + +/*! + * \brief Define t_nmf_virtualInterruptHandler function type to allow to dispatch virtual interrupt + * \ingroup VIRTUAL_INTERRUPT + */ +typedef void (*t_nmf_virtualInterruptHandler)(void *interruptContext); + +#endif + diff --git a/drivers/staging/nmf-cm/nmf/inc/component_type.h b/drivers/staging/nmf-cm/nmf/inc/component_type.h new file mode 100644 index 00000000000..08b63b21225 --- /dev/null +++ b/drivers/staging/nmf-cm/nmf/inc/component_type.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Common Nomadik Multiprocessing Framework type definition + * + * This file contains the shared between cm and ee type definitions used into NMF for callback. + */ +#ifndef __INC_COMPONENT_TYPE_H +#define __INC_COMPONENT_TYPE_H + +#include + +/*! + * \brief Identifier of a component instance handle + * + * \ingroup NMF_COMMON + */ +typedef t_nmf_component_handle t_cm_instance_handle; + +#endif + diff --git a/drivers/staging/nmf-cm/nmf/inc/service_type.h b/drivers/staging/nmf-cm/nmf/inc/service_type.h new file mode 100644 index 00000000000..3e5473338ee --- /dev/null +++ b/drivers/staging/nmf-cm/nmf/inc/service_type.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Service type and data used through service callback. + * \defgroup NMF_SERVICE NMF Service Callback types and data definition + * \ingroup NMF_COMMON + */ +#ifndef SERVICE_TYPE_H +#define SERVICE_TYPE_H + +#include +#include +#include + +/*! + * \brief Define t_nmf_service_type type + * + * It gives the type of service message passed to service callback. + * \ingroup NMF_SERVICE + */ +typedef t_uint32 t_nmf_service_type; +#define NMF_SERVICE_PANIC ((t_nmf_service_type)0) //!< \ingroup NMF_SERVICE +#define NMF_SERVICE_SHUTDOWN ((t_nmf_service_type)1) //!< \ingroup NMF_SERVICE + +/* + * The following structured define each data structure used for each service type + * and given to each serviceCallback + */ + +/*! + * \brief Define t_nmf_panic_data type + * + * This is the data structure passed to the service callback (inside \ref t_nmf_service_data) + * when t_nmf_service_type == NMF_SERVICE_PANIC + * \ingroup NMF_SERVICE + */ +typedef struct { + t_panic_reason panicReason; //!< The reason of the panic + t_panic_source panicSource; //!< THe source of the panic (One of the MPC or the ARM-EE) + /*! + * union of structures containing specific info, depending on the panicSource + */ + union { + struct { + t_nmf_core_id coreid; //!< The coreId of the MPC on which the panic occured + t_cm_instance_handle faultingComponent; //!< The faulting component handle + t_uint32 panicInfo1; //!< First info (depend on \ref panicReason) + t_uint32 panicInfo2; //!< Second info (depend on \ref panicReason) + } mpc; //!< member to use if panicSource == MPC_EE + struct { + void * faultingComponent; //!< The faulting component handle + t_uint32 panicInfo1; //!< First info (depend on \ref panicReason) + t_uint32 panicInfo2; //!< Second info (depend on \ref panicReason) + } host; //!< member to use if panicSource == HOST_EE + } info; //!< union of structures containing specific info, depending on the panicSource +} t_nmf_panic_data; + +/*! + * \brief Define t_nmf_shutdown_data type + * + * This is the data structure passed to the service callback (inside \ref t_nmf_service_data) + * when t_nmf_service_type == NMF_SERVICE_SHUTDOWN + * \ingroup NMF_SERVICE + */ +typedef struct { + t_nmf_core_id coreid; //!< The coreId of the MPC on which has been shutdown +} t_nmf_shutdown_data; + +/*! + * \brief Define t_nmf_service_data type + * + * It gives the data passed to the service callbacks for each service type + * This is an union whose member to use is defined by the given \ref t_nmf_service_type + * + * \ingroup NMF_SERVICE + */ +typedef union { + t_nmf_panic_data panic; //!< if service_type == NMF_SERVICE_PANIC + t_nmf_shutdown_data shutdown; //!< if service_type == NMF_SERVICE_SHUTDOWN +} t_nmf_service_data; + +/*! + * \brief Define t_nmf_serviceCallback function type to allow to dispatch service message to user. + * \ingroup NMF_SERVICE + */ +typedef void (*t_nmf_serviceCallback)(void *contextHandler, t_nmf_service_type serviceType, t_nmf_service_data *serviceData); + +#endif //SERVICE_TYPE_H diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c new file mode 100644 index 00000000000..8f547ba0ad9 --- /dev/null +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -0,0 +1,1162 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Pierre Peiffer for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +/** \file osal-kernel.c + * + * Implements NMF OSAL for Linux kernel-space environment + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "cmioctl.h" +#include "osal-kernel.h" +#include "cm_service.h" +#include "cmld.h" + +__iomem void *prcmu_base = NULL; +__iomem void *prcmu_tcdm_base = NULL; + +/* DSP Load Monitoring */ +#define FULL_OPP 100 +#define HALF_OPP 50 +static unsigned long running_dsp = 0; +static unsigned int dspLoadMonitorPeriod = 1000; +module_param(dspLoadMonitorPeriod, uint, S_IWUSR|S_IRUGO); +MODULE_PARM_DESC(dspLoadMonitorPeriod, "Period of the DSP-Load monitoring in ms"); +static unsigned int dspLoadHighThreshold = 85; +module_param(dspLoadHighThreshold, uint, S_IWUSR|S_IRUGO); +MODULE_PARM_DESC(dspLoadHighThreshold, "Threshold above which 100 APE OPP is requested"); +static unsigned int dspLoadLowThreshold = 35; +module_param(dspLoadLowThreshold, uint, S_IWUSR|S_IRUGO); +MODULE_PARM_DESC(dspLoadLowThreshold, "Threshold below which 100 APE OPP request is removed"); + +/** \defgroup ENVIRONMENT_INITIALIZATION Environment initialization + * Includes functions that initialize the Linux OSAL itself plus functions that + * are responsible to factor configuration objects needed to initialize Component Manager library + */ + +/** \defgroup OSAL_IMPLEMENTATION OSAL implementation + * Linux-specific implementation of the Component Manager OSAL interface. + */ + + +/** \ingroup ENVIRONMENT_INITIALIZATION + * Remaps IO, SDRAM and ESRAM regions + * + * \osalEnvironment NMF-Osal descriptor + * \return POSIX error code + */ +int remapRegions(void) +{ + unsigned i; + + /* Remap DSP base areas */ + for (i=0; iesramDesc.systemAddr.physical = ESRAM_BASE; + nmfHwMappingDesc->esramDesc.systemAddr.logical = (t_cm_logical_address)osalEnv.esram_base; + nmfHwMappingDesc->esramDesc.size = cfgESRAMSize*ONE_KB; + + nmfHwMappingDesc->hwSemaphoresMappingBaseAddr.physical = HWSEM_BASE; + nmfHwMappingDesc->hwSemaphoresMappingBaseAddr.logical = (t_cm_logical_address)osalEnv.hwsem_base; + + return 0; +} + +/** \ingroup ENVIRONMENT_INITIALIZATION + * Fills a t_cm_system_address object + * + * \param mpcSystemAddress Pointer to a t_cm_system_address object + * \return POSIX error code + */ +void getMpcSystemAddress(unsigned i, t_cm_system_address* mpcSystemAddress) +{ + mpcSystemAddress->physical = (t_cm_physical_address)osalEnv.mpc[i].baseP; + mpcSystemAddress->logical = (t_cm_logical_address)osalEnv.mpc[i].baseL; +} + + +/** \ingroup ENVIRONMENT_INITIALIZATION + * Fills t_nmf_memory_segment objects for MPC code and data segments + * + * \param i Index of the MPC to initialize + * \param codeSegment Pointer to a t_nmf_memory_segment (code segment) + * \param dataSegment Pointer to a t_nmf_memory_segment (data segment) + * \return Always 0 + */ +void getMpcSdramSegments(unsigned i, t_nmf_memory_segment* codeSegment, t_nmf_memory_segment* dataSegment) +{ + codeSegment->systemAddr.logical = (t_cm_logical_address)osalEnv.mpc[i].sdramCodeL; + codeSegment->systemAddr.physical = osalEnv.mpc[i].sdramCodeP; + codeSegment->size = osalEnv.mpc[i].sdramCodeSize; + + dataSegment->systemAddr.logical = (t_cm_logical_address)osalEnv.mpc[i].sdramDataL; + dataSegment->systemAddr.physical = osalEnv.mpc[i].sdramDataP; + dataSegment->size = osalEnv.mpc[i].sdramDataSize; +} + +#ifdef CM_DEBUG_ALLOC +#include +struct cm_alloc cm_alloc; + +/** + * These routines initializes the structures used to trace all alloc/free. + * These are used in debug mode to track all memory leak about the allocations + * done through the OSAL. + */ +void init_debug_alloc(void) +{ + INIT_LIST_HEAD(&cm_alloc.chain); + spin_lock_init(&cm_alloc.lock); +} + +void cleanup_debug_alloc(void) +{ + struct cm_alloc_elem *entry, *next; + char buffer[128]; + + list_for_each_entry_safe(entry, next, &cm_alloc.chain, elem) { + sprint_symbol(buffer, (int)entry->caller); + pr_err("/!\\ ALLOC(size=%d) not freed from: 0x%p (%s)\n", + entry->size, entry->caller, buffer); + list_del(&entry->elem); + if ((void*)entry >= (void*)VMALLOC_START + && (void*)entry < (void*)VMALLOC_END) + vfree(entry); + else + kfree(entry); + } +} + +void dump_debug_alloc(void) +{ + struct cm_alloc_elem *entry, *next; + char buffer[128]; + + pr_err("Current allocated memory:\n"); + list_for_each_entry_safe(entry, next, &cm_alloc.chain, elem) { + sprint_symbol(buffer, (int)entry->caller); + pr_err("=> Alloc of size=%d from: 0x%p (%s)\n", + entry->size, entry->caller, buffer); + } +} +#endif + + +/** \ingroup OSAL_IMPLEMENTATION + * Called by CM_ProcessMpcEvent in interrupt/tasklet context. Schedules the DFC. + * Enqueues the new event in the process' message queue. + * + * \note This is _not_ called in response to internal events such as in + * response to a CM_InstantiateComponent. It is called when user-defined + * functions need to be called in skeletons. This behavior is different + * from 0.8.1 version. + */ +void OSAL_PostDfc(t_nmf_mpc2host_handle upLayerTHIS, t_uint32 methodIndex, t_event_params_handle ptr, t_uint32 size) +{ + /* skelwrapper has been created in CM_SYSCALL_BindComponentToCMCore and conveys per-process private data */ + t_skelwrapper* skelwrapper = (t_skelwrapper*)upLayerTHIS; + struct osal_msg* message; + + /* If the clannel has been closed, no more reader exists + => discard the message */ + if (skelwrapper->channelPriv->state == CHANNEL_CLOSED) { + pr_warning("%s: message discarded (channel closed)\n", + __func__ ); + return; + } + + /* Create a new message */ + message = kmalloc(sizeof(*message), GFP_ATOMIC); + if (!message) { + pr_err("%s: message discarded (alloc failed)\n", __func__ ); + return; + } + + /* Stuff it */ + plist_node_init(&message->msg_entry, 0); + message->msg_type = MSG_INTERFACE; + message->d.itf.skelwrap = skelwrapper; + message->d.itf.methodIdx = methodIndex; + message->d.itf.anyPtr = ptr; + message->d.itf.ptrSize = size; + + /* Enqueue it */ + /* Should be protected with the cmPriv->msgQueueLock held + But we know by design that we are safe here. (Alone here in + tasklet (soft-interrupt) context. + When accessed in process context, soft-irq are disable) + */ + spin_lock_bh(&skelwrapper->channelPriv->bh_lock); + plist_add(&message->msg_entry, &skelwrapper->channelPriv->messageQueue); + spin_unlock_bh(&skelwrapper->channelPriv->bh_lock); + + /* Wake up process' wait queue */ + wake_up_interruptible(&skelwrapper->channelPriv->waitq); +} + + +#define MAX_LOCKS 8 // max number of locks/semaphores creatable +static unsigned long semused = 0; // bit field for used semaphores +static unsigned long lockused = 0; // bit field for used mutexes +static struct mutex cmld_locks[MAX_LOCKS]; + +/** \ingroup OSAL_IMPLEMENTATION + */ +t_nmf_osal_sync_handle OSAL_CreateLock(void) +{ + int i; + + for (i=0; icaller = __builtin_return_address(0); + entry->size = size; + + spin_lock(&cm_alloc.lock); + list_add_tail(&entry->elem, &cm_alloc.chain); + spin_unlock(&cm_alloc.lock); + + return entry->addr; +#else + void* mem; + + if (size == 0) + return NULL; + mem = kmalloc(size, GFP_KERNEL); + if (mem == NULL) { + mem = vmalloc(size); + if (mem == NULL) + pr_alert("CM (%s): No more memory (requested " + "size=%d) !!!\n", __func__, (int)size); + } + return mem; +#endif +} + + +/** \ingroup OSAL_IMPLEMENTATION + * OSAL alloc implementation + */ +void* OSAL_Alloc_Zero(t_cm_size size) +{ +#ifdef CM_DEBUG_ALLOC + struct cm_alloc_elem *entry; + + if (size == 0) + return NULL; + + entry = kzalloc(size + sizeof(*entry), GFP_KERNEL); + if (entry == NULL) { + entry = vmalloc(size + sizeof(*entry)); + if (entry == NULL) { + pr_alert("%s: kmalloc(%d) and vmalloc(%d) failed\n", + __func__, (int)size, (int)size); + dump_debug_alloc(); + return NULL; + } else { + memset(entry, 0, size + sizeof(*entry)); + } + } + + /* return address of the caller */ + entry->caller = __builtin_return_address(0); + entry->size = size; + + spin_lock(&cm_alloc.lock); + list_add_tail(&entry->elem, &cm_alloc.chain); + spin_unlock(&cm_alloc.lock); + + return entry->addr; +#else + void* mem; + + if (size == 0) + return NULL; + mem = kzalloc(size, GFP_KERNEL); + if (mem == NULL) { + mem = vmalloc(size); + if (mem == NULL) + pr_alert("CM (%s): No more memory (requested " + "size=%d) !!!\n", __func__, (int)size); + else + memset(mem, 0, size); + } + + return mem; +#endif +} + + +/** \ingroup OSAL_IMPLEMENTATION + * OSAL free implementation + */ +void OSAL_Free(void* mem) +{ +#ifdef CM_DEBUG_ALLOC + struct cm_alloc_elem *entry = container_of(mem, struct cm_alloc_elem, addr); + unsigned int i; + char pattern[4] = { 0xEF, 0xBE, 0xAD, 0xDE }; + + if (mem == NULL) + return; + + /* fill with a pattern to detect bad re-use of this area */ + for (i=0; isize; i++) + entry->addr[i] = pattern[i%4]; + + spin_lock(&cm_alloc.lock); + list_del(&entry->elem); + spin_unlock(&cm_alloc.lock); + + if ((void*)entry >= (void*)VMALLOC_START + && (void*)entry < (void*)VMALLOC_END) + vfree(entry); + else + kfree(entry); +#else + if (mem >= (void*)VMALLOC_START && mem < (void*)VMALLOC_END) + vfree(mem); + else + kfree(mem); +#endif +} + +/** \ingroup OSAL_IMPLEMENTATION + * OSAL Copy implementation + * This copy some data from userspace (address to kernel space. + * This implementation differs on Symbian. + */ +t_cm_error OSAL_Copy(void *dst, const void *src, t_cm_size size) +{ + if (copy_from_user(dst, src, size)) + return CM_UNKNOWN_MEMORY_HANDLE; + return CM_OK; +} + +/** \ingroup OSAL_IMPLEMENTATION + * OSAL write64 function implementation + */ +void OSAL_Write64(t_nmf_trace_channel channel, t_uint8 isTimestamped, t_uint64 value) +{ +#ifdef CONFIG_STM_TRACE + if (isTimestamped) + stm_tracet_64(channel, value); + else + stm_trace_64(channel, value); +#endif +} + + +/** \ingroup OSAL_IMPLEMENTATION + * OSAL log function implementation + */ +void OSAL_Log(const char *format, int param1, int param2, int param3, int param4, int param5, int param6) +{ + printk(format, param1, param2, param3, param4, param5, param6); +} + +/** + * compute the dsp load + * + * return -1 if in case of failure, a value between 0 and 100 otherwise + */ +static s8 computeDspLoad(t_cm_mpc_load_counter *oldCounter, t_cm_mpc_load_counter *counter) +{ + u32 t, l; + + if ((oldCounter->totalCounter == 0) && (oldCounter->loadCounter == 0)) + return -1; // Failure or not started ? + if ((counter->totalCounter == 0) && (counter->loadCounter == 0)) + return -1; // Failure or already stopped ? + + if (counter->totalCounter < oldCounter->totalCounter) + t = (u32)((((u64)-1) - oldCounter->totalCounter) + + counter->totalCounter + 1); + else + t = (u32)(counter->totalCounter - oldCounter->totalCounter); + + if (counter->loadCounter < oldCounter->loadCounter) + l = (u32)((((u64)-1) - oldCounter->loadCounter) + + counter->loadCounter + 1); + else + l = (u32)(counter->loadCounter - oldCounter->loadCounter); + + if (t == 0) // not significant + return -1; + + if (l > t) // not significant + return -1; + + return (l*100) / t; +} + +static void wakeup_process(unsigned long data) +{ + wake_up_process((struct task_struct *)data); +} + +/** + * Thread function entry for monitorin the CPU load + */ +static int dspload_monitor(void *idx) +{ + int i = (int)idx; + unsigned char current_opp_request = HALF_OPP; + struct mpcConfig *mpc = &osalEnv.mpc[i]; + struct timer_list timer; + + timer.function = wakeup_process; + timer.data = (unsigned long)current; + init_timer_deferrable(&timer); + + if (prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, + (char*)mpc->name, + current_opp_request)) + pr_err("CM Driver: Add QoS failed\n"); + + /* init counter */ + if (CM_GetMpcLoadCounter(mpc->coreId, + &mpc->oldLoadCounter) != CM_OK) + pr_err("CM Driver: Failed to init load counter for %s\n", + mpc->name); + + while (!kthread_should_stop()) { + t_cm_mpc_load_counter loadCounter; + s8 load = -1; + unsigned long expire; + + __set_current_state(TASK_UNINTERRUPTIBLE); + + expire = msecs_to_jiffies(dspLoadMonitorPeriod) + jiffies; + + mod_timer(&timer, expire); + schedule(); + /* We can be woken up before the expiration of the timer + but we don't need to handle that case as the + computation of the DSP load takes that into account */ + + if (!test_bit(i, &running_dsp)) + continue; + + if (CM_GetMpcLoadCounter(mpc->coreId, + &loadCounter) != CM_OK) + loadCounter = mpc->oldLoadCounter; + + load = computeDspLoad(&mpc->oldLoadCounter, &loadCounter); + mpc->oldLoadCounter = loadCounter; + + if (load == -1) + continue; + /* check if we must request more opp */ + if ((current_opp_request == HALF_OPP) + && (load > dspLoadHighThreshold)) { + current_opp_request = FULL_OPP; + if (cm_debug_level) + pr_info("CM Driver: Request QoS OPP %d for %s\n", + current_opp_request, mpc->name); + prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, + (char*)mpc->name, + current_opp_request); + } + /* check if we can request less opp */ + else if ((current_opp_request == FULL_OPP) + && (load < dspLoadLowThreshold)) { + current_opp_request = HALF_OPP; + if (cm_debug_level) + pr_info("CM Driver: Request QoS OPP %d for %s\n", + current_opp_request, mpc->name); + prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP, + (char*)mpc->name, + current_opp_request); + } + } + + del_singleshot_timer_sync(&timer); + if (cm_debug_level) + pr_info("CM Driver: Remove QoS OPP for %s\n", mpc->name); + prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, + (char*)mpc->name); + return 0; +} + +static int enable_auto_pm = 0; +module_param(enable_auto_pm, bool, S_IWUSR|S_IRUGO); + +/** \ingroup OSAL_IMPLEMENTATION + * Used by CM to disable a power resource + */ +void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam, t_uint32 secondParam) +{ + switch (resource) { + case CM_OSAL_POWER_SxA_CLOCK: { + unsigned idx = COREIDX(firstParam); + struct osal_msg msg; + + if (idx >= NB_MPC) { + pr_err("CM Driver(%s(res=%d)): core %u unknown\n", + __func__, (int)resource, (unsigned)firstParam); + return; + } + + /* Stop the DSP load monitoring */ + clear_bit(idx, &running_dsp); + if (osalEnv.mpc[idx].monitor_tsk) { + kthread_stop(osalEnv.mpc[idx].monitor_tsk); + osalEnv.mpc[idx].monitor_tsk = NULL; + } + + /* Stop the DSP */ + if (regulator_disable(osalEnv.mpc[idx].mmdsp_regulator) < 0) + pr_err("CM Driver(%s): can't disable regulator %s-mmsdp\n", + __func__, osalEnv.mpc[idx].name); +#ifdef CONFIG_HAS_WAKELOCK + wake_unlock(&osalEnv.mpc[idx].wakelock); +#endif + + /* Create and dispatch a shutdown service message */ + msg.msg_type = MSG_SERVICE; + msg.d.srv.srvType = NMF_SERVICE_SHUTDOWN; + msg.d.srv.srvData.shutdown.coreid = firstParam; + dispatch_service_msg(&msg); + break; + } + case CM_OSAL_POWER_SxA_AUTOIDLE: + switch (firstParam) { + case SVA_CORE_ID: + osalEnv.dsp_sleep.sva_auto_pm_enable = PRCMU_AUTO_PM_OFF; + osalEnv.dsp_sleep.sva_power_on = 0; + osalEnv.dsp_sleep.sva_policy = PRCMU_AUTO_PM_POLICY_DSP_OFF_HWP_OFF; + break; + case SIA_CORE_ID: + osalEnv.dsp_sleep.sia_auto_pm_enable = PRCMU_AUTO_PM_OFF; + osalEnv.dsp_sleep.sia_power_on = 0; + osalEnv.dsp_sleep.sia_policy = PRCMU_AUTO_PM_POLICY_DSP_OFF_HWP_OFF; + break; + default: + pr_err("CM Driver(%s(res=%d)): core %u unknown\n", __func__, (int)resource, (unsigned)firstParam); + return; + } + if (enable_auto_pm) + prcmu_configure_auto_pm(&osalEnv.dsp_sleep, &osalEnv.dsp_idle); + break; + case CM_OSAL_POWER_SxA_HARDWARE: { + unsigned idx = COREIDX(firstParam); + if (idx >= NB_MPC) { + pr_err("CM Driver(%s(res=%d)): core %u unknown\n", + __func__, (int)resource, (unsigned)firstParam); + return; + } + if (regulator_disable(osalEnv.mpc[idx].pipe_regulator) < 0) + pr_err("CM Driver(%s): can't disable regulator %s-pipe\n", + __func__, osalEnv.mpc[idx].name); + break; + } + case CM_OSAL_POWER_HSEM: + break; + case CM_OSAL_POWER_SDRAM: + break; + case CM_OSAL_POWER_ESRAM: { + int i; + /* firstParam: base address; secondParam: size + U8500_ESRAM_BASE is the start address of BANK 0, + BANK size=0x20000 */ + + /* Compute the relative end address of the range, + relative to base address of BANK1 */ + secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); + + /* if end is below base address of BANK1, it means that full + range of addresses is on Bank0 */ + if (((int)secondParam) < 0) + break; + /* Compute the index of the last bank accessed among + esram 1+2 and esram 3+4 banks */ + secondParam /= 0x40000; + WARN_ON(secondParam > 1); + + /* Compute the index of the first bank accessed among esram 1+2 + and esram 3+4 banks + Do not manage Bank 0 (secured, must be always ON) */ + if (firstParam < (U8500_ESRAM_BASE+0x20000)) + firstParam = 0; + else + firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; + + /* power off the banks 1+2 and 3+4 if accessed. */ + for (i=firstParam; i<=secondParam; i++) { + if (regulator_disable(osalEnv.esram_regulator[i]) < 0) + pr_err("CM Driver(%s): can't disable regulator" + "for esram bank %s\n", __func__, + i ? "34" : "12"); + } + break; + } + default: + pr_err("CM Driver(%s): resource %d unknown/not supported\n", + __func__, (int)resource); + } +} + +/** \ingroup OSAL_IMPLEMENTATION + * Used by CM to enable a power resource + */ +t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam, t_uint32 secondParam) +{ + switch (resource) { + case CM_OSAL_POWER_SxA_CLOCK: { + unsigned idx = COREIDX(firstParam); + + if (idx > NB_MPC) { + pr_err("CM Driver(%s(res=%d)): core %u unknown\n", __func__, (int)resource, (unsigned)firstParam); + return CM_INVALID_PARAMETER; + } + + /* Start the DSP */ +#ifdef CONFIG_HAS_WAKELOCK + wake_lock(&osalEnv.mpc[idx].wakelock); +#endif + if (regulator_enable(osalEnv.mpc[idx].mmdsp_regulator) < 0) + pr_err("CM Driver(%s): can't enable regulator %s-mmsdp\n", __func__, osalEnv.mpc[idx].name); + + /* Start the DSP load monitoring for this dsp */ + set_bit(idx, &running_dsp); + osalEnv.mpc[idx].monitor_tsk = kthread_run(&dspload_monitor, + (void*)idx, + "%s-loadd", + osalEnv.mpc[idx].name); + if (IS_ERR(osalEnv.mpc[idx].monitor_tsk)) { + pr_err("CM Driver: failed to start dspmonitord " + "thread: %ld\n", PTR_ERR(osalEnv.mpc[idx].monitor_tsk)); + osalEnv.mpc[idx].monitor_tsk = NULL; + } + break; + } + case CM_OSAL_POWER_SxA_AUTOIDLE: + switch (firstParam) { + case SVA_CORE_ID: + osalEnv.dsp_sleep.sva_auto_pm_enable = PRCMU_AUTO_PM_ON; + osalEnv.dsp_sleep.sva_power_on = PRCMU_AUTO_PM_POWER_ON_HSEM | PRCMU_AUTO_PM_POWER_ON_ABB_FIFO_IT; + osalEnv.dsp_sleep.sva_policy = PRCMU_AUTO_PM_POLICY_DSP_OFF_RAMRET_HWP_OFF; + break; + case SIA_CORE_ID: + osalEnv.dsp_sleep.sia_auto_pm_enable = PRCMU_AUTO_PM_ON; + osalEnv.dsp_sleep.sia_power_on = PRCMU_AUTO_PM_POWER_ON_HSEM | PRCMU_AUTO_PM_POWER_ON_ABB_FIFO_IT; + osalEnv.dsp_sleep.sia_policy = PRCMU_AUTO_PM_POLICY_DSP_OFF_RAMRET_HWP_OFF; + break; + default: + pr_err("CM Driver(%s(res=%d)): core %u unknown\n", __func__, (int)resource, (unsigned)firstParam); + return CM_INVALID_PARAMETER; + } + if (enable_auto_pm) + prcmu_configure_auto_pm(&osalEnv.dsp_sleep, &osalEnv.dsp_idle); + break; + case CM_OSAL_POWER_SxA_HARDWARE: { + unsigned idx = COREIDX(firstParam); + + if (idx > NB_MPC) { + pr_err("CM Driver(%s(res=%d)): core %u unknown\n", __func__, (int)resource, (unsigned)firstParam); + return CM_INVALID_PARAMETER; + } + if (regulator_enable(osalEnv.mpc[idx].pipe_regulator) < 0) + pr_err("CM Driver(%s): can't enable regulator %s-pipe\n", __func__, osalEnv.mpc[idx].name); + break; + } + case CM_OSAL_POWER_HSEM: + return CM_OK; + case CM_OSAL_POWER_SDRAM: + break; + case CM_OSAL_POWER_ESRAM: + { + int i; + /* firstParam: base address; secondParam: size + U8500_ESRAM_BASE is the start address of BANK 0, + BANK size=0x20000 */ + + /* Compute the relative end address of the range, relative + to base address of BANK1 */ + secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); + + /* if end is below base address of BANK1, it means that full + range of addresses is on Bank0 */ + if (((int)secondParam) < 0) + break; + /* Compute the index of the last bank accessed among esram 1+2 + and esram 3+4 banks */ + secondParam /= 0x40000; + WARN_ON(secondParam > 1); + + /* Compute the index of the first bank accessed among esram 1+2 + and esram 3+4 banks + Do not manage Bank 0 (secured, must be always ON) */ + if (firstParam < (U8500_ESRAM_BASE+0x20000)) + firstParam = 0; + else + firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; + + /* power on the banks 1+2 and 3+4 if accessed. */ + for (i=firstParam; i<=secondParam; i++) { + if (regulator_enable(osalEnv.esram_regulator[i]) < 0) + pr_err("CM Driver(%s): can't enable regulator " + "for esram bank %s\n", __func__, + i ? "34" : "12"); + } + break; + } + default: + pr_err("CM Driver(%s): resource %x unknown/not supported\n", + __func__, (int)resource); + return CM_INVALID_PARAMETER; + } + + return CM_OK; +} + +/*! + * \brief Generate an OS-Panic. Called in from CM_ASSERT(). + * \ingroup CM_ENGINE_OSAL_API + */ +void OSAL_Panic(void) +{ + panic("FATAL ISSUE IN THE CM DRIVER !!"); +} +#include +/*! + * \brief Clean data cache in DDR in order to be accessible from peripheral. + * + * \ingroup CM_ENGINE_OSAL_API + */ +void OSAL_CleanDCache(t_uint32 startAddr, t_uint32 size) +{ +#if 0 + /* + * Currently, the code sections are non-cached/buffered, + * which normally doesn't required the maintenance done below. + * As the cost is low (doesn't do much thing), I keep it in case + * of the memory settings are changed later. + */ + + struct hwmem_region region; + struct mpcConfig *mpc; + t_uint32 endAddr = startAddr + size; + + if (startAddr >= (u32)osalEnv.mpc[0].sdramCodeL + && endAddr <= (u32)(osalEnv.mpc[0].sdramCodeL + + osalEnv.mpc[0].sdramCodeSize)) { + mpc = &osalEnv.mpc[0]; + } else if (startAddr >= (u32)osalEnv.mpc[1].sdramCodeL + && endAddr <= (u32)(osalEnv.mpc[1].sdramCodeL + + osalEnv.mpc[1].sdramCodeSize)) { + mpc = &osalEnv.mpc[1]; + } else { + /* The code may be in esram, in that case, nothing to do */ + return; + } + + region.offset = startAddr - (u32)mpc->sdramCodeL; + region.count = 1; + region.start = 0; + region.end = size; + region.size = size; + hwmem_set_domain(mpc->hwmemCode, HWMEM_ACCESS_READ, + HWMEM_DOMAIN_SYNC, ®ion); + /* + * The hwmem keep track of region being sync or not. + * Mark the region as being write-accessed here right now + * to let following clean being done as expected. Today, + * there is no other place to do that in CM Core right now + */ + hwmem_set_domain(mpc->hwmemCode, HWMEM_ACCESS_WRITE, + HWMEM_DOMAIN_CPU, ®ion); +#else + dsb(); + outer_cache.sync(); +#endif +} + +/*! + * \brief Flush write-buffer of L2 cache + * + * \ingroup CM_ENGINE_OSAL_API + */ +void OSAL_mb(void) +{ + mb(); +} + +/*! + * \brief return prcmu timer value. + * + * This is need for perfmeter api (see \ref t_nmf_power_resource) + * + * \ingroup CM_ENGINE_OSAL_API + */ +t_uint64 OSAL_GetPrcmuTimer() +{ + t_uint64 msbBefore; + t_uint32 lsb; + t_uint64 msbAfter; + + /* read prcmu timers */ + msbBefore = ~ioread32(prcmu_tcdm_base+0xDE4); + lsb = ~ioread32(prcmu_base+0x454); + msbAfter = ~ioread32(prcmu_tcdm_base+0xDE4); + + /* handle rollover test case */ + // NOTE : there is still a window in prcmu side between counter rollover + // and prcmu interrupt handling + // to update msb register => this can lead to erroneous value return here + if (msbBefore == msbAfter || lsb >= 0x80000000UL) + return (((msbBefore & 0xffffffUL) << 32) + lsb); + else + return (((msbAfter & 0xffffffUL) << 32) + lsb); +} + +/*! + * \brief Disable the service message handling (panic, etc) + * + * It must disable the handling of all service messages + * If a service message is currently handled, it must wait till the end + * of its managment before returning. + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_DisableServiceMessages(void) { + tasklet_disable(&cmld_service_tasklet); +} + +/*! + * \brief Enable the service message handling (panic, etc) + * + * It enables the handling of all service messages + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_EnableServiceMessages(void) { + tasklet_enable(&cmld_service_tasklet); +} diff --git a/drivers/staging/nmf-cm/osal-kernel.h b/drivers/staging/nmf-cm/osal-kernel.h new file mode 100644 index 00000000000..fd3b0acc301 --- /dev/null +++ b/drivers/staging/nmf-cm/osal-kernel.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Pierre Peiffer for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef OSAL_KERNEL_H +#define OSAL_KERNEL_H + +#include +#include +#include +#ifdef CONFIG_HAS_WAKELOCK +#include +#endif +#include +#include +#include +#include +#include + +#include "configuration.h" + +/** Per-MPC configuration structure */ +struct mpcConfig { + const t_nmf_core_id coreId; /**< MPC coreId */ + const char *name; /**< MPC name */ + t_uint8 nbYramBanks; /**< number of TCM ram banks to reserve for y memory */ + t_nmf_executive_engine_id eeId; /**< Type of Executive Engine */ + const void *baseP; /**< Physical base address of the MPC */ + void *baseL; /**< Remapped base address of the MPC */ + struct hwmem_alloc *hwmemCode; /**< hwmem code segment */ + u32 sdramCodeP; /**< Physical base address for MPC SDRAM Code region */ + void *sdramCodeL; /**< Remapped base address for MPC SDRAM Code region */ + size_t sdramCodeSize; /**< Size of MPC SDRAM Code region */ + struct hwmem_alloc *hwmemData; /**< hwmem data segment */ + u32 sdramDataP; /**< Physical base address for MPC SDRAM Data region */ + void *sdramDataL; /**< Remapped base address for MPC SDRAM Data region */ + size_t sdramDataSize; /**< Size of MPC SDRAM Data region */ + const unsigned int interrupt0; /**< interrupt line triggered by the MPC, for MPC events (if HSEM not used) */ + const unsigned int interrupt1; /**< interrupt line triggered by the MPC, for PANIC events */ + struct tasklet_struct tasklet; /**< taskket used to process MPC events */ + struct regulator *mmdsp_regulator; /**< mmdsp regulator linked to this MPC */ + struct regulator *pipe_regulator; /**< hardware pipe linked to this MPC */ +#ifdef CONFIG_HAS_WAKELOCK + struct wake_lock wakelock; /**< wakelock for this MPC to prevent ARM to go in APSLEEP state */ +#endif + struct task_struct *monitor_tsk;/**< task to monitor the dsp load; */ + t_cm_mpc_load_counter oldLoadCounter; /**< previous load counter of the DSP */ +}; + +/** Describes current Kernel OSAL environment + * + * Note about mpc.tasklet : we declare one tasklet per MPC but their usage depends + * on cfgSemaphoreTypeHSEM. + * + * This tasklet is scheduled by the interrupt handler to process MPC Events. + * - If we use Hardware Semaphore, there is only one interrupt handler used + * and thus only one tasklet, tasklet of MPC 0 (ie osalEnv.mpc[0].tasklet) + * - If we use local semaphore, there is one interrupt handler and tasklet per mpc + */ +struct OsalEnvironment +{ + struct mpcConfig mpc[NB_MPC]; + void* hwsem_base; /** < Remapped base address of the hardware semaphores */ + void* esram_base; /** < Remapped base address for embedded RAM used within the CM */ + struct regulator *esram_regulator[NB_ESRAM]; /**< regulator for ESRAM bank 1+2 and 3+4 */ + struct prcmu_auto_pm_config dsp_sleep; + struct prcmu_auto_pm_config dsp_idle; +}; + + +/** Structure used to store the skeleton related data. + * It is used for communicattion from a MPC to a user process (=host) + */ +typedef struct { + struct list_head entry; /**< Doubly linked list descriptor */ + t_cm_bf_mpc2host_handle mpc2hostId; /**< mpc2host ID */ + t_nmf_mpc2host_handle upperLayerThis;/**< upper-layer handle */ + struct cm_channel_priv* channelPriv; /**< Per-channel private data. The actual message queue is hold here */ +} t_skelwrapper; + +/** Message description for MPC to HOST communication + */ +struct osal_msg { + struct { + struct plist_node entry; /**< Doubly linked list descriptor */ + t_message_type type; /**< Type of message (callback, service or interrupt for now) */ + } hdr; /**< Header of the message */ +#define msg_entry hdr.entry +#define msg_type hdr.type + union { + struct { + t_skelwrapper *skelwrap; /**< Link to the skelwrapper, to retrieve the channel on which this message has to be forwarded */ + t_uint32 methodIdx; /**< callback data: method index*/ + t_event_params_handle anyPtr; /**< callback data: method parameters */ + t_uint32 ptrSize; /**< size of the parameters */ + } itf; /**< structure holding callback data */ + struct { + t_nmf_service_type srvType; /**< Type of the service */ + t_nmf_service_data srvData; /**< Data of the service */ + } srv; /**< structure holding service data */ + } d; /**< data */ +}; + +extern struct OsalEnvironment osalEnv; + +/** Environment initialization/deinitialization */ +int remapRegions(void); +void unmapRegions(void); + +/** Component manager configuration getters for CM_ENGINE_Init() */ +int getNmfHwMappingDesc(t_nmf_hw_mapping_desc* nmfHwMappingDesc); + +/** Component manager configuration getters for CM_ConfigureMediaProcessorCore (SVA and SIA) */ +void getMpcSystemAddress(unsigned i, t_cm_system_address* mpcSystemAddress); +void getMpcSdramSegments(unsigned i, t_nmf_memory_segment* codeSegment, t_nmf_memory_segment* dataSegment); + +#ifdef CM_DEBUG_ALLOC +struct cm_alloc { + spinlock_t lock; + struct list_head chain; +}; + +struct cm_alloc_elem { + struct list_head elem; + void *caller; + size_t size; + char addr[0]; +}; + +void init_debug_alloc(void); +void cleanup_debug_alloc(void); +#endif /* CM_DEBUG_ALLOC */ + +/* TODO: To remove later */ +extern __iomem void *prcmu_base; +extern __iomem void *prcmu_tcdm_base; +extern const char *cmld_devname[]; + +#define PRCM_SVAMMDSPCLK_MGT (prcmu_base + 0x008) +#define PRCM_SIAMMDSPCLK_MGT (prcmu_base + 0x00c) + +#endif /* OSAL_KERNEL_H */ diff --git a/drivers/staging/nmf-cm/share/communication/inc/communication_fifo.h b/drivers/staging/nmf-cm/share/communication/inc/communication_fifo.h new file mode 100644 index 00000000000..ea24e82ceae --- /dev/null +++ b/drivers/staging/nmf-cm/share/communication/inc/communication_fifo.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef __INC_NMF_COM_FIFO +#define __INC_NMF_COM_FIFO + +#include + +#define EVENT_ELEM_METHOD_IDX 0 +#define EVENT_ELEM_PARAM_IDX 1 +#define EVENT_ELEM_EXTFIELD_IDX 2 + +#define EVENT_ELEM_SIZE_IN_BYTE (3 * sizeof(t_shared_field)) + +#endif /* __INC_NMF_COM_FIFO */ diff --git a/drivers/staging/nmf-cm/share/communication/inc/initializer.h b/drivers/staging/nmf-cm/share/communication/inc/initializer.h new file mode 100644 index 00000000000..ea5aa68f2dc --- /dev/null +++ b/drivers/staging/nmf-cm/share/communication/inc/initializer.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef __INC_SHARE_INITIALIZER +#define __INC_SHARE_INITIALIZER + +#define NMF_CONSTRUCT_INDEX 0 +#define NMF_START_INDEX 1 +#define NMF_STOP_INDEX 2 +#define NMF_DESTROY_INDEX 3 +#define NMF_UPDATE_STACK 4 +#define NMF_LOCK_CACHE 5 +#define NMF_UNLOCK_CACHE 6 +#define NMF_ULP_FORCEWAKEUP 7 +#define NMF_ULP_ALLOWSLEEP 8 +#define NMF_CONSTRUCT_SYNC_INDEX 9 +#define NMF_START_SYNC_INDEX 10 + +/* + * Index of datas in command parameter format + */ +#define INIT_COMPONENT_CMD_HANDLE_INDEX 0 +#define INIT_COMPONENT_CMD_THIS_INDEX 2 +#define INIT_COMPONENT_CMD_METHOD_INDEX 4 +#define INIT_COMPONENT_CMD_SIZE 6 + +/* + * Index of datas in acknowledge parameter format + */ +#define INIT_COMPONENT_ACK_HANDLE_INDEX 0 +#define INIT_COMPONENT_ACK_SIZE 2 + +#endif /* __INC_SHARE_INITIALIZER */ diff --git a/drivers/staging/nmf-cm/share/communication/inc/nmf_fifo_desc.h b/drivers/staging/nmf-cm/share/communication/inc/nmf_fifo_desc.h new file mode 100644 index 00000000000..99caa48b05c --- /dev/null +++ b/drivers/staging/nmf-cm/share/communication/inc/nmf_fifo_desc.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef __INC_NMF_FIFO_DESC +#define __INC_NMF_FIFO_DESC + +#include +#include + +/* + * SHOULD be mapped onto a AHB burst (16 bytes=8x16-bit) + */ +typedef struct { + t_semaphore_id semId; + + t_uint16 elemSize; + t_uint16 fifoFullValue; + t_uint16 readIndex; + t_uint16 writeIndex; + t_uint16 wrappingValue; + + t_uint32 extendedField; /* in DSP 24 memory when to MPC in Logical Host when to ARM */ +} t_nmf_fifo_desc; + +#define EXTENDED_FIELD_BCTHIS_OR_TOP 0 //HOST binding + //MPC binding + //Host binding (today only [0] is used as max size) + +#endif /* __INC_NMF_FIFO */ diff --git a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h new file mode 100644 index 00000000000..5ec08434492 --- /dev/null +++ b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h @@ -0,0 +1,16 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef __INC_NMF_SERVICE_H +#define __INC_NMF_SERVICE_H + +/* 1 - 0xff Reserved for Panic Reason */ +#define MPC_SERVICE_NONE 0 +#define MPC_SERVICE_BOOT 0xB001 +#define MPC_SERVICE_PRINT 0x1234 + +#endif diff --git a/drivers/staging/nmf-cm/share/inc/macros.h b/drivers/staging/nmf-cm/share/inc/macros.h new file mode 100644 index 00000000000..c96fe031c25 --- /dev/null +++ b/drivers/staging/nmf-cm/share/inc/macros.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief NMF Macro API. + */ + +#ifndef _COMMON_MACROS_H_ +#define _COMMON_MACROS_H_ + +#undef ALIGN_VALUE +#define ALIGN_VALUE(value, alignment) (((value) + (alignment - 1)) & ~(alignment - 1)) + +#undef MIN +#define MIN(a,b) (((a)>(b))?(b):(a)) + +#undef MAX +#define MAX(a,b) (((a)<(b))?(b):(a)) + +/*----------------------------------------------------------------------------- + * endianess switch macros (32 bits and 16 bits) + *---------------------------------------------------------------------------*/ +#define ENDIANESS_32_SWITCH(value) ( \ + (((value) & MASK_BYTE3) >> SHIFT_BYTE3) | \ + (((value) & MASK_BYTE2) >> SHIFT_BYTE1) | \ + (((value) & MASK_BYTE1) << SHIFT_BYTE1) | \ + (((value) & MASK_BYTE0) << SHIFT_BYTE3) \ + ) + +#define ENDIANESS_16_SWITCH(value) ( \ + (((value) & MASK_BYTE0) << SHIFT_BYTE1) | \ + (((value) & MASK_BYTE1) >> SHIFT_BYTE1) \ + ) + +/*----------------------------------------------------------------------------- + * field offset extraction from a structure + *---------------------------------------------------------------------------*/ +#undef FIELD_OFFSET +#define FIELD_OFFSET(typeName, fieldName) ((t_uint32)(&(((typeName *)0)->fieldName))) + +#undef MASK_BIT +#define MASK_BIT(n) (1UL << ((n) - 1)) + +/*----------------------------------------------------------------------------- + * Misc definition + *---------------------------------------------------------------------------*/ + +#undef ONE_KB +#define ONE_KB (1024) +#undef ONE_MB +#define ONE_MB (ONE_KB * ONE_KB) + +/*----------------------------------------------------------------------------- + * Bit mask definition + *---------------------------------------------------------------------------*/ +#undef MASK_NULL8 +#define MASK_NULL8 0x00U +#undef MASK_NULL16 +#define MASK_NULL16 0x0000U +#undef MASK_NULL32 +#define MASK_NULL32 0x00000000UL +#undef MASK_ALL8 +#define MASK_ALL8 0xFFU +#undef MASK_ALL16 +#define MASK_ALL16 0xFFFFU +#undef MASK_ALL32 +#define MASK_ALL32 0xFFFFFFFFUL + +#undef MASK_BIT0 +#define MASK_BIT0 (1UL<<0) +#undef MASK_BIT1 +#define MASK_BIT1 (1UL<<1) +#undef MASK_BIT2 +#define MASK_BIT2 (1UL<<2) +#undef MASK_BIT3 +#define MASK_BIT3 (1UL<<3) +#undef MASK_BIT4 +#define MASK_BIT4 (1UL<<4) +#undef MASK_BIT5 +#define MASK_BIT5 (1UL<<5) +#undef MASK_BIT6 +#define MASK_BIT6 (1UL<<6) +#undef MASK_BIT7 +#define MASK_BIT7 (1UL<<7) +#undef MASK_BIT8 +#define MASK_BIT8 (1UL<<8) +#undef MASK_BIT9 +#define MASK_BIT9 (1UL<<9) +#undef MASK_BIT10 +#define MASK_BIT10 (1UL<<10) +#undef MASK_BIT11 +#define MASK_BIT11 (1UL<<11) +#undef MASK_BIT12 +#define MASK_BIT12 (1UL<<12) +#undef MASK_BIT13 +#define MASK_BIT13 (1UL<<13) +#undef MASK_BIT14 +#define MASK_BIT14 (1UL<<14) +#undef MASK_BIT15 +#define MASK_BIT15 (1UL<<15) +#undef MASK_BIT16 +#define MASK_BIT16 (1UL<<16) +#undef MASK_BIT17 +#define MASK_BIT17 (1UL<<17) +#undef MASK_BIT18 +#define MASK_BIT18 (1UL<<18) +#undef MASK_BIT19 +#define MASK_BIT19 (1UL<<19) +#undef MASK_BIT20 +#define MASK_BIT20 (1UL<<20) +#undef MASK_BIT21 +#define MASK_BIT21 (1UL<<21) +#undef MASK_BIT22 +#define MASK_BIT22 (1UL<<22) +#undef MASK_BIT23 +#define MASK_BIT23 (1UL<<23) +#undef MASK_BIT24 +#define MASK_BIT24 (1UL<<24) +#undef MASK_BIT25 +#define MASK_BIT25 (1UL<<25) +#undef MASK_BIT26 +#define MASK_BIT26 (1UL<<26) +#undef MASK_BIT27 +#define MASK_BIT27 (1UL<<27) +#undef MASK_BIT28 +#define MASK_BIT28 (1UL<<28) +#undef MASK_BIT29 +#define MASK_BIT29 (1UL<<29) +#undef MASK_BIT30 +#define MASK_BIT30 (1UL<<30) +#undef MASK_BIT31 +#define MASK_BIT31 (1UL<<31) + +/*----------------------------------------------------------------------------- + * quartet shift definition + *---------------------------------------------------------------------------*/ +#undef MASK_QUARTET +#define MASK_QUARTET (0xFUL) +#undef SHIFT_QUARTET0 +#define SHIFT_QUARTET0 0 +#undef SHIFT_QUARTET1 +#define SHIFT_QUARTET1 4 +#undef SHIFT_QUARTET2 +#define SHIFT_QUARTET2 8 +#undef SHIFT_QUARTET3 +#define SHIFT_QUARTET3 12 +#undef SHIFT_QUARTET4 +#define SHIFT_QUARTET4 16 +#undef SHIFT_QUARTET5 +#define SHIFT_QUARTET5 20 +#undef SHIFT_QUARTET6 +#define SHIFT_QUARTET6 24 +#undef SHIFT_QUARTET7 +#define SHIFT_QUARTET7 28 +#undef MASK_QUARTET0 +#define MASK_QUARTET0 (MASK_QUARTET << SHIFT_QUARTET0) +#undef MASK_QUARTET1 +#define MASK_QUARTET1 (MASK_QUARTET << SHIFT_QUARTET1) +#undef MASK_QUARTET2 +#define MASK_QUARTET2 (MASK_QUARTET << SHIFT_QUARTET2) +#undef MASK_QUARTET3 +#define MASK_QUARTET3 (MASK_QUARTET << SHIFT_QUARTET3) +#undef MASK_QUARTET4 +#define MASK_QUARTET4 (MASK_QUARTET << SHIFT_QUARTET4) +#undef MASK_QUARTET5 +#define MASK_QUARTET5 (MASK_QUARTET << SHIFT_QUARTET5) +#undef MASK_QUARTET6 +#define MASK_QUARTET6 (MASK_QUARTET << SHIFT_QUARTET6) +#undef MASK_QUARTET7 +#define MASK_QUARTET7 (MASK_QUARTET << SHIFT_QUARTET7) + +/*----------------------------------------------------------------------------- + * Byte shift definition + *---------------------------------------------------------------------------*/ +#undef MASK_BYTE +#define MASK_BYTE (0xFFUL) +#undef SHIFT_BYTE0 +#define SHIFT_BYTE0 0U +#undef SHIFT_BYTE1 +#define SHIFT_BYTE1 8U +#undef SHIFT_BYTE2 +#define SHIFT_BYTE2 16U +#undef SHIFT_BYTE3 +#define SHIFT_BYTE3 24U +#undef MASK_BYTE0 +#define MASK_BYTE0 (MASK_BYTE << SHIFT_BYTE0) +#undef MASK_BYTE1 +#define MASK_BYTE1 (MASK_BYTE << SHIFT_BYTE1) +#undef MASK_BYTE2 +#define MASK_BYTE2 (MASK_BYTE << SHIFT_BYTE2) +#undef MASK_BYTE3 +#define MASK_BYTE3 (MASK_BYTE << SHIFT_BYTE3) + +/*----------------------------------------------------------------------------- + * Halfword shift definition + *---------------------------------------------------------------------------*/ +#undef MASK_HALFWORD +#define MASK_HALFWORD (0xFFFFUL) +#undef SHIFT_HALFWORD0 +#define SHIFT_HALFWORD0 0U +#undef SHIFT_HALFWORD1 +#define SHIFT_HALFWORD1 16U +#undef MASK_HALFWORD0 +#define MASK_HALFWORD0 (MASK_HALFWORD << SHIFT_HALFWORD0) +#undef MASK_HALFWORD1 +#define MASK_HALFWORD1 (MASK_HALFWORD << SHIFT_HALFWORD1) + +#endif /* _COMMON_MACROS_H_ */ + diff --git a/drivers/staging/nmf-cm/share/inc/nmf.h b/drivers/staging/nmf-cm/share/inc/nmf.h new file mode 100644 index 00000000000..8be8b41e5e3 --- /dev/null +++ b/drivers/staging/nmf-cm/share/inc/nmf.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \brief Common Nomadik Multiprocessing Framework type definition + * + * This file contains the shared type definitions used into NMF. + */ + +#ifndef __INC_NMF_H +#define __INC_NMF_H + +#include + +/*! + * \brief Identification of the various cores (host cpu and Media Processors) into Nomadik Platform + * In order to improve performance, these ids are those used to interconnect HW Semaphores IP with Cores (Interrupt lines) + * \ingroup NMF_COMMON + */ +#if defined(__STN_8500) + //#warning "TODO : mapping below is not correct, need to think how to change it" +#endif +typedef t_uint8 t_nmf_core_id; +#define ARM_CORE_ID ((t_nmf_core_id)0) //!< HOST CPU Id +#define SVA_CORE_ID ((t_nmf_core_id)1) //!< Smart Video Accelerator Media Processor Code Id +#define SIA_CORE_ID ((t_nmf_core_id)2) //!< Smart Imaging Accelerator Media Processor Code Id +#define NB_CORE_IDS ((t_nmf_core_id)3) + +#define FIRST_CORE_ID ((t_nmf_core_id)ARM_CORE_ID) +#define FIRST_MPC_ID ((t_nmf_core_id)SVA_CORE_ID) +#define LAST_CORE_ID ((t_nmf_core_id)SIA_CORE_ID) +#define LAST_MPC_ID ((t_nmf_core_id)SIA_CORE_ID) + + +/*! + * \brief Define minimal stack size use by execution engine + */ +#define MIN_STACK_SIZE 128 + + + +#endif /* __INC_NMF_H */ diff --git a/drivers/staging/nmf-cm/share/inc/nomadik_mapping.h b/drivers/staging/nmf-cm/share/inc/nomadik_mapping.h new file mode 100644 index 00000000000..bec221aa111 --- /dev/null +++ b/drivers/staging/nmf-cm/share/inc/nomadik_mapping.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef __INC_NOMADIK_MAPPING_H +#define __INC_NOMADIK_MAPPING_H + +/*--------------------------------------------------------------------------*/ +#if defined(__STN_8810) + +/* XTI (CPU OSMO/OSMOT address space) */ +#define XTI_CPU_BASE_ADDR 0x10000000 +#define XTI_CPU_END_ADDR 0x100FFFFF + +/* XTI configuration registers */ +#define XTI_CFG_REG_BASE_ADDR 0x101A0000 +#define XTI_CFG_REG_END_ADDR 0x101AFFFF + +/* Core APB Peripherals */ +#define CORE_APB_BASE_ADDR 0x101E0000 +#define CORE_APB_END_ADDR 0x101EFFFF + +/* DMA APB Peripherals */ +#define DMA_APB_BASE_ADDR 0x101F0000 +#define DMA_APB_END_ADDR 0x101FFFFF + +/* XTI (DSP OSMO/OSMOT address space) */ +#define XTI_DSP_BASE_ADDR 0x10200000 +#define XTI_DSP_END_ADDR 0x1020FFFF + +#endif /* defined(__STN_8810) */ + +/*--------------------------------------------------------------------------*/ +#if defined(__STN_8815) + +/* XTI (CPU OSMO/OSMOT address space) */ +#define XTI_CPU_BASE_ADDR 0x10000000 +#define XTI_CPU_END_ADDR 0x100FFFFF + +/* XTI configuration registers */ +#define XTI_CFG_REG_BASE_ADDR 0x101A0000 +#define XTI_CFG_REG_END_ADDR 0x101AFFFF + +/* Core APB Peripherals */ +#define CORE_APB_BASE_ADDR 0x101E0000 +#define CORE_APB_END_ADDR 0x101EFFFF + +/* DMA APB Peripherals */ +#define DMA_APB_BASE_ADDR 0x101F0000 +#define DMA_APB_END_ADDR 0x101FFFFF + +/* XTI (DSP OSMO/OSMOT address space) */ +#define XTI_DSP_BASE_ADDR 0x10220000 +#define XTI_DSP_END_ADDR 0x1022FFFF + +#endif /* defined(__STN_8815) */ + + +/*--------------------------------------------------------------------------*/ +#if defined(__STN_8820) + +/* STM (System Trace Module address space) */ +#define STM_BASE_ADDR 0x700F0000 +#define STM_END_ADDR 0x700FFFFF + +/* AHB2 Peripherals */ +#define AHB2_PERIPH_BASE_ADDR 0x70100000 +#define AHB2_PERIPH_END_ADDR 0x7010FFFF + +/* APB2 Peripherals */ +#define APB2_PERIPH_BASE_ADDR 0x70110000 +#define APB2_PERIPH_END_ADDR 0x7011FFFF + +/* APB1 Peripherals */ +#define APB1_PERIPH_BASE_ADDR 0x70120000 +#define APB1_PERIPH_END_ADDR 0x7012FFFF + +#endif /* defined(__STN_8820) */ + +/*--------------------------------------------------------------------------*/ +#if defined(__STN_8500) +/* STM (System Trace Module address space) */ +#define STM_BASE_ADDR 0x80100000 +#define STM_END_ADDR 0x8010FFFF + +#define HSEM_BASE_ADDR 0x80140000 +#define HSEM_END_ADDR 0x8014FFFF + +#define DMA_CTRL_BASE_ADDR 0x801C0000 +#define DMA_CTRL_END_ADDR 0x801C0FFF + + +#endif /* defined(__STN_8500) */ + +#endif /*__INC_NOMADIK_MAPPING_H */ diff --git a/drivers/staging/nmf-cm/share/semaphores/inc/hwsem_hwp.h b/drivers/staging/nmf-cm/share/semaphores/inc/hwsem_hwp.h new file mode 100644 index 00000000000..b573627beae --- /dev/null +++ b/drivers/staging/nmf-cm/share/semaphores/inc/hwsem_hwp.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef __INC_HWSEM_HWP_H +#define __INC_HWSEM_HWP_H + +#include + +#define CORE_ID_2_HW_CORE_ID(coreId) (1U << (coreId)) + +/* + * Definition of the number of hw semaphores into the Nomadik IP + */ +#define NUM_HW_SEMAPHORES 32 + + +/* + * Definition of how HSEM IP interrupts are interconnected with cores + */ +typedef enum { + HSEM_FIRST_INTR = 0, + HSEM_INTRA = HSEM_FIRST_INTR, + HSEM_INTRB = 1, + HSEM_INTRC = 2, + HSEM_INTRD = 3, + HSEM_INTRE = 4, + HSEM_MAX_INTR +} t_hw_semaphore_irq_id; + +/* + * Description of the registers of the HW Sem IP + */ +#define HSEM_INTRA_MASK (1<<(4+HSEM_INTRA)) +#define HSEM_INTRB_MASK (1<<(4+HSEM_INTRB)) +#define HSEM_INTRC_MASK (1<<(4+HSEM_INTRC)) +#define HSEM_INTRD_MASK (1<<(4+HSEM_INTRD)) +#define HSEM_INTRE_MASK (1<<(4+HSEM_INTRE)) + +typedef struct { + t_shared_reg imsc; + t_shared_reg ris; + t_shared_reg mis; + t_shared_reg icr; +} t_hsem_it_regs; + +typedef volatile struct { +#if defined(__STN_8500) + t_shared_reg cr; + t_shared_reg dummy; +#endif + t_shared_reg sem[NUM_HW_SEMAPHORES]; +#if defined(__STN_8820) + t_shared_reg RESERVED1[(0x90 - 0x80)>>2]; +#elif defined(__STN_8500) + t_shared_reg RESERVED1[(0x90 - 0x88)>>2]; +#else /* __STN_8820 or __STN_8500 -> _STN_8815 */ + t_shared_reg RESERVED1[(0x90 - 0x40)>>2]; +#endif /* __STN_8820 or __STN_8500 -> _STN_8815 */ + t_shared_reg icrall; + t_shared_reg RESERVED2[(0xa0 - 0x94)>>2]; + t_hsem_it_regs it[HSEM_MAX_INTR]; +#if defined(__STN_8820) || defined(__STN_8500) + t_shared_reg RESERVED3[(0x100 - 0xf0)>>2]; +#else /* __STN_8820 or __STN_8500 -> _STN_8815 */ + t_shared_reg RESERVED3[(0x100 - 0xe0)>>2]; +#endif /* __STN_8820 or __STN_8500 -> _STN_8815 */ + t_shared_reg itcr; + t_shared_reg RESERVED4; + t_shared_reg itop; + t_shared_reg RESERVED5[(0xfe0 - 0x10c)>>2]; + t_shared_reg pid0; + t_shared_reg pid1; + t_shared_reg pid2; + t_shared_reg pid3; + t_shared_reg pcid0; + t_shared_reg pcid1; + t_shared_reg pcid2; + t_shared_reg pcid3; +} t_hw_semaphore_regs, *tp_hw_semaphore_regs; + +#endif /* __INC_HWSEM_HWP_H */ diff --git a/drivers/staging/nmf-cm/share/semaphores/inc/semaphores.h b/drivers/staging/nmf-cm/share/semaphores/inc/semaphores.h new file mode 100644 index 00000000000..c72b64cd709 --- /dev/null +++ b/drivers/staging/nmf-cm/share/semaphores/inc/semaphores.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) ST-Ericsson SA 2010. All rights reserved. + * This code is ST-Ericsson proprietary and confidential. + * Any use of the code for whatever purpose is subject to + * specific written permission of ST-Ericsson SA. + */ + +#ifndef __INC_SHARED_SEMAPHORE_H +#define __INC_SHARED_SEMAPHORE_H + +#include + +typedef t_uint16 t_semaphore_id; + +/* + * HW semaphore allocation + * ----------------------- + * We want to optimize interrupt demultiplexing at dsp interrupt handler level + * so a good solution would be to have sequentially the semaphores for each neighbors + * + * STn8500 : + * --------- + * ARM <- SVA COMS => 0 + * ARM <- SIA COMS => 1 + * SVA <- ARM COMS => 2 + * SVA <- SIA COMS => 3 + * SIA <- ARM COMS => 4 + * SIA <- SVA COMS => 5 + + * The first neighbor is always the ARM, then the other ones (SVA,SIA) + */ + +/* + * Local semaphore allocation + * ----------------------- + * 0 : ARM <- DSP + * 1 : DSP <- ARM + */ + +#define NB_USED_HSEM_PER_CORE (NB_CORE_IDS - 1) +#define FIRST_NEIGHBOR_SEMID(coreId) ((coreId)*NB_USED_HSEM_PER_CORE) + +#endif /* __INC_SHARED_SEMAPHORE_H */ -- cgit v1.2.3 From 1566c124c1325a566608c37af06646df2e5407d1 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Wed, 22 Jun 2011 21:30:54 +0200 Subject: staging: Add support in mmio driver for u5500 Signed-off-by: Robert Marklund --- drivers/staging/mmio/mmio.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/mmio/mmio.h b/drivers/staging/mmio/mmio.h index 9dee32055ef..1c6f68e3556 100644 --- a/drivers/staging/mmio/mmio.h +++ b/drivers/staging/mmio/mmio.h @@ -12,6 +12,7 @@ #include #define MMIO_NAME "mmio_camera" +#define SRA_SUPPORT 1 #ifdef SRA_SUPPORT #define SREG_16_BIT (0x1) -- cgit v1.2.3 From ec8f5c355f97153a0adcf9370b8b3cf468aef74a Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 16 Jun 2011 17:10:36 +0200 Subject: mach-ux500: Adding Support for U5500 Camera Board This change will allow users to use B5500/S5500 Camera ST-Ericsson Linux next: NA ST-Ericsson ID: ST-Ericsson FOSS-OUT ID: Trivial Change-Id: If26b76e2f400e2c67cdb555454e92cbcef5b65d4 Signed-off-by: Nikhil Bhandary Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/23087 Reviewed-by: QATEST Reviewed-by: Jonas ABERG --- arch/arm/mach-ux500/board-u5500-mmio.c | 387 +++++++++++++++++++++++++++++++++ drivers/staging/mmio/Kconfig | 4 + 2 files changed, 391 insertions(+) create mode 100644 arch/arm/mach-ux500/board-u5500-mmio.c diff --git a/arch/arm/mach-ux500/board-u5500-mmio.c b/arch/arm/mach-ux500/board-u5500-mmio.c new file mode 100644 index 00000000000..e88dafb90e8 --- /dev/null +++ b/arch/arm/mach-ux500/board-u5500-mmio.c @@ -0,0 +1,387 @@ +/* + * Copyright (C) 2011 ST-Ericsson + * Author: Joakim Axelsson for ST-Ericsson + * Author: Rajat Verma for ST-Ericsson. + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "board-u5500.h" + +struct mmio_board_data{ + int number_of_regulators; + struct regulator **mmio_regulators; + /* * Pin configs */ + struct mmio_gpio xshutdown_pins[CAMERA_SLOT_END]; + /* * Internal clocks */ + struct clk *clk_ptr_bml; + struct clk *clk_ptr_ipi2c; + /* * External clocks */ + struct clk *clk_ptr_ext[CAMERA_SLOT_END]; +}; + +/* + * Fill names of regulators required for powering up the + * camera sensor in below array + */ +static char *regulator_names[] = {"v-mmio-camera" , "v-ana"}; + +static int mmio_clock_init(struct mmio_platform_data *pdata) +{ + int err; + struct mmio_board_data *extra = pdata->extra; + + extra->clk_ptr_ext[PRIMARY_CAMERA] = + clk_get(pdata->dev, "primary-cam"); + if (IS_ERR(extra->clk_ptr_ext[PRIMARY_CAMERA])) { + err = PTR_ERR(extra->clk_ptr_ext[PRIMARY_CAMERA]); + dev_err(pdata->dev, + "Error %d clock 'primary-cam'\n", err); + goto err_pri_ext_clk; + } + extra->clk_ptr_ext[SECONDARY_CAMERA] = + clk_get(pdata->dev, "secondary-cam"); + if (IS_ERR(extra->clk_ptr_ext[SECONDARY_CAMERA])) { + err = PTR_ERR(extra->clk_ptr_ext[SECONDARY_CAMERA]); + dev_err(pdata->dev, + "Error %d clock 'secondary-cam'\n", err); + goto err_sec_ext_clk; + } + + return 0; +err_sec_ext_clk: + clk_put(extra->clk_ptr_ext[PRIMARY_CAMERA]); +err_pri_ext_clk: + return err; +} + +static void mmio_clock_exit(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + + clk_put(extra->clk_ptr_ext[PRIMARY_CAMERA]); + clk_put(extra->clk_ptr_ext[SECONDARY_CAMERA]); +} + +static int mmio_pin_cfg_init(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + + extra->xshutdown_pins[PRIMARY_CAMERA].gpio = + GPIO_PRIMARY_CAM_XSHUTDOWN; + extra->xshutdown_pins[PRIMARY_CAMERA].active_high = 0; + extra->xshutdown_pins[PRIMARY_CAMERA].udelay = 250; + + extra->xshutdown_pins[SECONDARY_CAMERA].gpio = + GPIO_SECONDARY_CAM_XSHUTDOWN; + extra->xshutdown_pins[SECONDARY_CAMERA].active_high = 0; + extra->xshutdown_pins[SECONDARY_CAMERA].udelay = 250; + + return 0; +} + +static void mmio_pin_cfg_exit(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; +} + +/* + * For now, both sensors on B5500/S5500 have some power up sequence. If + * different sequences are needed for primary and secondary sensors, it can + * be implemented easily. Just use camera_slot field of mmio_platform_data + * to determine which camera needs to be powered up + */ +static int mmio_power_init(struct mmio_platform_data *pdata) +{ + int err = 0, i = 0; + struct mmio_board_data *extra = pdata->extra; + + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + extra->number_of_regulators = ARRAY_SIZE(regulator_names); + extra->mmio_regulators = + kzalloc(sizeof(struct regulator *) * extra->number_of_regulators, + GFP_KERNEL); + if (!extra->mmio_regulators) { + dev_err(pdata->dev + , "Error allocating memory for mmio regulators\n"); + err = -ENOMEM; + goto err_no_mem_reg; + } + for (i = 0; i < + extra->number_of_regulators; i++) { + extra->mmio_regulators[i] = + regulator_get(pdata->dev, regulator_names[i]); + if (IS_ERR(extra->mmio_regulators[i])) { + err = PTR_ERR(extra->mmio_regulators[i]); + dev_err(pdata->dev + , "Error %d getting regulator '%s'\n" + , err, regulator_names[i]); + goto err_regulator; + } + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_regulator: + /* + * Return regulators we have already requested + */ + while (i--) + regulator_put(extra->mmio_regulators[i]); + kfree(extra->mmio_regulators); +err_no_mem_reg: + return err; +} + +static void mmio_power_exit(struct mmio_platform_data *pdata) +{ + int i = 0; + struct mmio_board_data *extra = pdata->extra;; + + for (i = 0; i < extra->number_of_regulators; i++) + regulator_put(extra->mmio_regulators[i]); + kfree(extra->mmio_regulators); +} + +static int mmio_platform_init(struct mmio_platform_data *pdata) +{ + int err = 0; + struct mmio_board_data *extra = NULL; + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* + * Alloc memory for our own extra data + */ + extra = kzalloc(sizeof(struct mmio_board_data), GFP_KERNEL); + if (!extra) { + dev_err(pdata->dev, "%s: memory alloc failed for " + "mmio_board_data\n", __func__); + err = -ENOMEM; + goto err_no_mem_extra; + } + /* + * Hook the data for other callbacks to use + */ + pdata->extra = extra; + + pdata->camera_slot = -1; + + err = mmio_power_init(pdata); + if (err) + goto err_regulator; + err = mmio_clock_init(pdata); + if (err) + goto err_clock; + err = mmio_pin_cfg_init(pdata); + if (err) + goto err_pin_cfg; + + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; + +err_pin_cfg: + mmio_clock_exit(pdata); +err_clock: + mmio_power_exit(pdata); +err_regulator: + kfree(extra); +err_no_mem_extra: + return err; +} + +static void mmio_platform_exit(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + + mmio_power_exit(pdata); + mmio_clock_exit(pdata); + mmio_pin_cfg_exit(pdata); + kfree(extra); + pdata->extra = NULL; +} + +static int mmio_power_enable(struct mmio_platform_data *pdata) +{ + int err = 0, i = 0; + struct mmio_board_data *extra = pdata->extra; + + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + /* + * Enable the regulators + */ + for (i = 0; i < extra->number_of_regulators; i++) { + err = regulator_enable(extra->mmio_regulators[i]); + if (IS_ERR(extra->mmio_regulators[i])) { + err = PTR_ERR(extra->mmio_regulators[i]); + dev_err(pdata->dev , "Error %d enabling regulator '%s'" + "\n", err, regulator_names[i]); + goto err_regulator; + } + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_regulator: + /* + * Disable regulators we already enabled + */ + while (i--) + regulator_disable(extra->mmio_regulators[i]); + return err; +} + +static void mmio_power_disable(struct mmio_platform_data *pdata) +{ + int i; + struct mmio_board_data *extra = pdata->extra; + /* + * Disable the regulators + */ + for (i = 0; i < extra->number_of_regulators; i++) + regulator_disable(extra->mmio_regulators[i]); +} + +static int mmio_clock_enable(struct mmio_platform_data *pdata) +{ + int err = 0; + struct mmio_board_data *extra = pdata->extra; + + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + + /* + * Enable appropriate external clock + */ + err = clk_enable(extra->clk_ptr_ext[pdata->camera_slot]); + if (err) { + dev_err(pdata->dev, "Error activating clock for sensor %d, err" + "%d\n", pdata->camera_slot, err); + goto err_ext_clk; + } + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); + return 0; +err_ext_clk: + return err; +} + +static void mmio_clock_disable(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + + clk_disable(extra->clk_ptr_ext[pdata->camera_slot]); +} + +static int mmio_config_xshutdown_pins(struct mmio_platform_data *pdata, + enum mmio_select_xshutdown_t select, + int is_active_high) +{ + int err = 0; + struct mmio_board_data *extra = pdata->extra; + + dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); + switch (select) { + case MMIO_ENABLE_XSHUTDOWN_HOST: + extra->xshutdown_pins[pdata->camera_slot].active_high = + is_active_high; + dev_dbg(pdata->dev , "Enabling Xshutdown GPIO PIN = %d", + extra->xshutdown_pins[pdata->camera_slot].gpio); + + err = gpio_request + (extra->xshutdown_pins[pdata->camera_slot].gpio, + "MMIO GPIO"); + if (err) { + dev_err(pdata->dev, "Error %d while requesting" + "Xshutdown MMIO GPIO\n", + err); + return err; + } + + err = gpio_direction_output + (extra->xshutdown_pins[pdata->camera_slot].gpio, + 0); + if (err) { + dev_err(pdata->dev, "Error %d while setting" + "Xshutdown MMIO GPIO" + "output mode\n", err); + return err; + } + break; + case MMIO_DISABLE_XSHUTDOWN: + dev_dbg(pdata->dev , "Disabling Xshutdown GPIO PIN = %d", + extra->xshutdown_pins[pdata->camera_slot].gpio); + gpio_free(extra->xshutdown_pins[pdata->camera_slot].gpio); + break; + default: + break; + } + if (err) + dev_err(pdata->dev , "Error configuring xshutdown, err = %d\n", + err); + return err; +} + +static void mmio_set_xshutdown(struct mmio_platform_data *pdata) +{ + struct mmio_board_data *extra = pdata->extra; + + gpio_set_value(extra->xshutdown_pins[pdata->camera_slot].gpio , + (extra->xshutdown_pins[pdata->camera_slot].active_high + ? 1 : 0)); + udelay(extra->xshutdown_pins[pdata->camera_slot].udelay); +} + +/* + * TODO: This function would be removed in futute. + * Since this function is called frequently + * from HSM Camera code , it is kept for Legacy. + */ +static int mmio_config_i2c_pins(struct mmio_platform_data *pdata, + enum mmio_select_i2c_t select) +{ + int err = 0; + + switch (select) { + case MMIO_ACTIVATE_I2C_HOST: + dev_dbg(pdata->dev , "Activate I2C from Host called\n"); + break; + case MMIO_DEACTIVATE_I2C: + dev_dbg(pdata->dev , "DeActivate I2C from Host called\n"); + break; + default: + break; + } + + return err; +} + +static struct mmio_platform_data mmio_config = { + .platform_init = mmio_platform_init, + .platform_exit = mmio_platform_exit, + .power_enable = mmio_power_enable, + .power_disable = mmio_power_disable, + .clock_enable = mmio_clock_enable, + .clock_disable = mmio_clock_disable, + .config_i2c_pins = mmio_config_i2c_pins, + .config_xshutdown_pins = mmio_config_xshutdown_pins, + .set_xshutdown = mmio_set_xshutdown +}; + +struct platform_device u5500_mmio_device = { + .name = MMIO_NAME, + .id = -1, + .dev = { + .platform_data = &mmio_config, + } +}; diff --git a/drivers/staging/mmio/Kconfig b/drivers/staging/mmio/Kconfig index eb4a93e2545..d6a5a9ad918 100644 --- a/drivers/staging/mmio/Kconfig +++ b/drivers/staging/mmio/Kconfig @@ -5,3 +5,7 @@ config U8500_MMIO help Enables the ST-Ericsson MMIO (Camera) Driver +config U5500_MMIO + bool "ST-Ericsson U5500 MMIO (Camera) Driver" + depends on UX500_SOC_DB5500 + -- cgit v1.2.3 From 821308fa3824e39b05e6e76b42b645c7734be54f Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 17 Jun 2011 09:58:22 +0200 Subject: ux500: mmio: Fix 2.6.38 ioctl porting Signed-off-by: Philippe Langlais --- drivers/staging/mmio/st_mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/mmio/st_mmio.c b/drivers/staging/mmio/st_mmio.c index 1dc82a9671b..b7f2cc997e6 100644 --- a/drivers/staging/mmio/st_mmio.c +++ b/drivers/staging/mmio/st_mmio.c @@ -513,7 +513,7 @@ out: return ret; } -static int mmio_ioctl(struct inode *node, struct file *filp, u32 cmd, +static long mmio_ioctl(struct file *filp, u32 cmd, unsigned long arg) { struct mmio_input_output_t data; -- cgit v1.2.3 From 96d29093cb4ac7439d026ca2ff8c55b67b3010c8 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Thu, 23 Jun 2011 13:20:42 +0200 Subject: staging: nmf-cm: Update for api changes in 3.0 Temp fix to make driver build until its fixed properly Change-Id: I095a907abed7175180cbfa4bd2bc389060afceb1 Signed-off-by: Robert Marklund --- drivers/staging/nmf-cm/cm_service.c | 1 + drivers/staging/nmf-cm/cm_syscall.c | 7 ++++--- drivers/staging/nmf-cm/cmld.c | 1 + drivers/staging/nmf-cm/osal-kernel.h | 1 + 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index 1b5ee111e09..cd7602a6cec 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -14,6 +14,7 @@ #include #include #include +#include #include diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index d1ad3a1f935..8a48ac10c60 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -1374,12 +1374,13 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd /* Mark this memory area reserved for a mapping for this thread ID */ /* It must not be already reserved but this should not happen */ if (curr->tid) { - pr_err("%s: thread %d can't reseveved memory %x already " + /*pr_err("%s: thread %d can't reseveved memory %x already " "reserved for %d\n", - __func__, current->pid, physAddr, curr->tid); + __func__, current->pid, physAddr, (int)curr->tid);*/ err = -EBUSY; } else { - curr->tid = current->pid; + curr->tid = 0; + //current->pid; err = 0; } break; diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 04433f10f0c..9a7183c14fc 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include diff --git a/drivers/staging/nmf-cm/osal-kernel.h b/drivers/staging/nmf-cm/osal-kernel.h index fd3b0acc301..36baf893fcc 100644 --- a/drivers/staging/nmf-cm/osal-kernel.h +++ b/drivers/staging/nmf-cm/osal-kernel.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "configuration.h" -- cgit v1.2.3 From a665f73d6f3244eb176163e48cce1ae56f96c203 Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Thu, 23 Jun 2011 13:21:41 +0200 Subject: staging: mmio: Use local header file Change-Id: I699cc94a62f8068bb42645b4c3ad4c9a22308499 Signed-off-by: Robert Marklund --- drivers/staging/mmio/st_mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/mmio/st_mmio.c b/drivers/staging/mmio/st_mmio.c index b7f2cc997e6..696644ae835 100644 --- a/drivers/staging/mmio/st_mmio.c +++ b/drivers/staging/mmio/st_mmio.c @@ -12,13 +12,13 @@ #include /* Defines standard err codes */ #include #include -#include #include #include #include #include #include #include +#include "mmio.h" #define ISP_REGION_IO (0xE0000000) #define SIA_ISP_REG_ADDR (0x521E4) -- cgit v1.2.3 From 2a3bdf199f9ad39b0b1dfff468332fa3ff89ea7b Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Thu, 23 Jun 2011 13:24:47 +0200 Subject: staging: camera-flash: Add missing include file Change-Id: I933543cbc2c1e79688f4f0b8c624c3b75f88d79c Signed-off-by: Robert Marklund --- drivers/staging/camera_flash/flash_common.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/camera_flash/flash_common.h b/drivers/staging/camera_flash/flash_common.h index 1153badddd1..d1f63631e82 100755 --- a/drivers/staging/camera_flash/flash_common.h +++ b/drivers/staging/camera_flash/flash_common.h @@ -2,6 +2,7 @@ #define __FLASH_COMMON_H__ #include "camera_flash_bitfields.h" +#include "camera_flash.h" struct flash_chip_ops{ int (*get_modes)( void *priv_data, unsigned long *modes); -- cgit v1.2.3 From f952adcb3cc9ce939fb6961bdcb1e275cc82d05f Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 14 Oct 2011 15:23:29 +0200 Subject: mach-ux500: Fix for gpio header move Signed-off-by: Robert Marklund --- arch/arm/mach-ux500/board-mop500-mmio.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-ux500/board-mop500-mmio.c b/arch/arm/mach-ux500/board-mop500-mmio.c index 762ac2553bc..975db6f7af8 100644 --- a/arch/arm/mach-ux500/board-mop500-mmio.c +++ b/arch/arm/mach-ux500/board-mop500-mmio.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 308a10ac2f80b34e930800d6c9bcfcd5e65b33b1 Mon Sep 17 00:00:00 2001 From: Rickard Andersson Date: Wed, 15 Jun 2011 15:50:23 +0200 Subject: drivers:nmf-cm: Correct handling of CR register This patch changes to using read-modify-write sequence when modifying content in the CR register in peripheral block 6. Without this patch secure world can hang during suspend/resume deep sleep with ESRAM0 turned off. This happend because important settings in CR register was lost. ST-Ericsson Linux next: - ST-Ericsson ID: ER345629 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I524e8ed307bca5645aecbcebf26317474234490b Signed-off-by: Rickard Andersson Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25174 Reviewed-by: Pierre PEIFFER Reviewed-by: Jonas ABERG --- drivers/staging/nmf-cm/cmld.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 9a7183c14fc..5b26762677d 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -1060,7 +1060,7 @@ static int __init cmld_init_module(void) /* Activate SVA 90 KHz timer */ if (htim_base == NULL) goto out; - iowrite32((1<<26), htim_base); + iowrite32((1<<26) | ioread32(htim_base), htim_base); iounmap(htim_base); /*i = ioread32(PRCM_SVAMMDSPCLK_MGT) & 0xFF; -- cgit v1.2.3 From a9ef57695842c65b18179a620810cf0e9efe3bc8 Mon Sep 17 00:00:00 2001 From: Rajat Verma Date: Thu, 16 Jun 2011 11:53:26 +0530 Subject: staging: mmio: enable extended DDR usage Enables configuration of DDR usage size for camera firmware. Earlier it was fixed at 64 kB, now ISP can use upto 256 MB of DDR memory. ST-Ericsson Linux next: NA ST-Ericsson ID: 345711 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Ie5599f55176ccaf42ba76392803057d96c096e62 Signed-off-by: Rajat Verma Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25193 Reviewed-by: QATOOLS Reviewed-by: QATEST Reviewed-by: Jonas ABERG --- drivers/staging/mmio/st_mmio.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/staging/mmio/st_mmio.c b/drivers/staging/mmio/st_mmio.c index 696644ae835..c79c2768d19 100644 --- a/drivers/staging/mmio/st_mmio.c +++ b/drivers/staging/mmio/st_mmio.c @@ -111,6 +111,36 @@ struct mmio_info { */ static struct mmio_info *info; +/* + * This function converts a given logical memory region size + * to appropriate ISP_MCU_SYS_SIZEx register value. + */ +static int get_mcu_sys_size(u32 size, u32 *val) +{ + int ret = 0; + + if (size > 0 && size <= SZ_4K) + *val = 4; + else if (size > SZ_4K && size <= SZ_8K) + *val = 5; + else if (size > SZ_8K && size <= SZ_16K) + *val = 6; + else if (size > SZ_16K && size <= SZ_32K) + *val = 7; + else if (size > SZ_32K && size <= SZ_64K) + *val = 0; + else if (size > SZ_64K && size <= SZ_1M) + *val = 1; + else if (size > SZ_1M && size <= SZ_16M) + *val = 2; + else if (size > SZ_16M && size <= SZ_256M) + *val = 3; + else + ret = -EINVAL; + + return ret; +} + static int mmio_cam_pwr_sensor(struct mmio_info *info, int on) { int err = 0; @@ -302,8 +332,13 @@ static int mmio_load_xp70_fw(struct mmio_info *info, */ writew(upper_16_bits(xp70_fw->addr_sdram_ext), info->siabase + SIA_ISP_MCU_SYS_ADDR1_OFFSET); - /* ISP_MCU_SYS_SIZEx XP70 register (size of the code =64KB) */ - writew(0x0, info->siabase + SIA_ISP_MCU_SYS_SIZE1_OFFSET); + /* ISP_MCU_SYS_SIZEx XP70 register */ + err = get_mcu_sys_size(xp70_fw->size_sdram_ext, &itval); + + if (err) + goto err_exit; + + writew(itval, info->siabase + SIA_ISP_MCU_SYS_SIZE1_OFFSET); } return 0; -- cgit v1.2.3 From 8c6f2e95f1b54c6c215591e0fb6673e40e616025 Mon Sep 17 00:00:00 2001 From: Rajat Verma Date: Mon, 20 Jun 2011 15:04:17 +0530 Subject: ARM: ux500: mmio: Correct disable mode gpio config Corrects the disable mode gpio configuration for XShutdown gpio pins of camera sensor. Change-Id: I040956a2b3b98d44270cd8374188aeb4339b467a Signed-off-by: Rajat Verma Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/25470 Reviewed-by: Rabin VINCENT Reviewed-by: QATEST Reviewed-by: Jonas ABERG --- arch/arm/mach-ux500/board-mop500-mmio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-mmio.c b/arch/arm/mach-ux500/board-mop500-mmio.c index 975db6f7af8..71028bd2f8f 100644 --- a/arch/arm/mach-ux500/board-mop500-mmio.c +++ b/arch/arm/mach-ux500/board-mop500-mmio.c @@ -51,8 +51,8 @@ static pin_cfg_t xshutdown_fw[] = { GPIO142_IP_GPIO3 }; static pin_cfg_t xshutdown_disable[] = { - GPIO141_GPIO, - GPIO142_GPIO + GPIO141_GPIO | PIN_OUTPUT_LOW, + GPIO142_GPIO | PIN_OUTPUT_LOW }; struct mmio_board_data{ -- cgit v1.2.3 From 1fb19303dabd06c8fffb35236a24d9067ad37861 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 7 Jul 2011 08:46:52 +0200 Subject: u5500: mmio: fix after move of mmio.h from include/linux to staging directory Signed-off-by: Philippe Langlais --- arch/arm/mach-ux500/board-u5500-mmio.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/board-u5500-mmio.c b/arch/arm/mach-ux500/board-u5500-mmio.c index e88dafb90e8..3326d69639d 100644 --- a/arch/arm/mach-ux500/board-u5500-mmio.c +++ b/arch/arm/mach-ux500/board-u5500-mmio.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include @@ -23,6 +22,7 @@ #include #include #include "board-u5500.h" +#include "../drivers/staging/mmio/mmio.h" struct mmio_board_data{ int number_of_regulators; @@ -98,7 +98,6 @@ static int mmio_pin_cfg_init(struct mmio_platform_data *pdata) static void mmio_pin_cfg_exit(struct mmio_platform_data *pdata) { - struct mmio_board_data *extra = pdata->extra; } /* -- cgit v1.2.3 From 6ff360b7b070fa5bbcf8bada29c8aeca0da8dc04 Mon Sep 17 00:00:00 2001 From: psen Date: Fri, 26 Aug 2011 10:45:17 +0530 Subject: Set Current Pid to Tid * in case of tid is zero * Check for KERNELRLEASE instead of MM_MAKEFILES_DIR in Makefile --- drivers/staging/nmf-cm/Makefile | 2 +- drivers/staging/nmf-cm/cm_syscall.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/nmf-cm/Makefile b/drivers/staging/nmf-cm/Makefile index 82fa97f81d1..0728ac5bc3f 100644 --- a/drivers/staging/nmf-cm/Makefile +++ b/drivers/staging/nmf-cm/Makefile @@ -7,7 +7,7 @@ # # Rules to build kernel modules # -ifndef MM_MAKEFILES_DIR +ifdef KERNELRELEASE # $(src): current relative dir; $(kbuild-dir): cur absolute dir ifdef kbuild-dir diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index 8a48ac10c60..70f73e8ad97 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -13,6 +13,7 @@ #include "cmld.h" #include #include +#include /** Dequeue and free per-process messages for specific binding * @@ -1379,8 +1380,8 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd __func__, current->pid, physAddr, (int)curr->tid);*/ err = -EBUSY; } else { - curr->tid = 0; //current->pid; + curr->tid = current->pid; err = 0; } break; -- cgit v1.2.3 From 0f47c95922e04bf0611ae81f24da470affd7d8cc Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Mon, 11 Jul 2011 11:05:42 +0200 Subject: u8500 CM: use vmalloc() for big allocations Use vmalloc() instead of OSAL_Alloc() for "big" allocations. OSAL_Alloc() uses kmalloc by default and default to vmalloc() if kmalloc() fails. The logic works, but an ugly print appears in the console each time kmalloc() fails. We use now directly vmalloc() to avoid these ugly prints ST-Ericsson Linux next: - ST-Ericsson ID: 343810 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer --- drivers/staging/nmf-cm/cm_syscall.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index 70f73e8ad97..0d1bf8ffe4e 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "cmioctl.h" #include "osal-kernel.h" @@ -65,7 +66,7 @@ inline int cmld_InstantiateComponent(struct cm_process_priv* procPriv, return -EFAULT; if (data.in.dataFile != NULL) { - dataFile = OSAL_Alloc(data.in.dataFileSize); + dataFile = vmalloc(data.in.dataFileSize); if (dataFile == NULL) { data.out.error = CM_NO_MORE_MEMORY; goto out; @@ -99,7 +100,7 @@ inline int cmld_InstantiateComponent(struct cm_process_priv* procPriv, out: if (dataFile) - OSAL_Free(dataFile); + vfree(dataFile); /* Copy results back to userspace */ if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) return -EFAULT; -- cgit v1.2.3 From 5fbff99037bb14886591b7fc7876a3fe4dddace5 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Mon, 11 Jul 2011 17:39:11 +0200 Subject: U8500 CM: protect driver against MMDSP corruption The loadmap of the MMDSP components is stored in shared memory (DDR memory shared between ARM and MMDSP). In case of corruption of this memory by some MMDSP firmware, current parsing of this loadmap on ARM side may lead to a kernel Panic. This patch makes the driver tolerant against any corruption ST-Ericsson Linux next: - ST-Ericsson ID: 351745 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer --- .../nmf-cm/cm/engine/component/inc/instance.h | 1 + .../nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h | 2 - .../staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c | 221 +++++++++++++++++---- drivers/staging/nmf-cm/cm/inc/cm_type.h | 3 +- 4 files changed, 184 insertions(+), 43 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/instance.h b/drivers/staging/nmf-cm/cm/engine/component/inc/instance.h index 1bef76501de..9172d99db79 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/inc/instance.h +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/instance.h @@ -70,6 +70,7 @@ typedef struct t_component_instance { t_cm_domain_id domainId; //!< Domain where the component has been installed struct t_client_of_singleton *clientOfSingleton; //!< Client of singleton list + t_memory_handle loadMapHandle; // handle of allocated memory for the loadMap structure and name; } t_component_instance; t_component_template* cm_lookupTemplate(t_nmf_core_id dspId, t_dup_char str); diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h index 78b00388802..bb65c0b1244 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/mmdsp-loadmap.h @@ -34,8 +34,6 @@ struct LoadMapItem struct LoadMapItem* pNextItem;// Pointer on the next list item, NULL if last one. void* pXROM; // Start address of XROM void* pYROM; // Start address of YROM - - void* memHandle; // handle of allocated memory for this structure and name, local field not use by mmdsp }; struct LoadMapHdr diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c index 0853e2d25b5..8826e727970 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c @@ -10,12 +10,14 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -24,6 +26,9 @@ static t_memory_handle headerHandle[NB_CORE_IDS] = {INVALID_MEMORY_HANDLE, }; static struct LoadMapHdr *headerAddresses[NB_CORE_IDS] = {0, }; static t_uint32 headerOffsets[NB_CORE_IDS] = {0, }; +static t_uint32 entryNumber[NB_CORE_IDS] = {0, }; + +#define myoffsetof(TYPE, MEMBER) ((unsigned int) &((TYPE *)0)->MEMBER) t_cm_error cm_DSPABI_AddLoadMap( t_cm_domain_id domainId, @@ -33,6 +38,8 @@ t_cm_error cm_DSPABI_AddLoadMap( void *componentHandle) { t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId); + int count=0; + struct LoadMapItem* curItem = NULL; if (headerHandle[coreId] == 0) /* Create loadmap header */ { @@ -85,20 +92,53 @@ t_cm_error cm_DSPABI_AddLoadMap( pItem = (struct LoadMapItem*)cm_DSP_GetHostLogicalAddress(handle); cm_DSP_GetDspAddress(handle, &dspentry); + count++; + entryNumber[coreId]++; // Link this new loadmap with the previous one if(headerAddresses[coreId]->pFirstItem == NULL) headerAddresses[coreId]->pFirstItem = (struct LoadMapItem *)dspentry; else { - struct LoadMapItem* curItem; + const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId); + t_uint32 endSegmentAddr = SDRAMMEM16_BASE_ADDR + pDspDesc->segments[SDRAM_DATA_USER].size / 2; + struct LoadMapItem* curItem, *prevItem = NULL; + t_uint32 curItemDspAdress; + + if( + ((t_uint32)headerAddresses[coreId]->pFirstItem < SDRAMMEM16_BASE_ADDR) || + ((t_uint32)headerAddresses[coreId]->pFirstItem > endSegmentAddr)) + { + ERROR("Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n", + headerOffsets[coreId], &headerAddresses[coreId]->pFirstItem, 0, 0, 0, 0); - curItem = headerAddresses[coreId]->pFirstItem; - curItem = (struct LoadMapItem*)(((t_uint32)curItem - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + return CM_INVALID_DATA; + } + curItemDspAdress = (t_uint32)headerAddresses[coreId]->pFirstItem; + curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + count++; while(curItem->pNextItem != NULL) { - curItem = curItem->pNextItem; - curItem = (struct LoadMapItem*)(((t_uint32)curItem - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + if(((t_uint32)curItem->pNextItem < SDRAMMEM16_BASE_ADDR) || ((t_uint32)curItem->pNextItem > endSegmentAddr)) + { + if (prevItem == NULL) + ERROR("AddLoadMap: Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n" + "Previou (first) component name %s<%s>\n", + curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, + curItem->pARMThis ? (char*)(((t_component_instance *)&curItem->pARMThis)->pathname) : "", + curItem->pARMThis ? (char*)(((t_component_instance *)&curItem->pARMThis)->template->name) : "", 0, 0); + else + ERROR("AddLoadMap: Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n" + "Previous valid component name %s<%s>", + curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, + prevItem->pARMThis ? (char*)(((t_component_instance *)&prevItem->pARMThis)->pathname) : "", + prevItem->pARMThis ? (char*)(((t_component_instance *)&prevItem->pARMThis)->template->name) : "", 0, 0); + return CM_INVALID_DATA; + } + curItemDspAdress = (t_uint32)curItem->pNextItem; + prevItem = curItem; + curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + count++; } curItem->pNextItem = (struct LoadMapItem *)dspentry; } @@ -211,11 +251,16 @@ t_cm_error cm_DSPABI_AddLoadMap( /* * Set memory handle (not used externally) */ - pItem->memHandle = (void*)handle; + ((t_component_instance *)componentHandle)->loadMapHandle = handle; } OSAL_mb(); + if (count != entryNumber[coreId]) { + ERROR("AddLoadMap: corrumption, number of component differs: count=%d, expected %d (last item @ %p)\n", + count, entryNumber[coreId], curItem, 0, 0, 0); + return CM_INVALID_DATA; + } return CM_OK; } @@ -226,62 +271,158 @@ t_cm_error cm_DSPABI_RemoveLoadMap( const char* localname, void *componentHandle) { - struct LoadMapItem* curItem, **prevItemReference; + struct LoadMapItem **prevItemReference; + t_uint32 prevItemReferenceDspAddress, curItemDspAdress; t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId); + const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId); + t_uint32 endSegmentAddr = SDRAMMEM16_BASE_ADDR + pDspDesc->segments[SDRAM_DATA_USER].size / 2; + struct LoadMapItem* curItem = NULL; CM_ASSERT (headerHandle[coreId] != INVALID_MEMORY_HANDLE); /* parse list until we find this */ + prevItemReferenceDspAddress = 0x2; // DSP address of load map head pointer prevItemReference = &headerAddresses[coreId]->pFirstItem; - curItem = *prevItemReference; - while(curItem != NULL) + curItemDspAdress = (t_uint32)*prevItemReference; + while(curItemDspAdress != 0x0) { - curItem = (struct LoadMapItem*)(((t_uint32)curItem - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + if((curItemDspAdress < SDRAMMEM16_BASE_ADDR) || (curItemDspAdress > endSegmentAddr)) + { + ERROR("Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n", + prevItemReferenceDspAddress, prevItemReference, 0, 0, 0, 0); + + return CM_OK; + } + + curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address if(curItem->pARMThis == componentHandle) - break; + { + // Remove component from loadmap - prevItemReference = &curItem->pNextItem; - curItem = *prevItemReference; - } + /* take local semaphore */ + cm_DSP_SEM_Take(coreId,LOADMAP_SEMAPHORE_USE_NB); + /* remove element from list */ + *prevItemReference = curItem->pNextItem; - // Remove component from loadmap if founded - if(curItem != NULL) - { - /* take local semaphore */ - cm_DSP_SEM_Take(coreId,LOADMAP_SEMAPHORE_USE_NB); + /* update nRevision field in header */ + headerAddresses[coreId]->nRevision++; - /* remove element from list */ - *prevItemReference = curItem->pNextItem; + /* If this is the last item, deallocate !!! */ + if(headerAddresses[coreId]->pFirstItem == NULL) + { + // Deallocate memory + cm_DM_Free(headerHandle[coreId], TRUE); + headerHandle[coreId] = INVALID_MEMORY_HANDLE; - /* update nRevision field in header */ - headerAddresses[coreId]->nRevision++; + //Register Header into XRAM:2 + cm_DSP_WriteXRamWord(coreId, 2, 0); + } - /* If this is the last item, deallocate !!! */ - if(headerAddresses[coreId]->pFirstItem == NULL) - { - // Deallocate memory - cm_DM_Free(headerHandle[coreId], TRUE); - headerHandle[coreId] = INVALID_MEMORY_HANDLE; + /* deallocate memory */ + cm_DM_Free(((t_component_instance *)componentHandle)->loadMapHandle, TRUE); - //Register Header into XRAM:2 - cm_DSP_WriteXRamWord(coreId, 2, 0); + /* be sure memory is updated before releasing local semaphore */ + OSAL_mb(); + + /* release local semaphore */ + cm_DSP_SEM_Give(coreId,LOADMAP_SEMAPHORE_USE_NB); + + entryNumber[coreId]--; + + return CM_OK; } - /* deallocate memory */ - cm_DM_Free((t_memory_handle)curItem->memHandle, TRUE); + prevItemReferenceDspAddress = curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem); + prevItemReference = &curItem->pNextItem; + curItemDspAdress = (t_uint32)*prevItemReference; + }; - /* be sure memory is updated before releasing local semaphore */ - OSAL_mb(); + ERROR("Memory corruption in MMDSP: component not in LoadMap %s\n", localname, 0, 0, 0, 0, 0); + + return CM_OK; +} + +#if 0 +t_cm_error cm_DSPABI_CheckLoadMap_nolock(t_nmf_core_id coreId) +{ + int count=0; + static int dump = 5; + struct LoadMapItem* curItem = NULL; + + if (!dump) + return CM_OK; + if (headerHandle[coreId] == 0) /* No load map yet */ + return CM_OK; - /* release local semaphore */ - cm_DSP_SEM_Give(coreId,LOADMAP_SEMAPHORE_USE_NB); - } - else { - ERROR("Component not in LoadMap %s, memory corruption????\n", localname, 0, 0, 0, 0, 0); + // No entry in loadmap + if(headerAddresses[coreId]->pFirstItem == NULL) + return CM_OK; + + { + const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId); + t_uint32 endSegmentAddr = SDRAMMEM16_BASE_ADDR + pDspDesc->segments[SDRAM_DATA_USER].size / 2; + struct LoadMapItem *prevItem=NULL; + t_uint32 curItemDspAdress; + + if (((t_uint32)headerAddresses[coreId]->pFirstItem < SDRAMMEM16_BASE_ADDR) || + ((t_uint32)headerAddresses[coreId]->pFirstItem > endSegmentAddr)) + { + ERROR("CheckLoadMap: Memory corruption in MMDSP at first item: at data DSP address=%x or ARM address=%x\n", + headerOffsets[coreId], &headerAddresses[coreId]->pFirstItem, 0, 0, 0, 0); + dump--; + return CM_INVALID_COMPONENT_HANDLE; + } + curItemDspAdress = (t_uint32)headerAddresses[coreId]->pFirstItem; + curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); + count++; + while(curItem->pNextItem != NULL) + { + if(((t_uint32)curItem->pNextItem < SDRAMMEM16_BASE_ADDR) || ((t_uint32)curItem->pNextItem > endSegmentAddr)) + { + if (!prevItem) + ERROR("CheckLoadMap: Memory corruption in MMDSP (count=%d): at data DSP address=%x or ARM address=%x\n" + "Previous (first) component name %s<%s>\n", + count, + curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, + (char*)(((t_component_instance *)&curItem->pARMThis)->pathname), + (char*)(((t_component_instance *)&curItem->pARMThis)->template->name), 0); + else + ERROR("CheckLoadMap: Memory corruption in MMDSP (count=%d): at data DSP address=%x or ARM address=%x\n" + "Previous valid component name %s<%s>", + count, + curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, + (char*)(((t_component_instance *)&prevItem->pARMThis)->pathname), + (char*)(((t_component_instance *)&prevItem->pARMThis)->template->name), 0); + dump--; + return CM_INVALID_COMPONENT_HANDLE; + } + curItemDspAdress = (t_uint32)curItem->pNextItem; + prevItem = curItem; + curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address + count++; + } + } + } + if (count != entryNumber[coreId]) { + ERROR("CheckLoadMap: number of component differs: count=%d, expected %d (last item @ %p)\n", count, entryNumber[coreId], + curItem, 0, 0, 0); + dump--; + return CM_INVALID_COMPONENT_HANDLE; + } return CM_OK; } + +t_cm_error cm_DSPABI_CheckLoadMap(t_nmf_core_id coreId) +{ + t_cm_error error; + OSAL_LOCK_API(); + error = cm_DSPABI_CheckLoadMap_nolock(coreId); + OSAL_UNLOCK_API(); + return error; +} +#endif diff --git a/drivers/staging/nmf-cm/cm/inc/cm_type.h b/drivers/staging/nmf-cm/cm/inc/cm_type.h index b2f97090a3a..83a34ecd706 100644 --- a/drivers/staging/nmf-cm/cm/inc/cm_type.h +++ b/drivers/staging/nmf-cm/cm/inc/cm_type.h @@ -37,7 +37,7 @@ typedef t_nmf_error t_cm_error; //!< /* tests/src/common/nte/src/nte.c */ /*********************************************************************************/ #define CM_LAST_ERROR_ID ((t_cm_error)-128) -#define CM_INTEGRATION_ERROR NMF_INTEGRATION_ERROR0 //!< \ref NMF_INTEGRATION_ERROR0 +#define CM_INTEGRATION_ERROR NMF_INTEGRATION_ERROR0 //!< \ref NMF_INTEGRATION_ERROR0 /* Communication */ #define CM_FLUSH_MESSAGE NMF_FLUSH_MESSAGE //!< Message send after call to CM_FlushChannel() @@ -107,6 +107,7 @@ typedef t_nmf_error t_cm_error; //!< #define CM_PWR_NOT_AVAILABLE ((t_cm_error)-16) //!< No modification of the state of the power input /* Common errors */ +#define CM_INVALID_DATA ((t_cm_error)-4) //!< Invalid internal data encountered #define CM_OUT_OF_LIMITS ((t_cm_error)-3) //!< User reach an internal nmf limits of limits.h file #define CM_INVALID_PARAMETER NMF_INVALID_PARAMETER //!< \ref NMF_INVALID_PARAMETER #define CM_NOT_YET_IMPLEMENTED ((t_cm_error)-1) //!< CM API not yet implemented -- cgit v1.2.3 From b2c1325f8f86729d8f964887bfeaa65f37be6576 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Mon, 18 Jul 2011 11:28:53 +0200 Subject: U8500 NMF-CM: rework the DMA part The addition of the DMA part within the driver has broken the OSI part. This prevents all easy merge of any new changes in this OSI part. This patch reworks this part by moving everything in linux specific files. ST-Ericsson ID: 343776 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Change-Id: Iafaa4b36539729826442d0c2dd95c5bbc52bfddb Signed-off-by: Pierre Peiffer --- .../staging/nmf-cm/cm/engine/api/memory_engine.h | 5 -- .../nmf-cm/cm/engine/memory/src/memory_wrapper.c | 22 -------- drivers/staging/nmf-cm/cm_dma.c | 59 +++++++++++++++++++--- drivers/staging/nmf-cm/cm_dma.h | 9 ++-- drivers/staging/nmf-cm/cm_service.c | 8 +++ drivers/staging/nmf-cm/cm_syscall.c | 51 ++++++++++--------- drivers/staging/nmf-cm/cmioctl.h | 7 ++- drivers/staging/nmf-cm/cmld.c | 9 +++- drivers/staging/nmf-cm/cmld.h | 2 +- drivers/staging/nmf-cm/osal-kernel.c | 5 ++ 10 files changed, 112 insertions(+), 65 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/api/memory_engine.h b/drivers/staging/nmf-cm/cm/engine/api/memory_engine.h index 49c0c815669..9f5e25b3ebf 100644 --- a/drivers/staging/nmf-cm/cm/engine/api/memory_engine.h +++ b/drivers/staging/nmf-cm/cm/engine/api/memory_engine.h @@ -75,10 +75,6 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryMpcAddress( t_cm_memory_handle handle, t_uint32 *pMpcAddress); -PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemorySize( - t_cm_memory_handle handle, - t_uint32 *pSize); - /*! * \brief Get the memory status for given memory type of a given Media Processor Core * @@ -93,6 +89,5 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryStatus( t_cm_mpc_memory_type memType, t_cm_allocator_status *pStatus); - #endif /* CM_MEMORY_ENGINE_H_ */ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c b/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c index 15961aea516..f7d47be924d 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c @@ -175,28 +175,6 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryMpcAddress(t_cm_memory_han return CM_OK; } -PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemorySize( - t_cm_memory_handle handle, - t_uint32 *pSize) -{ - t_cm_error error; - t_memory_handle validHandle; - - OSAL_LOCK_API(); - - if((error = cm_MM_getValidMemoryHandle(handle, &validHandle)) != CM_OK) - { - OSAL_UNLOCK_API(); - return error; - } - - *pSize = validHandle->size; - - OSAL_UNLOCK_API(); - return CM_OK; -} - - PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetMpcMemoryStatus(t_nmf_core_id coreId, t_cm_mpc_memory_type memType, t_cm_allocator_status *pStatus) { t_dsp_memory_type_id dspMemType; diff --git a/drivers/staging/nmf-cm/cm_dma.c b/drivers/staging/nmf-cm/cm_dma.c index 1db5a3cf951..c460728e6a0 100644 --- a/drivers/staging/nmf-cm/cm_dma.c +++ b/drivers/staging/nmf-cm/cm_dma.c @@ -6,15 +6,16 @@ #include #include #include +#include #include +#include - #include "cm_dma.h" +#include "cm_dma.h" - #define CMDMA_LIDX (2) - #define CMDMA_BASE (0x801C0000) - #define CMDMA_REG_LCLA (0x024) +#define CMDMA_LIDX (2) +#define CMDMA_REG_LCLA (0x024) -void __iomem *virtbase = NULL; +static void __iomem *virtbase = NULL; static int cmdma_write_cyclic_list_mem2per( unsigned int from_addr, @@ -30,6 +31,8 @@ static int cmdma_write_cyclic_list_per2mem( unsigned int segmentsize, unsigned int LOS); +static bool cmdma_setup_relink_area_called = false; + int cmdma_setup_relink_area( unsigned int mem_addr, unsigned int per_addr, unsigned int segments, @@ -37,6 +40,9 @@ int cmdma_setup_relink_area( unsigned int mem_addr, unsigned int LOS, enum cmdma_type type) { + if (!cmdma_setup_relink_area_called) + cmdma_setup_relink_area_called = true; + switch (type) { case CMDMA_MEM_2_PER: @@ -63,7 +69,7 @@ int cmdma_setup_relink_area( unsigned int mem_addr, static unsigned int cmdma_getlcla( void) { if(!virtbase) - virtbase = ioremap(CMDMA_BASE, CMDMA_REG_LCLA + sizeof(int) ); + virtbase = ioremap(U8500_DMA_BASE, CMDMA_REG_LCLA + sizeof(int) ); return readl(virtbase + CMDMA_REG_LCLA); } @@ -87,6 +93,8 @@ int cmdma_setup_relink_area( unsigned int mem_addr, relink[3] = (((dst_addr >> 16) & 0xFFFFUL) << 16 ) | 0x8201UL | ((LOS+1) << 1) | (burst_size<<10); + + (void) dma_map_single(NULL, relink, 16, DMA_TO_DEVICE); } static void cmdma_write_relink_params_per2mem ( @@ -108,6 +116,8 @@ static void cmdma_write_relink_params_per2mem ( relink[3] = (((dst_addr >> 16) & 0xFFFFUL) << 16 ) | 0x1200UL | ((LOS+1) << 1) | (burst_size<<10); + + (void) dma_map_single(NULL, relink, 16, DMA_TO_DEVICE); } static int cmdma_write_cyclic_list_mem2per( @@ -176,3 +186,40 @@ static int cmdma_write_cyclic_list_per2mem( return 0; } + +static void __iomem *dmabase = 0; +int cmdma_init(void) +{ + dmabase = ioremap_nocache(U8500_DMA_BASE, PAGE_SIZE); + if (dmabase == NULL) + return -ENOMEM; + else + return 0; +} + +void cmdma_destroy(void) +{ + iounmap(dmabase); +} + +#define SSLNK_CHAN_2 (0x40C + 0x20 * 2) +#define SDLNK_CHAN_2 (0x41C + 0x20 * 2) + +void cmdma_stop_dma(void) +{ + if(cmdma_setup_relink_area_called) { + cmdma_setup_relink_area_called = false; + if (readl(dmabase + SSLNK_CHAN_2) & (0x3 << 28)) { + printk(KERN_ERR "CM: ERROR - RX DMA was running\n"); + } + if (readl(dmabase + SDLNK_CHAN_2) & (0x3 << 28)) { + printk(KERN_ERR "CM: ERROR - TX DMA was running\n"); + } + + writel(~(1 << 28), dmabase + SSLNK_CHAN_2); + while (readl(dmabase + SSLNK_CHAN_2) & (0x3 << 28)); + + writel(~(1 << 28), dmabase + SDLNK_CHAN_2); + while (readl(dmabase + SDLNK_CHAN_2) & (0x3 << 28)); + } +} diff --git a/drivers/staging/nmf-cm/cm_dma.h b/drivers/staging/nmf-cm/cm_dma.h index 6ee4caafeae..92f67b05c77 100644 --- a/drivers/staging/nmf-cm/cm_dma.h +++ b/drivers/staging/nmf-cm/cm_dma.h @@ -7,11 +7,7 @@ #ifndef __CMDMA_H #define __CMDMA_H - -enum cmdma_type { - CMDMA_MEM_2_PER, - CMDMA_PER_2_MEM -}; +#include "cmioctl.h" int cmdma_setup_relink_area( unsigned int mem_addr, @@ -21,4 +17,7 @@ int cmdma_setup_relink_area( unsigned int LOS, enum cmdma_type type); +void cmdma_stop_dma(void); +int cmdma_init(void); +void cmdma_destroy(void); #endif diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index cd7602a6cec..bc70afe10a0 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -21,6 +21,7 @@ #include "osal-kernel.h" #include "cmld.h" #include "cm_service.h" +#include "cm_dma.h" /* Panic managment */ static void service_tasklet_func(unsigned long); @@ -75,6 +76,13 @@ static void service_tasklet_func(unsigned long unused) msg.d.srv.srvData.panic = desc.u.panic; dispatch_service_msg(&msg); + /* + * Stop DMA directly before shutdown, to avoid bad sound. + * Should be called after DSP has stopped executing, to avoid the DSP + * re-starting DMA + */ + if (osalEnv.mpc[i].coreId == SIA_CORE_ID) + cmdma_stop_dma(); break; } case CM_MPC_SERVICE_PRINT: { diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index 0d1bf8ffe4e..f4be2c2d3d1 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -9,12 +9,11 @@ #include #include #include +#include #include "cmioctl.h" #include "osal-kernel.h" #include "cmld.h" -#include -#include -#include +#include "cm_dma.h" /** Dequeue and free per-process messages for specific binding * @@ -1225,40 +1224,47 @@ inline int cmld_Unmigrate(CM_Unmigrate_t __user *param) return 0; } -int cmld_SetupRelinkArea(CM_SetupRelinkArea_t __user *param) +int cmld_SetupRelinkArea(struct cm_process_priv *procPriv, + CM_SetupRelinkArea_t __user *param) { CM_SetupRelinkArea_t data; - t_cm_system_address systemAddress; - t_uint32 size; + struct list_head *cursor, *next; + struct memAreaDesc_t *entry = NULL; /* coverity[tainted_data_argument : FALSE] */ if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) return -EFAULT; - data.out.error = CM_ENGINE_GetMpcMemorySystemAddress( - data.in.mem_handle, &systemAddress); + /* check that it is actually owned by the process */ + data.out.error = CM_UNKNOWN_MEMORY_HANDLE; - if (data.out.error != CM_OK) - return 0; + if (lock_process(procPriv)) + return -ERESTARTSYS; + list_for_each_safe(cursor, next, &procPriv->memAreaDescList){ + entry = list_entry(cursor, struct memAreaDesc_t, list); + if (entry->handle == data.in.mem_handle) + break; + } + unlock_process(procPriv); - data.out.error = CM_ENGINE_GetMpcMemorySize(data.in.mem_handle, &size); - if (data.out.error != CM_OK) - return 0; + if ((entry == NULL) || (entry->handle != data.in.mem_handle)) + goto out; - if (size < data.in.segments * data.in.segmentsize) + if (entry->size < data.in.segments * data.in.segmentsize) { - return -EINVAL; + data.out.error = CM_INVALID_PARAMETER; + goto out; } data.out.error = cmdma_setup_relink_area( - systemAddress.physical, - data.in.peripheral_addr, - data.in.segments, - data.in.segmentsize, - data.in.LOS, - data.in.type); - + entry->physAddr, + data.in.peripheral_addr, + data.in.segments, + data.in.segmentsize, + data.in.LOS, + data.in.type); +out: if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) return -EFAULT; @@ -1381,7 +1387,6 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd __func__, current->pid, physAddr, (int)curr->tid);*/ err = -EBUSY; } else { - //current->pid; curr->tid = current->pid; err = 0; } diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h index 7ca46fc25e8..15de0e50ca4 100644 --- a/drivers/staging/nmf-cm/cmioctl.h +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -16,7 +16,12 @@ #include #include #include -#include "cm_dma.h" + + +enum cmdma_type { + CMDMA_MEM_2_PER, + CMDMA_PER_2_MEM +}; #define CMLD_DEV_NAME \ { "cm_control", \ diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 5b26762677d..158524ddcb4 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -27,6 +27,7 @@ #include "osal-kernel.h" #include "cmld.h" #include "cm_service.h" +#include "cm_dma.h" #define CMDRIVER_PATCH_VERSION 106 #define O_FLUSH 0x1000000 @@ -624,7 +625,8 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long return cmld_Unmigrate((CM_Unmigrate_t *)arg); case CM_SETUPRELINKAREA: - return cmld_SetupRelinkArea((CM_SetupRelinkArea_t *)arg); + return cmld_SetupRelinkArea(procPriv, + (CM_SetupRelinkArea_t *)arg); case CM_PUSHCOMPONENT: return cmld_PushComponent((CM_PushComponent_t *)arg); @@ -1226,7 +1228,9 @@ static int __init cmld_init_module(void) } } - return 0; + err = cmdma_init(); + if (err == 0) + return 0; out_all: if (err) { @@ -1303,6 +1307,7 @@ static void __exit cmld_cleanup_module(void) CM_ENGINE_Destroy(); + cmdma_destroy(); unmapRegions(); #ifdef CM_DEBUG_ALLOC cleanup_debug_alloc(); diff --git a/drivers/staging/nmf-cm/cmld.h b/drivers/staging/nmf-cm/cmld.h index 234e30db503..cf183328ad6 100644 --- a/drivers/staging/nmf-cm/cmld.h +++ b/drivers/staging/nmf-cm/cmld.h @@ -126,7 +126,7 @@ int cmld_GetRequiredComponentFiles(struct cm_process_priv *cmPriv, CM_GetRequiredComponentFiles_t __user *); int cmld_Migrate(CM_Migrate_t __user *); int cmld_Unmigrate(CM_Unmigrate_t __user *); -int cmld_SetupRelinkArea(CM_SetupRelinkArea_t __user *); +int cmld_SetupRelinkArea(struct cm_process_priv *, CM_SetupRelinkArea_t __user *); int cmld_PushComponent(CM_PushComponent_t __user *); int cmld_ReleaseComponent(CM_ReleaseComponent_t __user *); int cmld_PrivGetMPCMemoryDesc(struct cm_process_priv *, CM_PrivGetMPCMemoryDesc_t __user *); diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 8f547ba0ad9..5027ac7d9f8 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -28,6 +28,7 @@ #include "osal-kernel.h" #include "cm_service.h" #include "cmld.h" +#include "cm_dma.h" __iomem void *prcmu_base = NULL; __iomem void *prcmu_tcdm_base = NULL; @@ -831,6 +832,10 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam osalEnv.mpc[idx].monitor_tsk = NULL; } + /* Stop the DMA (normally done on DSP side, but be safe) */ + if (firstParam == SIA_CORE_ID) + cmdma_stop_dma(); + /* Stop the DSP */ if (regulator_disable(osalEnv.mpc[idx].mmdsp_regulator) < 0) pr_err("CM Driver(%s): can't disable regulator %s-mmsdp\n", -- cgit v1.2.3 From 8ed2ca3781ca0e979245c9628fac06c0d31b5291 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Mon, 18 Jul 2011 15:38:18 +0200 Subject: U8500 NMF-CM: start DSP at 100 OPP Start the DSP at 100OPP instead of 50 OPP to speed up the start of some audio usecases. ST-Ericsson ID: 351728 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: If10f593719fc5e7a933997e7c7464b673586f65b --- drivers/staging/nmf-cm/osal-kernel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 5027ac7d9f8..f215f730a9a 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -728,7 +728,7 @@ static void wakeup_process(unsigned long data) static int dspload_monitor(void *idx) { int i = (int)idx; - unsigned char current_opp_request = HALF_OPP; + unsigned char current_opp_request = FULL_OPP; struct mpcConfig *mpc = &osalEnv.mpc[i]; struct timer_list timer; -- cgit v1.2.3 From 29857a2c55f4d50d411ddcedd5346e3942880ce9 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Mon, 18 Jul 2011 18:29:14 +0200 Subject: U8500 NMF-CM: make creation of domains more robust CM_ENGINE_CreateMemoryDomain() allows the creation of domains for some other client (process ID). Today, it doesn't check the existance of the target client, what can lead to an unused domain. This patch fixes it for forbidding the creation of domain for a non-existing client. ST-Ericsson ID: 352761 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: Icf81e9a9c18ce204d0f3c472a1ee05b140567738 --- drivers/staging/nmf-cm/cm_syscall.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index f4be2c2d3d1..a687e0206a3 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -514,10 +514,25 @@ inline int cmld_CreateMemoryDomain(struct cm_process_priv *procPriv, data.out.error = CM_ENGINE_CreateMemoryDomain(procPriv->pid, &domain, &data.out.handle); - else - data.out.error = CM_ENGINE_CreateMemoryDomain(data.in.client, - &domain, - &data.out.handle); + else { + /* Check if client is valid (ie already registered) */ + struct list_head* head; + struct cm_process_priv *entry; + + list_for_each(head, &process_list) { + entry = list_entry(head, struct cm_process_priv, + entry); + if (entry->pid == data.in.client) + break; + } + if (head == &process_list) + data.out.error = CM_INVALID_PARAMETER; + else + data.out.error = + CM_ENGINE_CreateMemoryDomain(data.in.client, + &domain, + &data.out.handle); + } /* Copy results back to userspace */ if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) -- cgit v1.2.3 From c853743a6bb48a1049791c1e8a8f9ae0dd6d06bd Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Mon, 18 Jul 2011 18:35:30 +0200 Subject: U8500 NMF-CM: add support for component preloading Provide support for pre-loading some NMF components, used to pre-load some components that are on a time critical path. Having such components already pre-loaded decreases the time required to instantiate and deploy them. ST-Ericsson ID: 352754 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Depends-On: If8e129163e6c94b7c239c84af667b16d7a1b56ac, I73416c15f75afce61a056f318a448a034182acb2, Id40225d1ce93f2c9cfc085744717dc091add74c4 Signed-off-by: Pierre Peiffer Change-Id: I4aecce1bcc63e6d4b04e251e821c8896ed63ba54 --- .../nmf-cm/cm/engine/api/repository_mgt_engine.h | 7 ++++ .../cm/engine/configuration/inc/configuration.h | 3 -- .../cm/engine/configuration/src/configuration.c | 41 ---------------------- .../cm/engine/repository_mgt/inc/repository_type.h | 1 - .../cm/engine/repository_mgt/src/repository_mgt.c | 20 ++++++++--- drivers/staging/nmf-cm/cm_dma.h | 2 +- drivers/staging/nmf-cm/cmioctl.h | 2 +- drivers/staging/nmf-cm/cmld.c | 7 +++- drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- drivers/staging/nmf-cm/osal-kernel.c | 7 ++-- 10 files changed, 34 insertions(+), 58 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/api/repository_mgt_engine.h b/drivers/staging/nmf-cm/cm/engine/api/repository_mgt_engine.h index 3520f974be6..b63c60d85eb 100644 --- a/drivers/staging/nmf-cm/cm/engine/api/repository_mgt_engine.h +++ b/drivers/staging/nmf-cm/cm/engine/api/repository_mgt_engine.h @@ -83,4 +83,11 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_PushComponent(const char *name, const */ PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_ReleaseComponent (const char *name); +/*! + * \brief Check if the CM Component Cache is empty. + * + * \return a boolean value TRUE or FALSE. + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_bool CM_ENGINE_IsComponentCacheEmpty(void); #endif /*REPOSITORY_MGT_ENGINE_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration.h b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration.h index 7156769bb2d..98d22bba743 100644 --- a/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration.h +++ b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration.h @@ -34,7 +34,4 @@ PUBLIC t_cm_error cm_CFG_CheckMpcStatus(t_nmf_core_id coreId); void cm_CFG_ReleaseMpc(t_nmf_core_id coreId); -PUBLIC t_cm_error cm_CFG_GetRequiredExecutiveEngineComponentNames( - char fileList[][MAX_INTERFACE_TYPE_NAME_LENGTH], t_uint32 listSize); - #endif /* __INC_CONFIGURATION_H_ */ diff --git a/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration.c b/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration.c index f3242af5da8..f092c7061b4 100644 --- a/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration.c +++ b/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration.c @@ -170,44 +170,3 @@ void cm_CFG_ReleaseMpc(t_nmf_core_id coreId) cfgMpcDescArray[coreId].EEmemoryCount = 0; // For debug purpose } } - -/****************************************************************************/ -/* NAME: cm_CFG_GetRequiredExecutiveEngineComponentNames( */ -/* char *fileList[], */ -/* t_uint32 *listSize */ -/* ) */ -/*--------------------------------------------------------------------------*/ -/* DESCRIPTION: retrieves the names of the required Executive Engine */ -/* component(s) to load. */ -/****************************************************************************/ -PUBLIC t_cm_error cm_CFG_GetRequiredExecutiveEngineComponentNames( - char fileList[][MAX_INTERFACE_TYPE_NAME_LENGTH], - t_uint32 listSize) -{ - t_nmf_core_id coreId; - t_uint32 nb=0; - - for (coreId = ARM_CORE_ID; coreId <= LAST_CORE_ID; coreId++) - { - if ((cm_DSP_GetState(coreId)->state == MPC_STATE_BOOTABLE) - && (cm_REP_lookupComponent(cfgMpcDescArray[coreId].eeName, NULL) != CM_OK)) - { - /* Check if we didn't already register this name in the list */ - int j, present=0; - for (j=0; j= listSize) - return CM_NO_MORE_MEMORY; - cm_StringCopy(fileList[nb], cfgMpcDescArray[coreId].eeName, MAX_EE_NAME_LENGTH); - nb++; - } - } - return CM_OK; -} - diff --git a/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h b/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h index 7c41fe1bedb..59abc269236 100644 --- a/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h +++ b/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h @@ -18,7 +18,6 @@ typedef enum { - GET_EE_NAME, BIND_ASYNC, BIND_TRACE, BIND_FROMUSER, diff --git a/drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c b/drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c index c972783db4b..176a965be22 100644 --- a/drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c +++ b/drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c @@ -137,11 +137,6 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetRequiredComponentFiles( compServer = cm_lookupComponent(server); switch(action) { - case GET_EE_NAME: - /* Get Executive Engine names */ - error = cm_CFG_GetRequiredExecutiveEngineComponentNames(fileList, listSize); - break; - case BIND_FROMUSER:{ t_interface_provide_description itfProvide; @@ -309,3 +304,18 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_ReleaseComponent (const char *name) return err; } + +PUBLIC EXPORT_SHARED t_bool CM_ENGINE_IsComponentCacheEmpty(void) +{ + int i; + + OSAL_LOCK_API(); + for(i = 0; i < NHASH; i++) { + if (componentCaches[i] != NULL) { + OSAL_UNLOCK_API(); + return FALSE; + } + } + OSAL_UNLOCK_API(); + return TRUE; +} diff --git a/drivers/staging/nmf-cm/cm_dma.h b/drivers/staging/nmf-cm/cm_dma.h index 92f67b05c77..4fccef03830 100644 --- a/drivers/staging/nmf-cm/cm_dma.h +++ b/drivers/staging/nmf-cm/cm_dma.h @@ -1,6 +1,6 @@ /* * Copyright (C) ST-Ericsson SA 2010 - * License terms: GNU General Public License (GPL), version 2, with + * License terms: GNU General Public License (GPL), version 2, with * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h index 15de0e50ca4..e1ef2bcb025 100644 --- a/drivers/staging/nmf-cm/cmioctl.h +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -585,9 +585,9 @@ typedef struct{ #define CM_PRIVGETMPCMEMORYDESC _IOWR('c', 100, CM_PrivGetMPCMemoryDesc_t) #define CM_PRIVRESERVEMEMORY _IOW('c', 101, unsigned int) #define CM_PRIV_GETBOARDVERSION _IOR('c', 102, unsigned int) +#define CM_PRIV_ISCOMPONENTCACHEEMPTY _IO('c', 103) enum board_version { - U8500_V1, U8500_V2 }; #endif diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 158524ddcb4..d01949c8673 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -29,7 +29,7 @@ #include "cm_service.h" #include "cm_dma.h" -#define CMDRIVER_PATCH_VERSION 106 +#define CMDRIVER_PATCH_VERSION 109 #define O_FLUSH 0x1000000 static int cmld_major; @@ -690,6 +690,11 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long return copy_to_user((void*)arg, &v, sizeof(v)); } else return -EINVAL; + case CM_PRIV_ISCOMPONENTCACHEEMPTY: + if (CM_ENGINE_IsComponentCacheEmpty()) + return 0; + else + return -ENOENT; default: { pr_err("CM(%s): unsupported command %i\n", __func__, cmd); diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index 345c8256212..1acfc870304 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (106)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (109)) /*! * \brief Get NMF major version corresponding to NMF version number diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index f215f730a9a..37e680a87a4 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -18,7 +18,6 @@ #include #include #include -#include #include @@ -383,7 +382,7 @@ t_nmf_osal_sync_handle OSAL_CreateLock(void) void OSAL_Lock(t_nmf_osal_sync_handle handle) { // unfortunately there is no return value to this function - // so we cannot use 'down_interruptible()' + // so we cannot use 'mutex_lock_killable()' mutex_lock((struct mutex*)handle); } @@ -833,8 +832,8 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam } /* Stop the DMA (normally done on DSP side, but be safe) */ - if (firstParam == SIA_CORE_ID) - cmdma_stop_dma(); + if (firstParam == SIA_CORE_ID) + cmdma_stop_dma(); /* Stop the DSP */ if (regulator_disable(osalEnv.mpc[idx].mmdsp_regulator) < 0) -- cgit v1.2.3 From 6231717843b56af23705f4adfa95b596ec259a0b Mon Sep 17 00:00:00 2001 From: Rabin Vincent Date: Tue, 12 Jul 2011 17:23:50 +0530 Subject: u5500: regulators: remove LDO S (VANA) control The PRCMU will manage this automatically based on the ePOD requests. ST-Ericsson Linux next: - ST-Ericsson ID: 332226 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I33aae94be2860f24bf5c5702f86a49525458be7d Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/27028 Reviewed-by: Srinidhi KASAGAR --- arch/arm/mach-ux500/board-u5500-mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-u5500-mmio.c b/arch/arm/mach-ux500/board-u5500-mmio.c index 3326d69639d..ca751da16fa 100644 --- a/arch/arm/mach-ux500/board-u5500-mmio.c +++ b/arch/arm/mach-ux500/board-u5500-mmio.c @@ -40,7 +40,7 @@ struct mmio_board_data{ * Fill names of regulators required for powering up the * camera sensor in below array */ -static char *regulator_names[] = {"v-mmio-camera" , "v-ana"}; +static char *regulator_names[] = {"v-mmio-camera"}; static int mmio_clock_init(struct mmio_platform_data *pdata) { -- cgit v1.2.3 From 907ef065c49bfe1e085f883fdae7a9325d7daa16 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Wed, 20 Jul 2011 13:28:23 +0200 Subject: U8500 NMF-CM: Increase internal fifo size In some media usecase, this internal fifo becomes too small. Increase its size to fix media usecase. ST-Ericsson ID: 341141 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: I3fe5195a3865b993783c0f1244eb89e7ce4c4f4a --- drivers/staging/nmf-cm/cm/engine/communication/src/communication.c | 2 +- drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c b/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c index 8f48f02afc2..897ed8038d1 100644 --- a/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c +++ b/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c @@ -24,7 +24,7 @@ #include -#define ARM_DSP_EVENT_FIFO_SIZE 16 +#define ARM_DSP_EVENT_FIFO_SIZE 128 t_dsp_memory_type_id comsLocation; t_dsp_memory_type_id paramsLocation; diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index 1acfc870304..8e042d3fe62 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (109)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (110)) /*! * \brief Get NMF major version corresponding to NMF version number -- cgit v1.2.3 From dcab3e4c337744c28f7512059dd8b0e2c685be8f Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Tue, 16 Aug 2011 17:43:12 +0200 Subject: U8500 CM: make call to stopper synchronous When a component uses the MMDSP hardware pipe, make the call to the stopper synchronous. Otherwise, the hardware pipe is stopped before the stopper is called, which may be wrong if the stopper still needs to access the pipe. ST-Ericsson ID: 352780 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: I9aaac434f2b11e25c54fae2c12ef3d812dd716ec Depends-On: I8c2e2d6f33af3c53d2438e57658337f6c9f91477 --- .../nmf-cm/cm/engine/communication/src/communication.c | 3 ++- .../staging/nmf-cm/cm/engine/component/src/initializer.c | 1 + .../staging/nmf-cm/cm/engine/component/src/instantiater.c | 15 +++++++++------ drivers/staging/nmf-cm/cm/engine/memory/src/chunk_mgr.c | 9 ++++++--- drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- .../staging/nmf-cm/share/communication/inc/initializer.h | 1 + 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c b/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c index 897ed8038d1..5bd9fbe22fa 100644 --- a/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c +++ b/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c @@ -52,7 +52,8 @@ PRIVATE const t_callback_method internalHostJumptable[] = { processSyncAcknowledge, processAsyncAcknowledge, processSyncAcknowledge, - processSyncAcknowledge + processSyncAcknowledge, // Start sync + processSyncAcknowledge // Stop sync }; PUBLIC t_cm_error cm_COM_Init(t_nmf_coms_location _comsLocation) diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c index 7391669419e..72bc286d1d4 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c @@ -134,6 +134,7 @@ PUBLIC t_cm_error cm_COMP_CallService( t_uint16 params[INIT_COMPONENT_CMD_SIZE]; t_bool isSynchronous = (serviceIndex == NMF_CONSTRUCT_SYNC_INDEX || serviceIndex == NMF_START_SYNC_INDEX || + serviceIndex == NMF_STOP_SYNC_INDEX || serviceIndex == NMF_DESTROY_INDEX)?TRUE:FALSE; params[INIT_COMPONENT_CMD_HANDLE_INDEX] = (t_uint16)((unsigned int)pComp & 0xFFFF); diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c index 2f517a98179..7897a237838 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c @@ -584,6 +584,7 @@ t_cm_error cm_stopComponent(t_component_instance* component, t_nmf_client_id cli { char value[MAX_PROPERTY_VALUE_LENGTH]; t_cm_error error = CM_OK; + t_bool isHwProperty; /* * Special code for SINGLETON handling @@ -609,6 +610,12 @@ t_cm_error cm_stopComponent(t_component_instance* component, t_nmf_client_id cli // CM_ASSERT component->state == STATE_RUNNABLE component->state = STATE_STOPPED; + isHwProperty = (cm_getComponentProperty( + component, + "hardware", + value, + sizeof(value)) == CM_OK); + if (cm_DSP_GetState(component->template->dspId)->state != MPC_STATE_BOOTED) { error = CM_MPC_NOT_RESPONDING; @@ -621,7 +628,7 @@ t_cm_error cm_stopComponent(t_component_instance* component, t_nmf_client_id cli if(component->template->LCCStopAddress != 0) { if ((error = cm_COMP_CallService( - NMF_STOP_INDEX, + isHwProperty ? NMF_STOP_SYNC_INDEX : NMF_STOP_INDEX, component, component->template->LCCStopAddress)) != CM_OK) { @@ -634,11 +641,7 @@ t_cm_error cm_stopComponent(t_component_instance* component, t_nmf_client_id cli /* * Power on, HW resources if required */ - if(cm_getComponentProperty( - component, - "hardware", - value, - sizeof(value)) == CM_OK) + if(isHwProperty) { cm_PWR_DisableMPC(MPC_PWR_HWIP, component->template->dspId); } diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/chunk_mgr.c b/drivers/staging/nmf-cm/cm/engine/memory/src/chunk_mgr.c index 26c00cdeb77..78a549a74ce 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/src/chunk_mgr.c +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/chunk_mgr.c @@ -19,10 +19,10 @@ struct t_page_chuncks { t_cm_chunk chunks[CHUNKS_PER_PAGE]; }; -static struct t_page_chuncks *firstPage; +static struct t_page_chuncks *firstPage = 0; -static unsigned int freeChunks; -static t_cm_chunk *firstFreeChunk; +static unsigned int freeChunks = 0; +static t_cm_chunk *firstFreeChunk = 0; t_cm_chunk* allocChunk() { @@ -91,4 +91,7 @@ void freeChunkPool(void) firstPage = firstPage->nextPage; OSAL_Free(tofree); } + + firstFreeChunk = 0; + freeChunks = 0; } diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index 8e042d3fe62..86e28626498 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (110)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (113)) /*! * \brief Get NMF major version corresponding to NMF version number diff --git a/drivers/staging/nmf-cm/share/communication/inc/initializer.h b/drivers/staging/nmf-cm/share/communication/inc/initializer.h index ea5aa68f2dc..10985c3981a 100644 --- a/drivers/staging/nmf-cm/share/communication/inc/initializer.h +++ b/drivers/staging/nmf-cm/share/communication/inc/initializer.h @@ -19,6 +19,7 @@ #define NMF_ULP_ALLOWSLEEP 8 #define NMF_CONSTRUCT_SYNC_INDEX 9 #define NMF_START_SYNC_INDEX 10 +#define NMF_STOP_SYNC_INDEX 11 /* * Index of datas in command parameter format -- cgit v1.2.3 From 410e1fe46039ea15870a9078d0dd11ddb3bae064 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Tue, 23 Aug 2011 09:13:49 +0200 Subject: U8500 CM: provide MMDSP dump in case of Panic Implement support of debugfs: - Provide several live information through debugfs - Provide support of MMDSP core dump also through debugfs, when a panic occurs. Rework the allocator to enhance the MMDSP stack allocation. ST-Ericsson ID: 356478 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: I19e21a8a0cfa23e9085c2c429ce13f973c552818 --- drivers/staging/nmf-cm/Makefile | 2 +- .../engine/communication/fifo/inc/nmf_fifo_arm.h | 1 - .../cm/engine/communication/src/communication.c | 1 + .../nmf-cm/cm/engine/component/inc/description.h | 2 +- .../nmf-cm/cm/engine/component/inc/instance.h | 5 +- .../nmf-cm/cm/engine/component/inc/nmfheaderabi.h | 6 +- .../nmf-cm/cm/engine/component/src/binder.c | 94 +-- .../nmf-cm/cm/engine/component/src/binder_check.c | 30 +- .../cm/engine/component/src/component_wrapper.c | 143 ++-- .../nmf-cm/cm/engine/component/src/dspevent.c | 6 +- .../nmf-cm/cm/engine/component/src/initializer.c | 6 +- .../nmf-cm/cm/engine/component/src/instantiater.c | 104 +-- .../nmf-cm/cm/engine/component/src/introspection.c | 28 +- .../nmf-cm/cm/engine/component/src/loader.c | 5 +- .../configuration/src/configuration_wrapper.c | 28 +- drivers/staging/nmf-cm/cm/engine/dsp/inc/dsp.h | 1 - drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c | 13 +- drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c | 6 +- .../staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c | 17 +- .../inc/executive_engine_mgt.h | 4 + .../src/executive_engine_mgt.c | 49 +- .../staging/nmf-cm/cm/engine/memory/inc/domain.h | 1 + .../nmf-cm/cm/engine/memory/inc/remote_allocator.h | 10 +- .../cm/engine/memory/inc/remote_allocator_utils.h | 3 +- .../staging/nmf-cm/cm/engine/memory/src/domain.c | 37 +- .../nmf-cm/cm/engine/memory/src/memory_wrapper.c | 1 + .../nmf-cm/cm/engine/memory/src/migration.c | 1 + .../nmf-cm/cm/engine/memory/src/remote_allocator.c | 405 +++++----- .../cm/engine/memory/src/remote_allocator_utils.c | 94 +-- .../os_adaptation_layer/inc/os_adaptation_layer.h | 10 + .../os_adaptation_layer/src/os_adaptation_layer.c | 17 +- .../nmf-cm/cm/engine/perfmeter/src/mpcload.c | 7 +- .../staging/nmf-cm/cm/engine/power_mgt/inc/power.h | 6 +- .../nmf-cm/cm/engine/power_mgt/src/cmpower.c | 6 +- .../cm/engine/repository_mgt/src/repository_mgt.c | 21 +- drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 12 +- drivers/staging/nmf-cm/cm/engine/trace/src/trace.c | 14 +- .../staging/nmf-cm/cm/engine/utils/src/string.c | 2 + drivers/staging/nmf-cm/cm_debug.c | 838 +++++++++++++++++++++ drivers/staging/nmf-cm/cm_debug.h | 19 + drivers/staging/nmf-cm/cm_service.c | 32 +- drivers/staging/nmf-cm/cmioctl.h | 9 + drivers/staging/nmf-cm/cmld.c | 157 ++-- drivers/staging/nmf-cm/cmld.h | 9 + drivers/staging/nmf-cm/configuration.c | 74 +- drivers/staging/nmf-cm/configuration.h | 9 +- drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- drivers/staging/nmf-cm/osal-kernel.c | 147 ++-- drivers/staging/nmf-cm/osal-kernel.h | 63 +- 49 files changed, 1752 insertions(+), 805 deletions(-) create mode 100644 drivers/staging/nmf-cm/cm_debug.c create mode 100644 drivers/staging/nmf-cm/cm_debug.h diff --git a/drivers/staging/nmf-cm/Makefile b/drivers/staging/nmf-cm/Makefile index 0728ac5bc3f..7745132f35e 100644 --- a/drivers/staging/nmf-cm/Makefile +++ b/drivers/staging/nmf-cm/Makefile @@ -34,7 +34,7 @@ ifdef KERNELRELEASE GENERIC_CM_FILES := $(filter-out $(CMENGINESRC_COPY_NO_BUILD), $(GENERIC_CM_FILES)) CM_OBJS := $(GENERIC_CM_FILES:.c=.o) - CM_OBJS += cmld.o cm_syscall.o osal-kernel.o cm_service.o configuration.o + CM_OBJS += cmld.o cm_syscall.o osal-kernel.o cm_service.o cm_debug.o configuration.o CM_OBJS += cm_dma.o obj-$(CONFIG_U8500_CM) := cm.o diff --git a/drivers/staging/nmf-cm/cm/engine/communication/fifo/inc/nmf_fifo_arm.h b/drivers/staging/nmf-cm/cm/engine/communication/fifo/inc/nmf_fifo_arm.h index 41c4f7a7ad6..0463d6a71a5 100644 --- a/drivers/staging/nmf-cm/cm/engine/communication/fifo/inc/nmf_fifo_arm.h +++ b/drivers/staging/nmf-cm/cm/engine/communication/fifo/inc/nmf_fifo_arm.h @@ -13,7 +13,6 @@ #include #include #include -#include #include /* diff --git a/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c b/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c index 5bd9fbe22fa..ead1e090d7c 100644 --- a/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c +++ b/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c @@ -131,6 +131,7 @@ PUBLIC t_cm_error cm_COM_AllocateMpc(t_nmf_core_id coreId) return CM_OK; oom: cm_COM_FreeMpc(coreId); + ERROR("CM_NO_MORE_MEMORY: fifo_alloc() failed in cm_COM_AllocateMpc()\n", 0, 0, 0, 0, 0, 0); return CM_NO_MORE_MEMORY; } diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/description.h b/drivers/staging/nmf-cm/cm/engine/component/inc/description.h index b7d3c34654d..9a03ac5d2f7 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/inc/description.h +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/description.h @@ -21,7 +21,7 @@ typedef struct _t_interface_description { t_uint16 referenceCounter; //!< Number of template referencing the interface t_uint8 methodNumber; //!< Number of method in the interfaces struct _t_interface_description* next; - t_dup_char methodNames[]; //!< Array of method names + t_dup_char methodNames[1]; //!< Array of method names } t_interface_description; /*! diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/instance.h b/drivers/staging/nmf-cm/cm/engine/component/inc/instance.h index 9172d99db79..0a7d80e2e02 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/inc/instance.h +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/instance.h @@ -55,7 +55,7 @@ typedef struct t_component_instance { t_component_state state; //!< Component state t_nmf_ee_priority priority; //!< Executive engine component priority - t_component_template *template; //!< Component template + t_component_template *Template; //!< Component template t_uint32 thisAddress; //!< Cached value of cm_DSP_GetDspAddress(component->memories[data], &thisAddress); @@ -71,6 +71,7 @@ typedef struct t_component_instance { struct t_client_of_singleton *clientOfSingleton; //!< Client of singleton list t_memory_handle loadMapHandle; // handle of allocated memory for the loadMap structure and name; + void *dbgCooky; //!< pointer to OS internal data } t_component_instance; t_component_template* cm_lookupTemplate(t_nmf_core_id dspId, t_dup_char str); @@ -115,7 +116,7 @@ t_cm_error cm_loadComponent( * \ingroup COMPONENT_INTERNAL */ t_cm_error cm_unloadComponent( - t_component_template *template); + t_component_template *reftemplate); /*! * \internal diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/nmfheaderabi.h b/drivers/staging/nmf-cm/cm/engine/component/inc/nmfheaderabi.h index 59d2186f157..9eae19b2f70 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/inc/nmfheaderabi.h +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/nmfheaderabi.h @@ -28,7 +28,7 @@ typedef struct { char *type; //!< Type of this Interface t_uint8 methodNumber; //!< Number of method in the interfaces t_uint8 reserved1, reserved2, reserved3; - char *methodNames[]; //!< Array of method names + char *methodNames[1]; //!< Array of method names [methodNumber] } t_elf_interface_description; /*! @@ -64,7 +64,7 @@ typedef struct { t_uint8 collectionSize; //!< Size of the collection (1 if not a collection) t_uint8 reserved1, reserved2; t_elf_interface_description *interface; //!< Interface description - t_elf_interface_require_index indexes[]; /*!< Require information for each collection index + t_elf_interface_require_index indexes[1]; /*!< Require information for each collection index \note Real type: indexes[collectionSize], available only if not static interface */ } t_elf_required_interface; @@ -89,7 +89,7 @@ typedef struct { t_uint8 collectionSize; //!< Size of the collection (1 if not a collection) t_uint8 reserved1; t_elf_interface_description *interface; //!< Interface description - t_uint32 methodSymbols[]; /*!< Symbol of the real name of methods of the interface for each collection index + t_uint32 methodSymbols[1]; /*!< Symbol of the real name of methods of the interface for each collection index \note Real type: methodSymbols[collectionSize][methodNumber] \note Use relocation in order to get symbol information*/ } t_elf_provided_interface; diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/binder.c b/drivers/staging/nmf-cm/cm/engine/component/src/binder.c index 8586fdfcbc8..e82828f012b 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/binder.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/binder.c @@ -76,8 +76,8 @@ static void cm_bindLowLevelInterface( { const t_component_instance* client = itfRequire->client; t_component_instance* server = (t_component_instance*)itfLocalBC->server; - t_interface_require *require = &client->template->requires[itfRequire->requireIndex]; - t_interface_provide* provide = &server->template->provides[itfLocalBC->provideIndex]; + t_interface_require *require = &client->Template->requires[itfRequire->requireIndex]; + t_interface_provide* provide = &server->Template->provides[itfLocalBC->provideIndex]; int k, j; if(require->indexes != NULL) @@ -139,7 +139,7 @@ static void cm_bindLowLevelInterface( } else { - t_function_relocation *reloc = client->template->delayedRelocation; + t_function_relocation *reloc = client->Template->delayedRelocation; while(reloc != NULL) { for(j = 0; j < provide->interface->methodNumber; j++) { @@ -174,7 +174,7 @@ static void cm_bindLowLevelInterface( * cm_destroyInstance() of server to succeed (interrupt line bindings are * destroyed after the check in cm_destroyInstance() */ - if (client->template->classe != FIRMWARE) + if (client->Template->classe != FIRMWARE) server->providedItfUsedCount++; } } @@ -194,7 +194,7 @@ static void cm_registerLowLevelInterfaceToConst( // This is an unbind from a true component (not to void) // Do not count bindings from EE (ie interrupt line) if ((targetInstance == NULL) - && (client->template->classe != FIRMWARE) + && (client->Template->classe != FIRMWARE) && (itfRef->instance != (t_component_instance *)NMF_VOID_COMPONENT) && (itfRef->instance != NULL)) { @@ -211,14 +211,14 @@ static void cm_bindLowLevelInterfaceToConst( const t_dsp_address functionAddress, const t_component_instance* targetInstance) { const t_component_instance* client = itfRequire->client; - t_interface_require *require = &client->template->requires[itfRequire->requireIndex]; + t_interface_require *require = &client->Template->requires[itfRequire->requireIndex]; int j, k; // If DSP is off/panic/... -> write nothing if( require->indexes != NULL - && cm_DSP_GetState(client->template->dspId)->state == MPC_STATE_BOOTED) + && cm_DSP_GetState(client->Template->dspId)->state == MPC_STATE_BOOTED) { t_interface_require_index *requireindex = &require->indexes[itfRequire->collectionIndex]; @@ -295,8 +295,8 @@ t_cm_error cm_bindInterface( cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, itfRequire->client, itfProvide->server, - itfRequire->client->template->requires[itfRequire->requireIndex].name, - itfProvide->server->template->provides[itfProvide->provideIndex].name); + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + itfProvide->server->Template->provides[itfProvide->provideIndex].name); return CM_OK; } @@ -312,7 +312,7 @@ void cm_unbindInterface( cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_SYNCHRONOUS, itfRequire->client, NULL, - itfRequire->client->template->requires[itfRequire->requireIndex].name, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); cm_bindLowLevelInterfaceToConst(itfRequire, @@ -329,12 +329,12 @@ t_cm_error cm_bindInterfaceToVoid( itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); cm_bindLowLevelInterfaceToConst(itfRequire, - cm_EEM_getExecutiveEngine(itfRequire->client->template->dspId)->voidAddr, + cm_EEM_getExecutiveEngine(itfRequire->client->Template->dspId)->voidAddr, (t_component_instance*)NMF_VOID_COMPONENT); cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, itfRequire->client, NULL, - itfRequire->client->template->requires[itfRequire->requireIndex].name, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); return CM_OK; @@ -369,7 +369,7 @@ t_cm_error cm_bindInterfaceTrace( const t_interface_provide_description *itfProvide, t_elfdescription *elfhandleTrace) { - t_interface_require *require = &itfRequire->client->template->requires[itfRequire->requireIndex]; + t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; t_interface_require_description bcitfRequire; t_interface_provide_description bcitfProvide; t_trace_bf_info *bfInfo; @@ -418,8 +418,8 @@ t_cm_error cm_bindInterfaceTrace( cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, itfRequire->client, itfProvide->server, - itfRequire->client->template->requires[itfRequire->requireIndex].name, - itfProvide->server->template->provides[itfProvide->provideIndex].name); + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + itfProvide->server->Template->provides[itfProvide->provideIndex].name); return CM_OK; } @@ -435,7 +435,7 @@ void cm_unbindInterfaceTrace( cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_SYNCHRONOUS, itfRequire->client, NULL, - itfRequire->client->template->requires[itfRequire->requireIndex].name, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); /* Unbind Client from Event Binding Component */ @@ -464,7 +464,7 @@ t_cm_error cm_bindInterfaceAsynchronous( t_uint32 fifosize, t_dsp_memory_type_id dspEventMemType, t_elfdescription *elfhandleEvent) { - t_interface_require *require = &itfRequire->client->template->requires[itfRequire->requireIndex]; + t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; t_interface_require_description eventitfRequire; t_interface_provide_description eventitfProvide; t_async_bf_info *bfInfo; @@ -536,8 +536,8 @@ t_cm_error cm_bindInterfaceAsynchronous( cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, itfRequire->client, itfProvide->server, - itfRequire->client->template->requires[itfRequire->requireIndex].name, - itfProvide->server->template->provides[itfProvide->provideIndex].name); + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + itfProvide->server->Template->provides[itfProvide->provideIndex].name); return CM_OK; } @@ -553,7 +553,7 @@ void cm_unbindInterfaceAsynchronous( cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, itfRequire->client, NULL, - itfRequire->client->template->requires[itfRequire->requireIndex].name, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); /* Unbind Client from Event Binding Component */ @@ -586,8 +586,8 @@ PRIVATE t_cm_error cm_createParamsFifo(t_component_instance *stub, t_uint32 *fifoElemSize, t_uint32 bcDescSize) { - t_nmf_core_id stubcore = (stub != NULL) ?(stub->template->dspId): ARM_CORE_ID; - t_nmf_core_id skelcore = (skeleton != NULL) ?(skeleton->template->dspId) : ARM_CORE_ID; + t_nmf_core_id stubcore = (stub != NULL) ?(stub->Template->dspId): ARM_CORE_ID; + t_nmf_core_id skelcore = (skeleton != NULL) ?(skeleton->Template->dspId) : ARM_CORE_ID; t_component_instance *bcnotnull = (stub != NULL) ? stub : skeleton; int _fifoelemsize; @@ -601,8 +601,10 @@ PRIVATE t_cm_error cm_createParamsFifo(t_component_instance *stub, /* Allocation of the fifo params */ *fifo = fifo_alloc(stubcore, skelcore, _fifoelemsize, fifosize, 1+bcDescSize, paramsLocation, extendedFieldLocation, domainId); /* 1+nbMethods fro hostBCThis_or_TOP space */ - if(*fifo == NULL) + if(*fifo == NULL) { + ERROR("CM_NO_MORE_MEMORY: fifo_alloc() failed in cm_createParamsFifo()\n", 0, 0, 0, 0, 0, 0); return CM_NO_MORE_MEMORY; + } if(stub != NULL) { @@ -639,7 +641,7 @@ PRIVATE t_cm_error cm_createDSPSkeleton( t_elfdescription *elfhandleSkeleton, t_dspskel_bf_info *bfInfo) { - t_interface_provide *provide = &itfProvide->server->template->provides[itfProvide->provideIndex]; + t_interface_provide *provide = &itfProvide->server->Template->provides[itfProvide->provideIndex]; t_interface_require_description skelitfRequire; t_cm_error error; unsigned int fifoeventsize = 0; @@ -715,7 +717,7 @@ t_cm_error cm_bindComponentFromCMCore( t_dsp_memory_type_id dspEventMemType, t_elfdescription *elfhandleSkeleton, t_host2mpc_bf_info **bfInfo) { - t_interface_provide *provide = &itfProvide->server->template->provides[itfProvide->provideIndex]; + t_interface_provide *provide = &itfProvide->server->Template->provides[itfProvide->provideIndex]; t_dsp_offset shareVarOffset; t_cm_error error; @@ -771,7 +773,7 @@ t_cm_error cm_bindComponentFromCMCore( fifo_params_setSharedField( (*bfInfo)->fifo, 1+i, - skel->template->provides[0].indexes[0][i].methodAddresses + skel->Template->provides[0].indexes[0][i].methodAddresses ); } } @@ -779,7 +781,7 @@ t_cm_error cm_bindComponentFromCMCore( cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, ARM_TRACE_COMPONENT, itfProvide->server, NULL, - itfProvide->server->template->provides[itfProvide->provideIndex].name); + itfProvide->server->Template->provides[itfProvide->provideIndex].name); return CM_OK; } @@ -788,7 +790,7 @@ void cm_unbindComponentFromCMCore( t_host2mpc_bf_info* bfInfo) { t_component_instance *skel = bfInfo->dspskeleton.skelInstance; t_interface_reference* itfProvide = &skel->interfaceReferences[0][0]; - t_interface_provide *provide = &itfProvide->instance->template->provides[itfProvide->provideIndex]; + t_interface_provide *provide = &itfProvide->instance->Template->provides[itfProvide->provideIndex]; LOG_INTERNAL(1, "\n##### UnBind HOST -> %s/%x.%s #####\n", itfProvide->instance->pathname, itfProvide->instance, provide->name, 0, 0, 0); @@ -796,7 +798,7 @@ void cm_unbindComponentFromCMCore( cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, ARM_TRACE_COMPONENT, itfProvide->instance, NULL, - itfProvide->instance->template->provides[itfProvide->provideIndex].name); + itfProvide->instance->Template->provides[itfProvide->provideIndex].name); // Destroy FIFO params cm_destroyParamsFifo(bfInfo->fifo); @@ -866,7 +868,7 @@ t_cm_error cm_bindComponentToCMCore( t_uint32 context, t_elfdescription *elfhandleStub, t_mpc2host_bf_info ** bfInfo) { - t_interface_require *require = &itfRequire->client->template->requires[itfRequire->requireIndex]; + t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; t_interface_provide_description itfstubProvide; t_cm_error error; t_uint32 fifoelemsize; @@ -921,7 +923,7 @@ t_cm_error cm_bindComponentToCMCore( cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, itfRequire->client, ARM_TRACE_COMPONENT, - itfRequire->client->template->requires[itfRequire->requireIndex].name, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); return error; @@ -936,7 +938,7 @@ void cm_unbindComponentToCMCore( cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, itfRequire->client, ARM_TRACE_COMPONENT, - itfRequire->client->template->requires[itfRequire->requireIndex].name, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); /* Unbind virtual interface coms */ @@ -962,7 +964,7 @@ t_cm_error cm_bindInterfaceDistributed( t_dsp_memory_type_id dspEventMemType, t_elfdescription *elfhandleSkeleton, t_elfdescription *elfhandleStub) { - t_interface_require *require = &itfRequire->client->template->requires[itfRequire->requireIndex]; + t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; t_interface_provide_description itfstubProvide; t_cm_error error; t_mpc2mpc_bf_info *bfInfo; @@ -1041,15 +1043,15 @@ t_cm_error cm_bindInterfaceDistributed( fifo_params_setSharedField( bfInfo->fifo, 1+i, - skel->template->provides[0].indexes[0][i].methodAddresses + skel->Template->provides[0].indexes[0][i].methodAddresses ); } } cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, itfRequire->client, itfProvide->server, - itfRequire->client->template->requires[itfRequire->requireIndex].name, - itfProvide->server->template->provides[itfProvide->provideIndex].name); + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + itfProvide->server->Template->provides[itfProvide->provideIndex].name); return CM_OK; } @@ -1066,7 +1068,7 @@ void cm_unbindInterfaceDistributed( cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, itfRequire->client, NULL, - itfRequire->client->template->requires[itfRequire->requireIndex].name, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, NULL); /* Unbind virtual interface */ @@ -1138,15 +1140,15 @@ void cm_destroyRequireInterface(t_component_instance* component, t_nmf_client_id /* * Special code for SINGLETON handling */ - if(component->template->classe == SINGLETON) + if(component->Template->classe == SINGLETON) { if(getNumberOfBind(component) > 0) return; } - for(i = 0; i < component->template->requireNumber; i++) + for(i = 0; i < component->Template->requireNumber; i++) { - int nb = component->template->requires[i].collectionSize; + int nb = component->Template->requires[i].collectionSize; for(j = 0; j < nb; j++) { if(component->interfaceReferences[i][j].instance != NULL) @@ -1157,7 +1159,7 @@ void cm_destroyRequireInterface(t_component_instance* component, t_nmf_client_id itfRequire.client = component; itfRequire.requireIndex = i; itfRequire.collectionIndex = j; - itfRequire.origName = component->template->requires[i].name; + itfRequire.origName = component->Template->requires[i].name; switch (itfRef->bfInfoID) { case BF_SYNCHRONOUS: @@ -1202,7 +1204,7 @@ void cm_registerSingletonBinding( t_interface_provide_description* itfProvide, t_nmf_client_id clientId) { - if(component->template->classe == SINGLETON) + if(component->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); if(cl != NULL) @@ -1226,7 +1228,7 @@ t_bool cm_unregisterSingletonBinding( t_interface_provide_description* itfProvide, t_nmf_client_id clientId) { - if(component->template->classe == SINGLETON) + if(component->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); if(cl != NULL) @@ -1251,17 +1253,17 @@ t_bool cm_unregisterSingletonBinding( LOG_INTERNAL(1, " -> Singleton[%d] : All required of %s/%x logically unbound, perform physical unbind\n", clientId, itfRequire->client->pathname, itfRequire->client, 0, 0, 0); - (void)cm_EEM_ForceWakeup(component->template->dspId); + (void)cm_EEM_ForceWakeup(component->Template->dspId); // This is the last binding unbind all !!! cm_destroyRequireInterface(component, clientId); - cm_EEM_AllowSleep(component->template->dspId); + cm_EEM_AllowSleep(component->Template->dspId); } else if(itfProvide->server != NULL) { t_interface_require* itfReq; - itfReq = &itfRequire->client->template->requires[itfRequire->requireIndex]; + itfReq = &itfRequire->client->Template->requires[itfRequire->requireIndex]; if((itfReq->requireTypes & OPTIONAL_REQUIRE) != 0x0) return TRUE; } diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c b/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c index b141064c1c1..8a3c3c33de8 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c @@ -29,7 +29,7 @@ t_cm_error cm_checkValidClient( if(itfRef->instance != (t_component_instance*)NULL) { - if(client->template->classe == SINGLETON) + if(client->Template->classe == SINGLETON) { // Singleton is immutable thus we can't rebind it, nevertheless it's not an issue *bindable = FALSE; @@ -41,11 +41,11 @@ t_cm_error cm_checkValidClient( if(itfRef->instance == (const t_component_instance*)NMF_VOID_COMPONENT) ERROR("CM_INTERFACE_ALREADY_BINDED(): Component (%s<%s>.s) already bound to VOID\n", - client->pathname, client->template->name, requiredItfClientName, 0, 0, 0); + client->pathname, client->Template->name, requiredItfClientName, 0, 0, 0); else ERROR("CM_INTERFACE_ALREADY_BINDED(): Component (%s<%s>.s) already bound to another server (%s<%s>.%s)\n", - client->pathname, client->template->name, requiredItfClientName, - itfRef->instance->pathname, itfRef->instance->template->name, itfRef->instance->template->provides[itfRef->provideIndex].name); + client->pathname, client->Template->name, requiredItfClientName, + itfRef->instance->pathname, itfRef->instance->Template->name, itfRef->instance->Template->provides[itfRef->provideIndex].name); return CM_INTERFACE_ALREADY_BINDED; } } @@ -53,7 +53,7 @@ t_cm_error cm_checkValidClient( // Delayed Component LC state check done only if not optional required interface or intrinsic one that has been solved by loader { - t_interface_require* itfReq = &client->template->requires[itfRequire->requireIndex]; + t_interface_require* itfReq = &client->Template->requires[itfRequire->requireIndex]; if((itfReq->requireTypes & (OPTIONAL_REQUIRE | INTRINSEC_REQUIRE)) == 0) { if(client->state == STATE_RUNNABLE) @@ -107,7 +107,7 @@ t_cm_error cm_checkValidBinding( // If this is a singleton which has been already bound check that next binding is at the same server if(*bindable == FALSE - && client->template->classe == SINGLETON) + && client->Template->classe == SINGLETON) { t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; while( itfRef->instance != server @@ -117,7 +117,7 @@ t_cm_error cm_checkValidBinding( if(itfRef->instance == (const t_component_instance*)NMF_VOID_COMPONENT) { ERROR("CM_INTERFACE_ALREADY_BINDED(): Singleton (%s<%s>.s) already bound to VOID\n", - client->pathname, client->template->name, requiredItfClientName, 0, 0, 0); + client->pathname, client->Template->name, requiredItfClientName, 0, 0, 0); return CM_INTERFACE_ALREADY_BINDED; } else if(itfRef->bfInfoID == BF_ASYNCHRONOUS || itfRef->bfInfoID == BF_TRACE) @@ -131,16 +131,16 @@ t_cm_error cm_checkValidBinding( else { ERROR("CM_INTERFACE_ALREADY_BINDED(): Singleton (%s<%s>.s) already bound to different server (%s<%s>.%s)\n", - client->pathname, client->template->name, requiredItfClientName, - itfRef->instance->pathname, itfRef->instance->template->name, itfRef->instance->template->provides[itfRef->provideIndex].name); + client->pathname, client->Template->name, requiredItfClientName, + itfRef->instance->pathname, itfRef->instance->Template->name, itfRef->instance->Template->provides[itfRef->provideIndex].name); return CM_INTERFACE_ALREADY_BINDED; } } } // Check if provided and required type matches - require = &client->template->requires[itfRequire->requireIndex]; - provide = &server->template->provides[itfProvide->provideIndex]; + require = &client->Template->requires[itfRequire->requireIndex]; + provide = &server->Template->provides[itfProvide->provideIndex]; if(require->interface != provide->interface) { ERROR("CM_ILLEGAL_BINDING(%s, %s)\n", require->interface->type, provide->interface->type, 0, 0, 0, 0); @@ -149,7 +149,7 @@ t_cm_error cm_checkValidBinding( // Check if static required interface binded to singleton component if((require->requireTypes & STATIC_REQUIRE) && - (server->template->classe != SINGLETON)) + (server->Template->classe != SINGLETON)) { ERROR("CM_ILLEGAL_BINDING(): Can't bind static required interface to not singleton component\n", 0, 0, 0, 0, 0, 0); @@ -175,14 +175,14 @@ t_cm_error cm_checkValidUnbinding( if ((error = cm_getRequiredInterface(client, requiredItfClientName, itfRequire)) != CM_OK) return error; - itfReq = &client->template->requires[itfRequire->requireIndex]; + itfReq = &client->Template->requires[itfRequire->requireIndex]; // Check if the requiredItfClientName is required by client component if ((error = cm_lookupInterface(itfRequire, itfProvide)) != CM_OK) { // We allow to unbind optional required of singleton even if not binded, since it could have been unbound previously but we don't // want to break bind singleton reference counter - if((client->template->classe == SINGLETON) && + if((client->Template->classe == SINGLETON) && (itfReq->requireTypes & OPTIONAL_REQUIRE) != 0x0) return CM_OK; @@ -190,7 +190,7 @@ t_cm_error cm_checkValidUnbinding( } // Singleton is immutable, don't unbind it - if(client->template->classe == SINGLETON) + if(client->Template->classe == SINGLETON) return CM_OK; /* if interface is optionnal then allow unbinding even if not stop */ diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c b/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c index 07d20d0266e..88e6b4749ec 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c @@ -139,7 +139,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_DestroyComponent( } else { - t_nmf_core_id coreId = component->template->dspId; + t_nmf_core_id coreId = component->Template->dspId; (void)cm_EEM_ForceWakeup(coreId); @@ -171,18 +171,19 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_FlushComponents(t_nmf_client_id client (void)cm_EEM_ForceWakeup(SIA_CORE_ID); /* Destroy all host2mpc bindings */ + OSAL_LOCK_COM(); for (i=0; iclientId == clientId)) { cm_delEntry(&Host2MpcBindingTable, i); OSAL_UNLOCK_COM(); cm_unbindComponentFromCMCore(bfInfo); - } else - OSAL_UNLOCK_COM(); + OSAL_LOCK_COM(); + } } + OSAL_UNLOCK_COM(); /* First, stop all remaining components for this client */ for (i=0; itemplate->classe == FIRMWARE) || + (instance->Template->classe == FIRMWARE) || /* Skip all binding components */ - (cm_StringCompare(instance->template->name, "_ev.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_st.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_sk.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_tr.", 4) == 0)) + (cm_StringCompare(instance->Template->name, "_ev.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_st.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_sk.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_tr.", 4) == 0)) continue; /* * Special code for SINGLETON handling */ - if(instance->template->classe == SINGLETON) + if(instance->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = cm_getClientOfSingleton(instance, FALSE, clientId); if(cl == NULL) @@ -218,7 +219,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_FlushComponents(t_nmf_client_id client // Stop the component error = cm_stopComponent(instance, clientId); if (error != CM_OK && error != CM_COMPONENT_NOT_STARTED) - LOG_INTERNAL(0, "Error stopping component %s/%x (%s, error=%d, client=%u)\n", instance->pathname, instance, instance->template->name, error, clientId, 0); + LOG_INTERNAL(0, "Error stopping component %s/%x (%s, error=%d, client=%u)\n", instance->pathname, instance, instance->Template->name, error, clientId, 0); // Destroy dependencies cm_destroyRequireInterface(instance, clientId); @@ -230,12 +231,12 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_FlushComponents(t_nmf_client_id client if ((instance = componentEntry(i)) == NULL) continue; if (/* skip EE */ - (instance->template->classe == FIRMWARE) || + (instance->Template->classe == FIRMWARE) || /* Skip all binding components */ - (cm_StringCompare(instance->template->name, "_ev.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_st.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_sk.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_tr.", 4) == 0)) { + (cm_StringCompare(instance->Template->name, "_ev.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_st.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_sk.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_tr.", 4) == 0)) { continue; } @@ -243,7 +244,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_FlushComponents(t_nmf_client_id client /* * Special code for SINGLETON handling */ - if(instance->template->classe == SINGLETON) + if(instance->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = cm_getClientOfSingleton(instance, FALSE, clientId); if(cl == NULL) @@ -316,7 +317,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponent( goto out; // Check that client and server component run on same DSP - if (itfRequire.client->template->dspId != itfProvide.server->template->dspId) + if (itfRequire.client->Template->dspId != itfProvide.server->Template->dspId) { error = CM_ILLEGAL_BINDING; goto out; @@ -325,7 +326,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponent( // Check if we really need to bind if(bindable) { - if ((error = cm_EEM_ForceWakeup(itfRequire.client->template->dspId)) != CM_OK) + if ((error = cm_EEM_ForceWakeup(itfRequire.client->Template->dspId)) != CM_OK) goto out; /* @@ -336,7 +337,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponent( else error = cm_bindInterface(&itfRequire, &itfProvide); - cm_EEM_AllowSleep(itfRequire.client->template->dspId); + cm_EEM_AllowSleep(itfRequire.client->Template->dspId); } cm_registerSingletonBinding(client, &itfRequire, &itfProvide, clientId); @@ -376,7 +377,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponent( // Check if we really need to unbind if(cm_unregisterSingletonBinding(client, &itfRequire, &itfProvide, clientId)) { - (void)cm_EEM_ForceWakeup(itfRequire.client->template->dspId); + (void)cm_EEM_ForceWakeup(itfRequire.client->Template->dspId); if(bfInfoID == BF_SYNCHRONOUS) cm_unbindInterface(&itfRequire); @@ -385,7 +386,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponent( &itfRequire, (t_trace_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); - cm_EEM_AllowSleep(itfRequire.client->template->dspId); + cm_EEM_AllowSleep(itfRequire.client->Template->dspId); error = CM_OK; } @@ -416,12 +417,12 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentToVoid( // Check if we really need to bind if(bindable) { - if ((error = cm_EEM_ForceWakeup(itfRequire.client->template->dspId)) != CM_OK) + if ((error = cm_EEM_ForceWakeup(itfRequire.client->Template->dspId)) != CM_OK) goto out; error = cm_bindInterfaceToVoid(&itfRequire); - cm_EEM_AllowSleep(itfRequire.client->template->dspId); + cm_EEM_AllowSleep(itfRequire.client->Template->dspId); } cm_registerSingletonBinding(client, &itfRequire, NULL, clientId); @@ -496,13 +497,13 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentAsynchronous( if(bindable) { // Create the binding and bind it to the client (or all sub-components clients ....) - if (itfRequire.client->template->dspId != itfProvide.server->template->dspId) + if (itfRequire.client->Template->dspId != itfProvide.server->Template->dspId) { - if ((error = cm_EEM_ForceWakeup(itfRequire.client->template->dspId)) != CM_OK) + if ((error = cm_EEM_ForceWakeup(itfRequire.client->Template->dspId)) != CM_OK) goto out; - if ((error = cm_EEM_ForceWakeup(itfProvide.server->template->dspId)) != CM_OK) + if ((error = cm_EEM_ForceWakeup(itfProvide.server->Template->dspId)) != CM_OK) { - cm_EEM_AllowSleep(itfRequire.client->template->dspId); + cm_EEM_AllowSleep(itfRequire.client->Template->dspId); goto out; } @@ -515,12 +516,12 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentAsynchronous( elfhandleSkeletonOrEvent, elfhandleStub); - cm_EEM_AllowSleep(itfRequire.client->template->dspId); - cm_EEM_AllowSleep(itfProvide.server->template->dspId); + cm_EEM_AllowSleep(itfRequire.client->Template->dspId); + cm_EEM_AllowSleep(itfProvide.server->Template->dspId); } else { - if ((error = cm_EEM_ForceWakeup(itfRequire.client->template->dspId)) != CM_OK) + if ((error = cm_EEM_ForceWakeup(itfRequire.client->Template->dspId)) != CM_OK) goto out; // This is a acynchronous communication @@ -531,7 +532,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentAsynchronous( dspEventMemType, elfhandleSkeletonOrEvent); - cm_EEM_AllowSleep(itfRequire.client->template->dspId); + cm_EEM_AllowSleep(itfRequire.client->Template->dspId); } } @@ -570,8 +571,8 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentAsynchronous( // Check if this is a Asynchronous binding if(bfInfoID == BF_DSP2DSP) { - t_nmf_core_id clientDsp = itfRequire.client->template->dspId; - t_nmf_core_id serverDsp = itfProvide.server->template->dspId; + t_nmf_core_id clientDsp = itfRequire.client->Template->dspId; + t_nmf_core_id serverDsp = itfProvide.server->Template->dspId; (void)cm_EEM_ForceWakeup(clientDsp); (void)cm_EEM_ForceWakeup(serverDsp); @@ -587,7 +588,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentAsynchronous( } else if(bfInfoID == BF_ASYNCHRONOUS) { - t_nmf_core_id clientDsp = itfRequire.client->template->dspId; + t_nmf_core_id clientDsp = itfRequire.client->Template->dspId; (void)cm_EEM_ForceWakeup(clientDsp); @@ -641,7 +642,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentFromCMCore( &itfProvide)) != CM_OK) goto out; - if ((error = cm_EEM_ForceWakeup(itfProvide.server->template->dspId)) != CM_OK) + if ((error = cm_EEM_ForceWakeup(itfProvide.server->Template->dspId)) != CM_OK) goto out; switch(eventMemType) @@ -665,7 +666,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentFromCMCore( elfhandleSkeleton, &bfInfo); - cm_EEM_AllowSleep(itfProvide.server->template->dspId); + cm_EEM_AllowSleep(itfProvide.server->Template->dspId); out: cm_ELF_CloseFile(TRUE, elfhandleSkeleton); @@ -681,9 +682,9 @@ out: if (error != CM_OK) { OSAL_LOCK_API(); - (void)cm_EEM_ForceWakeup(itfProvide.server->template->dspId); + (void)cm_EEM_ForceWakeup(itfProvide.server->Template->dspId); cm_unbindComponentFromCMCore(bfInfo); - cm_EEM_AllowSleep(itfProvide.server->template->dspId); + cm_EEM_AllowSleep(itfProvide.server->Template->dspId); OSAL_UNLOCK_API(); } } @@ -709,7 +710,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentFromCMCore( // Check if this is a DSP to Host binding //if(bfInfo->id != BF_HOST2DSP) // return CM_ILLEGAL_UNBINDING; - coreId = bfInfo->dspskeleton.skelInstance->template->dspId; + coreId = bfInfo->dspskeleton.skelInstance->Template->dspId; (void)cm_EEM_ForceWakeup(coreId); @@ -756,7 +757,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentToCMCore( // Check if we really need to bind if(bindable) { - if ((error = cm_EEM_ForceWakeup(itfRequire.client->template->dspId)) != CM_OK) + if ((error = cm_EEM_ForceWakeup(itfRequire.client->Template->dspId)) != CM_OK) goto out; error = cm_bindComponentToCMCore( @@ -766,7 +767,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentToCMCore( elfhandleStub, (t_mpc2host_bf_info**)mpc2hostId); - cm_EEM_AllowSleep(itfRequire.client->template->dspId); + cm_EEM_AllowSleep(itfRequire.client->Template->dspId); } cm_registerSingletonBinding(client, &itfRequire, NULL, clientId); @@ -811,11 +812,11 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentToCMCore( // Check if we really need to unbind if(cm_unregisterSingletonBinding(client, &itfRequire, &itfProvide, clientId)) { - (void)cm_EEM_ForceWakeup(itfRequire.client->template->dspId); + (void)cm_EEM_ForceWakeup(itfRequire.client->Template->dspId); cm_unbindComponentToCMCore(&itfRequire, bfInfo); - cm_EEM_AllowSleep(itfRequire.client->template->dspId); + cm_EEM_AllowSleep(itfRequire.client->Template->dspId); error = CM_OK; } @@ -838,7 +839,7 @@ PUBLIC EXPORT_SHARED t_event_params_handle CM_ENGINE_AllocEvent(t_cm_bf_host2mpc if(bfInfo->dspskeleton.skelInstance->interfaceReferences[0][0].instance->state != STATE_RUNNABLE) { ERROR("CM_COMPONENT_NOT_STARTED: Call interface before start component %s<%s>\n", bfInfo->dspskeleton.skelInstance->pathname, - bfInfo->dspskeleton.skelInstance->template->name, 0, 0, 0, 0); + bfInfo->dspskeleton.skelInstance->Template->name, 0, 0, 0, 0); } eventHandle = cm_AllocEvent(bfInfo->fifo); @@ -891,13 +892,13 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_ReadComponentAttribute( error = CM_INVALID_COMPONENT_HANDLE; else { - if ((error = cm_EEM_ForceWakeup(component->template->dspId)) != CM_OK) + if ((error = cm_EEM_ForceWakeup(component->Template->dspId)) != CM_OK) goto out; // t_uint24 -> t_uint32 possible since we know it same size error = cm_readAttribute(component, attrName, (t_uint32*)attrValue); - cm_EEM_AllowSleep(component->template->dspId); + cm_EEM_AllowSleep(component->Template->dspId); } out: @@ -921,7 +922,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentListHeader( *headerComponent = 0; for (i=0; i < ComponentTable.idxMax; i++) { if ((componentEntry(i) != NULL) && - (componentEntry(i)->template->classe != FIRMWARE) && + (componentEntry(i)->Template->classe != FIRMWARE) && (domainDesc[componentEntry(i)->domainId].client == client)) { *headerComponent = ENTRY2HANDLE(componentEntry(i), i);; break; @@ -950,7 +951,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentListNext( *nextComponent = 0; for (i++; i < ComponentTable.idxMax; i++) { if ((componentEntry(i) != NULL) && - (componentEntry(i)->template->classe != FIRMWARE) && + (componentEntry(i)->Template->classe != FIRMWARE) && (domainDesc[componentEntry(i)->domainId].client == client)) { *nextComponent = ENTRY2HANDLE(componentEntry(i), i);; break; @@ -985,9 +986,9 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentDescription( } else { cm_StringCopy( templateName, - comp->template->name, + comp->Template->name, templateNameLength); - *coreId = comp->template->dspId; + *coreId = comp->Template->dspId; cm_StringCopy( localName, comp->pathname, @@ -1018,7 +1019,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterfaceNumber( if (NULL == comp) { error = CM_INVALID_COMPONENT_HANDLE; } else { - *numberRequiredInterfaces = comp->template->requireNumber; + *numberRequiredInterfaces = comp->Template->requireNumber; error = CM_OK; } @@ -1046,29 +1047,29 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterface( // Sanity check if (NULL == comp) { error = CM_INVALID_COMPONENT_HANDLE; - } else if(index >= comp->template->requireNumber) { + } else if(index >= comp->Template->requireNumber) { error = CM_NO_SUCH_REQUIRED_INTERFACE; } else { cm_StringCopy( itfName, - comp->template->requires[index].name, + comp->Template->requires[index].name, itfNameLength); cm_StringCopy( itfType, - comp->template->requires[index].interface->type, + comp->Template->requires[index].interface->type, itfTypeLength); - if(comp->template->requires[index].requireTypes & COLLECTION_REQUIRE) - *collectionSize = comp->template->requires[index].collectionSize; + if(comp->Template->requires[index].requireTypes & COLLECTION_REQUIRE) + *collectionSize = comp->Template->requires[index].collectionSize; else *collectionSize = -1; if(requireState != NULL) { *requireState = 0; - if(comp->template->requires[index].requireTypes & COLLECTION_REQUIRE) + if(comp->Template->requires[index].requireTypes & COLLECTION_REQUIRE) *requireState |= CM_REQUIRE_COLLECTION; - if(comp->template->requires[index].requireTypes & OPTIONAL_REQUIRE) + if(comp->Template->requires[index].requireTypes & OPTIONAL_REQUIRE) *requireState |= CM_REQUIRE_OPTIONAL; - if(comp->template->requires[index].requireTypes & STATIC_REQUIRE) + if(comp->Template->requires[index].requireTypes & STATIC_REQUIRE) *requireState |= CM_REQUIRE_STATIC; } @@ -1119,9 +1120,9 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterfaceBinding( } else if(*server != 0) { cm_StringCopy( serverItfName, - itfProvide.server->template->provides[itfProvide.provideIndex].name, + itfProvide.server->Template->provides[itfProvide.provideIndex].name, serverItfNameLength); - if(itfProvide.server->template->provides[itfProvide.provideIndex].provideTypes & COLLECTION_PROVIDE) { + if(itfProvide.server->Template->provides[itfProvide.provideIndex].provideTypes & COLLECTION_PROVIDE) { int len = cm_StringLength(serverItfName, serverItfNameLength); serverItfName[len++] = '['; if(itfProvide.collectionIndex >= 100) @@ -1158,7 +1159,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentProvidedInterfaceNumber( if (NULL == comp) { error = CM_INVALID_COMPONENT_HANDLE; } else { - *numberProvidedInterfaces = comp->template->provideNumber; + *numberProvidedInterfaces = comp->Template->provideNumber; error = CM_OK; } @@ -1185,19 +1186,19 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentProvidedInterface( // Sanity check if (NULL == comp) { error = CM_INVALID_COMPONENT_HANDLE; - } else if(index >= comp->template->provideNumber) { + } else if(index >= comp->Template->provideNumber) { error = CM_NO_SUCH_PROVIDED_INTERFACE; } else { cm_StringCopy( itfName, - comp->template->provides[index].name, + comp->Template->provides[index].name, itfNameLength); cm_StringCopy( itfType, - comp->template->provides[index].interface->type, + comp->Template->provides[index].interface->type, itfTypeLength); - if(comp->template->provides[index].provideTypes & COLLECTION_PROVIDE) - *collectionSize = comp->template->provides[index].collectionSize; + if(comp->Template->provides[index].provideTypes & COLLECTION_PROVIDE) + *collectionSize = comp->Template->provides[index].collectionSize; else *collectionSize = -1; @@ -1225,7 +1226,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentPropertyNumber( if (NULL == comp) { error = CM_INVALID_COMPONENT_HANDLE; } else { - *numberProperties = comp->template->propertyNumber; + *numberProperties = comp->Template->propertyNumber; error = CM_OK; } @@ -1249,12 +1250,12 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentPropertyName( // Sanity check if (NULL == comp) { error = CM_INVALID_COMPONENT_HANDLE; - } else if(index >= comp->template->propertyNumber) { + } else if(index >= comp->Template->propertyNumber) { error = CM_NO_SUCH_PROPERTY; } else { cm_StringCopy( propertyName, - comp->template->properties[index].name, + comp->Template->properties[index].name, propertyNameLength); error = CM_OK; diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c b/drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c index 0c055c7f6f9..0d5e89e0515 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c @@ -33,8 +33,10 @@ t_cm_error dspevent_createDspEventFifo( // Allocate fifo *pHandle = cm_DM_Alloc(pComp->domainId, dspEventMemType, fifoNbElem*fifoElemSizeInWord, CM_MM_ALIGN_2WORDS, TRUE); - if(*pHandle == INVALID_MEMORY_HANDLE) - return CM_NO_MORE_MEMORY; + if(*pHandle == INVALID_MEMORY_HANDLE) { + ERROR("CM_NO_MORE_MEMORY: dspevent_createDspEventFifo()\n", 0, 0, 0, 0, 0, 0); + return CM_NO_MORE_MEMORY; + } cm_DSP_GetDspAddress(*pHandle, &dspElementAddr); diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c index 72bc286d1d4..625d0a06796 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c @@ -49,7 +49,7 @@ PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId) // Get interface description if((error = cm_getProvidedInterface(ee, "service", &itfProvide)) != CM_OK) return error; - provide = &ee->template->provides[itfProvide.provideIndex]; + provide = &ee->Template->provides[itfProvide.provideIndex]; if ((error = dspevent_createDspEventFifo( @@ -78,6 +78,7 @@ PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId) { OSAL_DestroySemaphore(initializerDesc[coreId].fifoSemHandle); dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle); + ERROR("CM_NO_MORE_MEMORY: fifo_alloc() failed in cm_COMP_INIT_Init()\n", 0, 0, 0, 0, 0, 0); return CM_NO_MORE_MEMORY; } @@ -92,6 +93,7 @@ PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId) OSAL_DestroySemaphore(initializerDesc[coreId].fifoSemHandle); fifo_free(initializerDesc[coreId].downlinkFifo); dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle); + ERROR("CM_NO_MORE_MEMORY: fifo_alloc() failed in cm_COMP_INIT_Init()\n", 0, 0, 0, 0, 0, 0); return CM_NO_MORE_MEMORY; } @@ -144,7 +146,7 @@ PUBLIC t_cm_error cm_COMP_CallService( params[INIT_COMPONENT_CMD_METHOD_INDEX] = (t_uint16)(methodAddress & 0xFFFF); params[INIT_COMPONENT_CMD_METHOD_INDEX+1] = (t_uint16)(methodAddress >> 16); - error = cm_COMP_generic(pComp->template->dspId, params, sizeof(params) / sizeof(t_uint16), serviceIndex); + error = cm_COMP_generic(pComp->Template->dspId, params, sizeof(params) / sizeof(t_uint16), serviceIndex); if (isSynchronous == TRUE && error == CM_OK) { if (OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c index 7897a237838..2a61d4a7433 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c @@ -110,16 +110,16 @@ static void cm_DestroyComponentMemory(t_component_instance *component) } } - for(i = 0; i < component->template->requireNumber; i++) + for(i = 0; i < component->Template->requireNumber; i++) { OSAL_Free(component->interfaceReferences[i]); } cm_StringRelease(component->pathname); - cm_ELF_FreeInstance(component->template->dspId, component->template->memories, component->memories); + cm_ELF_FreeInstance(component->Template->dspId, component->Template->memories, component->memories); - cm_unloadComponent(component->template); + cm_unloadComponent(component->Template); OSAL_Free(component); } @@ -130,12 +130,15 @@ static void cm_DestroyComponentMemory(t_component_instance *component) void cm_delayedDestroyComponent(t_component_instance *component) { int i; + if (osal_debug_ops.component_destroy) + osal_debug_ops.component_destroy(component); + /* * Remove component from load map here */ cm_DSPABI_RemoveLoadMap( component->domainId, - component->template->name, + component->Template->name, component->memories, component->pathname, component); @@ -146,28 +149,28 @@ void cm_delayedDestroyComponent(t_component_instance *component) { /* * disconnect interrupt handler if needed */ - for(i = 0; i < component->template->provideNumber; i++) + for(i = 0; i < component->Template->provideNumber; i++) { - if(component->template->provides[i].interruptLine) + if(component->Template->provides[i].interruptLine) { - cm_unbindInterfaceStaticInterrupt(component->template->dspId, component->template->provides[i].interruptLine); + cm_unbindInterfaceStaticInterrupt(component->Template->dspId, component->Template->provides[i].interruptLine); } } /* * Update dsp stack size if needed */ - if (component->template->minStackSize > MIN_STACK_SIZE) + if (component->Template->minStackSize > MIN_STACK_SIZE) { - if (cm_EEM_isStackUpdateNeed(component->template->dspId, component->priority, FALSE, component->template->minStackSize)) + if (cm_EEM_isStackUpdateNeed(component->Template->dspId, component->priority, FALSE, component->Template->minStackSize)) { t_uint32 newStackValue; t_uint32 maxComponentStackSize; maxComponentStackSize = cm_getMaxStackValue(component); - cm_EEM_UpdateStack(component->template->dspId, component->priority, maxComponentStackSize, &newStackValue); - if (cm_DSP_GetState(component->template->dspId)->state == MPC_STATE_BOOTED) - cm_COMP_UpdateStack(component->template->dspId, newStackValue); + cm_EEM_UpdateStack(component->Template->dspId, component->priority, maxComponentStackSize, &newStackValue); + if (cm_DSP_GetState(component->Template->dspId)->state == MPC_STATE_BOOTED) + cm_COMP_UpdateStack(component->Template->dspId, newStackValue); } } @@ -253,7 +256,7 @@ t_cm_error cm_instantiateComponent(const char* templateName, } component->interfaceReferences = (t_interface_reference**)((char*)component + sizeof(t_component_instance)); - component->template = template; + component->Template = template; /* * Update linked list @@ -300,7 +303,7 @@ t_cm_error cm_instantiateComponent(const char* templateName, component->thisAddress = 0xFFFFFFFF; component->state = STATE_NONE; - if(component->template->classe == SINGLETON) + if(component->Template->classe == SINGLETON) { // Return same handle for singleton component struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, TRUE, domainDesc[domainId].client); if(cl == NULL) @@ -450,6 +453,9 @@ t_cm_error cm_instantiateComponent(const char* templateName, else component->state = STATE_STOPPED; + if (osal_debug_ops.component_create) + osal_debug_ops.component_create(component); + *refcomponent = component; return CM_OK; } @@ -495,7 +501,7 @@ t_cm_error cm_startComponent(t_component_instance* component, t_nmf_client_id cl /* * Special code for SINGLETON handling */ - if(component->template->classe == SINGLETON) + if(component->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); if(cl != NULL) @@ -515,15 +521,15 @@ t_cm_error cm_startComponent(t_component_instance* component, t_nmf_client_id cl /* * Check that all required binding have been binded! */ - for(i = 0; i < component->template->requireNumber; i++) + for(i = 0; i < component->Template->requireNumber; i++) { - int nb = component->template->requires[i].collectionSize, j; + int nb = component->Template->requires[i].collectionSize, j; for(j = 0; j < nb; j++) { if(component->interfaceReferences[i][j].instance == NULL && - (component->template->requires[i].requireTypes & (OPTIONAL_REQUIRE | INTRINSEC_REQUIRE)) == 0) + (component->Template->requires[i].requireTypes & (OPTIONAL_REQUIRE | INTRINSEC_REQUIRE)) == 0) { - ERROR("CM_REQUIRE_INTERFACE_UNBINDED: Required interface '%s'.'%s' binded\n", component->pathname, component->template->requires[i].name, 0, 0, 0, 0); + ERROR("CM_REQUIRE_INTERFACE_UNBINDED: Required interface '%s'.'%s' binded\n", component->pathname, component->Template->requires[i].name, 0, 0, 0, 0); return CM_REQUIRE_INTERFACE_UNBINDED; } } @@ -542,12 +548,12 @@ t_cm_error cm_startComponent(t_component_instance* component, t_nmf_client_id cl { // The PRCMU seem not supporting the transition of asking HW IP on while DSP in retention // -> Thus force wake up of the MMDSP before asking the transition - if ((error = cm_EEM_ForceWakeup(component->template->dspId)) != CM_OK) + if ((error = cm_EEM_ForceWakeup(component->Template->dspId)) != CM_OK) return error; - error = cm_PWR_EnableMPC(MPC_PWR_HWIP, component->template->dspId); + error = cm_PWR_EnableMPC(MPC_PWR_HWIP, component->Template->dspId); - cm_EEM_AllowSleep(component->template->dspId); + cm_EEM_AllowSleep(component->Template->dspId); if(error != CM_OK) return error; @@ -556,16 +562,16 @@ t_cm_error cm_startComponent(t_component_instance* component, t_nmf_client_id cl /* * Call starter if available */ - if(component->template->LCCStartAddress != 0) + if(component->Template->LCCStartAddress != 0) { - if (cm_DSP_GetState(component->template->dspId)->state != MPC_STATE_BOOTED) + if (cm_DSP_GetState(component->Template->dspId)->state != MPC_STATE_BOOTED) { return CM_MPC_NOT_RESPONDING; } else if ((error = cm_COMP_CallService( - (component->priority > cm_EEM_getExecutiveEngine(component->template->dspId)->instance->priority)?NMF_START_SYNC_INDEX:NMF_START_INDEX, + (component->priority > cm_EEM_getExecutiveEngine(component->Template->dspId)->instance->priority)?NMF_START_SYNC_INDEX:NMF_START_INDEX, component, - component->template->LCCStartAddress)) != CM_OK) + component->Template->LCCStartAddress)) != CM_OK) { if (error == CM_MPC_NOT_RESPONDING) ERROR("CM_MPC_NOT_RESPONDING: can't call starter '%s'\n", component->pathname, 0, 0, 0, 0, 0); @@ -589,7 +595,7 @@ t_cm_error cm_stopComponent(t_component_instance* component, t_nmf_client_id cli /* * Special code for SINGLETON handling */ - if(component->template->classe == SINGLETON) + if(component->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); if(cl != NULL) @@ -616,7 +622,7 @@ t_cm_error cm_stopComponent(t_component_instance* component, t_nmf_client_id cli value, sizeof(value)) == CM_OK); - if (cm_DSP_GetState(component->template->dspId)->state != MPC_STATE_BOOTED) + if (cm_DSP_GetState(component->Template->dspId)->state != MPC_STATE_BOOTED) { error = CM_MPC_NOT_RESPONDING; } @@ -625,12 +631,12 @@ t_cm_error cm_stopComponent(t_component_instance* component, t_nmf_client_id cli /* * Call stopper if available */ - if(component->template->LCCStopAddress != 0) + if(component->Template->LCCStopAddress != 0) { if ((error = cm_COMP_CallService( isHwProperty ? NMF_STOP_SYNC_INDEX : NMF_STOP_INDEX, component, - component->template->LCCStopAddress)) != CM_OK) + component->Template->LCCStopAddress)) != CM_OK) { if (error == CM_MPC_NOT_RESPONDING) ERROR("CM_MPC_NOT_RESPONDING: can't call stopper '%s'\n", component->pathname, 0, 0, 0, 0, 0); @@ -643,7 +649,7 @@ t_cm_error cm_stopComponent(t_component_instance* component, t_nmf_client_id cli */ if(isHwProperty) { - cm_PWR_DisableMPC(MPC_PWR_HWIP, component->template->dspId); + cm_PWR_DisableMPC(MPC_PWR_HWIP, component->Template->dspId); } return error; @@ -654,7 +660,7 @@ t_cm_error cm_destroyInstance(t_component_instance* component, t_destroy_state f int i, j; LOG_INTERNAL(1, "\n##### Destroy %s/%x (%s) component on %s #####\n", - component->pathname, component, component->template->name, cm_getDspName(component->template->dspId), 0, 0); + component->pathname, component, component->Template->name, cm_getDspName(component->Template->dspId), 0, 0); /* * Component life cycle sanity check; do it only when destroying last reference. @@ -667,15 +673,15 @@ t_cm_error cm_destroyInstance(t_component_instance* component, t_destroy_state f // CM_ASSERT component->state == STATE_STOPPED // Check that all required binding have been unbound! - for(i = 0; i < component->template->requireNumber; i++) + for(i = 0; i < component->Template->requireNumber; i++) { - int nb = component->template->requires[i].collectionSize; + int nb = component->Template->requires[i].collectionSize; for(j = 0; j < nb; j++) { if(component->interfaceReferences[i][j].instance != NULL) { ERROR("CM_COMPONENT_NOT_UNBINDED: Required interface %s/%x.%s still binded\n", - component->pathname, component, component->template->requires[i].name, 0, 0, 0); + component->pathname, component, component->Template->requires[i].name, 0, 0, 0); return CM_COMPONENT_NOT_UNBINDED; } } @@ -694,19 +700,19 @@ t_cm_error cm_destroyInstance(t_component_instance* component, t_destroy_state f { if ((componentEntry(idx) == NULL) || (componentEntry(idx) == component)) continue; - for (i = 0; i < componentEntry(idx)->template->requireNumber; i++) + for (i = 0; i < componentEntry(idx)->Template->requireNumber; i++) { - for (j = 0; j < componentEntry(idx)->template->requires[i].collectionSize; j++) + for (j = 0; j < componentEntry(idx)->Template->requires[i].collectionSize; j++) { if(componentEntry(idx)->interfaceReferences[i][j].instance == component - && component->template->provides[componentEntry(idx)->interfaceReferences[i][j].provideIndex].interruptLine == 0) + && component->Template->provides[componentEntry(idx)->interfaceReferences[i][j].provideIndex].interruptLine == 0) { ERROR(" -> %s/%x.%s still used by %s/%x.%s\n", component->pathname, component, - component->template->provides[componentEntry(idx)->interfaceReferences[i][j].provideIndex].name, + component->Template->provides[componentEntry(idx)->interfaceReferences[i][j].provideIndex].name, componentEntry(idx)->pathname, componentEntry(idx), - componentEntry(idx)->template->requires[i].name); + componentEntry(idx)->Template->requires[i].name); } } } @@ -718,18 +724,18 @@ t_cm_error cm_destroyInstance(t_component_instance* component, t_destroy_state f // Sanity check finished, here, we will do the JOB whatever error - if (cm_DSP_GetState(component->template->dspId)->state == MPC_STATE_BOOTED) + if (cm_DSP_GetState(component->Template->dspId)->state == MPC_STATE_BOOTED) { /* * Call destroy if available */ /* Call the destructor only if we don't want to force the destruction */ - if(forceDestroy != DESTROY_WITHOUT_CHECK_CALL && component->template->LCCDestroyAddress != 0) + if(forceDestroy != DESTROY_WITHOUT_CHECK_CALL && component->Template->LCCDestroyAddress != 0) { if (cm_COMP_CallService( NMF_DESTROY_INDEX, component, - component->template->LCCDestroyAddress) != CM_OK) + component->Template->LCCDestroyAddress) != CM_OK) { ERROR("CM_MPC_NOT_RESPONDING: can't call destroy '%s'\n", component->pathname, 0, 0, 0, 0, 0); } @@ -750,7 +756,7 @@ t_cm_error cm_destroyInstanceForClient(t_component_instance* component, t_destro /* * Special code for SINGLETON handling */ - if(component->template->classe == SINGLETON) + if(component->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); int nbinstance; @@ -762,7 +768,7 @@ t_cm_error cm_destroyInstanceForClient(t_component_instance* component, t_destro if(nbinstance > 0) { LOG_INTERNAL(1, "##### Singleton : Delete handle of %s/%x (%s) component on %s [%d] provItf=%d #####\n", - component->pathname, component, component->template->name, cm_getDspName(component->template->dspId), + component->pathname, component, component->Template->name, cm_getDspName(component->Template->dspId), nbinstance, component->providedItfUsedCount); return CM_OK; } @@ -776,7 +782,7 @@ t_cm_error cm_destroyInstanceForClient(t_component_instance* component, t_destro static t_uint32 cm_getMaxStackValue(t_component_instance *pComponent) { - t_nmf_executive_engine_id executiveEngineId = cm_EEM_getExecutiveEngine(pComponent->template->dspId)->executiveEngineId; + t_nmf_executive_engine_id executiveEngineId = cm_EEM_getExecutiveEngine(pComponent->Template->dspId)->executiveEngineId; t_uint32 res = MIN_STACK_SIZE; unsigned int i; @@ -784,11 +790,11 @@ static t_uint32 cm_getMaxStackValue(t_component_instance *pComponent) { if ((componentEntry(i) != NULL) && (componentEntry(i) != pComponent) && - (pComponent->template->dspId == componentEntry(i)->template->dspId) && + (pComponent->Template->dspId == componentEntry(i)->Template->dspId) && (executiveEngineId == SYNCHRONOUS_EXECUTIVE_ENGINE || componentEntry(i)->priority == pComponent->priority)) { - if (componentEntry(i)->template->minStackSize > res) - res = componentEntry(i)->template->minStackSize; + if (componentEntry(i)->Template->minStackSize > res) + res = componentEntry(i)->Template->minStackSize; } } diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c b/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c index a4e0a01a242..3855f97ded8 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c @@ -15,7 +15,7 @@ t_cm_error cm_getComponentProperty( const char *propName, char value[MAX_PROPERTY_VALUE_LENGTH], t_uint32 valueLength){ - t_component_template* template = component->template; + t_component_template* template = component->Template; int i; for(i = 0; i < template->propertyNumber; i++) { @@ -40,11 +40,11 @@ static t_attribute* cm_getAttributeDescriptor( { int i; - for(i = 0; i < component->template->attributeNumber; i++) + for(i = 0; i < component->Template->attributeNumber; i++) { - if(cm_StringCompare(component->template->attributes[i].name, attrName, MAX_ATTRIBUTE_NAME_LENGTH) == 0) + if(cm_StringCompare(component->Template->attributes[i].name, attrName, MAX_ATTRIBUTE_NAME_LENGTH) == 0) { - return &component->template->attributes[i]; + return &component->Template->attributes[i]; } } @@ -76,7 +76,7 @@ t_cm_logical_address cm_getAttributeHostAddr( if((attribute = cm_getAttributeDescriptor(component, attrName)) == NULL) return 0x0; - // TODO JPF: component->template->attributes[i].memory.offset could be converted in byte during load + // TODO JPF: component->Template->attributes[i].memory.offset could be converted in byte during load return cm_DSP_GetHostLogicalAddress(component->memories[attribute->memory.memory->id]) + attribute->memory.offset * attribute->memory.memory->memEntSize; } @@ -96,7 +96,7 @@ t_cm_error cm_readAttribute( return CM_NO_SUCH_ATTRIBUTE; } - // TODO JPF: component->template->attributes[i].memory.offset could be converted in byte during load + // TODO JPF: component->Template->attributes[i].memory.offset could be converted in byte during load hostAddr = cm_DSP_GetHostLogicalAddress(component->memories[attribute->memory.memory->id]) + attribute->memory.offset * attribute->memory.memory->memEntSize; @@ -137,7 +137,7 @@ t_cm_error cm_writeAttribute( return CM_NO_SUCH_ATTRIBUTE; } - // TODO JPF: component->template->attributes[i].memory.offset could be converted in byte during load + // TODO JPF: component->Template->attributes[i].memory.offset could be converted in byte during load hostAddr = cm_DSP_GetHostLogicalAddress(component->memories[attribute->memory.memory->id]) + attribute->memory.offset * attribute->memory.memory->memEntSize; @@ -173,7 +173,7 @@ t_dsp_address cm_getFunction( if((error = cm_getProvidedInterface(component, interfaceName, &itfProvide)) != CM_OK) return error; - provide = &component->template->provides[itfProvide.provideIndex]; + provide = &component->Template->provides[itfProvide.provideIndex]; for(i = 0; i < provide->interface->methodNumber; i++) { @@ -232,12 +232,12 @@ PUBLIC t_cm_error cm_getProvidedInterface(const t_component_instance* server, t_interface_provide_description *itfProvide){ int i; - for(i = 0; i < server->template->provideNumber; i++) + for(i = 0; i < server->Template->provideNumber; i++) { int collectionIndex; - if(compareItfName(server->template->provides[i].name, itfName, &collectionIndex) == 0) + if(compareItfName(server->Template->provides[i].name, itfName, &collectionIndex) == 0) { - t_interface_provide *provide = &server->template->provides[i]; + t_interface_provide *provide = &server->Template->provides[i]; if(collectionIndex >= 0) { if(! (provide->provideTypes & COLLECTION_PROVIDE)) { @@ -287,10 +287,10 @@ t_cm_error cm_getRequiredInterface(const t_component_instance* client, t_interface_require_description *itfRequire){ int i; - for(i = 0; i < client->template->requireNumber; i++) { + for(i = 0; i < client->Template->requireNumber; i++) { int collectionIndex; - if(compareItfName(client->template->requires[i].name, itfName, &collectionIndex) == 0) { - t_interface_require *require = &client->template->requires[i]; + if(compareItfName(client->Template->requires[i].name, itfName, &collectionIndex) == 0) { + t_interface_require *require = &client->Template->requires[i]; if(collectionIndex >= 0) { if(! (require->requireTypes & COLLECTION_REQUIRE)) { ERROR("CM_NO_SUCH_REQUIRED_INTERFACE(%s, %s)\n", diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/loader.c b/drivers/staging/nmf-cm/cm/engine/component/src/loader.c index 762f74c4479..ad6af00f5a5 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/loader.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/loader.c @@ -15,6 +15,7 @@ void START(void); void END(char*); +#undef NHASH #define NHASH 79 //Use a prime number! #define MULT 17 @@ -107,9 +108,9 @@ t_uint32 cm_resolvSymbol( int i, j; // Search if this method is provided by EE and resolve it directly - for(i = 0; i < ee->template->provideNumber; i++) + for(i = 0; i < ee->Template->provideNumber; i++) { - t_interface_provide* provide = &ee->template->provides[i]; + t_interface_provide* provide = &ee->Template->provides[i]; for(j = 0; j < provide->interface->methodNumber; j++) { diff --git a/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration_wrapper.c b/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration_wrapper.c index 34789752b7d..bc3952e63b4 100644 --- a/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration_wrapper.c +++ b/drivers/staging/nmf-cm/cm/engine/configuration/src/configuration_wrapper.c @@ -89,20 +89,20 @@ PUBLIC void CM_ENGINE_Destroy(void) if ((instance = componentEntry(i)) == NULL) continue; clientId = domainDesc[instance->domainId].client; - LOG_INTERNAL(0, "Found a remaining component %s (%s) when destroying the CM !!!\n", instance->pathname, instance->template->name, 0, 0, 0, 0); + LOG_INTERNAL(0, "Found a remaining component %s (%s) when destroying the CM !!!\n", instance->pathname, instance->Template->name, 0, 0, 0, 0); if (/* skip EE */ - (instance->template->classe == FIRMWARE) || + (instance->Template->classe == FIRMWARE) || /* Skip all binding components */ - (cm_StringCompare(instance->template->name, "_ev.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_st.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_sk.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_tr.", 4) == 0)) + (cm_StringCompare(instance->Template->name, "_ev.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_st.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_sk.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_tr.", 4) == 0)) continue; /* * Special code for SINGLETON handling */ - if(instance->template->classe == SINGLETON) + if(instance->Template->classe == SINGLETON) { struct t_client_of_singleton* cl = instance->clientOfSingleton; @@ -126,7 +126,7 @@ PUBLIC void CM_ENGINE_Destroy(void) // Stop the component error = cm_stopComponent(instance, clientId); if (error != CM_OK && error != CM_COMPONENT_NOT_STARTED) - LOG_INTERNAL(0, "Error stopping component %s/%x (%s, error=%d, client=%u)\n", instance->pathname, instance, instance->template->name, error, clientId, 0); + LOG_INTERNAL(0, "Error stopping component %s/%x (%s, error=%d, client=%u)\n", instance->pathname, instance, instance->Template->name, error, clientId, 0); // Destroy dependencies cm_destroyRequireInterface(instance, clientId); @@ -142,16 +142,16 @@ PUBLIC void CM_ENGINE_Destroy(void) clientId = domainDesc[instance->domainId].client; if (/* skip EE */ - (instance->template->classe == FIRMWARE) || + (instance->Template->classe == FIRMWARE) || /* Skip all binding components */ - (cm_StringCompare(instance->template->name, "_ev.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_st.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_sk.", 4) == 0) || - (cm_StringCompare(instance->template->name, "_tr.", 4) == 0)) { + (cm_StringCompare(instance->Template->name, "_ev.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_st.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_sk.", 4) == 0) || + (cm_StringCompare(instance->Template->name, "_tr.", 4) == 0)) { continue; } - if(instance->template->classe == SINGLETON) + if(instance->Template->classe == SINGLETON) { clientId = instance->clientOfSingleton->clientId; } diff --git a/drivers/staging/nmf-cm/cm/engine/dsp/inc/dsp.h b/drivers/staging/nmf-cm/cm/engine/dsp/inc/dsp.h index 5cd65289ff8..439deac115f 100644 --- a/drivers/staging/nmf-cm/cm/engine/dsp/inc/dsp.h +++ b/drivers/staging/nmf-cm/cm/engine/dsp/inc/dsp.h @@ -17,7 +17,6 @@ #include #include #include -#include #include diff --git a/drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c b/drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c index de4ea3b7ba5..7646f6301de 100644 --- a/drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c +++ b/drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c @@ -528,20 +528,27 @@ PUBLIC t_cm_error cm_DSP_setStackSize(t_nmf_core_id coreId, t_uint32 newStackSiz { t_uint8 nbXramBanks; t_uint32 xramSize; + t_cm_error error; /* compute size of xram allocator */ nbXramBanks = SxA_NB_BLOCK_RAM - mpcDesc[coreId].nbYramBank; /* check first that required stack size is less then xram memory ....*/ - if (newStackSize >= nbXramBanks * 4 * ONE_KB) + if (newStackSize >= nbXramBanks * 4 * ONE_KB) { + ERROR("CM_NO_MORE_MEMORY: cm_DSP_setStackSize(), required stack size doesn't fit in XRAM.\n", 0, 0, 0, 0, 0, 0); return CM_NO_MORE_MEMORY; + } /* compute new xram allocator size */ xramSize = nbXramBanks * 4 * ONE_KB - newStackSize; /* try to resize it */ - return cm_MM_ResizeAllocator(cm_DSP_GetAllocator(coreId, INTERNAL_XRAM24), - xramSize << dspMemoryTypeId2OffsetShifter[INTERNAL_XRAM24]); + if ((error = cm_MM_ResizeAllocator(cm_DSP_GetAllocator(coreId, INTERNAL_XRAM24), + xramSize << dspMemoryTypeId2OffsetShifter[INTERNAL_XRAM24])) == CM_NO_MORE_MEMORY) { + ERROR("CM_NO_MORE_MEMORY: Couldn't resize stack in cm_DSP_setStackSize()\n", 0, 0, 0, 0, 0, 0); + } + + return error; } PUBLIC t_cm_error cm_DSP_IsNbYramBanksValid(t_nmf_core_id coreId, t_uint8 nbYramBanks) diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c index 2efe6edbf69..84f841ef443 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c @@ -103,7 +103,7 @@ static t_interface_description* getInterfaceDescription(t_tmp_elfdescription *el } // Create a new interface if not exists - itf = (t_interface_description*)OSAL_Alloc_Zero(sizeof(t_interface_description) + sizeof(char*) * (elfitf->methodNumber /*- 1*/)); + itf = (t_interface_description*)OSAL_Alloc_Zero(sizeof(t_interface_description) + sizeof(t_dup_char) * (elfitf->methodNumber - 1)); if(itf == NULL) goto out_itf_type; itf->referenceCounter = 1; @@ -343,7 +343,7 @@ t_cm_error cm_ELF_CheckFile( elfhandle->requires[i].requireTypes, 0, 0, 0); CM_ASSERT(elfhandle->requires[i].collectionSize != 0); - ref += sizeof(t_elf_required_interface); + ref = (char*)&require->indexes[0]; if((elfhandle->requires[i].requireTypes & VIRTUAL_REQUIRE) == 0 && (elfhandle->requires[i].requireTypes & STATIC_REQUIRE) == 0) @@ -420,7 +420,7 @@ t_cm_error cm_ELF_CheckFile( 0,0, 0, 0); CM_ASSERT(elfhandle->provides[i].collectionSize != 0); - ref += sizeof(t_elf_required_interface); + ref = (char*)&provide->methodSymbols[0]; { t_uint32 *methodSymbols = (t_uint32*)ref; diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c index 8826e727970..26e66c4a640 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c @@ -28,6 +28,7 @@ static struct LoadMapHdr *headerAddresses[NB_CORE_IDS] = {0, }; static t_uint32 headerOffsets[NB_CORE_IDS] = {0, }; static t_uint32 entryNumber[NB_CORE_IDS] = {0, }; +#undef myoffsetof #define myoffsetof(TYPE, MEMBER) ((unsigned int) &((TYPE *)0)->MEMBER) t_cm_error cm_DSPABI_AddLoadMap( @@ -45,8 +46,10 @@ t_cm_error cm_DSPABI_AddLoadMap( { headerHandle[coreId] = cm_DM_Alloc(domainId, SDRAM_EXT16, sizeof(struct LoadMapHdr)/2, CM_MM_ALIGN_2WORDS, TRUE); - if (headerHandle[coreId] == INVALID_MEMORY_HANDLE) + if (headerHandle[coreId] == INVALID_MEMORY_HANDLE) { + ERROR("CM_NO_MORE_MEMORY: Unable to allocate loadmap in cm_DSPABI_AddLoadMap()\n", 0, 0, 0, 0, 0, 0); return CM_NO_MORE_MEMORY; + } headerAddresses[coreId] = (struct LoadMapHdr*)cm_DSP_GetHostLogicalAddress(headerHandle[coreId]); @@ -87,8 +90,10 @@ t_cm_error cm_DSPABI_AddLoadMap( handle = cm_DM_Alloc(domainId, SDRAM_EXT16, sizeof(struct LoadMapItem)/2 + (1 + fnlenaligned/2) + (1 + lnlenaligned/2), CM_MM_ALIGN_2WORDS, TRUE); - if (handle == INVALID_MEMORY_HANDLE) + if (handle == INVALID_MEMORY_HANDLE) { + ERROR("CM_NO_MORE_MEMORY: Unable to allocate loadmap entry in cm_DSPABI_AddLoadMap\n", 0, 0, 0, 0, 0, 0); return CM_NO_MORE_MEMORY; + } pItem = (struct LoadMapItem*)cm_DSP_GetHostLogicalAddress(handle); cm_DSP_GetDspAddress(handle, &dspentry); @@ -126,13 +131,13 @@ t_cm_error cm_DSPABI_AddLoadMap( "Previou (first) component name %s<%s>\n", curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, curItem->pARMThis ? (char*)(((t_component_instance *)&curItem->pARMThis)->pathname) : "", - curItem->pARMThis ? (char*)(((t_component_instance *)&curItem->pARMThis)->template->name) : "", 0, 0); + curItem->pARMThis ? (char*)(((t_component_instance *)&curItem->pARMThis)->Template->name) : "", 0, 0); else ERROR("AddLoadMap: Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n" "Previous valid component name %s<%s>", curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, prevItem->pARMThis ? (char*)(((t_component_instance *)&prevItem->pARMThis)->pathname) : "", - prevItem->pARMThis ? (char*)(((t_component_instance *)&prevItem->pARMThis)->template->name) : "", 0, 0); + prevItem->pARMThis ? (char*)(((t_component_instance *)&prevItem->pARMThis)->Template->name) : "", 0, 0); return CM_INVALID_DATA; } curItemDspAdress = (t_uint32)curItem->pNextItem; @@ -388,14 +393,14 @@ t_cm_error cm_DSPABI_CheckLoadMap_nolock(t_nmf_core_id coreId) count, curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, (char*)(((t_component_instance *)&curItem->pARMThis)->pathname), - (char*)(((t_component_instance *)&curItem->pARMThis)->template->name), 0); + (char*)(((t_component_instance *)&curItem->pARMThis)->Template->name), 0); else ERROR("CheckLoadMap: Memory corruption in MMDSP (count=%d): at data DSP address=%x or ARM address=%x\n" "Previous valid component name %s<%s>", count, curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, (char*)(((t_component_instance *)&prevItem->pARMThis)->pathname), - (char*)(((t_component_instance *)&prevItem->pARMThis)->template->name), 0); + (char*)(((t_component_instance *)&prevItem->pARMThis)->Template->name), 0); dump--; return CM_INVALID_COMPONENT_HANDLE; } diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h index 3f995982088..aacffd15a17 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h @@ -20,6 +20,10 @@ typedef struct { t_uint32 traceState; t_uint32 printLevel; t_uint32 nbOfForceWakeup; + struct { + t_memory_handle handle; + t_cm_logical_address addr; + } panicArea; } t_ee_state; //TODO, juraj, this should be done more properly, like accessor method, instead making this global variable.. diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c index 14889ec6e4d..f2c833ff7dc 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c @@ -27,6 +27,8 @@ t_ee_state eeState[NB_CORE_IDS]; /****************************************************************** Functions ****************************************************************************/ +static t_cm_error cm_EEM_allocPanicArea(t_nmf_core_id coreId, t_cm_domain_id domainId); +static void cm_EEM_freePanicArea(t_nmf_core_id coreId); PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetExecutiveEngineHandle( t_cm_domain_id domainId, @@ -109,9 +111,19 @@ PUBLIC t_cm_error cm_EEM_Init( return error; } + /* allocate sdram memory for panic area */ + error = cm_EEM_allocPanicArea(coreId, cm_DSP_GetState(coreId)->domainEE); + if (error != CM_OK) { + cm_delayedDestroyComponent(eeState[coreId].instance); + eeState[coreId].instance = (t_component_instance *)0; + cm_DSP_Shutdown(coreId); + return error; + } + /* allocate sdram memory to share perfmeters data */ error = cm_PFM_allocatePerfmeterDataMemory(coreId, cm_DSP_GetState(coreId)->domainEE); if (error != CM_OK) { + cm_EEM_freePanicArea(coreId); cm_delayedDestroyComponent(eeState[coreId].instance); eeState[coreId].instance = (t_component_instance *)0; cm_DSP_Shutdown(coreId); @@ -168,7 +180,7 @@ PUBLIC void cm_EEM_Close(t_nmf_core_id coreId) cm_delayedDestroyComponent(eeState[coreId].instance); eeState[coreId].instance = (t_component_instance *)0; cm_PFM_deallocatePerfmeterDataMemory(coreId); - + cm_EEM_freePanicArea(coreId); cm_DSP_Shutdown(coreId); } @@ -323,8 +335,13 @@ t_cm_error cm_EEM_ForceWakeup(t_nmf_core_id coreId) else if ((error = cm_COMP_ULPForceWakeup(coreId)) != CM_OK) { if (error == CM_MPC_NOT_RESPONDING) { - ERROR("CM_MPC_NOT_RESPONDING: DSP %s can't be wakeup'ed\n", cm_getDspName(coreId), 0, 0, 0, 0, 0); - cm_DSP_SetStatePanic(coreId); + if(cm_DSP_GetState(coreId)->state == MPC_STATE_PANIC) + /* Don't print error which has been done by Panic handling */; + else + { + ERROR("CM_MPC_NOT_RESPONDING: DSP %s can't be wakeup'ed\n", cm_getDspName(coreId), 0, 0, 0, 0, 0); + cm_DSP_SetStatePanic(coreId); + } } return error; } @@ -347,3 +364,29 @@ void cm_EEM_AllowSleep(t_nmf_core_id coreId) } } } + +/* internal api */ +t_cm_error cm_EEM_allocPanicArea(t_nmf_core_id coreId, t_cm_domain_id domainId) +{ + t_cm_error error = CM_OK; + + eeState[coreId].panicArea.handle = cm_DM_Alloc(cm_DSP_GetState(coreId)->domainEE, SDRAM_EXT24, 45 /* 42 registers, pc, 2 magic words */,CM_MM_ALIGN_WORD, TRUE); + if (eeState[coreId].panicArea.handle == INVALID_MEMORY_HANDLE) + error = CM_NO_MORE_MEMORY; + else { + t_uint32 mmdspAddr; + + eeState[coreId].panicArea.addr = cm_DSP_GetHostLogicalAddress(eeState[coreId].panicArea.handle); + cm_DSP_GetDspAddress(eeState[coreId].panicArea.handle, &mmdspAddr); + + cm_writeAttribute(eeState[coreId].instance, "rtos/commonpart/panicDataAddr", mmdspAddr); + } + + return error; +} + +void cm_EEM_freePanicArea(t_nmf_core_id coreId) +{ + eeState[coreId].panicArea.addr = 0; + cm_DM_Free(eeState[coreId].panicArea.handle, TRUE); +} diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h index bf75915c259..07caee2d8c1 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h @@ -52,6 +52,7 @@ typedef struct { t_cm_domain_id parent_ref; //parent domain reference } child; } scratch; + void *dbgCooky; //pointer to OS internal data } t_cm_domain_desc; #ifdef DEBUG diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h index e639c94cb46..f556c6f7056 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h @@ -76,8 +76,11 @@ typedef t_cm_chunk* t_memory_handle; //TODO, juraj, add memType to alloc struct ? typedef struct cm_allocator_desc { const char *pAllocName; /* Name of the allocator */ - t_uint32 size; /* Size of the allocator */ + t_uint32 maxSize; /* Max size of the allocator -> Potentially increase/decrease by stack management */ + t_uint32 sbrkSize; /* Current size of allocator */ + t_uint32 offset; /* Offset of the allocator */ t_cm_chunk *chunks; /* Array of chunk */ + t_cm_chunk *lastChunk; /* Null terminated last chunk of previous array declaration */ t_cm_chunk *free_mem_chunks[BINS]; /* List of free memory */ struct cm_allocator_desc* next; /* List of allocator */ } t_cm_allocator_desc; @@ -158,12 +161,11 @@ PUBLIC t_memory_handle cm_MM_Alloc( * * \ingroup MEMORY_INTERNAL */ -PUBLIC t_memory_handle cm_MM_Realloc( +PUBLIC t_cm_error cm_MM_Realloc( t_cm_allocator_desc* alloc, const t_cm_size size, const t_uint32 offset, - const t_cm_memory_alignment memAlignment, - const t_memory_handle handle); + t_memory_handle *handle); /*! * \brief Frees the allocated chunk * diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator_utils.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator_utils.h index ce99e4d7a94..0a7c901187b 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator_utils.h +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator_utils.h @@ -20,14 +20,13 @@ typedef enum { PUBLIC void updateFreeList(t_cm_allocator_desc* alloc, t_cm_chunk* chunk); -PUBLIC void linkChunk(t_cm_chunk* prev,t_cm_chunk* add); +PUBLIC void linkChunk(t_cm_allocator_desc* alloc, t_cm_chunk* prev,t_cm_chunk* add); PUBLIC void unlinkChunk(t_cm_allocator_desc* alloc,t_cm_chunk* current); PUBLIC void unlinkFreeMem(t_cm_allocator_desc* alloc,t_cm_chunk* current); PUBLIC void linkFreeMemBefore(t_cm_chunk* add, t_cm_chunk* next); PUBLIC void linkFreeMemAfter(t_cm_chunk* prev,t_cm_chunk* add); -PUBLIC void mergeChunk(t_cm_allocator_desc* alloc,t_cm_chunk *c,t_cm_chunk *destroy); PUBLIC t_cm_chunk* splitChunk(t_cm_allocator_desc* alloc, t_cm_chunk *chunk, t_uint32 offset, t_mem_split_position position); #endif /*REMOTE_ALLOCATOR_UTILS_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/domain.c b/drivers/staging/nmf-cm/cm/engine/memory/src/domain.c index 61cb25b39ec..8524183ce19 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/src/domain.c +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/domain.c @@ -13,6 +13,7 @@ #include #include #include +#include /* * domain_memory structure is all we need @@ -42,6 +43,7 @@ static void cm_DM_DomainError(const t_cm_domain_id parentId, const t_nmf_client_ domainDesc.scratch.parent.handle = 0; \ domainDesc.scratch.child.alloc = 0; \ domainDesc.scratch.child.parent_ref = 0; \ + domainDesc.dbgCooky = NULL; \ } while (0) #define FIND_DOMAIN_ID(domainId) \ @@ -204,6 +206,9 @@ PUBLIC t_cm_error cm_DM_CreateDomain(const t_nmf_client_id client, const t_cm_do domainDesc[domainId].client = client; domainDesc[domainId].domain = *domain; + if (osal_debug_ops.domain_create) + osal_debug_ops.domain_create(domainId); + *handle = domainId; return CM_OK; @@ -280,21 +285,15 @@ PUBLIC t_cm_error cm_DM_CreateDomainScratch(const t_nmf_client_id client, const if ((oldMin > scratchMin) || (oldMax < scratchMax)) { t_uint32 newMin = (oldMin > scratchMin)?scratchMin:oldMin; t_uint32 newMax = (oldMax < scratchMax)?scratchMax:oldMax; - t_uint16 userData; - /* save user data lost during realloc, user data do not change */ - cm_MM_GetMemoryHandleUserData(domainDesc[parentId].scratch.parent.handle, &userData, 0); - memhandle = cm_MM_Realloc(cm_DM_getAllocator(parentId, ESRAM_EXT16), newMax - newMin, newMin, - CM_MM_MPC_ALIGN_NONE, domainDesc[parentId].scratch.parent.handle); - if (memhandle == 0) { + if(cm_MM_Realloc(cm_DM_getAllocator(parentId, ESRAM_EXT16), newMax - newMin, newMin, + &domainDesc[parentId].scratch.parent.handle) != CM_OK) + { /* failed to extend the zone */ cm_DM_DestroyDomain(*handle); cm_DM_DomainError(parentId, client); return CM_NO_MORE_MEMORY; } - - cm_MM_SetMemoryHandleUserData(memhandle, userData); - domainDesc[parentId].scratch.parent.handle = memhandle; } } @@ -382,7 +381,6 @@ PUBLIC t_cm_error cm_DM_DestroyDomain(t_cm_domain_id handle) t_uint32 oldMax = 0x0; t_uint32 scratchMin = domainDesc[handle].domain.esramData.offset; t_uint32 scratchMax = domainDesc[handle].domain.esramData.offset + domainDesc[handle].domain.esramData.size; - t_memory_handle memhandle; /* compute the remaining reserved zone size */ for(i = 0; i < MAX_USER_DOMAIN_NB; i++) { @@ -400,20 +398,15 @@ PUBLIC t_cm_error cm_DM_DestroyDomain(t_cm_domain_id handle) /* resize the scratch zone */ if ((oldMin > scratchMin) || (oldMax < scratchMax)) { - t_uint16 userData; - - /* save user data lost during realloc, user data do not change */ - cm_MM_GetMemoryHandleUserData(domainDesc[parentId].scratch.parent.handle, &userData, 0); - memhandle = cm_MM_Realloc(cm_DM_getAllocator(parentId, ESRAM_EXT16), oldMax - oldMin, oldMin, - CM_MM_MPC_ALIGN_NONE, domainDesc[parentId].scratch.parent.handle); - CM_ASSERT(memhandle); //the realloc shouldn't fail.. - - cm_MM_SetMemoryHandleUserData(memhandle, userData); - domainDesc[parentId].scratch.parent.handle = memhandle; + CM_ASSERT(cm_MM_Realloc(cm_DM_getAllocator(parentId, ESRAM_EXT16), oldMax - oldMin, oldMin, + &domainDesc[parentId].scratch.parent.handle) == CM_OK); //the realloc shouldn't fail.. } } } + if (osal_debug_ops.domain_destroy) + osal_debug_ops.domain_destroy(handle); + //reset the domain desc INIT_DOMAIN_STRUCT(domainDesc[handle]); @@ -482,6 +475,10 @@ PUBLIC t_memory_handle cm_DM_Alloc(t_cm_domain_id domainId, t_dsp_memory_type_id cm_DSP_GetState(coreId)->allocator[memType]->baseAddress.physical + cm_MM_GetOffset(handle), cm_MM_GetSize(handle)); } + } else { + LOG_INTERNAL(0, "CM_NO_MORE_MEMORY domainId: %d, memType %d, wordSize %d, alignement %d\n", + domainId, memType, wordSize, memAlignment, 0, 0); + cm_MM_DumpMemory(alloc, offset, offset + size); } return handle; diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c b/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c index f7d47be924d..37bea690e48 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/memory_wrapper.c @@ -102,6 +102,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_AllocMpcMemory( if(*pHandle == (t_cm_memory_handle)INVALID_MEMORY_HANDLE) { OSAL_UNLOCK_API(); + ERROR("CM_NO_MORE_MEMORY: CM_AllocMpcMemory() failed\n", 0, 0, 0, 0, 0, 0); return CM_NO_MORE_MEMORY; } diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/migration.c b/drivers/staging/nmf-cm/cm/engine/memory/src/migration.c index 35813a56bf2..d68898d830e 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/src/migration.c +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/migration.c @@ -79,6 +79,7 @@ static t_cm_error _cm_migration_initSegment( handle = cm_DM_Alloc(dst, ESRAM_EXT16, size >> 1, CM_MM_ALIGN_AHB_BURST, TRUE); //note: byte to half-word conversion if (handle == 0) { + ERROR("CM_NO_MORE_MEMORY: Unable to init segment for migration\n", 0, 0, 0, 0, 0, 0); return CM_NO_MORE_MEMORY; } diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c b/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c index 3df552aca4d..ec23e28917c 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c @@ -18,7 +18,6 @@ #include #include -static t_cm_chunk* cm_MM_RA_getLastChunk(t_cm_allocator_desc* alloc); static void cm_MM_RA_checkAllocator(t_cm_allocator_desc* alloc); //static void cm_MM_RA_checkAlloc(t_cm_allocator_desc* alloc, t_uint32 size, t_uint32 align, t_uint32 min, t_uint32 max); @@ -56,18 +55,12 @@ PUBLIC t_cm_allocator_desc* cm_MM_CreateAllocator(t_cm_size size, t_uint32 offse alloc->next = ListOfAllocators; ListOfAllocators = alloc; - /* Create first chunk */ - alloc->chunks = allocChunk(); - /* assign name */ alloc->pAllocName = name; - alloc->chunks->size = size; - alloc->chunks->offset = offset; - alloc->chunks->alloc = alloc; - alloc->free_mem_chunks[bin_index(alloc->chunks->size)] = alloc->chunks; - - alloc->size = size; + alloc->maxSize = size; + alloc->sbrkSize = 0; + alloc->offset = offset; //TODO, juraj, alloc impacts trace format cm_TRC_traceMemAlloc(TRACE_ALLOCATOR_COMMAND_CREATE, 0, size, name); @@ -111,65 +104,17 @@ PUBLIC t_cm_error cm_MM_DeleteAllocator(t_cm_allocator_desc *alloc) PUBLIC t_cm_error cm_MM_ResizeAllocator(t_cm_allocator_desc *alloc, t_cm_size size) { - t_cm_error error; - /* sanity check */ if (size == 0) return CM_INVALID_PARAMETER; - if((error = fillChunkPool()) != CM_OK) - return error; - - if (size > alloc->size) { - /* ok, increase allocator */ - t_uint32 deltaSize = size - alloc->size; - t_cm_chunk *last = cm_MM_RA_getLastChunk(alloc); - - if (last->status == MEM_FREE) { - /* last chunk is a free one, just increase size */ - unlinkFreeMem(alloc, last); - last->size += deltaSize; - alloc->size += deltaSize; - /* now list of free chunk is potentially no more ordered */ - updateFreeList(alloc, last); - } else { - /* last chunk is a used one, add new free chunk */ - last->size += deltaSize; - splitChunk(alloc, last, last->offset + deltaSize, FREE_CHUNK_AFTER); - alloc->size += deltaSize; - } - } else { - /* reduce allocator */ - t_uint32 deltaSize = alloc->size - size; - t_cm_chunk *last = cm_MM_RA_getLastChunk(alloc); - - /* check if resize is possible */ - if (last->status == MEM_USED) - return CM_NO_MORE_MEMORY; - if (last->size < deltaSize) - return CM_NO_MORE_MEMORY; - - /* ok, rezise can be performed */ - if (last->size == deltaSize) { - t_cm_chunk *prev = last->prev; - - /* remove last free chunk */ - mergeChunk(alloc, prev, last); - prev->size -= deltaSize; - } else { - unlinkFreeMem(alloc, last); - /* reduce size of last free chunk */ - last->size -= deltaSize; - /* now list of free chunk is potentially no more ordered */ - updateFreeList(alloc, last); - } - } + if(alloc->sbrkSize > size) + return CM_NO_MORE_MEMORY; - alloc->size = size; + alloc->maxSize = size; - if (cmIntensiveCheckState) { + if (cmIntensiveCheckState) cm_MM_RA_checkAllocator(alloc); - } return CM_OK; } @@ -251,13 +196,40 @@ PUBLIC t_memory_handle cm_MM_Alloc( } } + // Try to increase sbrkSize through maxSize + aligned_offset = ALIGN_VALUE(MAX((alloc->offset + alloc->sbrkSize), seg_offset), (memAlignment + 1)); + + aligned_end = aligned_offset + size; + + if ((aligned_end <= seg_end) + && aligned_end <= (alloc->offset + alloc->maxSize) + && aligned_offset >= seg_offset + && aligned_offset >= (alloc->offset + alloc->sbrkSize)) + { + /* If that fit requirement, create a new free chunk at the end of current allocator */ + chunk = allocChunk(); + + /* Update chunk size */ + chunk->offset = alloc->offset + alloc->sbrkSize; // offset start at end of current allocator + chunk->size = aligned_end - chunk->offset; + chunk->alloc = alloc; + + /* Chain it with latest chunk */ + linkChunk(alloc, alloc->lastChunk, chunk); + + /* Increase sbrkSize to end of this new chunk */ + alloc->sbrkSize += chunk->size; + + goto foundNew; + } + return INVALID_MEMORY_HANDLE; found: - /* Remove chunk from free list */ unlinkFreeMem(alloc, chunk); +foundNew: //create an empty chunk before the allocated one if (chunk->offset < aligned_offset) { chunk = splitChunk(alloc, chunk, aligned_offset, FREE_CHUNK_BEFORE); @@ -279,21 +251,45 @@ found: cm_MM_RA_checkAllocator(alloc); } - chunk->alloc = alloc; return (t_memory_handle) chunk; } //caution - if successfull, the chunk offset will be aligned with seg_offset //caution++ the offset of the allocated chunk changes implicitly -PUBLIC t_memory_handle cm_MM_Realloc( +PUBLIC t_cm_error cm_MM_Realloc( t_cm_allocator_desc* alloc, const t_cm_size size, const t_uint32 offset, - const t_cm_memory_alignment memAlignment, - const t_memory_handle handle) + t_memory_handle *handle) { - t_cm_chunk *chunk = (t_cm_chunk*)handle; + t_cm_chunk *chunk = (t_cm_chunk*)*handle; + t_uint32 oldOffset = chunk->offset; + t_uint32 oldSize = chunk->size; + t_uint32 oldDomainId = chunk->domainId; + t_uint16 userData = chunk->userData; + + cm_MM_Free(alloc, *handle); + + *handle = cm_MM_Alloc(alloc, size, CM_MM_ALIGN_NONE, offset, size, oldDomainId); + + if(*handle == INVALID_MEMORY_HANDLE) + { + *handle = cm_MM_Alloc(alloc, oldSize, CM_MM_ALIGN_NONE, oldOffset, oldSize, oldDomainId); + + CM_ASSERT(*handle != INVALID_MEMORY_HANDLE); + + chunk = (t_cm_chunk*)*handle; + chunk->userData = userData; + return CM_NO_MORE_MEMORY; + } + + chunk = (t_cm_chunk*)*handle; + chunk->userData = userData; + + return CM_OK; + +#if 0 /* check reallocation is related to this chunk! */ CM_ASSERT(chunk->offset <= (offset + size)); CM_ASSERT(offset <= (chunk->offset + chunk->size)); @@ -311,12 +307,20 @@ PUBLIC t_memory_handle cm_MM_Realloc( } } - /* check if extend high, note as above */ + /* check if extend high, extend sbrk if necessary */ if ( (offset + size) > (chunk->offset + chunk->size)) { - if ((chunk->next == 0) - ||(chunk->next->status != MEM_FREE) - ||( (chunk->next->offset + chunk->next->size) < (offset + size))) { - return INVALID_MEMORY_HANDLE; + if(chunk->next == 0) + { + // check if allocator can be extended to maxSize + if((offset + size) > (alloc->offset + alloc->maxSize)) + return INVALID_MEMORY_HANDLE; + } + else + { + if ((chunk->next->status != MEM_FREE) + ||( (chunk->next->offset + chunk->next->size) < (offset + size))) { + return INVALID_MEMORY_HANDLE; + } } } @@ -324,90 +328,63 @@ PUBLIC t_memory_handle cm_MM_Realloc( return INVALID_MEMORY_HANDLE; -#if 0 - /* extend low - * all conditions should have been checked - * this must not fail - */ - if (offset < chunk->offset) { - t_cm_chunk *tmp = splitChunk(alloc, chunk->prev, offset, FREE_CHUNK_BEFORE); //tmp = chunk->prev - CM_ASSERT(tmp); - tmp->status = MEM_USED; - tmp->prev->status = MEM_FREE; - mergeChunk(alloc, tmp, chunk); - if ((tmp->prev->prev != 0) - && (tmp->prev->prev->status == MEM_FREE)) { - mergeChunk(alloc, tmp->prev->prev, tmp->prev); - } - chunk = tmp; - } - - /* extend high */ - if ( (offset + size) > (chunk->offset + chunk->size)) { - t_cm_chunk *tmp = splitChunk(alloc, chunk->next, offset + size, FREE_CHUNK_AFTER); //tmp = chunk->next->next - CM_ASSERT(tmp); - tmp->status = MEM_USED; - mergeChunk(alloc, chunk, tmp); - if ((tmp->next->next != 0) - && (tmp->next->next->status == MEM_FREE)) { - mergeChunk(alloc, tmp->next, tmp->next->next); - } - } - - /* reduce top */ - if ((offset + size) < (chunk->offset + chunk->size)) { - t_cm_chunk *tmp = splitChunk(alloc, chunk, offset + size, FREE_CHUNK_AFTER); //tmp = chunk, chunk = result - CM_ASSERT(tmp); - tmp->status = MEM_USED; - tmp->next->status = MEM_FREE; - if ((tmp->next->next != 0) - && (tmp->next->next->status == MEM_FREE)) { - mergeChunk(alloc, tmp->next, tmp->next->next); - } - } - - /* reduce bottom */ - if (offset > chunk->offset) { - t_cm_chunk *tmp = splitChunk(alloc, chunk, offset, FREE_CHUNK_BEFORE); //tmp->next = chunk, tmp = result - CM_ASSERT(tmp); - tmp->status = MEM_USED; - tmp->prev->status = MEM_FREE; - if ((tmp->prev->prev != 0) - &&(tmp->prev->prev->status == MEM_FREE)) { - mergeChunk(alloc, tmp->prev->prev, tmp->prev); - } - chunk = tmp; - } -#else /* extend low * all conditions should have been checked * this must not fail */ if (offset < chunk->offset) { t_uint32 delta = chunk->prev->offset + chunk->prev->size - offset; - CM_ASSERT(chunk->prev->status == MEM_FREE); //TODO, juraj, already checked - unlinkFreeMem(alloc, chunk->prev); - chunk->prev->size -= delta; + t_cm_chunk *prev = chunk->prev; + chunk->offset -= delta; chunk->size += delta; - updateFreeList(alloc, chunk->prev); + + CM_ASSERT(prev->status == MEM_FREE); //TODO, juraj, already checked + unlinkFreeMem(alloc, prev); + prev->size -= delta; + if(prev->size == 0) + { + unlinkChunk(alloc, prev); + freeChunk(prev); + } else { + updateFreeList(alloc, prev); + } } /* extend high */ if ( (offset + size) > (chunk->offset + chunk->size)) { t_uint32 delta = size - chunk->size; - CM_ASSERT(chunk->next->status == MEM_FREE); //TODO, juraj, already checked - unlinkFreeMem(alloc, chunk->next); + t_cm_chunk *next = chunk->next; + chunk->size += delta; - chunk->next->offset += delta; - chunk->next->size -= delta; - updateFreeList(alloc, chunk->next); + + if(next == 0) + { + alloc->sbrkSize += delta; + } else { + CM_ASSERT(next->status == MEM_FREE); + unlinkFreeMem(alloc, next); + next->offset += delta; + next->size -= delta; + if(next->size == 0) + { + unlinkChunk(alloc, next); + freeChunk(next); + } else { + updateFreeList(alloc, next); + } + } } /* reduce top */ if ((offset + size) < (chunk->offset + chunk->size)) { - if (chunk->next->status == MEM_FREE) { - t_uint32 delta = chunk->size - size; + t_uint32 delta = chunk->size - size; + + if(chunk->next == 0) { + alloc->sbrkSize -= delta; + chunk->size -= delta; + + } else if (chunk->next->status == MEM_FREE) { unlinkFreeMem(alloc, chunk->next); chunk->size -= delta; chunk->next->offset -= delta; @@ -435,10 +412,11 @@ PUBLIC t_memory_handle cm_MM_Realloc( tmp->prev->status = MEM_FREE; } } -#endif + cm_MM_RA_checkAllocator(alloc); return (t_memory_handle)chunk; +#endif } PUBLIC void cm_MM_Free(t_cm_allocator_desc* alloc, t_memory_handle memHandle) @@ -453,19 +431,58 @@ PUBLIC void cm_MM_Free(t_cm_allocator_desc* alloc, t_memory_handle memHandle) chunk->status = MEM_FREE; chunk->domainId = 0x0; + // Invariant: Current chunk is free but not in free list + /* Check if the previous chunk is free */ - if((chunk->prev != 0) && (chunk->prev->status == MEM_FREE)) { - chunk = chunk->prev; //chunk, ie. chunk->next, will be freed - mergeChunk(alloc, chunk, chunk->next); + if((chunk->prev != 0) && (chunk->prev->status == MEM_FREE)) + { + t_cm_chunk* prev = chunk->prev; + + // Remove chunk to be freed from memory list + unlinkChunk(alloc, chunk); + + // Remove previous from free list + unlinkFreeMem(alloc, prev); + + // Update previous size + prev->size += chunk->size; + + freeChunk(chunk); + + chunk = prev; } /* Check if the next chunk is free */ - if((chunk->next != 0) && (chunk->next->status == MEM_FREE)) { - mergeChunk(alloc, chunk, chunk->next); + if((chunk->next != 0) && (chunk->next->status == MEM_FREE)) + { + t_cm_chunk* next = chunk->next; + + // Remove next from memory list + unlinkChunk(alloc, next); + + // Remove next from free list + unlinkFreeMem(alloc, next); + + // Update previous size + chunk->size += next->size; + + freeChunk(next); } - unlinkFreeMem(alloc, chunk); - updateFreeList(alloc, chunk); + if(chunk->next == 0) + { + // If we are the last one, decrease sbrkSize + alloc->sbrkSize -= chunk->size; + + unlinkChunk(alloc, chunk); + freeChunk(chunk); + + } + else + { + // Add it in free list + updateFreeList(alloc, chunk); + } if (cmIntensiveCheckState) { cm_MM_RA_checkAllocator(alloc); @@ -475,6 +492,7 @@ PUBLIC void cm_MM_Free(t_cm_allocator_desc* alloc, t_memory_handle memHandle) PUBLIC t_cm_error cm_MM_GetAllocatorStatus(t_cm_allocator_desc* alloc, t_uint32 offset, t_uint32 size, t_cm_allocator_status *pStatus) { t_cm_chunk* chunk = alloc->chunks; + t_uint32 sbrkFree = alloc->maxSize - alloc->sbrkSize; t_uint8 min_free_size_updated = FALSE; /* Init status */ @@ -484,14 +502,13 @@ PUBLIC t_cm_error cm_MM_GetAllocatorStatus(t_cm_allocator_desc* alloc, t_uint32 pStatus->global.minimum_free_size = 0xFFFFFFFF; pStatus->global.accumulate_free_memory = 0; pStatus->global.accumulate_used_memory = 0; - pStatus->global.size = alloc->size; + pStatus->global.size = alloc->maxSize; pStatus->domain.maximum_free_size = 0; pStatus->domain.minimum_free_size = 0xFFFFFFFF; pStatus->domain.accumulate_free_memory = 0; pStatus->domain.accumulate_used_memory = 0; pStatus->domain.size= size; - //TODO, juraj, get allocator status for a domain /* Parse all chunks */ while(chunk != 0) { @@ -521,6 +538,17 @@ PUBLIC t_cm_error cm_MM_GetAllocatorStatus(t_cm_allocator_desc* alloc, t_uint32 chunk = chunk->next; } + /* Accumulate free space between sbrkSize and maxSize */ + pStatus->global.accumulate_free_memory += sbrkFree; + if (sbrkFree > 0) + pStatus->global.free_block_number++; + if (pStatus->global.maximum_free_size < sbrkFree) + pStatus->global.maximum_free_size = sbrkFree; + if (pStatus->global.minimum_free_size > sbrkFree) { + pStatus->global.minimum_free_size = sbrkFree; + min_free_size_updated = TRUE; + } + /* Put max free size to min free size */ if (min_free_size_updated == FALSE) { pStatus->global.minimum_free_size = pStatus->global.maximum_free_size; @@ -542,7 +570,7 @@ PUBLIC t_uint32 cm_MM_GetSize(t_memory_handle memHandle) PUBLIC t_uint32 cm_MM_GetAllocatorSize(t_cm_allocator_desc* alloc) { - return alloc->size; + return alloc->maxSize; } PUBLIC void cm_MM_SetMemoryHandleUserData(t_memory_handle memHandle, t_uint16 userData) @@ -565,24 +593,29 @@ PUBLIC void cm_MM_GetMemoryHandleUserData(t_memory_handle memHandle, t_uint16 *p static void cm_MM_RA_checkAllocator(t_cm_allocator_desc* alloc) { t_cm_chunk *chunk = alloc->chunks; - t_cm_chunk *first = chunk; - t_cm_chunk *last = chunk; t_uint32 size = 0; int i; + CM_ASSERT(alloc->sbrkSize <= alloc->maxSize); + while(chunk != 0) { + if(chunk == alloc->chunks) + CM_ASSERT(chunk->prev == 0); + if(chunk == alloc->lastChunk) + CM_ASSERT(chunk->next == 0); + CM_ASSERT(chunk->alloc == alloc); if (chunk->next != 0) { CM_ASSERT(!((chunk->status == MEM_FREE) && (chunk->next->status == MEM_FREE))); //two free adjacent blocks CM_ASSERT(chunk->offset < chunk->next->offset); //offsets reverted - last = chunk->next; + CM_ASSERT(chunk->offset + chunk->size == chunk->next->offset); // Not hole in allocator } size += chunk->size; chunk = chunk->next; } - CM_ASSERT(size == alloc->size); + CM_ASSERT(size == alloc->sbrkSize); for(i = 0; i < BINS; i++) { @@ -591,73 +624,11 @@ static void cm_MM_RA_checkAllocator(t_cm_allocator_desc* alloc) if (chunk->next_free_mem != 0) { CM_ASSERT(chunk->size <= chunk->next_free_mem->size); //free list not ordered } - CM_ASSERT(!(chunk->prev == 0 && (chunk != first))); //chunk not linked properly - CM_ASSERT(!(chunk->next == 0 && (chunk != last))); //chunk not linked property chunk = chunk->next_free_mem; } } } -#if 0 -static void cm_MM_RA_checkAlloc(t_cm_allocator_desc* alloc, t_uint32 size, t_uint32 align, t_uint32 min, t_uint32 max) -{ - t_cm_chunk *chunk = alloc->chunks; - - while(chunk != 0) { - if (chunk->status == MEM_USED) { - chunk = chunk->next; - continue; - } - if (chunk->size < size) { - chunk = chunk->next; - continue; - } - - if (min < chunk->offset) { - t_uint32 aligned_offset = ALIGN_VALUE(chunk->offset, align + 1); - t_uint32 aligned_end = aligned_offset + size; - if ((aligned_offset + size <= chunk->offset + chunk->size) - && (chunk->offset + chunk->size <= aligned_end)){ - break; - } - } - - if (min >= chunk->offset) { - t_uint32 aligned_offset = ALIGN_VALUE(min, align + 1); - t_uint32 aligned_end = aligned_offset + size; - if ((aligned_offset + size <= chunk->offset + chunk->size) - && (chunk->offset + chunk->size <= aligned_end)) { - break; - } - } - - chunk = chunk->next; - } - - CM_ASSERT(chunk == 0); -} -#endif - -/***************************************************************************/ -/* - * cm_mm_ra_getLastChunk - * param handle : Handle of the allocator - * return : last - * - * Free all chunk in the allocator - * Free allocator descriptor - * - */ -/***************************************************************************/ -static t_cm_chunk* cm_MM_RA_getLastChunk(t_cm_allocator_desc* alloc) -{ - t_cm_chunk* pChunk = alloc->chunks; - - while(pChunk->next != 0) {pChunk = pChunk->next;} - - return pChunk; -} - PUBLIC void cm_MM_DumpMemory(t_cm_allocator_desc* alloc, t_uint32 start, t_uint32 end) { t_cm_chunk *chunk = alloc->chunks; @@ -669,7 +640,7 @@ PUBLIC void cm_MM_DumpMemory(t_cm_allocator_desc* alloc, t_uint32 start, t_uint3 || ((chunk->offset > start) && (chunk->offset + chunk->size < end)) || ((chunk->offset < start) && (chunk->offset + chunk->size > end))) { - LOG_INTERNAL(0, "ALLOCATOR chunk 0x%08x -> 0x%08x: status:%s, domainId: 0x%x\n", + LOG_INTERNAL(0, "ALLOCATOR chunk [0x%08x -> 0x%08x[: status:%s, domainId: 0x%x\n", chunk->offset, chunk->offset + chunk->size, chunk->status?"FREE":"USED", diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator_utils.c b/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator_utils.c index 5c19d3e9b5e..4e800376dbb 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator_utils.c +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator_utils.c @@ -4,6 +4,7 @@ * License terms: GNU General Public License (GPL) version 2. */ #include +#include /***************************************************************************/ /* @@ -15,18 +16,29 @@ * */ /***************************************************************************/ -PUBLIC void linkChunk(t_cm_chunk* prev, t_cm_chunk* add) +PUBLIC void linkChunk(t_cm_allocator_desc* alloc, t_cm_chunk* prev, t_cm_chunk* add) { - /* Link previous */ - add->prev = prev; - add->next = prev->next; + // Link previous + if(prev == 0) + { + add->next = alloc->chunks; + alloc->chunks = add; + } + else + { + add->prev = prev; + add->next = prev->next; + prev->next = add; + } - /* Link next */ - if (prev->next != 0) + // Link next + if(add->next == 0) { - prev->next->prev = add; + // Link at the end + alloc->lastChunk = add; } - prev->next = add; + else + add->next->prev = add; } /***************************************************************************/ @@ -39,24 +51,28 @@ PUBLIC void linkChunk(t_cm_chunk* prev, t_cm_chunk* add) * */ /***************************************************************************/ -PUBLIC void unlinkChunk(t_cm_allocator_desc* alloc ,t_cm_chunk* current) +PUBLIC void unlinkChunk(t_cm_allocator_desc* alloc, t_cm_chunk* current) { - /* Unlink previous */ - if (current->prev !=0) - { + /* Link previous with next */ + if (current->prev != 0) current->prev->next = current->next; - } - - /* Unlink next */ - if (current->next !=0) + else { - current->next->prev= current->prev; + CM_ASSERT(alloc->chunks == current); + + // We remove the first, update chunks + alloc->chunks = current->next; } - /* Update first pointer */ - if (alloc ->chunks == current) + /* Link next with previous */ + if(current->next != 0) + current->next->prev= current->prev; + else { - alloc ->chunks = current->next; + CM_ASSERT(alloc->lastChunk == current); + + // We remove the last, update lastChunk + alloc->lastChunk = current->prev; } } @@ -194,42 +210,6 @@ PUBLIC void updateFreeList(t_cm_allocator_desc* alloc , t_cm_chunk* chunk) } -/***************************************************************************/ -/* - * mergeChunk - * param allocHandle : Allocator handle - * param merged_chunk : Pointer on merged chunk - * param destroy : Pointer on chunk to destroy - * - * Link and destroy merged chunks - * - */ -/***************************************************************************/ -PUBLIC void mergeChunk(t_cm_allocator_desc* alloc,t_cm_chunk *merged_chunk, t_cm_chunk *destroy) -{ - /* Assign offset to the merged */ - /* assume chunks ordered! - if (merged_chunk->offset > destroy->offset) { - merged_chunk->offset = destroy->offset; - } - */ - - /* Remove chunk */ - unlinkChunk(alloc, destroy); - unlinkFreeMem(alloc, destroy); - - if (merged_chunk->status == MEM_FREE) - unlinkFreeMem(alloc, merged_chunk); - - /* Update size */ - merged_chunk->size += destroy->size; - - if (merged_chunk->status == MEM_FREE) - updateFreeList(alloc, merged_chunk); - - freeChunk(destroy); -} - /***************************************************************************/ /* * splitChunk @@ -262,7 +242,7 @@ PUBLIC t_cm_chunk* splitChunk(t_cm_allocator_desc* alloc ,t_cm_chunk *chunk, new_chunk->alloc = alloc; chunk->size = offset - chunk->offset; - linkChunk(chunk, new_chunk); + linkChunk(alloc, chunk, new_chunk); unlinkFreeMem(alloc, free); updateFreeList(alloc, free); diff --git a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h index 8d95436e796..e2f6e8dec81 100644 --- a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h +++ b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h @@ -14,6 +14,7 @@ #include #include +#include /*! * \brief Identifier of a trace channel (id in [0..255]) @@ -43,6 +44,15 @@ typedef t_uint8 t_nmf_osal_sync_error; #define SEM_TIMEOUT_NORMAL 3000 #define SEM_TIMEOUT_DEBUG 300000 +struct osal_debug_operations { + void (*component_create)(t_component_instance *component); + void (*component_destroy)(t_component_instance *component); + void (*domain_create)(t_cm_domain_id id); + void (*domain_destroy)(t_cm_domain_id id); +}; + +extern struct osal_debug_operations osal_debug_ops; + /*! * \brief Description of the Scheduling part of the OS Adaptation Layer * diff --git a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/src/os_adaptation_layer.c b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/src/os_adaptation_layer.c index 9beb60dea18..380692e3cd8 100644 --- a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/src/os_adaptation_layer.c +++ b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/src/os_adaptation_layer.c @@ -4,10 +4,12 @@ * License terms: GNU General Public License (GPL) version 2. */ #include +#include t_nmf_osal_sync_handle lockHandleApi; t_nmf_osal_sync_handle lockHandleCom; t_nmf_osal_sem_handle semHandle; +struct osal_debug_operations osal_debug_ops; /****************/ /* Generic part */ @@ -15,17 +17,20 @@ t_nmf_osal_sem_handle semHandle; PUBLIC t_cm_error cm_OSAL_Init(void) { - /* create locks */ - lockHandleApi = OSAL_CreateLock(); - if (lockHandleApi == 0) {return CM_INVALID_PARAMETER;} - lockHandleCom = OSAL_CreateLock(); + /* create locks */ + lockHandleApi = OSAL_CreateLock(); + if (lockHandleApi == 0) {return CM_INVALID_PARAMETER;} + lockHandleCom = OSAL_CreateLock(); if (lockHandleCom == 0) {return CM_INVALID_PARAMETER;} - /* create semaphore */ + /* create semaphore */ semHandle = OSAL_CreateSemaphore(0); if (semHandle == 0) {return CM_INVALID_PARAMETER;} - return CM_OK; + /* init to zero */ + cm_MemSet(&osal_debug_ops, 0, sizeof(osal_debug_ops)); + + return CM_OK; } PUBLIC void cm_OSAL_Destroy(void) diff --git a/drivers/staging/nmf-cm/cm/engine/perfmeter/src/mpcload.c b/drivers/staging/nmf-cm/cm/engine/perfmeter/src/mpcload.c index b157103934d..193d155b97b 100644 --- a/drivers/staging/nmf-cm/cm/engine/perfmeter/src/mpcload.c +++ b/drivers/staging/nmf-cm/cm/engine/perfmeter/src/mpcload.c @@ -10,6 +10,8 @@ #include #include +#include + #define PERFMETER_MAX_RETRIES 32 #define PERFMETER_DATA_WORD_NB 7 @@ -96,9 +98,10 @@ PUBLIC t_cm_error cm_PFM_allocatePerfmeterDataMemory(t_nmf_core_id coreId, t_cm_ t_mpcLoad *pMpcLoad = (t_mpcLoad *) &mpcLoad_i[coreId]; pMpcLoad->perfmeterDataHandle = cm_DM_Alloc(domainId, SDRAM_EXT24, PERFMETER_DATA_WORD_NB, CM_MM_ALIGN_WORD, TRUE); - if (pMpcLoad->perfmeterDataHandle == INVALID_MEMORY_HANDLE) + if (pMpcLoad->perfmeterDataHandle == INVALID_MEMORY_HANDLE) { error = CM_NO_MORE_MEMORY; - else { + ERROR("CM_NO_MORE_MEMORY: Unable to allocate perfmeter\n", 0, 0, 0, 0, 0, 0); + } else { t_uint32 mmdspAddr; pMpcLoad->perfmeterDataAddr = cm_DSP_GetHostLogicalAddress(pMpcLoad->perfmeterDataHandle); diff --git a/drivers/staging/nmf-cm/cm/engine/power_mgt/inc/power.h b/drivers/staging/nmf-cm/cm/engine/power_mgt/inc/power.h index 1ca1b314833..942805df2f3 100644 --- a/drivers/staging/nmf-cm/cm/engine/power_mgt/inc/power.h +++ b/drivers/staging/nmf-cm/cm/engine/power_mgt/inc/power.h @@ -18,10 +18,12 @@ typedef enum { - NORMAL_PWR_MODE = 0x1, //!< Normal mode - DISABLE_PWR_MODE = 0x2 //!< Disable mode - CM Power management is disabled. CM Power domain are always enabled and the EEs are loaded by default + DISABLE_PWR_MODE = 0x0, //!< Disable mode - CM Power management is disabled. CM Power domain are always enabled and the EEs are loaded by default + NORMAL_PWR_MODE = 0x1 //!< Normal mode } t_nmf_power_mode; +extern t_nmf_power_mode powerMode; + PUBLIC t_cm_error cm_PWR_Init(void); void cm_PWR_SetMode(t_nmf_power_mode aMode); t_nmf_power_mode cm_PWR_GetMode(void); diff --git a/drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c b/drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c index 5b206bfb82d..37ba11314f9 100644 --- a/drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c +++ b/drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c @@ -29,7 +29,7 @@ static t_uint32 _pwrMPCMemoryCountT[NB_CORE_IDS]; // ------------------------------------------------------------------------------- // Internal data to store the global Power Manager mode (see cm_PWR_Init fct) // ------------------------------------------------------------------------------- -static t_nmf_power_mode _pwrMode = NORMAL_PWR_MODE; +t_nmf_power_mode powerMode = NORMAL_PWR_MODE; // ------------------------------------------------------------------------------- // cm_PWR_Init @@ -52,12 +52,12 @@ PUBLIC t_cm_error cm_PWR_Init(void) // ------------------------------------------------------------------------------- void cm_PWR_SetMode(t_nmf_power_mode aMode) { - _pwrMode = aMode; + powerMode = aMode; } t_nmf_power_mode cm_PWR_GetMode() { - return _pwrMode; + return powerMode; } t_uint32 cm_PWR_GetMPCMemoryCount(t_nmf_core_id coreId) diff --git a/drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c b/drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c index 176a965be22..f6ccb4a9992 100644 --- a/drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c +++ b/drivers/staging/nmf-cm/cm/engine/repository_mgt/src/repository_mgt.c @@ -18,6 +18,7 @@ #include +#undef NHASH #define NHASH 157 //Use a prime number! #define MULT 17 @@ -144,10 +145,10 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetRequiredComponentFiles( if((error = cm_checkValidServer(compServer, providedItfServerName, &itfProvide)) == CM_OK) { - cm_StringCopy(type, itfProvide.server->template->provides[itfProvide.provideIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringCopy(type, itfProvide.server->Template->provides[itfProvide.provideIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); cm_StringCopy(fileList[0], "_sk.", MAX_INTERFACE_TYPE_NAME_LENGTH); - cm_StringConcatenate(fileList[0], itfProvide.server->template->provides[itfProvide.provideIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[0], itfProvide.server->Template->provides[itfProvide.provideIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); } } break; @@ -160,11 +161,11 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetRequiredComponentFiles( if((error = cm_checkValidClient(compClient, requiredItfClientName, &itfRequire, &bindable)) == CM_OK) { - cm_StringCopy(type, itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); - *methodNumber = itfRequire.client->template->requires[itfRequire.requireIndex].interface->methodNumber; + cm_StringCopy(type, itfRequire.client->Template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + *methodNumber = itfRequire.client->Template->requires[itfRequire.requireIndex].interface->methodNumber; cm_StringCopy(fileList[0], "_st.", MAX_INTERFACE_TYPE_NAME_LENGTH); - cm_StringConcatenate(fileList[0], itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[0], itfRequire.client->Template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); } }; break; @@ -179,18 +180,18 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetRequiredComponentFiles( compServer, providedItfServerName, &itfRequire, &itfProvide, &bindable)) == CM_OK) { - if(compClient->template->dspId != compServer->template->dspId) + if(compClient->Template->dspId != compServer->Template->dspId) { cm_StringCopy(fileList[0], "_sk.", MAX_INTERFACE_TYPE_NAME_LENGTH); - cm_StringConcatenate(fileList[0], itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[0], itfRequire.client->Template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); cm_StringCopy(fileList[1], "_st.", MAX_INTERFACE_TYPE_NAME_LENGTH); - cm_StringConcatenate(fileList[1], itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[1], itfRequire.client->Template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); } else { cm_StringCopy(fileList[0], "_ev.", MAX_INTERFACE_TYPE_NAME_LENGTH); - cm_StringConcatenate(fileList[0], itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[0], itfRequire.client->Template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); } } }; break; @@ -207,7 +208,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetRequiredComponentFiles( &itfRequire, &itfProvide, &bindable)) == CM_OK) { cm_StringCopy(fileList[0], "_tr.", MAX_INTERFACE_TYPE_NAME_LENGTH); - cm_StringConcatenate(fileList[0], itfRequire.client->template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + cm_StringConcatenate(fileList[0], itfRequire.client->Template->requires[itfRequire.requireIndex].interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); } }; break; diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c index 832b9f28756..8a4d499ce41 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -59,15 +59,15 @@ static t_component_instance* getCorrespondingInstance( return instance; } - for(i = 0; i < instance->template->requireNumber; i++) { - int nb = instance->template->requires[i].collectionSize, j; + for(i = 0; i < instance->Template->requireNumber; i++) { + int nb = instance->Template->requires[i].collectionSize, j; for(j = 0; j < nb; j++) { if(instance->interfaceReferences[i][j].instance != NULL && instance->interfaceReferences[i][j].instance != (t_component_instance *)NMF_HOST_COMPONENT && instance->interfaceReferences[i][j].instance != (t_component_instance *)NMF_VOID_COMPONENT && instance->interfaceReferences[i][j].instance->thisAddress == panicThis) { - *itfName = instance->template->requires[i].name; + *itfName = instance->Template->requires[i].name; *instHandle = ENTRY2HANDLE(instance, k); return instance; } @@ -181,8 +181,8 @@ PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( if(instance != 0) { - cm_DSP_GetDspAddress(instance->memories[instance->template->codeMemory->id], &DspAddress); - cm_DSP_GetDspMemoryHandleSize(instance->memories[instance->template->codeMemory->id], &DspSize); + cm_DSP_GetDspAddress(instance->memories[instance->Template->codeMemory->id], &DspAddress); + cm_DSP_GetDspMemoryHandleSize(instance->memories[instance->Template->codeMemory->id], &DspSize); } if(DspAddress <= srcDescr->u.panic.info.mpc.panicInfo1 && @@ -206,7 +206,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( if(instance != 0) { LOG_INTERNAL(0, "Error: Component=%s<%s>\n", - instance->pathname, instance->template->name, 0, 0, 0, 0); + instance->pathname, instance->Template->name, 0, 0, 0, 0); } // We don't set rtos/commonpart/serviceReason = MPC_SERVICE_NONE, since we don't want the diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c b/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c index ac948c767b4..4620bc0fd07 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c @@ -72,11 +72,11 @@ void cm_TRC_traceLoadMap( trace.header.v = HEADER(TRACE_TYPE_COMPONENT, sizeof(trace)); trace.command = (t_uint16)command; - trace.domainId = (t_uint16)component->template->dspId + 1; + trace.domainId = (t_uint16)component->Template->dspId + 1; trace.componentContext = (t_uint32)component->thisAddress; trace.componentUserContext = (t_uint32)component; cm_StringCopy((char*)trace.componentLocalName, component->pathname, MAX_COMPONENT_NAME_LENGTH); - cm_StringCopy((char*)trace.componentTemplateName, component->template->name, MAX_TEMPLATE_NAME_LENGTH); + cm_StringCopy((char*)trace.componentTemplateName, component->Template->name, MAX_TEMPLATE_NAME_LENGTH); writeN((struct t_nmfTraceChannelHeader*)&trace); @@ -90,12 +90,12 @@ void cm_TRC_traceLoadMap( */ tracemethod.header.v = HEADER(TRACE_TYPE_METHOD, sizeof(tracemethod)); - tracemethod.domainId = (t_uint16)component->template->dspId + 1; + tracemethod.domainId = (t_uint16)component->Template->dspId + 1; tracemethod.componentContext = (t_uint32)component->thisAddress; - for(i = 0; i < component->template->provideNumber; i++) + for(i = 0; i < component->Template->provideNumber; i++) { - t_interface_provide* provide = &component->template->provides[i]; + t_interface_provide* provide = &component->Template->provides[i]; for(j = 0; j < provide->collectionSize; j++) { @@ -133,7 +133,7 @@ void cm_TRC_traceBinding( } else { - trace.clientDomainId = (t_uint16)clientComponent->template->dspId + 1; + trace.clientDomainId = (t_uint16)clientComponent->Template->dspId + 1; trace.clientComponentContext = (t_uint32)clientComponent->thisAddress; } if(requiredItfName != NULL) @@ -153,7 +153,7 @@ void cm_TRC_traceBinding( } else { - trace.serverDomainId = (t_uint16)serverComponent->template->dspId + 1; + trace.serverDomainId = (t_uint16)serverComponent->Template->dspId + 1; trace.serverComponentContext = (t_uint32)serverComponent->thisAddress; } if(providedItfName != NULL) diff --git a/drivers/staging/nmf-cm/cm/engine/utils/src/string.c b/drivers/staging/nmf-cm/cm/engine/utils/src/string.c index 0ed6fb3a214..89058d5825a 100644 --- a/drivers/staging/nmf-cm/cm/engine/utils/src/string.c +++ b/drivers/staging/nmf-cm/cm/engine/utils/src/string.c @@ -14,6 +14,7 @@ #include #include +#undef NHASH #define NHASH 257 //Use a prime number! #define MULT 17 @@ -29,6 +30,7 @@ struct t_linkedstring static struct t_linkedstring *list[NHASH]; +#undef myoffsetof #define myoffsetof(st, m) \ ((int) ( (char *)&((st *)(0))->m - (char *)0 )) diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c new file mode 100644 index 00000000000..bf3fa422208 --- /dev/null +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -0,0 +1,838 @@ +/* + * Copyright (C) ST-Ericsson SA 2011 + * Author: Pierre Peiffer for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +#include + +#include "osal-kernel.h" +#include "cm_debug.h" + +#ifdef CONFIG_DEBUG_FS + +static struct dentry *cm_dir; /* nmf-cm/ */ +static struct dentry *proc_dir; /* nmf-cm/proc/ */ +static struct dentry *core_dir; /* nmf-cm/dsp/ */ +static struct dentry *domain_dir; /* nmf-cm/domains/ */ + +/* components data managment */ +struct cm_debug_component_cooky { + struct dentry *comp_file; /* entry in nmf-cm/dsp/sxa/components/ */ + struct dentry *proc_link; /* entry in nmf-cm/proc/ */ +}; + +static ssize_t component_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) { + t_component_instance *component = file->f_dentry->d_inode->i_private; + char buf[640]; + int ret=0; + + OSAL_LOCK_API(); + if ((component != NULL) && (component->dbgCooky != NULL)) { + char nb_i[16] = ""; + int i; + + if (component->Template->classe == SINGLETON) + snprintf(nb_i, sizeof(nb_i), " (%d)", + component->Template->numberOfInstance); + + ret = snprintf(buf, sizeof(buf), + "Name:\t\t%s <%s>\n" + "Class:\t\t%s%s\n" + "State:\t\t%s\n" + "Priority:\t%u\n" + "Domain:\t\t%u\n\n" + "Memory : Physical address Logical address" + " DSP address Size\n" + "---------------------------------------------" + "-----------------------------\n", + component->pathname, + component->Template->name, + component->Template->classe == COMPONENT ? + "Component" : + (component->Template->classe == SINGLETON ? + "Singleton" : + (component->Template->classe == FIRMWARE ? + "Firmware" : + "?")), + nb_i, + component->state == STATE_RUNNABLE ? "Runnable" : + (component->state == STATE_STOPPED ? "Sopped" : + "None"), + (unsigned)component->priority, + component->domainId + ); + + for (i=0; imemories[i]) { + t_cm_system_address addr; + t_uint32 dspAddr, dspSize; + cm_DSP_GetHostSystemAddress( + component->memories[i], &addr); + cm_DSP_GetDspAddress( + component->memories[i], &dspAddr); + cm_DSP_GetDspMemoryHandleSize( + component->memories[i], &dspSize); + ret += snprintf( + &buf[ret], sizeof(buf)-ret, + "%-10s: %p-%p %p-%p %p-%p %8lu\n", + MMDSP_getMappingById(i)->memoryName, + (void *)addr.physical, + (void *)addr.physical + + component->memories[i]->size-1, + (void *)addr.logical, + (void *)addr.logical + + component->memories[i]->size-1, + (void *)dspAddr, + (void *)dspAddr + dspSize - 1, + component->memories[i]->size); + } + } + } + + OSAL_UNLOCK_API(); + return simple_read_from_buffer(userbuf, count, ppos, buf, ret); +} + +static const struct file_operations component_fops = { + .read = component_read, +}; + +static void cm_debug_component_create(t_component_instance *component) +{ + char tmp[12+MAX_COMPONENT_NAME_LENGTH]; + struct cm_debug_component_cooky *cooky; + struct mpcConfig *mpc; + mpc = &osalEnv.mpc[COREIDX(component->Template->dspId)]; + + cooky = OSAL_Alloc_Zero(sizeof(*cooky)); + if (cooky == NULL) + return; + + component->dbgCooky = cooky; + sprintf(tmp, "%s-%08x", component->pathname, + (unsigned int)component->instance); + cooky->comp_file = debugfs_create_file(tmp, S_IRUSR|S_IRGRP, + mpc->comp_dir, + component, &component_fops); + if (IS_ERR(cooky->comp_file)) { + if (PTR_ERR(cooky->comp_file) != -ENODEV) + pr_info("CM: Can't create dsp/%s/components/%s" + "debugfs file: %ld\n", + mpc->name, + tmp, + PTR_ERR(cooky->comp_file)); + cooky->comp_file = NULL; + } else { + char target_lnk[40+MAX_COMPONENT_NAME_LENGTH]; + sprintf(target_lnk, "../../../dsp/%s/components/%s-%08x", + mpc->name, + component->pathname, + (unsigned int)component->instance); + + /* Some firmware, like Executive Engine, do not belong + to any process */ + if (domainDesc[component->domainId].client == current->tgid) { + struct list_head* head; + struct cm_process_priv *entry = NULL; + /* Search the entry for the calling process */ + list_for_each(head, &process_list) { + entry = list_entry(head, + struct cm_process_priv, + entry); + if (entry->pid == current->tgid) + break; + } + + if (entry) { + cooky->proc_link = debugfs_create_symlink( + tmp, + entry->comp_dir, + target_lnk); + if (IS_ERR(cooky->proc_link)) { + long err = PTR_ERR(cooky->proc_link); + if (err != -ENODEV) + pr_info("CM: Can't create " + "proc/%d/%s " + "debugfs link: %ld\n", + entry->pid, tmp, err); + cooky->proc_link = NULL; + } + } + } + } +} + +static void cm_debug_component_destroy(t_component_instance *component) +{ + struct cm_debug_component_cooky *cooky = component->dbgCooky; + + if (cooky) { + component->dbgCooky = NULL; + debugfs_remove(cooky->proc_link); + debugfs_remove(cooky->comp_file); + OSAL_Free(cooky); + } +} + +/* domain data managment */ +struct cm_debug_domain_cooky { + struct dentry *domain_file; /* entry in nmf-cm/components/ */ + struct dentry *proc_link; /* entry in nmf-cm/proc/ */ + struct dentry *dsp_link; /* entry in nmf-cm/dsp/sxa/domains */ +}; + +static ssize_t domain_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + t_cm_domain_id id = + (t_cm_domain_id)(long)file->f_dentry->d_inode->i_private; + t_cm_domain_desc *domain = &domainDesc[id]; + + char buf[640]; + int ret=0; + + OSAL_LOCK_API(); + if ((cm_DM_CheckDomain(id, DOMAIN_ANY) == CM_OK) + && (domain->domain.coreId != -1) + && (domain->dbgCooky != NULL)) { + t_cm_allocator_status status; + t_uint32 dOffset; + t_uint32 dSize; + if (domain->domain.coreId != ARM_CORE_ID) { + t_cm_domain_info info; + + cm_DM_GetDomainAbsAdresses(id, &info); + cm_DSP_GetInternalMemoriesInfo(id, ESRAM_CODE, + &dOffset, &dSize); + cm_MM_GetAllocatorStatus( + cm_DSP_GetAllocator(domain->domain.coreId, + ESRAM_CODE), + dOffset, dSize, &status); + ret = snprintf( + buf, sizeof(buf), + "Core:\t%s\n\n" + "Memory : Physical address Logical address" + " Size Free Used\n" + "---------------------------------------------" + "-----------------------------\n" + "ESRAM Code: %08x-%08lx %08x-%08lx\t%8lu %8lu " + "%8lu\n", + osalEnv.mpc[COREIDX(domain->domain.coreId)].name, + (unsigned int)info.esramCode.physical, + domain->domain.esramCode.size ? + info.esramCode.physical + + domain->domain.esramCode.size - 1 : 0, + (unsigned int)info.esramCode.logical, + domain->domain.esramCode.size ? + info.esramCode.logical + + domain->domain.esramCode.size - 1 : 0, + domain->domain.esramCode.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + + cm_DSP_GetInternalMemoriesInfo(id, ESRAM_EXT24, + &dOffset, &dSize); + cm_MM_GetAllocatorStatus( + cm_DSP_GetAllocator(domain->domain.coreId, + ESRAM_EXT24), + dOffset, dSize, &status); + ret += snprintf( + &buf[ret], sizeof(buf)-ret, + "ESRAM Data: %08x-%08lx " + "%08x-%08lx\t%8lu %8lu %8lu\n", + (unsigned int)info.esramData.physical, + domain->domain.esramData.size ? + info.esramData.physical + + domain->domain.esramData.size - 1 : 0, + (unsigned int)info.esramData.logical, + domain->domain.esramData.size ? + info.esramData.logical + + domain->domain.esramData.size - 1 : 0, + domain->domain.esramData.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + + cm_DSP_GetInternalMemoriesInfo(id, SDRAM_CODE, + &dOffset, &dSize); + cm_MM_GetAllocatorStatus( + cm_DSP_GetAllocator(domain->domain.coreId, + SDRAM_CODE), + dOffset, dSize, &status); + ret += snprintf( + &buf[ret], sizeof(buf)-ret, + "SDRAM Code: %08x-%08lx " + "%08x-%08lx\t%8lu %8lu %8lu\n", + (unsigned int)info.sdramCode.physical, + domain->domain.sdramCode.size ? + info.sdramCode.physical + + domain->domain.sdramCode.size - 1 : 0, + (unsigned int)info.sdramCode.logical, + domain->domain.sdramCode.size ? + info.sdramCode.logical + + domain->domain.sdramCode.size - 1 : 0, + domain->domain.sdramCode.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + + cm_DSP_GetInternalMemoriesInfo(id, SDRAM_EXT24, + &dOffset, &dSize); + cm_MM_GetAllocatorStatus( + cm_DSP_GetAllocator(domain->domain.coreId, + SDRAM_EXT24), + dOffset, dSize, &status); + ret += snprintf( + &buf[ret], sizeof(buf)-ret, + "SDRAM Data: %08x-%08lx " + "%08x-%08lx\t%8lu %8lu %8lu\n", + (unsigned int)info.sdramData.physical, + domain->domain.sdramData.size ? + info.sdramData.physical + + domain->domain.sdramData.size - 1 : 0, + (unsigned int)info.sdramData.logical, + domain->domain.sdramData.size ? + info.sdramData.logical + + domain->domain.sdramData.size - 1 : 0, + domain->domain.sdramData.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + } else { + t_cm_system_address addr; + ret = snprintf( + buf, sizeof(buf), + "Core:\tarm\n\n" + "Memory : Physical address Logical " + "address Size Free Used\n" + "---------------------------------------" + "-----------------------------------\n"); + if (domain->domain.esramCode.size) { + cm_DSP_GetDspBaseAddress(ARM_CORE_ID, + ESRAM_CODE, &addr); + cm_DSP_GetInternalMemoriesInfo(id, ESRAM_CODE, + &dOffset, + &dSize); + cm_MM_GetAllocatorStatus( + cm_DSP_GetAllocator(ARM_CORE_ID, + ESRAM_CODE), + dOffset, dSize, &status); + ret += snprintf( + &buf[ret], sizeof(buf)-ret, + "ESRAM Code: %08x-%08lx " + "%08x-%08lx\t%8lu %8lu %8lu\n", + (unsigned int)addr.physical, + addr.physical + + domain->domain.esramCode.size - 1, + (unsigned int)addr.logical, + addr.logical + + domain->domain.esramCode.size - 1, + domain->domain.esramCode.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + } + if (domain->domain.esramData.size) { + cm_DSP_GetDspBaseAddress(ARM_CORE_ID, + ESRAM_EXT24, &addr); + cm_DSP_GetInternalMemoriesInfo(id, ESRAM_EXT24, + &dOffset, + &dSize); + cm_MM_GetAllocatorStatus( + cm_DSP_GetAllocator(ARM_CORE_ID, + ESRAM_EXT24), + dOffset, dSize, &status); + ret += snprintf( + &buf[ret], sizeof(buf)-ret, + "ESRAM Data: %08x-%08lx " + "%08x-%08lx\t%8lu %8lu %8lu\n", + (unsigned int)addr.physical, + addr.physical + + domain->domain.esramData.size - 1, + (unsigned int)addr.logical, + addr.logical + + domain->domain.esramData.size - 1, + domain->domain.esramData.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + } + if (domain->domain.sdramCode.size) { + cm_DSP_GetDspBaseAddress(ARM_CORE_ID, + SDRAM_CODE, &addr); + cm_DSP_GetInternalMemoriesInfo(id, SDRAM_CODE, + &dOffset, + &dSize); + cm_MM_GetAllocatorStatus( + cm_DSP_GetAllocator(ARM_CORE_ID, + SDRAM_CODE), + dOffset, dSize, &status); + ret += snprintf( + &buf[ret], sizeof(buf)-ret, + "SDRAM Code: %08x-%08lx %08x-%08lx\t" + "%8lu %8lu %8lu\n", + (unsigned int)addr.physical, + addr.physical + + domain->domain.sdramCode.size - 1, + (unsigned int)addr.logical, + addr.logical + + domain->domain.sdramCode.size - 1, + domain->domain.sdramCode.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + } + if (domain->domain.sdramData.size) { + cm_DSP_GetDspBaseAddress(ARM_CORE_ID, + SDRAM_EXT24, &addr); + cm_DSP_GetInternalMemoriesInfo(id, SDRAM_EXT24, + &dOffset, + &dSize); + cm_MM_GetAllocatorStatus( + cm_DSP_GetAllocator(ARM_CORE_ID, + SDRAM_EXT24), + dOffset, dSize, &status); + ret += snprintf( + &buf[ret], sizeof(buf)-ret, + "SDRAM Data: %08x-%08lx %08x-%08lx\t" + "%8lu %8lu %8lu\n", + (unsigned int)addr.physical, + addr.physical + + domain->domain.sdramData.size - 1, + (unsigned int)addr.logical, + addr.logical + + domain->domain.sdramData.size - 1, + domain->domain.sdramData.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + } + } + } + OSAL_UNLOCK_API(); + return simple_read_from_buffer(userbuf, count, ppos, buf, ret);; +} + +static const struct file_operations domain_fops = { + .read = domain_read, +}; + +static void cm_debug_domain_create(t_cm_domain_id id) +{ + char tmp[12]; + struct cm_debug_domain_cooky *cooky; + + cooky = OSAL_Alloc_Zero(sizeof(*cooky)); + if (cooky == NULL) + return; + + domainDesc[id].dbgCooky = cooky; + sprintf(tmp, "%u", id); + cooky->domain_file = debugfs_create_file(tmp, S_IRUSR|S_IRGRP, + domain_dir, + (void *)(long)id, + &domain_fops); + if (IS_ERR(cooky->domain_file)) { + if (PTR_ERR(cooky->domain_file) != -ENODEV) + pr_err("CM: Can't create domains/%s debugfs " + "file: %ld\n", tmp, + PTR_ERR(cooky->domain_file)); + cooky->domain_file = NULL; + } else { + char target_lnk[40]; + sprintf(target_lnk, "../../../domains/%u", id); + + if (domainDesc[id].client != NMF_CORE_CLIENT) { + struct list_head* head; + struct cm_process_priv *entry = NULL; + + /* Search the entry for the target process */ + list_for_each(head, &process_list) { + entry = list_entry(head, + struct cm_process_priv, + entry); + if (entry->pid == domainDesc[id].client) + break; + } + + if (entry) { + cooky->proc_link = debugfs_create_symlink( + tmp, + entry->domain_dir, + target_lnk); + if (IS_ERR(cooky->proc_link)) { + long err = PTR_ERR(cooky->proc_link); + if (err != -ENODEV) + pr_err("CM: Can't create " + "proc/%d/domains/%s " + "debugfs link: %ld\n", + entry->pid, tmp, err); + cooky->proc_link = NULL; + } + } + } + if (domainDesc[id].domain.coreId != ARM_CORE_ID) { + cooky->dsp_link = + debugfs_create_symlink( + tmp, + osalEnv.mpc[COREIDX(domainDesc[id].domain.coreId)].domain_dir, + target_lnk); + if (IS_ERR(cooky->dsp_link)) { + if (PTR_ERR(cooky->dsp_link) != -ENODEV) + pr_err("CM: Can't create dsp/%s/domains/%s " + "debugfs link: %ld\n", + osalEnv.mpc[COREIDX(domainDesc[id].domain.coreId)].name, + tmp, + PTR_ERR(cooky->dsp_link)); + cooky->dsp_link = NULL; + } + } + } +} + +static void cm_debug_domain_destroy(t_cm_domain_id id) +{ + struct cm_debug_domain_cooky *cooky = domainDesc[id].dbgCooky; + if (cooky) { + domainDesc[id].dbgCooky = NULL; + debugfs_remove(cooky->proc_link); + debugfs_remove(cooky->dsp_link); + debugfs_remove(cooky->domain_file); + OSAL_Free(cooky); + } +} + +/* proc directory */ +void cm_debug_proc_init(struct cm_process_priv *entry) +{ + char tmp[PROC_NUMBUF]; + sprintf(tmp, "%d", entry->pid); + entry->dir = debugfs_create_dir(tmp, proc_dir); + if (IS_ERR(entry->dir)) { + if (PTR_ERR(entry->dir) != -ENODEV) + pr_info("CM: Can't create proc/%d debugfs directory: " + "%ld\n", entry->pid, PTR_ERR(entry->dir)); + entry->dir = NULL; + return; + } + entry->comp_dir = debugfs_create_dir("components", entry->dir); + if (IS_ERR(entry->comp_dir)) { + if (PTR_ERR(entry->comp_dir) != -ENODEV) + pr_info("CM: Can't create proc/%d/components debugfs " + "directory: %ld\n", entry->pid, + PTR_ERR(entry->comp_dir)); + entry->comp_dir = NULL; + } + entry->domain_dir = debugfs_create_dir("domains", entry->dir); + if (IS_ERR(entry->domain_dir)) { + if (PTR_ERR(entry->domain_dir) != -ENODEV) + pr_info("CM: Can't create proc/%d/domains debugfs " + "directory: %ld\n", entry->pid, + PTR_ERR(entry->domain_dir)); + entry->domain_dir = NULL; + } +} + +/* DSP meminfo */ +static ssize_t meminfo_read(struct file *file, char __user *userbuf, + size_t count, loff_t *ppos) +{ + const t_nmf_core_id id = + *(t_nmf_core_id *)file->f_dentry->d_inode->i_private; + char buf[640]; + int ret=0; + t_cm_allocator_status status; + t_cm_system_address addr; + + OSAL_LOCK_API(); + cm_MM_GetAllocatorStatus(cm_DSP_GetAllocator(id, ESRAM_CODE), + 0, 0, &status); + cm_DSP_GetDspBaseAddress(id, ESRAM_CODE, &addr); + ret = snprintf(buf, sizeof(buf), + "Memory : Physical address Logical address Size " + " Free Used\n" + "-------------------------------------------------------" + "-------------------\n" + "ESRAM Code: %08x-%08lx %08x-%08lx\t%8lu %8lu %8lu\n", + (unsigned int)addr.physical, + addr.physical + status.global.size - 1, + (unsigned int)addr.logical, + addr.logical + status.global.size - 1, + status.global.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + + cm_MM_GetAllocatorStatus(cm_DSP_GetAllocator(id, ESRAM_EXT24), + 0, 0, &status); + cm_DSP_GetDspBaseAddress(id, ESRAM_EXT24, &addr); + ret += snprintf(&buf[ret], sizeof(buf)-ret, + "ESRAM Data: %08x-%08lx %08x-%08lx\t%8lu %8lu %8lu\n", + (unsigned int)addr.physical, + addr.physical + status.global.size - 1, + (unsigned int)addr.logical, + addr.logical + status.global.size - 1, + status.global.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + + cm_MM_GetAllocatorStatus(cm_DSP_GetAllocator(id, SDRAM_CODE), + 0, 0, &status); + cm_DSP_GetDspBaseAddress(id, SDRAM_CODE, &addr); + ret += snprintf(&buf[ret], sizeof(buf)-ret, + "SDRAM Code: %08x-%08lx %08x-%08lx\t%8lu %8lu %8lu\n", + (unsigned int)addr.physical, + addr.physical + status.global.size - 1, + (unsigned int)addr.logical, + addr.logical + status.global.size - 1, + status.global.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + + cm_MM_GetAllocatorStatus(cm_DSP_GetAllocator(id, SDRAM_EXT24), + 0, 0, &status); + cm_DSP_GetDspBaseAddress(id, SDRAM_EXT24, &addr); + ret += snprintf(&buf[ret], sizeof(buf)-ret, + "SDRAM Data: %08x-%08lx %08x-%08lx\t%8lu %8lu %8lu\n", + (unsigned int)addr.physical, + addr.physical + status.global.size - 1, + (unsigned int)addr.logical, + addr.logical + status.global.size - 1, + status.global.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + + cm_MM_GetAllocatorStatus(cm_DSP_GetAllocator(id, INTERNAL_XRAM24), + 0, 0, &status); + cm_DSP_GetDspBaseAddress(id, INTERNAL_XRAM24, &addr); + ret += snprintf(&buf[ret], sizeof(buf)-ret, + "TCM XRAM : %08x-%08lx %08x-%08lx\t%8lu %8lu %8lu\n", + (unsigned int)addr.physical, + addr.physical + status.global.size - 1, + (unsigned int)addr.logical, + addr.logical + status.global.size - 1, + status.global.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + + cm_MM_GetAllocatorStatus(cm_DSP_GetAllocator(id, INTERNAL_YRAM24), + 0, 0, &status); + cm_DSP_GetDspBaseAddress(id, INTERNAL_YRAM24, &addr); + ret += snprintf(&buf[ret], sizeof(buf)-ret, + "TCM YRAM : %08x-%08lx %08x-%08lx\t%8lu %8lu %8lu\n", + (unsigned int)addr.physical, + addr.physical + status.global.size - 1, + (unsigned int)addr.logical, + addr.logical + status.global.size - 1, + status.global.size, + status.global.accumulate_free_memory, + status.global.accumulate_used_memory); + + OSAL_UNLOCK_API(); + return simple_read_from_buffer(userbuf, count, ppos, buf, ret);; +} + +static const struct file_operations mem_fops = { + .read = meminfo_read, +}; + +/* ESRAM file operations */ +static int esram_open(struct inode *inode, struct file *file) +{ + int i, err=0; + for (i=0; i=0; i--) + regulator_disable(osalEnv.esram_regulator[i]); + } + + return err; +} + +static int esram_release(struct inode *inode, struct file *file) +{ + int i; + for (i=0; i for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2. + */ + +#ifndef CM_DEBUG_H +#define CM_DEBUG_H + +#ifdef CONFIG_DEBUG_FS +#include "cmld.h" + +void cm_debug_init(void); +void cm_debug_exit(void); +void cm_debug_proc_init(struct cm_process_priv *entry); +void cm_debug_create_tcm_file(unsigned mpc_index); +void cm_debug_destroy_tcm_file(unsigned mpc_index); +#endif /* CONFIG_DEBUG_FS */ +#endif /* CM_DEBUG_H */ diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index bc70afe10a0..06cfbc74146 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -31,9 +31,14 @@ DECLARE_TASKLET(cmld_service_tasklet, service_tasklet_func, 0); void dispatch_service_msg(struct osal_msg *msg) { struct list_head *head, *next; - - /* Note: no lock needed to protect the channel_list to protect against list - changes, as the current tasklet is disabled each time we modify the list */ +#ifdef CONFIG_DEBUG_FS + bool dump_flag_to_set = true; +#endif + /* + * Note: no lock needed to protect the channel_list against list + * changes, as the current tasklet is disabled each time we modify + * the list + */ list_for_each_safe(head, next, &channel_list) { struct cm_channel_priv *channelPriv = list_entry(head, struct cm_channel_priv, entry); struct osal_msg *new_msg; @@ -50,6 +55,19 @@ void dispatch_service_msg(struct osal_msg *msg) } memcpy(new_msg, msg, msg_size); plist_node_init(&new_msg->msg_entry, 0); +#ifdef CONFIG_DEBUG_FS + if (user_has_debugfs && dump_flag_to_set + && (new_msg->d.srv.srvType == NMF_SERVICE_PANIC)) { + /* + * The reciever of this message will do the DSP + * memory dump + */ + new_msg->d.srv.srvData.panic.panicSource + |= DEBUGFS_DUMP_FLAG; + dump_flag_to_set = false; + dump_done = false; + } +#endif spin_lock_bh(&channelPriv->bh_lock); plist_add(&new_msg->msg_entry, &channelPriv->messageQueue); spin_unlock_bh(&channelPriv->bh_lock); @@ -77,8 +95,9 @@ static void service_tasklet_func(unsigned long unused) dispatch_service_msg(&msg); /* - * Stop DMA directly before shutdown, to avoid bad sound. - * Should be called after DSP has stopped executing, to avoid the DSP + * Stop DMA directly before shutdown, to avoid + * bad sound. Should be called after DSP has + * stopped executing, to avoid the DSP * re-starting DMA */ if (osalEnv.mpc[i].coreId == SIA_CORE_ID) @@ -90,7 +109,8 @@ static void service_tasklet_func(unsigned long unused) if (CM_ReadMPCString(osalEnv.mpc[i].coreId, desc.u.print.dspAddress, msg, sizeof(msg)) == CM_OK) - printk(msg, desc.u.print.value1, desc.u.print.value2); + printk(msg, desc.u.print.value1, + desc.u.print.value2); break; } default: diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h index e1ef2bcb025..96481be38b8 100644 --- a/drivers/staging/nmf-cm/cmioctl.h +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -9,6 +9,10 @@ #ifndef __CMIOCTL_H #define __CMIOCTL_H +#ifndef __KERNEL__ +#define BITS_PER_BYTE 8 +#endif + #include #include #include @@ -17,6 +21,8 @@ #include #include +#define DEBUGFS_ROOT "nmf-cm" +#define DEBUGFS_DUMP_FLAG (1 << (sizeof(t_panic_source)*BITS_PER_BYTE - 1)) enum cmdma_type { CMDMA_MEM_2_PER, @@ -586,6 +592,9 @@ typedef struct{ #define CM_PRIVRESERVEMEMORY _IOW('c', 101, unsigned int) #define CM_PRIV_GETBOARDVERSION _IOR('c', 102, unsigned int) #define CM_PRIV_ISCOMPONENTCACHEEMPTY _IO('c', 103) +#define CM_PRIV_DEBUGFS_READY _IO('c', 104) +#define CM_PRIV_DEBUGFS_WAIT_DUMP _IO('c', 105) +#define CM_PRIV_DEBUGFS_DUMP_DONE _IO('c', 106) enum board_version { U8500_V2 diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index d01949c8673..f8fe0d41059 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -11,10 +11,8 @@ */ #include -#include #include #include -#include #include #include #include @@ -23,13 +21,14 @@ #include #include -#include "cmioctl.h" #include "osal-kernel.h" #include "cmld.h" +#include "cmioctl.h" +#include "cm_debug.h" #include "cm_service.h" #include "cm_dma.h" -#define CMDRIVER_PATCH_VERSION 109 +#define CMDRIVER_PATCH_VERSION 112 #define O_FLUSH 0x1000000 static int cmld_major; @@ -49,19 +48,13 @@ static DEFINE_MUTEX(process_lock); /* lock used to protect previous list */ LIST_HEAD(channel_list); static DEFINE_MUTEX(channel_lock); /* lock used to protect previous list */ -/* Variables used to manage temporary allocation of ESRAM - reserved for DMA and B2R2 + MCDE */ -/* As of now, the reservation is done in RME */ -static int cfgESRAM_ReserveMCDE = 0; -static int cfgESRAM_ReserveDMA = 0; -static int cfgESRAMDmaSize = 4; /* in Kb */ -static int cfgESRAMMcdeSize = 128; /* in Kb */ -module_param(cfgESRAM_ReserveMCDE, bool, S_IRUGO); -module_param(cfgESRAM_ReserveDMA, bool, S_IRUGO); -module_param(cfgESRAMDmaSize, uint, S_IRUGO); -module_param(cfgESRAMMcdeSize, uint, S_IRUGO); -static t_cm_domain_id dmaDomainId, mcdeDomainId; -static t_cm_memory_handle dmaMemoryHdl, mcdeMemoryHdl; +#ifdef CONFIG_DEBUG_FS +/* Debugfs support */ +bool user_has_debugfs = false; +bool dump_done = true; +module_param(dump_done, bool, S_IWUSR|S_IRUGO); +static DECLARE_WAIT_QUEUE_HEAD(dump_waitq); +#endif static inline struct cm_process_priv *getProcessPriv(void) { @@ -95,6 +88,9 @@ static inline struct cm_process_priv *getProcessPriv(void) entry->pid = current->tgid; mutex_lock(&process_lock); list_add(&entry->entry, &process_list); +#ifdef CONFIG_DEBUG_FS + cm_debug_proc_init(entry); +#endif out: mutex_unlock(&process_lock); return entry; @@ -113,11 +109,9 @@ static inline void freeMessages(struct cm_channel_priv* channelPriv) warn = 1; } spin_unlock_bh(&channelPriv->bh_lock); - if (warn) { + if (warn) pr_err("[CM - PID=%d]: Some remaining" " message(s) freed\n", current->tgid); - warn = 0; - } } /* Free all pending memory areas and relative descriptors */ @@ -231,6 +225,10 @@ static void freeProcessPriv(struct kref *ref) pr_err("[CM - PID=%d]: Error while flushing some remaining" " domains: error=%d\n", current->tgid, err); +#ifdef CONFIG_DEBUG_FS + debugfs_remove_recursive(entry->dir); +#endif + /* Free the per-process descriptor */ OSAL_Free(entry); } @@ -288,8 +286,6 @@ static int cmld_release(struct inode *inode, struct file *file) { struct cm_process_priv* procPriv; - BUG_ON(file->private_data == NULL); - /* The driver must guarantee that all related resources are released. Thus all these checks below are necessary to release all remaining resources still linked to this 'client', in case of abnormal process @@ -364,11 +360,11 @@ static ssize_t cmld_read(struct file *file, char *buf, size_t count, loff_t *ppo if (iminor(file->f_dentry->d_inode) == 0) return -ENOSYS; - BUG_ON(channelPriv == NULL); messageQueue = &channelPriv->messageQueue; if (mutex_lock_killable(&channelPriv->msgQueueLock)) return -ERESTARTSYS; + wait: while (plist_head_empty(messageQueue)) { mutex_unlock(&channelPriv->msgQueueLock); @@ -467,9 +463,8 @@ static int cmld_flush(struct file *file, fl_owner_t id) { if (iminor(file->f_dentry->d_inode) != 0) { struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); - //channelPriv->closed = CHANNEL_CLOSED; file->f_flags |= O_FLUSH; - wake_up_all(&channelPriv->waitq); + wake_up_interruptible(&channelPriv->waitq); } return 0; } @@ -695,12 +690,18 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long return 0; else return -ENOENT; - - default: { + case CM_PRIV_DEBUGFS_READY: +#ifdef CONFIG_DEBUG_FS + user_has_debugfs = true; +#endif + return 0; + case CM_PRIV_DEBUGFS_DUMP_DONE: + case CM_PRIV_DEBUGFS_WAIT_DUMP: + return 0; + default: pr_err("CM(%s): unsupported command %i\n", __func__, cmd); return -EINVAL; } - } return 0; } @@ -712,7 +713,14 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long */ static long cmld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { - BUG_ON(filp->private_data == NULL); +#ifdef CONFIG_DEBUG_FS + if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { + dump_done = true; + wake_up_interruptible(&dump_waitq); + return 0; + } else if (wait_event_interruptible(dump_waitq, dump_done)) + return -ERESTARTSYS; +#endif if (iminor(filp->f_dentry->d_inode) == 0) { return cmld_control_ctl(filp, cmd, arg); @@ -756,8 +764,6 @@ static int cmld_mmap(struct file* file, struct vm_area_struct* vma) struct memAreaDesc_t* curr = NULL; unsigned int vma_size = vma->vm_end-vma->vm_start; - BUG_ON(procPriv == NULL); - listHead = &procPriv->memAreaDescList; if (lock_process(procPriv)) return -ERESTARTSYS; @@ -918,7 +924,7 @@ static int configureMpc(unsigned i, t_cfg_allocator_id *dataAllocId) * (see in remapRegions()) and we need to create the segment only at first call. * => we reuse the same allocId for the following MPCs */ - if ((osalEnv.mpc[i].sdramDataL != osalEnv.mpc[0].sdramDataL) + if ((osalEnv.mpc[i].sdram_data.data != osalEnv.mpc[0].sdram_data.data) || *dataAllocId == -1) { err = CM_ENGINE_AddMpcSdramSegment(&dataSegment, dataAllocId, "Data"); if (err != CM_OK) { @@ -1155,62 +1161,9 @@ static int __init cmld_init_module(void) CMDRIVER_PATCH_VERSION); } - /* Reserve DMA and MCDE ESRAM if needed */ - if (cfgESRAM_ReserveDMA) { - t_cm_domain_memory domain = INIT_DOMAIN; - - // Reserve memory used by DMA - domain.coreId = ARM_CORE_ID; - domain.esramData.offset = 0x0; - domain.esramData.size = cfgESRAMDmaSize * ONE_KB; - err = CM_ENGINE_CreateMemoryDomain(NMF_CORE_CLIENT, - &domain, &dmaDomainId); - if (err != CM_OK) { - pr_err("CM: Create DMA/ESRAM domain failed with error code: %d\n", err); - err = -EAGAIN; - goto out_all; - } - - err = CM_ENGINE_AllocMpcMemory(dmaDomainId, - NMF_CORE_CLIENT, - CM_MM_MPC_ESRAM16, - cfgESRAMDmaSize * ONE_KB / 2, - CM_MM_MPC_ALIGN_NONE, - &dmaMemoryHdl); - if (err != CM_OK) { - pr_err("CM: Alloc DMA in ESRAM domain failed with error code: %d\n", err); - err = -EAGAIN; - goto out_all; - } - } - - if (cfgESRAM_ReserveMCDE) { - t_cm_domain_memory domain = INIT_DOMAIN; - - // Reserve memory used by MCDE - domain.coreId = ARM_CORE_ID; - domain.esramData.offset = (cfgESRAMSize - cfgESRAMMcdeSize) * ONE_KB; - domain.esramData.size = cfgESRAMMcdeSize * ONE_KB; - err = CM_ENGINE_CreateMemoryDomain(NMF_CORE_CLIENT, - &domain, &mcdeDomainId); - if (err != CM_OK) { - pr_err("CM: Create MCDE/ESRAM domain failed with error code: %d\n", err); - err = -EAGAIN; - goto out_all; - } - - err = CM_ENGINE_AllocMpcMemory(mcdeDomainId, - NMF_CORE_CLIENT, - CM_MM_MPC_ESRAM16, - cfgESRAMMcdeSize * ONE_KB / 2, - CM_MM_MPC_ALIGN_NONE, - &mcdeMemoryHdl); - if (err != CM_OK) { - pr_err("CM: Alloc MCDE in ESRAM domain failed with error code: %d\n", err); - err = -EAGAIN; - goto out_all; - } - } +#ifdef CONFIG_DEBUG_FS + cm_debug_init(); +#endif /* Configure MPC Cores */ for (i=0; i #include - +#include #include "osal-kernel.h" /* Per-driver environment */ @@ -20,28 +20,28 @@ struct OsalEnvironment osalEnv = { .mpc = { { - .coreId = SVA_CORE_ID, - .name = "sva", - .baseP = (void*)SVA_BASE_ADDR, - .interrupt0 = IRQ_DB8500_SVA, - .interrupt1 = IRQ_DB8500_SVA2, + .coreId = SVA_CORE_ID, + .name = "sva", + .base_phys = (void*)U8500_SVA_BASE, + .interrupt0 = IRQ_DB8500_SVA, + .interrupt1 = IRQ_DB8500_SVA2, .mmdsp_regulator = NULL, .pipe_regulator = NULL, .monitor_tsk = NULL, - .hwmemCode = NULL, - .hwmemData = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, }, { - .coreId = SIA_CORE_ID, - .name = "sia", - .baseP = (void*)SIA_BASE_ADDR, - .interrupt0 = IRQ_DB8500_SIA, - .interrupt1 = IRQ_DB8500_SIA2, + .coreId = SIA_CORE_ID, + .name = "sia", + .base_phys = (void*)U8500_SIA_BASE, + .interrupt0 = IRQ_DB8500_SIA, + .interrupt1 = IRQ_DB8500_SIA2, .mmdsp_regulator = NULL, .pipe_regulator = NULL, .monitor_tsk = NULL, - .hwmemCode = NULL, - .hwmemData = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, } }, .esram_regulator = { NULL, NULL}, @@ -79,11 +79,11 @@ DECLARE_MPC_PARAM(SVA, SDRAM_DATA_SIZE, "", 1); DECLARE_MPC_PARAM(SIA, 0, "\n\t\t\t(0 means shared with SVA)", 2); -int cfgCommunicationLocationInSDRAM = 1; +bool cfgCommunicationLocationInSDRAM = true; module_param(cfgCommunicationLocationInSDRAM, bool, S_IRUGO); MODULE_PARM_DESC(cfgCommunicationLocationInSDRAM, "Location of communications (SDRAM or ESRAM)"); -int cfgSemaphoreTypeHSEM = 1; +bool cfgSemaphoreTypeHSEM = true; module_param(cfgSemaphoreTypeHSEM, bool, S_IRUGO); MODULE_PARM_DESC(cfgSemaphoreTypeHSEM, "Semaphore used (HSEM or LSEM)"); @@ -91,6 +91,28 @@ int cfgESRAMSize = ESRAM_SIZE; module_param(cfgESRAMSize, uint, S_IRUGO); MODULE_PARM_DESC(cfgESRAMSize, "Size of ESRAM used in the CM (in Kb)"); +static int set_param_powerMode(const char *val, struct kernel_param *kp) +{ + /* No equals means "set"... */ + if (!val) val = "1"; + + /* One of =[yYnN01] */ + switch (val[0]) { + case 'y': case 'Y': case '1': + CM_ENGINE_SetMode(CM_CMD_DBG_MODE, 0); + break; + case 'n': case 'N': case '0': + CM_ENGINE_SetMode(CM_CMD_DBG_MODE, 1); + break; + default: + return -EINVAL; + } + return 0; +} + +module_param_call(powerMode, set_param_powerMode, param_get_bool, &powerMode, S_IWUSR|S_IRUGO); +MODULE_PARM_DESC(powerMode, "DSP power mode enable"); + int init_config(void) { if (cfgMpcSDRAMCodeSize_SVA == 0 || cfgMpcSDRAMCodeSize_SIA == 0) { @@ -102,14 +124,16 @@ int init_config(void) pr_err("SDRAM data size for SVA must be greater than 0\n"); return -EINVAL; } - osalEnv.mpc[SVA].nbYramBanks = cfgMpcYBanks_SVA; - osalEnv.mpc[SVA].eeId = cfgSchedulerTypeHybrid_SVA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; - osalEnv.mpc[SVA].sdramCodeSize = cfgMpcSDRAMCodeSize_SVA * ONE_KB; - osalEnv.mpc[SVA].sdramDataSize = cfgMpcSDRAMDataSize_SVA * ONE_KB; - osalEnv.mpc[SIA].nbYramBanks = cfgMpcYBanks_SIA; - osalEnv.mpc[SIA].eeId = cfgSchedulerTypeHybrid_SIA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; - osalEnv.mpc[SIA].sdramCodeSize = cfgMpcSDRAMCodeSize_SIA * ONE_KB; - osalEnv.mpc[SIA].sdramDataSize = cfgMpcSDRAMDataSize_SIA * ONE_KB; + osalEnv.mpc[SVA].nbYramBanks = cfgMpcYBanks_SVA; + osalEnv.mpc[SVA].eeId = cfgSchedulerTypeHybrid_SVA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; + osalEnv.mpc[SVA].sdram_code.size = cfgMpcSDRAMCodeSize_SVA * ONE_KB; + osalEnv.mpc[SVA].sdram_data.size = cfgMpcSDRAMDataSize_SVA * ONE_KB; + osalEnv.mpc[SVA].base.size = 128*ONE_KB; //we expose only TCM24 + osalEnv.mpc[SIA].nbYramBanks = cfgMpcYBanks_SIA; + osalEnv.mpc[SIA].eeId = cfgSchedulerTypeHybrid_SIA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; + osalEnv.mpc[SIA].sdram_code.size = cfgMpcSDRAMCodeSize_SIA * ONE_KB; + osalEnv.mpc[SIA].sdram_data.size = cfgMpcSDRAMDataSize_SIA * ONE_KB; + osalEnv.mpc[SIA].base.size = 128*ONE_KB; //we expose only TCM24 return 0; } diff --git a/drivers/staging/nmf-cm/configuration.h b/drivers/staging/nmf-cm/configuration.h index a3bc1ca9063..8f1b88bc23f 100644 --- a/drivers/staging/nmf-cm/configuration.h +++ b/drivers/staging/nmf-cm/configuration.h @@ -21,11 +21,6 @@ /** Nomadik embedded Static RAM base address*/ #define ESRAM_BASE (U8500_ESRAM_BASE + 0x10000) // V1/V2 config: 0-64k: secure; -#define HWSEM_BASE U8500_HSEM_BASE - -/** SxA base address */ -#define SVA_BASE_ADDR U8500_SVA_BASE -#define SIA_BASE_ADDR U8500_SIA_BASE /** Nomadik embedded ram size for CM (in Kb) */ #define ESRAM_SIZE 576 @@ -48,8 +43,8 @@ enum { #define SDRAM_CODE_SIZE_SIA (2*ONE_KB) #define SDRAM_DATA_SIZE (8*ONE_KB) -extern int cfgCommunicationLocationInSDRAM; -extern int cfgSemaphoreTypeHSEM; +extern bool cfgCommunicationLocationInSDRAM; +extern bool cfgSemaphoreTypeHSEM; extern int cfgESRAMSize; int init_config(void); diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index 86e28626498..b095eb883f4 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (113)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (114)) /*! * \brief Get NMF major version corresponding to NMF version number diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 37e680a87a4..12a88923f50 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -27,6 +27,7 @@ #include "osal-kernel.h" #include "cm_service.h" #include "cmld.h" +#include "cm_debug.h" #include "cm_dma.h" __iomem void *prcmu_base = NULL; @@ -68,15 +69,15 @@ int remapRegions(void) /* Remap DSP base areas */ for (i=0; iesramDesc.systemAddr.logical = (t_cm_logical_address)osalEnv.esram_base; nmfHwMappingDesc->esramDesc.size = cfgESRAMSize*ONE_KB; - nmfHwMappingDesc->hwSemaphoresMappingBaseAddr.physical = HWSEM_BASE; + nmfHwMappingDesc->hwSemaphoresMappingBaseAddr.physical = U8500_HSEM_BASE; nmfHwMappingDesc->hwSemaphoresMappingBaseAddr.logical = (t_cm_logical_address)osalEnv.hwsem_base; return 0; @@ -230,8 +231,8 @@ int getNmfHwMappingDesc(t_nmf_hw_mapping_desc* nmfHwMappingDesc) */ void getMpcSystemAddress(unsigned i, t_cm_system_address* mpcSystemAddress) { - mpcSystemAddress->physical = (t_cm_physical_address)osalEnv.mpc[i].baseP; - mpcSystemAddress->logical = (t_cm_logical_address)osalEnv.mpc[i].baseL; + mpcSystemAddress->physical = (t_cm_physical_address)osalEnv.mpc[i].base_phys; + mpcSystemAddress->logical = (t_cm_logical_address)osalEnv.mpc[i].base.data; } @@ -245,13 +246,13 @@ void getMpcSystemAddress(unsigned i, t_cm_system_address* mpcSystemAddress) */ void getMpcSdramSegments(unsigned i, t_nmf_memory_segment* codeSegment, t_nmf_memory_segment* dataSegment) { - codeSegment->systemAddr.logical = (t_cm_logical_address)osalEnv.mpc[i].sdramCodeL; - codeSegment->systemAddr.physical = osalEnv.mpc[i].sdramCodeP; - codeSegment->size = osalEnv.mpc[i].sdramCodeSize; + codeSegment->systemAddr.logical = (t_cm_logical_address)osalEnv.mpc[i].sdram_code.data; + codeSegment->systemAddr.physical = osalEnv.mpc[i].sdram_code_phys; + codeSegment->size = osalEnv.mpc[i].sdram_code.size; - dataSegment->systemAddr.logical = (t_cm_logical_address)osalEnv.mpc[i].sdramDataL; - dataSegment->systemAddr.physical = osalEnv.mpc[i].sdramDataP; - dataSegment->size = osalEnv.mpc[i].sdramDataSize; + dataSegment->systemAddr.logical = (t_cm_logical_address)osalEnv.mpc[i].sdram_data.data; + dataSegment->systemAddr.physical = osalEnv.mpc[i].sdram_data_phys; + dataSegment->size = osalEnv.mpc[i].sdram_data.size; } #ifdef CM_DEBUG_ALLOC @@ -735,11 +736,21 @@ static int dspload_monitor(void *idx) timer.data = (unsigned long)current; init_timer_deferrable(&timer); +#ifdef CONFIG_DEBUG_FS + mpc->opp_request = current_opp_request; +#endif if (prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char*)mpc->name, current_opp_request)) pr_err("CM Driver: Add QoS failed\n"); + /* + * Wait for 500ms before initializing the counter, + * to let the DSP boot (init of counter will failed if + * DSP is not booted). + */ + schedule_timeout_uninterruptible(msecs_to_jiffies(500)); + /* init counter */ if (CM_GetMpcLoadCounter(mpc->coreId, &mpc->oldLoadCounter) != CM_OK) @@ -768,6 +779,9 @@ static int dspload_monitor(void *idx) &loadCounter) != CM_OK) loadCounter = mpc->oldLoadCounter; +#ifdef CONFIG_DEBUG_FS + mpc->load = +#endif load = computeDspLoad(&mpc->oldLoadCounter, &loadCounter); mpc->oldLoadCounter = loadCounter; @@ -776,6 +790,9 @@ static int dspload_monitor(void *idx) /* check if we must request more opp */ if ((current_opp_request == HALF_OPP) && (load > dspLoadHighThreshold)) { +#ifdef CONFIG_DEBUG_FS + mpc->opp_request = +#endif current_opp_request = FULL_OPP; if (cm_debug_level) pr_info("CM Driver: Request QoS OPP %d for %s\n", @@ -787,6 +804,9 @@ static int dspload_monitor(void *idx) /* check if we can request less opp */ else if ((current_opp_request == FULL_OPP) && (load < dspLoadLowThreshold)) { +#ifdef CONFIG_DEBUG_FS + mpc->opp_request = +#endif current_opp_request = HALF_OPP; if (cm_debug_level) pr_info("CM Driver: Request QoS OPP %d for %s\n", @@ -797,6 +817,9 @@ static int dspload_monitor(void *idx) } } +#ifdef CONFIG_DEBUG_FS + mpc->opp_request = mpc->load = 0; +#endif del_singleshot_timer_sync(&timer); if (cm_debug_level) pr_info("CM Driver: Remove QoS OPP for %s\n", mpc->name); @@ -805,7 +828,7 @@ static int dspload_monitor(void *idx) return 0; } -static int enable_auto_pm = 0; +static int enable_auto_pm = 1; module_param(enable_auto_pm, bool, S_IWUSR|S_IRUGO); /** \ingroup OSAL_IMPLEMENTATION @@ -824,6 +847,9 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam return; } +#ifdef CONFIG_DEBUG_FS + cm_debug_destroy_tcm_file(idx); +#endif /* Stop the DSP load monitoring */ clear_bit(idx, &running_dsp); if (osalEnv.mpc[idx].monitor_tsk) { @@ -959,6 +985,9 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first "thread: %ld\n", PTR_ERR(osalEnv.mpc[idx].monitor_tsk)); osalEnv.mpc[idx].monitor_tsk = NULL; } +#ifdef CONFIG_DEBUG_FS + cm_debug_create_tcm_file(idx); +#endif break; } case CM_OSAL_POWER_SxA_AUTOIDLE: @@ -1069,25 +1098,25 @@ void OSAL_CleanDCache(t_uint32 startAddr, t_uint32 size) struct mpcConfig *mpc; t_uint32 endAddr = startAddr + size; - if (startAddr >= (u32)osalEnv.mpc[0].sdramCodeL - && endAddr <= (u32)(osalEnv.mpc[0].sdramCodeL - + osalEnv.mpc[0].sdramCodeSize)) { + if (startAddr >= (u32)osalEnv.mpc[0].sdram_code.data + && endAddr <= (u32)(osalEnv.mpc[0].sdram_code.data + + osalEnv.mpc[0].sdram_code.size)) { mpc = &osalEnv.mpc[0]; - } else if (startAddr >= (u32)osalEnv.mpc[1].sdramCodeL - && endAddr <= (u32)(osalEnv.mpc[1].sdramCodeL - + osalEnv.mpc[1].sdramCodeSize)) { + } else if (startAddr >= (u32)osalEnv.mpc[1].sdram_code.data + && endAddr <= (u32)(osalEnv.mpc[1].sdram_code.data + + osalEnv.mpc[1].sdram_code.size)) { mpc = &osalEnv.mpc[1]; } else { /* The code may be in esram, in that case, nothing to do */ return; } - region.offset = startAddr - (u32)mpc->sdramCodeL; + region.offset = startAddr - (u32)mpc->sdram_code.data; region.count = 1; region.start = 0; region.end = size; region.size = size; - hwmem_set_domain(mpc->hwmemCode, HWMEM_ACCESS_READ, + hwmem_set_domain(mpc->hwmem_code, HWMEM_ACCESS_READ, HWMEM_DOMAIN_SYNC, ®ion); /* * The hwmem keep track of region being sync or not. @@ -1095,7 +1124,7 @@ void OSAL_CleanDCache(t_uint32 startAddr, t_uint32 size) * to let following clean being done as expected. Today, * there is no other place to do that in CM Core right now */ - hwmem_set_domain(mpc->hwmemCode, HWMEM_ACCESS_WRITE, + hwmem_set_domain(mpc->hwmem_code, HWMEM_ACCESS_WRITE, HWMEM_DOMAIN_CPU, ®ion); #else dsb(); diff --git a/drivers/staging/nmf-cm/osal-kernel.h b/drivers/staging/nmf-cm/osal-kernel.h index 36baf893fcc..7a3834fec59 100644 --- a/drivers/staging/nmf-cm/osal-kernel.h +++ b/drivers/staging/nmf-cm/osal-kernel.h @@ -7,6 +7,7 @@ #ifndef OSAL_KERNEL_H #define OSAL_KERNEL_H +#include #include #include #include @@ -17,37 +18,55 @@ #include #include #include +/* + * Do not include ELF definition from cm/engine/elf/inc/elfapi.h file + * because it conflicts with definition from linux/elf.h file + */ +#define _CM_ELF_H #include #include #include "configuration.h" -/** Per-MPC configuration structure */ +/* + * Per-MPC configuration structure + * Use struct debugfs_blob_wrapper to store pointer and size of section + * to allow easy re-use of data through debugfs + */ struct mpcConfig { - const t_nmf_core_id coreId; /**< MPC coreId */ - const char *name; /**< MPC name */ - t_uint8 nbYramBanks; /**< number of TCM ram banks to reserve for y memory */ - t_nmf_executive_engine_id eeId; /**< Type of Executive Engine */ - const void *baseP; /**< Physical base address of the MPC */ - void *baseL; /**< Remapped base address of the MPC */ - struct hwmem_alloc *hwmemCode; /**< hwmem code segment */ - u32 sdramCodeP; /**< Physical base address for MPC SDRAM Code region */ - void *sdramCodeL; /**< Remapped base address for MPC SDRAM Code region */ - size_t sdramCodeSize; /**< Size of MPC SDRAM Code region */ - struct hwmem_alloc *hwmemData; /**< hwmem data segment */ - u32 sdramDataP; /**< Physical base address for MPC SDRAM Data region */ - void *sdramDataL; /**< Remapped base address for MPC SDRAM Data region */ - size_t sdramDataSize; /**< Size of MPC SDRAM Data region */ - const unsigned int interrupt0; /**< interrupt line triggered by the MPC, for MPC events (if HSEM not used) */ - const unsigned int interrupt1; /**< interrupt line triggered by the MPC, for PANIC events */ - struct tasklet_struct tasklet; /**< taskket used to process MPC events */ + const t_nmf_core_id coreId; /**< MPC coreId */ + const char *name; /**< MPC name */ + t_uint8 nbYramBanks; /**< number of TCM ram banks to reserve for y memory */ + t_nmf_executive_engine_id eeId; /**< Type of Executive Engine */ + const void *base_phys; /**< Physical base address of the MPC */ + struct debugfs_blob_wrapper base;/**< Remapped base address of the MPC and size of TCM24 */ + struct hwmem_alloc *hwmem_code; /**< hwmem code segment */ + u32 sdram_code_phys; /**< Physical base address for MPC SDRAM Code region */ + struct debugfs_blob_wrapper sdram_code; /**< Remapped base address and size for MPC SDRAM Code */ + struct hwmem_alloc *hwmem_data; /**< hwmem data segment */ + u32 sdram_data_phys; /**< Physical base address for MPC SDRAM Data region */ + struct debugfs_blob_wrapper sdram_data; /**< Remapped base address and size for MPC SDRAM Data */ + const unsigned int interrupt0; /**< interrupt line triggered by the MPC, for MPC events (if HSEM not used) */ + const unsigned int interrupt1; /**< interrupt line triggered by the MPC, for PANIC events */ + struct tasklet_struct tasklet; /**< taskket used to process MPC events */ struct regulator *mmdsp_regulator; /**< mmdsp regulator linked to this MPC */ struct regulator *pipe_regulator; /**< hardware pipe linked to this MPC */ #ifdef CONFIG_HAS_WAKELOCK - struct wake_lock wakelock; /**< wakelock for this MPC to prevent ARM to go in APSLEEP state */ + struct wake_lock wakelock; /**< wakelock for this MPC to prevent ARM to go in APSLEEP state */ #endif - struct task_struct *monitor_tsk;/**< task to monitor the dsp load; */ + struct task_struct *monitor_tsk; /**< task to monitor the dsp load; */ t_cm_mpc_load_counter oldLoadCounter; /**< previous load counter of the DSP */ +#ifdef CONFIG_DEBUG_FS + struct dentry *dir; /**< debugfs dir entry */ + struct dentry *comp_dir; /**< debugfs component dir entry */ + struct dentry *domain_dir; /**< debugfs domain dir entry */ + struct dentry *snapshot_dir; /**< debugfs snapshot dir entry */ + struct dentry *mem_file; /**< debugfs meminfo file entry */ + struct dentry *tcm_file; /**< debugfs meminfo file entry */ + struct dentry *esram_file; /**< debugfs meminfo file entry */ + s8 load; /**< current load of the DSP */ + s8 opp_request; /**< current requested opp of the DSP */ +#endif }; /** Describes current Kernel OSAL environment @@ -63,8 +82,8 @@ struct mpcConfig { struct OsalEnvironment { struct mpcConfig mpc[NB_MPC]; - void* hwsem_base; /** < Remapped base address of the hardware semaphores */ - void* esram_base; /** < Remapped base address for embedded RAM used within the CM */ + void* hwsem_base; /** < Remapped base address of the hardware semaphores */ + void* esram_base; /**< Remapped base address embedded RAM used within the CM */ struct regulator *esram_regulator[NB_ESRAM]; /**< regulator for ESRAM bank 1+2 and 3+4 */ struct prcmu_auto_pm_config dsp_sleep; struct prcmu_auto_pm_config dsp_idle; -- cgit v1.2.3 From 03bea25a71792646dd3d7b2a6b90f3672749eeaf Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Wed, 24 Aug 2011 16:00:42 +0200 Subject: U8500 CM: instantiate singleton in default domain Singleton components are components used as shared lib on MMDSP and are allocated in the memory domain given at first instantiation. That domain will thus be seen as busy until all users have released their reference to this singleton component, preventing this domain to be released by its creator, even if it has released his reference. This patch assigns these singletons to a default domain once they are created to avoid this issue. ST-Ericsson ID: 356938 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: Ie5590147624d3cb399469600bbc35359ef741295 --- .../nmf-cm/cm/engine/component/src/instantiater.c | 9 +++++++-- .../staging/nmf-cm/cm/engine/component/src/loader.c | 2 +- drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h | 6 ++++-- drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c | 16 +++++++++++----- .../staging/nmf-cm/cm/engine/memory/inc/domain.h | 8 ++++++++ .../nmf-cm/cm/engine/memory/inc/domain_type.h | 1 - .../nmf-cm/cm/engine/memory/inc/remote_allocator.h | 11 +++++++++++ .../staging/nmf-cm/cm/engine/memory/src/domain.c | 21 +++++++++++++++++++++ .../nmf-cm/cm/engine/memory/src/remote_allocator.c | 5 +++++ drivers/staging/nmf-cm/cm_debug.c | 5 +---- drivers/staging/nmf-cm/cmld.c | 4 ++++ 11 files changed, 73 insertions(+), 15 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c index 2a61d4a7433..b7b42802cea 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c @@ -278,7 +278,7 @@ t_cm_error cm_instantiateComponent(const char* templateName, LOG_INTERNAL(1, "\n##### Instantiate %s/%x (%s) component on %s at priority %d #####\n", component->pathname, component, template->name, cm_getDspName(coreId), priority, 0); - if((error = cm_ELF_LoadInstance(domainId, elfhandle, template->memories, component->memories)) != CM_OK) + if((error = cm_ELF_LoadInstance(domainId, elfhandle, template->memories, component->memories, template->classe == SINGLETON)) != CM_OK) { cm_DestroyComponentMemory(component); return error; @@ -298,7 +298,6 @@ t_cm_error cm_instantiateComponent(const char* templateName, /* * Create a new component instance */ - component->domainId = domainId; component->priority = priority; component->thisAddress = 0xFFFFFFFF; component->state = STATE_NONE; @@ -314,6 +313,12 @@ t_cm_error cm_instantiateComponent(const char* templateName, cl->numberOfInstance = 1; template->singletonIfAvaliable = component; + if (cm_DM_GetDomainCoreId(domainId) == SVA_CORE_ID) + component->domainId = DEFAULT_SVA_DOMAIN; + else + component->domainId = DEFAULT_SIA_DOMAIN; + } else { + component->domainId = domainId; } if(component->memories[template->thisMemory->id] != INVALID_MEMORY_HANDLE) diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/loader.c b/drivers/staging/nmf-cm/cm/engine/component/src/loader.c index ad6af00f5a5..a128b7aa8c7 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/loader.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/loader.c @@ -226,7 +226,7 @@ t_cm_error cm_loadComponent( * Load shared memory from file */ // START(); - if((error = cm_ELF_LoadTemplate(domainId, elfhandle, template->memories)) != CM_OK) + if((error = cm_ELF_LoadTemplate(domainId, elfhandle, template->memories, template->classe == SINGLETON)) != CM_OK) goto out; MMDSP_serializeMemories(elfhandle->instanceProperty, &template->codeMemory, &template->thisMemory); // END("cm_ELF_LoadTemplate"); diff --git a/drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h b/drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h index 564086db26c..cce6d158b4e 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h +++ b/drivers/staging/nmf-cm/cm/engine/elf/inc/elfapi.h @@ -48,7 +48,8 @@ void cm_ELF_CloseFile( t_cm_error cm_ELF_LoadTemplate( t_cm_domain_id domainId, t_elfdescription *elfhandle, - t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]); + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_bool isSingleton); /*! * \internal @@ -73,7 +74,8 @@ t_cm_error cm_ELF_LoadInstance( t_cm_domain_id domainId, t_elfdescription *elfhandle, t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], - t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]); + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY], + t_bool isSingleton); void cm_ELF_FreeInstance( t_nmf_core_id coreId, diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c index 84f841ef443..7950cd99007 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c @@ -574,7 +574,8 @@ static t_cm_error allocSegment( t_cm_domain_id domainId, t_elfdescription *elfhandle, t_memory_handle memories[NUMBER_OF_MMDSP_MEMORY], - t_memory_property property) { + t_memory_property property, + t_bool isSingleton) { t_memory_id memId; const t_elfmemory *thisMemory; //!< Memory used to determine this const t_elfmemory *codeMemory; //!< Memory used to determine code @@ -610,6 +611,9 @@ static t_cm_error allocSegment( cm_DSP_GetDspAddress(memories[memId], &elfhandle->segments[memId].mpcAddr); + if (isSingleton) + cm_DM_SetDefaultDomain(memories[memId], cm_DM_GetDomainCoreId(domainId)); + // Log it LOG_INTERNAL(1, "\t%s%s: 0x%x..+0x%x (0x%x)\n", mapping->memoryName, @@ -639,11 +643,12 @@ static t_cm_error allocSegment( t_cm_error cm_ELF_LoadTemplate( t_cm_domain_id domainId, t_elfdescription *elfhandle, - t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY]) + t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], + t_bool isSingleton) { t_cm_error error; - if((error = allocSegment(domainId, elfhandle, sharedMemories, MEM_SHARABLE)) != CM_OK) + if((error = allocSegment(domainId, elfhandle, sharedMemories, MEM_SHARABLE, isSingleton)) != CM_OK) return error; // Load each readonly segment @@ -657,7 +662,8 @@ t_cm_error cm_ELF_LoadInstance( t_cm_domain_id domainId, t_elfdescription *elfhandle, t_memory_handle sharedMemories[NUMBER_OF_MMDSP_MEMORY], - t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY]) + t_memory_handle privateMemories[NUMBER_OF_MMDSP_MEMORY], + t_bool isSingleton) { t_memory_id memId; t_cm_error error; @@ -668,7 +674,7 @@ t_cm_error cm_ELF_LoadInstance( privateMemories[memId] = sharedMemories[memId]; } - if((error = allocSegment(domainId, elfhandle, privateMemories, MEM_PRIVATE)) != CM_OK) + if((error = allocSegment(domainId, elfhandle, privateMemories, MEM_PRIVATE, isSingleton)) != CM_OK) return error; // Load each writable memory diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h index 07caee2d8c1..c9b39956c63 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain.h @@ -20,6 +20,10 @@ #include #include +/* These default domains are used for singleton only ! */ +#define DEFAULT_SVA_DOMAIN (t_cm_domain_id)1 +#define DEFAULT_SIA_DOMAIN (t_cm_domain_id)2 + /*! * \brief Domain type. * \internal @@ -152,4 +156,8 @@ PUBLIC t_cm_error cm_DM_GetAllocatorStatus(t_cm_domain_id domainId, t_dsp_memory PUBLIC t_cm_error cm_DM_GetDomainAbsAdresses(t_cm_domain_id domainId, t_cm_domain_info *info); +/*! + * \brief Change the domain for the given allocated chunk + */ +PUBLIC void cm_DM_SetDefaultDomain(t_memory_handle memHandle, t_nmf_core_id coreId); #endif /* DOMAIN_H_ */ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h index 712d077d894..7463f82eb89 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h @@ -33,7 +33,6 @@ typedef t_uint8 t_cm_domain_id; * \ingroup CM_DOMAIN_API */ typedef t_uint32 t_nmf_client_id; -// TO BE REMOVED LATER, I guess, when default domains will be removed (PP) #define NMF_CORE_CLIENT (t_nmf_client_id)-1 #define NMF_CURRENT_CLIENT (t_nmf_client_id)0 diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h index f556c6f7056..36994f37daa 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/remote_allocator.h @@ -261,4 +261,15 @@ PUBLIC void cm_MM_GetMemoryHandleUserData(t_memory_handle memHandle, t_uint16 *p */ PUBLIC void cm_MM_DumpMemory(t_cm_allocator_desc* alloc, t_uint32 start, t_uint32 end); +/*! + * \brief Change the domain for the given chunk of memory + * + * \param[in] memHandle The given chunk of memory + * \param[in] domainId The new domain id to set + * + * \retval void + * + * \ingroup MEMORY_INTERNAL + */ +PUBLIC void cm_MM_SetDefaultDomain(t_memory_handle memHandle, t_uint32 domainId); #endif /* _REMOTE_ALLOCATOR_H_*/ diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/domain.c b/drivers/staging/nmf-cm/cm/engine/memory/src/domain.c index 8524183ce19..a605cc475a9 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/src/domain.c +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/domain.c @@ -122,6 +122,20 @@ PUBLIC t_cm_error cm_DM_Init(void) domainDesc[2].client = NMF_CORE_CLIENT; domainDesc[3].client = NMF_CORE_CLIENT; + /* We use domain 1 and 2 for the singleton, only used for components structure */ + domainDesc[DEFAULT_SVA_DOMAIN].type = DOMAIN_NORMAL; + domainDesc[DEFAULT_SVA_DOMAIN].domain.coreId= SVA_CORE_ID; + domainDesc[DEFAULT_SVA_DOMAIN].domain.esramCode.size = (t_uint32)-1; + domainDesc[DEFAULT_SVA_DOMAIN].domain.esramData.size = (t_uint32)-1; + domainDesc[DEFAULT_SVA_DOMAIN].domain.sdramCode.size = (t_uint32)-1; + domainDesc[DEFAULT_SVA_DOMAIN].domain.sdramData.size = (t_uint32)-1; + domainDesc[DEFAULT_SIA_DOMAIN].type = DOMAIN_NORMAL; + domainDesc[DEFAULT_SIA_DOMAIN].domain.coreId= SIA_CORE_ID; + domainDesc[DEFAULT_SIA_DOMAIN].domain.esramCode.size = (t_uint32)-1; + domainDesc[DEFAULT_SIA_DOMAIN].domain.esramData.size = (t_uint32)-1; + domainDesc[DEFAULT_SIA_DOMAIN].domain.sdramCode.size = (t_uint32)-1; + domainDesc[DEFAULT_SIA_DOMAIN].domain.sdramData.size = (t_uint32)-1; + for(i = 0; i < MAX_SCRATCH_DOMAIN_NB; i++) { domainScratchDesc[i].domainId = 0; domainScratchDesc[i].parentId = 0; @@ -585,3 +599,10 @@ static void cm_DM_DomainError(const t_cm_domain_id parentId, const t_nmf_client_ domainDesc[parentId].domain.esramData.offset + domainDesc[parentId].domain.esramData.size); } +PUBLIC void cm_DM_SetDefaultDomain(t_memory_handle memHandle, t_nmf_core_id coreId) +{ + if (coreId == SVA_CORE_ID) + cm_MM_SetDefaultDomain(memHandle, DEFAULT_SVA_DOMAIN); + else if (coreId == SIA_CORE_ID) + cm_MM_SetDefaultDomain(memHandle, DEFAULT_SIA_DOMAIN); +} diff --git a/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c b/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c index ec23e28917c..0d000d37371 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c +++ b/drivers/staging/nmf-cm/cm/engine/memory/src/remote_allocator.c @@ -649,3 +649,8 @@ PUBLIC void cm_MM_DumpMemory(t_cm_allocator_desc* alloc, t_uint32 start, t_uint3 chunk = chunk->next; } } + +PUBLIC void cm_MM_SetDefaultDomain(t_memory_handle memHandle, t_uint32 domainId) +{ + ((t_cm_chunk *) memHandle)->domainId = domainId; +} diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c index bf3fa422208..78552c9ce67 100644 --- a/drivers/staging/nmf-cm/cm_debug.c +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -194,8 +194,7 @@ static ssize_t domain_read(struct file *file, char __user *userbuf, int ret=0; OSAL_LOCK_API(); - if ((cm_DM_CheckDomain(id, DOMAIN_ANY) == CM_OK) - && (domain->domain.coreId != -1) + if ((domain->domain.coreId != -1) && (domain->dbgCooky != NULL)) { t_cm_allocator_status status; t_uint32 dOffset; @@ -822,8 +821,6 @@ void cm_debug_init(void) debugfs_create_u8("requested_opp", S_IRUSR|S_IRGRP, osalEnv.mpc[i].dir, &osalEnv.mpc[i].opp_request); - - } } osal_debug_ops.component_create = cm_debug_component_create; diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index f8fe0d41059..4c754c55b72 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -1163,6 +1163,10 @@ static int __init cmld_init_module(void) #ifdef CONFIG_DEBUG_FS cm_debug_init(); + if (osal_debug_ops.domain_create) { + osal_debug_ops.domain_create(DEFAULT_SVA_DOMAIN); + osal_debug_ops.domain_create(DEFAULT_SIA_DOMAIN); + } #endif /* Configure MPC Cores */ -- cgit v1.2.3 From d312fc107db52f15908d173a0b6638be57b9a431 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Fri, 26 Aug 2011 13:03:09 +0200 Subject: U8500 CM: Fix issue in component-preload mechanism An address must not been assigned to preloaded component, but only with template ST-Ericsson ID: 358497 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: I13a30973c27d757b48e35bf3f7f78b880ee3027a --- .../nmf-cm/cm/engine/component/inc/description.h | 1 - .../nmf-cm/cm/engine/component/inc/template.h | 21 ++++++++ .../nmf-cm/cm/engine/component/src/binder.c | 15 +++--- .../nmf-cm/cm/engine/component/src/initializer.c | 4 +- .../nmf-cm/cm/engine/component/src/introspection.c | 4 +- .../nmf-cm/cm/engine/component/src/loader.c | 63 ++++++++++++++++++---- drivers/staging/nmf-cm/cm/engine/trace/src/trace.c | 3 +- 7 files changed, 91 insertions(+), 20 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/description.h b/drivers/staging/nmf-cm/cm/engine/component/inc/description.h index 9a03ac5d2f7..882dc1ea873 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/inc/description.h +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/description.h @@ -65,7 +65,6 @@ typedef struct { * \ingroup COMPONENT_INTERNAL */ typedef struct { - t_uint32 methodAddresses; //!< Address of each method ; Available only when template loaded t_memory_reference memory; //!< Memory of the method } t_interface_provide_index; diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/template.h b/drivers/staging/nmf-cm/cm/engine/component/inc/template.h index 3e1a2c001e4..2718d8ae9fb 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/inc/template.h +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/template.h @@ -43,6 +43,25 @@ typedef struct _t_function_relocation { struct t_component_instance; +/*! + * \internal + * \brief Description of a provided interface method on a collection index ; Available only when template loaded + * \ingroup COMPONENT_INTERNAL + */ +typedef struct { + t_uint32 methodAddresses; //!< Address of each method +} t_interface_provide_index_loaded; + +/*! + * \internal + * \brief Description of a provided interface ; Available only when template loaded + * \ingroup COMPONENT_INTERNAL + */ +typedef struct { + t_interface_provide_index_loaded **indexesLoaded; //!< Provide information for each collection index +} t_interface_provide_loaded; + + /*! * \internal * \brief Description of a component template @@ -80,6 +99,8 @@ typedef struct _t_component_template { t_interface_provide *provides; //!< Array of interface provided by this template t_interface_require *requires; //!< Array of interface required by this template + t_interface_provide_loaded *providesLoaded; //!< Array of interface provided by this template ; Available when loaded + t_bool descriptionAssociatedWithTemplate; struct _t_component_template *prev, *next; diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/binder.c b/drivers/staging/nmf-cm/cm/engine/component/src/binder.c index e82828f012b..5f08713833b 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/binder.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/binder.c @@ -78,6 +78,7 @@ static void cm_bindLowLevelInterface( t_component_instance* server = (t_component_instance*)itfLocalBC->server; t_interface_require *require = &client->Template->requires[itfRequire->requireIndex]; t_interface_provide* provide = &server->Template->provides[itfLocalBC->provideIndex]; + t_interface_provide_loaded* provideLoaded = &server->Template->providesLoaded[itfLocalBC->provideIndex]; int k, j; if(require->indexes != NULL) @@ -113,7 +114,7 @@ static void cm_bindLowLevelInterface( // We are 64word byte aligned, combine this write with first method *(volatile t_uint64*)hostAddr = ((t_uint64)server->thisAddress << 0) | - ((t_uint64)provide->indexes[itfLocalBC->collectionIndex][0].methodAddresses << 32); + ((t_uint64)provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][0].methodAddresses << 32); hostAddr += 2; j = 1; } @@ -127,14 +128,14 @@ static void cm_bindLowLevelInterface( // Word align copy for(; j < require->interface->methodNumber - 1; j+=2) { *(volatile t_uint64*)hostAddr = - ((t_uint64)provide->indexes[itfLocalBC->collectionIndex][j].methodAddresses << 0) | - ((t_uint64)provide->indexes[itfLocalBC->collectionIndex][j+1].methodAddresses << 32); + ((t_uint64)provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j].methodAddresses << 0) | + ((t_uint64)provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j+1].methodAddresses << 32); hostAddr += 2; } // Last word align if required if(j < require->interface->methodNumber) - *hostAddr = provide->indexes[itfLocalBC->collectionIndex][j].methodAddresses; + *hostAddr = provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j].methodAddresses; } } else @@ -147,7 +148,7 @@ static void cm_bindLowLevelInterface( cm_ELF_performRelocation( reloc->type, reloc->symbol_name, - provide->indexes[itfLocalBC->collectionIndex][j].methodAddresses, + provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j].methodAddresses, reloc->reloc_addr); break; } @@ -773,7 +774,7 @@ t_cm_error cm_bindComponentFromCMCore( fifo_params_setSharedField( (*bfInfo)->fifo, 1+i, - skel->Template->provides[0].indexes[0][i].methodAddresses + skel->Template->providesLoaded[0].indexesLoaded[0][i].methodAddresses ); } } @@ -1043,7 +1044,7 @@ t_cm_error cm_bindInterfaceDistributed( fifo_params_setSharedField( bfInfo->fifo, 1+i, - skel->Template->provides[0].indexes[0][i].methodAddresses + skel->Template->providesLoaded[0].indexesLoaded[0][i].methodAddresses ); } } diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c index 625d0a06796..6950efb76b6 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c @@ -43,6 +43,7 @@ PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId) t_dsp_offset sharedVarOffset; t_interface_provide_description itfProvide; t_interface_provide* provide; + t_interface_provide_loaded* provideLoaded; ee = cm_EEM_getExecutiveEngine(coreId)->instance; @@ -50,6 +51,7 @@ PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId) if((error = cm_getProvidedInterface(ee, "service", &itfProvide)) != CM_OK) return error; provide = &ee->Template->provides[itfProvide.provideIndex]; + provideLoaded = &ee->Template->providesLoaded[itfProvide.provideIndex]; if ((error = dspevent_createDspEventFifo( @@ -114,7 +116,7 @@ PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId) fifo_params_setSharedField( initializerDesc[coreId].downlinkFifo, i + 1, - provide->indexes[itfProvide.collectionIndex][i].methodAddresses); + provideLoaded->indexesLoaded[itfProvide.collectionIndex][i].methodAddresses); } /* DSP->HOST ParamsFifo extended fields initialisation */ diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c b/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c index 3855f97ded8..4aaf8dff889 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c @@ -166,6 +166,7 @@ t_dsp_address cm_getFunction( { t_interface_provide_description itfProvide; t_interface_provide* provide; + t_interface_provide_loaded* provideLoaded; t_cm_error error; int i; @@ -174,12 +175,13 @@ t_dsp_address cm_getFunction( return error; provide = &component->Template->provides[itfProvide.provideIndex]; + provideLoaded = &component->Template->providesLoaded[itfProvide.provideIndex]; for(i = 0; i < provide->interface->methodNumber; i++) { if(cm_StringCompare(provide->interface->methodNames[i], methodName, MAX_INTERFACE_METHOD_NAME_LENGTH) == 0) { - return provide->indexes[itfProvide.collectionIndex][i].methodAddresses; + return provideLoaded->indexesLoaded[itfProvide.collectionIndex][i].methodAddresses; } } diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/loader.c b/drivers/staging/nmf-cm/cm/engine/component/src/loader.c index a128b7aa8c7..3d81e8308f9 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/loader.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/loader.c @@ -111,12 +111,13 @@ t_uint32 cm_resolvSymbol( for(i = 0; i < ee->Template->provideNumber; i++) { t_interface_provide* provide = &ee->Template->provides[i]; + t_interface_provide_loaded* provideLoaded = &ee->Template->providesLoaded[i]; for(j = 0; j < provide->interface->methodNumber; j++) { if(provide->interface->methodNames[j] == symbolName) { - return provide->indexes[0][j].methodAddresses; // Here we assume no collection provided !! + return provideLoaded->indexesLoaded[0][j].methodAddresses; // Here we assume no collection provided !! } } } @@ -244,17 +245,40 @@ t_cm_error cm_loadComponent( template->LCCConstructAddress = cm_EEM_getExecutiveEngine(coreId)->voidAddr; // Compute provide methodIndex - for(i = 0; i < template->provideNumber; i++) + if(template->provideNumber != 0) { - for(j = 0; j < template->provides[i].collectionSize; j++) + template->providesLoaded = + (t_interface_provide_loaded*)OSAL_Alloc_Zero(sizeof(t_interface_provide_loaded) * template->provideNumber); + if(template->providesLoaded == NULL) + goto oom; + + for(i = 0; i < template->provideNumber; i++) { - for(k = 0; k < template->provides[i].interface->methodNumber; k++) - { - template->provides[i].indexes[j][k].methodAddresses = - MemoryToDspAdress(template, &template->provides[i].indexes[j][k].memory); + template->providesLoaded[i].indexesLoaded = (t_interface_provide_index_loaded**)OSAL_Alloc_Zero( + sizeof(t_interface_provide_index_loaded*) * template->provides[i].collectionSize); + if(template->providesLoaded[i].indexesLoaded == NULL) + goto oom; - LOG_INTERNAL(2, " [%d, %d] method '%s' @ %x\n", - j, k, template->provides[i].interface->methodNames[k], template->provides[i].indexes[j][k].methodAddresses, 0, 0); + if(template->provides[i].interface->methodNumber != 0) + { + for(j = 0; j < template->provides[i].collectionSize; j++) + { + template->providesLoaded[i].indexesLoaded[j] = (t_interface_provide_index_loaded*)OSAL_Alloc( + sizeof(t_interface_provide_index_loaded) * template->provides[i].interface->methodNumber); + if(template->providesLoaded[i].indexesLoaded[j] == NULL) + goto oom; + + for(k = 0; k < template->provides[i].interface->methodNumber; k++) + { + template->providesLoaded[i].indexesLoaded[j][k].methodAddresses = + MemoryToDspAdress(template, &template->provides[i].indexes[j][k].memory); + + LOG_INTERNAL(2, " [%d, %d] method '%s' @ %x\n", + j, k, template->provides[i].interface->methodNames[k], + template->providesLoaded[i].indexesLoaded[j][k].methodAddresses, 0, 0); + } + + } } } } @@ -282,6 +306,8 @@ t_cm_error cm_loadComponent( templateAdd(template); return CM_OK; + oom: + error = CM_NO_MORE_MEMORY; out: cm_unloadComponent(template); return error; @@ -317,6 +343,25 @@ PUBLIC t_cm_error cm_unloadComponent( OSAL_Free(tofree); } + if(template->providesLoaded != NULL) + { + int i, j; + + for(i = 0; i < template->provideNumber; i++) + { + if(template->providesLoaded[i].indexesLoaded != NULL) + { + for(j = 0; j < template->provides[i].collectionSize; j++) + { + OSAL_Free(template->providesLoaded[i].indexesLoaded[j]); + } + OSAL_Free(template->providesLoaded[i].indexesLoaded); + } + } + + OSAL_Free(template->providesLoaded); + } + if(template->descriptionAssociatedWithTemplate) { cm_ELF_ReleaseDescription( diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c b/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c index 4620bc0fd07..e27d3284ed2 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/trace.c @@ -96,12 +96,13 @@ void cm_TRC_traceLoadMap( for(i = 0; i < component->Template->provideNumber; i++) { t_interface_provide* provide = &component->Template->provides[i]; + t_interface_provide_loaded* provideLoaded = &component->Template->providesLoaded[i]; for(j = 0; j < provide->collectionSize; j++) { for(k = 0; k < provide->interface->methodNumber; k++) { - tracemethod.methodId = provide->indexes[j][k].methodAddresses; + tracemethod.methodId = provideLoaded->indexesLoaded[j][k].methodAddresses; cm_StringCopy((char*)tracemethod.methodName, provide->interface->methodNames[k], MAX_INTERFACE_METHOD_NAME_LENGTH); -- cgit v1.2.3 From 44a446451bde6f886f923facf15ce527ade4b96a Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Fri, 26 Aug 2011 13:23:25 +0200 Subject: U8500 CM: execute services before detroying component Force MMDSP to have executed all previous services before detroying the components: service construct / start / stop on a component could remain on the pipe when the component is destroyed. ST-Ericsson ID: 358445 ST-Ericsson Linux next: - ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: Icd8c0fe7d567128562599e928b381514e4a71fa8 --- .../nmf-cm/cm/engine/component/inc/initializer.h | 1 + .../nmf-cm/cm/engine/component/src/binder_check.c | 8 +++--- .../nmf-cm/cm/engine/component/src/initializer.c | 32 ++++++++++++++++++++++ .../nmf-cm/cm/engine/component/src/instantiater.c | 4 +++ drivers/staging/nmf-cm/cm_debug.h | 9 ++++++ drivers/staging/nmf-cm/cm_service.c | 4 +-- drivers/staging/nmf-cm/cmld.c | 22 +++++---------- drivers/staging/nmf-cm/cmld.h | 4 +-- drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- drivers/staging/nmf-cm/osal-kernel.c | 6 ++-- 10 files changed, 64 insertions(+), 28 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/initializer.h b/drivers/staging/nmf-cm/cm/engine/component/inc/initializer.h index b4416f3ce20..5ac9ec453b7 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/inc/initializer.h +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/initializer.h @@ -15,6 +15,7 @@ PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId); PUBLIC t_cm_error cm_COMP_CallService(int serviceIndex, t_component_instance *pComp, t_uint32 methodAddress); +PUBLIC void cm_COMP_Flush(t_nmf_core_id coreId); PUBLIC void cm_COMP_INIT_Close(t_nmf_core_id coreId); PUBLIC t_cm_error cm_COMP_UpdateStack(t_nmf_core_id coreId, t_uint32 stackSize); PUBLIC t_cm_error cm_COMP_ULPForceWakeup(t_nmf_core_id coreId); diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c b/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c index 8a3c3c33de8..373fea0cd47 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c @@ -40,10 +40,10 @@ t_cm_error cm_checkValidClient( t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; if(itfRef->instance == (const t_component_instance*)NMF_VOID_COMPONENT) - ERROR("CM_INTERFACE_ALREADY_BINDED(): Component (%s<%s>.s) already bound to VOID\n", + ERROR("CM_INTERFACE_ALREADY_BINDED(): Component (%s<%s>.%s) already bound to VOID\n", client->pathname, client->Template->name, requiredItfClientName, 0, 0, 0); else - ERROR("CM_INTERFACE_ALREADY_BINDED(): Component (%s<%s>.s) already bound to another server (%s<%s>.%s)\n", + ERROR("CM_INTERFACE_ALREADY_BINDED(): Component (%s<%s>.%s) already bound to another server (%s<%s>.%s)\n", client->pathname, client->Template->name, requiredItfClientName, itfRef->instance->pathname, itfRef->instance->Template->name, itfRef->instance->Template->provides[itfRef->provideIndex].name); return CM_INTERFACE_ALREADY_BINDED; @@ -116,7 +116,7 @@ t_cm_error cm_checkValidBinding( { if(itfRef->instance == (const t_component_instance*)NMF_VOID_COMPONENT) { - ERROR("CM_INTERFACE_ALREADY_BINDED(): Singleton (%s<%s>.s) already bound to VOID\n", + ERROR("CM_INTERFACE_ALREADY_BINDED(): Singleton (%s<%s>.%s) already bound to VOID\n", client->pathname, client->Template->name, requiredItfClientName, 0, 0, 0); return CM_INTERFACE_ALREADY_BINDED; } @@ -130,7 +130,7 @@ t_cm_error cm_checkValidBinding( } else { - ERROR("CM_INTERFACE_ALREADY_BINDED(): Singleton (%s<%s>.s) already bound to different server (%s<%s>.%s)\n", + ERROR("CM_INTERFACE_ALREADY_BINDED(): Singleton (%s<%s>.%s) already bound to different server (%s<%s>.%s)\n", client->pathname, client->Template->name, requiredItfClientName, itfRef->instance->pathname, itfRef->instance->Template->name, itfRef->instance->Template->provides[itfRef->provideIndex].name); return CM_INTERFACE_ALREADY_BINDED; diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c index 6950efb76b6..011dfa18398 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c @@ -33,6 +33,7 @@ static struct { t_nmf_fifo_arm_desc* uplinkFifo; t_memory_handle dspfifoHandle; t_nmf_osal_sem_handle fifoSemHandle; + t_uint32 servicePending; // TODO : Use sem counter instead of defining such variable (need to create new OSAL) } initializerDesc[NB_CORE_IDS]; PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId) @@ -63,6 +64,7 @@ PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId) return error; /* create fifo semaphore */ + initializerDesc[coreId].servicePending = 0; initializerDesc[coreId].fifoSemHandle = OSAL_CreateSemaphore(DEFAULT_INITIALIZER_FIFO_SIZE); if (initializerDesc[coreId].fifoSemHandle == 0) { dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle); @@ -158,6 +160,31 @@ PUBLIC t_cm_error cm_COMP_CallService( return error; } +PUBLIC void cm_COMP_Flush(t_nmf_core_id coreId) { + + if(initializerDesc[coreId].servicePending > 0) + { + t_uint16 params[INIT_COMPONENT_CMD_SIZE]; + t_uint32 methodAddress = cm_EEM_getExecutiveEngine(coreId)->voidAddr; + + // If service still pending on MMDSP side, send a flush command (today, we reuse Destroy to not create new empty service) + // When we receive the result, this mean that we have flushed all previous request. + + params[INIT_COMPONENT_CMD_HANDLE_INDEX] = (t_uint16)(0x0 & 0xFFFF); + params[INIT_COMPONENT_CMD_HANDLE_INDEX+1] = (t_uint16)(0x0 >> 16); + params[INIT_COMPONENT_CMD_THIS_INDEX] = (t_uint16)(0x0 & 0xFFFF); + params[INIT_COMPONENT_CMD_THIS_INDEX+1] = (t_uint16)(0x0 >> 16); + params[INIT_COMPONENT_CMD_METHOD_INDEX] = (t_uint16)(methodAddress & 0xFFFF); + params[INIT_COMPONENT_CMD_METHOD_INDEX+1] = (t_uint16)(methodAddress >> 16); + + if (cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_DESTROY_INDEX) != CM_OK || + OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) + { + ERROR("CM_MPC_NOT_RESPONDING: can't call flush service\n", 0, 0, 0, 0, 0, 0); + } + } +} + PUBLIC void cm_COMP_INIT_Close(t_nmf_core_id coreId) { unsigned int i; @@ -187,6 +214,7 @@ PUBLIC void processAsyncAcknowledge(t_nmf_core_id coreId, t_event_params_handle { cm_AcknowledgeEvent(initializerDesc[coreId].uplinkFifo); + initializerDesc[coreId].servicePending--; OSAL_SemaphorePost(initializerDesc[coreId].fifoSemHandle,1); } @@ -194,6 +222,7 @@ PUBLIC void processSyncAcknowledge(t_nmf_core_id coreId, t_event_params_handle p { cm_AcknowledgeEvent(initializerDesc[coreId].uplinkFifo); + initializerDesc[coreId].servicePending--; OSAL_SemaphorePost(initializerDesc[coreId].fifoSemHandle,1); OSAL_SemaphorePost(semHandle,1); } @@ -309,6 +338,7 @@ PRIVATE t_cm_error cm_COMP_generic( if (OSAL_SEMAPHORE_WAIT_TIMEOUT(initializerDesc[coreId].fifoSemHandle) != SYNC_OK) return CM_MPC_NOT_RESPONDING; + // AllocEvent if((_xyuv_data = cm_AllocEvent(initializerDesc[coreId].downlinkFifo)) == NULL) { @@ -325,6 +355,8 @@ PRIVATE t_cm_error cm_COMP_generic( // Send Command error = cm_PushEventTrace(initializerDesc[coreId].downlinkFifo, _xyuv_data, serviceIndex,0); + if(error == CM_OK) + initializerDesc[coreId].servicePending++; unlock: OSAL_UNLOCK_COM(); diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c index b7b42802cea..bd410c9acd9 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c @@ -745,6 +745,10 @@ t_cm_error cm_destroyInstance(t_component_instance* component, t_destroy_state f ERROR("CM_MPC_NOT_RESPONDING: can't call destroy '%s'\n", component->pathname, 0, 0, 0, 0, 0); } } + else + { + cm_COMP_Flush(component->Template->dspId); + } } cm_delayedDestroyComponent(component); diff --git a/drivers/staging/nmf-cm/cm_debug.h b/drivers/staging/nmf-cm/cm_debug.h index 8afb3550c0c..26c80682d11 100644 --- a/drivers/staging/nmf-cm/cm_debug.h +++ b/drivers/staging/nmf-cm/cm_debug.h @@ -15,5 +15,14 @@ void cm_debug_exit(void); void cm_debug_proc_init(struct cm_process_priv *entry); void cm_debug_create_tcm_file(unsigned mpc_index); void cm_debug_destroy_tcm_file(unsigned mpc_index); + +#else + +#define cm_debug_init() +#define cm_debug_exit() +#define cm_debug_proc_init(entry) +#define cm_debug_create_tcm_file(mpc_index) +#define cm_debug_destroy_tcm_file(mpc_index) + #endif /* CONFIG_DEBUG_FS */ #endif /* CM_DEBUG_H */ diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index 06cfbc74146..70cf6f37524 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -56,7 +56,7 @@ void dispatch_service_msg(struct osal_msg *msg) memcpy(new_msg, msg, msg_size); plist_node_init(&new_msg->msg_entry, 0); #ifdef CONFIG_DEBUG_FS - if (user_has_debugfs && dump_flag_to_set + if (cmld_user_has_debugfs && dump_flag_to_set && (new_msg->d.srv.srvType == NMF_SERVICE_PANIC)) { /* * The reciever of this message will do the DSP @@ -65,7 +65,7 @@ void dispatch_service_msg(struct osal_msg *msg) new_msg->d.srv.srvData.panic.panicSource |= DEBUGFS_DUMP_FLAG; dump_flag_to_set = false; - dump_done = false; + cmld_dump_ongoing = true; } #endif spin_lock_bh(&channelPriv->bh_lock); diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 4c754c55b72..9e26955d100 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -28,7 +28,7 @@ #include "cm_service.h" #include "cm_dma.h" -#define CMDRIVER_PATCH_VERSION 112 +#define CMDRIVER_PATCH_VERSION 115 #define O_FLUSH 0x1000000 static int cmld_major; @@ -50,9 +50,9 @@ static DEFINE_MUTEX(channel_lock); /* lock used to protect previous list */ #ifdef CONFIG_DEBUG_FS /* Debugfs support */ -bool user_has_debugfs = false; -bool dump_done = true; -module_param(dump_done, bool, S_IWUSR|S_IRUGO); +bool cmld_user_has_debugfs = false; +bool cmld_dump_ongoing = false; +module_param(cmld_dump_ongoing, bool, S_IWUSR|S_IRUGO); static DECLARE_WAIT_QUEUE_HEAD(dump_waitq); #endif @@ -88,9 +88,7 @@ static inline struct cm_process_priv *getProcessPriv(void) entry->pid = current->tgid; mutex_lock(&process_lock); list_add(&entry->entry, &process_list); -#ifdef CONFIG_DEBUG_FS cm_debug_proc_init(entry); -#endif out: mutex_unlock(&process_lock); return entry; @@ -692,7 +690,7 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long return -ENOENT; case CM_PRIV_DEBUGFS_READY: #ifdef CONFIG_DEBUG_FS - user_has_debugfs = true; + cmld_user_has_debugfs = true; #endif return 0; case CM_PRIV_DEBUGFS_DUMP_DONE: @@ -715,10 +713,10 @@ static long cmld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { #ifdef CONFIG_DEBUG_FS if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { - dump_done = true; + cmld_dump_ongoing = false; wake_up_interruptible(&dump_waitq); return 0; - } else if (wait_event_interruptible(dump_waitq, dump_done)) + } else if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) return -ERESTARTSYS; #endif @@ -1161,13 +1159,11 @@ static int __init cmld_init_module(void) CMDRIVER_PATCH_VERSION); } -#ifdef CONFIG_DEBUG_FS cm_debug_init(); if (osal_debug_ops.domain_create) { osal_debug_ops.domain_create(DEFAULT_SVA_DOMAIN); osal_debug_ops.domain_create(DEFAULT_SIA_DOMAIN); } -#endif /* Configure MPC Cores */ for (i=0; i Date: Mon, 5 Sep 2011 15:05:44 +0530 Subject: NMF CM Build Issue Fixed --- drivers/staging/nmf-cm/cm_debug.c | 1 + drivers/staging/nmf-cm/configuration.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c index 78552c9ce67..cb753ea2593 100644 --- a/drivers/staging/nmf-cm/cm_debug.c +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -5,6 +5,7 @@ */ #include +#include #include "osal-kernel.h" #include "cm_debug.h" diff --git a/drivers/staging/nmf-cm/configuration.c b/drivers/staging/nmf-cm/configuration.c index 898aab94877..b61ab509d94 100644 --- a/drivers/staging/nmf-cm/configuration.c +++ b/drivers/staging/nmf-cm/configuration.c @@ -91,7 +91,7 @@ int cfgESRAMSize = ESRAM_SIZE; module_param(cfgESRAMSize, uint, S_IRUGO); MODULE_PARM_DESC(cfgESRAMSize, "Size of ESRAM used in the CM (in Kb)"); -static int set_param_powerMode(const char *val, struct kernel_param *kp) +static int set_param_powerMode(const char *val, const struct kernel_param *kp) { /* No equals means "set"... */ if (!val) val = "1"; -- cgit v1.2.3 From 7414c9e088dcadd847dedc813e568a2bd4f754c9 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 10:59:29 +0200 Subject: mach-ux500: mmio: Enable Camera PMIC for S5500V2 Board ST-Ericsson Id: 351836 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Nikhil Bhandary Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/30969 Reviewed-by: Srinidhi KASAGAR --- arch/arm/mach-ux500/board-u5500-mmio.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-u5500-mmio.c b/arch/arm/mach-ux500/board-u5500-mmio.c index ca751da16fa..bbf2b4bf949 100644 --- a/arch/arm/mach-ux500/board-u5500-mmio.c +++ b/arch/arm/mach-ux500/board-u5500-mmio.c @@ -40,7 +40,7 @@ struct mmio_board_data{ * Fill names of regulators required for powering up the * camera sensor in below array */ -static char *regulator_names[] = {"v-mmio-camera"}; +static char *regulator_names[] = {"v-mmio-camera", "v-ana"}; static int mmio_clock_init(struct mmio_platform_data *pdata) { @@ -231,6 +231,28 @@ static int mmio_power_enable(struct mmio_platform_data *pdata) goto err_regulator; } } + + err = gpio_request(GPIO_CAMERA_PMIC_EN, "Camera PMIC GPIO"); + if (err) { + dev_err(pdata->dev, "Error %d while requesting" + "Camera PMIC GPIO\n", + err); + return err; + } + + err = gpio_direction_output(GPIO_CAMERA_PMIC_EN, 0); + if (err) { + dev_err(pdata->dev, "Error %d while setting" + "Camera PMIC GPIO" + "output mode\n", err); + return err; + } + + if (!(is_s5500_board())) + gpio_set_value(GPIO_CAMERA_PMIC_EN, 1); + else + gpio_set_value(GPIO_CAMERA_PMIC_EN, 0); + dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); return 0; err_regulator: @@ -251,6 +273,13 @@ static void mmio_power_disable(struct mmio_platform_data *pdata) */ for (i = 0; i < extra->number_of_regulators; i++) regulator_disable(extra->mmio_regulators[i]); + + if (!(is_s5500_board())) + gpio_set_value(GPIO_CAMERA_PMIC_EN, 0); + else + gpio_set_value(GPIO_CAMERA_PMIC_EN, 1); + + gpio_free(GPIO_CAMERA_PMIC_EN); } static int mmio_clock_enable(struct mmio_platform_data *pdata) -- cgit v1.2.3 From 4a229e574d63c884f6a79e977262b397ec4e40e2 Mon Sep 17 00:00:00 2001 From: Rajat Verma Date: Thu, 15 Sep 2011 15:47:34 +0530 Subject: staging: camera_flash: Enable FLASH_MODE_NONE FLASH_MODE_NONE should be enabled by flash clients to put the flash IC in sleep mode, dropping the input current to less that 45 microamperes. ST-Ericsson ID: 361897 ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Rajat Verma Change-Id: I5ff4e409344578043b2f35e19474e215ddde2e44 Signed-off-by: Rajat Verma Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/31744 Reviewed-by: Bibek BASU Tested-by: Bibek BASU --- drivers/staging/camera_flash/adp1653.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/camera_flash/adp1653.c b/drivers/staging/camera_flash/adp1653.c index c97014fc5ad..8264e46a1f2 100644 --- a/drivers/staging/camera_flash/adp1653.c +++ b/drivers/staging/camera_flash/adp1653.c @@ -117,7 +117,8 @@ static int adp1653_enable_flash_mode(void *priv_data, if(enable){ - if(!(mode & ADP1653_SUPPORTED_MODES)){ + if((!(mode & ADP1653_SUPPORTED_MODES)) && + (mode != FLASH_MODE_NONE)) { DEBUG_LOG("Unsupported mode %lx\n",mode); err = -EINVAL; goto out; -- cgit v1.2.3 From ad0ea990e3130779e50cbaf01d0f67f25a4a0992 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 17 Oct 2011 13:07:25 +0200 Subject: ARM: ux500: miltimedia: Replace mach prcmu driver with mainlined version The prcmu driver now exists in drivers/mfd Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32057 --- drivers/staging/mmio/st_mmio.c | 2 +- drivers/staging/nmf-cm/osal-kernel.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/mmio/st_mmio.c b/drivers/staging/mmio/st_mmio.c index c79c2768d19..655f7ce3a93 100644 --- a/drivers/staging/mmio/st_mmio.c +++ b/drivers/staging/mmio/st_mmio.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include "mmio.h" #define ISP_REGION_IO (0xE0000000) diff --git a/drivers/staging/nmf-cm/osal-kernel.h b/drivers/staging/nmf-cm/osal-kernel.h index 7a3834fec59..7a71bdd591d 100644 --- a/drivers/staging/nmf-cm/osal-kernel.h +++ b/drivers/staging/nmf-cm/osal-kernel.h @@ -14,7 +14,7 @@ #ifdef CONFIG_HAS_WAKELOCK #include #endif -#include +#include #include #include #include -- cgit v1.2.3 From cfe9c706e479cdd3cbe3a4447c0898c4141b4ff7 Mon Sep 17 00:00:00 2001 From: Mian Yousaf Kaukab Date: Wed, 21 Sep 2011 11:23:16 +0200 Subject: ux500: mmio: update supply name Regulator supply name update according to the mainline version of regulator framework. Change-Id: I6a20a1a03024880361d1fe3375d978ba00678554 Signed-off-by: Mian Yousaf Kaukab Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32123 Reviewed-by: Jonas ABERG Tested-by: Jonas ABERG --- arch/arm/mach-ux500/board-mop500-mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-mop500-mmio.c b/arch/arm/mach-ux500/board-mop500-mmio.c index 71028bd2f8f..6b93514ebdd 100644 --- a/arch/arm/mach-ux500/board-mop500-mmio.c +++ b/arch/arm/mach-ux500/board-mop500-mmio.c @@ -70,7 +70,7 @@ struct mmio_board_data{ /* Fill names of regulators required for powering up the * camera sensor in below array */ -static char *regulator_names[] = {"v-mmio-camera" , "v-ana"}; +static char *regulator_names[] = {"vaux12v5" , "vddcsi1v2"}; /* This function is used to translate the physical GPIO used for reset GPIO * to logical IPGPIO that needs to be communicated to Firmware. so that -- cgit v1.2.3 From 751eab27ef00d5058111f276f9b0ed2f959bfd89 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Thu, 29 Sep 2011 16:04:42 +0200 Subject: U8500 CM: fix 'make mrproper' issue Fix NMF-CM Makefile to allow a proper run of 'make mrproper' in all cases. ST-Ericsson ID: - ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: - Signed-off-by: Pierre Peiffer Change-Id: I3e03b6ba02b5f8f333b1d494e8ce6076f3da56ff Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32554 Reviewed-by: Pierre PEIFFER Tested-by: Pierre PEIFFER Reviewed-by: Jonas ABERG --- drivers/staging/nmf-cm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/nmf-cm/Makefile b/drivers/staging/nmf-cm/Makefile index 7745132f35e..b1a5b9afe1f 100644 --- a/drivers/staging/nmf-cm/Makefile +++ b/drivers/staging/nmf-cm/Makefile @@ -7,7 +7,7 @@ # # Rules to build kernel modules # -ifdef KERNELRELEASE +ifneq ($(findstring KERNELRELEASE,$(.VARIABLES)),) # $(src): current relative dir; $(kbuild-dir): cur absolute dir ifdef kbuild-dir -- cgit v1.2.3 From b1e221178aa2c7b4801902f330bfc5dfb7089c18 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Wed, 26 Oct 2011 13:44:56 +0200 Subject: staging: nmf-cm: Fix after 3.1 rebase Signed-off-by: Philippe Langlais --- drivers/staging/nmf-cm/cm_dma.c | 1 + drivers/staging/nmf-cm/cmld.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/nmf-cm/cm_dma.c b/drivers/staging/nmf-cm/cm_dma.c index c460728e6a0..d1c99d6af9a 100644 --- a/drivers/staging/nmf-cm/cm_dma.c +++ b/drivers/staging/nmf-cm/cm_dma.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 9e26955d100..d735323c572 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -258,7 +258,7 @@ static int cmld_open(struct inode *inode, struct file *file) /* Initialize wait_queue, lists and mutexes */ init_waitqueue_head(&channelPriv->waitq); - plist_head_init(&channelPriv->messageQueue, &channelPriv->bh_lock); + plist_head_init(&channelPriv->messageQueue); INIT_LIST_HEAD(&channelPriv->skelList); spin_lock_init(&channelPriv->bh_lock); mutex_init(&channelPriv->msgQueueLock); -- cgit v1.2.3 From 291cd3ddd68f516be8af90c8d49fc0ab21fff681 Mon Sep 17 00:00:00 2001 From: Rajat Verma Date: Thu, 29 Sep 2011 19:03:39 +0530 Subject: ARM: ux500: mmio: Removes gpio_set_value warning mmio uses gpio pin (BASE + 5) located on gpio expander chip for XENON_CHARGE. For setting this pin to high safely gpio_set_value_cansleep() must be used instead of gpio_set_value(). ST-Ericsson Linux next: NA ST-Ericsson ID: 361940 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I02e06faa3d9c1862a649f6eb84336734490a7b2b Signed-off-by: Rajat Verma Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32531 Reviewed-by: Jonas ABERG Reviewed-by: Rabin VINCENT --- arch/arm/mach-ux500/board-mop500-mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-mop500-mmio.c b/arch/arm/mach-ux500/board-mop500-mmio.c index 6b93514ebdd..a67b16aba2c 100644 --- a/arch/arm/mach-ux500/board-mop500-mmio.c +++ b/arch/arm/mach-ux500/board-mop500-mmio.c @@ -363,7 +363,7 @@ static int mmio_power_enable(struct mmio_platform_data *pdata) } } /* Set Xenon Charge */ - gpio_set_value(extra->xenon_charge, 1); + gpio_set_value_cansleep(extra->xenon_charge, 1); dev_dbg(pdata->dev , "Board %s() Exit\n", __func__); return 0; err_regulator: -- cgit v1.2.3 From 8bbaaf6aa2dce9eef6467bdcb129c7493a3ce813 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Fri, 9 Sep 2011 14:45:37 +0200 Subject: U8500 CM: send a DSP Panic if it's not responding * Generate a DSP Panic and send it to user process when the DSP does not respond anymore. The issue is that when a process is using a DSP (ie has some components deployed on a DSP) without any activity (no interaction with the DSP), the driver needs to tell it when the DSP is dead. This Panic message is there to solve this issue. * Force wake-up of MMDSP before changing hardware power state This a work around for prcmu issue. ST-Ericsson ID: 359048 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: I920cc6a8e79e7dc9b39bd77f700a9e0e056b6a81 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32584 Reviewed-by: Pierre PEIFFER Tested-by: Pierre PEIFFER --- .../nmf-cm/cm/engine/component/src/initializer.c | 23 +++++++++++++++++++--- .../nmf-cm/cm/engine/component/src/instantiater.c | 8 -------- .../staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c | 2 +- .../os_adaptation_layer/inc/os_adaptation_layer.h | 15 +++++++++++++- .../nmf-cm/cm/engine/power_mgt/src/cmpower.c | 18 +++++++++++++++++ drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 20 +++++++++---------- drivers/staging/nmf-cm/cm_debug.c | 2 +- drivers/staging/nmf-cm/cmld.c | 2 +- drivers/staging/nmf-cm/ee/api/panic.idt | 3 ++- drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- drivers/staging/nmf-cm/osal-kernel.c | 22 +++++++++++++++++++++ 11 files changed, 90 insertions(+), 27 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c index 011dfa18398..7f99b710401 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c @@ -24,6 +24,7 @@ /* private prototype */ PRIVATE t_cm_error cm_COMP_generic(t_nmf_core_id coreId, t_event_params_handle paramArray, t_uint32 paramNumber, t_uint32 serviceIndex); +PRIVATE void cm_COMP_generatePanic(t_nmf_core_id coreId); /* * This module is tightly coupled with cm_DSP_components one (communication/initializer) @@ -153,8 +154,10 @@ PUBLIC t_cm_error cm_COMP_CallService( error = cm_COMP_generic(pComp->Template->dspId, params, sizeof(params) / sizeof(t_uint16), serviceIndex); if (isSynchronous == TRUE && error == CM_OK) { - if (OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) + if (OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) { + cm_COMP_generatePanic(pComp->Template->dspId); error = CM_MPC_NOT_RESPONDING; + } } return error; @@ -180,6 +183,7 @@ PUBLIC void cm_COMP_Flush(t_nmf_core_id coreId) { if (cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_DESTROY_INDEX) != CM_OK || OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) { + cm_COMP_generatePanic(coreId); ERROR("CM_MPC_NOT_RESPONDING: can't call flush service\n", 0, 0, 0, 0, 0, 0); } } @@ -250,8 +254,10 @@ PUBLIC t_cm_error cm_COMP_ULPForceWakeup( error = cm_COMP_generic(coreId, NULL, 0, NMF_ULP_FORCEWAKEUP); if (error == CM_OK) { - if (OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) + if (OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) { + cm_COMP_generatePanic(coreId); error = CM_MPC_NOT_RESPONDING; + } } return error; @@ -335,8 +341,10 @@ PRIVATE t_cm_error cm_COMP_generic( t_uint32 i; // wait for an event in fifo - if (OSAL_SEMAPHORE_WAIT_TIMEOUT(initializerDesc[coreId].fifoSemHandle) != SYNC_OK) + if (OSAL_SEMAPHORE_WAIT_TIMEOUT(initializerDesc[coreId].fifoSemHandle) != SYNC_OK) { + cm_COMP_generatePanic(coreId); return CM_MPC_NOT_RESPONDING; + } // AllocEvent @@ -364,3 +372,12 @@ unlock: return error; } +PRIVATE void cm_COMP_generatePanic(t_nmf_core_id coreId) +{ + const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId); + + if (pDspDesc->state != MPC_STATE_PANIC) { + cm_DSP_SetStatePanic(coreId); + OSAL_GeneratePanic(coreId, 0); + } +} diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c index bd410c9acd9..92c28b63171 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c @@ -551,15 +551,7 @@ t_cm_error cm_startComponent(t_component_instance* component, t_nmf_client_id cl value, sizeof(value)) == CM_OK) { - // The PRCMU seem not supporting the transition of asking HW IP on while DSP in retention - // -> Thus force wake up of the MMDSP before asking the transition - if ((error = cm_EEM_ForceWakeup(component->Template->dspId)) != CM_OK) - return error; - error = cm_PWR_EnableMPC(MPC_PWR_HWIP, component->Template->dspId); - - cm_EEM_AllowSleep(component->Template->dspId); - if(error != CM_OK) return error; } diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c index 452d0f1b175..5f6641b188d 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfmmdsp.c @@ -28,7 +28,7 @@ static const t_elfmemory mmdspMemories[NUMBER_OF_MMDSP_MEMORY] = { {9, INTERNAL_YRAM24, 0, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "YRAM"}, /* 2: Y memory */ {10, SDRAM_EXT24, SDRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "SDRAM24"}, /* 5: SDRAM24 */ {11, SDRAM_EXT16, SDRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 2, "SDRAM16"}, /* 6: SDRAM16 */ - {12, ESRAM_EXT24, ESRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "ESRAM24"}, /* 8: ESRAM24 */ + {12, ESRAM_EXT24, ESRAMMEM24_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 4, "ESRAM24"}, /* 8: ESRAM24 */ {13, ESRAM_EXT16, ESRAMMEM16_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_PRIVATE, MEM_DATA, 3, 2, "ESRAM16"}, /* 9: ESRAM16 */ {14, LOCKED_CODE, SDRAMTEXT_BASE_ADDR, CM_MM_ALIGN_2WORDS, MEM_SHARABLE, MEM_CODE, 8, 8, "LOCKED_CODE"}, /* : .locked */ }; diff --git a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h index e2f6e8dec81..f57c92ea41b 100644 --- a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h +++ b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h @@ -430,6 +430,20 @@ PUBLIC void OSAL_DisableServiceMessages(void); */ PUBLIC void OSAL_EnableServiceMessages(void); +/*! + * \brief Generate 'software' panic due to dsp crash + * + * We request that the os part generate a panic to notify cm users +* that a problem occur but not dsp panic has been sent (for example +* a dsp crash) + * + * \param[in] t_nmf_core_id : core_id is the id of dsp for which we need to generate a panic. + * \param[in] reason : additional information. Today only 0 is valid. + * + * \ingroup CM_ENGINE_OSAL_API + */ +PUBLIC void OSAL_GeneratePanic(t_nmf_core_id coreId, t_uint32 reason); + extern /*const*/ t_nmf_osal_sync_handle lockHandleApi; extern /*const*/ t_nmf_osal_sync_handle lockHandleCom; extern /*const*/ t_nmf_osal_sem_handle semHandle; @@ -471,7 +485,6 @@ extern /*const*/ t_nmf_osal_sem_handle semHandle; */ #define OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) OSAL_SemaphoreWaitTimed(semHandle, (cm_PWR_GetMode() == NORMAL_PWR_MODE)?SEM_TIMEOUT_NORMAL:SEM_TIMEOUT_DEBUG) - /****************/ /* Generic part */ /****************/ diff --git a/drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c b/drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c index 37ba11314f9..a104486db6c 100644 --- a/drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c +++ b/drivers/staging/nmf-cm/cm/engine/power_mgt/src/cmpower.c @@ -9,6 +9,7 @@ #include #include #include +#include // ------------------------------------------------------------------------------- // Compilation flags @@ -93,11 +94,20 @@ PUBLIC t_cm_error cm_PWR_EnableMPC( if(_pwrMPCHWIPCountT[coreId]++ == 0) { LOG_INTERNAL(__PWR_DEBUG_TRACE_LEVEL, "[Pwr] MPC %s HW IP enable clock\n",cm_getDspName(coreId), 0, 0, 0, 0, 0); + + // The PRCMU seem not supporting the transition of asking HW IP on while DSP in retention + // -> Thus force wake up of the MMDSP before asking the transition + if ((error = cm_EEM_ForceWakeup(coreId)) != CM_OK) + return error; + if((error = OSAL_EnablePwrRessource(CM_OSAL_POWER_SxA_HARDWARE, coreId, 0)) != CM_OK) { ERROR("[Pwr] MPC %s HW IP clock can't be enabled\n", cm_getDspName(coreId), 0, 0, 0, 0, 0); + cm_EEM_AllowSleep(coreId); return error; } + + cm_EEM_AllowSleep(coreId); } break; } @@ -122,7 +132,15 @@ PUBLIC void cm_PWR_DisableMPC( if(--_pwrMPCHWIPCountT[coreId] == 0) { LOG_INTERNAL(__PWR_DEBUG_TRACE_LEVEL, "[Pwr] MPC %s HW IP disable clock\n",cm_getDspName(coreId), 0, 0, 0, 0, 0); + + // The PRCMU seem not supporting the transition of asking HW IP on while DSP in retention + // -> Thus force wake up of the MMDSP before asking the transition + if (cm_EEM_ForceWakeup(coreId) != CM_OK) + return; + OSAL_DisablePwrRessource(CM_OSAL_POWER_SxA_HARDWARE, coreId, 0); + + cm_EEM_AllowSleep(coreId); } break; } diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c index 8a4d499ce41..68552b38229 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -24,16 +24,16 @@ const struct { unsigned int SP:1; unsigned int interface:1; } reason_descrs[] = { - {"NONE_PANIC", 0, 0, 0, 0}, - {"INTERNAL_PANIC", 1, 0, 0, 0}, - {"Reserved Panic", 0, 0, 0, 0}, - {"USER_STACK_OVERFLOW", 0, 1, 1, 0}, - {"SYSTEM_STACK_OVERFLOW", 0, 1, 1, 0}, - {"UNALIGNED_LONG_ACCESS", 0, 1, 0, 0}, - {"EVENT_FIFO_OVERFLOW", 0, 0, 0, 1}, - {"PARAM_FIFO_OVERFLOW", 0, 0, 0, 1}, - {"INTERFACE_NOT_BINDED", 0, 0, 0, 0}, - {"USER_PANIC", 1, 0, 0, 0} + {"NONE_PANIC", 0, 0, 0, 0}, + {"INTERNAL_PANIC", 1, 0, 0, 0}, + {"MPC_NOT_RESPONDING_PANIC", 0, 0, 0, 0}, /* Should not be useful since in that case CM_getServiceDescription() not call */ + {"USER_STACK_OVERFLOW", 0, 1, 1, 0}, + {"SYSTEM_STACK_OVERFLOW", 0, 1, 1, 0}, + {"UNALIGNED_LONG_ACCESS", 0, 1, 0, 0}, + {"EVENT_FIFO_OVERFLOW", 0, 0, 0, 1}, + {"PARAM_FIFO_OVERFLOW", 0, 0, 0, 1}, + {"INTERFACE_NOT_BINDED", 0, 0, 0, 0}, + {"USER_PANIC", 1, 0, 0, 0} }; static t_component_instance* getCorrespondingInstance( diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c index cb753ea2593..a934aa33e92 100644 --- a/drivers/staging/nmf-cm/cm_debug.c +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -195,7 +195,7 @@ static ssize_t domain_read(struct file *file, char __user *userbuf, int ret=0; OSAL_LOCK_API(); - if ((domain->domain.coreId != -1) + if ((domain->domain.coreId != MASK_ALL8) && (domain->dbgCooky != NULL)) { t_cm_allocator_status status; t_uint32 dOffset; diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index d735323c572..d96ceaa3fe5 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -28,7 +28,7 @@ #include "cm_service.h" #include "cm_dma.h" -#define CMDRIVER_PATCH_VERSION 115 +#define CMDRIVER_PATCH_VERSION 117 #define O_FLUSH 0x1000000 static int cmld_major; diff --git a/drivers/staging/nmf-cm/ee/api/panic.idt b/drivers/staging/nmf-cm/ee/api/panic.idt index 612dfcc8b4b..f971fdad8c5 100644 --- a/drivers/staging/nmf-cm/ee/api/panic.idt +++ b/drivers/staging/nmf-cm/ee/api/panic.idt @@ -30,6 +30,7 @@ typedef t_uint8 t_panic_reason; * Reason | Information | Behavior * ------------------------------------------------------------------- * INTERNAL_PANIC | Not interpreted | Fatal panic, stop MPC + * MPC_NOT_RESPONDING_PANIC | Not interpreted | Fatal panic, stop MPC * USER_STACK_OVERFLOW | Faulting address & SPu | Fatal panic, stop MPC * SYSTEM_STACK_OVERFLOW | Faulting address & SPu | Fatal panic, stop MPC * UNALIGNED_LONG_ACCESS | Indicative Faulting address & SPu | Fatal panic, stop MPC @@ -45,7 +46,7 @@ typedef t_uint8 t_panic_reason; */ typedef enum { INTERNAL_PANIC = 1, - RESERVED_PANIC = 2, + MPC_NOT_RESPONDING_PANIC = 2, USER_STACK_OVERFLOW = 3, SYSTEM_STACK_OVERFLOW = 4, UNALIGNED_LONG_ACCESS = 5, diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index f7a60383198..fc2539eefca 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (115)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (117)) /*! * \brief Get NMF major version corresponding to NMF version number diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index d50d1215646..4ab3552bd75 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -1068,6 +1068,28 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first return CM_OK; } +/*! + * \brief Generate 'software' panic to notify cm users + * that a problem occurs but no dsp panic has been sent yet + * (for example a dsp crash) + * \ingroup CM_ENGINE_OSAL_API + */ +void OSAL_GeneratePanic(t_nmf_core_id coreId, t_uint32 reason) +{ + struct osal_msg msg; + + /* Create and dispatch a shutdown service message */ + msg.msg_type = MSG_SERVICE; + msg.d.srv.srvType = NMF_SERVICE_PANIC; + msg.d.srv.srvData.panic.panicReason = MPC_NOT_RESPONDING_PANIC; + msg.d.srv.srvData.panic.panicSource = MPC_EE; + msg.d.srv.srvData.panic.info.mpc.coreid = coreId; + msg.d.srv.srvData.panic.info.mpc.faultingComponent = 0; + msg.d.srv.srvData.panic.info.mpc.panicInfo1 = reason; + msg.d.srv.srvData.panic.info.mpc.panicInfo2 = 0; + dispatch_service_msg(&msg); +} + /*! * \brief Generate an OS-Panic. Called in from CM_ASSERT(). * \ingroup CM_ENGINE_OSAL_API -- cgit v1.2.3 From f34c96d7190b1c30bd5ef5cc880706af0d06d2a3 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Tue, 13 Sep 2011 13:22:43 +0200 Subject: U8500 CM: always release the loadmap entry When releasing a component, its loadmap entry is not released if a corruption is detected. Free this entry in any case to avoid any leakage even in case corruption. ST-Ericsson ID: 361414 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: Ifbf60e88b4875fffeff50a896a862f850e06227f Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32585 Reviewed-by: Pierre PEIFFER Tested-by: Pierre PEIFFER --- drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c index 26e66c4a640..1342e9e0155 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c @@ -296,7 +296,10 @@ t_cm_error cm_DSPABI_RemoveLoadMap( ERROR("Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n", prevItemReferenceDspAddress, prevItemReference, 0, 0, 0, 0); - return CM_OK; + /* free the entry anyway to avoid leakage */ + cm_DM_Free(((t_component_instance *)componentHandle)->loadMapHandle, TRUE); + + return CM_OK; } curItem = (struct LoadMapItem*)((curItemDspAdress - headerOffsets[coreId]) * 2 + (t_uint32)headerAddresses[coreId]); // To ARM address @@ -346,6 +349,9 @@ t_cm_error cm_DSPABI_RemoveLoadMap( ERROR("Memory corruption in MMDSP: component not in LoadMap %s\n", localname, 0, 0, 0, 0, 0); + /* free the entry anyway to avoid leakage */ + cm_DM_Free(((t_component_instance *)componentHandle)->loadMapHandle, TRUE); + return CM_OK; } -- cgit v1.2.3 From ed75b8b05d869a790e53d517ecd4874e56d1e1bd Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Wed, 14 Sep 2011 15:14:35 +0200 Subject: U8500 CM: Add caller info in some panic Add caller information in case of INTERFACE_NOT_BINDED panic ST-Ericsson ID: 361780 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Signed-off-by: Pierre Peiffer Change-Id: I7caf788a30268cd977c67efe62f8182a76502d4c Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32586 Reviewed-by: Pierre PEIFFER Tested-by: Pierre PEIFFER --- drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 2 +- drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c index 68552b38229..9cb1a729a92 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -32,7 +32,7 @@ const struct { {"UNALIGNED_LONG_ACCESS", 0, 1, 0, 0}, {"EVENT_FIFO_OVERFLOW", 0, 0, 0, 1}, {"PARAM_FIFO_OVERFLOW", 0, 0, 0, 1}, - {"INTERFACE_NOT_BINDED", 0, 0, 0, 0}, + {"INTERFACE_NOT_BINDED", 0, 1, 0, 0}, {"USER_PANIC", 1, 0, 0, 0} }; diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index fc2539eefca..e671198f7b9 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (117)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (118)) /*! * \brief Get NMF major version corresponding to NMF version number -- cgit v1.2.3 From c82f06f5611499f3b47ca7a872afc3c9bca328a2 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Wed, 7 Sep 2011 15:21:05 +0200 Subject: U8500 CM: remove useless files Remove some useless files from the NMF-CM driver. ST-Ericsson ID: 360466 ST-Ericsson Linux next: - Signed-off-by: Pierre Peiffer Change-Id: I05eae0cf823b44b0861bff6aedc5341d5cc1d8d0 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32588 Reviewed-by: Pierre PEIFFER Tested-by: Pierre PEIFFER --- drivers/staging/nmf-cm/ee/api/ee.h | 197 ----------------------------- drivers/staging/nmf-cm/ee/api/ee_type.h | 32 ----- drivers/staging/nmf-cm/ee/api/list.idt | 18 --- drivers/staging/nmf-cm/ee/api/outnotify.h | 14 -- drivers/staging/nmf-cm/ee/api/priority.idt | 24 ---- 5 files changed, 285 deletions(-) delete mode 100644 drivers/staging/nmf-cm/ee/api/ee.h delete mode 100644 drivers/staging/nmf-cm/ee/api/ee_type.h delete mode 100644 drivers/staging/nmf-cm/ee/api/list.idt delete mode 100644 drivers/staging/nmf-cm/ee/api/outnotify.h delete mode 100644 drivers/staging/nmf-cm/ee/api/priority.idt diff --git a/drivers/staging/nmf-cm/ee/api/ee.h b/drivers/staging/nmf-cm/ee/api/ee.h deleted file mode 100644 index bde3cee9425..00000000000 --- a/drivers/staging/nmf-cm/ee/api/ee.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010. All rights reserved. - * This code is ST-Ericsson proprietary and confidential. - * Any use of the code for whatever purpose is subject to - * specific written permission of ST-Ericsson SA. - */ - -/*! - * \defgroup HOSTEE_MODULE Host Execution Engine - */ - -/*! - * \defgroup HOSTEE Host Execution Engine API - * \ingroup HOSTEE_MODULE - */ - -#ifndef HOST_EE_H -#define HOST_EE_H - - -#include - -#include -#include - -#include - -/*! - * \brief Get the version of the NMF Host EE at runtime - * - * This method should be used to query the version number of the - * NMF Component Manager engine at runtime. This is useful when using - * to check if version of the engine linked with application correspond - * to engine used for development. - * - * Such code can be used to check compatibility: \code - t_uint32 nmfversion; - - // Print NMF version - EE_GetVersion(&nmfversion); - LOG("NMF Version %d-%d-%d\n", - VERSION_MAJOR(nmfversion), - VERSION_MINOR(nmfversion), - VERSION_PATCH(nmfversion)); - if(NMF_VERSION != nmfversion) { - LOG("Error: Incompatible API version %d != %d\n", NMF_VERSION, nmfversion); - EXIT(); - } - * \endcode - * - * \param[out] version Internal hardcoded version (use \ref VERSION_MAJOR, \ref VERSION_MINOR, \ref VERSION_PATCH macros to decode it). - * - * \ingroup HOSTEE - */ -PUBLIC IMPORT_SHARED void EE_GetVersion(t_uint32 *version); - -/*! - * \brief Set the mode of the Host EE. - * - * According the (\ref t_ee_cmd_id) value, this routine allows to modify dynamically the behavior of the Host EE. - * - * \param[in] aCmdID Command ID. - * \param[in] aParam Parameter of command ID if required. - * - * \ingroup HOSTEE - */ -PUBLIC IMPORT_SHARED t_nmf_error EE_SetMode(t_ee_cmd_id aCmdID, t_sint32 aParam); - -/*! - * \brief Create a channel for communication between host ee and user. - * - * The purpose of the function is to: - * - create a channel or get a channel, regarding the flag parameter - * - * \param[in] flags Whether the caller want to create a new channel (CHANNEL_PRIVATE) - * or use the shared one (CHANNEL_PRIVATE) (it will be created - * if it does not yet exist) - * \param[out] channel Channel number. - * - * \exception NMF_NO_MORE_MEMORY Not enough memory to create the callback Channel. - * \exception NMF_INVALID_PARAMETER The specified flags is invalid. - * - * \ingroup HOSTEE - */ -PUBLIC IMPORT_SHARED t_nmf_error EE_CreateChannel(t_nmf_channel_flag flags, t_nmf_channel *channel); - -/*! - * \brief Flush a channel to allow user to safely close it. - * - * The purpose of the function is to allow safe call of EE_CloseChannel() later on. Calling - * EE_FlushChannel() will allow a blocking call to EE_GetMessage() to exit with an error - * NMF_FLUSH_MESSAGE. After EE_GetMessage() has exit with such a value user must no more - * call EE_GetMessage() and can safely call EE_CloseChannel() that will destroy channel. - * In case of the share channel EE_FlushChannel() will return false for isFlushMessageGenerated if - * it's internal reference counter is not zero, in that case no NMF_FLUSH_MESSAGE error is return - * by EE_GetMessage() and user can immediatly call EE_CloseChannel(). - * In case user know that no usage of channel is done when he want to destroy channel, call to this api - * is optionnal and user can safely call EE_CloseChannel(). - * - * \param[in] channel Channel number - * \param[out] isFlushMessageGenerated Allow user to know if it must wait for NMF_FLUSH_MESSAGE return - * of EE_GetMessage() before calling EE_CloseChannel() - * - * \exception NMF_INVALID_PARAMETER The specified flags is invalid. - * - * \ingroup HOSTEE - */ -PUBLIC IMPORT_SHARED t_nmf_error EE_FlushChannel(t_nmf_channel channel, t_bool *isFlushMessageGenerated); - -/*! - * \brief Unregister channel - * - * The purpose of the function is to: - * - destroy a channel from the user to the Host ee. - * - * The user must call EE_UserDone() as many time as EE_UserInit(). - * At the last EE_UserDone() call, the channel is closed and definitely destroyed - * All service callback must be unregistered first. - * - * \param[in] channel Channel number: - * - * \ingroup HOSTEE - */ -PUBLIC IMPORT_SHARED t_nmf_error EE_CloseChannel(t_nmf_channel channel); - -/*! - * \brief Register a service callback to this channel. - * - * \param[in] channel The channel on which the callback must be registered. - * \param[in] handler The given callback. - * \param[in] contextHandler The context associated with this callback. - * - * \exception NMF_NO_MORE_MEMORY Not enough memory to associate service with the Channel. - * - * \ingroup HOSTEE - */ -PUBLIC IMPORT_SHARED t_nmf_error EE_RegisterService(t_nmf_channel channel, t_nmf_serviceCallback handler, void *contextHandler); - -/*! - * \brief Unregister a service callback from this channel. - * - * \param[in] channel The channel on which the callback must be registered. - * \param[in] handler The given callback. - * \param[in] contextHandler The context associated with this callback. - * - * \exception NMF_INVALID_PARAMETER The channel or the callback doesn't exist. - * - * \ingroup HOSTEE - */ -PUBLIC IMPORT_SHARED t_nmf_error EE_UnregisterService(t_nmf_channel channel, t_nmf_serviceCallback handler, void *contextHandler); - -/*! - * \brief Unregister a notify callback for this channel. - * - * This method will register a callback that will be call each time a message has - * been push in queue of the channel. - * To unregister your callback just register a null notify. - * - * \param[in] channel The channel on which the callback must be registered. - * \param[in] notify The given callback. - * \param[in] contextHandler The context associated with this callback. - * - * \ingroup HOSTEE - */ -PUBLIC IMPORT_SHARED t_nmf_error EE_RegisterNotify(t_nmf_channel channel, t_nmf_notify notify, void *contextHandler); - -/*! - * \brief Get received message from specified callback channel. - * - * This method can be used to retrieve callback message from Host ee. Returned message could then - * be dispatch through EE_ExecuteMessage. - * - * \param[in] channel The channel from which the message must be retrieved - * \param[out] clientContext client context. - * \param[out] message Reference on buffer to be unmarshalled. The buffer is allocated internally. - * \param[in] blockable Indicate if the call could blocked or not. - * - * \exception NMF_NO_MESSAGE No waited message. - * \exception NMF_INVALID_PARAMETER At least one input parameters is invalid - * - * \ingroup HOSTEE - */ -PUBLIC IMPORT_SHARED t_nmf_error EE_GetMessage(t_nmf_channel channel, void **clientContext, char **message, t_bool blockable); - -/*! - * \brief Execute a message. User callback will be execute. - * - * This method allow the message retrieved through EE_GetMessage to the right user callback. - * - * \param[in] itfref Interface reference. - * \param[in] message Reference on buffer to be unmarshalled. - * - * \ingroup HOSTEE - */ -PUBLIC IMPORT_SHARED void EE_ExecuteMessage(void *itfref, char *message); - -#endif diff --git a/drivers/staging/nmf-cm/ee/api/ee_type.h b/drivers/staging/nmf-cm/ee/api/ee_type.h deleted file mode 100644 index 368cd6d29ba..00000000000 --- a/drivers/staging/nmf-cm/ee/api/ee_type.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010. All rights reserved. - * This code is ST-Ericsson proprietary and confidential. - * Any use of the code for whatever purpose is subject to - * specific written permission of ST-Ericsson SA. - */ - -#ifndef HOST_EE_TYPE_H -#define HOST_EE_TYPE_H - -/*! - * \brief Notify callback method type. - * - * \ingroup HOSTEE - */ -typedef void (*t_nmf_notify)(void *contextHandler); - -/*! - * \brief Definition of the command ID type - */ -typedef t_uint32 t_ee_cmd_id; - -/*! - * \brief Definition of the command ID - */ -typedef enum { - EE_CMD_TRACE_ON, //!< Enable tracing and force network resetting and dumping - EE_CMD_TRACE_OFF //!< Disable tracing -} t_ee_cmd_idDescription; - - -#endif diff --git a/drivers/staging/nmf-cm/ee/api/list.idt b/drivers/staging/nmf-cm/ee/api/list.idt deleted file mode 100644 index a53a39734d8..00000000000 --- a/drivers/staging/nmf-cm/ee/api/list.idt +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010. All rights reserved. - * This code is ST-Ericsson proprietary and confidential. - * Any use of the code for whatever purpose is subject to - * specific written permission of ST-Ericsson SA. - */ - -#ifndef LIST_IDT -#define LIST_IDT - -/* linking elem */ -struct _t_list_link { - struct _t_list_link *pNext; -}; -typedef struct _t_list_link t_list_link; - -#endif - diff --git a/drivers/staging/nmf-cm/ee/api/outnotify.h b/drivers/staging/nmf-cm/ee/api/outnotify.h deleted file mode 100644 index c88185fac16..00000000000 --- a/drivers/staging/nmf-cm/ee/api/outnotify.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010. All rights reserved. - * This code is ST-Ericsson proprietary and confidential. - * Any use of the code for whatever purpose is subject to - * specific written permission of ST-Ericsson SA. - */ - -#ifndef OUT_IDT -#define OUT_IDT - -typedef void (*t_nmf_notify)(void *contextHandler); - -#endif - diff --git a/drivers/staging/nmf-cm/ee/api/priority.idt b/drivers/staging/nmf-cm/ee/api/priority.idt deleted file mode 100644 index a276ba57727..00000000000 --- a/drivers/staging/nmf-cm/ee/api/priority.idt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010. All rights reserved. - * This code is ST-Ericsson proprietary and confidential. - * Any use of the code for whatever purpose is subject to - * specific written permission of ST-Ericsson SA. - */ - -#ifndef PRIORITY_IDT -#define PRIORITY_IDT - -/** - * 0 : background - * 1 : normal - * 2 : urgent - * 3 : - * 4 : CScall - * 5 : CScall - * 6 : IO (not linked with priority ordering) - */ -#define MAX_SCHEDULER_PRIORITY_NUMBER 7 -#define MAX_SCHEDULER_SUBPRIORITY_NUMBER 4 - -#endif - -- cgit v1.2.3 From 24133f32843de5e3524c5902ca14409db768d8ed Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Tue, 4 Oct 2011 15:47:02 +0200 Subject: U8500 CM: do not initialize ESRAM to zero The CM driver initializes the whole ESRAM to zero, including the DMA part (at offset 64k-68k) which can be already in use. Let the CM map only the required part (ie exclude the MCDE part) and do not reset the ESRAM to zero at init. ST-Ericsson ID: 361307 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Signed-off-by: Pierre Peiffer Change-Id: Ie930e7febe7e24b790c2d2b8ffadc4198daabac7 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/32980 Reviewed-by: Pierre PEIFFER Tested-by: Pierre PEIFFER --- drivers/staging/nmf-cm/configuration.h | 10 +++++++--- drivers/staging/nmf-cm/osal-kernel.c | 2 -- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/staging/nmf-cm/configuration.h b/drivers/staging/nmf-cm/configuration.h index 8f1b88bc23f..35072831a13 100644 --- a/drivers/staging/nmf-cm/configuration.h +++ b/drivers/staging/nmf-cm/configuration.h @@ -19,11 +19,15 @@ #include #endif -/** Nomadik embedded Static RAM base address*/ +/* Embedded Static RAM base address */ #define ESRAM_BASE (U8500_ESRAM_BASE + 0x10000) // V1/V2 config: 0-64k: secure; -/** Nomadik embedded ram size for CM (in Kb) */ -#define ESRAM_SIZE 576 +/* + * Embedded ram size for CM (in Kb) + * 5 banks of 128k: skip the first half bank (secure) and the last + * one (used for MCDE/B2R2), but include DMA part (4k after the secure part) + */ +#define ESRAM_SIZE 448 enum { ESRAM_12, ESRAM_34, diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 4ab3552bd75..f792312e940 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -89,8 +89,6 @@ int remapRegions(void) pr_err("%s: could not remap ESRAM Base\n", __func__); return -ENOMEM; } - memset(osalEnv.esram_base, 0x0, cfgESRAMSize*ONE_KB); - /* Allocate code and data sections for MPC (SVA, SIA) */ for (i=0; i Date: Fri, 7 Oct 2011 11:44:27 +0530 Subject: u5500: mmio: fix build failure The header was moved but 5500 was not updated. Change-Id: Ica5e1d5386c1a41797eaac87b2e04222d06866e3 Signed-off-by: Rabin Vincent Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33275 Reviewed-by: Jonas ABERG --- arch/arm/mach-ux500/board-u5500-mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-u5500-mmio.c b/arch/arm/mach-ux500/board-u5500-mmio.c index bbf2b4bf949..0f1c00c4a5d 100644 --- a/arch/arm/mach-ux500/board-u5500-mmio.c +++ b/arch/arm/mach-ux500/board-u5500-mmio.c @@ -22,7 +22,7 @@ #include #include #include "board-u5500.h" -#include "../drivers/staging/mmio/mmio.h" +#include struct mmio_board_data{ int number_of_regulators; -- cgit v1.2.3 From f819c5ccb26dd5b031b1564bcda2d30c13038b0c Mon Sep 17 00:00:00 2001 From: Rajat Verma Date: Fri, 7 Oct 2011 12:13:05 +0530 Subject: ux500: camera_flash: add platform data for adp1653 board specific information such as enable_gpio and interrupt line information should be obtained using platform_data and not hardcoded inside the driver itself. ST-Ericsson Linux next: NA ST-Ericsson ID: 361940 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I73a0f3e986bd3cbf19a0797190d514af9b84e3df Signed-off-by: Rajat Verma Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33282 Reviewed-by: Jonas ABERG Reviewed-by: Rabin VINCENT Signed-off-by: Robert Marklund --- drivers/staging/camera_flash/adp1653.c | 163 +++++++++------------------- drivers/staging/camera_flash/adp1653_plat.h | 24 ++++ 2 files changed, 76 insertions(+), 111 deletions(-) create mode 100755 drivers/staging/camera_flash/adp1653_plat.h diff --git a/drivers/staging/camera_flash/adp1653.c b/drivers/staging/camera_flash/adp1653.c index 8264e46a1f2..f7483eac11f 100644 --- a/drivers/staging/camera_flash/adp1653.c +++ b/drivers/staging/camera_flash/adp1653.c @@ -17,26 +17,16 @@ #include "flash_common.h" #include "adp1653.h" #include "camera_flash.h" +#include "adp1653_plat.h" /* This data is platform specific for 8500 href-v1 platform, * Ideally this should be supplied from platform code */ -//#define ADAPTER_I2C2 (2) -#define STR_GPIO (6) -static int strobe_gpio = 0; //TODO: set to 0 when it works static int adapter_i2c2 = 2; -static int flash_irq = 7; -static int enable_gpio = 272; static int flash_position = 0; -module_param(strobe_gpio, int, S_IRUGO); -MODULE_PARM_DESC(strobe_gpio, "use GPIO 6 to strobe, 0 means that someone else (sensor?) will strobe for us"); module_param(adapter_i2c2, int, S_IRUGO); MODULE_PARM_DESC(adapter_i2c2, "use the given I2C adaptater to communicate with the chip"); -module_param(flash_irq, int, S_IRUGO); -MODULE_PARM_DESC(flash_irq, "the GPIO number associated to the i2c irq line"); -module_param(enable_gpio, int, S_IRUGO); -MODULE_PARM_DESC(enable_gpio, "use the given GPIO line to enable the chip"); module_param(flash_position, int, S_IRUGO); MODULE_PARM_DESC(flash_position, "the position of the flash chip (0=PRIMARY, 1=SECONDARY)"); @@ -251,11 +241,6 @@ static int adp1653_strobe_still_led(struct adp1653_priv_data *priv_p,int enable) goto out; } - if (strobe_gpio != 0 ) - { - gpio_set_value(priv_p->strobe_gpio,gpio_val); - } - out: return err; } @@ -394,9 +379,10 @@ static irqreturn_t adp1653_irq_hdlr(int irq_no,void *data) static int __devinit adp1653_probe(struct i2c_client *client, const struct i2c_device_id *id) { - int err=0; + int err = 0; struct flash_chip *flash_chip_p=NULL; struct adp1653_priv_data *priv_p=NULL; + struct adp1653_platform_data *pdata = client->dev.platform_data; DEBUG_LOG("> adp1653_probe\n"); @@ -404,15 +390,23 @@ static int __devinit adp1653_probe(struct i2c_client *client, if(!priv_p){ DEBUG_LOG("Kmalloc failed for priv data\n"); err = ENOMEM; - goto out; + goto err_priv; } priv_p->i2c_client = client; flash_chip_p = kzalloc(sizeof(struct flash_chip),GFP_KERNEL); if(!flash_chip_p){ DEBUG_LOG("Kmalloc failed for flash_chip_p"); err = ENOMEM; - goto out; + goto err_flash_chip_alloc; } + + if (!pdata) { + dev_err(&client->dev, + "%s: No platform data supplied.\n", __func__); + err = -EINVAL; + goto err_pdata; + } + flash_chip_p->priv_data = priv_p; flash_chip_p->ops = &adp1653_ops; SET_FLASHCHIP_TYPE(flash_chip_p,FLASH_TYPE_HPLED); @@ -423,98 +417,53 @@ static int __devinit adp1653_probe(struct i2c_client *client, i2c_set_clientdata(client,priv_p); /*Request GPIO and Register IRQ if supported by platform and flash chip*/ - if(machine_is_hrefv60()) - enable_gpio = 21; - else - enable_gpio = 272; - - if(enable_gpio){ - err = gpio_request(enable_gpio,"Camera LED flash Enable"); - if(err){ - DEBUG_LOG("Unable to get GPIO %d, for enable\n",enable_gpio); - goto out; - } - priv_p->enable_gpio = enable_gpio; - - err = gpio_direction_output(priv_p->enable_gpio, 1); - if(err){ - DEBUG_LOG("Unable to set GPIO %lu in output mode, err %d\n",priv_p->enable_gpio,err); - gpio_free(priv_p->enable_gpio); - goto out; - } - gpio_set_value(priv_p->enable_gpio, 1); + err = gpio_request(pdata->enable_gpio,"Camera LED flash Enable"); + if(err){ + DEBUG_LOG("Unable to get GPIO %d, for enable\n",pdata->enable_gpio); + goto err_pdata; } - if (strobe_gpio != 0) - { - err = gpio_request(STR_GPIO,"Camera flash strobe\n"); - if(err){ - DEBUG_LOG("Unable to request strobe GPIO\n"); - // somebody else requested this gpio ... - //goto out; - } - - err = gpio_direction_output(STR_GPIO, 0); - if(err){ - DEBUG_LOG("Unable to set GPIO %d in output mode, err %d\n",STR_GPIO,err); - goto out; - } + err = gpio_direction_output(pdata->enable_gpio, 1); + if(err){ + DEBUG_LOG("Unable to set GPIO %u in output mode, err %d\n",pdata->enable_gpio,err); + gpio_free(pdata->enable_gpio); + goto err_gpio_set; } - else - { - err = gpio_request(STR_GPIO,"Camera flash strobe\n"); - if(err){ - DEBUG_LOG("Unable to request strobe GPIO\n"); - // somebody else requested this gpio ... - //goto out; - } - - err = gpio_direction_input(STR_GPIO); - if(err){ - DEBUG_LOG("Unable to set GPIO %d in input mode, err %d\n",STR_GPIO,err); - goto out; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) - err = nmk_gpio_set_pull(STR_GPIO, NMK_GPIO_PULL_DOWN); -#endif - if(err){ - DEBUG_LOG("Unable to set pull down on GPIO %d\n",STR_GPIO); - goto out; - } + gpio_set_value_cansleep(pdata->enable_gpio, 1); + err = request_threaded_irq(gpio_to_irq(pdata->irq_no),NULL,adp1653_irq_hdlr, + IRQF_ONESHOT|IRQF_TRIGGER_FALLING, + "Adp1653 flash",priv_p); + if(err){ + DEBUG_LOG("Unable to register flash IRQ handler, irq %d, err %d\n", + pdata->irq_no,err); + goto err_irq; } - priv_p->strobe_gpio = STR_GPIO; - - if(client->irq){ - err = request_threaded_irq(client->irq,NULL,adp1653_irq_hdlr, - IRQF_ONESHOT|IRQF_TRIGGER_FALLING, - "Adp1653 flash",priv_p); - if(err){ - DEBUG_LOG("Unable to register flash IRQ handler, irq %d, err %d\n", - client->irq,err); - goto out; - } - } err = register_flash_chip(flash_position,flash_chip_p); if(err){ DEBUG_LOG("Failed to register Adp1653 as flash for %s camera\n", (flash_position?"Primary":"Secondary")); - goto out; + goto err_register; } SET_FLASH_STATUS(priv_p->status,FLASH_STATUS_READY); DEBUG_LOG("< adp1653_probe ok\n"); return err; -out: - if(priv_p->irq_no) - free_irq(priv_p->irq_no,NULL); - if(priv_p->enable_gpio) - gpio_free(priv_p->enable_gpio); - if(priv_p) - kfree(priv_p); +err_register: + if(pdata->irq_no) + free_irq(pdata->irq_no,NULL); +err_irq: + gpio_set_value_cansleep(pdata->enable_gpio, 0); +err_gpio_set: + if(pdata->enable_gpio) + gpio_free(pdata->enable_gpio); +err_pdata: if(flash_chip_p) kfree(flash_chip_p); +err_flash_chip_alloc: + if(priv_p) + kfree(priv_p); +err_priv: DEBUG_LOG("< adp1653_probe (%d)\n", err); return err; } @@ -540,16 +489,15 @@ static struct i2c_driver adp1653_i2c_driver = { }; int adp1653_init(void){ - int err=0; + int err = 0; struct i2c_adapter *adap_p; struct i2c_board_info info; - /*Registration of I2C flash device is platform specific code - *Ideally it should be done from kernel (arch/arm/mach-XXX). - *Do it locally till the time it gets into platform code - *OR This portion (registration of device) and flash chip init - *Routine can be moved to Flash chip module init. - */ + /* Registration of I2C flash device is platform specific code + * Ideally it should be done from kernel (arch/arm/mach-XXX). + * Do it locally till the time it gets into platform code + * OR This portion (registration of device) and flash chip init + * Routine can be moved to Flash chip module init. */ DEBUG_LOG("getting I2C adaptor %d\n",adapter_i2c2); adap_p = i2c_get_adapter(adapter_i2c2); if(!adap_p){ @@ -558,21 +506,16 @@ int adp1653_init(void){ } memset(&info,0,sizeof( struct i2c_board_info)); - info.irq = __flash_gpio_to_irq(flash_irq); - strcpy(&info.type[0],"adp1653"); - DEBUG_LOG("trying to register %s at position %d, GPIO enable %d, GPIO IRQ line %d\n", + DEBUG_LOG("trying to register %s at position %d\n", info.type, - flash_position, - enable_gpio, - flash_irq); + flash_position); /* I2C framework expects least significant 7 bits as address, not complete * 8 bits with bit 0 (read/write bit) */ info.addr = 0x60 >> 1; - err = i2c_add_driver(&adp1653_i2c_driver); if(err) { @@ -580,13 +523,11 @@ int adp1653_init(void){ goto out; } - DEBUG_LOG("Initialized adp1653\n"); if(!i2c_new_device(adap_p,&info)){ DEBUG_LOG("Unable to add i2c dev: %s (err=%d)\n",info.type, err); goto out; } - out: return err; } diff --git a/drivers/staging/camera_flash/adp1653_plat.h b/drivers/staging/camera_flash/adp1653_plat.h new file mode 100755 index 00000000000..325097aa2a8 --- /dev/null +++ b/drivers/staging/camera_flash/adp1653_plat.h @@ -0,0 +1,24 @@ +/* + * adp1653_plat.h + * ADP1653 Led Flash Driver platform specific structures + * + * Copyright (C) ST-Ericsson SA 2011 + * Author: Rajat Verma + * + * License Terms: GNU General Public License v2 + */ + +#ifndef __LINUX_I2C_ADP1653_PLAT_H__ +#define __LINUX_I2C_ADP1653_PLAT_H__ + +/** + * struct adp1653_platform_data - platform data structure for adp1653 + * @enable_gpio: gpio for chip enable/disable + * @irq_no: interrupt line for flash ic + */ +struct adp1653_platform_data { + u32 enable_gpio; + u32 irq_no; +}; + +#endif //__LINUX_I2C_ADP1653_PLAT_H__ -- cgit v1.2.3 From f6fac2492301e1185153c95a9e3a607c4ed4c7df Mon Sep 17 00:00:00 2001 From: Rajat Verma Date: Fri, 7 Oct 2011 16:25:22 +0530 Subject: u8500: mmio: fix gpio_set_value warning gpio_set_value_cansleep() should be used in place of gpio_set_value() for setting xenon_charge gpio pin which is located on expander chip in case of href boards < v60. ST-Ericsson Linux next: NA ST-Ericsson ID: 361940 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I62676b374552a2fa86f273c9d006220436c0fe68 Signed-off-by: Rajat Verma Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33338 Reviewed-by: QABUILD Reviewed-by: Rabin VINCENT --- arch/arm/mach-ux500/board-mop500-mmio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-mmio.c b/arch/arm/mach-ux500/board-mop500-mmio.c index a67b16aba2c..10dedfac8e8 100644 --- a/arch/arm/mach-ux500/board-mop500-mmio.c +++ b/arch/arm/mach-ux500/board-mop500-mmio.c @@ -55,7 +55,7 @@ static pin_cfg_t xshutdown_disable[] = { GPIO142_GPIO | PIN_OUTPUT_LOW }; -struct mmio_board_data{ +struct mmio_board_data { int number_of_regulators; struct regulator **mmio_regulators; /* Pin configs */ @@ -274,7 +274,7 @@ err_no_mem_reg: static void mmio_power_exit(struct mmio_platform_data *pdata) { int i = 0; - struct mmio_board_data *extra = pdata->extra;; + struct mmio_board_data *extra = pdata->extra; dev_dbg(pdata->dev , "Board %s() Enter\n", __func__); for (i = 0; i < extra->number_of_regulators; i++) regulator_put(extra->mmio_regulators[i]); @@ -382,7 +382,7 @@ static void mmio_power_disable(struct mmio_platform_data *pdata) for (i = 0; i < extra->number_of_regulators; i++) regulator_disable(extra->mmio_regulators[i]); /* Disable Xenon Charge */ - gpio_set_value(extra->xenon_charge, 0); + gpio_set_value_cansleep(extra->xenon_charge, 0); } static int mmio_clock_enable(struct mmio_platform_data *pdata) { -- cgit v1.2.3 From 451bc5f0e64a7fb3f8383803329f0a11671a828b Mon Sep 17 00:00:00 2001 From: Rajat Verma Date: Tue, 11 Oct 2011 09:34:50 +0530 Subject: ARM: ux500: mmio: Corrects disable mode pin config Corrects disable mode pin configuration for xshutdown pins of camera in case of HREF v60 boards. XShutdown pins should be configured in mode (dir: out, value: low) when disabled. ST-Ericsson ID: 328427 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Change-Id: I6db2fafef8061d43f191f4d7ffef6a15d2063c16 Signed-off-by: Rajat Verma Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33571 Reviewed-by: QABUILD Reviewed-by: Rabin VINCENT --- arch/arm/mach-ux500/board-mop500-mmio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/board-mop500-mmio.c b/arch/arm/mach-ux500/board-mop500-mmio.c index 10dedfac8e8..355f835caa1 100644 --- a/arch/arm/mach-ux500/board-mop500-mmio.c +++ b/arch/arm/mach-ux500/board-mop500-mmio.c @@ -193,13 +193,15 @@ static int mmio_pin_cfg_init(struct mmio_platform_data *pdata) extra->xenon_charge = HREFV60_MMIO_XENON_CHARGE; xshutdown_host[SECONDARY_CAMERA] = GPIO140_GPIO; xshutdown_fw[SECONDARY_CAMERA] = GPIO140_IP_GPIO7; - xshutdown_disable[SECONDARY_CAMERA] = GPIO140_GPIO; + xshutdown_disable[SECONDARY_CAMERA] = + GPIO140_GPIO | PIN_OUTPUT_LOW; extra->xshutdown_pins[SECONDARY_CAMERA].gpio = 140; } else { extra->xenon_charge = GPIO_MMIO_XENON_CHARGE; xshutdown_host[SECONDARY_CAMERA] = GPIO142_GPIO; xshutdown_fw[SECONDARY_CAMERA] = GPIO142_IP_GPIO3; - xshutdown_disable[SECONDARY_CAMERA] = GPIO142_GPIO; + xshutdown_disable[SECONDARY_CAMERA] = + GPIO142_GPIO | PIN_OUTPUT_LOW; extra->xshutdown_pins[SECONDARY_CAMERA].gpio = 142; } /* Setup Xenon Charge */ @@ -271,6 +273,7 @@ err_regulator: err_no_mem_reg: return err; } + static void mmio_power_exit(struct mmio_platform_data *pdata) { int i = 0; -- cgit v1.2.3 From e068bc878e17b16474561e20d5cb80a0150b9771 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 17 Nov 2011 15:41:30 +0100 Subject: staging: add STE mmio driver compilation Signed-off-by: Philippe Langlais --- drivers/staging/Kconfig | 2 ++ drivers/staging/Makefile | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 97d412d9145..a8efed2558c 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -132,4 +132,6 @@ source "drivers/staging/ramster/Kconfig" source "drivers/staging/ozwpan/Kconfig" +source "drivers/staging/mmio/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index ffe7d44374e..01f7c1bfe56 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -57,3 +57,4 @@ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_RAMSTER) += ramster/ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ +obj-$(CONFIG_U8500_MMIO) += mmio/ -- cgit v1.2.3 From 9a4d7d2a1256fa259372b2e8ebc0f0d655d1ca46 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 21 Oct 2011 10:59:22 +0200 Subject: staging: Add STE NMF/CM driver compilation --- drivers/staging/Kconfig | 2 ++ drivers/staging/Makefile | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index a8efed2558c..368d723c5bb 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -134,4 +134,6 @@ source "drivers/staging/ozwpan/Kconfig" source "drivers/staging/mmio/Kconfig" +source "drivers/staging/nmf-cm/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 01f7c1bfe56..2eac8b57cdc 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -58,3 +58,4 @@ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_RAMSTER) += ramster/ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ obj-$(CONFIG_U8500_MMIO) += mmio/ +obj-$(CONFIG_U8500_CM) += nmf-cm/ -- cgit v1.2.3 From 1c43eb9fdaeb78be8deff277c4212625120d1687 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 21 Oct 2011 11:03:45 +0200 Subject: statging: Add STE camera flash driver compilation Signed-off-by: Philippe Langlais --- drivers/staging/Kconfig | 2 ++ drivers/staging/Makefile | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 368d723c5bb..bcbecff7561 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -136,4 +136,6 @@ source "drivers/staging/mmio/Kconfig" source "drivers/staging/nmf-cm/Kconfig" +source "drivers/staging/camera_flash/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 2eac8b57cdc..4630499a5c5 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -58,4 +58,5 @@ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_RAMSTER) += ramster/ obj-$(CONFIG_USB_WPAN_HCD) += ozwpan/ obj-$(CONFIG_U8500_MMIO) += mmio/ +obj-$(CONFIG_U8500_FLASH) += camera_flash/ obj-$(CONFIG_U8500_CM) += nmf-cm/ -- cgit v1.2.3 From 37832d62154fb8edf64bfc1c5749ff2f3a6a625b Mon Sep 17 00:00:00 2001 From: Robert Marklund Date: Wed, 22 Jun 2011 21:05:59 +0200 Subject: include: Fix so the nmf-cm modules compiles Signed-off-by: Robert Marklund --- include/linux/moduleparam.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index ea36486378d..3856fdba2c1 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -196,7 +196,7 @@ struct kparam_array /* We don't get oldget: it's often a new-style param_get_uint, etc. */ static inline int -__check_old_set_param(int (*oldset)(const char *, struct kernel_param *)) +__check_old_set_param(int (*oldset)(const char *, const struct kernel_param *)) { return 0; } -- cgit v1.2.3 From deb006698c6bb9496e550233708d3d9d0a85852f Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 21 Nov 2011 09:20:47 +0100 Subject: staging: nmf/cm: Fix dependency with STM trace driver Signed-off-by: Philippe Langlais --- drivers/staging/nmf-cm/osal-kernel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index f792312e940..0b0eeac4ce3 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -19,7 +19,9 @@ #include #include +#ifdef CONFIG_STM_TRACE #include +#endif #include -- cgit v1.2.3 From e302925edc2a78569e1742e523db4b55a3fc4e26 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Fri, 2 Dec 2011 14:30:59 +0100 Subject: nmf-cm: Include module.h after 3.2 update Signed-off-by: Philippe Langlais --- drivers/staging/nmf-cm/cmld.c | 1 + drivers/staging/nmf-cm/configuration.c | 1 + drivers/staging/nmf-cm/osal-kernel.c | 1 + 3 files changed, 3 insertions(+) diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index d96ceaa3fe5..7b1061d9d52 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -10,6 +10,7 @@ * */ +#include #include #include #include diff --git a/drivers/staging/nmf-cm/configuration.c b/drivers/staging/nmf-cm/configuration.c index b61ab509d94..d62bcb45500 100644 --- a/drivers/staging/nmf-cm/configuration.c +++ b/drivers/staging/nmf-cm/configuration.c @@ -10,6 +10,7 @@ * */ +#include #include #include #include diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 0b0eeac4ce3..94aa11fc91c 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -9,6 +9,7 @@ * Implements NMF OSAL for Linux kernel-space environment */ +#include #include #include #include -- cgit v1.2.3 From c6458fb663047d93f8b8453eef114d90e324ca39 Mon Sep 17 00:00:00 2001 From: cnanda Date: Thu, 13 Oct 2011 16:00:18 +0530 Subject: staging: mmio: protect shared resource using mutex mmio_trace structure maintains information about the shared log buffer from camera firmware. As it is accessed from two different contexts, it needs to be protected using mutex to guard against possible corruption. ST-Ericsson ID: 356426 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Change-Id: I806b4d26b3466a9873a8a02f8c9ac51e0ad44fd5 Signed-off-by: cnanda Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33915 Reviewed-by: QATOOLS Tested-by: Rajat VERMA Reviewed-by: Jonas ABERG --- drivers/staging/mmio/st_mmio.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/staging/mmio/st_mmio.c b/drivers/staging/mmio/st_mmio.c index 655f7ce3a93..51e92666e28 100644 --- a/drivers/staging/mmio/st_mmio.c +++ b/drivers/staging/mmio/st_mmio.c @@ -16,8 +16,10 @@ #include #include #include +#include #include #include +#include #include "mmio.h" #define ISP_REGION_IO (0xE0000000) @@ -103,6 +105,7 @@ struct mmio_info { struct mmio_trace *trace_buffer; struct delayed_work trace_work; int trace_allowed; + struct mutex lock; }; /* @@ -507,6 +510,7 @@ static int mmio_set_trace_buffer(struct mmio_info *info, goto out; } + mutex_lock(&info->lock); if (info->trace_buffer) { dev_info(info->dev, "unmap old buffer"); iounmap(info->trace_buffer); @@ -518,7 +522,7 @@ static int mmio_set_trace_buffer(struct mmio_info *info, if (!info->trace_buffer) { dev_err(info->dev, "failed to map trace buffer\n"); ret = -ENOMEM; - goto out; + goto out_unlock; } dev_info(info->dev, "xp70 overwrite_cnt=%d (0x%x) blk_id=%d (0x%x)", @@ -544,6 +548,8 @@ static int mmio_set_trace_buffer(struct mmio_info *info, msecs_to_jiffies(XP70_TIMEOUT_MSEC))) dev_err(info->dev, "failed to schedule work\n"); +out_unlock: + mutex_unlock(&info->lock); out: return ret; } @@ -763,12 +769,13 @@ static int mmio_release(struct inode *node, struct file *filp) info->pdata->config_xshutdown_pins(info->pdata, MMIO_DISABLE_XSHUTDOWN, -1); + mutex_lock(&info->lock); if (info->trace_buffer) { + flush_delayed_work_sync(&info->trace_work); iounmap(info->trace_buffer); info->trace_buffer = NULL; } - - flush_delayed_work(&info->trace_work); + mutex_unlock(&info->lock); return 0; } @@ -794,6 +801,7 @@ static ssize_t xp70_data_show(struct device *device, int size = 0; int count = 0; int first_index; + mutex_lock(&info->lock); first_index = info->trace_status.prev_block_id + 1; if (!info->trace_buffer || info->trace_buffer->block_id == @@ -859,6 +867,7 @@ static ssize_t xp70_data_show(struct device *device, } out_unlock: + mutex_unlock(&info->lock); return size; } @@ -903,6 +912,7 @@ static void xp70_buffer_wqtask(struct work_struct *data) int i; int first_index = info->trace_status.prev_block_id + 1; int count; + mutex_lock(&info->lock); if (!info->trace_buffer) goto out_err; @@ -929,8 +939,7 @@ static void xp70_buffer_wqtask(struct work_struct *data) first_index = info->trace_buffer->block_id + 1; count = XP70_NB_BLOCK; - if (printk_ratelimit()) - dev_info(info->dev, "XP70 trace overflow\n"); + pr_info_ratelimited("XP70 trace overflow\n"); } else if (info->trace_buffer->block_id >= info->trace_status.prev_block_id) { count = info->trace_buffer->block_id - @@ -945,8 +954,7 @@ static void xp70_buffer_wqtask(struct work_struct *data) for (i = first_index; count; count--) { if (i < 0 || i >= XP70_NB_BLOCK || count > XP70_NB_BLOCK) { - if (printk_ratelimit()) - dev_info(info->dev, "trace index out-of-bounds" + pr_info_ratelimited("trace index out-of-bounds" "i=%d count=%d XP70_NB_BLOCK=%d\n", i, count, XP70_NB_BLOCK); @@ -978,13 +986,13 @@ static void xp70_buffer_wqtask(struct work_struct *data) info->trace_buffer->overwrite_count; info->trace_status.prev_block_id = info->trace_buffer->block_id; out: - /* Schedule work */ if (!schedule_delayed_work(&info->trace_work, msecs_to_jiffies(XP70_TIMEOUT_MSEC))) dev_info(info->dev, "failed to schedule work\n"); out_err: + mutex_unlock(&info->lock); return; } @@ -1023,6 +1031,7 @@ static int __devinit mmio_probe(struct platform_device *pdev) info->misc_dev.name = MMIO_NAME; info->misc_dev.fops = &mmio_fops; info->misc_dev.parent = pdev->dev.parent; + mutex_init(&info->lock); info->xshutdown_enabled = 0; info->xshutdown_is_active_high = 0; info->trace_allowed = 0; @@ -1119,6 +1128,7 @@ static int __devexit mmio_remove(struct platform_device *pdev) info->pdata->platform_exit(info->pdata); iounmap(info->siabase); iounmap(info->crbase); + mutex_destroy(&info->lock); kfree(info); info = NULL; return 0; -- cgit v1.2.3 From febb8c01c1b0702a3eab3ab41a0369844153e49c Mon Sep 17 00:00:00 2001 From: barge Date: Tue, 18 Oct 2011 14:08:26 +0200 Subject: ux500: nmf cm: Manage the dma lcla in esram Manage the dma lcla in esram instead of ddr Depends-On: I4bc5b72f6d198f26c7b48572cb3843d18c6b8553, I590751f732021c5f2f4da9b7d51ae5dc10087be7, If5d86036b8b9ef72863c447f0e400bb4e51b2ab3 ST-Ericsson ID: 364165 ST-Ericsson FOSS-OUT ID: Trivial: ST-Ericsson Linux next: NA Change-Id: Ic9ac2971bd9f3bf267e04de37b698ff968033ebc Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/34369 Reviewed-by: Sylvain BARGE Reviewed-by: Thierry STRUDEL Tested-by: Sylvain BARGE --- drivers/staging/nmf-cm/cm_dma.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/staging/nmf-cm/cm_dma.c b/drivers/staging/nmf-cm/cm_dma.c index d1c99d6af9a..652b504324c 100644 --- a/drivers/staging/nmf-cm/cm_dma.c +++ b/drivers/staging/nmf-cm/cm_dma.c @@ -94,8 +94,6 @@ int cmdma_setup_relink_area( unsigned int mem_addr, relink[3] = (((dst_addr >> 16) & 0xFFFFUL) << 16 ) | 0x8201UL | ((LOS+1) << 1) | (burst_size<<10); - - (void) dma_map_single(NULL, relink, 16, DMA_TO_DEVICE); } static void cmdma_write_relink_params_per2mem ( @@ -117,8 +115,6 @@ static void cmdma_write_relink_params_per2mem ( relink[3] = (((dst_addr >> 16) & 0xFFFFUL) << 16 ) | 0x1200UL | ((LOS+1) << 1) | (burst_size<<10); - - (void) dma_map_single(NULL, relink, 16, DMA_TO_DEVICE); } static int cmdma_write_cyclic_list_mem2per( @@ -134,7 +130,7 @@ static int cmdma_write_cyclic_list_mem2per( j = LOS; for ( i = 0; i < segments; i++) { - relink = phys_to_virt (cmdma_getlcla() + 1024 * CMDMA_LIDX + 8 * j); + relink = ioremap_nocache (cmdma_getlcla() + 1024 * CMDMA_LIDX + 8 * j, 4 * sizeof(int)); if (i == (segments-1)) j = LOS; @@ -149,6 +145,8 @@ static int cmdma_write_cyclic_list_mem2per( to_addr, 0x2); + iounmap(relink); + from_addr += segmentsize; } @@ -167,7 +165,7 @@ static int cmdma_write_cyclic_list_per2mem( j = LOS; for ( i = 0; i < segments; i++) { - relink = phys_to_virt (cmdma_getlcla() + 1024 * CMDMA_LIDX + 8 * j); + relink = ioremap_nocache (cmdma_getlcla() + 1024 * CMDMA_LIDX + 8 * j, 4 * sizeof(int)); if (i == (segments-1)) j = LOS; @@ -182,6 +180,8 @@ static int cmdma_write_cyclic_list_per2mem( to_addr, 0x2); + iounmap(relink); + to_addr += segmentsize; } -- cgit v1.2.3 From 872dcea1624d339d205e1e8a31e8f29be8d84ccb Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Thu, 20 Oct 2011 13:09:01 +0200 Subject: U8500 CM: fix re-entrancy issue Fix a re-entrancy issue when killing two processes that use the CM driver simultaneously. ST-Ericsson ID: 364585 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I48cb434b87a85b635fe4506a92d7b1c7086071fb Signed-off-by: Pierre Peiffer Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/35216 Reviewed-by: QATOOLS Reviewed-by: QABUILD --- drivers/staging/nmf-cm/cmld.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 7b1061d9d52..ef9753de7a4 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -166,16 +166,15 @@ static inline void freeChannels(struct cm_process_priv* processPriv) { struct list_head* head, *next; int warn = 0; - + + mutex_lock(&channel_lock); list_for_each_safe(head, next, &channel_list) { struct cm_channel_priv *channelPriv; channelPriv = list_entry(head, struct cm_channel_priv, entry); /* Only channels belonging to this process are concerned */ if (channelPriv->proc == processPriv) { tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); list_del(&channelPriv->entry); - mutex_unlock(&channel_lock); tasklet_enable(&cmld_service_tasklet); /* Free all remaining messages if any @@ -191,6 +190,8 @@ static inline void freeChannels(struct cm_process_priv* processPriv) } warn = 1; } + mutex_unlock(&channel_lock); + if (warn) pr_err("[CM - PID=%d]: Some remaining channel entries " "freed\n", current->tgid); -- cgit v1.2.3 From 28aca83fac60b63d03c33428ea5cf02e0ae73523 Mon Sep 17 00:00:00 2001 From: Rajat Verma Date: Thu, 3 Nov 2011 14:53:28 +0530 Subject: staging: mmio: Corrects bug in buffer copy In copy_user_buffer(), result of "kmalloc()" called is checked against NULL as "if (!dest_buf)" whereas correct check must be "if (!*dest_buf)" as memory allocation is done against *dest_buf and not dest_buf. ST-Ericsson ID: 369361 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Change-Id: I78971455a8aa3cb3b31a27572939f2e64fc4d65e Signed-off-by: Rajat Verma Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/36170 Reviewed-by: Jonas ABERG --- drivers/staging/mmio/st_mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/mmio/st_mmio.c b/drivers/staging/mmio/st_mmio.c index 51e92666e28..a006c55c544 100644 --- a/drivers/staging/mmio/st_mmio.c +++ b/drivers/staging/mmio/st_mmio.c @@ -245,7 +245,7 @@ static int copy_user_buffer(void __iomem **dest_buf, *dest_buf = kmalloc(size, GFP_KERNEL); - if (!dest_buf) { + if (!*dest_buf) { err = -ENOMEM; goto nomem; } -- cgit v1.2.3 From 3b3c91a8ba4005fa72bb1e553db7300fce3ffbbb Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Fri, 28 Oct 2011 11:12:48 +0200 Subject: U8500 CM: Add support to get DSP OST Trace on ARM Provide two new devices /dev/cm_sia_trace and /dev/cm_sva_trace that allow any user to retrieve live OST traces coming from DSP component by doing 'cat /dev/cm_sia_trace > file.bin'. This traces are till now available through XTI device. This feature also requires some change in OSTTrace component to be fully operationnal. ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson ID: 324035 ST-Ericsson Linux next: NA Change-Id: I351d3b294667116b8b6900ef7292f4a62d911b9a Signed-off-by: Pierre Peiffer Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/35778 Reviewed-by: QABUILD --- .../nmf-cm/cm/engine/api/control/irq_engine.h | 14 +- .../inc/executive_engine_mgt.h | 6 + .../src/executive_engine_mgt.c | 13 + .../os_adaptation_layer/inc/os_adaptation_layer.h | 4 + .../staging/nmf-cm/cm/engine/trace/inc/xtitrace.h | 8 + drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 109 +++++ drivers/staging/nmf-cm/cm_debug.c | 2 +- drivers/staging/nmf-cm/cm_service.c | 10 +- drivers/staging/nmf-cm/cm_syscall.c | 6 +- drivers/staging/nmf-cm/cmioctl.h | 8 +- drivers/staging/nmf-cm/cmld.c | 450 ++++++++++++++------- drivers/staging/nmf-cm/cmld.h | 46 +++ drivers/staging/nmf-cm/configuration.c | 46 ++- drivers/staging/nmf-cm/configuration.h | 4 +- drivers/staging/nmf-cm/ee/api/panic.idt | 3 +- drivers/staging/nmf-cm/ee/api/trace.idt | 31 ++ drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- drivers/staging/nmf-cm/osal-kernel.c | 22 +- drivers/staging/nmf-cm/osal-kernel.h | 5 +- .../nmf-cm/share/communication/inc/nmf_service.h | 1 + 20 files changed, 593 insertions(+), 197 deletions(-) create mode 100644 drivers/staging/nmf-cm/ee/api/trace.idt diff --git a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h index 20313f13256..e3974764e91 100644 --- a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h +++ b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h @@ -14,6 +14,7 @@ #include #include #include +#include /*! * \brief MPCs -> HOST communication handler @@ -49,7 +50,8 @@ PUBLIC IMPORT_SHARED void CM_ProcessMpcEvent(t_nmf_core_id coreId); typedef enum { // Allowed since i CM_MPC_SERVICE_NONE = 0, //!< No service found CM_MPC_SERVICE_PANIC = 1, //!< Panic service found - CM_MPC_SERVICE_PRINT = 2 //!< Print service found + CM_MPC_SERVICE_PRINT = 2, //!< Print service found + CM_MPC_SERVICE_TRACE = 3 //!< Trace service found } t_cm_service_type; //!< Service description type /*! @@ -105,4 +107,14 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ReadMPCString( char * buffer, t_uint32 bufferSize); +typedef enum { + CM_MPC_TRACE_NONE = 0, + CM_MPC_TRACE_READ = 1, + CM_MPC_TRACE_READ_OVERRUN = 2 +} t_cm_trace_type; + +PUBLIC IMPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( + t_nmf_core_id coreId, + struct t_nmf_trace *trace); + #endif /* CONTROL_IRQ_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h index aacffd15a17..0894410ae0d 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h @@ -24,6 +24,12 @@ typedef struct { t_memory_handle handle; t_cm_logical_address addr; } panicArea; + + // Trace Management + t_uint32 readTracePointer; + t_uint32 lastReadedTraceRevision; + t_memory_handle traceDataHandle; + struct t_nmf_trace *traceDataAddr; } t_ee_state; //TODO, juraj, this should be done more properly, like accessor method, instead making this global variable.. diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c index f2c833ff7dc..4df3d7ee0f5 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c @@ -21,6 +21,8 @@ #include #include +#include + #include t_ee_state eeState[NB_CORE_IDS]; @@ -130,6 +132,16 @@ PUBLIC t_cm_error cm_EEM_Init( return error; } + if((error = cm_SRV_allocateTraceBufferMemory(coreId, cm_DSP_GetState(coreId)->domainEE)) != CM_OK) + { + cm_PFM_deallocatePerfmeterDataMemory(coreId); + cm_EEM_freePanicArea(coreId); + cm_delayedDestroyComponent(eeState[coreId].instance); + eeState[coreId].instance = (t_component_instance *)0; + cm_DSP_Shutdown(coreId); + return error; + } + /* set initial stack value */ cm_writeAttribute(eeState[coreId].instance, "rtos/scheduler/topOfStack", cm_DSP_getStackAddr(coreId)); @@ -179,6 +191,7 @@ PUBLIC void cm_EEM_Close(t_nmf_core_id coreId) cm_DSP_setStackSize(coreId, 0); cm_delayedDestroyComponent(eeState[coreId].instance); eeState[coreId].instance = (t_component_instance *)0; + cm_SRV_deallocateTraceBufferMemory(coreId); cm_PFM_deallocatePerfmeterDataMemory(coreId); cm_EEM_freePanicArea(coreId); cm_DSP_Shutdown(coreId); diff --git a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h index f57c92ea41b..c9ec864795f 100644 --- a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h +++ b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h @@ -44,6 +44,10 @@ typedef t_uint8 t_nmf_osal_sync_error; #define SEM_TIMEOUT_NORMAL 3000 #define SEM_TIMEOUT_DEBUG 300000 +/*! + * \brief Operations used to support additionnal OS-specific debug feature + * \ingroup CM_ENGINE_OSAL_API + */ struct osal_debug_operations { void (*component_create)(t_component_instance *component); void (*component_destroy)(t_component_instance *component); diff --git a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h index 6ab960b69b2..1efd4f1e699 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h +++ b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h @@ -39,4 +39,12 @@ void cm_TRC_traceMemAlloc(t_nmfTraceAllocatorCommandDescription command, t_uint8 void cm_TRC_traceMem(t_nmfTraceAllocCommandDescription command, t_uint8 allocId, t_uint32 startAddress, t_uint32 memorySize); +/*************************/ +/* MMDSP trace buffer */ +/*************************/ +PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId); +PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId); + + + #endif /* __INC_CM_TRACE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c index 9cb1a729a92..e59d9f8b1ba 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -13,6 +13,111 @@ #include #include +PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + + state->traceDataHandle = cm_DM_Alloc(domainId, SDRAM_EXT16, + TRACE_BUFFER_SIZE * sizeof(struct t_nmf_trace) / 2, CM_MM_ALIGN_WORD, TRUE); + if (state->traceDataHandle == INVALID_MEMORY_HANDLE) + return CM_NO_MORE_MEMORY; + else + { + t_uint32 mmdspAddr; + int i; + + state->traceDataAddr = (struct t_nmf_trace*)cm_DSP_GetHostLogicalAddress(state->traceDataHandle); + cm_DSP_GetDspAddress(state->traceDataHandle, &mmdspAddr); + cm_writeAttribute(state->instance, "rtos/commonpart/traceDataAddr", mmdspAddr); + + eeState[coreId].readTracePointer = 0; + eeState[coreId].lastReadedTraceRevision = 0; + + for(i = 0; i < TRACE_BUFFER_SIZE; i++) + state->traceDataAddr[i].revision = 0; + + return CM_OK; + } +} + +PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + + state->traceDataAddr = 0; + cm_DM_Free(state->traceDataHandle, TRUE); +} + +static t_uint32 swapHalfWord(t_uint32 word) +{ + return (word >> 16) | (word << 16); +} + +PUBLIC EXPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( + t_nmf_core_id coreId, + struct t_nmf_trace *trace) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + t_uint32 foundRevision; + t_cm_trace_type type; + + OSAL_LOCK_API(); + if (state->traceDataAddr == NULL) { + type = CM_MPC_TRACE_NONE; + goto out; + } + + foundRevision = swapHalfWord(state->traceDataAddr[state->readTracePointer].revision); + + if(foundRevision <= state->lastReadedTraceRevision) + { + // It's an old trace forgot it + type = CM_MPC_TRACE_NONE; + } + else + { + struct t_nmf_trace *traceRaw; + + if(foundRevision == state->lastReadedTraceRevision + 1) + { + type = CM_MPC_TRACE_READ; + } + else + { + type = CM_MPC_TRACE_READ_OVERRUN; + /* + * If we find that revision is bigger, thus we are in overrun, then we take the writePointer + 1 which + * correspond to the older one. + * => Here there is a window where the MMDSP could update writePointer just after + */ + state->readTracePointer = (cm_readAttributeNoError(state->instance, "rtos/commonpart/writePointer") + 1) % TRACE_BUFFER_SIZE; + } + + traceRaw = &state->traceDataAddr[state->readTracePointer]; + + trace->timeStamp = swapHalfWord(traceRaw->timeStamp); + trace->componentId = swapHalfWord(traceRaw->componentId); + trace->traceId = swapHalfWord(traceRaw->traceId); + trace->paramOpt = swapHalfWord(traceRaw->paramOpt); + trace->componentHandle = swapHalfWord(traceRaw->componentHandle); + trace->parentHandle = swapHalfWord(traceRaw->parentHandle); + + trace->params[0] = swapHalfWord(traceRaw->params[0]); + trace->params[1] = swapHalfWord(traceRaw->params[1]); + trace->params[2] = swapHalfWord(traceRaw->params[2]); + trace->params[3] = swapHalfWord(traceRaw->params[3]); + + state->readTracePointer = (state->readTracePointer + 1) % TRACE_BUFFER_SIZE; + state->lastReadedTraceRevision = swapHalfWord(traceRaw->revision); + trace->revision = state->lastReadedTraceRevision; + } + +out: + OSAL_UNLOCK_API(); + + return type; +} + /* * Panic @@ -139,6 +244,10 @@ PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( srcDescr->u.print.value1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); srcDescr->u.print.value2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); } + else if(serviceReason == MPC_SERVICE_TRACE) + { + *srcType = CM_MPC_SERVICE_TRACE; + } else if(serviceReason != MPC_SERVICE_NONE) { t_uint32 panicThis; diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c index a934aa33e92..26446e19cdb 100644 --- a/drivers/staging/nmf-cm/cm_debug.c +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -5,12 +5,12 @@ */ #include -#include #include "osal-kernel.h" #include "cm_debug.h" #ifdef CONFIG_DEBUG_FS +#include static struct dentry *cm_dir; /* nmf-cm/ */ static struct dentry *proc_dir; /* nmf-cm/proc/ */ diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index 70cf6f37524..a2a6ffa5b57 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -12,9 +12,9 @@ #include #include +#include #include #include -#include #include @@ -71,7 +71,7 @@ void dispatch_service_msg(struct osal_msg *msg) spin_lock_bh(&channelPriv->bh_lock); plist_add(&new_msg->msg_entry, &channelPriv->messageQueue); spin_unlock_bh(&channelPriv->bh_lock); - wake_up_interruptible(&channelPriv->waitq); + wake_up(&channelPriv->waitq); } } @@ -113,6 +113,12 @@ static void service_tasklet_func(unsigned long unused) desc.u.print.value2); break; } + case CM_MPC_SERVICE_TRACE: + spin_lock_bh(&osalEnv.mpc[i].trace_reader_lock); + if (osalEnv.mpc[i].trace_reader) + wake_up_process(osalEnv.mpc[i].trace_reader); + spin_unlock_bh(&osalEnv.mpc[i].trace_reader_lock); + break; default: pr_err("[CM] %s: MPC Service Type %d not supported\n", __func__, type); } diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index a687e0206a3..ca8d664abb4 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -5,11 +5,11 @@ */ #include +#include #include #include #include #include -#include #include "cmioctl.h" #include "osal-kernel.h" #include "cmld.h" @@ -1397,9 +1397,9 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd /* Mark this memory area reserved for a mapping for this thread ID */ /* It must not be already reserved but this should not happen */ if (curr->tid) { - /*pr_err("%s: thread %d can't reseveved memory %x already " + pr_err("%s: thread %d can't reseveved memory %x already " "reserved for %d\n", - __func__, current->pid, physAddr, (int)curr->tid);*/ + __func__, current->pid, physAddr, curr->tid); err = -EBUSY; } else { curr->tid = current->pid; diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h index 96481be38b8..5f7d5b6a349 100644 --- a/drivers/staging/nmf-cm/cmioctl.h +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -29,9 +29,11 @@ enum cmdma_type { CMDMA_PER_2_MEM }; -#define CMLD_DEV_NAME \ - { "cm_control", \ - "cm_channel" \ +#define CMLD_DEV_NAME \ + { "cm_control", \ + "cm_channel", \ + "cm_sia_trace", \ + "cm_sva_trace", \ } /* diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index ef9753de7a4..17af63ac407 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -14,9 +14,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -29,7 +29,7 @@ #include "cm_service.h" #include "cm_dma.h" -#define CMDRIVER_PATCH_VERSION 117 +#define CMDRIVER_PATCH_VERSION 121 #define O_FLUSH 0x1000000 static int cmld_major; @@ -233,111 +233,6 @@ static void freeProcessPriv(struct kref *ref) OSAL_Free(entry); } -/** Driver's open method - * Allocates per-process resources: private data, wait queue, - * memory area descriptors linked list, message queue. - * - * \return POSIX error code - */ -static int cmld_open(struct inode *inode, struct file *file) -{ - struct cm_process_priv *procPriv = getProcessPriv(); - - if (IS_ERR(procPriv)) - return PTR_ERR(procPriv); - - if (iminor(inode) == 0) - file->private_data = procPriv; - else { - struct cm_channel_priv *channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); - if (channelPriv == NULL) { - kref_put(&procPriv->ref, freeProcessPriv); - return -ENOMEM; - } - - channelPriv->proc = procPriv; - channelPriv->state = CHANNEL_OPEN; - - /* Initialize wait_queue, lists and mutexes */ - init_waitqueue_head(&channelPriv->waitq); - plist_head_init(&channelPriv->messageQueue); - INIT_LIST_HEAD(&channelPriv->skelList); - spin_lock_init(&channelPriv->bh_lock); - mutex_init(&channelPriv->msgQueueLock); - mutex_init(&channelPriv->skelListLock); - - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_add(&channelPriv->entry, &channel_list); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - file->private_data = channelPriv; // store channel private struct in file descriptor - } - return 0; -} - -/** Driver's release method. - * Frees any per-process pending resource: components, bindings, memory areas. - * - * \return POSIX error code - */ -static int cmld_release(struct inode *inode, struct file *file) -{ - struct cm_process_priv* procPriv; - - /* The driver must guarantee that all related resources are released. - Thus all these checks below are necessary to release all remaining - resources still linked to this 'client', in case of abnormal process - exit. - => These are error cases ! - In the usual case, nothing should be done except the free of - the cmPriv itself - */ - - if (iminor(inode) != 0) { - struct cm_channel_priv* channelPriv; - channelPriv = file->private_data; - procPriv = channelPriv->proc; - - /* We don't need to synchronize here by using the skelListLock: - the list is only accessed during ioctl() and we can't be here - if an ioctl() is on-going */ - if (list_empty(&channelPriv->skelList)) { - /* There is no pending MPC->HOST binding - => we can quietly delete the channel */ - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_del(&channelPriv->entry); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - /* Free all remaining messages if any */ - freeMessages(channelPriv); - - /* Free the per-channel descriptor */ - OSAL_Free(channelPriv); - } else { - /* Uh: there are still some MPC->HOST binding but we don't have the - required info to unbind them. - => we must keep all skel structures because possibly used in OSAL_PostDfc - (incoming callback msg) */ - /* We flag the channel as closed to discard any new msg that will never be read anyway */ - channelPriv->state = CHANNEL_CLOSED; - - /* Already Free all remaining messages if any, - they will never be read anyway */ - freeMessages(channelPriv); - } - } else - procPriv = file->private_data; - - kref_put(&procPriv->ref, freeProcessPriv); - file->private_data = NULL; - - return 0; -} - /** Reads Component Manager messages destinated to this process. * The message is composed by three fields: * 1) mpc2host handle (distinguishes interfaces) @@ -347,19 +242,16 @@ static int cmld_release(struct inode *inode, struct file *file) * \note cfr GetEvent() * \return POSIX error code */ -static ssize_t cmld_read(struct file *file, char *buf, size_t count, loff_t *ppos) +static ssize_t cmld_channel_read(struct file *file, char *buf, size_t count, loff_t *ppos) { int err = 0; - struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); + struct cm_channel_priv* channelPriv = file->private_data; int msgSize = 0; struct plist_head* messageQueue; struct osal_msg* msg; t_os_message *os_msg = (t_os_message *)buf; int block = !(file->f_flags & O_NONBLOCK); - if (iminor(file->f_dentry->d_inode) == 0) - return -ENOSYS; - messageQueue = &channelPriv->messageQueue; if (mutex_lock_killable(&channelPriv->msgQueueLock)) @@ -371,7 +263,7 @@ wait: if (block == 0) return -EAGAIN; /* Wait until there is a message to ferry up */ - if (wait_event_interruptible(channelPriv->waitq, ((!plist_head_empty(messageQueue)) || (file->f_flags & O_FLUSH)))) + if (wait_event_killable(channelPriv->waitq, ((!plist_head_empty(messageQueue)) || (file->f_flags & O_FLUSH)))) return -ERESTARTSYS; if (file->f_flags & O_FLUSH) { file->f_flags &= ~O_FLUSH; @@ -459,19 +351,21 @@ out: * * \return POSIX error code */ -static int cmld_flush(struct file *file, fl_owner_t id) +static int cmld_channel_flush(struct file *file, fl_owner_t id) { - if (iminor(file->f_dentry->d_inode) != 0) { - struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); - file->f_flags |= O_FLUSH; - wake_up_interruptible(&channelPriv->waitq); - } + struct cm_channel_priv* channelPriv = file->private_data; + file->f_flags |= O_FLUSH; + wake_up(&channelPriv->waitq); return 0; } -static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_channel_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_channel_priv *channelPriv = file->private_data; +#ifdef CONFIG_DEBUG_FS + if (wait_event_killable(dump_waitq, (!cmld_dump_ongoing))) + return -ERESTARTSYS; +#endif switch(cmd) { /* @@ -480,7 +374,7 @@ static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long case CM_BINDCOMPONENTTOCMCORE: return cmld_BindComponentToCMCore(channelPriv, (CM_BindComponentToCMCore_t *)arg); case CM_FLUSHCHANNEL: - return cmld_flush(file, 0); + return cmld_channel_flush(file, 0); default: pr_err("CM(%s): unsupported command %i\n", __func__, cmd); return -EINVAL; @@ -488,9 +382,18 @@ static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long return 0; } -static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_process_priv* procPriv = file->private_data; +#ifdef CONFIG_DEBUG_FS + if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { + cmld_dump_ongoing = false; + wake_up(&dump_waitq); + return 0; + } else if (wait_event_killable(dump_waitq, (!cmld_dump_ongoing))) + return -ERESTARTSYS; +#endif + switch(cmd) { /* * All wrapped CM SYSCALL @@ -695,7 +598,6 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long cmld_user_has_debugfs = true; #endif return 0; - case CM_PRIV_DEBUGFS_DUMP_DONE: case CM_PRIV_DEBUGFS_WAIT_DUMP: return 0; default: @@ -706,29 +608,6 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long return 0; } -/** Driver's ioctl method - * Implements user/kernel crossing for SYSCALL API. - * - * \return POSIX error code - */ -static long cmld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ -#ifdef CONFIG_DEBUG_FS - if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { - cmld_dump_ongoing = false; - wake_up_interruptible(&dump_waitq); - return 0; - } else if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) - return -ERESTARTSYS; -#endif - - if (iminor(filp->f_dentry->d_inode) == 0) { - return cmld_control_ctl(filp, cmd, arg); - } else { - return cmld_channel_ctl(filp, cmd, arg); - } -} - /** VMA open callback function */ static void cmld_vma_open(struct vm_area_struct* vma) { @@ -755,7 +634,7 @@ static struct vm_operations_struct cmld_remap_vm_ops = { * * \return POSIX error code */ -static int cmld_mmap(struct file* file, struct vm_area_struct* vma) +static int cmld_control_mmap(struct file *file, struct vm_area_struct *vma) { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; struct list_head* listHead; @@ -827,6 +706,278 @@ static int cmld_mmap(struct file* file, struct vm_area_struct* vma) return 0; } +/* Driver's release method for /dev/cm_channel */ +static int cmld_channel_release(struct inode *inode, struct file *file) +{ + struct cm_channel_priv* channelPriv = file->private_data; + struct cm_process_priv* procPriv = channelPriv->proc; + + /* + * The driver must guarantee that all related resources are released. + * Thus all these checks below are necessary to release all remaining + * resources still linked to this 'client', in case of abnormal process + * exit. + * => These are error cases ! + * In the usual case, nothing should be done except the free of + * the cmPriv itself + */ + + /* We don't need to synchronize here by using the skelListLock: + the list is only accessed during ioctl() and we can't be here + if an ioctl() is on-going */ + if (list_empty(&channelPriv->skelList)) { + /* There is no pending MPC->HOST binding + => we can quietly delete the channel */ + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_del(&channelPriv->entry); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + /* Free all remaining messages if any */ + freeMessages(channelPriv); + + /* Free the per-channel descriptor */ + OSAL_Free(channelPriv); + } else { + /* + * Uh: there are still some MPC->HOST binding but we don't have + * the required info to unbind them. + * => we must keep all skel structures because possibly used in + * OSAL_PostDfc (incoming callback msg). We flag the channel as + * closed to discard any new msg that will never be read anyway + */ + channelPriv->state = CHANNEL_CLOSED; + + /* Already Free all remaining messages if any, + they will never be read anyway */ + freeMessages(channelPriv); + } + + kref_put(&procPriv->ref, freeProcessPriv); + file->private_data = NULL; + + return 0; +} + +/* Driver's release method for /dev/cm_control */ +static int cmld_control_release(struct inode *inode, struct file *file) +{ + struct cm_process_priv* procPriv = file->private_data; + + kref_put(&procPriv->ref, freeProcessPriv); + file->private_data = NULL; + + return 0; +} + +static struct file_operations cmld_control_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = cmld_control_ioctl, + .mmap = cmld_control_mmap, + .release = cmld_control_release, +}; + +static int cmld_control_open(struct file *file) +{ + struct cm_process_priv *procPriv = getProcessPriv(); + if (IS_ERR(procPriv)) + return PTR_ERR(procPriv); + file->private_data = procPriv; + file->f_op = &cmld_control_fops; + return 0; +} + +static struct file_operations cmld_channel_fops = { + .owner = THIS_MODULE, + .read = cmld_channel_read, + .unlocked_ioctl = cmld_channel_ioctl, + .flush = cmld_channel_flush, + .release = cmld_channel_release, +}; + +static int cmld_channel_open(struct file *file) +{ + struct cm_process_priv *procPriv = getProcessPriv(); + struct cm_channel_priv *channelPriv; + + if (IS_ERR(procPriv)) + return PTR_ERR(procPriv); + + channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); + if (channelPriv == NULL) { + kref_put(&procPriv->ref, freeProcessPriv); + return -ENOMEM; + } + + channelPriv->proc = procPriv; + channelPriv->state = CHANNEL_OPEN; + + /* Initialize wait_queue, lists and mutexes */ + init_waitqueue_head(&channelPriv->waitq); + plist_head_init(&channelPriv->messageQueue); + INIT_LIST_HEAD(&channelPriv->skelList); + spin_lock_init(&channelPriv->bh_lock); + mutex_init(&channelPriv->msgQueueLock); + mutex_init(&channelPriv->skelListLock); + + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_add(&channelPriv->entry, &channel_list); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + file->private_data = channelPriv; + file->f_op = &cmld_channel_fops; + return 0; +} + +static ssize_t cmld_sxa_trace_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + struct mpcConfig *mpc = file->private_data; + size_t written = 0; + struct t_nmf_trace trace; + t_cm_trace_type traceType; + struct mmdsp_trace mmdsp_tr = { + .media = TB_MEDIA_FILE, + .receiver_dev = TB_DEV_PC, + .sender_dev = TB_DEV_TRACEBOX, + .unused = TB_TRACEBOX, + .receiver_obj = DEFAULT_RECEIVERR_OBJ, + .sender_obj = DEFAULT_SENDER_OBJ, + .transaction_id = 0, + .message_id = TB_TRACE_MSG, + .master_id = mpc->coreId+1, + .channel_id = 0, + .ost_version = OST_VERSION, + .entity = ENTITY, + .protocol_id = PROTOCOL_ID, + .btrace_hdr_flag = 0, + .btrace_hdr_subcategory = 0, + }; + + while ((count - written) >= sizeof(mmdsp_tr)) { + traceType = CM_ENGINE_GetNextTrace(mpc->coreId, &trace); + + switch (traceType) { + case CM_MPC_TRACE_READ_OVERRUN: + mmdsp_tr.size = + cpu_to_be16(offsetof(struct mmdsp_trace, + ost_version) + -offsetof(struct mmdsp_trace, + receiver_obj)); + mmdsp_tr.message_id = TB_TRACE_EXCEPTION_MSG; + mmdsp_tr.ost_master_id = TB_EXCEPTION_LONG_OVRF_PACKET; + if (copy_to_user(&buf[written], &mmdsp_tr, + offsetof(struct mmdsp_trace, + ost_version))) + return -EFAULT; + written += offsetof(struct mmdsp_trace, ost_version); + if ((count - written) < sizeof(mmdsp_tr)) + break; + case CM_MPC_TRACE_READ: { + u16 param_nr = (u16)trace.paramOpt; + u16 handle_valid = (u16)(trace.paramOpt >> 16); + u32 to_write = offsetof(struct mmdsp_trace, + parent_handle); + mmdsp_tr.transaction_id = trace.revision%256; + mmdsp_tr.message_id = TB_TRACE_MSG; + mmdsp_tr.ost_master_id = OST_MASTERID; + mmdsp_tr.timestamp = cpu_to_be64(trace.timeStamp); + mmdsp_tr.timestamp2 = cpu_to_be64(trace.timeStamp); + mmdsp_tr.component_id = cpu_to_be32(trace.componentId); + mmdsp_tr.trace_id = cpu_to_be32(trace.traceId); + mmdsp_tr.btrace_hdr_category = (trace.traceId>>16)&0xFF; + mmdsp_tr.btrace_hdr_size = BTRACE_HEADER_SIZE + + sizeof(trace.params[0]) * param_nr; + if (handle_valid) { + mmdsp_tr.parent_handle = trace.parentHandle; + mmdsp_tr.component_handle = + trace.componentHandle; + to_write += sizeof(trace.parentHandle) + + sizeof(trace.componentHandle); + mmdsp_tr.btrace_hdr_size += + sizeof(trace.parentHandle) + + sizeof(trace.componentHandle); + } + mmdsp_tr.size = + cpu_to_be16(to_write + + (sizeof(trace.params[0])*param_nr) + - offsetof(struct mmdsp_trace, + receiver_obj)); + mmdsp_tr.length = to_write + + (sizeof(trace.params[0])*param_nr) + - offsetof(struct mmdsp_trace, + timestamp2); + if (copy_to_user(&buf[written], &mmdsp_tr, to_write)) + return -EFAULT; + written += to_write; + /* write param */ + to_write = sizeof(trace.params[0]) * param_nr; + if (copy_to_user(&buf[written], trace.params, to_write)) + return -EFAULT; + written += to_write; + break; + } + case CM_MPC_TRACE_NONE: + default: + if ((file->f_flags & O_NONBLOCK) || written) + return written; + spin_lock_bh(&mpc->trace_reader_lock); + mpc->trace_reader = current; + spin_unlock_bh(&mpc->trace_reader_lock); + schedule_timeout_killable(msecs_to_jiffies(200)); + spin_lock_bh(&mpc->trace_reader_lock); + mpc->trace_reader = NULL; + spin_unlock_bh(&mpc->trace_reader_lock); + if (signal_pending(current)) + return -ERESTARTSYS; + } + } + return written; +} + +/* Driver's release method for /dev/cm_sxa_trace */ +static int cmld_sxa_trace_release(struct inode *inode, struct file *file) +{ + struct mpcConfig *mpc = file->private_data; + atomic_dec(&mpc->trace_read_count); + return 0; +} + +static struct file_operations cmld_sxa_trace_fops = { + .owner = THIS_MODULE, + .read = cmld_sxa_trace_read, + .release = cmld_sxa_trace_release, +}; + +static int cmld_sxa_trace_open(struct file *file, struct mpcConfig *mpc) +{ + if (atomic_add_unless(&mpc->trace_read_count, 1, 1) == 0) + return -EBUSY; + + file->private_data = mpc; + file->f_op = &cmld_sxa_trace_fops; + return 0; +} + +/* driver open() call: specific */ +static int cmld_open(struct inode *inode, struct file *file) +{ + switch (iminor(inode)) { + case 0: + return cmld_control_open(file); + case 1: + return cmld_channel_open(file); + case 2: + return cmld_sxa_trace_open(file, &osalEnv.mpc[SIA]); + case 3: + return cmld_sxa_trace_open(file, &osalEnv.mpc[SVA]); + default: + return -ENOSYS; + } +} + /** MPC Events tasklet * The parameter is used to know from which interrupts we're comming * and which core to pass to CM_ProcessMpcEvent(): @@ -882,12 +1033,7 @@ static irqreturn_t panic_handler(int irq, void *idx) */ static struct file_operations cmld_fops = { .owner = THIS_MODULE, - .read = cmld_read, - .unlocked_ioctl = cmld_ioctl, - .mmap = cmld_mmap, .open = cmld_open, - .flush = cmld_flush, - .release = cmld_release, }; /** diff --git a/drivers/staging/nmf-cm/cmld.h b/drivers/staging/nmf-cm/cmld.h index 4c5a5bed7e6..17e6c55ff61 100644 --- a/drivers/staging/nmf-cm/cmld.h +++ b/drivers/staging/nmf-cm/cmld.h @@ -79,6 +79,52 @@ extern bool cmld_user_has_debugfs; /**< Whether user side has proper support of extern bool cmld_dump_ongoing; /**< Whether a dump is on-going */ #endif +/* Structure used to embed DSP traces */ +#define TB_MEDIA_FILE 0x1C +#define TB_DEV_PC 0x10 +#define TB_DEV_TRACEBOX 0x4C +#define TB_TRACEBOX 0x7C +#define DEFAULT_RECEIVERR_OBJ 0x0 +#define DEFAULT_SENDER_OBJ 0x0A +#define TB_TRACE_MSG 0x94 +#define TB_TRACE_EXCEPTION_MSG 0x95 +#define TB_EXCEPTION_LONG_OVRF_PACKET 0x07 +#define OST_MASTERID 0x08 +#define OST_VERSION 0x05 +#define ENTITY 0xAA +#define PROTOCOL_ID 0x03 +#define BTRACE_HEADER_SIZE 4 + +struct __attribute__ ((__packed__)) mmdsp_trace { + u8 media; + u8 receiver_dev; + u8 sender_dev; + u8 unused; + u16 size; + u8 receiver_obj; + u8 sender_obj; + u8 transaction_id; + u8 message_id; + u8 master_id; + u8 channel_id; + u64 timestamp; + u8 ost_master_id; + u8 ost_version; + u8 entity; + u8 protocol_id; + u8 length; + u64 timestamp2; + u32 component_id; + u32 trace_id; + u8 btrace_hdr_size; + u8 btrace_hdr_flag; + u8 btrace_hdr_category; + u8 btrace_hdr_subcategory; + u32 parent_handle; + u32 component_handle; + u32 params[4]; +}; + /** Lock/unlock per process mutex * * \note Must be taken before tasklet_disable (if necessary)! diff --git a/drivers/staging/nmf-cm/configuration.c b/drivers/staging/nmf-cm/configuration.c index d62bcb45500..523874fc586 100644 --- a/drivers/staging/nmf-cm/configuration.c +++ b/drivers/staging/nmf-cm/configuration.c @@ -21,28 +21,30 @@ struct OsalEnvironment osalEnv = { .mpc = { { - .coreId = SVA_CORE_ID, - .name = "sva", - .base_phys = (void*)U8500_SVA_BASE, - .interrupt0 = IRQ_DB8500_SVA, - .interrupt1 = IRQ_DB8500_SVA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, + .coreId = SVA_CORE_ID, + .name = "sva", + .base_phys = (void*)U8500_SVA_BASE, + .interrupt0 = IRQ_DB8500_SVA, + .interrupt1 = IRQ_DB8500_SVA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, + .trace_read_count = ATOMIC_INIT(0), }, { - .coreId = SIA_CORE_ID, - .name = "sia", - .base_phys = (void*)U8500_SIA_BASE, - .interrupt0 = IRQ_DB8500_SIA, - .interrupt1 = IRQ_DB8500_SIA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, + .coreId = SIA_CORE_ID, + .name = "sia", + .base_phys = (void*)U8500_SIA_BASE, + .interrupt0 = IRQ_DB8500_SIA, + .interrupt1 = IRQ_DB8500_SIA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, + .trace_read_count = ATOMIC_INIT(0), } }, .esram_regulator = { NULL, NULL}, @@ -125,16 +127,20 @@ int init_config(void) pr_err("SDRAM data size for SVA must be greater than 0\n"); return -EINVAL; } + osalEnv.mpc[SVA].nbYramBanks = cfgMpcYBanks_SVA; osalEnv.mpc[SVA].eeId = cfgSchedulerTypeHybrid_SVA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SVA].sdram_code.size = cfgMpcSDRAMCodeSize_SVA * ONE_KB; osalEnv.mpc[SVA].sdram_data.size = cfgMpcSDRAMDataSize_SVA * ONE_KB; osalEnv.mpc[SVA].base.size = 128*ONE_KB; //we expose only TCM24 + spin_lock_init(&osalEnv.mpc[SVA].trace_reader_lock); + osalEnv.mpc[SIA].nbYramBanks = cfgMpcYBanks_SIA; osalEnv.mpc[SIA].eeId = cfgSchedulerTypeHybrid_SIA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SIA].sdram_code.size = cfgMpcSDRAMCodeSize_SIA * ONE_KB; osalEnv.mpc[SIA].sdram_data.size = cfgMpcSDRAMDataSize_SIA * ONE_KB; osalEnv.mpc[SIA].base.size = 128*ONE_KB; //we expose only TCM24 + spin_lock_init(&osalEnv.mpc[SIA].trace_reader_lock); return 0; } diff --git a/drivers/staging/nmf-cm/configuration.h b/drivers/staging/nmf-cm/configuration.h index 35072831a13..f4146dc6117 100644 --- a/drivers/staging/nmf-cm/configuration.h +++ b/drivers/staging/nmf-cm/configuration.h @@ -20,12 +20,14 @@ #endif /* Embedded Static RAM base address */ -#define ESRAM_BASE (U8500_ESRAM_BASE + 0x10000) // V1/V2 config: 0-64k: secure; +/* config: 0-64k: secure */ +#define ESRAM_BASE (U8500_ESRAM_BASE + U8500_ESRAM_DMA_LCPA_OFFSET) /* * Embedded ram size for CM (in Kb) * 5 banks of 128k: skip the first half bank (secure) and the last * one (used for MCDE/B2R2), but include DMA part (4k after the secure part) + * to give access from DSP side */ #define ESRAM_SIZE 448 enum { diff --git a/drivers/staging/nmf-cm/ee/api/panic.idt b/drivers/staging/nmf-cm/ee/api/panic.idt index f971fdad8c5..53135819f4a 100644 --- a/drivers/staging/nmf-cm/ee/api/panic.idt +++ b/drivers/staging/nmf-cm/ee/api/panic.idt @@ -55,7 +55,8 @@ typedef enum { INTERFACE_NOT_BINDED = 8, USER_PANIC = 9, UNBIND_INTERRUPT = 10, - EVENT_FIFO_IN_USE = 11 + EVENT_FIFO_IN_USE = 11, + RESERVED_PANIC = 2 //for COMPATIBILITY with previous versions of NMF, to be deprecated } t_panic_reasonDescription; /*! diff --git a/drivers/staging/nmf-cm/ee/api/trace.idt b/drivers/staging/nmf-cm/ee/api/trace.idt new file mode 100644 index 00000000000..3c21c6a860f --- /dev/null +++ b/drivers/staging/nmf-cm/ee/api/trace.idt @@ -0,0 +1,31 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ + +/*! + * \defgroup NMF_EE_TYPE Execution Engine Common Type Definitions + * \ingroup COMMON + */ + +#ifndef __INC_TRACE_IDT +#define __INC_TRACE_IDT + +struct t_nmf_trace +{ + t_uint32 revision; + t_uint32 timeStamp; + t_uint32 componentId; + t_uint32 traceId; + t_uint32 paramOpt; + t_uint32 componentHandle; + t_uint32 parentHandle; + t_uint32 params[4]; +}; + +#define TRACE_BUFFER_SIZE 128 + +#endif diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index e671198f7b9..5cb1ec7fcec 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (118)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (121)) /*! * \brief Get NMF major version corresponding to NMF version number diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 94aa11fc91c..e79e35db106 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -353,7 +353,7 @@ void OSAL_PostDfc(t_nmf_mpc2host_handle upLayerTHIS, t_uint32 methodIndex, t_eve spin_unlock_bh(&skelwrapper->channelPriv->bh_lock); /* Wake up process' wait queue */ - wake_up_interruptible(&skelwrapper->channelPriv->waitq); + wake_up(&skelwrapper->channelPriv->waitq); } @@ -755,8 +755,8 @@ static int dspload_monitor(void *idx) /* init counter */ if (CM_GetMpcLoadCounter(mpc->coreId, &mpc->oldLoadCounter) != CM_OK) - pr_err("CM Driver: Failed to init load counter for %s\n", - mpc->name); + pr_warn("CM Driver: Failed to init load counter for %s\n", + mpc->name); while (!kthread_should_stop()) { t_cm_mpc_load_counter loadCounter; @@ -919,7 +919,7 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); + secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -927,16 +927,16 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= 0x40000; + secondParam /= (2*U8500_ESRAM_BANK_SIZE); WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < (U8500_ESRAM_BASE+0x20000)) + if (firstParam < U8500_ESRAM_BANK1) firstParam = 0; else - firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; + firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); /* power off the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { @@ -1032,7 +1032,7 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); + secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -1040,16 +1040,16 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= 0x40000; + secondParam /= (2*U8500_ESRAM_BANK_SIZE); WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < (U8500_ESRAM_BASE+0x20000)) + if (firstParam < U8500_ESRAM_BANK1) firstParam = 0; else - firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; + firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); /* power on the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { diff --git a/drivers/staging/nmf-cm/osal-kernel.h b/drivers/staging/nmf-cm/osal-kernel.h index 7a71bdd591d..dc9bc8445ac 100644 --- a/drivers/staging/nmf-cm/osal-kernel.h +++ b/drivers/staging/nmf-cm/osal-kernel.h @@ -11,6 +11,7 @@ #include #include #include +#include #ifdef CONFIG_HAS_WAKELOCK #include #endif @@ -24,7 +25,6 @@ */ #define _CM_ELF_H #include -#include #include "configuration.h" @@ -56,6 +56,9 @@ struct mpcConfig { #endif struct task_struct *monitor_tsk; /**< task to monitor the dsp load; */ t_cm_mpc_load_counter oldLoadCounter; /**< previous load counter of the DSP */ + atomic_t trace_read_count; /**< number of trace reader */ + spinlock_t trace_reader_lock; + struct task_struct *trace_reader;/**< current reader task */ #ifdef CONFIG_DEBUG_FS struct dentry *dir; /**< debugfs dir entry */ struct dentry *comp_dir; /**< debugfs component dir entry */ diff --git a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h index 5ec08434492..71dfc534f97 100644 --- a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h +++ b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h @@ -12,5 +12,6 @@ #define MPC_SERVICE_NONE 0 #define MPC_SERVICE_BOOT 0xB001 #define MPC_SERVICE_PRINT 0x1234 +#define MPC_SERVICE_TRACE 0x789 #endif -- cgit v1.2.3 From d15e182dc74e2470dd8300436f665eccbc0fb179 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 12 Jan 2012 11:54:00 +0100 Subject: mmio: ux500: Coding style fixes Fix the most obvious violations of the kernel coding style Signed-off-by: Jonas Aaberg --- arch/arm/mach-ux500/board-u5500-mmio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/board-u5500-mmio.c b/arch/arm/mach-ux500/board-u5500-mmio.c index 0f1c00c4a5d..8c84aebccee 100644 --- a/arch/arm/mach-ux500/board-u5500-mmio.c +++ b/arch/arm/mach-ux500/board-u5500-mmio.c @@ -24,7 +24,7 @@ #include "board-u5500.h" #include -struct mmio_board_data{ +struct mmio_board_data { int number_of_regulators; struct regulator **mmio_regulators; /* * Pin configs */ @@ -150,7 +150,7 @@ err_no_mem_reg: static void mmio_power_exit(struct mmio_platform_data *pdata) { int i = 0; - struct mmio_board_data *extra = pdata->extra;; + struct mmio_board_data *extra = pdata->extra; for (i = 0; i < extra->number_of_regulators; i++) regulator_put(extra->mmio_regulators[i]); -- cgit v1.2.3 From 1e96d1026edb86c7e6f62dfdfcdcf1110aac1cd7 Mon Sep 17 00:00:00 2001 From: himansh Date: Wed, 9 Nov 2011 16:11:59 +0530 Subject: Revert "U8500 CM: Add support to get DSP OST Trace on ARM" This reverts commit 6cfa5e388f0250764e7b9d11d2c3f141b408a93e. ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson ID: 373198 ST-Ericsson Linux next: NA Change-Id: I0ff4c175c3e1c0c7070b76719e1ad51d390221c9 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/37036 Reviewed-by: Himanshu AGRAWAL Reviewed-by: Swinder Pal SINGH Tested-by: Himanshu AGRAWAL Reviewed-by: Sarvesh SANT --- .../nmf-cm/cm/engine/api/control/irq_engine.h | 14 +- .../inc/executive_engine_mgt.h | 6 - .../src/executive_engine_mgt.c | 13 - .../os_adaptation_layer/inc/os_adaptation_layer.h | 4 - .../staging/nmf-cm/cm/engine/trace/inc/xtitrace.h | 8 - drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 109 ----- drivers/staging/nmf-cm/cm_debug.c | 2 +- drivers/staging/nmf-cm/cm_service.c | 10 +- drivers/staging/nmf-cm/cm_syscall.c | 6 +- drivers/staging/nmf-cm/cmioctl.h | 8 +- drivers/staging/nmf-cm/cmld.c | 450 +++++++-------------- drivers/staging/nmf-cm/cmld.h | 46 --- drivers/staging/nmf-cm/configuration.c | 46 +-- drivers/staging/nmf-cm/configuration.h | 4 +- drivers/staging/nmf-cm/ee/api/panic.idt | 3 +- drivers/staging/nmf-cm/ee/api/trace.idt | 31 -- drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- drivers/staging/nmf-cm/osal-kernel.c | 22 +- drivers/staging/nmf-cm/osal-kernel.h | 5 +- .../nmf-cm/share/communication/inc/nmf_service.h | 1 - 20 files changed, 197 insertions(+), 593 deletions(-) delete mode 100644 drivers/staging/nmf-cm/ee/api/trace.idt diff --git a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h index e3974764e91..20313f13256 100644 --- a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h +++ b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h @@ -14,7 +14,6 @@ #include #include #include -#include /*! * \brief MPCs -> HOST communication handler @@ -50,8 +49,7 @@ PUBLIC IMPORT_SHARED void CM_ProcessMpcEvent(t_nmf_core_id coreId); typedef enum { // Allowed since i CM_MPC_SERVICE_NONE = 0, //!< No service found CM_MPC_SERVICE_PANIC = 1, //!< Panic service found - CM_MPC_SERVICE_PRINT = 2, //!< Print service found - CM_MPC_SERVICE_TRACE = 3 //!< Trace service found + CM_MPC_SERVICE_PRINT = 2 //!< Print service found } t_cm_service_type; //!< Service description type /*! @@ -107,14 +105,4 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ReadMPCString( char * buffer, t_uint32 bufferSize); -typedef enum { - CM_MPC_TRACE_NONE = 0, - CM_MPC_TRACE_READ = 1, - CM_MPC_TRACE_READ_OVERRUN = 2 -} t_cm_trace_type; - -PUBLIC IMPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( - t_nmf_core_id coreId, - struct t_nmf_trace *trace); - #endif /* CONTROL_IRQ_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h index 0894410ae0d..aacffd15a17 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h @@ -24,12 +24,6 @@ typedef struct { t_memory_handle handle; t_cm_logical_address addr; } panicArea; - - // Trace Management - t_uint32 readTracePointer; - t_uint32 lastReadedTraceRevision; - t_memory_handle traceDataHandle; - struct t_nmf_trace *traceDataAddr; } t_ee_state; //TODO, juraj, this should be done more properly, like accessor method, instead making this global variable.. diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c index 4df3d7ee0f5..f2c833ff7dc 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c @@ -21,8 +21,6 @@ #include #include -#include - #include t_ee_state eeState[NB_CORE_IDS]; @@ -132,16 +130,6 @@ PUBLIC t_cm_error cm_EEM_Init( return error; } - if((error = cm_SRV_allocateTraceBufferMemory(coreId, cm_DSP_GetState(coreId)->domainEE)) != CM_OK) - { - cm_PFM_deallocatePerfmeterDataMemory(coreId); - cm_EEM_freePanicArea(coreId); - cm_delayedDestroyComponent(eeState[coreId].instance); - eeState[coreId].instance = (t_component_instance *)0; - cm_DSP_Shutdown(coreId); - return error; - } - /* set initial stack value */ cm_writeAttribute(eeState[coreId].instance, "rtos/scheduler/topOfStack", cm_DSP_getStackAddr(coreId)); @@ -191,7 +179,6 @@ PUBLIC void cm_EEM_Close(t_nmf_core_id coreId) cm_DSP_setStackSize(coreId, 0); cm_delayedDestroyComponent(eeState[coreId].instance); eeState[coreId].instance = (t_component_instance *)0; - cm_SRV_deallocateTraceBufferMemory(coreId); cm_PFM_deallocatePerfmeterDataMemory(coreId); cm_EEM_freePanicArea(coreId); cm_DSP_Shutdown(coreId); diff --git a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h index c9ec864795f..f57c92ea41b 100644 --- a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h +++ b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h @@ -44,10 +44,6 @@ typedef t_uint8 t_nmf_osal_sync_error; #define SEM_TIMEOUT_NORMAL 3000 #define SEM_TIMEOUT_DEBUG 300000 -/*! - * \brief Operations used to support additionnal OS-specific debug feature - * \ingroup CM_ENGINE_OSAL_API - */ struct osal_debug_operations { void (*component_create)(t_component_instance *component); void (*component_destroy)(t_component_instance *component); diff --git a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h index 1efd4f1e699..6ab960b69b2 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h +++ b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h @@ -39,12 +39,4 @@ void cm_TRC_traceMemAlloc(t_nmfTraceAllocatorCommandDescription command, t_uint8 void cm_TRC_traceMem(t_nmfTraceAllocCommandDescription command, t_uint8 allocId, t_uint32 startAddress, t_uint32 memorySize); -/*************************/ -/* MMDSP trace buffer */ -/*************************/ -PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId); -PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId); - - - #endif /* __INC_CM_TRACE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c index e59d9f8b1ba..9cb1a729a92 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -13,111 +13,6 @@ #include #include -PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId) -{ - t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); - - state->traceDataHandle = cm_DM_Alloc(domainId, SDRAM_EXT16, - TRACE_BUFFER_SIZE * sizeof(struct t_nmf_trace) / 2, CM_MM_ALIGN_WORD, TRUE); - if (state->traceDataHandle == INVALID_MEMORY_HANDLE) - return CM_NO_MORE_MEMORY; - else - { - t_uint32 mmdspAddr; - int i; - - state->traceDataAddr = (struct t_nmf_trace*)cm_DSP_GetHostLogicalAddress(state->traceDataHandle); - cm_DSP_GetDspAddress(state->traceDataHandle, &mmdspAddr); - cm_writeAttribute(state->instance, "rtos/commonpart/traceDataAddr", mmdspAddr); - - eeState[coreId].readTracePointer = 0; - eeState[coreId].lastReadedTraceRevision = 0; - - for(i = 0; i < TRACE_BUFFER_SIZE; i++) - state->traceDataAddr[i].revision = 0; - - return CM_OK; - } -} - -PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId) -{ - t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); - - state->traceDataAddr = 0; - cm_DM_Free(state->traceDataHandle, TRUE); -} - -static t_uint32 swapHalfWord(t_uint32 word) -{ - return (word >> 16) | (word << 16); -} - -PUBLIC EXPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( - t_nmf_core_id coreId, - struct t_nmf_trace *trace) -{ - t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); - t_uint32 foundRevision; - t_cm_trace_type type; - - OSAL_LOCK_API(); - if (state->traceDataAddr == NULL) { - type = CM_MPC_TRACE_NONE; - goto out; - } - - foundRevision = swapHalfWord(state->traceDataAddr[state->readTracePointer].revision); - - if(foundRevision <= state->lastReadedTraceRevision) - { - // It's an old trace forgot it - type = CM_MPC_TRACE_NONE; - } - else - { - struct t_nmf_trace *traceRaw; - - if(foundRevision == state->lastReadedTraceRevision + 1) - { - type = CM_MPC_TRACE_READ; - } - else - { - type = CM_MPC_TRACE_READ_OVERRUN; - /* - * If we find that revision is bigger, thus we are in overrun, then we take the writePointer + 1 which - * correspond to the older one. - * => Here there is a window where the MMDSP could update writePointer just after - */ - state->readTracePointer = (cm_readAttributeNoError(state->instance, "rtos/commonpart/writePointer") + 1) % TRACE_BUFFER_SIZE; - } - - traceRaw = &state->traceDataAddr[state->readTracePointer]; - - trace->timeStamp = swapHalfWord(traceRaw->timeStamp); - trace->componentId = swapHalfWord(traceRaw->componentId); - trace->traceId = swapHalfWord(traceRaw->traceId); - trace->paramOpt = swapHalfWord(traceRaw->paramOpt); - trace->componentHandle = swapHalfWord(traceRaw->componentHandle); - trace->parentHandle = swapHalfWord(traceRaw->parentHandle); - - trace->params[0] = swapHalfWord(traceRaw->params[0]); - trace->params[1] = swapHalfWord(traceRaw->params[1]); - trace->params[2] = swapHalfWord(traceRaw->params[2]); - trace->params[3] = swapHalfWord(traceRaw->params[3]); - - state->readTracePointer = (state->readTracePointer + 1) % TRACE_BUFFER_SIZE; - state->lastReadedTraceRevision = swapHalfWord(traceRaw->revision); - trace->revision = state->lastReadedTraceRevision; - } - -out: - OSAL_UNLOCK_API(); - - return type; -} - /* * Panic @@ -244,10 +139,6 @@ PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( srcDescr->u.print.value1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); srcDescr->u.print.value2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); } - else if(serviceReason == MPC_SERVICE_TRACE) - { - *srcType = CM_MPC_SERVICE_TRACE; - } else if(serviceReason != MPC_SERVICE_NONE) { t_uint32 panicThis; diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c index 26446e19cdb..a934aa33e92 100644 --- a/drivers/staging/nmf-cm/cm_debug.c +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -5,12 +5,12 @@ */ #include +#include #include "osal-kernel.h" #include "cm_debug.h" #ifdef CONFIG_DEBUG_FS -#include static struct dentry *cm_dir; /* nmf-cm/ */ static struct dentry *proc_dir; /* nmf-cm/proc/ */ diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index a2a6ffa5b57..70cf6f37524 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -12,9 +12,9 @@ #include #include -#include #include #include +#include #include @@ -71,7 +71,7 @@ void dispatch_service_msg(struct osal_msg *msg) spin_lock_bh(&channelPriv->bh_lock); plist_add(&new_msg->msg_entry, &channelPriv->messageQueue); spin_unlock_bh(&channelPriv->bh_lock); - wake_up(&channelPriv->waitq); + wake_up_interruptible(&channelPriv->waitq); } } @@ -113,12 +113,6 @@ static void service_tasklet_func(unsigned long unused) desc.u.print.value2); break; } - case CM_MPC_SERVICE_TRACE: - spin_lock_bh(&osalEnv.mpc[i].trace_reader_lock); - if (osalEnv.mpc[i].trace_reader) - wake_up_process(osalEnv.mpc[i].trace_reader); - spin_unlock_bh(&osalEnv.mpc[i].trace_reader_lock); - break; default: pr_err("[CM] %s: MPC Service Type %d not supported\n", __func__, type); } diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index ca8d664abb4..a687e0206a3 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -5,11 +5,11 @@ */ #include -#include #include #include #include #include +#include #include "cmioctl.h" #include "osal-kernel.h" #include "cmld.h" @@ -1397,9 +1397,9 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd /* Mark this memory area reserved for a mapping for this thread ID */ /* It must not be already reserved but this should not happen */ if (curr->tid) { - pr_err("%s: thread %d can't reseveved memory %x already " + /*pr_err("%s: thread %d can't reseveved memory %x already " "reserved for %d\n", - __func__, current->pid, physAddr, curr->tid); + __func__, current->pid, physAddr, (int)curr->tid);*/ err = -EBUSY; } else { curr->tid = current->pid; diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h index 5f7d5b6a349..96481be38b8 100644 --- a/drivers/staging/nmf-cm/cmioctl.h +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -29,11 +29,9 @@ enum cmdma_type { CMDMA_PER_2_MEM }; -#define CMLD_DEV_NAME \ - { "cm_control", \ - "cm_channel", \ - "cm_sia_trace", \ - "cm_sva_trace", \ +#define CMLD_DEV_NAME \ + { "cm_control", \ + "cm_channel" \ } /* diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 17af63ac407..ef9753de7a4 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -14,9 +14,9 @@ #include #include #include -#include #include #include +#include #include #include @@ -29,7 +29,7 @@ #include "cm_service.h" #include "cm_dma.h" -#define CMDRIVER_PATCH_VERSION 121 +#define CMDRIVER_PATCH_VERSION 117 #define O_FLUSH 0x1000000 static int cmld_major; @@ -233,6 +233,111 @@ static void freeProcessPriv(struct kref *ref) OSAL_Free(entry); } +/** Driver's open method + * Allocates per-process resources: private data, wait queue, + * memory area descriptors linked list, message queue. + * + * \return POSIX error code + */ +static int cmld_open(struct inode *inode, struct file *file) +{ + struct cm_process_priv *procPriv = getProcessPriv(); + + if (IS_ERR(procPriv)) + return PTR_ERR(procPriv); + + if (iminor(inode) == 0) + file->private_data = procPriv; + else { + struct cm_channel_priv *channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); + if (channelPriv == NULL) { + kref_put(&procPriv->ref, freeProcessPriv); + return -ENOMEM; + } + + channelPriv->proc = procPriv; + channelPriv->state = CHANNEL_OPEN; + + /* Initialize wait_queue, lists and mutexes */ + init_waitqueue_head(&channelPriv->waitq); + plist_head_init(&channelPriv->messageQueue); + INIT_LIST_HEAD(&channelPriv->skelList); + spin_lock_init(&channelPriv->bh_lock); + mutex_init(&channelPriv->msgQueueLock); + mutex_init(&channelPriv->skelListLock); + + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_add(&channelPriv->entry, &channel_list); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + file->private_data = channelPriv; // store channel private struct in file descriptor + } + return 0; +} + +/** Driver's release method. + * Frees any per-process pending resource: components, bindings, memory areas. + * + * \return POSIX error code + */ +static int cmld_release(struct inode *inode, struct file *file) +{ + struct cm_process_priv* procPriv; + + /* The driver must guarantee that all related resources are released. + Thus all these checks below are necessary to release all remaining + resources still linked to this 'client', in case of abnormal process + exit. + => These are error cases ! + In the usual case, nothing should be done except the free of + the cmPriv itself + */ + + if (iminor(inode) != 0) { + struct cm_channel_priv* channelPriv; + channelPriv = file->private_data; + procPriv = channelPriv->proc; + + /* We don't need to synchronize here by using the skelListLock: + the list is only accessed during ioctl() and we can't be here + if an ioctl() is on-going */ + if (list_empty(&channelPriv->skelList)) { + /* There is no pending MPC->HOST binding + => we can quietly delete the channel */ + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_del(&channelPriv->entry); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + /* Free all remaining messages if any */ + freeMessages(channelPriv); + + /* Free the per-channel descriptor */ + OSAL_Free(channelPriv); + } else { + /* Uh: there are still some MPC->HOST binding but we don't have the + required info to unbind them. + => we must keep all skel structures because possibly used in OSAL_PostDfc + (incoming callback msg) */ + /* We flag the channel as closed to discard any new msg that will never be read anyway */ + channelPriv->state = CHANNEL_CLOSED; + + /* Already Free all remaining messages if any, + they will never be read anyway */ + freeMessages(channelPriv); + } + } else + procPriv = file->private_data; + + kref_put(&procPriv->ref, freeProcessPriv); + file->private_data = NULL; + + return 0; +} + /** Reads Component Manager messages destinated to this process. * The message is composed by three fields: * 1) mpc2host handle (distinguishes interfaces) @@ -242,16 +347,19 @@ static void freeProcessPriv(struct kref *ref) * \note cfr GetEvent() * \return POSIX error code */ -static ssize_t cmld_channel_read(struct file *file, char *buf, size_t count, loff_t *ppos) +static ssize_t cmld_read(struct file *file, char *buf, size_t count, loff_t *ppos) { int err = 0; - struct cm_channel_priv* channelPriv = file->private_data; + struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); int msgSize = 0; struct plist_head* messageQueue; struct osal_msg* msg; t_os_message *os_msg = (t_os_message *)buf; int block = !(file->f_flags & O_NONBLOCK); + if (iminor(file->f_dentry->d_inode) == 0) + return -ENOSYS; + messageQueue = &channelPriv->messageQueue; if (mutex_lock_killable(&channelPriv->msgQueueLock)) @@ -263,7 +371,7 @@ wait: if (block == 0) return -EAGAIN; /* Wait until there is a message to ferry up */ - if (wait_event_killable(channelPriv->waitq, ((!plist_head_empty(messageQueue)) || (file->f_flags & O_FLUSH)))) + if (wait_event_interruptible(channelPriv->waitq, ((!plist_head_empty(messageQueue)) || (file->f_flags & O_FLUSH)))) return -ERESTARTSYS; if (file->f_flags & O_FLUSH) { file->f_flags &= ~O_FLUSH; @@ -351,21 +459,19 @@ out: * * \return POSIX error code */ -static int cmld_channel_flush(struct file *file, fl_owner_t id) +static int cmld_flush(struct file *file, fl_owner_t id) { - struct cm_channel_priv* channelPriv = file->private_data; - file->f_flags |= O_FLUSH; - wake_up(&channelPriv->waitq); + if (iminor(file->f_dentry->d_inode) != 0) { + struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); + file->f_flags |= O_FLUSH; + wake_up_interruptible(&channelPriv->waitq); + } return 0; } -static long cmld_channel_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_channel_priv *channelPriv = file->private_data; -#ifdef CONFIG_DEBUG_FS - if (wait_event_killable(dump_waitq, (!cmld_dump_ongoing))) - return -ERESTARTSYS; -#endif switch(cmd) { /* @@ -374,7 +480,7 @@ static long cmld_channel_ioctl(struct file *file, unsigned int cmd, unsigned lon case CM_BINDCOMPONENTTOCMCORE: return cmld_BindComponentToCMCore(channelPriv, (CM_BindComponentToCMCore_t *)arg); case CM_FLUSHCHANNEL: - return cmld_channel_flush(file, 0); + return cmld_flush(file, 0); default: pr_err("CM(%s): unsupported command %i\n", __func__, cmd); return -EINVAL; @@ -382,18 +488,9 @@ static long cmld_channel_ioctl(struct file *file, unsigned int cmd, unsigned lon return 0; } -static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_process_priv* procPriv = file->private_data; -#ifdef CONFIG_DEBUG_FS - if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { - cmld_dump_ongoing = false; - wake_up(&dump_waitq); - return 0; - } else if (wait_event_killable(dump_waitq, (!cmld_dump_ongoing))) - return -ERESTARTSYS; -#endif - switch(cmd) { /* * All wrapped CM SYSCALL @@ -598,6 +695,7 @@ static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned lon cmld_user_has_debugfs = true; #endif return 0; + case CM_PRIV_DEBUGFS_DUMP_DONE: case CM_PRIV_DEBUGFS_WAIT_DUMP: return 0; default: @@ -608,6 +706,29 @@ static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned lon return 0; } +/** Driver's ioctl method + * Implements user/kernel crossing for SYSCALL API. + * + * \return POSIX error code + */ +static long cmld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ +#ifdef CONFIG_DEBUG_FS + if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { + cmld_dump_ongoing = false; + wake_up_interruptible(&dump_waitq); + return 0; + } else if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) + return -ERESTARTSYS; +#endif + + if (iminor(filp->f_dentry->d_inode) == 0) { + return cmld_control_ctl(filp, cmd, arg); + } else { + return cmld_channel_ctl(filp, cmd, arg); + } +} + /** VMA open callback function */ static void cmld_vma_open(struct vm_area_struct* vma) { @@ -634,7 +755,7 @@ static struct vm_operations_struct cmld_remap_vm_ops = { * * \return POSIX error code */ -static int cmld_control_mmap(struct file *file, struct vm_area_struct *vma) +static int cmld_mmap(struct file* file, struct vm_area_struct* vma) { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; struct list_head* listHead; @@ -706,278 +827,6 @@ static int cmld_control_mmap(struct file *file, struct vm_area_struct *vma) return 0; } -/* Driver's release method for /dev/cm_channel */ -static int cmld_channel_release(struct inode *inode, struct file *file) -{ - struct cm_channel_priv* channelPriv = file->private_data; - struct cm_process_priv* procPriv = channelPriv->proc; - - /* - * The driver must guarantee that all related resources are released. - * Thus all these checks below are necessary to release all remaining - * resources still linked to this 'client', in case of abnormal process - * exit. - * => These are error cases ! - * In the usual case, nothing should be done except the free of - * the cmPriv itself - */ - - /* We don't need to synchronize here by using the skelListLock: - the list is only accessed during ioctl() and we can't be here - if an ioctl() is on-going */ - if (list_empty(&channelPriv->skelList)) { - /* There is no pending MPC->HOST binding - => we can quietly delete the channel */ - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_del(&channelPriv->entry); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - /* Free all remaining messages if any */ - freeMessages(channelPriv); - - /* Free the per-channel descriptor */ - OSAL_Free(channelPriv); - } else { - /* - * Uh: there are still some MPC->HOST binding but we don't have - * the required info to unbind them. - * => we must keep all skel structures because possibly used in - * OSAL_PostDfc (incoming callback msg). We flag the channel as - * closed to discard any new msg that will never be read anyway - */ - channelPriv->state = CHANNEL_CLOSED; - - /* Already Free all remaining messages if any, - they will never be read anyway */ - freeMessages(channelPriv); - } - - kref_put(&procPriv->ref, freeProcessPriv); - file->private_data = NULL; - - return 0; -} - -/* Driver's release method for /dev/cm_control */ -static int cmld_control_release(struct inode *inode, struct file *file) -{ - struct cm_process_priv* procPriv = file->private_data; - - kref_put(&procPriv->ref, freeProcessPriv); - file->private_data = NULL; - - return 0; -} - -static struct file_operations cmld_control_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = cmld_control_ioctl, - .mmap = cmld_control_mmap, - .release = cmld_control_release, -}; - -static int cmld_control_open(struct file *file) -{ - struct cm_process_priv *procPriv = getProcessPriv(); - if (IS_ERR(procPriv)) - return PTR_ERR(procPriv); - file->private_data = procPriv; - file->f_op = &cmld_control_fops; - return 0; -} - -static struct file_operations cmld_channel_fops = { - .owner = THIS_MODULE, - .read = cmld_channel_read, - .unlocked_ioctl = cmld_channel_ioctl, - .flush = cmld_channel_flush, - .release = cmld_channel_release, -}; - -static int cmld_channel_open(struct file *file) -{ - struct cm_process_priv *procPriv = getProcessPriv(); - struct cm_channel_priv *channelPriv; - - if (IS_ERR(procPriv)) - return PTR_ERR(procPriv); - - channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); - if (channelPriv == NULL) { - kref_put(&procPriv->ref, freeProcessPriv); - return -ENOMEM; - } - - channelPriv->proc = procPriv; - channelPriv->state = CHANNEL_OPEN; - - /* Initialize wait_queue, lists and mutexes */ - init_waitqueue_head(&channelPriv->waitq); - plist_head_init(&channelPriv->messageQueue); - INIT_LIST_HEAD(&channelPriv->skelList); - spin_lock_init(&channelPriv->bh_lock); - mutex_init(&channelPriv->msgQueueLock); - mutex_init(&channelPriv->skelListLock); - - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_add(&channelPriv->entry, &channel_list); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - file->private_data = channelPriv; - file->f_op = &cmld_channel_fops; - return 0; -} - -static ssize_t cmld_sxa_trace_read(struct file *file, char *buf, size_t count, loff_t *ppos) -{ - struct mpcConfig *mpc = file->private_data; - size_t written = 0; - struct t_nmf_trace trace; - t_cm_trace_type traceType; - struct mmdsp_trace mmdsp_tr = { - .media = TB_MEDIA_FILE, - .receiver_dev = TB_DEV_PC, - .sender_dev = TB_DEV_TRACEBOX, - .unused = TB_TRACEBOX, - .receiver_obj = DEFAULT_RECEIVERR_OBJ, - .sender_obj = DEFAULT_SENDER_OBJ, - .transaction_id = 0, - .message_id = TB_TRACE_MSG, - .master_id = mpc->coreId+1, - .channel_id = 0, - .ost_version = OST_VERSION, - .entity = ENTITY, - .protocol_id = PROTOCOL_ID, - .btrace_hdr_flag = 0, - .btrace_hdr_subcategory = 0, - }; - - while ((count - written) >= sizeof(mmdsp_tr)) { - traceType = CM_ENGINE_GetNextTrace(mpc->coreId, &trace); - - switch (traceType) { - case CM_MPC_TRACE_READ_OVERRUN: - mmdsp_tr.size = - cpu_to_be16(offsetof(struct mmdsp_trace, - ost_version) - -offsetof(struct mmdsp_trace, - receiver_obj)); - mmdsp_tr.message_id = TB_TRACE_EXCEPTION_MSG; - mmdsp_tr.ost_master_id = TB_EXCEPTION_LONG_OVRF_PACKET; - if (copy_to_user(&buf[written], &mmdsp_tr, - offsetof(struct mmdsp_trace, - ost_version))) - return -EFAULT; - written += offsetof(struct mmdsp_trace, ost_version); - if ((count - written) < sizeof(mmdsp_tr)) - break; - case CM_MPC_TRACE_READ: { - u16 param_nr = (u16)trace.paramOpt; - u16 handle_valid = (u16)(trace.paramOpt >> 16); - u32 to_write = offsetof(struct mmdsp_trace, - parent_handle); - mmdsp_tr.transaction_id = trace.revision%256; - mmdsp_tr.message_id = TB_TRACE_MSG; - mmdsp_tr.ost_master_id = OST_MASTERID; - mmdsp_tr.timestamp = cpu_to_be64(trace.timeStamp); - mmdsp_tr.timestamp2 = cpu_to_be64(trace.timeStamp); - mmdsp_tr.component_id = cpu_to_be32(trace.componentId); - mmdsp_tr.trace_id = cpu_to_be32(trace.traceId); - mmdsp_tr.btrace_hdr_category = (trace.traceId>>16)&0xFF; - mmdsp_tr.btrace_hdr_size = BTRACE_HEADER_SIZE - + sizeof(trace.params[0]) * param_nr; - if (handle_valid) { - mmdsp_tr.parent_handle = trace.parentHandle; - mmdsp_tr.component_handle = - trace.componentHandle; - to_write += sizeof(trace.parentHandle) - + sizeof(trace.componentHandle); - mmdsp_tr.btrace_hdr_size += - sizeof(trace.parentHandle) - + sizeof(trace.componentHandle); - } - mmdsp_tr.size = - cpu_to_be16(to_write - + (sizeof(trace.params[0])*param_nr) - - offsetof(struct mmdsp_trace, - receiver_obj)); - mmdsp_tr.length = to_write - + (sizeof(trace.params[0])*param_nr) - - offsetof(struct mmdsp_trace, - timestamp2); - if (copy_to_user(&buf[written], &mmdsp_tr, to_write)) - return -EFAULT; - written += to_write; - /* write param */ - to_write = sizeof(trace.params[0]) * param_nr; - if (copy_to_user(&buf[written], trace.params, to_write)) - return -EFAULT; - written += to_write; - break; - } - case CM_MPC_TRACE_NONE: - default: - if ((file->f_flags & O_NONBLOCK) || written) - return written; - spin_lock_bh(&mpc->trace_reader_lock); - mpc->trace_reader = current; - spin_unlock_bh(&mpc->trace_reader_lock); - schedule_timeout_killable(msecs_to_jiffies(200)); - spin_lock_bh(&mpc->trace_reader_lock); - mpc->trace_reader = NULL; - spin_unlock_bh(&mpc->trace_reader_lock); - if (signal_pending(current)) - return -ERESTARTSYS; - } - } - return written; -} - -/* Driver's release method for /dev/cm_sxa_trace */ -static int cmld_sxa_trace_release(struct inode *inode, struct file *file) -{ - struct mpcConfig *mpc = file->private_data; - atomic_dec(&mpc->trace_read_count); - return 0; -} - -static struct file_operations cmld_sxa_trace_fops = { - .owner = THIS_MODULE, - .read = cmld_sxa_trace_read, - .release = cmld_sxa_trace_release, -}; - -static int cmld_sxa_trace_open(struct file *file, struct mpcConfig *mpc) -{ - if (atomic_add_unless(&mpc->trace_read_count, 1, 1) == 0) - return -EBUSY; - - file->private_data = mpc; - file->f_op = &cmld_sxa_trace_fops; - return 0; -} - -/* driver open() call: specific */ -static int cmld_open(struct inode *inode, struct file *file) -{ - switch (iminor(inode)) { - case 0: - return cmld_control_open(file); - case 1: - return cmld_channel_open(file); - case 2: - return cmld_sxa_trace_open(file, &osalEnv.mpc[SIA]); - case 3: - return cmld_sxa_trace_open(file, &osalEnv.mpc[SVA]); - default: - return -ENOSYS; - } -} - /** MPC Events tasklet * The parameter is used to know from which interrupts we're comming * and which core to pass to CM_ProcessMpcEvent(): @@ -1033,7 +882,12 @@ static irqreturn_t panic_handler(int irq, void *idx) */ static struct file_operations cmld_fops = { .owner = THIS_MODULE, + .read = cmld_read, + .unlocked_ioctl = cmld_ioctl, + .mmap = cmld_mmap, .open = cmld_open, + .flush = cmld_flush, + .release = cmld_release, }; /** diff --git a/drivers/staging/nmf-cm/cmld.h b/drivers/staging/nmf-cm/cmld.h index 17e6c55ff61..4c5a5bed7e6 100644 --- a/drivers/staging/nmf-cm/cmld.h +++ b/drivers/staging/nmf-cm/cmld.h @@ -79,52 +79,6 @@ extern bool cmld_user_has_debugfs; /**< Whether user side has proper support of extern bool cmld_dump_ongoing; /**< Whether a dump is on-going */ #endif -/* Structure used to embed DSP traces */ -#define TB_MEDIA_FILE 0x1C -#define TB_DEV_PC 0x10 -#define TB_DEV_TRACEBOX 0x4C -#define TB_TRACEBOX 0x7C -#define DEFAULT_RECEIVERR_OBJ 0x0 -#define DEFAULT_SENDER_OBJ 0x0A -#define TB_TRACE_MSG 0x94 -#define TB_TRACE_EXCEPTION_MSG 0x95 -#define TB_EXCEPTION_LONG_OVRF_PACKET 0x07 -#define OST_MASTERID 0x08 -#define OST_VERSION 0x05 -#define ENTITY 0xAA -#define PROTOCOL_ID 0x03 -#define BTRACE_HEADER_SIZE 4 - -struct __attribute__ ((__packed__)) mmdsp_trace { - u8 media; - u8 receiver_dev; - u8 sender_dev; - u8 unused; - u16 size; - u8 receiver_obj; - u8 sender_obj; - u8 transaction_id; - u8 message_id; - u8 master_id; - u8 channel_id; - u64 timestamp; - u8 ost_master_id; - u8 ost_version; - u8 entity; - u8 protocol_id; - u8 length; - u64 timestamp2; - u32 component_id; - u32 trace_id; - u8 btrace_hdr_size; - u8 btrace_hdr_flag; - u8 btrace_hdr_category; - u8 btrace_hdr_subcategory; - u32 parent_handle; - u32 component_handle; - u32 params[4]; -}; - /** Lock/unlock per process mutex * * \note Must be taken before tasklet_disable (if necessary)! diff --git a/drivers/staging/nmf-cm/configuration.c b/drivers/staging/nmf-cm/configuration.c index 523874fc586..d62bcb45500 100644 --- a/drivers/staging/nmf-cm/configuration.c +++ b/drivers/staging/nmf-cm/configuration.c @@ -21,30 +21,28 @@ struct OsalEnvironment osalEnv = { .mpc = { { - .coreId = SVA_CORE_ID, - .name = "sva", - .base_phys = (void*)U8500_SVA_BASE, - .interrupt0 = IRQ_DB8500_SVA, - .interrupt1 = IRQ_DB8500_SVA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, - .trace_read_count = ATOMIC_INIT(0), + .coreId = SVA_CORE_ID, + .name = "sva", + .base_phys = (void*)U8500_SVA_BASE, + .interrupt0 = IRQ_DB8500_SVA, + .interrupt1 = IRQ_DB8500_SVA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, }, { - .coreId = SIA_CORE_ID, - .name = "sia", - .base_phys = (void*)U8500_SIA_BASE, - .interrupt0 = IRQ_DB8500_SIA, - .interrupt1 = IRQ_DB8500_SIA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, - .trace_read_count = ATOMIC_INIT(0), + .coreId = SIA_CORE_ID, + .name = "sia", + .base_phys = (void*)U8500_SIA_BASE, + .interrupt0 = IRQ_DB8500_SIA, + .interrupt1 = IRQ_DB8500_SIA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, } }, .esram_regulator = { NULL, NULL}, @@ -127,20 +125,16 @@ int init_config(void) pr_err("SDRAM data size for SVA must be greater than 0\n"); return -EINVAL; } - osalEnv.mpc[SVA].nbYramBanks = cfgMpcYBanks_SVA; osalEnv.mpc[SVA].eeId = cfgSchedulerTypeHybrid_SVA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SVA].sdram_code.size = cfgMpcSDRAMCodeSize_SVA * ONE_KB; osalEnv.mpc[SVA].sdram_data.size = cfgMpcSDRAMDataSize_SVA * ONE_KB; osalEnv.mpc[SVA].base.size = 128*ONE_KB; //we expose only TCM24 - spin_lock_init(&osalEnv.mpc[SVA].trace_reader_lock); - osalEnv.mpc[SIA].nbYramBanks = cfgMpcYBanks_SIA; osalEnv.mpc[SIA].eeId = cfgSchedulerTypeHybrid_SIA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SIA].sdram_code.size = cfgMpcSDRAMCodeSize_SIA * ONE_KB; osalEnv.mpc[SIA].sdram_data.size = cfgMpcSDRAMDataSize_SIA * ONE_KB; osalEnv.mpc[SIA].base.size = 128*ONE_KB; //we expose only TCM24 - spin_lock_init(&osalEnv.mpc[SIA].trace_reader_lock); return 0; } diff --git a/drivers/staging/nmf-cm/configuration.h b/drivers/staging/nmf-cm/configuration.h index f4146dc6117..35072831a13 100644 --- a/drivers/staging/nmf-cm/configuration.h +++ b/drivers/staging/nmf-cm/configuration.h @@ -20,14 +20,12 @@ #endif /* Embedded Static RAM base address */ -/* config: 0-64k: secure */ -#define ESRAM_BASE (U8500_ESRAM_BASE + U8500_ESRAM_DMA_LCPA_OFFSET) +#define ESRAM_BASE (U8500_ESRAM_BASE + 0x10000) // V1/V2 config: 0-64k: secure; /* * Embedded ram size for CM (in Kb) * 5 banks of 128k: skip the first half bank (secure) and the last * one (used for MCDE/B2R2), but include DMA part (4k after the secure part) - * to give access from DSP side */ #define ESRAM_SIZE 448 enum { diff --git a/drivers/staging/nmf-cm/ee/api/panic.idt b/drivers/staging/nmf-cm/ee/api/panic.idt index 53135819f4a..f971fdad8c5 100644 --- a/drivers/staging/nmf-cm/ee/api/panic.idt +++ b/drivers/staging/nmf-cm/ee/api/panic.idt @@ -55,8 +55,7 @@ typedef enum { INTERFACE_NOT_BINDED = 8, USER_PANIC = 9, UNBIND_INTERRUPT = 10, - EVENT_FIFO_IN_USE = 11, - RESERVED_PANIC = 2 //for COMPATIBILITY with previous versions of NMF, to be deprecated + EVENT_FIFO_IN_USE = 11 } t_panic_reasonDescription; /*! diff --git a/drivers/staging/nmf-cm/ee/api/trace.idt b/drivers/staging/nmf-cm/ee/api/trace.idt deleted file mode 100644 index 3c21c6a860f..00000000000 --- a/drivers/staging/nmf-cm/ee/api/trace.idt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) ST-Ericsson SA 2010 - * Author: Jean-Philippe FASSINO for ST-Ericsson. - * License terms: GNU General Public License (GPL), version 2, with - * user space exemption described in the top-level COPYING file in - * the Linux kernel source tree. - */ - -/*! - * \defgroup NMF_EE_TYPE Execution Engine Common Type Definitions - * \ingroup COMMON - */ - -#ifndef __INC_TRACE_IDT -#define __INC_TRACE_IDT - -struct t_nmf_trace -{ - t_uint32 revision; - t_uint32 timeStamp; - t_uint32 componentId; - t_uint32 traceId; - t_uint32 paramOpt; - t_uint32 componentHandle; - t_uint32 parentHandle; - t_uint32 params[4]; -}; - -#define TRACE_BUFFER_SIZE 128 - -#endif diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index 5cb1ec7fcec..e671198f7b9 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (121)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (118)) /*! * \brief Get NMF major version corresponding to NMF version number diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index e79e35db106..94aa11fc91c 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -353,7 +353,7 @@ void OSAL_PostDfc(t_nmf_mpc2host_handle upLayerTHIS, t_uint32 methodIndex, t_eve spin_unlock_bh(&skelwrapper->channelPriv->bh_lock); /* Wake up process' wait queue */ - wake_up(&skelwrapper->channelPriv->waitq); + wake_up_interruptible(&skelwrapper->channelPriv->waitq); } @@ -755,8 +755,8 @@ static int dspload_monitor(void *idx) /* init counter */ if (CM_GetMpcLoadCounter(mpc->coreId, &mpc->oldLoadCounter) != CM_OK) - pr_warn("CM Driver: Failed to init load counter for %s\n", - mpc->name); + pr_err("CM Driver: Failed to init load counter for %s\n", + mpc->name); while (!kthread_should_stop()) { t_cm_mpc_load_counter loadCounter; @@ -919,7 +919,7 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); + secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -927,16 +927,16 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= (2*U8500_ESRAM_BANK_SIZE); + secondParam /= 0x40000; WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < U8500_ESRAM_BANK1) + if (firstParam < (U8500_ESRAM_BASE+0x20000)) firstParam = 0; else - firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); + firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; /* power off the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { @@ -1032,7 +1032,7 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); + secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -1040,16 +1040,16 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= (2*U8500_ESRAM_BANK_SIZE); + secondParam /= 0x40000; WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < U8500_ESRAM_BANK1) + if (firstParam < (U8500_ESRAM_BASE+0x20000)) firstParam = 0; else - firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); + firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; /* power on the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { diff --git a/drivers/staging/nmf-cm/osal-kernel.h b/drivers/staging/nmf-cm/osal-kernel.h index dc9bc8445ac..7a71bdd591d 100644 --- a/drivers/staging/nmf-cm/osal-kernel.h +++ b/drivers/staging/nmf-cm/osal-kernel.h @@ -11,7 +11,6 @@ #include #include #include -#include #ifdef CONFIG_HAS_WAKELOCK #include #endif @@ -25,6 +24,7 @@ */ #define _CM_ELF_H #include +#include #include "configuration.h" @@ -56,9 +56,6 @@ struct mpcConfig { #endif struct task_struct *monitor_tsk; /**< task to monitor the dsp load; */ t_cm_mpc_load_counter oldLoadCounter; /**< previous load counter of the DSP */ - atomic_t trace_read_count; /**< number of trace reader */ - spinlock_t trace_reader_lock; - struct task_struct *trace_reader;/**< current reader task */ #ifdef CONFIG_DEBUG_FS struct dentry *dir; /**< debugfs dir entry */ struct dentry *comp_dir; /**< debugfs component dir entry */ diff --git a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h index 71dfc534f97..5ec08434492 100644 --- a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h +++ b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h @@ -12,6 +12,5 @@ #define MPC_SERVICE_NONE 0 #define MPC_SERVICE_BOOT 0xB001 #define MPC_SERVICE_PRINT 0x1234 -#define MPC_SERVICE_TRACE 0x789 #endif -- cgit v1.2.3 From a1fc7f07ad31944d0ba0b1a958193182155e4156 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 12 Jan 2012 14:55:41 +0100 Subject: mmio: u5500: cleanup is_s5500_board() Rename is_s5500_board() -> u5500_board_is_s5500() Signed-off-by: Rabin Vincent --- arch/arm/mach-ux500/board-u5500-mmio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-ux500/board-u5500-mmio.c b/arch/arm/mach-ux500/board-u5500-mmio.c index 8c84aebccee..ded7cb94c1f 100644 --- a/arch/arm/mach-ux500/board-u5500-mmio.c +++ b/arch/arm/mach-ux500/board-u5500-mmio.c @@ -248,7 +248,7 @@ static int mmio_power_enable(struct mmio_platform_data *pdata) return err; } - if (!(is_s5500_board())) + if (!(u5500_board_is_s5500())) gpio_set_value(GPIO_CAMERA_PMIC_EN, 1); else gpio_set_value(GPIO_CAMERA_PMIC_EN, 0); @@ -274,7 +274,7 @@ static void mmio_power_disable(struct mmio_platform_data *pdata) for (i = 0; i < extra->number_of_regulators; i++) regulator_disable(extra->mmio_regulators[i]); - if (!(is_s5500_board())) + if (!(u5500_board_is_s5500())) gpio_set_value(GPIO_CAMERA_PMIC_EN, 0); else gpio_set_value(GPIO_CAMERA_PMIC_EN, 1); -- cgit v1.2.3 From 877cccc561b35b59383487b2ac73e7d8e8ed2f4d Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Fri, 28 Oct 2011 11:12:48 +0200 Subject: U8500 CM: Add support to get DSP OST Trace on ARM Provide two new devices /dev/cm_sia_trace and /dev/cm_sva_trace that allow any user to retrieve live OST traces coming from DSP components by doing 'cat /dev/cm_sia_trace > file.bin'. This traces are till now available through XTI device. This feature also requires some change in OSTTrace component to be fully operationnal. ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson ID: 324035 ST-Ericsson Linux next: NA Change-Id: I593c2f82be750bc1738281ee25d875b5a784ea04 Signed-off-by: Pierre Peiffer Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42605 Reviewed-by: QABUILD --- .../nmf-cm/cm/engine/api/control/irq_engine.h | 14 +- .../engine/communication/inc/communication_type.h | 1 - .../cm/engine/component/inc/component_type.h | 1 - .../engine/configuration/inc/configuration_type.h | 1 - drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c | 22 +- .../inc/executive_engine_mgt.h | 6 + .../src/executive_engine_mgt.c | 13 + .../nmf-cm/cm/engine/memory/inc/domain_type.h | 1 - .../nmf-cm/cm/engine/memory/inc/memory_type.h | 1 - .../os_adaptation_layer/inc/os_adaptation_layer.h | 4 + .../cm/engine/perfmeter/inc/perfmeter_type.h | 1 - .../cm/engine/repository_mgt/inc/repository_type.h | 1 - .../staging/nmf-cm/cm/engine/trace/inc/xtitrace.h | 8 + drivers/staging/nmf-cm/cm/engine/trace/src/panic.c | 109 +++++ drivers/staging/nmf-cm/cm/inc/cm_type.h | 1 - drivers/staging/nmf-cm/cm_debug.c | 2 +- drivers/staging/nmf-cm/cm_service.c | 10 +- drivers/staging/nmf-cm/cm_syscall.c | 6 +- drivers/staging/nmf-cm/cmioctl.h | 8 +- drivers/staging/nmf-cm/cmld.c | 448 ++++++++++++++------- drivers/staging/nmf-cm/cmld.h | 46 +++ drivers/staging/nmf-cm/configuration.c | 46 ++- drivers/staging/nmf-cm/configuration.h | 4 +- drivers/staging/nmf-cm/ee/api/panic.idt | 4 +- drivers/staging/nmf-cm/ee/api/trace.idt | 30 ++ drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- drivers/staging/nmf-cm/inc/nmf-limits.h | 1 - drivers/staging/nmf-cm/inc/nmf-tracedescription.h | 1 - drivers/staging/nmf-cm/inc/nmf_type.idt | 1 - drivers/staging/nmf-cm/inc/type.h | 1 - drivers/staging/nmf-cm/inc/typedef.h | 1 - drivers/staging/nmf-cm/nmf/inc/channel_type.h | 1 - drivers/staging/nmf-cm/nmf/inc/component_type.h | 1 - drivers/staging/nmf-cm/nmf/inc/service_type.h | 1 - drivers/staging/nmf-cm/osal-kernel.c | 22 +- drivers/staging/nmf-cm/osal-kernel.h | 6 +- .../nmf-cm/share/communication/inc/nmf_service.h | 1 + drivers/staging/nmf-cm/share/inc/macros.h | 1 - drivers/staging/nmf-cm/share/inc/nmf.h | 1 - 39 files changed, 612 insertions(+), 217 deletions(-) create mode 100644 drivers/staging/nmf-cm/ee/api/trace.idt diff --git a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h index 20313f13256..e3974764e91 100644 --- a/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h +++ b/drivers/staging/nmf-cm/cm/engine/api/control/irq_engine.h @@ -14,6 +14,7 @@ #include #include #include +#include /*! * \brief MPCs -> HOST communication handler @@ -49,7 +50,8 @@ PUBLIC IMPORT_SHARED void CM_ProcessMpcEvent(t_nmf_core_id coreId); typedef enum { // Allowed since i CM_MPC_SERVICE_NONE = 0, //!< No service found CM_MPC_SERVICE_PANIC = 1, //!< Panic service found - CM_MPC_SERVICE_PRINT = 2 //!< Print service found + CM_MPC_SERVICE_PRINT = 2, //!< Print service found + CM_MPC_SERVICE_TRACE = 3 //!< Trace service found } t_cm_service_type; //!< Service description type /*! @@ -105,4 +107,14 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ReadMPCString( char * buffer, t_uint32 bufferSize); +typedef enum { + CM_MPC_TRACE_NONE = 0, + CM_MPC_TRACE_READ = 1, + CM_MPC_TRACE_READ_OVERRUN = 2 +} t_cm_trace_type; + +PUBLIC IMPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( + t_nmf_core_id coreId, + struct t_nmf_trace *trace); + #endif /* CONTROL_IRQ_ENGINE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h b/drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h index db426845a82..53a6ff39b07 100644 --- a/drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h +++ b/drivers/staging/nmf-cm/cm/engine/communication/inc/communication_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Communication Component Manager API type. */ diff --git a/drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h b/drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h index 35571dde06d..2e769ec8b22 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h +++ b/drivers/staging/nmf-cm/cm/engine/component/inc/component_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Components Component Manager API type. * diff --git a/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h index abfe452cf78..af29d584ba4 100644 --- a/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h +++ b/drivers/staging/nmf-cm/cm/engine/configuration/inc/configuration_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Configuration Component Manager API type. */ diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c index 7950cd99007..274a1b6b59f 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c @@ -94,8 +94,26 @@ static t_interface_description* getInterfaceDescription(t_tmp_elfdescription *el // Search if interfane already loaded for(itf = interfaceList; itf != NULL; itf = itf->next) { if(itf->type == itfType) { - // TODO Sanity check - + if (itf->methodNumber != elfitf->methodNumber) { + ERROR("When loading component template %s:\n\tNumber of methods in interface type %s\n\tdiffers from previous declaration: was %d, found %d\n", + getElfHeaderReference(elftmp, (void*)elftmp->elfheader->templateName), itfType, itf->methodNumber, elfitf->methodNumber, 0, 0); + //Do not fail for now for compatibility reason + //goto out_itf_type; + } + if (cmIntensiveCheckState) { + for(i = 0; i < itf->methodNumber; i++) { + if (cm_StringCompare(itf->methodNames[i], getElfHeaderReference(elftmp, (void*)elfitf->methodNames[i]), MAX_INTERNAL_STRING_LENGTH) != 0) { + ERROR("When loading component template %s:\n" + "\tName of method number %d in interface type %s\n" + "\tdiffers from previous declaration: previous name was %s, new name found is %s\n", + getElfHeaderReference(elftmp, (void*)elftmp->elfheader->templateName), i, + itfType, itf->methodNames[i], + getElfHeaderReference(elftmp, (void*)elfitf->methodNames[i]), 0); + //Do not fail for now for compatibility reason + //goto out_itf_type; + } + } + } itf->referenceCounter++; cm_StringRelease(itfType); return itf; diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h index aacffd15a17..0894410ae0d 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h @@ -24,6 +24,12 @@ typedef struct { t_memory_handle handle; t_cm_logical_address addr; } panicArea; + + // Trace Management + t_uint32 readTracePointer; + t_uint32 lastReadedTraceRevision; + t_memory_handle traceDataHandle; + struct t_nmf_trace *traceDataAddr; } t_ee_state; //TODO, juraj, this should be done more properly, like accessor method, instead making this global variable.. diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c index f2c833ff7dc..4df3d7ee0f5 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c @@ -21,6 +21,8 @@ #include #include +#include + #include t_ee_state eeState[NB_CORE_IDS]; @@ -130,6 +132,16 @@ PUBLIC t_cm_error cm_EEM_Init( return error; } + if((error = cm_SRV_allocateTraceBufferMemory(coreId, cm_DSP_GetState(coreId)->domainEE)) != CM_OK) + { + cm_PFM_deallocatePerfmeterDataMemory(coreId); + cm_EEM_freePanicArea(coreId); + cm_delayedDestroyComponent(eeState[coreId].instance); + eeState[coreId].instance = (t_component_instance *)0; + cm_DSP_Shutdown(coreId); + return error; + } + /* set initial stack value */ cm_writeAttribute(eeState[coreId].instance, "rtos/scheduler/topOfStack", cm_DSP_getStackAddr(coreId)); @@ -179,6 +191,7 @@ PUBLIC void cm_EEM_Close(t_nmf_core_id coreId) cm_DSP_setStackSize(coreId, 0); cm_delayedDestroyComponent(eeState[coreId].instance); eeState[coreId].instance = (t_component_instance *)0; + cm_SRV_deallocateTraceBufferMemory(coreId); cm_PFM_deallocatePerfmeterDataMemory(coreId); cm_EEM_freePanicArea(coreId); cm_DSP_Shutdown(coreId); diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h index 7463f82eb89..354315d4d72 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/domain_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /***************************************************************************/ /* file : domain.h * author : NMF team diff --git a/drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h b/drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h index 91246f1ec0e..dbdba4c3d9d 100644 --- a/drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h +++ b/drivers/staging/nmf-cm/cm/engine/memory/inc/memory_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Public Component Manager Memory API type. * diff --git a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h index f57c92ea41b..c9ec864795f 100644 --- a/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h +++ b/drivers/staging/nmf-cm/cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h @@ -44,6 +44,10 @@ typedef t_uint8 t_nmf_osal_sync_error; #define SEM_TIMEOUT_NORMAL 3000 #define SEM_TIMEOUT_DEBUG 300000 +/*! + * \brief Operations used to support additionnal OS-specific debug feature + * \ingroup CM_ENGINE_OSAL_API + */ struct osal_debug_operations { void (*component_create)(t_component_instance *component); void (*component_destroy)(t_component_instance *component); diff --git a/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h b/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h index 78de395acc2..8733c20b21b 100644 --- a/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h +++ b/drivers/staging/nmf-cm/cm/engine/perfmeter/inc/perfmeter_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Public Component Manager Performance Meter API type. * diff --git a/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h b/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h index 59abc269236..30ef8004c48 100644 --- a/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h +++ b/drivers/staging/nmf-cm/cm/engine/repository_mgt/inc/repository_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Components Component Manager API type. * diff --git a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h index 6ab960b69b2..1efd4f1e699 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h +++ b/drivers/staging/nmf-cm/cm/engine/trace/inc/xtitrace.h @@ -39,4 +39,12 @@ void cm_TRC_traceMemAlloc(t_nmfTraceAllocatorCommandDescription command, t_uint8 void cm_TRC_traceMem(t_nmfTraceAllocCommandDescription command, t_uint8 allocId, t_uint32 startAddress, t_uint32 memorySize); +/*************************/ +/* MMDSP trace buffer */ +/*************************/ +PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId); +PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId); + + + #endif /* __INC_CM_TRACE_H */ diff --git a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c index 9cb1a729a92..e59d9f8b1ba 100644 --- a/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c +++ b/drivers/staging/nmf-cm/cm/engine/trace/src/panic.c @@ -13,6 +13,111 @@ #include #include +PUBLIC t_cm_error cm_SRV_allocateTraceBufferMemory(t_nmf_core_id coreId, t_cm_domain_id domainId) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + + state->traceDataHandle = cm_DM_Alloc(domainId, SDRAM_EXT16, + TRACE_BUFFER_SIZE * sizeof(struct t_nmf_trace) / 2, CM_MM_ALIGN_WORD, TRUE); + if (state->traceDataHandle == INVALID_MEMORY_HANDLE) + return CM_NO_MORE_MEMORY; + else + { + t_uint32 mmdspAddr; + int i; + + state->traceDataAddr = (struct t_nmf_trace*)cm_DSP_GetHostLogicalAddress(state->traceDataHandle); + cm_DSP_GetDspAddress(state->traceDataHandle, &mmdspAddr); + cm_writeAttribute(state->instance, "rtos/commonpart/traceDataAddr", mmdspAddr); + + eeState[coreId].readTracePointer = 0; + eeState[coreId].lastReadedTraceRevision = 0; + + for(i = 0; i < TRACE_BUFFER_SIZE; i++) + state->traceDataAddr[i].revision = 0; + + return CM_OK; + } +} + +PUBLIC void cm_SRV_deallocateTraceBufferMemory(t_nmf_core_id coreId) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + + state->traceDataAddr = 0; + cm_DM_Free(state->traceDataHandle, TRUE); +} + +static t_uint32 swapHalfWord(t_uint32 word) +{ + return (word >> 16) | (word << 16); +} + +PUBLIC EXPORT_SHARED t_cm_trace_type CM_ENGINE_GetNextTrace( + t_nmf_core_id coreId, + struct t_nmf_trace *trace) +{ + t_ee_state *state = cm_EEM_getExecutiveEngine(coreId); + t_uint32 foundRevision; + t_cm_trace_type type; + + OSAL_LOCK_API(); + if (state->traceDataAddr == NULL) { + type = CM_MPC_TRACE_NONE; + goto out; + } + + foundRevision = swapHalfWord(state->traceDataAddr[state->readTracePointer].revision); + + if(foundRevision <= state->lastReadedTraceRevision) + { + // It's an old trace forgot it + type = CM_MPC_TRACE_NONE; + } + else + { + struct t_nmf_trace *traceRaw; + + if(foundRevision == state->lastReadedTraceRevision + 1) + { + type = CM_MPC_TRACE_READ; + } + else + { + type = CM_MPC_TRACE_READ_OVERRUN; + /* + * If we find that revision is bigger, thus we are in overrun, then we take the writePointer + 1 which + * correspond to the older one. + * => Here there is a window where the MMDSP could update writePointer just after + */ + state->readTracePointer = (cm_readAttributeNoError(state->instance, "rtos/commonpart/writePointer") + 1) % TRACE_BUFFER_SIZE; + } + + traceRaw = &state->traceDataAddr[state->readTracePointer]; + + trace->timeStamp = swapHalfWord(traceRaw->timeStamp); + trace->componentId = swapHalfWord(traceRaw->componentId); + trace->traceId = swapHalfWord(traceRaw->traceId); + trace->paramOpt = swapHalfWord(traceRaw->paramOpt); + trace->componentHandle = swapHalfWord(traceRaw->componentHandle); + trace->parentHandle = swapHalfWord(traceRaw->parentHandle); + + trace->params[0] = swapHalfWord(traceRaw->params[0]); + trace->params[1] = swapHalfWord(traceRaw->params[1]); + trace->params[2] = swapHalfWord(traceRaw->params[2]); + trace->params[3] = swapHalfWord(traceRaw->params[3]); + + state->readTracePointer = (state->readTracePointer + 1) % TRACE_BUFFER_SIZE; + state->lastReadedTraceRevision = swapHalfWord(traceRaw->revision); + trace->revision = state->lastReadedTraceRevision; + } + +out: + OSAL_UNLOCK_API(); + + return type; +} + /* * Panic @@ -139,6 +244,10 @@ PUBLIC EXPORT_SHARED t_cm_error CM_getServiceDescription( srcDescr->u.print.value1 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo1"); srcDescr->u.print.value2 = cm_readAttributeNoError(ee, "rtos/commonpart/serviceInfo2"); } + else if(serviceReason == MPC_SERVICE_TRACE) + { + *srcType = CM_MPC_SERVICE_TRACE; + } else if(serviceReason != MPC_SERVICE_NONE) { t_uint32 panicThis; diff --git a/drivers/staging/nmf-cm/cm/inc/cm_type.h b/drivers/staging/nmf-cm/cm/inc/cm_type.h index 83a34ecd706..780e27ca600 100644 --- a/drivers/staging/nmf-cm/cm/inc/cm_type.h +++ b/drivers/staging/nmf-cm/cm/inc/cm_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Component Manager types. * diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c index a934aa33e92..26446e19cdb 100644 --- a/drivers/staging/nmf-cm/cm_debug.c +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -5,12 +5,12 @@ */ #include -#include #include "osal-kernel.h" #include "cm_debug.h" #ifdef CONFIG_DEBUG_FS +#include static struct dentry *cm_dir; /* nmf-cm/ */ static struct dentry *proc_dir; /* nmf-cm/proc/ */ diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index 70cf6f37524..a2a6ffa5b57 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -12,9 +12,9 @@ #include #include +#include #include #include -#include #include @@ -71,7 +71,7 @@ void dispatch_service_msg(struct osal_msg *msg) spin_lock_bh(&channelPriv->bh_lock); plist_add(&new_msg->msg_entry, &channelPriv->messageQueue); spin_unlock_bh(&channelPriv->bh_lock); - wake_up_interruptible(&channelPriv->waitq); + wake_up(&channelPriv->waitq); } } @@ -113,6 +113,12 @@ static void service_tasklet_func(unsigned long unused) desc.u.print.value2); break; } + case CM_MPC_SERVICE_TRACE: + spin_lock_bh(&osalEnv.mpc[i].trace_reader_lock); + if (osalEnv.mpc[i].trace_reader) + wake_up_process(osalEnv.mpc[i].trace_reader); + spin_unlock_bh(&osalEnv.mpc[i].trace_reader_lock); + break; default: pr_err("[CM] %s: MPC Service Type %d not supported\n", __func__, type); } diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index a687e0206a3..ca8d664abb4 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -5,11 +5,11 @@ */ #include +#include #include #include #include #include -#include #include "cmioctl.h" #include "osal-kernel.h" #include "cmld.h" @@ -1397,9 +1397,9 @@ int cmld_PrivReserveMemory(struct cm_process_priv *procPriv, unsigned int physAd /* Mark this memory area reserved for a mapping for this thread ID */ /* It must not be already reserved but this should not happen */ if (curr->tid) { - /*pr_err("%s: thread %d can't reseveved memory %x already " + pr_err("%s: thread %d can't reseveved memory %x already " "reserved for %d\n", - __func__, current->pid, physAddr, (int)curr->tid);*/ + __func__, current->pid, physAddr, curr->tid); err = -EBUSY; } else { curr->tid = current->pid; diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h index 96481be38b8..5f7d5b6a349 100644 --- a/drivers/staging/nmf-cm/cmioctl.h +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -29,9 +29,11 @@ enum cmdma_type { CMDMA_PER_2_MEM }; -#define CMLD_DEV_NAME \ - { "cm_control", \ - "cm_channel" \ +#define CMLD_DEV_NAME \ + { "cm_control", \ + "cm_channel", \ + "cm_sia_trace", \ + "cm_sva_trace", \ } /* diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index ef9753de7a4..53e07cd3137 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -14,9 +14,9 @@ #include #include #include +#include #include #include -#include #include #include @@ -29,7 +29,7 @@ #include "cm_service.h" #include "cm_dma.h" -#define CMDRIVER_PATCH_VERSION 117 +#define CMDRIVER_PATCH_VERSION 122 #define O_FLUSH 0x1000000 static int cmld_major; @@ -233,111 +233,6 @@ static void freeProcessPriv(struct kref *ref) OSAL_Free(entry); } -/** Driver's open method - * Allocates per-process resources: private data, wait queue, - * memory area descriptors linked list, message queue. - * - * \return POSIX error code - */ -static int cmld_open(struct inode *inode, struct file *file) -{ - struct cm_process_priv *procPriv = getProcessPriv(); - - if (IS_ERR(procPriv)) - return PTR_ERR(procPriv); - - if (iminor(inode) == 0) - file->private_data = procPriv; - else { - struct cm_channel_priv *channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); - if (channelPriv == NULL) { - kref_put(&procPriv->ref, freeProcessPriv); - return -ENOMEM; - } - - channelPriv->proc = procPriv; - channelPriv->state = CHANNEL_OPEN; - - /* Initialize wait_queue, lists and mutexes */ - init_waitqueue_head(&channelPriv->waitq); - plist_head_init(&channelPriv->messageQueue); - INIT_LIST_HEAD(&channelPriv->skelList); - spin_lock_init(&channelPriv->bh_lock); - mutex_init(&channelPriv->msgQueueLock); - mutex_init(&channelPriv->skelListLock); - - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_add(&channelPriv->entry, &channel_list); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - file->private_data = channelPriv; // store channel private struct in file descriptor - } - return 0; -} - -/** Driver's release method. - * Frees any per-process pending resource: components, bindings, memory areas. - * - * \return POSIX error code - */ -static int cmld_release(struct inode *inode, struct file *file) -{ - struct cm_process_priv* procPriv; - - /* The driver must guarantee that all related resources are released. - Thus all these checks below are necessary to release all remaining - resources still linked to this 'client', in case of abnormal process - exit. - => These are error cases ! - In the usual case, nothing should be done except the free of - the cmPriv itself - */ - - if (iminor(inode) != 0) { - struct cm_channel_priv* channelPriv; - channelPriv = file->private_data; - procPriv = channelPriv->proc; - - /* We don't need to synchronize here by using the skelListLock: - the list is only accessed during ioctl() and we can't be here - if an ioctl() is on-going */ - if (list_empty(&channelPriv->skelList)) { - /* There is no pending MPC->HOST binding - => we can quietly delete the channel */ - tasklet_disable(&cmld_service_tasklet); - mutex_lock(&channel_lock); - list_del(&channelPriv->entry); - mutex_unlock(&channel_lock); - tasklet_enable(&cmld_service_tasklet); - - /* Free all remaining messages if any */ - freeMessages(channelPriv); - - /* Free the per-channel descriptor */ - OSAL_Free(channelPriv); - } else { - /* Uh: there are still some MPC->HOST binding but we don't have the - required info to unbind them. - => we must keep all skel structures because possibly used in OSAL_PostDfc - (incoming callback msg) */ - /* We flag the channel as closed to discard any new msg that will never be read anyway */ - channelPriv->state = CHANNEL_CLOSED; - - /* Already Free all remaining messages if any, - they will never be read anyway */ - freeMessages(channelPriv); - } - } else - procPriv = file->private_data; - - kref_put(&procPriv->ref, freeProcessPriv); - file->private_data = NULL; - - return 0; -} - /** Reads Component Manager messages destinated to this process. * The message is composed by three fields: * 1) mpc2host handle (distinguishes interfaces) @@ -347,19 +242,16 @@ static int cmld_release(struct inode *inode, struct file *file) * \note cfr GetEvent() * \return POSIX error code */ -static ssize_t cmld_read(struct file *file, char *buf, size_t count, loff_t *ppos) +static ssize_t cmld_channel_read(struct file *file, char *buf, size_t count, loff_t *ppos) { int err = 0; - struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); + struct cm_channel_priv* channelPriv = file->private_data; int msgSize = 0; struct plist_head* messageQueue; struct osal_msg* msg; t_os_message *os_msg = (t_os_message *)buf; int block = !(file->f_flags & O_NONBLOCK); - if (iminor(file->f_dentry->d_inode) == 0) - return -ENOSYS; - messageQueue = &channelPriv->messageQueue; if (mutex_lock_killable(&channelPriv->msgQueueLock)) @@ -459,19 +351,21 @@ out: * * \return POSIX error code */ -static int cmld_flush(struct file *file, fl_owner_t id) +static int cmld_channel_flush(struct file *file, fl_owner_t id) { - if (iminor(file->f_dentry->d_inode) != 0) { - struct cm_channel_priv* channelPriv = (struct cm_channel_priv*)(file->private_data); - file->f_flags |= O_FLUSH; - wake_up_interruptible(&channelPriv->waitq); - } + struct cm_channel_priv* channelPriv = file->private_data; + file->f_flags |= O_FLUSH; + wake_up(&channelPriv->waitq); return 0; } -static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_channel_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_channel_priv *channelPriv = file->private_data; +#ifdef CONFIG_DEBUG_FS + if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) + return -ERESTARTSYS; +#endif switch(cmd) { /* @@ -480,7 +374,7 @@ static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long case CM_BINDCOMPONENTTOCMCORE: return cmld_BindComponentToCMCore(channelPriv, (CM_BindComponentToCMCore_t *)arg); case CM_FLUSHCHANNEL: - return cmld_flush(file, 0); + return cmld_channel_flush(file, 0); default: pr_err("CM(%s): unsupported command %i\n", __func__, cmd); return -EINVAL; @@ -488,9 +382,18 @@ static long cmld_channel_ctl(struct file *file, unsigned int cmd, unsigned long return 0; } -static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long arg) +static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct cm_process_priv* procPriv = file->private_data; +#ifdef CONFIG_DEBUG_FS + if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { + cmld_dump_ongoing = false; + wake_up(&dump_waitq); + return 0; + } else if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) + return -ERESTARTSYS; +#endif + switch(cmd) { /* * All wrapped CM SYSCALL @@ -695,7 +598,6 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long cmld_user_has_debugfs = true; #endif return 0; - case CM_PRIV_DEBUGFS_DUMP_DONE: case CM_PRIV_DEBUGFS_WAIT_DUMP: return 0; default: @@ -706,29 +608,6 @@ static long cmld_control_ctl(struct file *file, unsigned int cmd, unsigned long return 0; } -/** Driver's ioctl method - * Implements user/kernel crossing for SYSCALL API. - * - * \return POSIX error code - */ -static long cmld_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) -{ -#ifdef CONFIG_DEBUG_FS - if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { - cmld_dump_ongoing = false; - wake_up_interruptible(&dump_waitq); - return 0; - } else if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) - return -ERESTARTSYS; -#endif - - if (iminor(filp->f_dentry->d_inode) == 0) { - return cmld_control_ctl(filp, cmd, arg); - } else { - return cmld_channel_ctl(filp, cmd, arg); - } -} - /** VMA open callback function */ static void cmld_vma_open(struct vm_area_struct* vma) { @@ -755,7 +634,7 @@ static struct vm_operations_struct cmld_remap_vm_ops = { * * \return POSIX error code */ -static int cmld_mmap(struct file* file, struct vm_area_struct* vma) +static int cmld_control_mmap(struct file *file, struct vm_area_struct *vma) { unsigned long offset = vma->vm_pgoff << PAGE_SHIFT; struct list_head* listHead; @@ -827,6 +706,278 @@ static int cmld_mmap(struct file* file, struct vm_area_struct* vma) return 0; } +/* Driver's release method for /dev/cm_channel */ +static int cmld_channel_release(struct inode *inode, struct file *file) +{ + struct cm_channel_priv* channelPriv = file->private_data; + struct cm_process_priv* procPriv = channelPriv->proc; + + /* + * The driver must guarantee that all related resources are released. + * Thus all these checks below are necessary to release all remaining + * resources still linked to this 'client', in case of abnormal process + * exit. + * => These are error cases ! + * In the usual case, nothing should be done except the free of + * the cmPriv itself + */ + + /* We don't need to synchronize here by using the skelListLock: + the list is only accessed during ioctl() and we can't be here + if an ioctl() is on-going */ + if (list_empty(&channelPriv->skelList)) { + /* There is no pending MPC->HOST binding + => we can quietly delete the channel */ + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_del(&channelPriv->entry); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + /* Free all remaining messages if any */ + freeMessages(channelPriv); + + /* Free the per-channel descriptor */ + OSAL_Free(channelPriv); + } else { + /* + * Uh: there are still some MPC->HOST binding but we don't have + * the required info to unbind them. + * => we must keep all skel structures because possibly used in + * OSAL_PostDfc (incoming callback msg). We flag the channel as + * closed to discard any new msg that will never be read anyway + */ + channelPriv->state = CHANNEL_CLOSED; + + /* Already Free all remaining messages if any, + they will never be read anyway */ + freeMessages(channelPriv); + } + + kref_put(&procPriv->ref, freeProcessPriv); + file->private_data = NULL; + + return 0; +} + +/* Driver's release method for /dev/cm_control */ +static int cmld_control_release(struct inode *inode, struct file *file) +{ + struct cm_process_priv* procPriv = file->private_data; + + kref_put(&procPriv->ref, freeProcessPriv); + file->private_data = NULL; + + return 0; +} + +static struct file_operations cmld_control_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = cmld_control_ioctl, + .mmap = cmld_control_mmap, + .release = cmld_control_release, +}; + +static int cmld_control_open(struct file *file) +{ + struct cm_process_priv *procPriv = getProcessPriv(); + if (IS_ERR(procPriv)) + return PTR_ERR(procPriv); + file->private_data = procPriv; + file->f_op = &cmld_control_fops; + return 0; +} + +static struct file_operations cmld_channel_fops = { + .owner = THIS_MODULE, + .read = cmld_channel_read, + .unlocked_ioctl = cmld_channel_ioctl, + .flush = cmld_channel_flush, + .release = cmld_channel_release, +}; + +static int cmld_channel_open(struct file *file) +{ + struct cm_process_priv *procPriv = getProcessPriv(); + struct cm_channel_priv *channelPriv; + + if (IS_ERR(procPriv)) + return PTR_ERR(procPriv); + + channelPriv = (struct cm_channel_priv*)OSAL_Alloc(sizeof(*channelPriv)); + if (channelPriv == NULL) { + kref_put(&procPriv->ref, freeProcessPriv); + return -ENOMEM; + } + + channelPriv->proc = procPriv; + channelPriv->state = CHANNEL_OPEN; + + /* Initialize wait_queue, lists and mutexes */ + init_waitqueue_head(&channelPriv->waitq); + plist_head_init(&channelPriv->messageQueue); + INIT_LIST_HEAD(&channelPriv->skelList); + spin_lock_init(&channelPriv->bh_lock); + mutex_init(&channelPriv->msgQueueLock); + mutex_init(&channelPriv->skelListLock); + + tasklet_disable(&cmld_service_tasklet); + mutex_lock(&channel_lock); + list_add(&channelPriv->entry, &channel_list); + mutex_unlock(&channel_lock); + tasklet_enable(&cmld_service_tasklet); + + file->private_data = channelPriv; + file->f_op = &cmld_channel_fops; + return 0; +} + +static ssize_t cmld_sxa_trace_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + struct mpcConfig *mpc = file->private_data; + size_t written = 0; + struct t_nmf_trace trace; + t_cm_trace_type traceType; + struct mmdsp_trace mmdsp_tr = { + .media = TB_MEDIA_FILE, + .receiver_dev = TB_DEV_PC, + .sender_dev = TB_DEV_TRACEBOX, + .unused = TB_TRACEBOX, + .receiver_obj = DEFAULT_RECEIVERR_OBJ, + .sender_obj = DEFAULT_SENDER_OBJ, + .transaction_id = 0, + .message_id = TB_TRACE_MSG, + .master_id = mpc->coreId+1, + .channel_id = 0, + .ost_version = OST_VERSION, + .entity = ENTITY, + .protocol_id = PROTOCOL_ID, + .btrace_hdr_flag = 0, + .btrace_hdr_subcategory = 0, + }; + + while ((count - written) >= sizeof(mmdsp_tr)) { + traceType = CM_ENGINE_GetNextTrace(mpc->coreId, &trace); + + switch (traceType) { + case CM_MPC_TRACE_READ_OVERRUN: + mmdsp_tr.size = + cpu_to_be16(offsetof(struct mmdsp_trace, + ost_version) + -offsetof(struct mmdsp_trace, + receiver_obj)); + mmdsp_tr.message_id = TB_TRACE_EXCEPTION_MSG; + mmdsp_tr.ost_master_id = TB_EXCEPTION_LONG_OVRF_PACKET; + if (copy_to_user(&buf[written], &mmdsp_tr, + offsetof(struct mmdsp_trace, + ost_version))) + return -EFAULT; + written += offsetof(struct mmdsp_trace, ost_version); + if ((count - written) < sizeof(mmdsp_tr)) + break; + case CM_MPC_TRACE_READ: { + u16 param_nr = (u16)trace.paramOpt; + u16 handle_valid = (u16)(trace.paramOpt >> 16); + u32 to_write = offsetof(struct mmdsp_trace, + parent_handle); + mmdsp_tr.transaction_id = trace.revision%256; + mmdsp_tr.message_id = TB_TRACE_MSG; + mmdsp_tr.ost_master_id = OST_MASTERID; + mmdsp_tr.timestamp = cpu_to_be64(trace.timeStamp); + mmdsp_tr.timestamp2 = cpu_to_be64(trace.timeStamp); + mmdsp_tr.component_id = cpu_to_be32(trace.componentId); + mmdsp_tr.trace_id = cpu_to_be32(trace.traceId); + mmdsp_tr.btrace_hdr_category = (trace.traceId>>16)&0xFF; + mmdsp_tr.btrace_hdr_size = BTRACE_HEADER_SIZE + + sizeof(trace.params[0]) * param_nr; + if (handle_valid) { + mmdsp_tr.parent_handle = trace.parentHandle; + mmdsp_tr.component_handle = + trace.componentHandle; + to_write += sizeof(trace.parentHandle) + + sizeof(trace.componentHandle); + mmdsp_tr.btrace_hdr_size += + sizeof(trace.parentHandle) + + sizeof(trace.componentHandle); + } + mmdsp_tr.size = + cpu_to_be16(to_write + + (sizeof(trace.params[0])*param_nr) + - offsetof(struct mmdsp_trace, + receiver_obj)); + mmdsp_tr.length = to_write + + (sizeof(trace.params[0])*param_nr) + - offsetof(struct mmdsp_trace, + timestamp2); + if (copy_to_user(&buf[written], &mmdsp_tr, to_write)) + return -EFAULT; + written += to_write; + /* write param */ + to_write = sizeof(trace.params[0]) * param_nr; + if (copy_to_user(&buf[written], trace.params, to_write)) + return -EFAULT; + written += to_write; + break; + } + case CM_MPC_TRACE_NONE: + default: + if ((file->f_flags & O_NONBLOCK) || written) + return written; + spin_lock_bh(&mpc->trace_reader_lock); + mpc->trace_reader = current; + spin_unlock_bh(&mpc->trace_reader_lock); + schedule_timeout_killable(msecs_to_jiffies(200)); + spin_lock_bh(&mpc->trace_reader_lock); + mpc->trace_reader = NULL; + spin_unlock_bh(&mpc->trace_reader_lock); + if (signal_pending(current)) + return -ERESTARTSYS; + } + } + return written; +} + +/* Driver's release method for /dev/cm_sxa_trace */ +static int cmld_sxa_trace_release(struct inode *inode, struct file *file) +{ + struct mpcConfig *mpc = file->private_data; + atomic_dec(&mpc->trace_read_count); + return 0; +} + +static struct file_operations cmld_sxa_trace_fops = { + .owner = THIS_MODULE, + .read = cmld_sxa_trace_read, + .release = cmld_sxa_trace_release, +}; + +static int cmld_sxa_trace_open(struct file *file, struct mpcConfig *mpc) +{ + if (atomic_add_unless(&mpc->trace_read_count, 1, 1) == 0) + return -EBUSY; + + file->private_data = mpc; + file->f_op = &cmld_sxa_trace_fops; + return 0; +} + +/* driver open() call: specific */ +static int cmld_open(struct inode *inode, struct file *file) +{ + switch (iminor(inode)) { + case 0: + return cmld_control_open(file); + case 1: + return cmld_channel_open(file); + case 2: + return cmld_sxa_trace_open(file, &osalEnv.mpc[SIA]); + case 3: + return cmld_sxa_trace_open(file, &osalEnv.mpc[SVA]); + default: + return -ENOSYS; + } +} + /** MPC Events tasklet * The parameter is used to know from which interrupts we're comming * and which core to pass to CM_ProcessMpcEvent(): @@ -882,12 +1033,7 @@ static irqreturn_t panic_handler(int irq, void *idx) */ static struct file_operations cmld_fops = { .owner = THIS_MODULE, - .read = cmld_read, - .unlocked_ioctl = cmld_ioctl, - .mmap = cmld_mmap, .open = cmld_open, - .flush = cmld_flush, - .release = cmld_release, }; /** diff --git a/drivers/staging/nmf-cm/cmld.h b/drivers/staging/nmf-cm/cmld.h index 4c5a5bed7e6..17e6c55ff61 100644 --- a/drivers/staging/nmf-cm/cmld.h +++ b/drivers/staging/nmf-cm/cmld.h @@ -79,6 +79,52 @@ extern bool cmld_user_has_debugfs; /**< Whether user side has proper support of extern bool cmld_dump_ongoing; /**< Whether a dump is on-going */ #endif +/* Structure used to embed DSP traces */ +#define TB_MEDIA_FILE 0x1C +#define TB_DEV_PC 0x10 +#define TB_DEV_TRACEBOX 0x4C +#define TB_TRACEBOX 0x7C +#define DEFAULT_RECEIVERR_OBJ 0x0 +#define DEFAULT_SENDER_OBJ 0x0A +#define TB_TRACE_MSG 0x94 +#define TB_TRACE_EXCEPTION_MSG 0x95 +#define TB_EXCEPTION_LONG_OVRF_PACKET 0x07 +#define OST_MASTERID 0x08 +#define OST_VERSION 0x05 +#define ENTITY 0xAA +#define PROTOCOL_ID 0x03 +#define BTRACE_HEADER_SIZE 4 + +struct __attribute__ ((__packed__)) mmdsp_trace { + u8 media; + u8 receiver_dev; + u8 sender_dev; + u8 unused; + u16 size; + u8 receiver_obj; + u8 sender_obj; + u8 transaction_id; + u8 message_id; + u8 master_id; + u8 channel_id; + u64 timestamp; + u8 ost_master_id; + u8 ost_version; + u8 entity; + u8 protocol_id; + u8 length; + u64 timestamp2; + u32 component_id; + u32 trace_id; + u8 btrace_hdr_size; + u8 btrace_hdr_flag; + u8 btrace_hdr_category; + u8 btrace_hdr_subcategory; + u32 parent_handle; + u32 component_handle; + u32 params[4]; +}; + /** Lock/unlock per process mutex * * \note Must be taken before tasklet_disable (if necessary)! diff --git a/drivers/staging/nmf-cm/configuration.c b/drivers/staging/nmf-cm/configuration.c index d62bcb45500..523874fc586 100644 --- a/drivers/staging/nmf-cm/configuration.c +++ b/drivers/staging/nmf-cm/configuration.c @@ -21,28 +21,30 @@ struct OsalEnvironment osalEnv = { .mpc = { { - .coreId = SVA_CORE_ID, - .name = "sva", - .base_phys = (void*)U8500_SVA_BASE, - .interrupt0 = IRQ_DB8500_SVA, - .interrupt1 = IRQ_DB8500_SVA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, + .coreId = SVA_CORE_ID, + .name = "sva", + .base_phys = (void*)U8500_SVA_BASE, + .interrupt0 = IRQ_DB8500_SVA, + .interrupt1 = IRQ_DB8500_SVA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, + .trace_read_count = ATOMIC_INIT(0), }, { - .coreId = SIA_CORE_ID, - .name = "sia", - .base_phys = (void*)U8500_SIA_BASE, - .interrupt0 = IRQ_DB8500_SIA, - .interrupt1 = IRQ_DB8500_SIA2, - .mmdsp_regulator = NULL, - .pipe_regulator = NULL, - .monitor_tsk = NULL, - .hwmem_code = NULL, - .hwmem_data = NULL, + .coreId = SIA_CORE_ID, + .name = "sia", + .base_phys = (void*)U8500_SIA_BASE, + .interrupt0 = IRQ_DB8500_SIA, + .interrupt1 = IRQ_DB8500_SIA2, + .mmdsp_regulator = NULL, + .pipe_regulator = NULL, + .monitor_tsk = NULL, + .hwmem_code = NULL, + .hwmem_data = NULL, + .trace_read_count = ATOMIC_INIT(0), } }, .esram_regulator = { NULL, NULL}, @@ -125,16 +127,20 @@ int init_config(void) pr_err("SDRAM data size for SVA must be greater than 0\n"); return -EINVAL; } + osalEnv.mpc[SVA].nbYramBanks = cfgMpcYBanks_SVA; osalEnv.mpc[SVA].eeId = cfgSchedulerTypeHybrid_SVA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SVA].sdram_code.size = cfgMpcSDRAMCodeSize_SVA * ONE_KB; osalEnv.mpc[SVA].sdram_data.size = cfgMpcSDRAMDataSize_SVA * ONE_KB; osalEnv.mpc[SVA].base.size = 128*ONE_KB; //we expose only TCM24 + spin_lock_init(&osalEnv.mpc[SVA].trace_reader_lock); + osalEnv.mpc[SIA].nbYramBanks = cfgMpcYBanks_SIA; osalEnv.mpc[SIA].eeId = cfgSchedulerTypeHybrid_SIA ? HYBRID_EXECUTIVE_ENGINE : SYNCHRONOUS_EXECUTIVE_ENGINE; osalEnv.mpc[SIA].sdram_code.size = cfgMpcSDRAMCodeSize_SIA * ONE_KB; osalEnv.mpc[SIA].sdram_data.size = cfgMpcSDRAMDataSize_SIA * ONE_KB; osalEnv.mpc[SIA].base.size = 128*ONE_KB; //we expose only TCM24 + spin_lock_init(&osalEnv.mpc[SIA].trace_reader_lock); return 0; } diff --git a/drivers/staging/nmf-cm/configuration.h b/drivers/staging/nmf-cm/configuration.h index 35072831a13..f4146dc6117 100644 --- a/drivers/staging/nmf-cm/configuration.h +++ b/drivers/staging/nmf-cm/configuration.h @@ -20,12 +20,14 @@ #endif /* Embedded Static RAM base address */ -#define ESRAM_BASE (U8500_ESRAM_BASE + 0x10000) // V1/V2 config: 0-64k: secure; +/* config: 0-64k: secure */ +#define ESRAM_BASE (U8500_ESRAM_BASE + U8500_ESRAM_DMA_LCPA_OFFSET) /* * Embedded ram size for CM (in Kb) * 5 banks of 128k: skip the first half bank (secure) and the last * one (used for MCDE/B2R2), but include DMA part (4k after the secure part) + * to give access from DSP side */ #define ESRAM_SIZE 448 enum { diff --git a/drivers/staging/nmf-cm/ee/api/panic.idt b/drivers/staging/nmf-cm/ee/api/panic.idt index f971fdad8c5..71996b8a55e 100644 --- a/drivers/staging/nmf-cm/ee/api/panic.idt +++ b/drivers/staging/nmf-cm/ee/api/panic.idt @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \defgroup NMF_EE_TYPE Execution Engine Common Type Definitions * \ingroup COMMON @@ -55,7 +54,8 @@ typedef enum { INTERFACE_NOT_BINDED = 8, USER_PANIC = 9, UNBIND_INTERRUPT = 10, - EVENT_FIFO_IN_USE = 11 + EVENT_FIFO_IN_USE = 11, + RESERVED_PANIC = 2 //for COMPATIBILITY with previous versions of NMF, to be deprecated } t_panic_reasonDescription; /*! diff --git a/drivers/staging/nmf-cm/ee/api/trace.idt b/drivers/staging/nmf-cm/ee/api/trace.idt new file mode 100644 index 00000000000..f4d4c8615e2 --- /dev/null +++ b/drivers/staging/nmf-cm/ee/api/trace.idt @@ -0,0 +1,30 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO for ST-Ericsson. + * License terms: GNU General Public License (GPL), version 2, with + * user space exemption described in the top-level COPYING file in + * the Linux kernel source tree. + */ +/*! + * \defgroup NMF_EE_TYPE Execution Engine Common Type Definitions + * \ingroup COMMON + */ + +#ifndef __INC_TRACE_IDT +#define __INC_TRACE_IDT + +struct t_nmf_trace +{ + t_uint32 revision; + t_uint32 timeStamp; + t_uint32 componentId; + t_uint32 traceId; + t_uint32 paramOpt; + t_uint32 componentHandle; + t_uint32 parentHandle; + t_uint32 params[4]; +}; + +#define TRACE_BUFFER_SIZE 128 + +#endif diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index e671198f7b9..7cdea18996b 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (118)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (122)) /*! * \brief Get NMF major version corresponding to NMF version number diff --git a/drivers/staging/nmf-cm/inc/nmf-limits.h b/drivers/staging/nmf-cm/inc/nmf-limits.h index a942e542233..374795f91e0 100644 --- a/drivers/staging/nmf-cm/inc/nmf-limits.h +++ b/drivers/staging/nmf-cm/inc/nmf-limits.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Common Nomadik Multiprocessing Framework limits definition * diff --git a/drivers/staging/nmf-cm/inc/nmf-tracedescription.h b/drivers/staging/nmf-cm/inc/nmf-tracedescription.h index 9611803b978..bce589079b9 100644 --- a/drivers/staging/nmf-cm/inc/nmf-tracedescription.h +++ b/drivers/staging/nmf-cm/inc/nmf-tracedescription.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief NMF xti/stm trace format description * diff --git a/drivers/staging/nmf-cm/inc/nmf_type.idt b/drivers/staging/nmf-cm/inc/nmf_type.idt index e8cc4e09946..dda547a463e 100644 --- a/drivers/staging/nmf-cm/inc/nmf_type.idt +++ b/drivers/staging/nmf-cm/inc/nmf_type.idt @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - #ifndef NMF_TYPE_H_ #define NMF_TYPE_H_ diff --git a/drivers/staging/nmf-cm/inc/type.h b/drivers/staging/nmf-cm/inc/type.h index d6eafe9aea5..3075505aee5 100644 --- a/drivers/staging/nmf-cm/inc/type.h +++ b/drivers/staging/nmf-cm/inc/type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /* inc/type.h - Programming Model. * * Copyright (c) 2006, 2007, 2008 STMicroelectronics. diff --git a/drivers/staging/nmf-cm/inc/typedef.h b/drivers/staging/nmf-cm/inc/typedef.h index 97af9dec2c2..a29e6b88fde 100644 --- a/drivers/staging/nmf-cm/inc/typedef.h +++ b/drivers/staging/nmf-cm/inc/typedef.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \defgroup COMMON Common types and definitions * diff --git a/drivers/staging/nmf-cm/nmf/inc/channel_type.h b/drivers/staging/nmf-cm/nmf/inc/channel_type.h index 7d439ebf0cf..91a733dbbbf 100644 --- a/drivers/staging/nmf-cm/nmf/inc/channel_type.h +++ b/drivers/staging/nmf-cm/nmf/inc/channel_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Common Nomadik Multiprocessing Framework type definition * diff --git a/drivers/staging/nmf-cm/nmf/inc/component_type.h b/drivers/staging/nmf-cm/nmf/inc/component_type.h index 08b63b21225..26217554158 100644 --- a/drivers/staging/nmf-cm/nmf/inc/component_type.h +++ b/drivers/staging/nmf-cm/nmf/inc/component_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Common Nomadik Multiprocessing Framework type definition * diff --git a/drivers/staging/nmf-cm/nmf/inc/service_type.h b/drivers/staging/nmf-cm/nmf/inc/service_type.h index 3e5473338ee..06d5c72dce9 100644 --- a/drivers/staging/nmf-cm/nmf/inc/service_type.h +++ b/drivers/staging/nmf-cm/nmf/inc/service_type.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Service type and data used through service callback. * \defgroup NMF_SERVICE NMF Service Callback types and data definition diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 94aa11fc91c..e79e35db106 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -353,7 +353,7 @@ void OSAL_PostDfc(t_nmf_mpc2host_handle upLayerTHIS, t_uint32 methodIndex, t_eve spin_unlock_bh(&skelwrapper->channelPriv->bh_lock); /* Wake up process' wait queue */ - wake_up_interruptible(&skelwrapper->channelPriv->waitq); + wake_up(&skelwrapper->channelPriv->waitq); } @@ -755,8 +755,8 @@ static int dspload_monitor(void *idx) /* init counter */ if (CM_GetMpcLoadCounter(mpc->coreId, &mpc->oldLoadCounter) != CM_OK) - pr_err("CM Driver: Failed to init load counter for %s\n", - mpc->name); + pr_warn("CM Driver: Failed to init load counter for %s\n", + mpc->name); while (!kthread_should_stop()) { t_cm_mpc_load_counter loadCounter; @@ -919,7 +919,7 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); + secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -927,16 +927,16 @@ void OSAL_DisablePwrRessource(t_nmf_power_resource resource, t_uint32 firstParam break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= 0x40000; + secondParam /= (2*U8500_ESRAM_BANK_SIZE); WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < (U8500_ESRAM_BASE+0x20000)) + if (firstParam < U8500_ESRAM_BANK1) firstParam = 0; else - firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; + firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); /* power off the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { @@ -1032,7 +1032,7 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first /* Compute the relative end address of the range, relative to base address of BANK1 */ - secondParam = (firstParam+secondParam-(U8500_ESRAM_BASE+0x20000)-1); + secondParam = (firstParam+secondParam-U8500_ESRAM_BANK1-1); /* if end is below base address of BANK1, it means that full range of addresses is on Bank0 */ @@ -1040,16 +1040,16 @@ t_cm_error OSAL_EnablePwrRessource(t_nmf_power_resource resource, t_uint32 first break; /* Compute the index of the last bank accessed among esram 1+2 and esram 3+4 banks */ - secondParam /= 0x40000; + secondParam /= (2*U8500_ESRAM_BANK_SIZE); WARN_ON(secondParam > 1); /* Compute the index of the first bank accessed among esram 1+2 and esram 3+4 banks Do not manage Bank 0 (secured, must be always ON) */ - if (firstParam < (U8500_ESRAM_BASE+0x20000)) + if (firstParam < U8500_ESRAM_BANK1) firstParam = 0; else - firstParam = (firstParam-(U8500_ESRAM_BASE+0x20000))/0x40000; + firstParam = (firstParam-U8500_ESRAM_BANK1)/(2*U8500_ESRAM_BANK_SIZE); /* power on the banks 1+2 and 3+4 if accessed. */ for (i=firstParam; i<=secondParam; i++) { diff --git a/drivers/staging/nmf-cm/osal-kernel.h b/drivers/staging/nmf-cm/osal-kernel.h index 7a71bdd591d..29b82368d8d 100644 --- a/drivers/staging/nmf-cm/osal-kernel.h +++ b/drivers/staging/nmf-cm/osal-kernel.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #ifdef CONFIG_HAS_WAKELOCK #include #endif @@ -24,7 +26,6 @@ */ #define _CM_ELF_H #include -#include #include "configuration.h" @@ -56,6 +57,9 @@ struct mpcConfig { #endif struct task_struct *monitor_tsk; /**< task to monitor the dsp load; */ t_cm_mpc_load_counter oldLoadCounter; /**< previous load counter of the DSP */ + atomic_t trace_read_count; /**< number of trace reader */ + spinlock_t trace_reader_lock; + struct task_struct *trace_reader;/**< current reader task */ #ifdef CONFIG_DEBUG_FS struct dentry *dir; /**< debugfs dir entry */ struct dentry *comp_dir; /**< debugfs component dir entry */ diff --git a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h index 5ec08434492..71dfc534f97 100644 --- a/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h +++ b/drivers/staging/nmf-cm/share/communication/inc/nmf_service.h @@ -12,5 +12,6 @@ #define MPC_SERVICE_NONE 0 #define MPC_SERVICE_BOOT 0xB001 #define MPC_SERVICE_PRINT 0x1234 +#define MPC_SERVICE_TRACE 0x789 #endif diff --git a/drivers/staging/nmf-cm/share/inc/macros.h b/drivers/staging/nmf-cm/share/inc/macros.h index c96fe031c25..7d2c2289cd3 100644 --- a/drivers/staging/nmf-cm/share/inc/macros.h +++ b/drivers/staging/nmf-cm/share/inc/macros.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief NMF Macro API. */ diff --git a/drivers/staging/nmf-cm/share/inc/nmf.h b/drivers/staging/nmf-cm/share/inc/nmf.h index 8be8b41e5e3..2f73311c2f3 100644 --- a/drivers/staging/nmf-cm/share/inc/nmf.h +++ b/drivers/staging/nmf-cm/share/inc/nmf.h @@ -5,7 +5,6 @@ * user space exemption described in the top-level COPYING file in * the Linux kernel source tree. */ - /*! * \brief Common Nomadik Multiprocessing Framework type definition * -- cgit v1.2.3 From 5ebec164043cc51d5c24d935598148e0cd7cb655 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Thu, 15 Dec 2011 14:10:40 +0100 Subject: U8500 CM: Don't print corrupted data When we detect a corruption, we try to print the corrupted data leading to a kernel panic. We stop to do that. ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson ID: 402487 ST-Ericsson Linux next: NA Signed-off-by: Pierre Peiffer Change-Id: I80f43567e06f8a057afc62874ca2ab065bb8e2a7 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42710 Reviewed-by: QABUILD Reviewed-by: Pierre PEIFFER Tested-by: Pierre PEIFFER --- drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c index 1342e9e0155..c6c316046b3 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/mmdsp-debug.c @@ -127,17 +127,13 @@ t_cm_error cm_DSPABI_AddLoadMap( if(((t_uint32)curItem->pNextItem < SDRAMMEM16_BASE_ADDR) || ((t_uint32)curItem->pNextItem > endSegmentAddr)) { if (prevItem == NULL) - ERROR("AddLoadMap: Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n" - "Previou (first) component name %s<%s>\n", + ERROR("AddLoadMap: Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n", curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, - curItem->pARMThis ? (char*)(((t_component_instance *)&curItem->pARMThis)->pathname) : "", - curItem->pARMThis ? (char*)(((t_component_instance *)&curItem->pARMThis)->Template->name) : "", 0, 0); + 0, 0, 0, 0); else - ERROR("AddLoadMap: Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n" - "Previous valid component name %s<%s>", + ERROR("AddLoadMap: Memory corruption in MMDSP: at data DSP address=%x or ARM address=%x\n", curItemDspAdress + myoffsetof(struct LoadMapItem, pNextItem), &curItem->pNextItem, - prevItem->pARMThis ? (char*)(((t_component_instance *)&prevItem->pARMThis)->pathname) : "", - prevItem->pARMThis ? (char*)(((t_component_instance *)&prevItem->pARMThis)->Template->name) : "", 0, 0); + 0, 0, 0, 0); return CM_INVALID_DATA; } curItemDspAdress = (t_uint32)curItem->pNextItem; -- cgit v1.2.3 From 274c285bd7971c6fa76ad896f5275b359b85c323 Mon Sep 17 00:00:00 2001 From: Vincent Veron Date: Wed, 14 Dec 2011 11:47:36 +0100 Subject: U8500 CM: add read permission to others in debugfs The debugfs files used to do the DSP dump are not readable by others. This prevents user process not running at as root to take any dump. Add read permission to others to allow this. ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson ID: 404423 ST-Ericsson Linux next: NA Change-Id: Id43181ac67d5c1ead964233cc34c16942dd11771 Signed-off-by: Pierre Peiffer Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42776 Reviewed-by: QABUILD --- drivers/staging/nmf-cm/cm_debug.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c index 26446e19cdb..b894c6b8e4a 100644 --- a/drivers/staging/nmf-cm/cm_debug.c +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -679,7 +679,7 @@ static const struct file_operations esram_fops = { void cm_debug_create_tcm_file(unsigned mpc_index) { osalEnv.mpc[mpc_index].tcm_file = debugfs_create_blob( - "tcm24", S_IRUSR|S_IRGRP, + "tcm24", S_IRUSR|S_IRGRP|S_IROTH, osalEnv.mpc[mpc_index].snapshot_dir, &osalEnv.mpc[mpc_index].base); if (IS_ERR(osalEnv.mpc[mpc_index].tcm_file)) { @@ -801,14 +801,14 @@ void cm_debug_init(void) PTR_ERR(osalEnv.mpc[i].snapshot_dir)); osalEnv.mpc[i].snapshot_dir = NULL; } else { - debugfs_create_file("esram", S_IRUSR|S_IRGRP, + debugfs_create_file("esram", S_IRUSR|S_IRGRP|S_IROTH, osalEnv.mpc[i].snapshot_dir, &osalEnv.esram_base, &esram_fops); - debugfs_create_blob("sdram_data", S_IRUSR|S_IRGRP, + debugfs_create_blob("sdram_data", S_IRUSR|S_IRGRP|S_IROTH, osalEnv.mpc[i].snapshot_dir, &osalEnv.mpc[i].sdram_data); - debugfs_create_blob("sdram_code", S_IRUSR|S_IRGRP, + debugfs_create_blob("sdram_code", S_IRUSR|S_IRGRP|S_IROTH, osalEnv.mpc[i].snapshot_dir, &osalEnv.mpc[i].sdram_code); } -- cgit v1.2.3 From 221530527fe2428ba7c8171a9ddd0ed6582b7ee8 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Mon, 19 Dec 2011 18:29:49 +0100 Subject: U8500 CM: Enable logging through ftrace Logging all debug traces through printk is too intrusive to be usable, specialy when using debug level 2 or 3. Enable logging through ftrace by using a cm_use_ftrace flag. ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson ID: 405500 ST-Ericsson Linux next: NA Change-Id: I58cb53fb9801836ca85ee46144b05f39a5ac710e Signed-off-by: Pierre Peiffer Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/43145 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: QATEST --- drivers/staging/nmf-cm/osal-kernel.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index e79e35db106..6e3221130c5 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -49,6 +49,9 @@ MODULE_PARM_DESC(dspLoadHighThreshold, "Threshold above which 100 APE OPP is req static unsigned int dspLoadLowThreshold = 35; module_param(dspLoadLowThreshold, uint, S_IWUSR|S_IRUGO); MODULE_PARM_DESC(dspLoadLowThreshold, "Threshold below which 100 APE OPP request is removed"); +static bool cm_use_ftrace; +module_param(cm_use_ftrace, bool, S_IWUSR|S_IRUGO); +MODULE_PARM_DESC(cm_use_ftrace, "Whether all CM debug traces goes through ftrace or normal kernel output"); /** \defgroup ENVIRONMENT_INITIALIZATION Environment initialization * Includes functions that initialize the Linux OSAL itself plus functions that @@ -680,7 +683,11 @@ void OSAL_Write64(t_nmf_trace_channel channel, t_uint8 isTimestamped, t_uint64 v */ void OSAL_Log(const char *format, int param1, int param2, int param3, int param4, int param5, int param6) { - printk(format, param1, param2, param3, param4, param5, param6); + if (cm_use_ftrace) + trace_printk(format, + param1, param2, param3, param4, param5, param6); + else + printk(format, param1, param2, param3, param4, param5, param6); } /** -- cgit v1.2.3 From 2cf4e6c90e9eaa52e1e5d6160868e5232ff21fad Mon Sep 17 00:00:00 2001 From: Jonas Aaberg Date: Tue, 20 Dec 2011 08:18:45 +0100 Subject: drivers: stagning: nmf-cm: Always assume db v2.0 or later Remove check for pre v2.0 db8500 since pre v2.0 hardware is no longer supported. ST-Ericsson Linux next: - ST-Ericsson ID: 370799 ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I62ac40e8b8f34a3142465e5dde988704fb07095e Signed-off-by: Jonas Aaberg Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/43187 Reviewed-by: QABUILD Reviewed-by: Pierre PEIFFER --- drivers/staging/nmf-cm/cmld.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 53e07cd3137..60c20cadaee 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -582,12 +582,10 @@ static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned lon t_uint32 nmfversion = NMF_VERSION; return copy_to_user((void*)arg, &nmfversion, sizeof(nmfversion)); } - case CM_PRIV_GETBOARDVERSION: - if (cpu_is_u8500v20_or_later()) { - enum board_version v = U8500_V2; - return copy_to_user((void*)arg, &v, sizeof(v)); - } else - return -EINVAL; + case CM_PRIV_GETBOARDVERSION: { + enum board_version v = U8500_V2; + return copy_to_user((void*)arg, &v, sizeof(v)); + } case CM_PRIV_ISCOMPONENTCACHEEMPTY: if (CM_ENGINE_IsComponentCacheEmpty()) return 0; @@ -1207,14 +1205,10 @@ static int __init cmld_init_module(void) err = -EIO; prcmu_base = __io_address(U8500_PRCMU_BASE); - if (cpu_is_u8500v20_or_later()) { - /* power on a clock/timer 90KHz used on SVA */ - htim_base = ioremap_nocache(U8500_CR_BASE /*0xA03C8000*/, SZ_4K); - prcmu_tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); - } else { - pr_err("CM: Unsupported chip version\n"); - goto out; - } + + /* power on a clock/timer 90KHz used on SVA */ + htim_base = ioremap_nocache(U8500_CR_BASE /*0xA03C8000*/, SZ_4K); + prcmu_tcdm_base = __io_address(U8500_PRCMU_TCDM_BASE); /* Activate SVA 90 KHz timer */ if (htim_base == NULL) -- cgit v1.2.3 From 63b0b4e154652897ae8c4dbe6228990d76d57b17 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Tue, 20 Dec 2011 13:03:53 +0100 Subject: U8500 CM: fix crash when dumping domains info Fix a crash that happens when retrieving certain domains information through debugfs ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson ID: 405694 ST-Ericsson Linux next: NA Change-Id: Ia6940d1af6c696c00f630d56a9437f7bc7367667 Signed-off-by: Pierre Peiffer Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/43255 Reviewed-by: QABUILD --- drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c | 2 ++ drivers/staging/nmf-cm/cm_debug.c | 28 +++++++++++++++----------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c b/drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c index 7646f6301de..ef11a5265aa 100644 --- a/drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c +++ b/drivers/staging/nmf-cm/cm/engine/dsp/src/dsp.c @@ -513,6 +513,8 @@ PUBLIC void cm_DSP_GetDspAddress(t_memory_handle memHandle, t_uint32 *pDspAddres PUBLIC t_cm_error cm_DSP_GetDspBaseAddress(t_nmf_core_id coreId, t_dsp_memory_type_id memType, t_cm_system_address *pAddr) { cm_migration_check_state(coreId, STATE_NORMAL); + if (mpcDesc[coreId].allocator[memType] == NULL) + return CM_INVALID_PARAMETER; *pAddr = mpcDesc[coreId].allocator[memType]->baseAddress; return CM_OK; } diff --git a/drivers/staging/nmf-cm/cm_debug.c b/drivers/staging/nmf-cm/cm_debug.c index b894c6b8e4a..ffb067c65d9 100644 --- a/drivers/staging/nmf-cm/cm_debug.c +++ b/drivers/staging/nmf-cm/cm_debug.c @@ -306,9 +306,10 @@ static ssize_t domain_read(struct file *file, char __user *userbuf, "address Size Free Used\n" "---------------------------------------" "-----------------------------------\n"); - if (domain->domain.esramCode.size) { - cm_DSP_GetDspBaseAddress(ARM_CORE_ID, - ESRAM_CODE, &addr); + if (domain->domain.esramCode.size && + cm_DSP_GetDspBaseAddress(ARM_CORE_ID, + ESRAM_CODE, + &addr) == CM_OK) { cm_DSP_GetInternalMemoriesInfo(id, ESRAM_CODE, &dOffset, &dSize); @@ -330,9 +331,10 @@ static ssize_t domain_read(struct file *file, char __user *userbuf, status.global.accumulate_free_memory, status.global.accumulate_used_memory); } - if (domain->domain.esramData.size) { - cm_DSP_GetDspBaseAddress(ARM_CORE_ID, - ESRAM_EXT24, &addr); + if (domain->domain.esramData.size && + cm_DSP_GetDspBaseAddress(ARM_CORE_ID, + ESRAM_EXT24, + &addr) == CM_OK) { cm_DSP_GetInternalMemoriesInfo(id, ESRAM_EXT24, &dOffset, &dSize); @@ -354,9 +356,10 @@ static ssize_t domain_read(struct file *file, char __user *userbuf, status.global.accumulate_free_memory, status.global.accumulate_used_memory); } - if (domain->domain.sdramCode.size) { - cm_DSP_GetDspBaseAddress(ARM_CORE_ID, - SDRAM_CODE, &addr); + if (domain->domain.sdramCode.size && + cm_DSP_GetDspBaseAddress(ARM_CORE_ID, + SDRAM_CODE, + &addr) == CM_OK) { cm_DSP_GetInternalMemoriesInfo(id, SDRAM_CODE, &dOffset, &dSize); @@ -378,9 +381,10 @@ static ssize_t domain_read(struct file *file, char __user *userbuf, status.global.accumulate_free_memory, status.global.accumulate_used_memory); } - if (domain->domain.sdramData.size) { - cm_DSP_GetDspBaseAddress(ARM_CORE_ID, - SDRAM_EXT24, &addr); + if (domain->domain.sdramData.size && + cm_DSP_GetDspBaseAddress(ARM_CORE_ID, + SDRAM_EXT24, + &addr) == CM_OK) { cm_DSP_GetInternalMemoriesInfo(id, SDRAM_EXT24, &dOffset, &dSize); -- cgit v1.2.3 From 2cb8bf74ea2ba80e42c575b121c4c5c906e83903 Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Mon, 30 Jan 2012 13:01:32 +0100 Subject: nmf-cm: Declare bool module param in bool type Signed-off-by: Philippe Langlais --- drivers/staging/nmf-cm/configuration.h | 2 +- drivers/staging/nmf-cm/osal-kernel.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/staging/nmf-cm/configuration.h b/drivers/staging/nmf-cm/configuration.h index f4146dc6117..39416cde686 100644 --- a/drivers/staging/nmf-cm/configuration.h +++ b/drivers/staging/nmf-cm/configuration.h @@ -60,7 +60,7 @@ int init_config(void); module_param(cfgMpcYBanks_##mpc, uint, S_IRUGO); \ MODULE_PARM_DESC(cfgMpcYBanks_##mpc, "Nb of Y-Ram banks used on " #mpc); \ \ - static int cfgSchedulerTypeHybrid_##mpc = 1; \ + static bool cfgSchedulerTypeHybrid_##mpc = 1; \ module_param(cfgSchedulerTypeHybrid_##mpc, bool, S_IRUGO); \ MODULE_PARM_DESC(cfgSchedulerTypeHybrid_##mpc, "Scheduler used on " #mpc " (Hybrid or Synchronous)"); \ \ diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 6e3221130c5..0dc8328dfc0 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -836,7 +836,7 @@ static int dspload_monitor(void *idx) return 0; } -static int enable_auto_pm = 1; +static bool enable_auto_pm = 1; module_param(enable_auto_pm, bool, S_IWUSR|S_IRUGO); /** \ingroup OSAL_IMPLEMENTATION -- cgit v1.2.3 From 8b5892ba062aa859fb8fedbcf3d49b421f3bec36 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Wed, 11 Jan 2012 14:30:50 +0100 Subject: U8500 CM: fix issue when task doing DSP dump dies If the process doing the DSP dump abruptly dies, the dump is never acknoledged to the driver and all NMF activities remain blocked. Acknowledge the dump by resetting the dump_ongoing flag, if the process doing the dump closes the NMF driver, to unblock all NMF activities. ST-Ericsson ID: 409984 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: N/A Signed-off-by: Pierre Peiffer Change-Id: I3ee4f016e3bc824685f79016c51409903dc21a43 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/45134 Reviewed-by: Pierre PEIFFER Tested-by: Pierre PEIFFER Reviewed-by: QABUILD --- drivers/staging/nmf-cm/cm_service.c | 2 +- drivers/staging/nmf-cm/cmld.c | 10 +++++++--- drivers/staging/nmf-cm/cmld.h | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/staging/nmf-cm/cm_service.c b/drivers/staging/nmf-cm/cm_service.c index a2a6ffa5b57..7335cccbd6a 100644 --- a/drivers/staging/nmf-cm/cm_service.c +++ b/drivers/staging/nmf-cm/cm_service.c @@ -65,7 +65,7 @@ void dispatch_service_msg(struct osal_msg *msg) new_msg->d.srv.srvData.panic.panicSource |= DEBUGFS_DUMP_FLAG; dump_flag_to_set = false; - cmld_dump_ongoing = true; + cmld_dump_ongoing = channelPriv->proc->pid; } #endif spin_lock_bh(&channelPriv->bh_lock); diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index 60c20cadaee..d3a2f28ce4b 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -52,8 +52,8 @@ static DEFINE_MUTEX(channel_lock); /* lock used to protect previous list */ #ifdef CONFIG_DEBUG_FS /* Debugfs support */ bool cmld_user_has_debugfs = false; -bool cmld_dump_ongoing = false; -module_param(cmld_dump_ongoing, bool, S_IWUSR|S_IRUGO); +pid_t cmld_dump_ongoing = 0; +module_param(cmld_dump_ongoing, uint, S_IWUSR|S_IRUGO); static DECLARE_WAIT_QUEUE_HEAD(dump_waitq); #endif @@ -227,6 +227,10 @@ static void freeProcessPriv(struct kref *ref) #ifdef CONFIG_DEBUG_FS debugfs_remove_recursive(entry->dir); + if (cmld_dump_ongoing == entry->pid) { + cmld_dump_ongoing = 0; + wake_up(&dump_waitq); + } #endif /* Free the per-process descriptor */ @@ -387,7 +391,7 @@ static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned lon struct cm_process_priv* procPriv = file->private_data; #ifdef CONFIG_DEBUG_FS if (cmd == CM_PRIV_DEBUGFS_DUMP_DONE) { - cmld_dump_ongoing = false; + cmld_dump_ongoing = 0; wake_up(&dump_waitq); return 0; } else if (wait_event_interruptible(dump_waitq, (!cmld_dump_ongoing))) diff --git a/drivers/staging/nmf-cm/cmld.h b/drivers/staging/nmf-cm/cmld.h index 17e6c55ff61..78876bb01e6 100644 --- a/drivers/staging/nmf-cm/cmld.h +++ b/drivers/staging/nmf-cm/cmld.h @@ -76,7 +76,7 @@ extern struct list_head channel_list; /**< List of all allocated channel structu extern struct list_head process_list; /**< List of all allocated process private structure */ #ifdef CONFIG_DEBUG_FS extern bool cmld_user_has_debugfs; /**< Whether user side has proper support of debugfs to take a dump */ -extern bool cmld_dump_ongoing; /**< Whether a dump is on-going */ +extern pid_t cmld_dump_ongoing; /**< If a dump is on-going, store pid of process doing the dump */ #endif /* Structure used to embed DSP traces */ -- cgit v1.2.3 From c5eb43c9e7593ecdad53981b5db3c3cfe3e4f2bb Mon Sep 17 00:00:00 2001 From: Vincent Abriou Date: Wed, 11 Jan 2012 10:18:22 +0100 Subject: Update mmio interfaces Align mmio interfaces with l9540 project. It remains compatible with current mmio implementation. ST-Ericsson ID: 357839 Depends-On: I707d8227513cb1115d17afba60ae1559bb9b199b ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Change-Id: Iac0bfbe9be4c80a26033b9c082b6fbe63b2c71ff Signed-off-by: Vincent Abriou Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/45010 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: Rajat VERMA Reviewed-by: Linus WALLEIJ --- drivers/staging/mmio/mmio.h | 55 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/drivers/staging/mmio/mmio.h b/drivers/staging/mmio/mmio.h index 1c6f68e3556..1b201021982 100644 --- a/drivers/staging/mmio/mmio.h +++ b/drivers/staging/mmio/mmio.h @@ -3,6 +3,7 @@ * * Author: Joakim Axelsson for ST-Ericsson * Author: Rajat Verma for ST-Ericsson + * Author: Vincent Abriou for ST-Ericsson. * License Terms: GNU General Public License v2 */ @@ -11,7 +12,10 @@ #include -#define MMIO_NAME "mmio_camera" +#define MMIO_NAME "mmio_camera" /* kept for backward compatibility */ +#define MMIO_RAW_NAME "mmio_camera_raw" +#define MMIO_YUV_NAME "mmio_camera_yuv" + #define SRA_SUPPORT 1 #ifdef SRA_SUPPORT @@ -25,14 +29,44 @@ enum camera_slot_t { SECONDARY_CAMERA, CAMERA_SLOT_END }; + +enum camera_type_t { + RAW_CAMERA = 0, + YUV_CAMERA, + CAMERA_TYPE_END +}; + struct mmio_gpio { - int gpio; /* Set to zero if not in use */ - int active_high;/* Set if pin is active high */ - int udelay; /* Time to wait when activating the pin, in usec */ + /* Name of the gpio */ + const char *name; + /* Gpio number */ + int gpio; + /* pin configuration when feature is enabled */ + unsigned long cfg_ena; + /* pin configuration when feature is disabled */ + unsigned long cfg_disa; + /* Set if pin is active high */ + /* kept for backward compatibility */ + int active_high; + /* Time to wait when activating the pin, in usec */ + /* kept for backward compatibility */ + int udelay; +}; + +struct mmio_clk { + const char *name; /* Name of the clock */ + struct clk *clk_ptr; /* Pointer on the allocated clock */ +}; + +struct mmio_regulator { + const char *name; /* Name of the clock */ + struct regulator *reg_ptr; /* Pointer on the allocated regulator */ }; + enum mmio_select_i2c_t { - MMIO_ACTIVATE_IPI2C2 = 0, - MMIO_ACTIVATE_I2C_HOST, + MMIO_ACTIVATE_IPI2C2 = 0, /* kept for backward compatibility */ + MMIO_ACTIVATE_I2C_HOST, /* kept for backward compatibility */ + MMIO_ACTIVATE_I2C, MMIO_DEACTIVATE_I2C }; @@ -55,12 +89,14 @@ struct mmio_platform_data { void (*platform_exit)(struct mmio_platform_data *pdata); int (*power_enable)(struct mmio_platform_data *pdata); void (*power_disable)(struct mmio_platform_data *pdata); + /* kept for backward compatibility */ int (*config_xshutdown_pins)(struct mmio_platform_data *pdata, enum mmio_select_xshutdown_t select, int is_active_high); int (*config_i2c_pins)(struct mmio_platform_data *pdata, enum mmio_select_i2c_t select); int (*clock_enable)(struct mmio_platform_data *pdata); void (*clock_disable)(struct mmio_platform_data *pdata); + /* kept for backward compatibility */ void (*set_xshutdown)(struct mmio_platform_data *pdata); }; @@ -133,9 +169,10 @@ struct mmio_input_output_t { #define MMIO_INVALID (~0) /*Xshutdown from host takes two arguments*/ +/* kept for backward compatibility */ #define MMIO_XSHUTDOWN_ENABLE (0x1) +/* kept for backward compatibility */ #define MMIO_XSHUTDOWN_ACTIVE_HIGH (0x2) - #define MMIO_MAGIC_NUMBER 0x15 #define MMIO_CAM_INITBOARD _IOW(MMIO_MAGIC_NUMBER, 1,\ @@ -144,14 +181,18 @@ struct mmio_input_output_t*) struct mmio_input_output_t*) #define MMIO_CAM_SET_EXT_CLK _IOW(MMIO_MAGIC_NUMBER, 3,\ struct mmio_input_output_t*) +/* kept for backward compatibility */ #define MMIO_CAM_SET_PRI_HWIF _IO(MMIO_MAGIC_NUMBER, 4) +/* kept for backward compatibility */ #define MMIO_CAM_SET_SEC_HWIF _IO(MMIO_MAGIC_NUMBER, 5) #define MMIO_CAM_INITMMDSPTIMER _IO(MMIO_MAGIC_NUMBER, 6) #define MMIO_CAM_LOAD_XP70_FW _IOW(MMIO_MAGIC_NUMBER, 7,\ struct mmio_input_output_t*) #define MMIO_CAM_MAP_STATS_AREA _IOWR(MMIO_MAGIC_NUMBER, 8,\ struct mmio_input_output_t*) +/* kept for backward compatibility */ #define MMIO_ACTIVATE_I2C2 _IOW(MMIO_MAGIC_NUMBER, 9, int*) +/* kept for backward compatibility */ #define MMIO_ENABLE_XSHUTDOWN_FROM_HOST _IOW(MMIO_MAGIC_NUMBER, 10, int*) #define MMIO_CAM_ISP_WRITE _IOW(MMIO_MAGIC_NUMBER, 11,\ struct mmio_input_output_t*) -- cgit v1.2.3 From bfb0df3aba020bd53ab1fcd8aabc890d94002600 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Tue, 17 Jan 2012 18:17:37 +0100 Subject: Ux500 CM: wake-up DSP before doing any bindings When we try to set up some bindings to a component instantiated on a DSP which is in retention, we need to wake it up first. ST-Ericsson ID: 406310, 406504 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: N/A Change-Id: I07dc1576cbac73bbc3b0cc057808f4e67e7ba378 Signed-off-by: Pierre Peiffer Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/45727 Reviewed-by: QABUILD --- .../staging/nmf-cm/cm/engine/communication/src/communication.c | 10 ++++++++-- .../cm/engine/executive_engine_mgt/src/executive_engine_mgt.c | 9 +++++++-- drivers/staging/nmf-cm/inc/nmf-def.h | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c b/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c index ead1e090d7c..811e9b8c1e6 100644 --- a/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c +++ b/drivers/staging/nmf-cm/cm/engine/communication/src/communication.c @@ -170,11 +170,17 @@ PUBLIC void cm_COM_InitMpc(t_nmf_core_id coreId) if (localCoreId == coreId) continue; /* no coms fifo with itself ;) */ if(cm_DSP_GetState(localCoreId)->state != MPC_STATE_BOOTED) continue;/* no coms fifo initialisation with not booted MPC */ + fromNeighborsComsFifoIdSharedVar[coreId][localCoreId] = mpc2mpcComsFifoId[localCoreId][coreId]->dspAdress; toNeighborsComsFifoIdSharedVar[coreId][localCoreId] = mpc2mpcComsFifoId[coreId][localCoreId]->dspAdress; - fromNeighborsComsFifoIdSharedVar[localCoreId][coreId] = mpc2mpcComsFifoId[coreId][localCoreId]->dspAdress; - fromNeighborsComsFifoIdSharedVar[coreId][localCoreId] = mpc2mpcComsFifoId[localCoreId][coreId]->dspAdress; + LOG_INTERNAL(1, "ARM: Force Try to wake up on core id : %d\n", localCoreId, 0, 0, 0, 0, 0); + cm_EEM_ForceWakeup(localCoreId); + + fromNeighborsComsFifoIdSharedVar[localCoreId][coreId] = mpc2mpcComsFifoId[coreId][localCoreId]->dspAdress; toNeighborsComsFifoIdSharedVar[localCoreId][coreId] = mpc2mpcComsFifoId[localCoreId][coreId]->dspAdress; + + LOG_INTERNAL(1, "ARM: Force Allow sleep on core id : %d\n", localCoreId, 0, 0, 0, 0, 0); + cm_EEM_AllowSleep(localCoreId); } } diff --git a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c index 4df3d7ee0f5..a00ca4c4683 100644 --- a/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c +++ b/drivers/staging/nmf-cm/cm/engine/executive_engine_mgt/src/executive_engine_mgt.c @@ -339,7 +339,7 @@ t_cm_error cm_EEM_ForceWakeup(t_nmf_core_id coreId) { t_cm_error error; - LOG_INTERNAL(2, "ARM: Try to wake up\n", 0, 0, 0, 0, 0, 0); + LOG_INTERNAL(1, "ARM: Try to wake up on core id : %d\n", coreId, 0, 0, 0, 0, 0); if (cm_DSP_GetState(coreId)->state != MPC_STATE_BOOTED) { @@ -359,6 +359,9 @@ t_cm_error cm_EEM_ForceWakeup(t_nmf_core_id coreId) return error; } } + else + LOG_INTERNAL(1, "ARM: Not Try to wake up on core id : %d (nbOfForceWakeup = %d)\n", coreId, eeState[coreId].nbOfForceWakeup, 0, 0, 0, 0); + return CM_OK; } @@ -366,7 +369,7 @@ void cm_EEM_AllowSleep(t_nmf_core_id coreId) { if(--eeState[coreId].nbOfForceWakeup == 0) { - LOG_INTERNAL(2, "ARM: Allow sleep\n", 0, 0, 0, 0, 0, 0); + LOG_INTERNAL(1, "ARM: Allow sleep on core id : %d\n", coreId, 0, 0, 0, 0, 0); if (cm_DSP_GetState(coreId)->state != MPC_STATE_BOOTED) { @@ -376,6 +379,8 @@ void cm_EEM_AllowSleep(t_nmf_core_id coreId) ERROR("CM_MPC_NOT_RESPONDING: DSP %s can't be allow sleep'ed\n", cm_getDspName(coreId), 0, 0, 0, 0, 0); } } + else + LOG_INTERNAL(1, "ARM: Not Allow sleep on core id : %d (nbOfForceWakeup = %d)\n", coreId, eeState[coreId].nbOfForceWakeup, 0, 0, 0, 0); } /* internal api */ diff --git a/drivers/staging/nmf-cm/inc/nmf-def.h b/drivers/staging/nmf-cm/inc/nmf-def.h index 7cdea18996b..439adf8ef56 100644 --- a/drivers/staging/nmf-cm/inc/nmf-def.h +++ b/drivers/staging/nmf-cm/inc/nmf-def.h @@ -21,7 +21,7 @@ * * \ingroup NMF_VERSION */ -#define NMF_VERSION ((2 << 16) | (10 << 8) | (122)) +#define NMF_VERSION ((2 << 16) | (10 << 8) | (123)) /*! * \brief Get NMF major version corresponding to NMF version number -- cgit v1.2.3 From 2ec47b2b13e3ad33eb5c4f744e6b1ef1d4c04fb7 Mon Sep 17 00:00:00 2001 From: Pierre Peiffer Date: Thu, 26 Jan 2012 17:00:21 +0100 Subject: Ux500 CM: avoid ugly warning if kmalloc() fails In some cases, if the CM driver fails to allocate memory through kmalloc(), it falls back into vmalloc() which has better chance to succeed for big allocations. When this happens, kmalloc() reports its failure with an ugly warning on the console. Just avoid this warning in this case. ST-Ericsson ID: 413249 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: N/A Change-Id: I6c8a51eb430891727854b1800cf3a649dcb4b6e9 Signed-off-by: Pierre Peiffer Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/46815 Reviewed-by: QATOOLS --- drivers/staging/nmf-cm/osal-kernel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/nmf-cm/osal-kernel.c b/drivers/staging/nmf-cm/osal-kernel.c index 0dc8328dfc0..c1d8640b11b 100644 --- a/drivers/staging/nmf-cm/osal-kernel.c +++ b/drivers/staging/nmf-cm/osal-kernel.c @@ -527,7 +527,7 @@ void* OSAL_Alloc(t_cm_size size) if (size == 0) return NULL; - entry = kmalloc(size + sizeof(*entry), GFP_KERNEL); + entry = kmalloc(size + sizeof(*entry), GFP_KERNEL | __GFP_NOWARN); if (entry == NULL) { entry = vmalloc(size + sizeof(*entry)); @@ -553,7 +553,7 @@ void* OSAL_Alloc(t_cm_size size) if (size == 0) return NULL; - mem = kmalloc(size, GFP_KERNEL); + mem = kmalloc(size, GFP_KERNEL | __GFP_NOWARN); if (mem == NULL) { mem = vmalloc(size); if (mem == NULL) @@ -576,7 +576,7 @@ void* OSAL_Alloc_Zero(t_cm_size size) if (size == 0) return NULL; - entry = kzalloc(size + sizeof(*entry), GFP_KERNEL); + entry = kzalloc(size + sizeof(*entry), GFP_KERNEL | __GFP_NOWARN); if (entry == NULL) { entry = vmalloc(size + sizeof(*entry)); if (entry == NULL) { @@ -603,7 +603,7 @@ void* OSAL_Alloc_Zero(t_cm_size size) if (size == 0) return NULL; - mem = kzalloc(size, GFP_KERNEL); + mem = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); if (mem == NULL) { mem = vmalloc(size); if (mem == NULL) -- cgit v1.2.3 From 2cdec76f5ae4db714743109ef3c8749bd12d7670 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Tue, 10 Jan 2012 09:36:14 +0100 Subject: mmio: mach-ux500: Add support for 9540 ST-Ericsson ID: 398896 Signed-off-by: Yann Gautier --- arch/arm/mach-ux500/board-mop500-mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-mop500-mmio.c b/arch/arm/mach-ux500/board-mop500-mmio.c index 355f835caa1..a8939419b7b 100644 --- a/arch/arm/mach-ux500/board-mop500-mmio.c +++ b/arch/arm/mach-ux500/board-mop500-mmio.c @@ -189,7 +189,7 @@ static int mmio_pin_cfg_init(struct mmio_platform_data *pdata) extra->xshutdown_pins[SECONDARY_CAMERA].udelay = 500; /* Update GPIO mappings according to board */ - if (machine_is_hrefv60()) { + if (machine_is_hrefv60() || machine_is_u9540()) { extra->xenon_charge = HREFV60_MMIO_XENON_CHARGE; xshutdown_host[SECONDARY_CAMERA] = GPIO140_GPIO; xshutdown_fw[SECONDARY_CAMERA] = GPIO140_IP_GPIO7; -- cgit v1.2.3 From cd01a620f6629ff56aa0067d62d32ab431592ca7 Mon Sep 17 00:00:00 2001 From: Bengt Jonsson Date: Thu, 2 Feb 2012 11:36:49 +0100 Subject: mmio: ux500: Add U8520 machine ST-Ericsson ID: 371953 Signed-off-by: Bengt Jonsson --- arch/arm/mach-ux500/board-mop500-mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-ux500/board-mop500-mmio.c b/arch/arm/mach-ux500/board-mop500-mmio.c index a8939419b7b..45952d1823f 100644 --- a/arch/arm/mach-ux500/board-mop500-mmio.c +++ b/arch/arm/mach-ux500/board-mop500-mmio.c @@ -189,7 +189,7 @@ static int mmio_pin_cfg_init(struct mmio_platform_data *pdata) extra->xshutdown_pins[SECONDARY_CAMERA].udelay = 500; /* Update GPIO mappings according to board */ - if (machine_is_hrefv60() || machine_is_u9540()) { + if (machine_is_hrefv60() || machine_is_u8520() || machine_is_u9540()) { extra->xenon_charge = HREFV60_MMIO_XENON_CHARGE; xshutdown_host[SECONDARY_CAMERA] = GPIO140_GPIO; xshutdown_fw[SECONDARY_CAMERA] = GPIO140_IP_GPIO7; -- cgit v1.2.3 From eb4ef6da1a08940f1044ea021e037b083c75e0d6 Mon Sep 17 00:00:00 2001 From: himansh Date: Wed, 28 Dec 2011 19:50:41 +0530 Subject: Ux500 CM: Exported cm_writeAttribute to user side ST-Ericsson ID: 373536 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Change-Id: Ifc873304b8f9ec73fc3c34cec32e53e8c84bd89e Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/43927 Reviewed-by: Pierre PEIFFER Reviewed-by: Ashish Kumar TANWER Tested-by: Ashish Kumar TANWER --- .../nmf-cm/cm/engine/api/component_engine.h | 15 ++++++++++ .../cm/engine/component/src/component_wrapper.c | 33 ++++++++++++++++++++++ .../nmf-cm/cm/engine/component/src/introspection.c | 2 +- drivers/staging/nmf-cm/cm_syscall.c | 27 ++++++++++++++++++ drivers/staging/nmf-cm/cmioctl.h | 12 ++++++++ drivers/staging/nmf-cm/cmld.c | 5 ++++ drivers/staging/nmf-cm/cmld.h | 1 + 7 files changed, 94 insertions(+), 1 deletion(-) diff --git a/drivers/staging/nmf-cm/cm/engine/api/component_engine.h b/drivers/staging/nmf-cm/cm/engine/api/component_engine.h index cbd61769597..a1e9defda7e 100644 --- a/drivers/staging/nmf-cm/cm/engine/api/component_engine.h +++ b/drivers/staging/nmf-cm/cm/engine/api/component_engine.h @@ -222,6 +222,21 @@ PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_ReadComponentAttribute( const char* attrName, t_uint24 *value); +/*! + * \brief Write a value on an attribute exported by a component instance. + * + * \param[in] component + * \param[in] attrName Null terminated string (Max size=\ref MAX_ATTRIBUTE_NAME_LENGTH). + * \param[out] value + * + * \ingroup CM_ENGINE_API + */ +PUBLIC IMPORT_SHARED t_cm_error CM_ENGINE_WriteComponentAttribute( + const t_cm_instance_handle component, + const char* attrName, + t_uint24 value); + + /*! * \brief Get the older component. * diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c b/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c index 88e6b4749ec..9a5c683ed1f 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c @@ -906,6 +906,39 @@ out: return error; } +/* + * Get a reference on a given attribute of a given component + */ + +PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_WriteComponentAttribute( + const t_cm_instance_handle instance, + const char* attrName, + t_uint24 attrValue) +{ + t_cm_error error; + t_component_instance* component; + + OSAL_LOCK_API(); + + component = cm_lookupComponent(instance); + if (NULL == component) + error = CM_INVALID_COMPONENT_HANDLE; + else + { + if ((error = cm_EEM_ForceWakeup(component->Template->dspId)) != CM_OK) + goto out; + + //t_uint24 -> t_uint32 possible since we know it same size + error = cm_writeAttribute(component, attrName, attrValue); + + cm_EEM_AllowSleep(component->Template->dspId); + } + +out: + OSAL_UNLOCK_API(); + return error; +} + /*=============================================================================== * Introspection API *===============================================================================*/ diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c b/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c index 4aaf8dff889..7e2f7cd65d0 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c @@ -142,7 +142,7 @@ t_cm_error cm_writeAttribute( attribute->memory.offset * attribute->memory.memory->memEntSize; if(attribute->memory.memory->memEntSize != 2) - *((t_uint32 *)hostAddr) = value & ~MASK_BYTE3; + *((t_uint32 *)hostAddr) = value & ~MASK_BYTE3; else *((t_uint16 *)hostAddr) = value; diff --git a/drivers/staging/nmf-cm/cm_syscall.c b/drivers/staging/nmf-cm/cm_syscall.c index ca8d664abb4..304b86ffee7 100644 --- a/drivers/staging/nmf-cm/cm_syscall.c +++ b/drivers/staging/nmf-cm/cm_syscall.c @@ -1115,6 +1115,33 @@ out: return 0; } + +inline int cmld_WriteComponentAttribute(struct cm_process_priv *procPriv, + CM_WriteComponentAttribute_t __user *param) +{ + CM_WriteComponentAttribute_t data; + char attrName[MAX_ATTRIBUTE_NAME_LENGTH]; + + /* Copy user input data in kernel space */ + if (copy_from_user(&data.in, ¶m->in, sizeof(data.in))) + return -EFAULT; + + if ((data.out.error = copy_string_from_user(attrName, + data.in.attrName, + sizeof(attrName)))) + goto out; + + data.out.error = CM_ENGINE_WriteComponentAttribute(data.in.component, + attrName, + data.in.value); +out: + /* Copy results back to userspace */ + if (copy_to_user(¶m->out, &data.out, sizeof(data.out))) + return -EFAULT; + return 0; +} + + inline int cmld_GetExecutiveEngineHandle(struct cm_process_priv *procPriv, CM_GetExecutiveEngineHandle_t __user *param) { diff --git a/drivers/staging/nmf-cm/cmioctl.h b/drivers/staging/nmf-cm/cmioctl.h index 5f7d5b6a349..eafeb8acff1 100644 --- a/drivers/staging/nmf-cm/cmioctl.h +++ b/drivers/staging/nmf-cm/cmioctl.h @@ -458,6 +458,17 @@ typedef struct { } CM_ReadComponentAttribute_t; typedef struct { + struct { + t_cm_instance_handle component; + const char *attrName; + t_uint32 value; /** < In parameter */ + } in; + struct { + t_cm_error error; /** < Out parameter */ + } out; +} CM_WriteComponentAttribute_t; + +typedef struct{ struct { t_cm_domain_id domainId; } in; @@ -580,6 +591,7 @@ typedef struct{ #define CM_GETCOMPONENTPROPERTYNAME _IOWR('c', 32, CM_GetComponentPropertyName_t) #define CM_GETCOMPONENTPROPERTYVALUE _IOWR('c', 33, CM_GetComponentPropertyValue_t) #define CM_READCOMPONENTATTRIBUTE _IOWR('c', 34, CM_ReadComponentAttribute_t) +#define CM_WRITECOMPONENTATTRIBUTE _IOWR('c', 44, CM_WriteComponentAttribute_t) #define CM_GETEXECUTIVEENGINEHANDLE _IOWR('c', 35, CM_GetExecutiveEngineHandle_t) #define CM_SETMODE _IOWR('c', 36, CM_SetMode_t) #define CM_GETREQUIREDCOMPONENTFILES _IOWR('c', 37, CM_GetRequiredComponentFiles_t) diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index d3a2f28ce4b..ac16ef6f4ee 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -602,6 +602,11 @@ static long cmld_control_ioctl(struct file *file, unsigned int cmd, unsigned lon return 0; case CM_PRIV_DEBUGFS_WAIT_DUMP: return 0; + + case CM_WRITECOMPONENTATTRIBUTE: + return cmld_WriteComponentAttribute(procPriv, + (CM_WriteComponentAttribute_t *)arg); + default: pr_err("CM(%s): unsupported command %i\n", __func__, cmd); return -EINVAL; diff --git a/drivers/staging/nmf-cm/cmld.h b/drivers/staging/nmf-cm/cmld.h index 78876bb01e6..57dc3a4e8f7 100644 --- a/drivers/staging/nmf-cm/cmld.h +++ b/drivers/staging/nmf-cm/cmld.h @@ -175,6 +175,7 @@ int cmld_GetComponentPropertyNumber(struct cm_process_priv *, int cmld_GetComponentPropertyName(struct cm_process_priv *, CM_GetComponentPropertyName_t __user *); int cmld_GetComponentPropertyValue(struct cm_process_priv *, CM_GetComponentPropertyValue_t __user *); int cmld_ReadComponentAttribute(struct cm_process_priv *, CM_ReadComponentAttribute_t __user *); +int cmld_WriteComponentAttribute(struct cm_process_priv *, CM_WriteComponentAttribute_t __user *); int cmld_GetExecutiveEngineHandle(struct cm_process_priv *, CM_GetExecutiveEngineHandle_t __user *); int cmld_SetMode(CM_SetMode_t __user *); int cmld_GetRequiredComponentFiles(struct cm_process_priv *cmPriv, -- cgit v1.2.3 From cf5df5ea669adb16e6d4873755e5fedcdadc2d7f Mon Sep 17 00:00:00 2001 From: Rajat Verma Date: Tue, 14 Feb 2012 16:05:27 +0530 Subject: staging: mmio: use static buffer for i/o writes For doing I/O write, use static 1 Kb buffer instead of requesting memory through kmalloc every time. ST-Ericsson ID: 412155 ST-Ericsson FOSS-OUT ID: Trivial ST-Ericsson Linux next: NA Change-Id: I68710cd9d74c4a76753a7524431046e09a7aa1d0 Signed-off-by: Rajat Verma Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/48844 Reviewed-by: QATOOLS Reviewed-by: QABUILD Reviewed-by: QATEST Reviewed-by: Srinidhi KASAGAR --- drivers/staging/mmio/st_mmio.c | 151 +++++++++++++++++++++++++---------------- 1 file changed, 91 insertions(+), 60 deletions(-) diff --git a/drivers/staging/mmio/st_mmio.c b/drivers/staging/mmio/st_mmio.c index a006c55c544..27371bb3564 100644 --- a/drivers/staging/mmio/st_mmio.c +++ b/drivers/staging/mmio/st_mmio.c @@ -114,6 +114,13 @@ struct mmio_info { */ static struct mmio_info *info; +/* + * static 1K buffer to do I/O write instead of kmalloc, + * no locking, caller can not have parallel use of + * MMIO_CAM_LOAD_XP70_FW and MMIO_CAM_ISP_WRITE ioctl's + */ +static u16 copybuff[512]; + /* * This function converts a given logical memory region size * to appropriate ISP_MCU_SYS_SIZEx register value. @@ -235,86 +242,88 @@ static u32 t1_to_arm(u32 t1_addr, void __iomem *smia_base_address, return SIA_ISP_MEM + (t1_addr & FW_TO_HOST_ADDR_MASK); } -static int copy_user_buffer(void __iomem **dest_buf, - void __iomem *src_buf, u32 size) +static int write_user_buffer(struct mmio_info *info, u32 ioaddr, + void __iomem *src_buf, u32 size) { + u32 i, count, offset = 0; + u32 itval = 0; + u16 mem_page = 0; int err = 0; - if (!src_buf) + if (!src_buf || !ioaddr) { + dev_err(info->dev, "invalid parameters: %p, 0x%x", + src_buf, ioaddr); + return -EINVAL; + } - *dest_buf = kmalloc(size, GFP_KERNEL); + for (offset = 0; offset < size; ) { - if (!*dest_buf) { - err = -ENOMEM; - goto nomem; - } + if ((size - offset) > sizeof(copybuff)) + count = sizeof(copybuff); + else + count = (size - offset); + + if (copy_from_user(copybuff, src_buf + offset, count)) { + + dev_err(info->dev, "failed to copy user buffer" + " %p at offset=%d, count=%d\n", + src_buf, offset, count); - if (copy_from_user(*dest_buf, src_buf, size)) { - err = -EFAULT; - goto cp_failed; + err = -EFAULT; + goto cp_failed; + } + + for (i = 0; i < count; ) { + itval = t1_to_arm(ioaddr + offset, + info->siabase, &mem_page); + itval = ((u32) info->siabase) + itval; + + writew(copybuff[i/2], itval); + offset += 2; + i = i + 2; + } } - return err; cp_failed: - kfree(*dest_buf); -nomem: return err; } + static int mmio_load_xp70_fw(struct mmio_info *info, struct xp70_fw_t *xp70_fw) { - u32 i = 0; - u32 offset = 0; u32 itval = 0; - u16 mem_page = 0; - void __iomem *addr_split = NULL; - void __iomem *addr_data = NULL; int err = 0; if (xp70_fw->size_split != 0) { - err = copy_user_buffer(&addr_split, xp70_fw->addr_split, - xp70_fw->size_split); - - if (err) + /* if buff size is not as expected */ + if (xp70_fw->size_split != L2_PSRAM_MEM_SIZE) { + dev_err(info->dev, "xp70_fw_t.size_split must be " + "%d bytes!\n", L2_PSRAM_MEM_SIZE); + err = -EINVAL; goto err_exit; + } writel(0x0, info->siabase + SIA_ISP_REG_ADDR); /* Put the low 64k IRP firmware in ISP MCU L2 PSRAM */ - for (i = PICTOR_IN_XP70_L2_MEM_BASE_ADDR; - i < (PICTOR_IN_XP70_L2_MEM_BASE_ADDR + - L2_PSRAM_MEM_SIZE); i = i + 2) { - itval = t1_to_arm(i, info->siabase, &mem_page); - itval = ((u32) info->siabase) + itval; - /* Copy fw in L2 */ - writew((*((u16 *) addr_split + offset++)), itval); - } - - kfree(addr_split); + err = write_user_buffer(info, PICTOR_IN_XP70_L2_MEM_BASE_ADDR, + xp70_fw->addr_split, + L2_PSRAM_MEM_SIZE); + if (err) + goto err_exit; } if (xp70_fw->size_data != 0) { - mem_page = 0; - offset = 0; - err = copy_user_buffer(&addr_data, xp70_fw->addr_data, - xp70_fw->size_data); - - if (err) - goto err_exit; writel(0x0, info->siabase + SIA_ISP_REG_ADDR); - for (i = PICTOR_IN_XP70_TCDM_MEM_BASE_ADDR; - i < (PICTOR_IN_XP70_TCDM_MEM_BASE_ADDR + - (xp70_fw->size_data)); i = i + 2) { - itval = t1_to_arm(i, info->siabase, &mem_page); - itval = ((u32) info->siabase) + itval; - /* Copy fw data in TCDM */ - writew((*((u16 *) addr_data + offset++)), itval); - } + err = write_user_buffer(info, PICTOR_IN_XP70_TCDM_MEM_BASE_ADDR, + xp70_fw->addr_data, + xp70_fw->size_data); - kfree(addr_data); + if (err) + goto err_exit; } if (xp70_fw->size_esram_ext != 0) { @@ -464,29 +473,51 @@ static int mmio_isp_write(struct mmio_info *info, struct isp_write_t *isp_write_p) { int err = 0, i; - void __iomem *data = NULL; + u32 __iomem *data = NULL; void __iomem *addr = NULL; u16 mem_page = 0; + u32 size, count, offset; if (!isp_write_p->count) { dev_warn(info->dev, "no data to write to isp\n"); return -EINVAL; } - err = copy_user_buffer(&data, isp_write_p->data, - isp_write_p->count * ISP_WRITE_DATA_SIZE); + size = isp_write_p->count * ISP_WRITE_DATA_SIZE; + data = (u32 *) copybuff; - if (err) - goto out; + for (offset = 0; offset < size; ) { - for (i = 0; i < isp_write_p->count; i++) { - addr = (void *)(info->siabase + t1_to_arm(isp_write_p->t1_dest - + ISP_WRITE_DATA_SIZE * i, - info->siabase, &mem_page)); - *((u32 *)addr) = *((u32 *)data + i); + /* 'offset' and 'size' and 'count' is in bytes */ + if ((size - offset) > sizeof(copybuff)) + count = sizeof(copybuff); + else + count = (size - offset); + + if (copy_from_user(data, ((u8 *)isp_write_p->data) + offset, + count)) { + dev_err(info->dev, "failed to copy user buffer" + " %p at offset=%d, count=%d\n", + isp_write_p->data, offset, count); + + err = -EFAULT; + goto out; + } + + /* index 'i' and 'offset' is in bytes */ + for (i = 0; i < count; ) { + addr = (void *)(info->siabase + t1_to_arm( + isp_write_p->t1_dest + + offset, + info->siabase, &mem_page)); + + *((u32 *)addr) = data[i/ISP_WRITE_DATA_SIZE]; + + offset += ISP_WRITE_DATA_SIZE; + i = i + ISP_WRITE_DATA_SIZE; + } } - kfree(data); out: return err; } -- cgit v1.2.3 From 1f3fe7215aec7e40ad760eacbcbf7bef64a69b0b Mon Sep 17 00:00:00 2001 From: himansh Date: Fri, 17 Feb 2012 16:59:24 +0530 Subject: Ux500 CM: Correct variable initialization ST-Ericsson ID: 412189 ST-Ericsson Linux next: NA ST-Ericsson FOSS-OUT ID: Trivial Change-Id: I10ba7bf50be94424b3a2e122862c1fda08df769d Signed-off-by: Himanshu Agrawal Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/49349 Reviewed-by: Ashish Kumar TANWER Tested-by: Ashish Kumar TANWER Reviewed-by: Pierre PEIFFER --- drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c | 1 + drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c b/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c index 9a5c683ed1f..d593950cd97 100644 --- a/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c +++ b/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c @@ -657,6 +657,7 @@ PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentFromCMCore( dspEventMemType = SDRAM_EXT24; break; default: + error = CM_INVALID_PARAMETER; goto out; } diff --git a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c index 274a1b6b59f..466d04508d1 100644 --- a/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c +++ b/drivers/staging/nmf-cm/cm/engine/elf/src/elfload.c @@ -181,7 +181,7 @@ t_cm_error cm_ELF_CheckFile( t_elfdescription **elfhandlePtr) { t_elfdescription *elfhandle; - t_tmp_elfdescription elftmp; + t_tmp_elfdescription elftmp = {0,}; t_cm_error error; t_uint32 version; t_uint32 compatibleVersion; -- cgit v1.2.3 From 66e68aa37bceeb4279857b48d17023530aed4dbb Mon Sep 17 00:00:00 2001 From: Philippe Langlais Date: Thu, 19 Apr 2012 21:13:43 +0200 Subject: nmf/cm: Include missing for 3.4 Signed-off-by: Philippe Langlais --- drivers/staging/nmf-cm/cmld.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/staging/nmf-cm/cmld.c b/drivers/staging/nmf-cm/cmld.c index ac16ef6f4ee..8d3cbc037be 100644 --- a/drivers/staging/nmf-cm/cmld.c +++ b/drivers/staging/nmf-cm/cmld.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include -- cgit v1.2.3