2020-03-20 10:52:52 -06:00
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright ( c ) 2018 Linaro Limited , All rights reserved .
* Author : Mike Leach < mike . leach @ linaro . org >
*/
2020-03-20 10:52:59 -06:00
# include <linux/property.h>
2020-03-20 10:52:52 -06:00
# include "coresight-cti.h"
/**
* CTI devices can be associated with a PE , or be connected to CoreSight
* hardware . We have a list of all CTIs irrespective of CPU bound or
* otherwise .
*
* We assume that the non - CPU CTIs are always powered as we do with sinks etc .
*
* We leave the client to figure out if all the CTIs are interconnected with
* the same CTM , in general this is the case but does not always have to be .
*/
/* net of CTI devices connected via CTM */
LIST_HEAD ( ect_net ) ;
/* protect the list */
static DEFINE_MUTEX ( ect_mutex ) ;
# define csdev_to_cti_drvdata(csdev) \
dev_get_drvdata ( csdev - > dev . parent )
/*
* CTI naming . CTI bound to cores will have the name cti_cpu < N > where
* N is the CPU ID . System CTIs will have the name cti_sys < I > where I
* is an index allocated by order of discovery .
*
* CTI device name list - for CTI not bound to cores .
*/
DEFINE_CORESIGHT_DEVLIST ( cti_sys_devs , " cti_sys " ) ;
/* write set of regs to hardware - call with spinlock claimed */
void cti_write_all_hw_regs ( struct cti_drvdata * drvdata )
{
struct cti_config * config = & drvdata - > config ;
int i ;
CS_UNLOCK ( drvdata - > base ) ;
/* disable CTI before writing registers */
writel_relaxed ( 0 , drvdata - > base + CTICONTROL ) ;
/* write the CTI trigger registers */
for ( i = 0 ; i < config - > nr_trig_max ; i + + ) {
writel_relaxed ( config - > ctiinen [ i ] , drvdata - > base + CTIINEN ( i ) ) ;
writel_relaxed ( config - > ctiouten [ i ] ,
drvdata - > base + CTIOUTEN ( i ) ) ;
}
/* other regs */
writel_relaxed ( config - > ctigate , drvdata - > base + CTIGATE ) ;
writel_relaxed ( config - > asicctl , drvdata - > base + ASICCTL ) ;
writel_relaxed ( config - > ctiappset , drvdata - > base + CTIAPPSET ) ;
/* re-enable CTI */
writel_relaxed ( 1 , drvdata - > base + CTICONTROL ) ;
CS_LOCK ( drvdata - > base ) ;
}
static void cti_enable_hw_smp_call ( void * info )
{
struct cti_drvdata * drvdata = info ;
cti_write_all_hw_regs ( drvdata ) ;
}
/* write regs to hardware and enable */
static int cti_enable_hw ( struct cti_drvdata * drvdata )
{
struct cti_config * config = & drvdata - > config ;
struct device * dev = & drvdata - > csdev - > dev ;
int rc = 0 ;
pm_runtime_get_sync ( dev - > parent ) ;
spin_lock ( & drvdata - > spinlock ) ;
/* no need to do anything if enabled or unpowered*/
if ( config - > hw_enabled | | ! config - > hw_powered )
goto cti_state_unchanged ;
/* claim the device */
rc = coresight_claim_device ( drvdata - > base ) ;
if ( rc )
goto cti_err_not_enabled ;
if ( drvdata - > ctidev . cpu > = 0 ) {
rc = smp_call_function_single ( drvdata - > ctidev . cpu ,
cti_enable_hw_smp_call ,
drvdata , 1 ) ;
if ( rc )
goto cti_err_not_enabled ;
} else {
cti_write_all_hw_regs ( drvdata ) ;
}
config - > hw_enabled = true ;
atomic_inc ( & drvdata - > config . enable_req_count ) ;
spin_unlock ( & drvdata - > spinlock ) ;
return rc ;
cti_state_unchanged :
atomic_inc ( & drvdata - > config . enable_req_count ) ;
/* cannot enable due to error */
cti_err_not_enabled :
spin_unlock ( & drvdata - > spinlock ) ;
pm_runtime_put ( dev - > parent ) ;
return rc ;
}
/* disable hardware */
static int cti_disable_hw ( struct cti_drvdata * drvdata )
{
struct cti_config * config = & drvdata - > config ;
struct device * dev = & drvdata - > csdev - > dev ;
spin_lock ( & drvdata - > spinlock ) ;
/* check refcount - disable on 0 */
if ( atomic_dec_return ( & drvdata - > config . enable_req_count ) > 0 )
goto cti_not_disabled ;
/* no need to do anything if disabled or cpu unpowered */
if ( ! config - > hw_enabled | | ! config - > hw_powered )
goto cti_not_disabled ;
CS_UNLOCK ( drvdata - > base ) ;
/* disable CTI */
writel_relaxed ( 0 , drvdata - > base + CTICONTROL ) ;
config - > hw_enabled = false ;
coresight_disclaim_device_unlocked ( drvdata - > base ) ;
CS_LOCK ( drvdata - > base ) ;
spin_unlock ( & drvdata - > spinlock ) ;
pm_runtime_put ( dev ) ;
return 0 ;
/* not disabled this call */
cti_not_disabled :
spin_unlock ( & drvdata - > spinlock ) ;
return 0 ;
}
2020-03-20 10:52:54 -06:00
void cti_write_single_reg ( struct cti_drvdata * drvdata , int offset , u32 value )
{
CS_UNLOCK ( drvdata - > base ) ;
writel_relaxed ( value , drvdata - > base + offset ) ;
CS_LOCK ( drvdata - > base ) ;
}
void cti_write_intack ( struct device * dev , u32 ackval )
{
struct cti_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
struct cti_config * config = & drvdata - > config ;
spin_lock ( & drvdata - > spinlock ) ;
/* write if enabled */
if ( cti_active ( config ) )
cti_write_single_reg ( drvdata , CTIINTACK , ackval ) ;
spin_unlock ( & drvdata - > spinlock ) ;
}
2020-03-20 10:52:52 -06:00
/*
* Look at the HW DEVID register for some of the HW settings .
* DEVID [ 15 : 8 ] - max number of in / out triggers .
*/
# define CTI_DEVID_MAXTRIGS(devid_val) ((int) BMVAL(devid_val, 8, 15))
/* DEVID[19:16] - number of CTM channels */
# define CTI_DEVID_CTMCHANNELS(devid_val) ((int) BMVAL(devid_val, 16, 19))
static void cti_set_default_config ( struct device * dev ,
struct cti_drvdata * drvdata )
{
struct cti_config * config = & drvdata - > config ;
u32 devid ;
devid = readl_relaxed ( drvdata - > base + CORESIGHT_DEVID ) ;
config - > nr_trig_max = CTI_DEVID_MAXTRIGS ( devid ) ;
/*
* no current hardware should exceed this , but protect the driver
* in case of fault / out of spec hw
*/
if ( config - > nr_trig_max > CTIINOUTEN_MAX ) {
dev_warn_once ( dev ,
" Limiting HW MaxTrig value(%d) to driver max(%d) \n " ,
config - > nr_trig_max , CTIINOUTEN_MAX ) ;
config - > nr_trig_max = CTIINOUTEN_MAX ;
}
config - > nr_ctm_channels = CTI_DEVID_CTMCHANNELS ( devid ) ;
/* Most regs default to 0 as zalloc'ed except...*/
config - > trig_filter_enable = true ;
config - > ctigate = GENMASK ( config - > nr_ctm_channels - 1 , 0 ) ;
atomic_set ( & config - > enable_req_count , 0 ) ;
}
/*
* Add a connection entry to the list of connections for this
* CTI device .
*/
int cti_add_connection_entry ( struct device * dev , struct cti_drvdata * drvdata ,
struct cti_trig_con * tc ,
struct coresight_device * csdev ,
const char * assoc_dev_name )
{
struct cti_device * cti_dev = & drvdata - > ctidev ;
tc - > con_dev = csdev ;
/*
* Prefer actual associated CS device dev name to supplied value -
* which is likely to be node name / other conn name .
*/
if ( csdev )
tc - > con_dev_name = dev_name ( & csdev - > dev ) ;
else if ( assoc_dev_name ! = NULL ) {
tc - > con_dev_name = devm_kstrdup ( dev ,
assoc_dev_name , GFP_KERNEL ) ;
if ( ! tc - > con_dev_name )
return - ENOMEM ;
}
list_add_tail ( & tc - > node , & cti_dev - > trig_cons ) ;
cti_dev - > nr_trig_con + + ;
/* add connection usage bit info to overall info */
drvdata - > config . trig_in_use | = tc - > con_in - > used_mask ;
drvdata - > config . trig_out_use | = tc - > con_out - > used_mask ;
return 0 ;
}
/* create a trigger connection with appropriately sized signal groups */
struct cti_trig_con * cti_allocate_trig_con ( struct device * dev , int in_sigs ,
int out_sigs )
{
struct cti_trig_con * tc = NULL ;
struct cti_trig_grp * in = NULL , * out = NULL ;
tc = devm_kzalloc ( dev , sizeof ( struct cti_trig_con ) , GFP_KERNEL ) ;
if ( ! tc )
return tc ;
in = devm_kzalloc ( dev ,
offsetof ( struct cti_trig_grp , sig_types [ in_sigs ] ) ,
GFP_KERNEL ) ;
if ( ! in )
return NULL ;
out = devm_kzalloc ( dev ,
offsetof ( struct cti_trig_grp , sig_types [ out_sigs ] ) ,
GFP_KERNEL ) ;
if ( ! out )
return NULL ;
tc - > con_in = in ;
tc - > con_out = out ;
tc - > con_in - > nr_sigs = in_sigs ;
tc - > con_out - > nr_sigs = out_sigs ;
return tc ;
}
/*
* Add a default connection if nothing else is specified .
* single connection based on max in / out info , no assoc device
*/
int cti_add_default_connection ( struct device * dev , struct cti_drvdata * drvdata )
{
int ret = 0 ;
int n_trigs = drvdata - > config . nr_trig_max ;
u32 n_trig_mask = GENMASK ( n_trigs - 1 , 0 ) ;
struct cti_trig_con * tc = NULL ;
/*
* Assume max trigs for in and out ,
* all used , default sig types allocated
*/
tc = cti_allocate_trig_con ( dev , n_trigs , n_trigs ) ;
if ( ! tc )
return - ENOMEM ;
tc - > con_in - > used_mask = n_trig_mask ;
tc - > con_out - > used_mask = n_trig_mask ;
ret = cti_add_connection_entry ( dev , drvdata , tc , NULL , " default " ) ;
return ret ;
}
2020-03-20 10:52:55 -06:00
/** cti channel api **/
/* attach/detach channel from trigger - write through if enabled. */
int cti_channel_trig_op ( struct device * dev , enum cti_chan_op op ,
enum cti_trig_dir direction , u32 channel_idx ,
u32 trigger_idx )
{
struct cti_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
struct cti_config * config = & drvdata - > config ;
u32 trig_bitmask ;
u32 chan_bitmask ;
u32 reg_value ;
int reg_offset ;
/* ensure indexes in range */
if ( ( channel_idx > = config - > nr_ctm_channels ) | |
( trigger_idx > = config - > nr_trig_max ) )
return - EINVAL ;
trig_bitmask = BIT ( trigger_idx ) ;
/* ensure registered triggers and not out filtered */
if ( direction = = CTI_TRIG_IN ) {
if ( ! ( trig_bitmask & config - > trig_in_use ) )
return - EINVAL ;
} else {
if ( ! ( trig_bitmask & config - > trig_out_use ) )
return - EINVAL ;
if ( ( config - > trig_filter_enable ) & &
( config - > trig_out_filter & trig_bitmask ) )
return - EINVAL ;
}
/* update the local register values */
chan_bitmask = BIT ( channel_idx ) ;
reg_offset = ( direction = = CTI_TRIG_IN ? CTIINEN ( trigger_idx ) :
CTIOUTEN ( trigger_idx ) ) ;
spin_lock ( & drvdata - > spinlock ) ;
/* read - modify write - the trigger / channel enable value */
reg_value = direction = = CTI_TRIG_IN ? config - > ctiinen [ trigger_idx ] :
config - > ctiouten [ trigger_idx ] ;
if ( op = = CTI_CHAN_ATTACH )
reg_value | = chan_bitmask ;
else
reg_value & = ~ chan_bitmask ;
/* write local copy */
if ( direction = = CTI_TRIG_IN )
config - > ctiinen [ trigger_idx ] = reg_value ;
else
config - > ctiouten [ trigger_idx ] = reg_value ;
/* write through if enabled */
if ( cti_active ( config ) )
cti_write_single_reg ( drvdata , reg_offset , reg_value ) ;
spin_unlock ( & drvdata - > spinlock ) ;
return 0 ;
}
int cti_channel_gate_op ( struct device * dev , enum cti_chan_gate_op op ,
u32 channel_idx )
{
struct cti_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
struct cti_config * config = & drvdata - > config ;
u32 chan_bitmask ;
u32 reg_value ;
int err = 0 ;
if ( channel_idx > = config - > nr_ctm_channels )
return - EINVAL ;
chan_bitmask = BIT ( channel_idx ) ;
spin_lock ( & drvdata - > spinlock ) ;
reg_value = config - > ctigate ;
switch ( op ) {
case CTI_GATE_CHAN_ENABLE :
reg_value | = chan_bitmask ;
break ;
case CTI_GATE_CHAN_DISABLE :
reg_value & = ~ chan_bitmask ;
break ;
default :
err = - EINVAL ;
break ;
}
if ( err = = 0 ) {
config - > ctigate = reg_value ;
if ( cti_active ( config ) )
cti_write_single_reg ( drvdata , CTIGATE , reg_value ) ;
}
spin_unlock ( & drvdata - > spinlock ) ;
return err ;
}
int cti_channel_setop ( struct device * dev , enum cti_chan_set_op op ,
u32 channel_idx )
{
struct cti_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
struct cti_config * config = & drvdata - > config ;
u32 chan_bitmask ;
u32 reg_value ;
u32 reg_offset ;
int err = 0 ;
if ( channel_idx > = config - > nr_ctm_channels )
return - EINVAL ;
chan_bitmask = BIT ( channel_idx ) ;
spin_lock ( & drvdata - > spinlock ) ;
reg_value = config - > ctiappset ;
switch ( op ) {
case CTI_CHAN_SET :
config - > ctiappset | = chan_bitmask ;
reg_value = config - > ctiappset ;
reg_offset = CTIAPPSET ;
break ;
case CTI_CHAN_CLR :
config - > ctiappset & = ~ chan_bitmask ;
reg_value = chan_bitmask ;
reg_offset = CTIAPPCLEAR ;
break ;
case CTI_CHAN_PULSE :
config - > ctiappset & = ~ chan_bitmask ;
reg_value = chan_bitmask ;
reg_offset = CTIAPPPULSE ;
break ;
default :
err = - EINVAL ;
break ;
}
if ( ( err = = 0 ) & & cti_active ( config ) )
cti_write_single_reg ( drvdata , reg_offset , reg_value ) ;
spin_unlock ( & drvdata - > spinlock ) ;
return err ;
}
2020-03-20 10:52:59 -06:00
/*
* Look for a matching connection device name in the list of connections .
* If found then swap in the csdev name , set trig con association pointer
* and return found .
*/
static bool
cti_match_fixup_csdev ( struct cti_device * ctidev , const char * node_name ,
struct coresight_device * csdev )
{
struct cti_trig_con * tc ;
list_for_each_entry ( tc , & ctidev - > trig_cons , node ) {
if ( tc - > con_dev_name ) {
if ( ! strcmp ( node_name , tc - > con_dev_name ) ) {
/* match: so swap in csdev name & dev */
tc - > con_dev_name = dev_name ( & csdev - > dev ) ;
tc - > con_dev = csdev ;
return true ;
}
}
}
return false ;
}
/*
* Search the cti list to add an associated CTI into the supplied CS device
* This will set the association if CTI declared before the CS device .
* ( called from coresight_register ( ) with coresight_mutex locked ) .
*/
void cti_add_assoc_to_csdev ( struct coresight_device * csdev )
{
struct cti_drvdata * ect_item ;
struct cti_device * ctidev ;
const char * node_name = NULL ;
/* protect the list */
mutex_lock ( & ect_mutex ) ;
/* exit if current is an ECT device.*/
if ( ( csdev - > type = = CORESIGHT_DEV_TYPE_ECT ) | | list_empty ( & ect_net ) )
goto cti_add_done ;
/* if we didn't find the csdev previously we used the fwnode name */
node_name = cti_plat_get_node_name ( dev_fwnode ( csdev - > dev . parent ) ) ;
if ( ! node_name )
goto cti_add_done ;
/* for each CTI in list... */
list_for_each_entry ( ect_item , & ect_net , node ) {
ctidev = & ect_item - > ctidev ;
if ( cti_match_fixup_csdev ( ctidev , node_name , csdev ) ) {
/*
* if we found a matching csdev then update the ECT
* association pointer for the device with this CTI .
*/
csdev - > ect_dev = ect_item - > csdev ;
break ;
}
}
cti_add_done :
mutex_unlock ( & ect_mutex ) ;
}
EXPORT_SYMBOL_GPL ( cti_add_assoc_to_csdev ) ;
/*
* Removing the associated devices is easier .
* A CTI will not have a value for csdev - > ect_dev .
*/
void cti_remove_assoc_from_csdev ( struct coresight_device * csdev )
{
struct cti_drvdata * ctidrv ;
struct cti_trig_con * tc ;
struct cti_device * ctidev ;
mutex_lock ( & ect_mutex ) ;
if ( csdev - > ect_dev ) {
ctidrv = csdev_to_cti_drvdata ( csdev - > ect_dev ) ;
ctidev = & ctidrv - > ctidev ;
list_for_each_entry ( tc , & ctidev - > trig_cons , node ) {
if ( tc - > con_dev = = csdev - > ect_dev ) {
tc - > con_dev = NULL ;
break ;
}
}
csdev - > ect_dev = NULL ;
}
mutex_unlock ( & ect_mutex ) ;
}
EXPORT_SYMBOL_GPL ( cti_remove_assoc_from_csdev ) ;
/*
* Update the cross references where the associated device was found
* while we were building the connection info . This will occur if the
* assoc device was registered before the CTI .
*/
static void cti_update_conn_xrefs ( struct cti_drvdata * drvdata )
{
struct cti_trig_con * tc ;
struct cti_device * ctidev = & drvdata - > ctidev ;
list_for_each_entry ( tc , & ctidev - > trig_cons , node ) {
if ( tc - > con_dev )
/* set tc->con_dev->ect_dev */
coresight_set_assoc_ectdev_mutex ( tc - > con_dev ,
drvdata - > csdev ) ;
}
}
static void cti_remove_conn_xrefs ( struct cti_drvdata * drvdata )
{
struct cti_trig_con * tc ;
struct cti_device * ctidev = & drvdata - > ctidev ;
list_for_each_entry ( tc , & ctidev - > trig_cons , node ) {
if ( tc - > con_dev ) {
coresight_set_assoc_ectdev_mutex ( tc - > con_dev ,
NULL ) ;
}
}
}
2020-03-20 10:52:52 -06:00
/** cti ect operations **/
int cti_enable ( struct coresight_device * csdev )
{
struct cti_drvdata * drvdata = csdev_to_cti_drvdata ( csdev ) ;
return cti_enable_hw ( drvdata ) ;
}
int cti_disable ( struct coresight_device * csdev )
{
struct cti_drvdata * drvdata = csdev_to_cti_drvdata ( csdev ) ;
return cti_disable_hw ( drvdata ) ;
}
const struct coresight_ops_ect cti_ops_ect = {
. enable = cti_enable ,
. disable = cti_disable ,
} ;
const struct coresight_ops cti_ops = {
. ect_ops = & cti_ops_ect ,
} ;
/*
* Free up CTI specific resources
* called by dev - > release , need to call down to underlying csdev release .
*/
static void cti_device_release ( struct device * dev )
{
struct cti_drvdata * drvdata = dev_get_drvdata ( dev - > parent ) ;
struct cti_drvdata * ect_item , * ect_tmp ;
mutex_lock ( & ect_mutex ) ;
2020-03-20 10:52:59 -06:00
cti_remove_conn_xrefs ( drvdata ) ;
2020-03-20 10:52:52 -06:00
/* remove from the list */
list_for_each_entry_safe ( ect_item , ect_tmp , & ect_net , node ) {
if ( ect_item = = drvdata ) {
list_del ( & ect_item - > node ) ;
break ;
}
}
mutex_unlock ( & ect_mutex ) ;
if ( drvdata - > csdev_release )
drvdata - > csdev_release ( dev ) ;
}
static int cti_probe ( struct amba_device * adev , const struct amba_id * id )
{
int ret = 0 ;
void __iomem * base ;
struct device * dev = & adev - > dev ;
struct cti_drvdata * drvdata = NULL ;
struct coresight_desc cti_desc ;
struct coresight_platform_data * pdata = NULL ;
struct resource * res = & adev - > res ;
/* driver data*/
drvdata = devm_kzalloc ( dev , sizeof ( * drvdata ) , GFP_KERNEL ) ;
if ( ! drvdata ) {
ret = - ENOMEM ;
dev_info ( dev , " %s, mem err \n " , __func__ ) ;
goto err_out ;
}
/* Validity for the resource is already checked by the AMBA core */
base = devm_ioremap_resource ( dev , res ) ;
if ( IS_ERR ( base ) ) {
ret = PTR_ERR ( base ) ;
dev_err ( dev , " %s, remap err \n " , __func__ ) ;
goto err_out ;
}
drvdata - > base = base ;
dev_set_drvdata ( dev , drvdata ) ;
/* default CTI device info */
drvdata - > ctidev . cpu = - 1 ;
drvdata - > ctidev . nr_trig_con = 0 ;
drvdata - > ctidev . ctm_id = 0 ;
INIT_LIST_HEAD ( & drvdata - > ctidev . trig_cons ) ;
spin_lock_init ( & drvdata - > spinlock ) ;
/* initialise CTI driver config values */
cti_set_default_config ( dev , drvdata ) ;
pdata = coresight_cti_get_platform_data ( dev ) ;
if ( IS_ERR ( pdata ) ) {
dev_err ( dev , " coresight_cti_get_platform_data err \n " ) ;
ret = PTR_ERR ( pdata ) ;
goto err_out ;
}
/* default to powered - could change on PM notifications */
drvdata - > config . hw_powered = true ;
/* set up device name - will depend if cpu bound or otherwise */
if ( drvdata - > ctidev . cpu > = 0 )
cti_desc . name = devm_kasprintf ( dev , GFP_KERNEL , " cti_cpu%d " ,
drvdata - > ctidev . cpu ) ;
else
cti_desc . name = coresight_alloc_device_name ( & cti_sys_devs , dev ) ;
if ( ! cti_desc . name ) {
ret = - ENOMEM ;
goto err_out ;
}
2020-03-20 10:53:00 -06:00
/* create dynamic attributes for connections */
ret = cti_create_cons_sysfs ( dev , drvdata ) ;
if ( ret ) {
dev_err ( dev , " %s: create dynamic sysfs entries failed \n " ,
cti_desc . name ) ;
goto err_out ;
}
2020-03-20 10:52:52 -06:00
/* set up coresight component description */
cti_desc . pdata = pdata ;
cti_desc . type = CORESIGHT_DEV_TYPE_ECT ;
cti_desc . subtype . ect_subtype = CORESIGHT_DEV_SUBTYPE_ECT_CTI ;
cti_desc . ops = & cti_ops ;
2020-03-20 10:53:00 -06:00
cti_desc . groups = drvdata - > ctidev . con_groups ;
2020-03-20 10:52:52 -06:00
cti_desc . dev = dev ;
drvdata - > csdev = coresight_register ( & cti_desc ) ;
if ( IS_ERR ( drvdata - > csdev ) ) {
ret = PTR_ERR ( drvdata - > csdev ) ;
goto err_out ;
}
/* add to list of CTI devices */
mutex_lock ( & ect_mutex ) ;
list_add ( & drvdata - > node , & ect_net ) ;
2020-03-20 10:52:59 -06:00
/* set any cross references */
cti_update_conn_xrefs ( drvdata ) ;
2020-03-20 10:52:52 -06:00
mutex_unlock ( & ect_mutex ) ;
/* set up release chain */
drvdata - > csdev_release = drvdata - > csdev - > dev . release ;
drvdata - > csdev - > dev . release = cti_device_release ;
/* all done - dec pm refcount */
pm_runtime_put ( & adev - > dev ) ;
dev_info ( & drvdata - > csdev - > dev , " CTI initialized \n " ) ;
return 0 ;
err_out :
return ret ;
}
static struct amba_cs_uci_id uci_id_cti [ ] = {
{
/* CTI UCI data */
. devarch = 0x47701a14 , /* CTI v2 */
. devarch_mask = 0xfff0ffff ,
. devtype = 0x00000014 , /* maj(0x4-debug) min(0x1-ECT) */
}
} ;
static const struct amba_id cti_ids [ ] = {
CS_AMBA_ID ( 0x000bb906 ) , /* Coresight CTI (SoC 400), C-A72, C-A57 */
CS_AMBA_ID ( 0x000bb922 ) , /* CTI - C-A8 */
CS_AMBA_ID ( 0x000bb9a8 ) , /* CTI - C-A53 */
CS_AMBA_ID ( 0x000bb9aa ) , /* CTI - C-A73 */
CS_AMBA_UCI_ID ( 0x000bb9da , uci_id_cti ) , /* CTI - C-A35 */
CS_AMBA_UCI_ID ( 0x000bb9ed , uci_id_cti ) , /* Coresight CTI (SoC 600) */
{ 0 , 0 } ,
} ;
static struct amba_driver cti_driver = {
. drv = {
. name = " coresight-cti " ,
. owner = THIS_MODULE ,
. suppress_bind_attrs = true ,
} ,
. probe = cti_probe ,
. id_table = cti_ids ,
} ;
builtin_amba_driver ( cti_driver ) ;