2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2017-04-03 17:48:29 +02:00
/*
* Copyright ( C ) 2017 Rafał Miłecki < rafal @ milecki . pl >
*/
# include <linux/module.h>
# include <linux/of_address.h>
# include <linux/platform_device.h>
# include <linux/thermal.h>
# define PVTMON_CONTROL0 0x00
# define PVTMON_CONTROL0_SEL_MASK 0x0000000e
# define PVTMON_CONTROL0_SEL_TEMP_MONITOR 0x00000000
# define PVTMON_CONTROL0_SEL_TEST_MODE 0x0000000e
# define PVTMON_STATUS 0x08
2022-08-05 00:43:26 +02:00
static int ns_thermal_get_temp ( struct thermal_zone_device * tz , int * temp )
2017-04-03 17:48:29 +02:00
{
2023-03-01 21:14:30 +01:00
void __iomem * pvtmon = thermal_zone_device_priv ( tz ) ;
2022-08-05 00:43:26 +02:00
int offset = thermal_zone_get_offset ( tz ) ;
int slope = thermal_zone_get_slope ( tz ) ;
2017-04-03 17:48:29 +02:00
u32 val ;
2022-08-05 00:43:26 +02:00
val = readl ( pvtmon + PVTMON_CONTROL0 ) ;
2017-04-03 17:48:29 +02:00
if ( ( val & PVTMON_CONTROL0_SEL_MASK ) ! = PVTMON_CONTROL0_SEL_TEMP_MONITOR ) {
/* Clear current mode selection */
val & = ~ PVTMON_CONTROL0_SEL_MASK ;
/* Set temp monitor mode (it's the default actually) */
val | = PVTMON_CONTROL0_SEL_TEMP_MONITOR ;
2022-08-05 00:43:26 +02:00
writel ( val , pvtmon + PVTMON_CONTROL0 ) ;
2017-04-03 17:48:29 +02:00
}
2022-08-05 00:43:26 +02:00
val = readl ( pvtmon + PVTMON_STATUS ) ;
2017-04-03 17:48:29 +02:00
* temp = slope * val + offset ;
return 0 ;
}
2022-08-05 00:43:26 +02:00
static const struct thermal_zone_device_ops ns_thermal_ops = {
2017-04-03 17:48:29 +02:00
. get_temp = ns_thermal_get_temp ,
} ;
static int ns_thermal_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
2022-08-05 00:43:26 +02:00
struct thermal_zone_device * tz ;
void __iomem * pvtmon ;
2017-04-03 17:48:29 +02:00
2022-08-05 00:43:26 +02:00
pvtmon = of_iomap ( dev_of_node ( dev ) , 0 ) ;
if ( WARN_ON ( ! pvtmon ) )
2017-04-03 17:48:29 +02:00
return - ENOENT ;
2022-08-05 00:43:26 +02:00
tz = devm_thermal_of_zone_register ( dev , 0 ,
pvtmon ,
& ns_thermal_ops ) ;
if ( IS_ERR ( tz ) ) {
iounmap ( pvtmon ) ;
return PTR_ERR ( tz ) ;
2017-04-03 17:48:29 +02:00
}
2022-08-05 00:43:26 +02:00
platform_set_drvdata ( pdev , pvtmon ) ;
2017-04-03 17:48:29 +02:00
return 0 ;
}
2023-09-27 21:37:09 +02:00
static void ns_thermal_remove ( struct platform_device * pdev )
2017-04-03 17:48:29 +02:00
{
2022-08-05 00:43:26 +02:00
void __iomem * pvtmon = platform_get_drvdata ( pdev ) ;
2017-04-03 17:48:29 +02:00
2022-08-05 00:43:26 +02:00
iounmap ( pvtmon ) ;
2017-04-03 17:48:29 +02:00
}
static const struct of_device_id ns_thermal_of_match [ ] = {
{ . compatible = " brcm,ns-thermal " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , ns_thermal_of_match ) ;
static struct platform_driver ns_thermal_driver = {
. probe = ns_thermal_probe ,
2023-09-27 21:37:09 +02:00
. remove_new = ns_thermal_remove ,
2017-04-03 17:48:29 +02:00
. driver = {
. name = " ns-thermal " ,
. of_match_table = ns_thermal_of_match ,
} ,
} ;
module_platform_driver ( ns_thermal_driver ) ;
2017-04-17 23:02:01 +02:00
MODULE_AUTHOR ( " Rafał Miłecki <rafal@milecki.pl> " ) ;
2017-04-03 17:48:29 +02:00
MODULE_DESCRIPTION ( " Northstar thermal driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;