2014-11-03 11:07:35 -07:00
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 and
* only 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/types.h>
# include <linux/err.h>
# include <linux/slab.h>
# include <linux/clk.h>
# include <linux/of.h>
# include <linux/of_address.h>
# include <linux/of_graph.h>
# include <linux/of_platform.h>
# include <linux/platform_device.h>
# include <linux/amba/bus.h>
# include <linux/coresight.h>
2015-03-30 14:13:34 -06:00
# include <linux/cpumask.h>
2014-11-03 11:07:35 -07:00
# include <asm/smp_plat.h>
static int of_dev_node_match ( struct device * dev , void * data )
{
return dev - > of_node = = data ;
}
static struct device *
of_coresight_get_endpoint_device ( struct device_node * endpoint )
{
struct device * dev = NULL ;
/*
2015-05-19 10:55:20 -06:00
* If we have a non - configurable replicator , it will be found on the
2014-11-03 11:07:35 -07:00
* platform bus .
*/
dev = bus_find_device ( & platform_bus_type , NULL ,
endpoint , of_dev_node_match ) ;
if ( dev )
return dev ;
/*
* We have a configurable component - circle through the AMBA bus
* looking for the device that matches the endpoint node .
*/
return bus_find_device ( & amba_bustype , NULL ,
endpoint , of_dev_node_match ) ;
}
2017-06-05 14:15:06 -06:00
static void of_coresight_get_ports ( const struct device_node * node ,
2014-11-03 11:07:35 -07:00
int * nr_inport , int * nr_outport )
{
struct device_node * ep = NULL ;
int in = 0 , out = 0 ;
do {
2014-12-01 13:32:32 +01:00
ep = of_graph_get_next_endpoint ( node , ep ) ;
2014-11-03 11:07:35 -07:00
if ( ! ep )
break ;
if ( of_property_read_bool ( ep , " slave-mode " ) )
in + + ;
else
out + + ;
} while ( ep ) ;
* nr_inport = in ;
* nr_outport = out ;
}
static int of_coresight_alloc_memory ( struct device * dev ,
struct coresight_platform_data * pdata )
{
/* List of output port on this component */
pdata - > outports = devm_kzalloc ( dev , pdata - > nr_outport *
sizeof ( * pdata - > outports ) ,
GFP_KERNEL ) ;
if ( ! pdata - > outports )
return - ENOMEM ;
2015-01-09 16:57:21 -07:00
/* Children connected to this component via @outports */
2016-02-17 17:51:43 -07:00
pdata - > child_names = devm_kzalloc ( dev , pdata - > nr_outport *
2014-11-03 11:07:35 -07:00
sizeof ( * pdata - > child_names ) ,
GFP_KERNEL ) ;
if ( ! pdata - > child_names )
return - ENOMEM ;
/* Port number on the child this component is connected to */
pdata - > child_ports = devm_kzalloc ( dev , pdata - > nr_outport *
sizeof ( * pdata - > child_ports ) ,
GFP_KERNEL ) ;
if ( ! pdata - > child_ports )
return - ENOMEM ;
return 0 ;
}
2017-06-05 14:15:15 -06:00
int of_coresight_get_cpu ( const struct device_node * node )
{
int cpu ;
2018-01-02 11:25:28 +00:00
struct device_node * dn ;
2017-06-05 14:15:15 -06:00
dn = of_parse_phandle ( node , " cpu " , 0 ) ;
/* Affinity defaults to CPU0 */
if ( ! dn )
return 0 ;
2018-01-02 11:25:28 +00:00
cpu = of_cpu_node_to_id ( dn ) ;
2017-06-05 14:15:15 -06:00
of_node_put ( dn ) ;
/* Affinity to CPU0 if no cpu nodes are found */
2018-01-02 11:25:28 +00:00
return ( cpu < 0 ) ? 0 : cpu ;
2017-06-05 14:15:15 -06:00
}
EXPORT_SYMBOL_GPL ( of_coresight_get_cpu ) ;
2017-06-05 14:15:06 -06:00
struct coresight_platform_data *
of_get_coresight_platform_data ( struct device * dev ,
const struct device_node * node )
2014-11-03 11:07:35 -07:00
{
2017-06-05 14:15:15 -06:00
int i = 0 , ret = 0 ;
2014-11-03 11:07:35 -07:00
struct coresight_platform_data * pdata ;
struct of_endpoint endpoint , rendpoint ;
struct device * rdev ;
struct device_node * ep = NULL ;
struct device_node * rparent = NULL ;
struct device_node * rport = NULL ;
pdata = devm_kzalloc ( dev , sizeof ( * pdata ) , GFP_KERNEL ) ;
if ( ! pdata )
return ERR_PTR ( - ENOMEM ) ;
2015-01-09 16:57:19 -07:00
/* Use device name as sysfs handle */
2014-11-03 11:07:35 -07:00
pdata - > name = dev_name ( dev ) ;
/* Get the number of input and output port for this component */
of_coresight_get_ports ( node , & pdata - > nr_inport , & pdata - > nr_outport ) ;
if ( pdata - > nr_outport ) {
ret = of_coresight_alloc_memory ( dev , pdata ) ;
if ( ret )
return ERR_PTR ( ret ) ;
/* Iterate through each port to discover topology */
do {
/* Get a handle on a port */
2014-12-01 13:32:32 +01:00
ep = of_graph_get_next_endpoint ( node , ep ) ;
2014-11-03 11:07:35 -07:00
if ( ! ep )
break ;
/*
* No need to deal with input ports , processing for as
* processing for output ports will deal with them .
*/
if ( of_find_property ( ep , " slave-mode " , NULL ) )
continue ;
/* Get a handle on the local endpoint */
ret = of_graph_parse_endpoint ( ep , & endpoint ) ;
if ( ret )
continue ;
/* The local out port number */
2017-03-27 11:09:33 -06:00
pdata - > outports [ i ] = endpoint . port ;
2014-11-03 11:07:35 -07:00
/*
* Get a handle on the remote port and parent
* attached to it .
*/
rparent = of_graph_get_remote_port_parent ( ep ) ;
rport = of_graph_get_remote_port ( ep ) ;
if ( ! rparent | | ! rport )
continue ;
if ( of_graph_parse_endpoint ( rport , & rendpoint ) )
continue ;
rdev = of_coresight_get_endpoint_device ( rparent ) ;
2015-01-09 16:57:22 -07:00
if ( ! rdev )
2016-08-25 15:19:01 -06:00
return ERR_PTR ( - EPROBE_DEFER ) ;
2014-11-03 11:07:35 -07:00
pdata - > child_names [ i ] = dev_name ( rdev ) ;
pdata - > child_ports [ i ] = rendpoint . id ;
i + + ;
} while ( ep ) ;
}
2017-06-05 14:15:15 -06:00
pdata - > cpu = of_coresight_get_cpu ( node ) ;
2017-06-05 14:15:14 -06:00
2014-11-03 11:07:35 -07:00
return pdata ;
}
EXPORT_SYMBOL_GPL ( of_get_coresight_platform_data ) ;