diff options
Diffstat (limited to 'drivers/dsp/syslink/procmgr/proc4430/proc4430.c')
-rw-r--r-- | drivers/dsp/syslink/procmgr/proc4430/proc4430.c | 1021 |
1 files changed, 1021 insertions, 0 deletions
diff --git a/drivers/dsp/syslink/procmgr/proc4430/proc4430.c b/drivers/dsp/syslink/procmgr/proc4430/proc4430.c new file mode 100644 index 000000000000..e752a7932c9e --- /dev/null +++ b/drivers/dsp/syslink/procmgr/proc4430/proc4430.c @@ -0,0 +1,1021 @@ +/* + * proc4430.c + * + * Syslink driver support functions for TI OMAP processors. + * + * Copyright (C) 2009-2010 Texas Instruments, Inc. + * + * This package 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. + * + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/vmalloc.h> +#include <linux/uaccess.h> +#include <linux/io.h> +#include <linux/delay.h> + +/* Module level headers */ +#include "../procdefs.h" +#include "../processor.h" +#include <procmgr.h> +#include "../procmgr_drvdefs.h" +#include "proc4430.h" +#include "dmm4430.h" +#include <syslink/multiproc.h> +#include <syslink/ducatienabler.h> +#include <syslink/platform_mem.h> +#include <syslink/atomic_linux.h> + +#define DUCATI_DMM_START_ADDR 0xa0000000 +#define DUCATI_DMM_POOL_SIZE 0x6000000 + +#define SYS_M3 2 +#define APP_M3 3 +#define CORE_PRM_BASE OMAP2_L4_IO_ADDRESS(0x4a306700) +#define CORE_CM2_DUCATI_CLKSTCTRL OMAP2_L4_IO_ADDRESS(0x4A008900) +#define CORE_CM2_DUCATI_CLKCTRL OMAP2_L4_IO_ADDRESS(0x4A008920) +#define RM_MPU_M3_RSTCTRL_OFFSET 0x210 +#define RM_MPU_M3_RSTST_OFFSET 0x214 +#define RM_MPU_M3_RST1 0x1 +#define RM_MPU_M3_RST2 0x2 +#define RM_MPU_M3_RST3 0x4 + +#define OMAP4430PROC_MODULEID (u16) 0xbbec + +/* Macro to make a correct module magic number with refCount */ +#define OMAP4430PROC_MAKE_MAGICSTAMP(x) ((OMAP4430PROC_MODULEID << 12u) | (x)) + +/*OMAP4430 Module state object */ +struct proc4430_module_object { + u32 config_size; + /* Size of configuration structure */ + struct proc4430_config cfg; + /* OMAP4430 configuration structure */ + struct proc4430_config def_cfg; + /* Default module configuration */ + struct proc4430_params def_inst_params; + /* Default parameters for the OMAP4430 instances */ + void *proc_handles[MULTIPROC_MAXPROCESSORS]; + /* Processor handle array. */ + struct mutex *gate_handle; + /* void * of gate to be used for local thread safety */ + atomic_t ref_count; +}; + +/* + OMAP4430 instance object. + */ +struct proc4430_object { + struct proc4430_params params; + /* Instance parameters (configuration values) */ +}; + + +/* ================================= + * Globals + * ================================= + */ +/* + OMAP4430 state object variable + */ + +static struct proc4430_module_object proc4430_state = { + .config_size = sizeof(struct proc4430_config), + .gate_handle = NULL, + .def_inst_params.num_mem_entries = 0u, + .def_inst_params.mem_entries = NULL, + .def_inst_params.reset_vector_mem_entry = 0 +}; + + +/* ================================= + * APIs directly called by applications + * ================================= + */ +/* + * Function to get the default configuration for the OMAP4430 + * module. + * + * This function can be called by the application to get their + * configuration parameter to proc4430_setup filled in by the + * OMAP4430 module with the default parameters. If the user + * does not wish to make any change in the default parameters, this + * API is not required to be called. + */ +void proc4430_get_config(struct proc4430_config *cfg) +{ + BUG_ON(cfg == NULL); + memcpy(cfg, &(proc4430_state.def_cfg), + sizeof(struct proc4430_config)); +} +EXPORT_SYMBOL(proc4430_get_config); + +/* + * Function to setup the OMAP4430 module. + * + * This function sets up the OMAP4430 module. This function + * must be called before any other instance-level APIs can be + * invoked. + * Module-level configuration needs to be provided to this + * function. If the user wishes to change some specific config + * parameters, then proc4430_get_config can be called to get the + * configuration filled with the default values. After this, only + * the required configuration values can be changed. If the user + * does not wish to make any change in the default parameters, the + * application can simply call proc4430_setup with NULL + * parameters. The default parameters would get automatically used. + */ +int proc4430_setup(struct proc4430_config *cfg) +{ + int retval = 0; + struct proc4430_config tmp_cfg; + atomic_cmpmask_and_set(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(0)); + + if (atomic_inc_return(&proc4430_state.ref_count) != + OMAP4430PROC_MAKE_MAGICSTAMP(1)) { + return 1; + } + + if (cfg == NULL) { + proc4430_get_config(&tmp_cfg); + cfg = &tmp_cfg; + } + + dmm_create(); + dmm_create_tables(DUCATI_DMM_START_ADDR, DUCATI_DMM_POOL_SIZE); + + /* Create a default gate handle for local module protection. */ + proc4430_state.gate_handle = + kmalloc(sizeof(struct mutex), GFP_KERNEL); + if (proc4430_state.gate_handle == NULL) { + retval = -ENOMEM; + goto error; + } + + mutex_init(proc4430_state.gate_handle); + + /* Initialize the name to handles mapping array. */ + memset(&proc4430_state.proc_handles, 0, + (sizeof(void *) * MULTIPROC_MAXPROCESSORS)); + + /* Copy the user provided values into the state object. */ + memcpy(&proc4430_state.cfg, cfg, + sizeof(struct proc4430_config)); + + return 0; + +error: + atomic_dec_return(&proc4430_state.ref_count); + dmm_delete_tables(); + dmm_destroy(); + + return retval; +} +EXPORT_SYMBOL(proc4430_setup); + +/* + * Function to destroy the OMAP4430 module. + * + * Once this function is called, other OMAP4430 module APIs, + * except for the proc4430_get_config API cannot be called + * anymore. + */ +int proc4430_destroy(void) +{ + int retval = 0; + u16 i; + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + retval = -ENODEV; + goto exit; + } + if (!(atomic_dec_return(&proc4430_state.ref_count) + == OMAP4430PROC_MAKE_MAGICSTAMP(0))) { + + retval = 1; + goto exit; + } + + /* Check if any OMAP4430 instances have not been + * deleted so far. If not,delete them. + */ + + for (i = 0; i < MULTIPROC_MAXPROCESSORS; i++) { + if (proc4430_state.proc_handles[i] == NULL) + continue; + proc4430_delete(&(proc4430_state.proc_handles[i])); + } + + /* Check if the gate_handle was created internally. */ + if (proc4430_state.gate_handle != NULL) { + mutex_destroy(proc4430_state.gate_handle); + kfree(proc4430_state.gate_handle); + } + +exit: + return retval; +} +EXPORT_SYMBOL(proc4430_destroy); + +/*================================================= + * Function to initialize the parameters for this Processor + * instance. + */ +void proc4430_params_init(void *handle, struct proc4430_params *params) +{ + struct proc4430_object *proc_object = (struct proc4430_object *)handle; + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_params_init failed " + "Module not initialized"); + return; + } + + if (WARN_ON(params == NULL)) { + printk(KERN_ERR "proc4430_params_init failed " + "Argument of type proc4430_params * " + "is NULL"); + return; + } + + if (handle == NULL) + memcpy(params, &(proc4430_state.def_inst_params), + sizeof(struct proc4430_params)); + else + memcpy(params, &(proc_object->params), + sizeof(struct proc4430_params)); +} +EXPORT_SYMBOL(proc4430_params_init); + +/*=================================================== + *Function to create an instance of this Processor. + * + */ +void *proc4430_create(u16 proc_id, const struct proc4430_params *params) +{ + struct processor_object *handle = NULL; + struct proc4430_object *object = NULL; + + BUG_ON(!IS_VALID_PROCID(proc_id)); + BUG_ON(params == NULL); + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_create failed " + "Module not initialized"); + goto error; + } + + /* Enter critical section protection. */ + WARN_ON(mutex_lock_interruptible(proc4430_state.gate_handle)); + if (proc4430_state.proc_handles[proc_id] != NULL) { + handle = proc4430_state.proc_handles[proc_id]; + goto func_end; + } else { + handle = (struct processor_object *) + vmalloc(sizeof(struct processor_object)); + if (WARN_ON(handle == NULL)) + goto func_end; + + handle->proc_fxn_table.attach = &proc4430_attach; + handle->proc_fxn_table.detach = &proc4430_detach; + handle->proc_fxn_table.start = &proc4430_start; + handle->proc_fxn_table.stop = &proc4430_stop; + handle->proc_fxn_table.read = &proc4430_read; + handle->proc_fxn_table.write = &proc4430_write; + handle->proc_fxn_table.control = &proc4430_control; + handle->proc_fxn_table.translateAddr = + &proc4430_translate_addr; + handle->proc_fxn_table.map = &proc4430_map; + handle->proc_fxn_table.unmap = &proc4430_unmap; + handle->proc_fxn_table.procinfo = &proc4430_proc_info; + handle->proc_fxn_table.virt_to_phys = &proc4430_virt_to_phys; + handle->state = PROC_MGR_STATE_UNKNOWN; + handle->object = vmalloc(sizeof(struct proc4430_object)); + handle->proc_id = proc_id; + object = (struct proc4430_object *)handle->object; + if (params != NULL) { + /* Copy params into instance object. */ + memcpy(&(object->params), (void *)params, + sizeof(struct proc4430_params)); + } + if ((params != NULL) && (params->mem_entries != NULL) + && (params->num_mem_entries > 0)) { + /* Allocate memory for, and copy mem_entries table*/ + object->params.mem_entries = vmalloc(sizeof(struct + proc4430_mem_entry) * + params->num_mem_entries); + memcpy(object->params.mem_entries, + params->mem_entries, + (sizeof(struct proc4430_mem_entry) * + params->num_mem_entries)); + } + handle->boot_mode = PROC_MGR_BOOTMODE_NOLOAD; + /* Set the handle in the state object. */ + proc4430_state.proc_handles[proc_id] = handle; + } + +func_end: + mutex_unlock(proc4430_state.gate_handle); +error: + return (void *)handle; +} +EXPORT_SYMBOL(proc4430_create); + +/*================================================= + * Function to delete an instance of this Processor. + * + * The user provided pointer to the handle is reset after + * successful completion of this function. + * + */ +int proc4430_delete(void **handle_ptr) +{ + int retval = 0; + struct proc4430_object *object = NULL; + struct processor_object *handle; + + BUG_ON(handle_ptr == NULL); + BUG_ON(*handle_ptr == NULL); + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_delete failed " + "Module not initialized"); + return -ENODEV; + } + + handle = (struct processor_object *)(*handle_ptr); + BUG_ON(!IS_VALID_PROCID(handle->proc_id)); + /* Enter critical section protection. */ + WARN_ON(mutex_lock_interruptible(proc4430_state.gate_handle)); + /* Reset handle in PwrMgr handle array. */ + proc4430_state.proc_handles[handle->proc_id] = NULL; + /* Free memory used for the OMAP4430 object. */ + if (handle->object != NULL) { + object = (struct proc4430_object *)handle->object; + if (object->params.mem_entries != NULL) { + vfree(object->params.mem_entries); + object->params.mem_entries = NULL; + } + vfree(handle->object); + handle->object = NULL; + } + /* Free memory used for the Processor object. */ + vfree(handle); + *handle_ptr = NULL; + /* Leave critical section protection. */ + mutex_unlock(proc4430_state.gate_handle); + return retval; +} +EXPORT_SYMBOL(proc4430_delete); + +/*=================================================== + * Function to open a handle to an instance of this Processor. This + * function is called when access to the Processor is required from + * a different process. + */ +int proc4430_open(void **handle_ptr, u16 proc_id) +{ + int retval = 0; + + BUG_ON(handle_ptr == NULL); + BUG_ON(!IS_VALID_PROCID(proc_id)); + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_open failed " + "Module not initialized"); + return -ENODEV; + } + + /* Initialize return parameter handle. */ + *handle_ptr = NULL; + + /* Check if the PwrMgr exists and return the handle if found. */ + if (proc4430_state.proc_handles[proc_id] == NULL) { + retval = -ENODEV; + goto func_exit; + } else + *handle_ptr = proc4430_state.proc_handles[proc_id]; +func_exit: + return retval; +} +EXPORT_SYMBOL(proc4430_open); + +/*=============================================== + * Function to close a handle to an instance of this Processor. + * + */ +int proc4430_close(void *handle) +{ + int retval = 0; + + BUG_ON(handle == NULL); + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_close failed " + "Module not initialized"); + return -ENODEV; + } + + /* nothing to be done for now */ + return retval; +} +EXPORT_SYMBOL(proc4430_close); + +/* ================================= + * APIs called by Processor module (part of function table interface) + * ================================= + */ +/*================================ + * Function to initialize the slave processor + * + */ +int proc4430_attach(void *handle, struct processor_attach_params *params) +{ + int retval = 0; + + struct processor_object *proc_handle = NULL; + struct proc4430_object *object = NULL; + u32 map_count = 0; + u32 i; + memory_map_info map_info; + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_attach failed" + "Module not initialized"); + return -ENODEV; + } + + if (WARN_ON(handle == NULL)) { + printk(KERN_ERR "proc4430_attach failed" + "Driver handle is NULL"); + return -EINVAL; + } + + if (WARN_ON(params == NULL)) { + printk(KERN_ERR "proc4430_attach failed" + "Argument processor_attach_params * is NULL"); + return -EINVAL; + } + + proc_handle = (struct processor_object *)handle; + + object = (struct proc4430_object *)proc_handle->object; + /* Return memory information in params. */ + for (i = 0; (i < object->params.num_mem_entries); i++) { + /* If the configured master virtual address is invalid, get the + * actual address by mapping the physical address into master + * kernel memory space. + */ + if ((object->params.mem_entries[i].master_virt_addr == (u32)-1) + && (object->params.mem_entries[i].shared == true)) { + map_info.src = object->params.mem_entries[i].phys_addr; + map_info.size = object->params.mem_entries[i].size; + map_info.is_cached = false; + retval = platform_mem_map(&map_info); + if (retval != 0) { + printk(KERN_ERR "proc4430_attach failed\n"); + return -EFAULT; + } + map_count++; + object->params.mem_entries[i].master_virt_addr = + map_info.dst; + params->mem_entries[i].addr + [PROC_MGR_ADDRTYPE_MASTERKNLVIRT] = + map_info.dst; + params->mem_entries[i].addr + [PROC_MGR_ADDRTYPE_SLAVEVIRT] = + (object->params.mem_entries[i].slave_virt_addr); + /* User virtual will be filled by user side. For now, + fill in the physical address so that it can be used + by mmap to remap this region into user-space */ + params->mem_entries[i].addr + [PROC_MGR_ADDRTYPE_MASTERUSRVIRT] = \ + object->params.mem_entries[i].phys_addr; + params->mem_entries[i].size = + object->params.mem_entries[i].size; + } + } + params->num_mem_entries = map_count; + return retval; +} + + +/*========================================== + * Function to detach from the Processor. + * + */ +int proc4430_detach(void *handle) +{ + struct processor_object *proc_handle = NULL; + struct proc4430_object *object = NULL; + u32 i; + memory_unmap_info unmap_info; + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + + printk(KERN_ERR "proc4430_detach failed " + "Module not initialized"); + return -ENODEV; + } + + if (WARN_ON(handle == NULL)) { + printk(KERN_ERR "proc4430_detach failed " + "Argument Driverhandle is NULL"); + return -EINVAL; + } + + proc_handle = (struct processor_object *)handle; + object = (struct proc4430_object *)proc_handle->object; + for (i = 0; (i < object->params.num_mem_entries); i++) { + if ((object->params.mem_entries[i].master_virt_addr > 0) + && (object->params.mem_entries[i].shared == true)) { + unmap_info.addr = + object->params.mem_entries[i].master_virt_addr; + unmap_info.size = object->params.mem_entries[i].size; + platform_mem_unmap(&unmap_info); + object->params.mem_entries[i].master_virt_addr = + (u32)-1; + } + } + return 0; +} + +/*========================================== + * Function to start the slave processor + * + * Start the slave processor running from its entry point. + * Depending on the boot mode, this involves configuring the boot + * address and releasing the slave from reset. + * + */ +int proc4430_start(void *handle, u32 entry_pt, + struct processor_start_params *start_params) +{ + u32 reg; + int counter = 10; + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + + printk(KERN_ERR "proc4430_start failed " + "Module not initialized"); + return -ENODEV; + } + + /*FIXME: Remove handle and entry_pt if not used */ + if (WARN_ON(start_params == NULL)) { + printk(KERN_ERR "proc4430_start failed " + "Argument processor_start_params * is NULL"); + return -EINVAL; + } + switch (start_params->params->proc_id) { + case SYS_M3: + /* Module is managed automatically by HW */ + __raw_writel(0x01, CORE_CM2_DUCATI_CLKCTRL); + /* Enable the M3 clock */ + __raw_writel(0x02, CORE_CM2_DUCATI_CLKSTCTRL); + do { + reg = __raw_readl(CORE_CM2_DUCATI_CLKSTCTRL); + if (reg & 0x100) { + printk(KERN_INFO "M3 clock enabled:" + "CORE_CM2_DUCATI_CLKSTCTRL = 0x%x\n", reg); + break; + } + msleep(1); + } while (--counter); + if (counter == 0) { + printk(KERN_ERR "FAILED TO ENABLE DUCATI M3 CLOCK !\n"); + return -EFAULT; + } + /* De-assert RST 3 */ + __raw_writel(0x3, CORE_PRM_BASE + RM_MPU_M3_RSTCTRL_OFFSET); + ducati_setup(); + printk(KERN_INFO "De-assert RST1\n"); + __raw_writel(0x2, CORE_PRM_BASE + RM_MPU_M3_RSTCTRL_OFFSET); + return 0; + break; + case APP_M3: + __raw_writel(0x0, CORE_PRM_BASE + RM_MPU_M3_RSTCTRL_OFFSET); + printk(KERN_INFO "De-assert RST2\n"); + break; + default: + printk(KERN_ERR "proc4430_start: ERROR input\n"); + break; + } + return 0; +} + + +/* + * Function to stop the slave processor + * + * Stop the execution of the slave processor. Depending on the boot + * mode, this may result in placing the slave processor in reset. + * + * @param handle void * to the Processor instance + * + * @sa proc4430_start, OMAP3530_halResetCtrl + */ +int +proc4430_stop(void *handle, struct processor_stop_params *stop_params) +{ + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_stop failed " + "Module not initialized"); + return -ENODEV; + } + switch (stop_params->params->proc_id) { + case SYS_M3: + ducati_destroy(); + printk(KERN_INFO "Assert RST1 and RST2 and RST3\n"); + __raw_writel(0x7, CORE_PRM_BASE + RM_MPU_M3_RSTCTRL_OFFSET); + /* Disable the M3 clock */ + __raw_writel(0x01, CORE_CM2_DUCATI_CLKSTCTRL); + break; + case APP_M3: + printk(KERN_INFO "Assert RST2\n"); + __raw_writel(0x2, CORE_PRM_BASE + RM_MPU_M3_RSTCTRL_OFFSET); + break; + default: + printk(KERN_ERR "proc4430_stop: ERROR input\n"); + break; + } + return 0; +} + + +/*============================================== + * Function to read from the slave processor's memory. + * + * Read from the slave processor's memory and copy into the + * provided buffer. + */ +int proc4430_read(void *handle, u32 proc_addr, u32 *num_bytes, + void *buffer) +{ + int retval = 0; + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_read failed " + "Module not initialized"); + return -ENODEV; + } + + /* TODO */ + return retval; +} + + +/*============================================== + * Function to write into the slave processor's memory. + * + * Read from the provided buffer and copy into the slave + * processor's memory. + * + */ +int proc4430_write(void *handle, u32 proc_addr, u32 *num_bytes, + void *buffer) +{ + int retval = 0; + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_write failed " + "Module not initialized"); + return -ENODEV; + } + + /* TODO */ + return retval; +} + + +/*========================================================= + * Function to perform device-dependent operations. + * + * Performs device-dependent control operations as exposed by this + * implementation of the Processor module. + */ +int proc4430_control(void *handle, int cmd, void *arg) +{ + int retval = 0; + + /*FIXME: Remove handle,etc if not used */ + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_control failed " + "Module not initialized"); + return -ENODEV; + } + + return retval; +} + + +/*===================================================== + * Function to translate between two types of address spaces. + * + * Translate between the specified address spaces. + */ +int proc4430_translate_addr(void *handle, + void **dst_addr, enum proc_mgr_addr_type dst_addr_type, + void *src_addr, enum proc_mgr_addr_type src_addr_type) +{ + int retval = 0; + struct processor_object *proc_handle = NULL; + struct proc4430_object *object = NULL; + struct proc4430_mem_entry *entry = NULL; + bool found = false; + u32 fm_addr_base = (u32)NULL; + u32 to_addr_base = (u32)NULL; + u32 i; + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_translate_addr failed " + "Module not initialized"); + retval = -ENODEV; + goto error_exit; + } + + if (WARN_ON(handle == NULL)) { + retval = -EINVAL; + goto error_exit; + } + if (WARN_ON(dst_addr == NULL)) { + retval = -EINVAL; + goto error_exit; + } + if (WARN_ON(dst_addr_type > PROC_MGR_ADDRTYPE_ENDVALUE)) { + retval = -EINVAL; + goto error_exit; + } + if (WARN_ON(src_addr == NULL)) { + retval = -EINVAL; + goto error_exit; + } + if (WARN_ON(src_addr_type > PROC_MGR_ADDRTYPE_ENDVALUE)) { + retval = -EINVAL; + goto error_exit; + } + + proc_handle = (struct processor_object *)handle; + object = (struct proc4430_object *)proc_handle->object; + *dst_addr = NULL; + for (i = 0 ; i < object->params.num_mem_entries ; i++) { + entry = &(object->params.mem_entries[i]); + fm_addr_base = + (src_addr_type == PROC_MGR_ADDRTYPE_MASTERKNLVIRT) ? + entry->master_virt_addr : entry->slave_virt_addr; + to_addr_base = + (dst_addr_type == PROC_MGR_ADDRTYPE_MASTERKNLVIRT) ? + entry->master_virt_addr : entry->slave_virt_addr; + /* Determine whether which way to convert */ + if (((u32)src_addr < (fm_addr_base + entry->size)) && + ((u32)src_addr >= fm_addr_base)) { + found = true; + *dst_addr = (void *)(((u32)src_addr - fm_addr_base) + + to_addr_base); + break; + } + } + + /* This check must not be removed even with build optimize. */ + if (WARN_ON(found == false)) { + /*Failed to translate address. */ + retval = -ENXIO; + goto error_exit; + } + return 0; + +error_exit: + return retval; +} + + +/*================================================= + * Function to map slave address to host address space + * + * Map the provided slave address to master address space. This + * function also maps the specified address to slave MMU space. + */ +int proc4430_map(void *handle, u32 proc_addr, + u32 size, u32 *mapped_addr, u32 *mapped_size, u32 map_attribs) +{ + int retval = 0; + u32 da_align; + u32 da; + u32 va_align; + u32 size_align; + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_map failed " + "Module not initialized"); + retval = -ENODEV; + goto error_exit; + } + + /*FIXME: Remove handle,etc if not used */ + + /* FIX ME: Temporary work around until the dynamic memory mapping + * for Tiler address space is available + */ + if ((map_attribs & DSP_MAPTILERADDR)) { + da_align = user_va2pa(current->mm, proc_addr); + *mapped_addr = (da_align | (proc_addr & (PAGE_SIZE - 1))); + printk(KERN_INFO "proc4430_map -tiler: user_va2pa: mapped_addr" + "= 0x%x\n", *mapped_addr); + return 0; + } + + /* Calculate the page-aligned PA, VA and size */ + va_align = PG_ALIGN_LOW(proc_addr, PAGE_SIZE); + size_align = PG_ALIGN_HIGH(size + (u32)proc_addr - va_align, PAGE_SIZE); + + dmm_reserve_memory(size_align, &da); + da_align = PG_ALIGN_LOW((u32)da, PAGE_SIZE); + retval = ducati_mem_map(va_align, da_align, size_align, map_attribs); + + /* Mapped address = MSB of DA | LSB of VA */ + *mapped_addr = (da_align | (proc_addr & (PAGE_SIZE - 1))); + +error_exit: + return retval; +} + +/*================================================= + * Function to unmap slave address to host address space + * + * UnMap the provided slave address to master address space. This + * function also unmaps the specified address to slave MMU space. + */ +int proc4430_unmap(void *handle, u32 mapped_addr) +{ + int da_align; + int ret_val = 0; + int size_align; + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_map failed " + "Module not initialized"); + ret_val = -1; + goto error_exit; + } + + /*FIXME: Remove handle,etc if not used */ + + da_align = PG_ALIGN_LOW((u32)mapped_addr, PAGE_SIZE); + ret_val = dmm_unreserve_memory(da_align, &size_align); + if (WARN_ON(ret_val < 0)) + goto error_exit; + ret_val = ducati_mem_unmap(da_align, size_align); + if (WARN_ON(ret_val < 0)) + goto error_exit; + return 0; + +error_exit: + printk(KERN_WARNING "proc4430_unmap failed !!!!\n"); + return ret_val; +} + +/*================================================= + * Function to return list of translated mem entries + * + * This function takes the remote processor address as + * an input and returns the mapped Page entries in the + * buffer passed + */ +int proc4430_virt_to_phys(void *handle, u32 da, u32 *mapped_entries, + u32 num_of_entries) +{ + int da_align; + int i; + int ret_val = 0; + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_virt_to_phys failed " + "Module not initialized"); + ret_val = -EFAULT; + goto error_exit; + } + + if (handle == NULL || mapped_entries == NULL || num_of_entries == 0) { + ret_val = -EFAULT; + goto error_exit; + } + da_align = PG_ALIGN_LOW((u32)da, PAGE_SIZE); + for (i = 0; i < num_of_entries; i++) { + mapped_entries[i] = ducati_mem_virtToPhys(da_align); + da_align += PAGE_SIZE; + } + return 0; + +error_exit: + printk(KERN_WARNING "proc4430_virtToPhys failed !!!!\n"); + return ret_val; +} + + +/*================================================= + * Function to return PROC4430 mem_entries info + * + */ +int proc4430_proc_info(void *handle, struct proc_mgr_proc_info *procinfo) +{ + struct processor_object *proc_handle = NULL; + struct proc4430_object *object = NULL; + struct proc4430_mem_entry *entry = NULL; + int i; + + if (atomic_cmpmask_and_lt(&proc4430_state.ref_count, + OMAP4430PROC_MAKE_MAGICSTAMP(0), + OMAP4430PROC_MAKE_MAGICSTAMP(1)) + == true) { + printk(KERN_ERR "proc4430_proc_info failed " + "Module not initialized"); + goto error_exit; + } + + if (WARN_ON(handle == NULL)) + goto error_exit; + if (WARN_ON(procinfo == NULL)) + goto error_exit; + + proc_handle = (struct processor_object *)handle; + + object = (struct proc4430_object *)proc_handle->object; + + for (i = 0 ; i < object->params.num_mem_entries ; i++) { + entry = &(object->params.mem_entries[i]); + procinfo->mem_entries[i].addr[PROC_MGR_ADDRTYPE_MASTERKNLVIRT] + = entry->master_virt_addr; + procinfo->mem_entries[i].addr[PROC_MGR_ADDRTYPE_SLAVEVIRT] + = entry->slave_virt_addr; + procinfo->mem_entries[i].size = entry->size; + } + procinfo->num_mem_entries = object->params.num_mem_entries; + procinfo->boot_mode = proc_handle->boot_mode; + return 0; + +error_exit: + printk(KERN_WARNING "proc4430_proc_info failed !!!!\n"); + return -EFAULT; +} |