2010-10-27 08:34:41 +00:00
/*
* Copyright ( C ) ST - Ericsson AB 2010
* Contact : Sjur Brendeland / sjur . brandeland @ stericsson . com
* Author : Amarnath Revanna / amarnath . bangalore . revanna @ stericsson . com
* License terms : GNU General Public License ( GPL ) version 2
*/
2010-11-30 09:11:22 +00:00
# define pr_fmt(fmt) KBUILD_MODNAME ":" fmt
2010-10-27 08:34:41 +00:00
# include <linux/init.h>
# include <linux/module.h>
# include <linux/netdevice.h>
2010-12-17 21:16:23 +01:00
# include <mach/mbox-db5500.h>
2010-10-27 08:34:41 +00:00
# include <net/caif/caif_shm.h>
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " CAIF Shared Memory protocol driver " ) ;
# define MAX_SHM_INSTANCES 1
enum {
MBX_ACC0 ,
MBX_ACC1 ,
MBX_DSP
} ;
static struct shmdev_layer shmdev_lyr [ MAX_SHM_INSTANCES ] ;
static unsigned int shm_start ;
static unsigned int shm_size ;
module_param ( shm_size , uint , 0440 ) ;
MODULE_PARM_DESC ( shm_total_size , " Start of SHM shared memory " ) ;
module_param ( shm_start , uint , 0440 ) ;
MODULE_PARM_DESC ( shm_total_start , " Total Size of SHM shared memory " ) ;
static int shmdev_send_msg ( u32 dev_id , u32 mbx_msg )
{
/* Always block until msg is written successfully */
mbox_send ( shmdev_lyr [ dev_id ] . hmbx , mbx_msg , true ) ;
return 0 ;
}
static int shmdev_mbx_setup ( void * pshmdrv_cb , struct shmdev_layer * pshm_dev ,
void * pshm_drv )
{
/*
* For UX5500 , we have only 1 SHM instance which uses MBX0
* for communication with the peer modem
*/
pshm_dev - > hmbx = mbox_setup ( MBX_ACC0 , pshmdrv_cb , pshm_drv ) ;
if ( ! pshm_dev - > hmbx )
return - ENODEV ;
else
return 0 ;
}
static int __init caif_shmdev_init ( void )
{
int i , result ;
/* Loop is currently overkill, there is only one instance */
for ( i = 0 ; i < MAX_SHM_INSTANCES ; i + + ) {
shmdev_lyr [ i ] . shm_base_addr = shm_start ;
shmdev_lyr [ i ] . shm_total_sz = shm_size ;
if ( ( ( char * ) shmdev_lyr [ i ] . shm_base_addr = = NULL )
| | ( shmdev_lyr [ i ] . shm_total_sz < = 0 ) ) {
pr_warn ( " ERROR, "
" Shared memory Address and/or Size incorrect "
" , Bailing out ... \n " ) ;
result = - EINVAL ;
goto clean ;
}
pr_info ( " SHM AREA (instance %d) STARTS "
" AT %p \n " , i , ( char * ) shmdev_lyr [ i ] . shm_base_addr ) ;
shmdev_lyr [ i ] . shm_id = i ;
shmdev_lyr [ i ] . pshmdev_mbxsend = shmdev_send_msg ;
shmdev_lyr [ i ] . pshmdev_mbxsetup = shmdev_mbx_setup ;
/*
* Finally , CAIF core module is called with details in place :
* 1. SHM base address
* 2. SHM size
* 3. MBX handle
*/
result = caif_shmcore_probe ( & shmdev_lyr [ i ] ) ;
if ( result ) {
pr_warn ( " ERROR[%d], "
" Could not probe SHM core (instance %d) "
" Bailing out ... \n " , result , i ) ;
goto clean ;
}
}
return 0 ;
clean :
/*
* For now , we assume that even if one instance of SHM fails , we bail
* out of the driver support completely . For this , we need to release
* any memory allocated and unregister any instance of SHM net device .
*/
for ( i = 0 ; i < MAX_SHM_INSTANCES ; i + + ) {
if ( shmdev_lyr [ i ] . pshm_netdev )
unregister_netdev ( shmdev_lyr [ i ] . pshm_netdev ) ;
}
return result ;
}
static void __exit caif_shmdev_exit ( void )
{
int i ;
for ( i = 0 ; i < MAX_SHM_INSTANCES ; i + + ) {
caif_shmcore_remove ( shmdev_lyr [ i ] . pshm_netdev ) ;
kfree ( ( void * ) shmdev_lyr [ i ] . shm_base_addr ) ;
}
}
module_init ( caif_shmdev_init ) ;
module_exit ( caif_shmdev_exit ) ;