2014-11-03 11:07:40 -07:00
/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
2016-02-17 17:52:03 -07:00
*
* Description : CoreSight Replicator driver
2014-11-03 11:07:40 -07:00
*
* 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/kernel.h>
# include <linux/device.h>
# include <linux/platform_device.h>
# include <linux/io.h>
# include <linux/err.h>
# include <linux/slab.h>
2015-05-19 10:55:18 -06:00
# include <linux/pm_runtime.h>
2014-11-03 11:07:40 -07:00
# include <linux/clk.h>
# include <linux/of.h>
# include <linux/coresight.h>
# include "coresight-priv.h"
/**
* struct replicator_drvdata - specifics associated to a replicator component
* @ dev : the device entity associated with this component
2015-05-19 10:55:18 -06:00
* @ atclk : optional clock for the core parts of the replicator .
2014-11-03 11:07:40 -07:00
* @ csdev : component vitals needed by the framework
*/
struct replicator_drvdata {
struct device * dev ;
2015-05-19 10:55:18 -06:00
struct clk * atclk ;
2014-11-03 11:07:40 -07:00
struct coresight_device * csdev ;
} ;
static int replicator_enable ( struct coresight_device * csdev , int inport ,
int outport )
{
struct replicator_drvdata * drvdata = dev_get_drvdata ( csdev - > dev . parent ) ;
dev_info ( drvdata - > dev , " REPLICATOR enabled \n " ) ;
return 0 ;
}
static void replicator_disable ( struct coresight_device * csdev , int inport ,
int outport )
{
struct replicator_drvdata * drvdata = dev_get_drvdata ( csdev - > dev . parent ) ;
dev_info ( drvdata - > dev , " REPLICATOR disabled \n " ) ;
}
static const struct coresight_ops_link replicator_link_ops = {
. enable = replicator_enable ,
. disable = replicator_disable ,
} ;
static const struct coresight_ops replicator_cs_ops = {
. link_ops = & replicator_link_ops ,
} ;
static int replicator_probe ( struct platform_device * pdev )
{
2015-05-19 10:55:18 -06:00
int ret ;
2014-11-03 11:07:40 -07:00
struct device * dev = & pdev - > dev ;
struct coresight_platform_data * pdata = NULL ;
struct replicator_drvdata * drvdata ;
2016-08-25 15:19:05 -06:00
struct coresight_desc desc = { 0 } ;
2014-11-03 11:07:40 -07:00
struct device_node * np = pdev - > dev . of_node ;
if ( np ) {
pdata = of_get_coresight_platform_data ( dev , np ) ;
if ( IS_ERR ( pdata ) )
return PTR_ERR ( pdata ) ;
pdev - > dev . platform_data = pdata ;
}
drvdata = devm_kzalloc ( dev , sizeof ( * drvdata ) , GFP_KERNEL ) ;
if ( ! drvdata )
return - ENOMEM ;
drvdata - > dev = & pdev - > dev ;
2015-05-19 10:55:18 -06:00
drvdata - > atclk = devm_clk_get ( & pdev - > dev , " atclk " ) ; /* optional */
if ( ! IS_ERR ( drvdata - > atclk ) ) {
ret = clk_prepare_enable ( drvdata - > atclk ) ;
if ( ret )
return ret ;
}
pm_runtime_get_noresume ( & pdev - > dev ) ;
pm_runtime_set_active ( & pdev - > dev ) ;
pm_runtime_enable ( & pdev - > dev ) ;
2014-11-03 11:07:40 -07:00
platform_set_drvdata ( pdev , drvdata ) ;
2016-08-25 15:19:05 -06:00
desc . type = CORESIGHT_DEV_TYPE_LINK ;
desc . subtype . link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT ;
desc . ops = & replicator_cs_ops ;
desc . pdata = pdev - > dev . platform_data ;
desc . dev = & pdev - > dev ;
drvdata - > csdev = coresight_register ( & desc ) ;
2015-05-19 10:55:18 -06:00
if ( IS_ERR ( drvdata - > csdev ) ) {
ret = PTR_ERR ( drvdata - > csdev ) ;
goto out_disable_pm ;
}
pm_runtime_put ( & pdev - > dev ) ;
2014-11-03 11:07:40 -07:00
return 0 ;
2015-05-19 10:55:18 -06:00
out_disable_pm :
if ( ! IS_ERR ( drvdata - > atclk ) )
clk_disable_unprepare ( drvdata - > atclk ) ;
pm_runtime_put_noidle ( & pdev - > dev ) ;
pm_runtime_disable ( & pdev - > dev ) ;
return ret ;
2014-11-03 11:07:40 -07:00
}
2015-05-19 10:55:18 -06:00
# ifdef CONFIG_PM
static int replicator_runtime_suspend ( struct device * dev )
{
struct replicator_drvdata * drvdata = dev_get_drvdata ( dev ) ;
if ( drvdata & & ! IS_ERR ( drvdata - > atclk ) )
clk_disable_unprepare ( drvdata - > atclk ) ;
2014-11-03 11:07:40 -07:00
return 0 ;
}
2015-05-19 10:55:18 -06:00
static int replicator_runtime_resume ( struct device * dev )
{
struct replicator_drvdata * drvdata = dev_get_drvdata ( dev ) ;
if ( drvdata & & ! IS_ERR ( drvdata - > atclk ) )
clk_prepare_enable ( drvdata - > atclk ) ;
return 0 ;
}
# endif
static const struct dev_pm_ops replicator_dev_pm_ops = {
SET_RUNTIME_PM_OPS ( replicator_runtime_suspend ,
replicator_runtime_resume , NULL )
} ;
2015-03-16 20:20:33 +01:00
static const struct of_device_id replicator_match [ ] = {
2014-11-03 11:07:40 -07:00
{ . compatible = " arm,coresight-replicator " } ,
{ }
} ;
static struct platform_driver replicator_driver = {
. probe = replicator_probe ,
. driver = {
. name = " coresight-replicator " ,
. of_match_table = replicator_match ,
2015-05-19 10:55:18 -06:00
. pm = & replicator_dev_pm_ops ,
2016-02-02 14:14:00 -07:00
. suppress_bind_attrs = true ,
2014-11-03 11:07:40 -07:00
} ,
} ;
2015-07-31 09:37:23 -06:00
builtin_platform_driver ( replicator_driver ) ;