Commit 65942564 authored by Arun Gopalakrishnan's avatar Arun Gopalakrishnan Committed by Hari Kanigeri

ARM OMAP4 Syslink Utils Platform mem module

This patch can be used to sync with the syslink drop 2.0.0.6.,
this will add a new memory management module for Ducati-MPU
shared memory management

This module will keep track of the shared memory b/w Ducati-MPU that
is mapped in to MPU/Linux address space. This module also provides
functions that can be used for address translation(b/w physical
address and kernel virtual address)
Signed-off-by: default avatarArun M G <arunmg@ti.com>
parent e5ecbc5b
/*
* platform_mem.c
*
* Target memory management interface implementation.
*
* This abstracts the Memory management interface in the kernel
* code. Allocation, Freeing-up, copy and address translate are
* supported for the kernel memory management.
*
* Copyright (C) 2008-2009 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.
*/
#ifndef _PLATFORM_MEM_H_
#define _PLATFORM_MEM_H_
#include <linux/types.h>
/*
* MEMORYOS_MODULEID
* Module ID for platform mem module
*/
#define PLATFORM_MEM_MODULEID (u16) 0x97D2
/*
* Enumerates the types of caching for memory regions
*/
enum platform_mem_cache_flags {
PLATFORM_MEM_CACHE_FLAGS_DEFAULT = 0x00000000,
/* Default flags - Cached */
PLATFORM_MEM_CACHE_FLAGS_CACHED = 0x00010000,
/* Cached memory */
PLATFORM_MEM_CACHE_FLAGS_UNCACHED = 0x00020000,
/* Uncached memory */
PLATFORM_MEM_CACHE_FLAGS_END_VALUE = 0x00030000
/* End delimiter indicating start of invalid values for this enum */
};
/*
* Enumerates the types of memory allocation
*/
enum platform_mem_mtype_flags{
PLATFORM_MEM_MTYPE_FLAGS_DEFAULT = 0x00000000,
/* Default flags - virtually contiguous */
PLATFORM_MEM_MTYPE_FLAGS_PHYSICAL = 0x00000001,
/* Physically contiguous */
PLATFORM_MEM_MTYPE_FLAGS_DMA = 0x00000002,
/* Physically contiguous */
PLATFORM_MEM_MTYPE_FLAGS_END_VALUE = 0x00000003
/* End delimiter indicating start of invalid values for this enum */
};
/*
* Enumerates the types of translation
*/
enum memory_xlt_flags{
PLATFORM_MEM_XLT_FLAGS_VIRT2PHYS = 0x00000000,
/* Virtual to physical */
PLATFORM_MEM_XLT_FLAGS_PHYS2VIRT = 0x00000001,
/* Virtual to physical */
PLATFORM_MEM_XLT_FLAGS_END_VALUE = 0x00000002
/* End delimiter indicating start of invalid values for this enum */
};
/*
* Structure containing information required for mapping a
* memory region.
*/
struct platform_mem_map_info {
u32 src;
/* Address to be mapped. */
u32 size;
/* Size of memory region to be mapped. */
u32 dst;
/* Mapped address. */
bool is_cached;
/* Whether the mapping is to a cached area or uncached area. */
void *drv_handle;
/* Handle to the driver that is implementing the mmap call. Ignored for
Kernel-side version. */
};
/*
* Structure containing information required for unmapping a
* memory region.
*/
struct platform_mem_unmap_info {
u32 addr;
/* Address to be unmapped.*/
u32 size;
/* Size of memory region to be unmapped.*/
bool is_cached;
/* Whether the mapping is to a cached area or uncached area. */
};
/*
* Structure containing information required for mapping a
* memory region.
*/
#define memory_map_info struct platform_mem_map_info
/*
* Structure containing information required for unmapping a
* memory region.
*/
#define memory_unmap_info struct platform_mem_unmap_info
/* =============================================================================
* APIs
* =============================================================================
*/
/* Initialize the platform mem module. */
int platform_mem_setup(void);
/* Finalize the platform mem module. */
int platform_mem_destroy(void);
/* Maps a memory area into virtual space. */
int platform_mem_map(memory_map_info *map_info);
/* Unmaps a memory area into virtual space. */
int platform_mem_unmap(memory_unmap_info *unmap_info);
/* Translate API */
void *platform_mem_translate(void *srcAddr, enum memory_xlt_flags flags);
#endif /* ifndef _PLATFORM_MEM_H_ */
......@@ -4,7 +4,7 @@ gatepeterson.o gatepeterson_ioctl.o sharedregion.o sharedregion_ioctl.o \
nameserver_remote.o nameserver_remotenotify.o listmp_sharedmemory.o \
listmp.o listmp_sharedmemory_ioctl.o messageq.o messageq_ioctl.o \
messageq_transportshm.o messageq_transportshm_ioctl.o \
nameserver_remotenotify_ioctl.o ipc_ioctl.o ipc_drv.o
nameserver_remotenotify_ioctl.o platform_mem.o ipc_ioctl.o ipc_drv.o
obj-$(CONFIG_MPU_SYSLINK_IPC) += syslink_ipc.o
syslink_ipc-objs = $(libservices) $(libsyslink_ipc)
......
/*
* platform_mem.c
*
* Target memory management interface implementation.
*
* This abstracts the Memory management interface in the kernel
* code. Allocation, Freeing-up, copy and address translate are
* supported for the kernel memory management.
*
* Copyright (C) 2008-2009 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.
*/
/* Linux specific header files */
#include <linux/types.h>
#include <linux/vmalloc.h>
#include <linux/string.h>
#include <linux/io.h>
#include <linux/list.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <platform_mem.h>
#include <atomic_linux.h>
/* Macro to make a correct module magic number with ref_count */
#define PLATFORM_MEM_MAKE_MAGICSTAMP(x) ((PLATFORM_MEM_MODULEID << 12u) | (x))
/*
* Structure for containing
*/
struct platform_mem_map_table_info {
struct list_head mem_entry; /* Pointer to mem_entry entry */
u32 physical_address; /* Actual address */
u32 knl_virtual_address; /* Mapped address */
u32 size; /* Size of the region mapped */
};
/*
* Structure defining state object of system memory manager
*/
struct platform_mem_module_object {
atomic_t ref_count; /* Reference count */
struct list_head map_table; /* Head of map table */
struct mutex *gate; /* Pointer to lock */
};
/*
* Object containing state of the platform mem module
*/
static struct platform_mem_module_object platform_mem_state;
/*
* ======== platform_mem_setup ========
* Purpose:
* This will initialize the platform mem module.
*/
int platform_mem_setup(void)
{
s32 retval = 0;
atomic_cmpmask_and_set(&platform_mem_state.ref_count,
PLATFORM_MEM_MAKE_MAGICSTAMP(0),
PLATFORM_MEM_MAKE_MAGICSTAMP(0));
if (atomic_inc_return(&platform_mem_state.ref_count)
!= PLATFORM_MEM_MAKE_MAGICSTAMP(1)) {
retval = -EEXIST;
goto exit;
}
/* Create the Gate handle */
platform_mem_state.gate =
kmalloc(sizeof(struct mutex), GFP_KERNEL);
if (platform_mem_state.gate == NULL) {
retval = -ENOMEM;
goto gate_create_fail;
}
/* Construct the map table */
INIT_LIST_HEAD(&platform_mem_state.map_table);
mutex_init(platform_mem_state.gate);
goto exit;
gate_create_fail:
atomic_set(&platform_mem_state.ref_count,
PLATFORM_MEM_MAKE_MAGICSTAMP(0));
exit:
return retval;
}
EXPORT_SYMBOL(platform_mem_setup);
/*
* ======== platform_mem_destroy ========
* Purpose:
* This will finalize the platform mem module.
*/
int platform_mem_destroy(void)
{
s32 retval = 0;
if (atomic_cmpmask_and_lt(&(platform_mem_state.ref_count),
PLATFORM_MEM_MAKE_MAGICSTAMP(0),
PLATFORM_MEM_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto exit;
}
if (atomic_dec_return(&platform_mem_state.ref_count)
== PLATFORM_MEM_MAKE_MAGICSTAMP(0)) {
/* Delete the gate handle */
kfree(&platform_mem_state.gate);
}
exit:
return retval;
}
EXPORT_SYMBOL(platform_mem_destroy);
/*
* ======== platform_mem_map ========
* Purpose:
* This will maps a memory area into virtual space.
*/
int platform_mem_map(memory_map_info *map_info)
{
int retval = 0;
struct platform_mem_map_table_info *info = NULL;
if (atomic_cmpmask_and_lt(&(platform_mem_state.ref_count),
PLATFORM_MEM_MAKE_MAGICSTAMP(0),
PLATFORM_MEM_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto exit;
}
if (WARN_ON(map_info == NULL)) {
retval = -EINVAL;
goto exit;
}
if (map_info->src == (u32) NULL) {
retval = -EINVAL;
goto exit;
}
info = kmalloc(sizeof(struct platform_mem_map_table_info),
GFP_KERNEL);
if (info == NULL) {
retval = -ENOMEM;
goto exit;
}
retval = mutex_lock_interruptible(platform_mem_state.gate);
if (retval)
goto lock_fail;
map_info->dst = 0;
if (map_info->is_cached == true)
map_info->dst = (u32) ioremap((dma_addr_t)
(map_info->src), map_info->size);
else
map_info->dst = (u32) ioremap_nocache((dma_addr_t)
(map_info->src), map_info->size);
if (map_info->dst == 0) {
retval = -EFAULT;
goto exit;
}
/* Populate the info */
info->physical_address = map_info->src;
info->knl_virtual_address = map_info->dst;
info->size = map_info->size;
/* Put the info into the list */
list_add(&info->mem_entry, &platform_mem_state.map_table);
mutex_unlock(platform_mem_state.gate);
goto exit;
lock_fail:
kfree(info);
exit:
return retval;
}
EXPORT_SYMBOL(platform_mem_map);
/*
* ======== platform_mem_unmap ========
* Purpose:
* This will unmaps a memory area into virtual space.
*/
int platform_mem_unmap(memory_unmap_info *unmap_info)
{
s32 retval = 0;
struct platform_mem_map_table_info *info = NULL;
if (atomic_cmpmask_and_lt(&(platform_mem_state.ref_count),
PLATFORM_MEM_MAKE_MAGICSTAMP(0),
PLATFORM_MEM_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto exit;
}
if (unmap_info == NULL) {
retval = -EINVAL;
goto exit;
}
if (unmap_info->addr == (u32) NULL) {
retval = -EINVAL;
goto exit;
}
retval = mutex_lock_interruptible(platform_mem_state.gate);
if (retval)
goto exit;
iounmap((unsigned int *) unmap_info->addr);
/* Delete the node in the map table */
list_for_each_entry(info, &platform_mem_state.map_table, mem_entry) {
if (info->knl_virtual_address == unmap_info->addr) {
list_del(&info->mem_entry);
break;
}
}
mutex_unlock(platform_mem_state.gate);
exit:
return retval;
}
EXPORT_SYMBOL(platform_mem_unmap);
/*
* ======== platform_mem_map ========
* Purpose:
* This will translate an address.
*/
void *platform_mem_translate(void *src_addr, enum memory_xlt_flags flags)
{
void *buf = NULL;
struct platform_mem_map_table_info *tinfo = NULL;
u32 frm_addr;
u32 to_addr;
s32 retval = 0;
if (atomic_cmpmask_and_lt(&(platform_mem_state.ref_count),
PLATFORM_MEM_MAKE_MAGICSTAMP(0),
PLATFORM_MEM_MAKE_MAGICSTAMP(1)) == true) {
retval = -ENODEV;
goto exit;
}
retval = mutex_lock_interruptible(platform_mem_state.gate);
if (retval)
goto exit;
/* Traverse to the node in the map table */
list_for_each_entry(tinfo, &platform_mem_state.map_table, mem_entry) {
frm_addr = (flags == PLATFORM_MEM_XLT_FLAGS_VIRT2PHYS) ?
tinfo->knl_virtual_address : tinfo->physical_address;
to_addr = (flags == PLATFORM_MEM_XLT_FLAGS_VIRT2PHYS) ?
tinfo->physical_address : tinfo->knl_virtual_address;
if ((((u32) src_addr) >= frm_addr)
&& (((u32) src_addr) < (frm_addr + tinfo->size))) {
buf = (void *) (to_addr + ((u32)src_addr - frm_addr));
break;
}
}
mutex_unlock(platform_mem_state.gate);
exit:
return buf;
}
EXPORT_SYMBOL(platform_mem_translate);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment