2016-06-17 15:40:32 +03:00
/*
* Tegra ACONNECT Bus Driver
*
* Copyright ( C ) 2016 , NVIDIA CORPORATION . All rights reserved .
*
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
*/
# include <linux/clk.h>
# include <linux/module.h>
# include <linux/of_platform.h>
# include <linux/platform_device.h>
# include <linux/pm_runtime.h>
2019-03-13 07:41:58 +03:00
struct tegra_aconnect {
struct clk * ape_clk ;
struct clk * apb2ape_clk ;
} ;
2016-06-17 15:40:32 +03:00
static int tegra_aconnect_probe ( struct platform_device * pdev )
{
2019-03-13 07:41:58 +03:00
struct tegra_aconnect * aconnect ;
2016-06-17 15:40:32 +03:00
if ( ! pdev - > dev . of_node )
return - EINVAL ;
2019-03-13 07:41:58 +03:00
aconnect = devm_kzalloc ( & pdev - > dev , sizeof ( struct tegra_aconnect ) ,
GFP_KERNEL ) ;
if ( ! aconnect )
return - ENOMEM ;
2016-06-17 15:40:32 +03:00
2019-03-13 07:41:58 +03:00
aconnect - > ape_clk = devm_clk_get ( & pdev - > dev , " ape " ) ;
if ( IS_ERR ( aconnect - > ape_clk ) ) {
dev_err ( & pdev - > dev , " Can't retrieve ape clock \n " ) ;
return PTR_ERR ( aconnect - > ape_clk ) ;
}
2016-06-17 15:40:32 +03:00
2019-03-13 07:41:58 +03:00
aconnect - > apb2ape_clk = devm_clk_get ( & pdev - > dev , " apb2ape " ) ;
if ( IS_ERR ( aconnect - > apb2ape_clk ) ) {
dev_err ( & pdev - > dev , " Can't retrieve apb2ape clock \n " ) ;
return PTR_ERR ( aconnect - > apb2ape_clk ) ;
}
2016-06-17 15:40:32 +03:00
2019-03-13 07:41:58 +03:00
dev_set_drvdata ( & pdev - > dev , aconnect ) ;
2016-06-17 15:40:32 +03:00
pm_runtime_enable ( & pdev - > dev ) ;
of_platform_populate ( pdev - > dev . of_node , NULL , NULL , & pdev - > dev ) ;
dev_info ( & pdev - > dev , " Tegra ACONNECT bus registered \n " ) ;
return 0 ;
}
static int tegra_aconnect_remove ( struct platform_device * pdev )
{
pm_runtime_disable ( & pdev - > dev ) ;
return 0 ;
}
static int tegra_aconnect_runtime_resume ( struct device * dev )
{
2019-03-13 07:41:58 +03:00
struct tegra_aconnect * aconnect = dev_get_drvdata ( dev ) ;
int ret ;
ret = clk_prepare_enable ( aconnect - > ape_clk ) ;
if ( ret ) {
dev_err ( dev , " ape clk_enable failed: %d \n " , ret ) ;
return ret ;
}
ret = clk_prepare_enable ( aconnect - > apb2ape_clk ) ;
if ( ret ) {
clk_disable_unprepare ( aconnect - > ape_clk ) ;
dev_err ( dev , " apb2ape clk_enable failed: %d \n " , ret ) ;
return ret ;
}
return 0 ;
2016-06-17 15:40:32 +03:00
}
static int tegra_aconnect_runtime_suspend ( struct device * dev )
{
2019-03-13 07:41:58 +03:00
struct tegra_aconnect * aconnect = dev_get_drvdata ( dev ) ;
clk_disable_unprepare ( aconnect - > ape_clk ) ;
clk_disable_unprepare ( aconnect - > apb2ape_clk ) ;
return 0 ;
2016-06-17 15:40:32 +03:00
}
static const struct dev_pm_ops tegra_aconnect_pm_ops = {
SET_RUNTIME_PM_OPS ( tegra_aconnect_runtime_suspend ,
tegra_aconnect_runtime_resume , NULL )
2019-03-13 07:41:59 +03:00
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS ( pm_runtime_force_suspend ,
pm_runtime_force_resume )
2016-06-17 15:40:32 +03:00
} ;
static const struct of_device_id tegra_aconnect_of_match [ ] = {
{ . compatible = " nvidia,tegra210-aconnect " , } ,
{ }
} ;
MODULE_DEVICE_TABLE ( of , tegra_aconnect_of_match ) ;
static struct platform_driver tegra_aconnect_driver = {
. probe = tegra_aconnect_probe ,
. remove = tegra_aconnect_remove ,
. driver = {
. name = " tegra-aconnect " ,
. of_match_table = tegra_aconnect_of_match ,
. pm = & tegra_aconnect_pm_ops ,
} ,
} ;
module_platform_driver ( tegra_aconnect_driver ) ;
MODULE_DESCRIPTION ( " NVIDIA Tegra ACONNECT Bus Driver " ) ;
MODULE_AUTHOR ( " Jon Hunter <jonathanh@nvidia.com> " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;