2019-05-29 17:17:56 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2010-04-23 07:30:13 +04:00
/*
* Copyright ( C ) 2010 Google , Inc .
*
* Author :
* Colin Cross < ccross @ google . com >
* Based on arch / arm / plat - omap / cpu - omap . c , ( C ) 2005 Nokia Corporation
*/
2020-03-19 22:02:26 +03:00
# include <linux/bits.h>
# include <linux/cpu.h>
2010-04-23 07:30:13 +04:00
# include <linux/err.h>
2018-05-18 23:06:34 +03:00
# include <linux/init.h>
# include <linux/module.h>
2020-03-19 22:02:26 +03:00
# include <linux/of_device.h>
2018-05-18 23:06:42 +03:00
# include <linux/platform_device.h>
2020-03-19 22:02:26 +03:00
# include <linux/pm_opp.h>
2018-05-18 23:06:34 +03:00
# include <linux/types.h>
2010-04-23 07:30:13 +04:00
2020-03-19 22:02:26 +03:00
# include <soc/tegra/common.h>
# include <soc/tegra/fuse.h>
2010-04-23 07:30:13 +04:00
2020-03-19 22:02:26 +03:00
static bool cpu0_node_has_opp_v2_prop ( void )
2014-06-02 21:19:29 +04:00
{
2020-03-19 22:02:26 +03:00
struct device_node * np = of_cpu_device_node_get ( 0 ) ;
bool ret = false ;
2014-06-02 21:19:29 +04:00
2020-03-19 22:02:26 +03:00
if ( of_get_property ( np , " operating-points-v2 " , NULL ) )
ret = true ;
2012-09-11 03:05:01 +04:00
2020-03-19 22:02:26 +03:00
of_node_put ( np ) ;
2012-09-11 03:05:01 +04:00
return ret ;
}
2021-01-18 02:18:25 +03:00
static void tegra20_cpufreq_put_supported_hw ( void * opp_table )
{
dev_pm_opp_put_supported_hw ( opp_table ) ;
}
static void tegra20_cpufreq_dt_unregister ( void * cpufreq_dt )
{
platform_device_unregister ( cpufreq_dt ) ;
}
2018-05-18 23:06:42 +03:00
static int tegra20_cpufreq_probe ( struct platform_device * pdev )
2010-04-23 07:30:13 +04:00
{
2020-03-19 22:02:26 +03:00
struct platform_device * cpufreq_dt ;
struct opp_table * opp_table ;
struct device * cpu_dev ;
u32 versions [ 2 ] ;
2018-05-18 23:06:36 +03:00
int err ;
2020-03-19 22:02:26 +03:00
if ( ! cpu0_node_has_opp_v2_prop ( ) ) {
dev_err ( & pdev - > dev , " operating points not found \n " ) ;
dev_err ( & pdev - > dev , " please update your device tree \n " ) ;
return - ENODEV ;
}
if ( of_machine_is_compatible ( " nvidia,tegra20 " ) ) {
versions [ 0 ] = BIT ( tegra_sku_info . cpu_process_id ) ;
versions [ 1 ] = BIT ( tegra_sku_info . soc_speedo_id ) ;
} else {
versions [ 0 ] = BIT ( tegra_sku_info . cpu_process_id ) ;
versions [ 1 ] = BIT ( tegra_sku_info . cpu_speedo_id ) ;
}
dev_info ( & pdev - > dev , " hardware version 0x%x 0x%x \n " ,
versions [ 0 ] , versions [ 1 ] ) ;
2018-05-18 23:06:40 +03:00
2020-03-19 22:02:26 +03:00
cpu_dev = get_cpu_device ( 0 ) ;
if ( WARN_ON ( ! cpu_dev ) )
return - ENODEV ;
2012-12-21 04:09:55 +04:00
2020-03-19 22:02:26 +03:00
opp_table = dev_pm_opp_set_supported_hw ( cpu_dev , versions , 2 ) ;
err = PTR_ERR_OR_ZERO ( opp_table ) ;
if ( err ) {
dev_err ( & pdev - > dev , " failed to set supported hw: %d \n " , err ) ;
return err ;
2018-05-18 23:06:36 +03:00
}
2012-12-21 04:09:55 +04:00
2021-01-18 02:18:25 +03:00
err = devm_add_action_or_reset ( & pdev - > dev ,
tegra20_cpufreq_put_supported_hw ,
opp_table ) ;
if ( err )
return err ;
2020-03-19 22:02:26 +03:00
cpufreq_dt = platform_device_register_simple ( " cpufreq-dt " , - 1 , NULL , 0 ) ;
err = PTR_ERR_OR_ZERO ( cpufreq_dt ) ;
if ( err ) {
dev_err ( & pdev - > dev ,
" failed to create cpufreq-dt device: %d \n " , err ) ;
2021-01-18 02:18:25 +03:00
return err ;
2018-05-18 23:06:36 +03:00
}
2021-01-18 02:18:25 +03:00
err = devm_add_action_or_reset ( & pdev - > dev ,
tegra20_cpufreq_dt_unregister ,
cpufreq_dt ) ;
if ( err )
return err ;
2018-05-18 23:06:42 +03:00
return 0 ;
2010-04-23 07:30:13 +04:00
}
2018-05-18 23:06:42 +03:00
static struct platform_driver tegra20_cpufreq_driver = {
. probe = tegra20_cpufreq_probe ,
. driver = {
. name = " tegra20-cpufreq " ,
} ,
} ;
module_platform_driver ( tegra20_cpufreq_driver ) ;
MODULE_ALIAS ( " platform:tegra20-cpufreq " ) ;
2010-04-23 07:30:13 +04:00
MODULE_AUTHOR ( " Colin Cross <ccross@android.com> " ) ;
2018-05-18 23:06:32 +03:00
MODULE_DESCRIPTION ( " NVIDIA Tegra20 cpufreq driver " ) ;
2010-04-23 07:30:13 +04:00
MODULE_LICENSE ( " GPL " ) ;