2011-10-20 20:53:35 +04:00
/*
* OMAP Remote Processor driver
*
* Copyright ( C ) 2011 Texas Instruments , Inc .
* Copyright ( C ) 2011 Google , Inc .
*
* Ohad Ben - Cohen < ohad @ wizery . com >
* Brian Swetland < swetland @ google . com >
* Fernando Guzman Lugo < fernando . lugo @ ti . com >
* Mark Grosen < mgrosen @ ti . com >
* Suman Anna < s - anna @ ti . com >
* Hari Kanigeri < h - kanigeri2 @ ti . com >
*
* This program 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 program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/err.h>
# include <linux/platform_device.h>
# include <linux/dma-mapping.h>
# include <linux/remoteproc.h>
2014-11-04 02:05:50 +03:00
# include <linux/mailbox_client.h>
2013-03-13 02:55:29 +04:00
# include <linux/omap-mailbox.h>
2011-10-20 20:53:35 +04:00
2012-08-24 17:21:06 +04:00
# include <linux/platform_data/remoteproc-omap.h>
2011-10-20 20:53:35 +04:00
# include "omap_remoteproc.h"
# include "remoteproc_internal.h"
/**
* struct omap_rproc - omap remote processor state
2014-11-04 02:05:50 +03:00
* @ mbox : mailbox channel handle
* @ client : mailbox client to request the mailbox channel
2011-10-20 20:53:35 +04:00
* @ rproc : rproc handle
*/
struct omap_rproc {
2014-11-04 02:05:50 +03:00
struct mbox_chan * mbox ;
struct mbox_client client ;
2011-10-20 20:53:35 +04:00
struct rproc * rproc ;
} ;
/**
* omap_rproc_mbox_callback ( ) - inbound mailbox message handler
2014-11-04 02:05:50 +03:00
* @ client : mailbox client pointer used for requesting the mailbox channel
2011-10-20 20:53:35 +04:00
* @ data : mailbox payload
*
* This handler is invoked by omap ' s mailbox driver whenever a mailbox
* message is received . Usually , the mailbox payload simply contains
* the index of the virtqueue that is kicked by the remote processor ,
* and we let remoteproc core handle it .
*
* In addition to virtqueue indices , we also have some out - of - band values
* that indicates different events . Those values are deliberately very
* big so they don ' t coincide with virtqueue indices .
*/
2014-11-04 02:05:50 +03:00
static void omap_rproc_mbox_callback ( struct mbox_client * client , void * data )
2011-10-20 20:53:35 +04:00
{
2014-11-04 02:05:50 +03:00
struct omap_rproc * oproc = container_of ( client , struct omap_rproc ,
client ) ;
remoteproc: maintain a generic child device for each rproc
For each registered rproc, maintain a generic remoteproc device whose
parent is the low level platform-specific device (commonly a pdev, but
it may certainly be any other type of device too).
With this in hand, the resulting device hierarchy might then look like:
omap-rproc.0
|
- remoteproc0 <---- new !
|
- virtio0
|
- virtio1
|
- rpmsg0
|
- rpmsg1
|
- rpmsg2
Where:
- omap-rproc.0 is the low level device that's bound to the
driver which invokes rproc_register()
- remoteproc0 is the result of this patch, and will be added by the
remoteproc framework when rproc_register() is invoked
- virtio0 and virtio1 are vdevs that are registered by remoteproc
when it realizes that they are supported by the firmware
of the physical remote processor represented by omap-rproc.0
- rpmsg0, rpmsg1 and rpmsg2 are rpmsg devices that represent rpmsg
channels, and are registerd by the rpmsg bus when it gets notified
about their existence
Technically, this patch:
- changes 'struct rproc' to contain this generic remoteproc.x device
- creates a new "remoteproc" type, to which this new generic remoteproc.x
device belong to.
- adds a super simple enumeration method for the indices of the
remoteproc.x devices
- updates all dev_* messaging to use the generic remoteproc.x device
instead of the low level platform-specific device
- updates all dma_* allocations to use the parent of remoteproc.x (where
the platform-specific memory pools, most commonly CMA, are to be found)
Adding this generic device has several merits:
- we can now add remoteproc runtime PM support simply by hooking onto the
new "remoteproc" type
- all remoteproc log messages will now carry a common name prefix
instead of having a platform-specific one
- having a device as part of the rproc struct makes it possible to simplify
refcounting (see subsequent patch)
Thanks to Stephen Boyd <sboyd@codeaurora.org> for suggesting and
discussing these ideas in one of the remoteproc review threads and
to Fernando Guzman Lugo <fernando.lugo@ti.com> for trying them out
with the (upcoming) runtime PM support for remoteproc.
Cc: Fernando Guzman Lugo <fernando.lugo@ti.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2012-05-30 23:01:25 +04:00
struct device * dev = oproc - > rproc - > dev . parent ;
2011-10-20 20:53:35 +04:00
const char * name = oproc - > rproc - > name ;
2014-11-04 02:05:50 +03:00
u32 msg = ( u32 ) data ;
2011-10-20 20:53:35 +04:00
dev_dbg ( dev , " mbox msg: 0x%x \n " , msg ) ;
switch ( msg ) {
case RP_MBOX_CRASH :
/* just log this for now. later, we'll also do recovery */
dev_err ( dev , " omap rproc %s crashed \n " , name ) ;
break ;
case RP_MBOX_ECHO_REPLY :
dev_info ( dev , " received echo reply from %s \n " , name ) ;
break ;
default :
2012-02-13 14:24:50 +04:00
/* msg contains the index of the triggered vring */
2011-10-20 20:53:35 +04:00
if ( rproc_vq_interrupt ( oproc - > rproc , msg ) = = IRQ_NONE )
dev_dbg ( dev , " no message was found in vqid %d \n " , msg ) ;
}
}
/* kick a virtqueue */
static void omap_rproc_kick ( struct rproc * rproc , int vqid )
{
struct omap_rproc * oproc = rproc - > priv ;
remoteproc: maintain a generic child device for each rproc
For each registered rproc, maintain a generic remoteproc device whose
parent is the low level platform-specific device (commonly a pdev, but
it may certainly be any other type of device too).
With this in hand, the resulting device hierarchy might then look like:
omap-rproc.0
|
- remoteproc0 <---- new !
|
- virtio0
|
- virtio1
|
- rpmsg0
|
- rpmsg1
|
- rpmsg2
Where:
- omap-rproc.0 is the low level device that's bound to the
driver which invokes rproc_register()
- remoteproc0 is the result of this patch, and will be added by the
remoteproc framework when rproc_register() is invoked
- virtio0 and virtio1 are vdevs that are registered by remoteproc
when it realizes that they are supported by the firmware
of the physical remote processor represented by omap-rproc.0
- rpmsg0, rpmsg1 and rpmsg2 are rpmsg devices that represent rpmsg
channels, and are registerd by the rpmsg bus when it gets notified
about their existence
Technically, this patch:
- changes 'struct rproc' to contain this generic remoteproc.x device
- creates a new "remoteproc" type, to which this new generic remoteproc.x
device belong to.
- adds a super simple enumeration method for the indices of the
remoteproc.x devices
- updates all dev_* messaging to use the generic remoteproc.x device
instead of the low level platform-specific device
- updates all dma_* allocations to use the parent of remoteproc.x (where
the platform-specific memory pools, most commonly CMA, are to be found)
Adding this generic device has several merits:
- we can now add remoteproc runtime PM support simply by hooking onto the
new "remoteproc" type
- all remoteproc log messages will now carry a common name prefix
instead of having a platform-specific one
- having a device as part of the rproc struct makes it possible to simplify
refcounting (see subsequent patch)
Thanks to Stephen Boyd <sboyd@codeaurora.org> for suggesting and
discussing these ideas in one of the remoteproc review threads and
to Fernando Guzman Lugo <fernando.lugo@ti.com> for trying them out
with the (upcoming) runtime PM support for remoteproc.
Cc: Fernando Guzman Lugo <fernando.lugo@ti.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2012-05-30 23:01:25 +04:00
struct device * dev = rproc - > dev . parent ;
2011-10-20 20:53:35 +04:00
int ret ;
/* send the index of the triggered virtqueue in the mailbox payload */
2014-11-04 02:05:50 +03:00
ret = mbox_send_message ( oproc - > mbox , ( void * ) vqid ) ;
if ( ret < 0 )
remoteproc: maintain a generic child device for each rproc
For each registered rproc, maintain a generic remoteproc device whose
parent is the low level platform-specific device (commonly a pdev, but
it may certainly be any other type of device too).
With this in hand, the resulting device hierarchy might then look like:
omap-rproc.0
|
- remoteproc0 <---- new !
|
- virtio0
|
- virtio1
|
- rpmsg0
|
- rpmsg1
|
- rpmsg2
Where:
- omap-rproc.0 is the low level device that's bound to the
driver which invokes rproc_register()
- remoteproc0 is the result of this patch, and will be added by the
remoteproc framework when rproc_register() is invoked
- virtio0 and virtio1 are vdevs that are registered by remoteproc
when it realizes that they are supported by the firmware
of the physical remote processor represented by omap-rproc.0
- rpmsg0, rpmsg1 and rpmsg2 are rpmsg devices that represent rpmsg
channels, and are registerd by the rpmsg bus when it gets notified
about their existence
Technically, this patch:
- changes 'struct rproc' to contain this generic remoteproc.x device
- creates a new "remoteproc" type, to which this new generic remoteproc.x
device belong to.
- adds a super simple enumeration method for the indices of the
remoteproc.x devices
- updates all dev_* messaging to use the generic remoteproc.x device
instead of the low level platform-specific device
- updates all dma_* allocations to use the parent of remoteproc.x (where
the platform-specific memory pools, most commonly CMA, are to be found)
Adding this generic device has several merits:
- we can now add remoteproc runtime PM support simply by hooking onto the
new "remoteproc" type
- all remoteproc log messages will now carry a common name prefix
instead of having a platform-specific one
- having a device as part of the rproc struct makes it possible to simplify
refcounting (see subsequent patch)
Thanks to Stephen Boyd <sboyd@codeaurora.org> for suggesting and
discussing these ideas in one of the remoteproc review threads and
to Fernando Guzman Lugo <fernando.lugo@ti.com> for trying them out
with the (upcoming) runtime PM support for remoteproc.
Cc: Fernando Guzman Lugo <fernando.lugo@ti.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2012-05-30 23:01:25 +04:00
dev_err ( dev , " omap_mbox_msg_send failed: %d \n " , ret ) ;
2011-10-20 20:53:35 +04:00
}
/*
* Power up the remote processor .
*
* This function will be invoked only after the firmware for this rproc
* was loaded , parsed successfully , and all of its resource requirements
* were met .
*/
static int omap_rproc_start ( struct rproc * rproc )
{
struct omap_rproc * oproc = rproc - > priv ;
remoteproc: maintain a generic child device for each rproc
For each registered rproc, maintain a generic remoteproc device whose
parent is the low level platform-specific device (commonly a pdev, but
it may certainly be any other type of device too).
With this in hand, the resulting device hierarchy might then look like:
omap-rproc.0
|
- remoteproc0 <---- new !
|
- virtio0
|
- virtio1
|
- rpmsg0
|
- rpmsg1
|
- rpmsg2
Where:
- omap-rproc.0 is the low level device that's bound to the
driver which invokes rproc_register()
- remoteproc0 is the result of this patch, and will be added by the
remoteproc framework when rproc_register() is invoked
- virtio0 and virtio1 are vdevs that are registered by remoteproc
when it realizes that they are supported by the firmware
of the physical remote processor represented by omap-rproc.0
- rpmsg0, rpmsg1 and rpmsg2 are rpmsg devices that represent rpmsg
channels, and are registerd by the rpmsg bus when it gets notified
about their existence
Technically, this patch:
- changes 'struct rproc' to contain this generic remoteproc.x device
- creates a new "remoteproc" type, to which this new generic remoteproc.x
device belong to.
- adds a super simple enumeration method for the indices of the
remoteproc.x devices
- updates all dev_* messaging to use the generic remoteproc.x device
instead of the low level platform-specific device
- updates all dma_* allocations to use the parent of remoteproc.x (where
the platform-specific memory pools, most commonly CMA, are to be found)
Adding this generic device has several merits:
- we can now add remoteproc runtime PM support simply by hooking onto the
new "remoteproc" type
- all remoteproc log messages will now carry a common name prefix
instead of having a platform-specific one
- having a device as part of the rproc struct makes it possible to simplify
refcounting (see subsequent patch)
Thanks to Stephen Boyd <sboyd@codeaurora.org> for suggesting and
discussing these ideas in one of the remoteproc review threads and
to Fernando Guzman Lugo <fernando.lugo@ti.com> for trying them out
with the (upcoming) runtime PM support for remoteproc.
Cc: Fernando Guzman Lugo <fernando.lugo@ti.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2012-05-30 23:01:25 +04:00
struct device * dev = rproc - > dev . parent ;
struct platform_device * pdev = to_platform_device ( dev ) ;
2011-10-20 20:53:35 +04:00
struct omap_rproc_pdata * pdata = pdev - > dev . platform_data ;
int ret ;
2014-11-04 02:05:50 +03:00
struct mbox_client * client = & oproc - > client ;
2011-10-20 20:53:35 +04:00
2012-08-15 19:25:48 +04:00
if ( pdata - > set_bootaddr )
pdata - > set_bootaddr ( rproc - > bootaddr ) ;
2014-11-04 02:05:50 +03:00
client - > dev = dev ;
client - > tx_done = NULL ;
client - > rx_callback = omap_rproc_mbox_callback ;
client - > tx_block = false ;
client - > knows_txdone = false ;
2011-10-20 20:53:35 +04:00
2014-11-04 02:05:50 +03:00
oproc - > mbox = omap_mbox_request_channel ( client , pdata - > mbox_name ) ;
2011-10-20 20:53:35 +04:00
if ( IS_ERR ( oproc - > mbox ) ) {
2014-11-04 02:05:50 +03:00
ret = - EBUSY ;
dev_err ( dev , " mbox_request_channel failed: %ld \n " ,
PTR_ERR ( oproc - > mbox ) ) ;
2011-10-20 20:53:35 +04:00
return ret ;
}
/*
* Ping the remote processor . this is only for sanity - sake ;
* there is no functional effect whatsoever .
*
* Note that the reply will _not_ arrive immediately : this message
* will wait in the mailbox fifo until the remote processor is booted .
*/
2014-11-04 02:05:50 +03:00
ret = mbox_send_message ( oproc - > mbox , ( void * ) RP_MBOX_ECHO_REQUEST ) ;
if ( ret < 0 ) {
dev_err ( dev , " mbox_send_message failed: %d \n " , ret ) ;
2011-10-20 20:53:35 +04:00
goto put_mbox ;
}
ret = pdata - > device_enable ( pdev ) ;
if ( ret ) {
remoteproc: maintain a generic child device for each rproc
For each registered rproc, maintain a generic remoteproc device whose
parent is the low level platform-specific device (commonly a pdev, but
it may certainly be any other type of device too).
With this in hand, the resulting device hierarchy might then look like:
omap-rproc.0
|
- remoteproc0 <---- new !
|
- virtio0
|
- virtio1
|
- rpmsg0
|
- rpmsg1
|
- rpmsg2
Where:
- omap-rproc.0 is the low level device that's bound to the
driver which invokes rproc_register()
- remoteproc0 is the result of this patch, and will be added by the
remoteproc framework when rproc_register() is invoked
- virtio0 and virtio1 are vdevs that are registered by remoteproc
when it realizes that they are supported by the firmware
of the physical remote processor represented by omap-rproc.0
- rpmsg0, rpmsg1 and rpmsg2 are rpmsg devices that represent rpmsg
channels, and are registerd by the rpmsg bus when it gets notified
about their existence
Technically, this patch:
- changes 'struct rproc' to contain this generic remoteproc.x device
- creates a new "remoteproc" type, to which this new generic remoteproc.x
device belong to.
- adds a super simple enumeration method for the indices of the
remoteproc.x devices
- updates all dev_* messaging to use the generic remoteproc.x device
instead of the low level platform-specific device
- updates all dma_* allocations to use the parent of remoteproc.x (where
the platform-specific memory pools, most commonly CMA, are to be found)
Adding this generic device has several merits:
- we can now add remoteproc runtime PM support simply by hooking onto the
new "remoteproc" type
- all remoteproc log messages will now carry a common name prefix
instead of having a platform-specific one
- having a device as part of the rproc struct makes it possible to simplify
refcounting (see subsequent patch)
Thanks to Stephen Boyd <sboyd@codeaurora.org> for suggesting and
discussing these ideas in one of the remoteproc review threads and
to Fernando Guzman Lugo <fernando.lugo@ti.com> for trying them out
with the (upcoming) runtime PM support for remoteproc.
Cc: Fernando Guzman Lugo <fernando.lugo@ti.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2012-05-30 23:01:25 +04:00
dev_err ( dev , " omap_device_enable failed: %d \n " , ret ) ;
2011-10-20 20:53:35 +04:00
goto put_mbox ;
}
return 0 ;
put_mbox :
2014-11-04 02:05:50 +03:00
mbox_free_channel ( oproc - > mbox ) ;
2011-10-20 20:53:35 +04:00
return ret ;
}
/* power off the remote processor */
static int omap_rproc_stop ( struct rproc * rproc )
{
remoteproc: maintain a generic child device for each rproc
For each registered rproc, maintain a generic remoteproc device whose
parent is the low level platform-specific device (commonly a pdev, but
it may certainly be any other type of device too).
With this in hand, the resulting device hierarchy might then look like:
omap-rproc.0
|
- remoteproc0 <---- new !
|
- virtio0
|
- virtio1
|
- rpmsg0
|
- rpmsg1
|
- rpmsg2
Where:
- omap-rproc.0 is the low level device that's bound to the
driver which invokes rproc_register()
- remoteproc0 is the result of this patch, and will be added by the
remoteproc framework when rproc_register() is invoked
- virtio0 and virtio1 are vdevs that are registered by remoteproc
when it realizes that they are supported by the firmware
of the physical remote processor represented by omap-rproc.0
- rpmsg0, rpmsg1 and rpmsg2 are rpmsg devices that represent rpmsg
channels, and are registerd by the rpmsg bus when it gets notified
about their existence
Technically, this patch:
- changes 'struct rproc' to contain this generic remoteproc.x device
- creates a new "remoteproc" type, to which this new generic remoteproc.x
device belong to.
- adds a super simple enumeration method for the indices of the
remoteproc.x devices
- updates all dev_* messaging to use the generic remoteproc.x device
instead of the low level platform-specific device
- updates all dma_* allocations to use the parent of remoteproc.x (where
the platform-specific memory pools, most commonly CMA, are to be found)
Adding this generic device has several merits:
- we can now add remoteproc runtime PM support simply by hooking onto the
new "remoteproc" type
- all remoteproc log messages will now carry a common name prefix
instead of having a platform-specific one
- having a device as part of the rproc struct makes it possible to simplify
refcounting (see subsequent patch)
Thanks to Stephen Boyd <sboyd@codeaurora.org> for suggesting and
discussing these ideas in one of the remoteproc review threads and
to Fernando Guzman Lugo <fernando.lugo@ti.com> for trying them out
with the (upcoming) runtime PM support for remoteproc.
Cc: Fernando Guzman Lugo <fernando.lugo@ti.com>
Reviewed-by: Stephen Boyd <sboyd@codeaurora.org>
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2012-05-30 23:01:25 +04:00
struct device * dev = rproc - > dev . parent ;
struct platform_device * pdev = to_platform_device ( dev ) ;
2011-10-20 20:53:35 +04:00
struct omap_rproc_pdata * pdata = pdev - > dev . platform_data ;
struct omap_rproc * oproc = rproc - > priv ;
int ret ;
ret = pdata - > device_shutdown ( pdev ) ;
if ( ret )
return ret ;
2014-11-04 02:05:50 +03:00
mbox_free_channel ( oproc - > mbox ) ;
2011-10-20 20:53:35 +04:00
return 0 ;
}
static struct rproc_ops omap_rproc_ops = {
. start = omap_rproc_start ,
. stop = omap_rproc_stop ,
. kick = omap_rproc_kick ,
} ;
2012-12-22 03:14:44 +04:00
static int omap_rproc_probe ( struct platform_device * pdev )
2011-10-20 20:53:35 +04:00
{
struct omap_rproc_pdata * pdata = pdev - > dev . platform_data ;
struct omap_rproc * oproc ;
struct rproc * rproc ;
int ret ;
ret = dma_set_coherent_mask ( & pdev - > dev , DMA_BIT_MASK ( 32 ) ) ;
if ( ret ) {
2012-05-21 17:31:12 +04:00
dev_err ( & pdev - > dev , " dma_set_coherent_mask: %d \n " , ret ) ;
2011-10-20 20:53:35 +04:00
return ret ;
}
rproc = rproc_alloc ( & pdev - > dev , pdata - > name , & omap_rproc_ops ,
pdata - > firmware , sizeof ( * oproc ) ) ;
if ( ! rproc )
return - ENOMEM ;
oproc = rproc - > priv ;
oproc - > rproc = rproc ;
platform_set_drvdata ( pdev , rproc ) ;
2012-07-04 17:25:06 +04:00
ret = rproc_add ( rproc ) ;
2011-10-20 20:53:35 +04:00
if ( ret )
goto free_rproc ;
return 0 ;
free_rproc :
2012-07-04 17:25:06 +04:00
rproc_put ( rproc ) ;
2011-10-20 20:53:35 +04:00
return ret ;
}
2012-12-22 03:14:44 +04:00
static int omap_rproc_remove ( struct platform_device * pdev )
2011-10-20 20:53:35 +04:00
{
struct rproc * rproc = platform_get_drvdata ( pdev ) ;
2012-07-04 17:25:06 +04:00
rproc_del ( rproc ) ;
rproc_put ( rproc ) ;
2012-07-02 12:41:16 +04:00
return 0 ;
2011-10-20 20:53:35 +04:00
}
static struct platform_driver omap_rproc_driver = {
. probe = omap_rproc_probe ,
2012-12-22 03:14:44 +04:00
. remove = omap_rproc_remove ,
2011-10-20 20:53:35 +04:00
. driver = {
. name = " omap-rproc " ,
} ,
} ;
2011-12-13 16:41:47 +04:00
module_platform_driver ( omap_rproc_driver ) ;
2011-10-20 20:53:35 +04:00
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_DESCRIPTION ( " OMAP Remote Processor control driver " ) ;