-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
caif-u5500: CAIF shared memory mailbox interface
Signed-off-by: Sjur Braendeland <sjur.brandeland@stericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
- Loading branch information
Amarnath Revanna
authored and
David S. Miller
committed
Oct 27, 2010
1 parent
dfae55d
commit e57731f
Showing
1 changed file
with
129 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
/* | ||
* 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 | ||
*/ | ||
|
||
#define pr_fmt(fmt) KBUILD_MODNAME ":" __func__ "():" fmt | ||
|
||
#include <linux/version.h> | ||
#include <linux/init.h> | ||
#include <linux/module.h> | ||
#include <linux/netdevice.h> | ||
#include <mach/mbox.h> | ||
#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); |