Other Parts Discussed in Thread: OMAP-L138
Hello,
I'm want to map the DSP memory regions to Linux userspace, using the OMAP L-137 EVM. The main reason for this is to enable high speed communication between the ARM and DSP applications by means of shared memory and interrupts. I'm not able to use DSP Link since this introduces a variable delay in the DSP application.
I'm implementing my driver in the form of a Kernel module. This module exports a number of character devices which represent the DSP memory regions. I've attached mmap file operations to these devices so the memory can be mapped in userspace by using mmap(). When mmap is performed on the device it performs an remap_pfn_range on the physical address of the memory region.
For some reason this strategy is not working out. The memory is mapped without error but when I read mmap'ed memory in userspace it contains all zeroes. When I attach Code Composer Studio to the DSP and read the same regiser (for example L1DRAM @ 0x11F0 0000) it shows random data.
- Does anybody know why this is happening?
I've also noticed that when I perform an ioremap action on the same physical address (for example L1DRAM @ 0x11F0 0000) I'm able to print the data. This data corresponds to the data read from Code Composer Studio. So it seems I'm able to access the DSP memory using ioremap, but I'm not sure how I can provide this map to userspace.
- Is there a way to convert and supply the mapped memory using ioremap to userspace (via the mmap call for example)? Which functions can be used for that operation?
Another thing I noticed is that when I connect Code Composer to debug both the ARM and DSP after Linux is booted, I'm only able to read the L1DRAM from the DSP debug connection. When I enter the address in the ARM memory view it displays all zeroes.
- Can anybody tell me what is responsible for this behaviour?
I've also added parts of my source code to make it all a little bit more understandable. I've only added the parts that apply to L1DRAM but I'm having the same problem with;
- L2ROM, L2RAM and L1PRAM
I'm able to map the SDRAM and Shared Ram using /dev/mem but I want to add those devices to my own driver as well.
-- dspcomk.c : kernel module --
#define L1DRAM_ADDR 0x11F00000
#define L1DRAM_SIZE 0x8000 //32K
static int
dspcom_mmap(struct file * filp, struct vm_area_struct * vma)
{
int retval;
unsigned long physical = 0;
unsigned long psize = 0;
unsigned long vsize = vma->vm_end - vma->vm_start;
switch( iminor( filp->f_dentry->d_inode ) )
{
case DSPCOM_MINOR_L1DRAM:
physical = L1DRAM_ADDR;
psize = L1DRAM_SIZE;
break;
default:
return -ENOMEM;
}
printk( " DSPCom: physical addr: 0x%lX\n", physical );
printk( " DSPCom: vsize: 0x%lX\n", vsize );
printk( " DSPCom: psize: 0x%lX\n", psize );
printk( " DSPCom: vm start addr: 0x%lX\n", vma->vm_start );
printk( " DSPCom: vm end addr: 0x%lX\n", vma->vm_end );
printk( " DSPCom: vm offset: 0x%lX\n", vma->vm_pgoff << PAGE_SHIFT );
if( vsize > psize )
{
printk( "DSPCom: vsize[%ld] > psize[%ld]\n", vsize, psize );
return -ENOMEM;
}
retval = remap_pfn_range( vma, vma->vm_start,physical , vsize, vma->vm_page_prot );
if( 0 != retval )
{
printk( "DSPCom: unable to remap_pfn_range: %d\n", retval );
}
return 0;
}
struct file_operations dspcom_sharedmem_fops =
{
.owner = THIS_MODULE,
.mmap = dspcom_mmap,
};
static int __init
dspcom_init_module ( void )
{
dev_l1dram = cdev_alloc();
...
dev_l1dram->ops = &dspcom_sharedmem_fops;
dev_l1dram->dev = MKDEV( DSPCOM_MAJOR, DSPCOM_MINOR_L1DRAM );
retval = cdev_add( dev_l1dram, MKDEV( DSPCOM_MAJOR, DSPCOM_MINOR_L1DRAM ), 1 );
...
}
static void __exit
dspcom_cleanup_module ( void )
{
cdev_del( dev_l1dram );
}
-- Test App --
fd = open( "/dev/l1dram", O_RDWR );
if( -1 == fd) error("bad file");
buf = mmap( 0, 256*1024, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED, fd, 0 );
if( -1 == buf ) error("bad map" );
printf( "[0]:0x%X\n[1]:0x%X\n[2]:0x%X\n[3]:0x%X\n",
static_cast<unsigned int*>(buf)[0], static_cast<unsigned int*>(buf)[1],
static_cast<unsigned int*>(buf)[2], static_cast<unsigned int*>(buf)[3] );
retval = close( fd );
if( -1 == retval ) error( "bad close");
-- ioremap in init --
volatile unsigned int* L2RAM; // declared globaly
L2RAM = ioremap( L2RAM_ADDR, 256*1024 );
printk( " DSPCom: L2RAM addr: 0x%X, data[0]: 0x%X\n", L2RAM, (unsigned int)(L2RAM)[0] );