2019-05-29 17:18:02 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2014-11-24 07:58:59 +03:00
/*
2016-04-18 06:35:58 +03:00
* Copyright ( c ) 2014 - 2016 , Fuzhou Rockchip Electronics Co . , Ltd
2015-11-09 07:48:59 +03:00
* Caesar Wang < wxt @ rock - chips . com >
2014-11-24 07:58:59 +03:00
*/
# include <linux/clk.h>
# include <linux/delay.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/module.h>
# include <linux/of.h>
# include <linux/of_address.h>
# include <linux/of_irq.h>
# include <linux/platform_device.h>
2016-04-18 06:35:56 +03:00
# include <linux/regmap.h>
2014-11-24 07:58:59 +03:00
# include <linux/reset.h>
# include <linux/thermal.h>
2016-04-18 06:35:56 +03:00
# include <linux/mfd/syscon.h>
2015-11-12 06:43:11 +03:00
# include <linux/pinctrl/consumer.h>
2014-11-24 07:58:59 +03:00
2019-11-20 18:45:16 +03:00
/*
2014-11-24 07:58:59 +03:00
* If the temperature over a period of time High ,
* the resulting TSHUT gave CRU module , let it reset the entire chip ,
* or via GPIO give PMIC .
*/
enum tshut_mode {
TSHUT_MODE_CRU = 0 ,
TSHUT_MODE_GPIO ,
} ;
2019-11-20 18:45:16 +03:00
/*
2015-12-03 11:48:39 +03:00
* The system Temperature Sensors tshut ( tshut ) polarity
2014-11-24 07:58:59 +03:00
* the bit 8 is tshut polarity .
* 0 : low active , 1 : high active
*/
enum tshut_polarity {
TSHUT_LOW_ACTIVE = 0 ,
TSHUT_HIGH_ACTIVE ,
} ;
2019-11-20 18:45:16 +03:00
/*
2015-12-03 11:48:39 +03:00
* The conversion table has the adc value and temperature .
2016-02-15 10:33:30 +03:00
* ADC_DECREMENT : the adc value is of diminishing . ( e . g . rk3288_code_table )
* ADC_INCREMENT : the adc value is incremental . ( e . g . rk3368_code_table )
2015-12-03 11:48:39 +03:00
*/
2015-11-09 07:48:57 +03:00
enum adc_sort_mode {
ADC_DECREMENT = 0 ,
ADC_INCREMENT ,
} ;
2019-12-12 09:17:02 +03:00
# include "thermal_hwmon.h"
2015-12-03 11:48:39 +03:00
/**
2016-04-18 06:35:58 +03:00
* struct chip_tsadc_table - hold information about chip - specific differences
2015-12-03 11:48:39 +03:00
* @ id : conversion table
* @ length : size of conversion table
* @ data_mask : mask to apply on data inputs
* @ mode : sort mode of this adc variant ( incrementing or decrementing )
*/
2015-11-09 07:48:56 +03:00
struct chip_tsadc_table {
const struct tsadc_table * id ;
unsigned int length ;
u32 data_mask ;
2015-11-09 07:48:57 +03:00
enum adc_sort_mode mode ;
2015-11-09 07:48:56 +03:00
} ;
2016-04-18 06:35:58 +03:00
/**
* struct rockchip_tsadc_chip - hold the private data of tsadc chip
2023-03-08 14:22:50 +03:00
* @ chn_offset : the channel offset of the first channel
2016-04-18 06:35:58 +03:00
* @ chn_num : the channel number of tsadc chip
* @ tshut_temp : the hardware - controlled shutdown temperature value
* @ tshut_mode : the hardware - controlled shutdown mode ( 0 : CRU 1 : GPIO )
* @ tshut_polarity : the hardware - controlled active polarity ( 0 : LOW 1 : HIGH )
* @ initialize : SoC special initialize tsadc controller method
* @ irq_ack : clear the interrupt
2019-11-20 18:45:16 +03:00
* @ control : enable / disable method for the tsadc controller
2016-04-18 06:35:58 +03:00
* @ get_temp : get the temperature
2016-06-22 11:42:05 +03:00
* @ set_alarm_temp : set the high temperature interrupt
2016-04-18 06:35:58 +03:00
* @ set_tshut_temp : set the hardware - controlled shutdown temperature
* @ set_tshut_mode : set the hardware - controlled shutdown mode
* @ table : the chip - specific conversion table
*/
2014-11-24 07:58:59 +03:00
struct rockchip_tsadc_chip {
2015-11-05 08:17:58 +03:00
/* The sensor id of chip correspond to the ADC channel */
2023-03-08 14:22:50 +03:00
int chn_offset ;
2015-11-05 08:17:58 +03:00
int chn_num ;
2014-11-24 07:58:59 +03:00
/* The hardware-controlled tshut property */
2015-11-09 07:48:58 +03:00
int tshut_temp ;
2014-11-24 07:58:59 +03:00
enum tshut_mode tshut_mode ;
enum tshut_polarity tshut_polarity ;
/* Chip-wide methods */
2016-04-18 06:35:56 +03:00
void ( * initialize ) ( struct regmap * grf ,
void __iomem * reg , enum tshut_polarity p ) ;
2014-11-24 07:58:59 +03:00
void ( * irq_ack ) ( void __iomem * reg ) ;
void ( * control ) ( void __iomem * reg , bool on ) ;
/* Per-sensor methods */
2016-12-12 14:05:32 +03:00
int ( * get_temp ) ( const struct chip_tsadc_table * table ,
2015-11-09 07:48:56 +03:00
int chn , void __iomem * reg , int * temp ) ;
2016-12-12 14:05:33 +03:00
int ( * set_alarm_temp ) ( const struct chip_tsadc_table * table ,
int chn , void __iomem * reg , int temp ) ;
int ( * set_tshut_temp ) ( const struct chip_tsadc_table * table ,
int chn , void __iomem * reg , int temp ) ;
2014-11-24 07:58:59 +03:00
void ( * set_tshut_mode ) ( int chn , void __iomem * reg , enum tshut_mode m ) ;
2015-11-09 07:48:56 +03:00
/* Per-table methods */
struct chip_tsadc_table table ;
2014-11-24 07:58:59 +03:00
} ;
2016-04-18 06:35:58 +03:00
/**
* struct rockchip_thermal_sensor - hold the information of thermal sensor
* @ thermal : pointer to the platform / configuration data
* @ tzd : pointer to a thermal zone
* @ id : identifier of the thermal sensor
*/
2014-11-24 07:58:59 +03:00
struct rockchip_thermal_sensor {
struct rockchip_thermal_data * thermal ;
struct thermal_zone_device * tzd ;
2015-11-05 08:17:58 +03:00
int id ;
2014-11-24 07:58:59 +03:00
} ;
2016-04-18 06:35:58 +03:00
/**
* struct rockchip_thermal_data - hold the private data of thermal driver
* @ chip : pointer to the platform / configuration data
* @ pdev : platform device of thermal
* @ reset : the reset controller of tsadc
2019-11-20 18:45:16 +03:00
* @ sensors : array of thermal sensors
2016-04-18 06:35:58 +03:00
* @ clk : the controller clock is divided by the exteral 24 MHz
* @ pclk : the advanced peripherals bus clock
* @ grf : the general register file will be used to do static set by software
* @ regs : the base address of tsadc controller
* @ tshut_temp : the hardware - controlled shutdown temperature value
* @ tshut_mode : the hardware - controlled shutdown mode ( 0 : CRU 1 : GPIO )
* @ tshut_polarity : the hardware - controlled active polarity ( 0 : LOW 1 : HIGH )
*/
2014-11-24 07:58:59 +03:00
struct rockchip_thermal_data {
const struct rockchip_tsadc_chip * chip ;
struct platform_device * pdev ;
struct reset_control * reset ;
2023-03-08 14:22:51 +03:00
struct rockchip_thermal_sensor * sensors ;
2014-11-24 07:58:59 +03:00
struct clk * clk ;
struct clk * pclk ;
2016-04-18 06:35:56 +03:00
struct regmap * grf ;
2014-11-24 07:58:59 +03:00
void __iomem * regs ;
2015-11-09 07:48:58 +03:00
int tshut_temp ;
2014-11-24 07:58:59 +03:00
enum tshut_mode tshut_mode ;
enum tshut_polarity tshut_polarity ;
} ;
2023-01-13 09:45:00 +03:00
/*
2016-02-15 10:33:30 +03:00
* TSADC Sensor Register description :
*
* TSADCV2_ * are used for RK3288 SoCs , the other chips can reuse it .
* TSADCV3_ * are used for newer SoCs than RK3288 . ( e . g : RK3228 , RK3399 )
*
*/
2016-04-18 06:35:56 +03:00
# define TSADCV2_USER_CON 0x00
2014-11-24 07:58:59 +03:00
# define TSADCV2_AUTO_CON 0x04
# define TSADCV2_INT_EN 0x08
# define TSADCV2_INT_PD 0x0c
2023-03-08 14:22:52 +03:00
# define TSADCV3_AUTO_SRC_CON 0x0c
# define TSADCV3_HT_INT_EN 0x14
# define TSADCV3_HSHUT_GPIO_INT_EN 0x18
# define TSADCV3_HSHUT_CRU_INT_EN 0x1c
# define TSADCV3_INT_PD 0x24
# define TSADCV3_HSHUT_PD 0x28
2014-11-24 07:58:59 +03:00
# define TSADCV2_DATA(chn) (0x20 + (chn) * 0x04)
2016-06-22 11:42:05 +03:00
# define TSADCV2_COMP_INT(chn) (0x30 + (chn) * 0x04)
2014-11-24 07:58:59 +03:00
# define TSADCV2_COMP_SHUT(chn) (0x40 + (chn) * 0x04)
2023-03-08 14:22:52 +03:00
# define TSADCV3_DATA(chn) (0x2c + (chn) * 0x04)
# define TSADCV3_COMP_INT(chn) (0x6c + (chn) * 0x04)
# define TSADCV3_COMP_SHUT(chn) (0x10c + (chn) * 0x04)
2014-11-24 07:58:59 +03:00
# define TSADCV2_HIGHT_INT_DEBOUNCE 0x60
# define TSADCV2_HIGHT_TSHUT_DEBOUNCE 0x64
2023-03-08 14:22:52 +03:00
# define TSADCV3_HIGHT_INT_DEBOUNCE 0x14c
# define TSADCV3_HIGHT_TSHUT_DEBOUNCE 0x150
2014-11-24 07:58:59 +03:00
# define TSADCV2_AUTO_PERIOD 0x68
# define TSADCV2_AUTO_PERIOD_HT 0x6c
2023-03-08 14:22:52 +03:00
# define TSADCV3_AUTO_PERIOD 0x154
# define TSADCV3_AUTO_PERIOD_HT 0x158
2014-11-24 07:58:59 +03:00
# define TSADCV2_AUTO_EN BIT(0)
2023-03-08 14:22:52 +03:00
# define TSADCV2_AUTO_EN_MASK BIT(16)
2014-11-24 07:58:59 +03:00
# define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn))
2023-03-08 14:22:52 +03:00
# define TSADCV3_AUTO_SRC_EN(chn) BIT(chn)
# define TSADCV3_AUTO_SRC_EN_MASK(chn) BIT(16 + chn)
2014-11-24 07:58:59 +03:00
# define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8)
2023-03-08 14:22:52 +03:00
# define TSADCV2_AUTO_TSHUT_POLARITY_MASK BIT(24)
2016-04-18 06:35:58 +03:00
2016-02-15 10:33:31 +03:00
# define TSADCV3_AUTO_Q_SEL_EN BIT(1)
2014-11-24 07:58:59 +03:00
# define TSADCV2_INT_SRC_EN(chn) BIT(chn)
2023-03-08 14:22:52 +03:00
# define TSADCV2_INT_SRC_EN_MASK(chn) BIT(16 + (chn))
2014-11-24 07:58:59 +03:00
# define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn))
# define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn))
2015-08-08 00:00:52 +03:00
# define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8)
2016-02-15 10:33:30 +03:00
# define TSADCV3_INT_PD_CLEAR_MASK ~BIT(16)
2023-03-08 14:22:52 +03:00
# define TSADCV4_INT_PD_CLEAR_MASK 0xffffffff
2014-11-24 07:58:59 +03:00
# define TSADCV2_DATA_MASK 0xfff
2015-11-09 07:48:59 +03:00
# define TSADCV3_DATA_MASK 0x3ff
2023-03-08 14:22:52 +03:00
# define TSADCV4_DATA_MASK 0x1ff
2015-11-09 07:48:59 +03:00
2014-11-24 07:58:59 +03:00
# define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4
# define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT 4
2016-06-22 13:13:56 +03:00
# define TSADCV2_AUTO_PERIOD_TIME 250 /* 250ms */
# define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* 50ms */
2016-07-27 17:10:43 +03:00
# define TSADCV3_AUTO_PERIOD_TIME 1875 /* 2.5ms */
# define TSADCV3_AUTO_PERIOD_HT_TIME 1875 /* 2.5ms */
2016-06-22 13:13:56 +03:00
2021-05-06 20:55:14 +03:00
# define TSADCV5_AUTO_PERIOD_TIME 1622 /* 2.5ms */
# define TSADCV5_AUTO_PERIOD_HT_TIME 1622 /* 2.5ms */
2023-03-08 14:22:52 +03:00
# define TSADCV6_AUTO_PERIOD_TIME 5000 /* 2.5ms */
# define TSADCV6_AUTO_PERIOD_HT_TIME 5000 /* 2.5ms */
2021-05-06 20:55:14 +03:00
2016-04-18 06:35:56 +03:00
# define TSADCV2_USER_INTER_PD_SOC 0x340 /* 13 clocks */
2021-05-06 20:55:14 +03:00
# define TSADCV5_USER_INTER_PD_SOC 0xfc0 /* 97us, at least 90us */
2016-04-18 06:35:56 +03:00
# define GRF_SARADC_TESTBIT 0x0e644
# define GRF_TSADC_TESTBIT_L 0x0e648
# define GRF_TSADC_TESTBIT_H 0x0e64c
2019-04-30 13:09:46 +03:00
# define PX30_GRF_SOC_CON2 0x0408
2021-05-06 20:55:14 +03:00
# define RK3568_GRF_TSADC_CON 0x0600
# define RK3568_GRF_TSADC_ANA_REG0 (0x10001 << 0)
# define RK3568_GRF_TSADC_ANA_REG1 (0x10001 << 1)
# define RK3568_GRF_TSADC_ANA_REG2 (0x10001 << 2)
# define RK3568_GRF_TSADC_TSEN (0x10001 << 8)
2023-03-08 14:22:52 +03:00
# define RK3588_GRF0_TSADC_CON 0x0100
# define RK3588_GRF0_TSADC_TRM (0xff0077 << 0)
# define RK3588_GRF0_TSADC_SHUT_2CRU (0x30003 << 10)
# define RK3588_GRF0_TSADC_SHUT_2GPIO (0x70007 << 12)
2016-04-18 06:35:56 +03:00
# define GRF_SARADC_TESTBIT_ON (0x10001 << 2)
# define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2)
2016-07-27 17:10:42 +03:00
# define GRF_TSADC_VCM_EN_L (0x10001 << 7)
# define GRF_TSADC_VCM_EN_H (0x10001 << 7)
2014-11-24 07:58:59 +03:00
2019-04-30 13:09:46 +03:00
# define GRF_CON_TSADC_CH_INV (0x10001 << 1)
2015-12-03 11:48:42 +03:00
/**
2016-04-18 06:35:58 +03:00
* struct tsadc_table - code to temperature conversion table
* @ code : the value of adc channel
* @ temp : the temperature
2015-12-03 11:48:42 +03:00
* Note :
2016-04-18 06:35:58 +03:00
* code to temperature mapping of the temperature sensor is a piece wise linear
2015-12-03 11:48:42 +03:00
* curve . Any temperature , code faling between to 2 give temperatures can be
* linearly interpolated .
2016-04-18 06:35:58 +03:00
* Code to Temperature mapping should be updated based on manufacturer results .
2015-12-03 11:48:42 +03:00
*/
2016-04-18 06:35:58 +03:00
struct tsadc_table {
u32 code ;
int temp ;
} ;
2017-08-24 13:27:52 +03:00
static const struct tsadc_table rv1108_table [ ] = {
{ 0 , - 40000 } ,
{ 374 , - 40000 } ,
{ 382 , - 35000 } ,
{ 389 , - 30000 } ,
{ 397 , - 25000 } ,
{ 405 , - 20000 } ,
{ 413 , - 15000 } ,
{ 421 , - 10000 } ,
{ 429 , - 5000 } ,
{ 436 , 0 } ,
{ 444 , 5000 } ,
{ 452 , 10000 } ,
{ 460 , 15000 } ,
{ 468 , 20000 } ,
{ 476 , 25000 } ,
{ 483 , 30000 } ,
{ 491 , 35000 } ,
{ 499 , 40000 } ,
{ 507 , 45000 } ,
{ 515 , 50000 } ,
{ 523 , 55000 } ,
{ 531 , 60000 } ,
{ 539 , 65000 } ,
{ 547 , 70000 } ,
{ 555 , 75000 } ,
{ 562 , 80000 } ,
{ 570 , 85000 } ,
{ 578 , 90000 } ,
{ 586 , 95000 } ,
{ 594 , 100000 } ,
{ 602 , 105000 } ,
{ 610 , 110000 } ,
{ 618 , 115000 } ,
{ 626 , 120000 } ,
{ 634 , 125000 } ,
{ TSADCV2_DATA_MASK , 125000 } ,
} ;
2016-02-15 10:33:30 +03:00
static const struct tsadc_table rk3228_code_table [ ] = {
2016-02-15 10:33:31 +03:00
{ 0 , - 40000 } ,
{ 588 , - 40000 } ,
{ 593 , - 35000 } ,
{ 598 , - 30000 } ,
{ 603 , - 25000 } ,
{ 608 , - 20000 } ,
{ 613 , - 15000 } ,
{ 618 , - 10000 } ,
{ 623 , - 5000 } ,
{ 629 , 0 } ,
{ 634 , 5000 } ,
{ 639 , 10000 } ,
{ 644 , 15000 } ,
{ 649 , 20000 } ,
{ 654 , 25000 } ,
{ 660 , 30000 } ,
{ 665 , 35000 } ,
{ 670 , 40000 } ,
{ 675 , 45000 } ,
{ 681 , 50000 } ,
{ 686 , 55000 } ,
{ 691 , 60000 } ,
{ 696 , 65000 } ,
{ 702 , 70000 } ,
{ 707 , 75000 } ,
{ 712 , 80000 } ,
{ 717 , 85000 } ,
{ 723 , 90000 } ,
{ 728 , 95000 } ,
{ 733 , 100000 } ,
{ 738 , 105000 } ,
{ 744 , 110000 } ,
{ 749 , 115000 } ,
{ 754 , 120000 } ,
{ 760 , 125000 } ,
{ TSADCV2_DATA_MASK , 125000 } ,
2015-12-03 11:48:42 +03:00
} ;
2016-02-15 10:33:30 +03:00
static const struct tsadc_table rk3288_code_table [ ] = {
2014-11-24 07:58:59 +03:00
{ TSADCV2_DATA_MASK , - 40000 } ,
{ 3800 , - 40000 } ,
{ 3792 , - 35000 } ,
{ 3783 , - 30000 } ,
{ 3774 , - 25000 } ,
{ 3765 , - 20000 } ,
{ 3756 , - 15000 } ,
{ 3747 , - 10000 } ,
{ 3737 , - 5000 } ,
{ 3728 , 0 } ,
{ 3718 , 5000 } ,
{ 3708 , 10000 } ,
{ 3698 , 15000 } ,
{ 3688 , 20000 } ,
{ 3678 , 25000 } ,
{ 3667 , 30000 } ,
{ 3656 , 35000 } ,
{ 3645 , 40000 } ,
{ 3634 , 45000 } ,
{ 3623 , 50000 } ,
{ 3611 , 55000 } ,
{ 3600 , 60000 } ,
{ 3588 , 65000 } ,
{ 3575 , 70000 } ,
{ 3563 , 75000 } ,
{ 3550 , 80000 } ,
{ 3537 , 85000 } ,
{ 3524 , 90000 } ,
{ 3510 , 95000 } ,
{ 3496 , 100000 } ,
{ 3482 , 105000 } ,
{ 3467 , 110000 } ,
{ 3452 , 115000 } ,
{ 3437 , 120000 } ,
{ 3421 , 125000 } ,
2016-12-12 14:05:34 +03:00
{ 0 , 125000 } ,
2014-11-24 07:58:59 +03:00
} ;
2017-08-04 11:06:13 +03:00
static const struct tsadc_table rk3328_code_table [ ] = {
{ 0 , - 40000 } ,
{ 296 , - 40000 } ,
{ 304 , - 35000 } ,
{ 313 , - 30000 } ,
{ 331 , - 20000 } ,
{ 340 , - 15000 } ,
{ 349 , - 10000 } ,
{ 359 , - 5000 } ,
{ 368 , 0 } ,
{ 378 , 5000 } ,
{ 388 , 10000 } ,
{ 398 , 15000 } ,
{ 408 , 20000 } ,
{ 418 , 25000 } ,
{ 429 , 30000 } ,
{ 440 , 35000 } ,
{ 451 , 40000 } ,
{ 462 , 45000 } ,
{ 473 , 50000 } ,
{ 485 , 55000 } ,
{ 496 , 60000 } ,
{ 508 , 65000 } ,
{ 521 , 70000 } ,
{ 533 , 75000 } ,
{ 546 , 80000 } ,
{ 559 , 85000 } ,
{ 572 , 90000 } ,
{ 586 , 95000 } ,
{ 600 , 100000 } ,
{ 614 , 105000 } ,
{ 629 , 110000 } ,
{ 644 , 115000 } ,
{ 659 , 120000 } ,
{ 675 , 125000 } ,
{ TSADCV2_DATA_MASK , 125000 } ,
} ;
2016-02-15 10:33:30 +03:00
static const struct tsadc_table rk3368_code_table [ ] = {
2015-11-09 07:48:59 +03:00
{ 0 , - 40000 } ,
{ 106 , - 40000 } ,
{ 108 , - 35000 } ,
{ 110 , - 30000 } ,
{ 112 , - 25000 } ,
{ 114 , - 20000 } ,
{ 116 , - 15000 } ,
{ 118 , - 10000 } ,
{ 120 , - 5000 } ,
{ 122 , 0 } ,
{ 124 , 5000 } ,
{ 126 , 10000 } ,
{ 128 , 15000 } ,
{ 130 , 20000 } ,
{ 132 , 25000 } ,
{ 134 , 30000 } ,
{ 136 , 35000 } ,
{ 138 , 40000 } ,
{ 140 , 45000 } ,
{ 142 , 50000 } ,
{ 144 , 55000 } ,
{ 146 , 60000 } ,
{ 148 , 65000 } ,
{ 150 , 70000 } ,
{ 152 , 75000 } ,
{ 154 , 80000 } ,
{ 156 , 85000 } ,
{ 158 , 90000 } ,
{ 160 , 95000 } ,
{ 162 , 100000 } ,
{ 163 , 105000 } ,
{ 165 , 110000 } ,
{ 167 , 115000 } ,
{ 169 , 120000 } ,
{ 171 , 125000 } ,
{ TSADCV3_DATA_MASK , 125000 } ,
} ;
2016-02-15 10:33:30 +03:00
static const struct tsadc_table rk3399_code_table [ ] = {
2016-02-15 10:33:31 +03:00
{ 0 , - 40000 } ,
2016-04-18 06:35:55 +03:00
{ 402 , - 40000 } ,
{ 410 , - 35000 } ,
{ 419 , - 30000 } ,
{ 427 , - 25000 } ,
{ 436 , - 20000 } ,
{ 444 , - 15000 } ,
{ 453 , - 10000 } ,
{ 461 , - 5000 } ,
{ 470 , 0 } ,
{ 478 , 5000 } ,
{ 487 , 10000 } ,
{ 496 , 15000 } ,
{ 504 , 20000 } ,
{ 513 , 25000 } ,
{ 521 , 30000 } ,
{ 530 , 35000 } ,
{ 538 , 40000 } ,
{ 547 , 45000 } ,
{ 555 , 50000 } ,
{ 564 , 55000 } ,
{ 573 , 60000 } ,
{ 581 , 65000 } ,
{ 590 , 70000 } ,
{ 599 , 75000 } ,
{ 607 , 80000 } ,
{ 616 , 85000 } ,
{ 624 , 90000 } ,
{ 633 , 95000 } ,
{ 642 , 100000 } ,
{ 650 , 105000 } ,
{ 659 , 110000 } ,
{ 668 , 115000 } ,
{ 677 , 120000 } ,
{ 685 , 125000 } ,
2016-02-15 10:33:31 +03:00
{ TSADCV3_DATA_MASK , 125000 } ,
2015-12-03 11:48:43 +03:00
} ;
2021-05-06 20:55:14 +03:00
static const struct tsadc_table rk3568_code_table [ ] = {
{ 0 , - 40000 } ,
{ 1584 , - 40000 } ,
{ 1620 , - 35000 } ,
{ 1652 , - 30000 } ,
{ 1688 , - 25000 } ,
{ 1720 , - 20000 } ,
{ 1756 , - 15000 } ,
{ 1788 , - 10000 } ,
{ 1824 , - 5000 } ,
{ 1856 , 0 } ,
{ 1892 , 5000 } ,
{ 1924 , 10000 } ,
{ 1956 , 15000 } ,
{ 1992 , 20000 } ,
{ 2024 , 25000 } ,
{ 2060 , 30000 } ,
{ 2092 , 35000 } ,
{ 2128 , 40000 } ,
{ 2160 , 45000 } ,
{ 2196 , 50000 } ,
{ 2228 , 55000 } ,
{ 2264 , 60000 } ,
{ 2300 , 65000 } ,
{ 2332 , 70000 } ,
{ 2368 , 75000 } ,
{ 2400 , 80000 } ,
{ 2436 , 85000 } ,
{ 2468 , 90000 } ,
{ 2500 , 95000 } ,
{ 2536 , 100000 } ,
{ 2572 , 105000 } ,
{ 2604 , 110000 } ,
{ 2636 , 115000 } ,
{ 2672 , 120000 } ,
{ 2704 , 125000 } ,
{ TSADCV2_DATA_MASK , 125000 } ,
} ;
2023-03-08 14:22:52 +03:00
static const struct tsadc_table rk3588_code_table [ ] = {
{ 0 , - 40000 } ,
{ 215 , - 40000 } ,
{ 285 , 25000 } ,
{ 350 , 85000 } ,
{ 395 , 125000 } ,
{ TSADCV4_DATA_MASK , 125000 } ,
} ;
2016-12-12 14:05:32 +03:00
static u32 rk_tsadcv2_temp_to_code ( const struct chip_tsadc_table * table ,
2015-11-09 07:48:58 +03:00
int temp )
2014-11-24 07:58:59 +03:00
{
int high , low , mid ;
2016-12-12 14:05:34 +03:00
unsigned long num ;
unsigned int denom ;
2016-12-12 14:05:33 +03:00
u32 error = table - > data_mask ;
2014-11-24 07:58:59 +03:00
low = 0 ;
2016-12-12 14:05:34 +03:00
high = ( table - > length - 1 ) - 1 ; /* ignore the last check for table */
2014-11-24 07:58:59 +03:00
mid = ( high + low ) / 2 ;
2016-06-22 13:13:57 +03:00
/* Return mask code data when the temp is over table range */
2016-12-12 14:05:33 +03:00
if ( temp < table - > id [ low ] . temp | | temp > table - > id [ high ] . temp )
2016-06-22 13:13:57 +03:00
goto exit ;
2014-11-24 07:58:59 +03:00
while ( low < = high ) {
2016-12-12 14:05:32 +03:00
if ( temp = = table - > id [ mid ] . temp )
return table - > id [ mid ] . code ;
else if ( temp < table - > id [ mid ] . temp )
2014-11-24 07:58:59 +03:00
high = mid - 1 ;
else
low = mid + 1 ;
mid = ( low + high ) / 2 ;
}
2016-12-12 14:05:34 +03:00
/*
* The conversion code granularity provided by the table . Let ' s
* assume that the relationship between temperature and
* analog value between 2 table entries is linear and interpolate
* to produce less granular result .
*/
num = abs ( table - > id [ mid + 1 ] . code - table - > id [ mid ] . code ) ;
num * = temp - table - > id [ mid ] . temp ;
denom = table - > id [ mid + 1 ] . temp - table - > id [ mid ] . temp ;
switch ( table - > mode ) {
case ADC_DECREMENT :
return table - > id [ mid ] . code - ( num / denom ) ;
case ADC_INCREMENT :
return table - > id [ mid ] . code + ( num / denom ) ;
default :
pr_err ( " %s: unknown table mode: %d \n " , __func__ , table - > mode ) ;
return error ;
}
2016-06-22 13:13:57 +03:00
exit :
2016-12-12 14:05:31 +03:00
pr_err ( " %s: invalid temperature, temp=%d error=%d \n " ,
__func__ , temp , error ) ;
2016-06-22 13:13:57 +03:00
return error ;
2014-11-24 07:58:59 +03:00
}
2016-12-12 14:05:32 +03:00
static int rk_tsadcv2_code_to_temp ( const struct chip_tsadc_table * table ,
u32 code , int * temp )
2014-11-24 07:58:59 +03:00
{
2015-08-07 23:59:23 +03:00
unsigned int low = 1 ;
2016-12-12 14:05:32 +03:00
unsigned int high = table - > length - 1 ;
2015-01-25 05:11:11 +03:00
unsigned int mid = ( low + high ) / 2 ;
unsigned int num ;
unsigned long denom ;
2016-12-12 14:05:32 +03:00
WARN_ON ( table - > length < 2 ) ;
2015-01-25 05:11:11 +03:00
2016-12-12 14:05:32 +03:00
switch ( table - > mode ) {
2015-11-09 07:48:57 +03:00
case ADC_DECREMENT :
2016-12-12 14:05:32 +03:00
code & = table - > data_mask ;
2017-01-05 07:37:55 +03:00
if ( code < = table - > id [ high ] . code )
2015-11-09 07:48:57 +03:00
return - EAGAIN ; /* Incorrect reading */
while ( low < = high ) {
2016-12-12 14:05:32 +03:00
if ( code > = table - > id [ mid ] . code & &
code < table - > id [ mid - 1 ] . code )
2015-11-09 07:48:57 +03:00
break ;
2016-12-12 14:05:32 +03:00
else if ( code < table - > id [ mid ] . code )
2015-11-09 07:48:57 +03:00
low = mid + 1 ;
else
high = mid - 1 ;
mid = ( low + high ) / 2 ;
}
break ;
case ADC_INCREMENT :
2016-12-12 14:05:32 +03:00
code & = table - > data_mask ;
if ( code < table - > id [ low ] . code )
2015-11-09 07:48:57 +03:00
return - EAGAIN ; /* Incorrect reading */
while ( low < = high ) {
2016-12-12 14:05:32 +03:00
if ( code < = table - > id [ mid ] . code & &
code > table - > id [ mid - 1 ] . code )
2015-11-09 07:48:57 +03:00
break ;
2016-12-12 14:05:32 +03:00
else if ( code > table - > id [ mid ] . code )
2015-11-09 07:48:57 +03:00
low = mid + 1 ;
else
high = mid - 1 ;
mid = ( low + high ) / 2 ;
}
break ;
default :
2016-12-12 14:05:32 +03:00
pr_err ( " %s: unknown table mode: %d \n " , __func__ , table - > mode ) ;
2016-12-12 14:05:31 +03:00
return - EINVAL ;
2014-11-24 07:58:59 +03:00
}
2015-01-25 05:11:11 +03:00
/*
* The 5 C granularity provided by the table is too much . Let ' s
* assume that the relationship between sensor readings and
* temperature between 2 table entries is linear and interpolate
* to produce less granular result .
*/
2016-12-12 14:05:32 +03:00
num = table - > id [ mid ] . temp - table - > id [ mid - 1 ] . temp ;
num * = abs ( table - > id [ mid - 1 ] . code - code ) ;
denom = abs ( table - > id [ mid - 1 ] . code - table - > id [ mid ] . code ) ;
* temp = table - > id [ mid - 1 ] . temp + ( num / denom ) ;
2015-08-07 23:59:23 +03:00
return 0 ;
2014-11-24 07:58:59 +03:00
}
/**
2015-11-05 08:17:59 +03:00
* rk_tsadcv2_initialize - initialize TASDC Controller .
2019-11-20 18:45:16 +03:00
* @ grf : the general register file will be used to do static set by software
* @ regs : the base address of tsadc controller
* @ tshut_polarity : the hardware - controlled active polarity ( 0 : LOW 1 : HIGH )
2015-11-05 08:17:59 +03:00
*
* ( 1 ) Set TSADC_V2_AUTO_PERIOD :
* Configure the interleave between every two accessing of
* TSADC in normal operation .
*
* ( 2 ) Set TSADCV2_AUTO_PERIOD_HT :
* Configure the interleave between every two accessing of
* TSADC after the temperature is higher than COM_SHUT or COM_INT .
*
* ( 3 ) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE :
* If the temperature is higher than COMP_INT or COMP_SHUT for
* " debounce " times , TSADC controller will generate interrupt or TSHUT .
2014-11-24 07:58:59 +03:00
*/
2016-04-18 06:35:56 +03:00
static void rk_tsadcv2_initialize ( struct regmap * grf , void __iomem * regs ,
2014-11-24 07:58:59 +03:00
enum tshut_polarity tshut_polarity )
{
if ( tshut_polarity = = TSHUT_HIGH_ACTIVE )
2015-08-08 00:00:52 +03:00
writel_relaxed ( 0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH ,
2014-11-24 07:58:59 +03:00
regs + TSADCV2_AUTO_CON ) ;
else
2015-08-08 00:00:52 +03:00
writel_relaxed ( 0U & ~ TSADCV2_AUTO_TSHUT_POLARITY_HIGH ,
2014-11-24 07:58:59 +03:00
regs + TSADCV2_AUTO_CON ) ;
writel_relaxed ( TSADCV2_AUTO_PERIOD_TIME , regs + TSADCV2_AUTO_PERIOD ) ;
writel_relaxed ( TSADCV2_HIGHT_INT_DEBOUNCE_COUNT ,
regs + TSADCV2_HIGHT_INT_DEBOUNCE ) ;
writel_relaxed ( TSADCV2_AUTO_PERIOD_HT_TIME ,
regs + TSADCV2_AUTO_PERIOD_HT ) ;
writel_relaxed ( TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT ,
regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE ) ;
2016-04-18 06:35:56 +03:00
}
/**
* rk_tsadcv3_initialize - initialize TASDC Controller .
2019-11-20 18:45:16 +03:00
* @ grf : the general register file will be used to do static set by software
* @ regs : the base address of tsadc controller
* @ tshut_polarity : the hardware - controlled active polarity ( 0 : LOW 1 : HIGH )
2016-04-18 06:35:58 +03:00
*
2016-04-18 06:35:56 +03:00
* ( 1 ) The tsadc control power sequence .
*
* ( 2 ) Set TSADC_V2_AUTO_PERIOD :
* Configure the interleave between every two accessing of
* TSADC in normal operation .
*
* ( 2 ) Set TSADCV2_AUTO_PERIOD_HT :
* Configure the interleave between every two accessing of
* TSADC after the temperature is higher than COM_SHUT or COM_INT .
*
* ( 3 ) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE :
* If the temperature is higher than COMP_INT or COMP_SHUT for
* " debounce " times , TSADC controller will generate interrupt or TSHUT .
*/
static void rk_tsadcv3_initialize ( struct regmap * grf , void __iomem * regs ,
enum tshut_polarity tshut_polarity )
{
/* The tsadc control power sequence */
if ( IS_ERR ( grf ) ) {
/* Set interleave value to workround ic time sync issue */
writel_relaxed ( TSADCV2_USER_INTER_PD_SOC , regs +
TSADCV2_USER_CON ) ;
2016-06-22 13:13:56 +03:00
writel_relaxed ( TSADCV2_AUTO_PERIOD_TIME ,
regs + TSADCV2_AUTO_PERIOD ) ;
writel_relaxed ( TSADCV2_HIGHT_INT_DEBOUNCE_COUNT ,
regs + TSADCV2_HIGHT_INT_DEBOUNCE ) ;
writel_relaxed ( TSADCV2_AUTO_PERIOD_HT_TIME ,
regs + TSADCV2_AUTO_PERIOD_HT ) ;
writel_relaxed ( TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT ,
regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE ) ;
2016-04-18 06:35:56 +03:00
} else {
2016-07-27 17:10:42 +03:00
/* Enable the voltage common mode feature */
regmap_write ( grf , GRF_TSADC_TESTBIT_L , GRF_TSADC_VCM_EN_L ) ;
regmap_write ( grf , GRF_TSADC_TESTBIT_H , GRF_TSADC_VCM_EN_H ) ;
2016-05-03 05:23:50 +03:00
usleep_range ( 15 , 100 ) ; /* The spec note says at least 15 us */
2016-04-18 06:35:56 +03:00
regmap_write ( grf , GRF_SARADC_TESTBIT , GRF_SARADC_TESTBIT_ON ) ;
regmap_write ( grf , GRF_TSADC_TESTBIT_H , GRF_TSADC_TESTBIT_H_ON ) ;
2016-05-03 05:23:50 +03:00
usleep_range ( 90 , 200 ) ; /* The spec note says at least 90 us */
2016-06-22 13:13:56 +03:00
writel_relaxed ( TSADCV3_AUTO_PERIOD_TIME ,
regs + TSADCV2_AUTO_PERIOD ) ;
writel_relaxed ( TSADCV2_HIGHT_INT_DEBOUNCE_COUNT ,
regs + TSADCV2_HIGHT_INT_DEBOUNCE ) ;
writel_relaxed ( TSADCV3_AUTO_PERIOD_HT_TIME ,
regs + TSADCV2_AUTO_PERIOD_HT ) ;
writel_relaxed ( TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT ,
regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE ) ;
2016-04-18 06:35:56 +03:00
}
if ( tshut_polarity = = TSHUT_HIGH_ACTIVE )
writel_relaxed ( 0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH ,
regs + TSADCV2_AUTO_CON ) ;
else
writel_relaxed ( 0U & ~ TSADCV2_AUTO_TSHUT_POLARITY_HIGH ,
regs + TSADCV2_AUTO_CON ) ;
2014-11-24 07:58:59 +03:00
}
2019-04-30 13:09:46 +03:00
static void rk_tsadcv4_initialize ( struct regmap * grf , void __iomem * regs ,
enum tshut_polarity tshut_polarity )
{
rk_tsadcv2_initialize ( grf , regs , tshut_polarity ) ;
regmap_write ( grf , PX30_GRF_SOC_CON2 , GRF_CON_TSADC_CH_INV ) ;
}
2021-05-06 20:55:14 +03:00
static void rk_tsadcv7_initialize ( struct regmap * grf , void __iomem * regs ,
enum tshut_polarity tshut_polarity )
{
writel_relaxed ( TSADCV5_USER_INTER_PD_SOC , regs + TSADCV2_USER_CON ) ;
writel_relaxed ( TSADCV5_AUTO_PERIOD_TIME , regs + TSADCV2_AUTO_PERIOD ) ;
writel_relaxed ( TSADCV2_HIGHT_INT_DEBOUNCE_COUNT ,
regs + TSADCV2_HIGHT_INT_DEBOUNCE ) ;
writel_relaxed ( TSADCV5_AUTO_PERIOD_HT_TIME ,
regs + TSADCV2_AUTO_PERIOD_HT ) ;
writel_relaxed ( TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT ,
regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE ) ;
if ( tshut_polarity = = TSHUT_HIGH_ACTIVE )
writel_relaxed ( 0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH ,
regs + TSADCV2_AUTO_CON ) ;
else
writel_relaxed ( 0U & ~ TSADCV2_AUTO_TSHUT_POLARITY_HIGH ,
regs + TSADCV2_AUTO_CON ) ;
/*
* The general register file will is optional
* and might not be available .
*/
if ( ! IS_ERR ( grf ) ) {
regmap_write ( grf , RK3568_GRF_TSADC_CON , RK3568_GRF_TSADC_TSEN ) ;
/*
* RK3568 TRM , section 18.5 . requires a delay no less
* than 10u s between the rising edge of tsadc_tsen_en
* and the rising edge of tsadc_ana_reg_0 / 1 / 2.
*/
udelay ( 15 ) ;
regmap_write ( grf , RK3568_GRF_TSADC_CON , RK3568_GRF_TSADC_ANA_REG0 ) ;
regmap_write ( grf , RK3568_GRF_TSADC_CON , RK3568_GRF_TSADC_ANA_REG1 ) ;
regmap_write ( grf , RK3568_GRF_TSADC_CON , RK3568_GRF_TSADC_ANA_REG2 ) ;
/*
* RK3568 TRM , section 18.5 . requires a delay no less
* than 90u s after the rising edge of tsadc_ana_reg_0 / 1 / 2.
*/
usleep_range ( 100 , 200 ) ;
}
}
2023-03-08 14:22:52 +03:00
static void rk_tsadcv8_initialize ( struct regmap * grf , void __iomem * regs ,
enum tshut_polarity tshut_polarity )
{
writel_relaxed ( TSADCV6_AUTO_PERIOD_TIME , regs + TSADCV3_AUTO_PERIOD ) ;
writel_relaxed ( TSADCV6_AUTO_PERIOD_HT_TIME ,
regs + TSADCV3_AUTO_PERIOD_HT ) ;
writel_relaxed ( TSADCV2_HIGHT_INT_DEBOUNCE_COUNT ,
regs + TSADCV3_HIGHT_INT_DEBOUNCE ) ;
writel_relaxed ( TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT ,
regs + TSADCV3_HIGHT_TSHUT_DEBOUNCE ) ;
if ( tshut_polarity = = TSHUT_HIGH_ACTIVE )
writel_relaxed ( TSADCV2_AUTO_TSHUT_POLARITY_HIGH |
TSADCV2_AUTO_TSHUT_POLARITY_MASK ,
regs + TSADCV2_AUTO_CON ) ;
else
writel_relaxed ( TSADCV2_AUTO_TSHUT_POLARITY_MASK ,
regs + TSADCV2_AUTO_CON ) ;
}
2016-02-15 10:33:30 +03:00
static void rk_tsadcv2_irq_ack ( void __iomem * regs )
2015-12-03 11:48:42 +03:00
{
u32 val ;
val = readl_relaxed ( regs + TSADCV2_INT_PD ) ;
2016-02-15 10:33:30 +03:00
writel_relaxed ( val & TSADCV2_INT_PD_CLEAR_MASK , regs + TSADCV2_INT_PD ) ;
2015-12-03 11:48:42 +03:00
}
2016-02-15 10:33:30 +03:00
static void rk_tsadcv3_irq_ack ( void __iomem * regs )
2014-11-24 07:58:59 +03:00
{
u32 val ;
val = readl_relaxed ( regs + TSADCV2_INT_PD ) ;
2016-02-15 10:33:30 +03:00
writel_relaxed ( val & TSADCV3_INT_PD_CLEAR_MASK , regs + TSADCV2_INT_PD ) ;
2014-11-24 07:58:59 +03:00
}
2023-03-08 14:22:52 +03:00
static void rk_tsadcv4_irq_ack ( void __iomem * regs )
{
u32 val ;
val = readl_relaxed ( regs + TSADCV3_INT_PD ) ;
writel_relaxed ( val & TSADCV4_INT_PD_CLEAR_MASK , regs + TSADCV3_INT_PD ) ;
val = readl_relaxed ( regs + TSADCV3_HSHUT_PD ) ;
writel_relaxed ( val & TSADCV3_INT_PD_CLEAR_MASK ,
regs + TSADCV3_HSHUT_PD ) ;
}
2014-11-24 07:58:59 +03:00
static void rk_tsadcv2_control ( void __iomem * regs , bool enable )
{
u32 val ;
val = readl_relaxed ( regs + TSADCV2_AUTO_CON ) ;
if ( enable )
val | = TSADCV2_AUTO_EN ;
else
val & = ~ TSADCV2_AUTO_EN ;
writel_relaxed ( val , regs + TSADCV2_AUTO_CON ) ;
}
2016-02-15 10:33:31 +03:00
/**
2016-04-18 06:35:58 +03:00
* rk_tsadcv3_control - the tsadc controller is enabled or disabled .
2019-11-20 18:45:16 +03:00
* @ regs : the base address of tsadc controller
* @ enable : boolean flag to enable the controller
2016-04-18 06:35:58 +03:00
*
* NOTE : TSADC controller works at auto mode , and some SoCs need set the
* tsadc_q_sel bit on TSADCV2_AUTO_CON [ 1 ] . The ( 1024 - tsadc_q ) as output
* adc value if setting this bit to enable .
2016-02-15 10:33:31 +03:00
*/
static void rk_tsadcv3_control ( void __iomem * regs , bool enable )
{
u32 val ;
val = readl_relaxed ( regs + TSADCV2_AUTO_CON ) ;
if ( enable )
val | = TSADCV2_AUTO_EN | TSADCV3_AUTO_Q_SEL_EN ;
else
val & = ~ TSADCV2_AUTO_EN ;
writel_relaxed ( val , regs + TSADCV2_AUTO_CON ) ;
}
2023-03-08 14:22:52 +03:00
static void rk_tsadcv4_control ( void __iomem * regs , bool enable )
{
u32 val ;
if ( enable )
val = TSADCV2_AUTO_EN | TSADCV2_AUTO_EN_MASK ;
else
val = TSADCV2_AUTO_EN_MASK ;
writel_relaxed ( val , regs + TSADCV2_AUTO_CON ) ;
}
2016-12-12 14:05:32 +03:00
static int rk_tsadcv2_get_temp ( const struct chip_tsadc_table * table ,
2015-11-09 07:48:56 +03:00
int chn , void __iomem * regs , int * temp )
2014-11-24 07:58:59 +03:00
{
u32 val ;
val = readl_relaxed ( regs + TSADCV2_DATA ( chn ) ) ;
2015-11-09 07:48:56 +03:00
return rk_tsadcv2_code_to_temp ( table , val , temp ) ;
2014-11-24 07:58:59 +03:00
}
2023-03-08 14:22:52 +03:00
static int rk_tsadcv4_get_temp ( const struct chip_tsadc_table * table ,
int chn , void __iomem * regs , int * temp )
{
u32 val ;
val = readl_relaxed ( regs + TSADCV3_DATA ( chn ) ) ;
return rk_tsadcv2_code_to_temp ( table , val , temp ) ;
}
2016-12-12 14:05:33 +03:00
static int rk_tsadcv2_alarm_temp ( const struct chip_tsadc_table * table ,
int chn , void __iomem * regs , int temp )
2016-06-22 11:42:05 +03:00
{
2016-12-12 14:05:35 +03:00
u32 alarm_value ;
u32 int_en , int_clr ;
/*
* In some cases , some sensors didn ' t need the trip points , the
* set_trips will pass { - INT_MAX , INT_MAX } to trigger tsadc alarm
* in the end , ignore this case and disable the high temperature
* interrupt .
*/
if ( temp = = INT_MAX ) {
int_clr = readl_relaxed ( regs + TSADCV2_INT_EN ) ;
int_clr & = ~ TSADCV2_INT_SRC_EN ( chn ) ;
writel_relaxed ( int_clr , regs + TSADCV2_INT_EN ) ;
return 0 ;
}
2016-06-22 11:42:05 +03:00
2016-06-22 13:13:57 +03:00
/* Make sure the value is valid */
2016-06-22 11:42:05 +03:00
alarm_value = rk_tsadcv2_temp_to_code ( table , temp ) ;
2016-12-12 14:05:32 +03:00
if ( alarm_value = = table - > data_mask )
2016-12-12 14:05:33 +03:00
return - ERANGE ;
2016-06-22 13:13:57 +03:00
2016-12-12 14:05:32 +03:00
writel_relaxed ( alarm_value & table - > data_mask ,
2016-06-22 11:42:05 +03:00
regs + TSADCV2_COMP_INT ( chn ) ) ;
int_en = readl_relaxed ( regs + TSADCV2_INT_EN ) ;
int_en | = TSADCV2_INT_SRC_EN ( chn ) ;
writel_relaxed ( int_en , regs + TSADCV2_INT_EN ) ;
2016-12-12 14:05:33 +03:00
return 0 ;
2016-06-22 11:42:05 +03:00
}
2023-03-08 14:22:52 +03:00
static int rk_tsadcv3_alarm_temp ( const struct chip_tsadc_table * table ,
int chn , void __iomem * regs , int temp )
{
u32 alarm_value ;
/*
* In some cases , some sensors didn ' t need the trip points , the
* set_trips will pass { - INT_MAX , INT_MAX } to trigger tsadc alarm
* in the end , ignore this case and disable the high temperature
* interrupt .
*/
if ( temp = = INT_MAX ) {
writel_relaxed ( TSADCV2_INT_SRC_EN_MASK ( chn ) ,
regs + TSADCV3_HT_INT_EN ) ;
return 0 ;
}
/* Make sure the value is valid */
alarm_value = rk_tsadcv2_temp_to_code ( table , temp ) ;
if ( alarm_value = = table - > data_mask )
return - ERANGE ;
writel_relaxed ( alarm_value & table - > data_mask ,
regs + TSADCV3_COMP_INT ( chn ) ) ;
writel_relaxed ( TSADCV2_INT_SRC_EN ( chn ) | TSADCV2_INT_SRC_EN_MASK ( chn ) ,
regs + TSADCV3_HT_INT_EN ) ;
return 0 ;
}
2016-12-12 14:05:33 +03:00
static int rk_tsadcv2_tshut_temp ( const struct chip_tsadc_table * table ,
int chn , void __iomem * regs , int temp )
2014-11-24 07:58:59 +03:00
{
u32 tshut_value , val ;
2016-06-22 13:13:57 +03:00
/* Make sure the value is valid */
2015-11-09 07:48:56 +03:00
tshut_value = rk_tsadcv2_temp_to_code ( table , temp ) ;
2016-12-12 14:05:32 +03:00
if ( tshut_value = = table - > data_mask )
2016-12-12 14:05:33 +03:00
return - ERANGE ;
2016-06-22 13:13:57 +03:00
2014-11-24 07:58:59 +03:00
writel_relaxed ( tshut_value , regs + TSADCV2_COMP_SHUT ( chn ) ) ;
/* TSHUT will be valid */
val = readl_relaxed ( regs + TSADCV2_AUTO_CON ) ;
writel_relaxed ( val | TSADCV2_AUTO_SRC_EN ( chn ) , regs + TSADCV2_AUTO_CON ) ;
2016-12-12 14:05:33 +03:00
return 0 ;
2014-11-24 07:58:59 +03:00
}
2023-03-08 14:22:52 +03:00
static int rk_tsadcv3_tshut_temp ( const struct chip_tsadc_table * table ,
int chn , void __iomem * regs , int temp )
{
u32 tshut_value ;
/* Make sure the value is valid */
tshut_value = rk_tsadcv2_temp_to_code ( table , temp ) ;
if ( tshut_value = = table - > data_mask )
return - ERANGE ;
writel_relaxed ( tshut_value , regs + TSADCV3_COMP_SHUT ( chn ) ) ;
/* TSHUT will be valid */
writel_relaxed ( TSADCV3_AUTO_SRC_EN ( chn ) | TSADCV3_AUTO_SRC_EN_MASK ( chn ) ,
regs + TSADCV3_AUTO_SRC_CON ) ;
return 0 ;
}
2014-11-24 07:58:59 +03:00
static void rk_tsadcv2_tshut_mode ( int chn , void __iomem * regs ,
enum tshut_mode mode )
{
u32 val ;
val = readl_relaxed ( regs + TSADCV2_INT_EN ) ;
if ( mode = = TSHUT_MODE_GPIO ) {
val & = ~ TSADCV2_SHUT_2CRU_SRC_EN ( chn ) ;
val | = TSADCV2_SHUT_2GPIO_SRC_EN ( chn ) ;
} else {
val & = ~ TSADCV2_SHUT_2GPIO_SRC_EN ( chn ) ;
val | = TSADCV2_SHUT_2CRU_SRC_EN ( chn ) ;
}
writel_relaxed ( val , regs + TSADCV2_INT_EN ) ;
}
2023-03-08 14:22:52 +03:00
static void rk_tsadcv3_tshut_mode ( int chn , void __iomem * regs ,
enum tshut_mode mode )
{
u32 val_gpio , val_cru ;
if ( mode = = TSHUT_MODE_GPIO ) {
val_gpio = TSADCV2_INT_SRC_EN ( chn ) | TSADCV2_INT_SRC_EN_MASK ( chn ) ;
val_cru = TSADCV2_INT_SRC_EN_MASK ( chn ) ;
} else {
val_cru = TSADCV2_INT_SRC_EN ( chn ) | TSADCV2_INT_SRC_EN_MASK ( chn ) ;
val_gpio = TSADCV2_INT_SRC_EN_MASK ( chn ) ;
}
writel_relaxed ( val_gpio , regs + TSADCV3_HSHUT_GPIO_INT_EN ) ;
writel_relaxed ( val_cru , regs + TSADCV3_HSHUT_CRU_INT_EN ) ;
}
2019-04-30 13:09:46 +03:00
static const struct rockchip_tsadc_chip px30_tsadc_data = {
2023-03-08 14:22:50 +03:00
/* cpu, gpu */
. chn_offset = 0 ,
2019-04-30 13:09:46 +03:00
. chn_num = 2 , /* 2 channels for tsadc */
. tshut_mode = TSHUT_MODE_CRU , /* default TSHUT via CRU */
. tshut_temp = 95000 ,
. initialize = rk_tsadcv4_initialize ,
. irq_ack = rk_tsadcv3_irq_ack ,
. control = rk_tsadcv3_control ,
. get_temp = rk_tsadcv2_get_temp ,
. set_alarm_temp = rk_tsadcv2_alarm_temp ,
. set_tshut_temp = rk_tsadcv2_tshut_temp ,
. set_tshut_mode = rk_tsadcv2_tshut_mode ,
. table = {
. id = rk3328_code_table ,
. length = ARRAY_SIZE ( rk3328_code_table ) ,
. data_mask = TSADCV2_DATA_MASK ,
. mode = ADC_INCREMENT ,
} ,
} ;
2017-08-24 13:27:52 +03:00
static const struct rockchip_tsadc_chip rv1108_tsadc_data = {
2023-03-08 14:22:50 +03:00
/* cpu */
. chn_offset = 0 ,
2017-08-24 13:27:52 +03:00
. chn_num = 1 , /* one channel for tsadc */
. tshut_mode = TSHUT_MODE_GPIO , /* default TSHUT via GPIO give PMIC */
. tshut_polarity = TSHUT_LOW_ACTIVE , /* default TSHUT LOW ACTIVE */
. tshut_temp = 95000 ,
. initialize = rk_tsadcv2_initialize ,
. irq_ack = rk_tsadcv3_irq_ack ,
. control = rk_tsadcv3_control ,
. get_temp = rk_tsadcv2_get_temp ,
. set_alarm_temp = rk_tsadcv2_alarm_temp ,
. set_tshut_temp = rk_tsadcv2_tshut_temp ,
. set_tshut_mode = rk_tsadcv2_tshut_mode ,
. table = {
. id = rv1108_table ,
. length = ARRAY_SIZE ( rv1108_table ) ,
. data_mask = TSADCV2_DATA_MASK ,
. mode = ADC_INCREMENT ,
} ,
} ;
2015-12-03 11:48:42 +03:00
static const struct rockchip_tsadc_chip rk3228_tsadc_data = {
2023-03-08 14:22:50 +03:00
/* cpu */
. chn_offset = 0 ,
2015-12-03 11:48:42 +03:00
. chn_num = 1 , /* one channel for tsadc */
. tshut_mode = TSHUT_MODE_GPIO , /* default TSHUT via GPIO give PMIC */
. tshut_polarity = TSHUT_LOW_ACTIVE , /* default TSHUT LOW ACTIVE */
. tshut_temp = 95000 ,
. initialize = rk_tsadcv2_initialize ,
2016-02-15 10:33:30 +03:00
. irq_ack = rk_tsadcv3_irq_ack ,
2016-02-15 10:33:31 +03:00
. control = rk_tsadcv3_control ,
2015-12-03 11:48:42 +03:00
. get_temp = rk_tsadcv2_get_temp ,
2016-06-22 11:42:05 +03:00
. set_alarm_temp = rk_tsadcv2_alarm_temp ,
2015-12-03 11:48:42 +03:00
. set_tshut_temp = rk_tsadcv2_tshut_temp ,
. set_tshut_mode = rk_tsadcv2_tshut_mode ,
. table = {
2016-02-15 10:33:30 +03:00
. id = rk3228_code_table ,
. length = ARRAY_SIZE ( rk3228_code_table ) ,
2015-12-03 11:48:42 +03:00
. data_mask = TSADCV3_DATA_MASK ,
2016-02-15 10:33:31 +03:00
. mode = ADC_INCREMENT ,
2015-12-03 11:48:42 +03:00
} ,
} ;
2014-11-24 07:58:59 +03:00
static const struct rockchip_tsadc_chip rk3288_tsadc_data = {
2023-03-08 14:22:50 +03:00
/* cpu, gpu */
. chn_offset = 1 ,
2015-11-05 08:17:58 +03:00
. chn_num = 2 , /* two channels for tsadc */
2014-11-24 07:58:59 +03:00
. tshut_mode = TSHUT_MODE_GPIO , /* default TSHUT via GPIO give PMIC */
. tshut_polarity = TSHUT_LOW_ACTIVE , /* default TSHUT LOW ACTIVE */
. tshut_temp = 95000 ,
. initialize = rk_tsadcv2_initialize ,
. irq_ack = rk_tsadcv2_irq_ack ,
. control = rk_tsadcv2_control ,
. get_temp = rk_tsadcv2_get_temp ,
2016-06-22 11:42:05 +03:00
. set_alarm_temp = rk_tsadcv2_alarm_temp ,
2014-11-24 07:58:59 +03:00
. set_tshut_temp = rk_tsadcv2_tshut_temp ,
. set_tshut_mode = rk_tsadcv2_tshut_mode ,
2015-11-09 07:48:56 +03:00
. table = {
2016-02-15 10:33:30 +03:00
. id = rk3288_code_table ,
. length = ARRAY_SIZE ( rk3288_code_table ) ,
2015-11-09 07:48:56 +03:00
. data_mask = TSADCV2_DATA_MASK ,
2015-11-09 07:48:57 +03:00
. mode = ADC_DECREMENT ,
2015-11-09 07:48:56 +03:00
} ,
2014-11-24 07:58:59 +03:00
} ;
2017-08-04 11:06:13 +03:00
static const struct rockchip_tsadc_chip rk3328_tsadc_data = {
2023-03-08 14:22:50 +03:00
/* cpu */
. chn_offset = 0 ,
2017-08-04 11:06:13 +03:00
. chn_num = 1 , /* one channels for tsadc */
. tshut_mode = TSHUT_MODE_CRU , /* default TSHUT via CRU */
. tshut_temp = 95000 ,
. initialize = rk_tsadcv2_initialize ,
. irq_ack = rk_tsadcv3_irq_ack ,
. control = rk_tsadcv3_control ,
. get_temp = rk_tsadcv2_get_temp ,
. set_alarm_temp = rk_tsadcv2_alarm_temp ,
. set_tshut_temp = rk_tsadcv2_tshut_temp ,
. set_tshut_mode = rk_tsadcv2_tshut_mode ,
. table = {
. id = rk3328_code_table ,
. length = ARRAY_SIZE ( rk3328_code_table ) ,
. data_mask = TSADCV2_DATA_MASK ,
. mode = ADC_INCREMENT ,
} ,
} ;
2016-04-18 06:35:57 +03:00
static const struct rockchip_tsadc_chip rk3366_tsadc_data = {
2023-03-08 14:22:50 +03:00
/* cpu, gpu */
. chn_offset = 0 ,
2016-04-18 06:35:57 +03:00
. chn_num = 2 , /* two channels for tsadc */
. tshut_mode = TSHUT_MODE_GPIO , /* default TSHUT via GPIO give PMIC */
. tshut_polarity = TSHUT_LOW_ACTIVE , /* default TSHUT LOW ACTIVE */
. tshut_temp = 95000 ,
. initialize = rk_tsadcv3_initialize ,
. irq_ack = rk_tsadcv3_irq_ack ,
. control = rk_tsadcv3_control ,
. get_temp = rk_tsadcv2_get_temp ,
2016-06-22 11:42:05 +03:00
. set_alarm_temp = rk_tsadcv2_alarm_temp ,
2016-04-18 06:35:57 +03:00
. set_tshut_temp = rk_tsadcv2_tshut_temp ,
. set_tshut_mode = rk_tsadcv2_tshut_mode ,
. table = {
. id = rk3228_code_table ,
. length = ARRAY_SIZE ( rk3228_code_table ) ,
. data_mask = TSADCV3_DATA_MASK ,
. mode = ADC_INCREMENT ,
} ,
} ;
2015-11-09 07:48:59 +03:00
static const struct rockchip_tsadc_chip rk3368_tsadc_data = {
2023-03-08 14:22:50 +03:00
/* cpu, gpu */
. chn_offset = 0 ,
2015-11-09 07:48:59 +03:00
. chn_num = 2 , /* two channels for tsadc */
. tshut_mode = TSHUT_MODE_GPIO , /* default TSHUT via GPIO give PMIC */
. tshut_polarity = TSHUT_LOW_ACTIVE , /* default TSHUT LOW ACTIVE */
. tshut_temp = 95000 ,
. initialize = rk_tsadcv2_initialize ,
. irq_ack = rk_tsadcv2_irq_ack ,
. control = rk_tsadcv2_control ,
. get_temp = rk_tsadcv2_get_temp ,
2016-06-22 11:42:05 +03:00
. set_alarm_temp = rk_tsadcv2_alarm_temp ,
2015-11-09 07:48:59 +03:00
. set_tshut_temp = rk_tsadcv2_tshut_temp ,
. set_tshut_mode = rk_tsadcv2_tshut_mode ,
. table = {
2016-02-15 10:33:30 +03:00
. id = rk3368_code_table ,
. length = ARRAY_SIZE ( rk3368_code_table ) ,
2015-11-09 07:48:59 +03:00
. data_mask = TSADCV3_DATA_MASK ,
. mode = ADC_INCREMENT ,
} ,
} ;
2015-12-03 11:48:43 +03:00
static const struct rockchip_tsadc_chip rk3399_tsadc_data = {
2023-03-08 14:22:50 +03:00
/* cpu, gpu */
. chn_offset = 0 ,
2015-12-03 11:48:43 +03:00
. chn_num = 2 , /* two channels for tsadc */
. tshut_mode = TSHUT_MODE_GPIO , /* default TSHUT via GPIO give PMIC */
. tshut_polarity = TSHUT_LOW_ACTIVE , /* default TSHUT LOW ACTIVE */
. tshut_temp = 95000 ,
2016-04-18 06:35:56 +03:00
. initialize = rk_tsadcv3_initialize ,
2016-02-15 10:33:30 +03:00
. irq_ack = rk_tsadcv3_irq_ack ,
2016-02-15 10:33:31 +03:00
. control = rk_tsadcv3_control ,
2015-12-03 11:48:43 +03:00
. get_temp = rk_tsadcv2_get_temp ,
2016-06-22 11:42:05 +03:00
. set_alarm_temp = rk_tsadcv2_alarm_temp ,
2015-12-03 11:48:43 +03:00
. set_tshut_temp = rk_tsadcv2_tshut_temp ,
. set_tshut_mode = rk_tsadcv2_tshut_mode ,
. table = {
2016-02-15 10:33:30 +03:00
. id = rk3399_code_table ,
. length = ARRAY_SIZE ( rk3399_code_table ) ,
2015-12-03 11:48:43 +03:00
. data_mask = TSADCV3_DATA_MASK ,
2016-02-15 10:33:31 +03:00
. mode = ADC_INCREMENT ,
2015-12-03 11:48:43 +03:00
} ,
} ;
2021-05-06 20:55:14 +03:00
static const struct rockchip_tsadc_chip rk3568_tsadc_data = {
2023-03-08 14:22:50 +03:00
/* cpu, gpu */
. chn_offset = 0 ,
2021-05-06 20:55:14 +03:00
. chn_num = 2 , /* two channels for tsadc */
. tshut_mode = TSHUT_MODE_GPIO , /* default TSHUT via GPIO give PMIC */
. tshut_polarity = TSHUT_LOW_ACTIVE , /* default TSHUT LOW ACTIVE */
. tshut_temp = 95000 ,
. initialize = rk_tsadcv7_initialize ,
. irq_ack = rk_tsadcv3_irq_ack ,
. control = rk_tsadcv3_control ,
. get_temp = rk_tsadcv2_get_temp ,
. set_alarm_temp = rk_tsadcv2_alarm_temp ,
. set_tshut_temp = rk_tsadcv2_tshut_temp ,
. set_tshut_mode = rk_tsadcv2_tshut_mode ,
. table = {
. id = rk3568_code_table ,
. length = ARRAY_SIZE ( rk3568_code_table ) ,
. data_mask = TSADCV2_DATA_MASK ,
. mode = ADC_INCREMENT ,
} ,
} ;
2023-03-08 14:22:52 +03:00
static const struct rockchip_tsadc_chip rk3588_tsadc_data = {
/* top, big_core0, big_core1, little_core, center, gpu, npu */
. chn_offset = 0 ,
. chn_num = 7 , /* seven channels for tsadc */
. tshut_mode = TSHUT_MODE_GPIO , /* default TSHUT via GPIO give PMIC */
. tshut_polarity = TSHUT_LOW_ACTIVE , /* default TSHUT LOW ACTIVE */
. tshut_temp = 95000 ,
. initialize = rk_tsadcv8_initialize ,
. irq_ack = rk_tsadcv4_irq_ack ,
. control = rk_tsadcv4_control ,
. get_temp = rk_tsadcv4_get_temp ,
. set_alarm_temp = rk_tsadcv3_alarm_temp ,
. set_tshut_temp = rk_tsadcv3_tshut_temp ,
. set_tshut_mode = rk_tsadcv3_tshut_mode ,
. table = {
. id = rk3588_code_table ,
. length = ARRAY_SIZE ( rk3588_code_table ) ,
. data_mask = TSADCV4_DATA_MASK ,
. mode = ADC_INCREMENT ,
} ,
} ;
2014-11-24 07:58:59 +03:00
static const struct of_device_id of_rockchip_thermal_match [ ] = {
2019-04-30 13:09:46 +03:00
{ . compatible = " rockchip,px30-tsadc " ,
. data = ( void * ) & px30_tsadc_data ,
} ,
2017-08-24 13:27:52 +03:00
{
. compatible = " rockchip,rv1108-tsadc " ,
. data = ( void * ) & rv1108_tsadc_data ,
} ,
2015-12-03 11:48:42 +03:00
{
. compatible = " rockchip,rk3228-tsadc " ,
. data = ( void * ) & rk3228_tsadc_data ,
} ,
2014-11-24 07:58:59 +03:00
{
. compatible = " rockchip,rk3288-tsadc " ,
. data = ( void * ) & rk3288_tsadc_data ,
} ,
2017-08-04 11:06:13 +03:00
{
. compatible = " rockchip,rk3328-tsadc " ,
. data = ( void * ) & rk3328_tsadc_data ,
} ,
2016-04-18 06:35:57 +03:00
{
. compatible = " rockchip,rk3366-tsadc " ,
. data = ( void * ) & rk3366_tsadc_data ,
} ,
2015-11-09 07:48:59 +03:00
{
. compatible = " rockchip,rk3368-tsadc " ,
. data = ( void * ) & rk3368_tsadc_data ,
} ,
2015-12-03 11:48:43 +03:00
{
. compatible = " rockchip,rk3399-tsadc " ,
. data = ( void * ) & rk3399_tsadc_data ,
} ,
2021-05-06 20:55:14 +03:00
{
. compatible = " rockchip,rk3568-tsadc " ,
. data = ( void * ) & rk3568_tsadc_data ,
} ,
2023-03-08 14:22:52 +03:00
{
. compatible = " rockchip,rk3588-tsadc " ,
. data = ( void * ) & rk3588_tsadc_data ,
} ,
2014-11-24 07:58:59 +03:00
{ /* end */ } ,
} ;
MODULE_DEVICE_TABLE ( of , of_rockchip_thermal_match ) ;
static void
rockchip_thermal_toggle_sensor ( struct rockchip_thermal_sensor * sensor , bool on )
{
struct thermal_zone_device * tzd = sensor - > tzd ;
thermal: Use mode helpers in drivers
Use thermal_zone_device_{en|dis}able() and thermal_zone_device_is_enabled().
Consequently, all set_mode() implementations in drivers:
- can stop modifying tzd's "mode" member,
- shall stop taking tzd's lock, as it is taken in the helpers
- shall stop calling thermal_zone_device_update() as it is called in the
helpers
- can assume they are called when the mode truly changes, so checks to
verify that can be dropped
Not providing set_mode() by a driver no longer prevents the core from
being able to set tzd's mode, so the relevant check in mode_store() is
removed.
Other comments:
- acpi/thermal.c: tz->thermal_zone->mode will be updated only after we
return from set_mode(), so use function parameter in thermal_set_mode()
instead, no need to call acpi_thermal_check() in set_mode()
- thermal/imx_thermal.c: regmap writes and mode assignment are done in
thermal_zone_device_{en|dis}able() and set_mode() callback
- thermal/intel/intel_quark_dts_thermal.c: soc_dts_{en|dis}able() are a
part of set_mode() callback, so they don't need to modify tzd->mode, and
don't need to fall back to the opposite mode if unsuccessful, as the return
value will be propagated to thermal_zone_device_{en|dis}able() and
ultimately tzd's member will not be changed in thermal_zone_device_set_mode().
- thermal/of-thermal.c: no need to set zone->mode to DISABLED in
of_parse_thermal_zones() as a tzd is kzalloc'ed so mode is DISABLED anyway
Signed-off-by: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
[for acerhdf]
Acked-by: Peter Kaestle <peter@piie.net>
Reviewed-by: Amit Kucheria <amit.kucheria@linaro.org>
Reviewed-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Link: https://lore.kernel.org/r/20200629122925.21729-8-andrzej.p@collabora.com
2020-06-29 15:29:21 +03:00
if ( on )
thermal_zone_device_enable ( tzd ) ;
else
thermal_zone_device_disable ( tzd ) ;
2014-11-24 07:58:59 +03:00
}
static irqreturn_t rockchip_thermal_alarm_irq_thread ( int irq , void * dev )
{
struct rockchip_thermal_data * thermal = dev ;
int i ;
dev_dbg ( & thermal - > pdev - > dev , " thermal alarm \n " ) ;
thermal - > chip - > irq_ack ( thermal - > regs ) ;
2015-11-05 08:17:58 +03:00
for ( i = 0 ; i < thermal - > chip - > chn_num ; i + + )
2016-08-27 02:21:16 +03:00
thermal_zone_device_update ( thermal - > sensors [ i ] . tzd ,
THERMAL_EVENT_UNSPECIFIED ) ;
2014-11-24 07:58:59 +03:00
return IRQ_HANDLED ;
}
2022-08-05 01:43:19 +03:00
static int rockchip_thermal_set_trips ( struct thermal_zone_device * tz , int low , int high )
2016-06-22 11:42:05 +03:00
{
2023-03-01 23:14:30 +03:00
struct rockchip_thermal_sensor * sensor = thermal_zone_device_priv ( tz ) ;
2016-06-22 11:42:05 +03:00
struct rockchip_thermal_data * thermal = sensor - > thermal ;
const struct rockchip_tsadc_chip * tsadc = thermal - > chip ;
dev_dbg ( & thermal - > pdev - > dev , " %s: sensor %d: low: %d, high %d \n " ,
__func__ , sensor - > id , low , high ) ;
2016-12-12 14:05:33 +03:00
return tsadc - > set_alarm_temp ( & tsadc - > table ,
sensor - > id , thermal - > regs , high ) ;
2016-06-22 11:42:05 +03:00
}
2022-08-05 01:43:19 +03:00
static int rockchip_thermal_get_temp ( struct thermal_zone_device * tz , int * out_temp )
2014-11-24 07:58:59 +03:00
{
2023-03-01 23:14:30 +03:00
struct rockchip_thermal_sensor * sensor = thermal_zone_device_priv ( tz ) ;
2014-11-24 07:58:59 +03:00
struct rockchip_thermal_data * thermal = sensor - > thermal ;
const struct rockchip_tsadc_chip * tsadc = sensor - > thermal - > chip ;
int retval ;
2016-12-12 14:05:32 +03:00
retval = tsadc - > get_temp ( & tsadc - > table ,
2015-11-09 07:48:56 +03:00
sensor - > id , thermal - > regs , out_temp ) ;
2014-11-24 07:58:59 +03:00
return retval ;
}
2022-08-05 01:43:19 +03:00
static const struct thermal_zone_device_ops rockchip_of_thermal_ops = {
2014-11-24 07:58:59 +03:00
. get_temp = rockchip_thermal_get_temp ,
2016-06-22 11:42:05 +03:00
. set_trips = rockchip_thermal_set_trips ,
2014-11-24 07:58:59 +03:00
} ;
static int rockchip_configure_from_dt ( struct device * dev ,
struct device_node * np ,
struct rockchip_thermal_data * thermal )
{
u32 shut_temp , tshut_mode , tshut_polarity ;
if ( of_property_read_u32 ( np , " rockchip,hw-tshut-temp " , & shut_temp ) ) {
dev_warn ( dev ,
2015-11-09 07:48:58 +03:00
" Missing tshut temp property, using default %d \n " ,
2014-11-24 07:58:59 +03:00
thermal - > chip - > tshut_temp ) ;
thermal - > tshut_temp = thermal - > chip - > tshut_temp ;
} else {
2016-02-15 10:33:28 +03:00
if ( shut_temp > INT_MAX ) {
dev_err ( dev , " Invalid tshut temperature specified: %d \n " ,
shut_temp ) ;
return - ERANGE ;
}
2014-11-24 07:58:59 +03:00
thermal - > tshut_temp = shut_temp ;
}
if ( of_property_read_u32 ( np , " rockchip,hw-tshut-mode " , & tshut_mode ) ) {
dev_warn ( dev ,
" Missing tshut mode property, using default (%s) \n " ,
thermal - > chip - > tshut_mode = = TSHUT_MODE_GPIO ?
" gpio " : " cru " ) ;
thermal - > tshut_mode = thermal - > chip - > tshut_mode ;
} else {
thermal - > tshut_mode = tshut_mode ;
}
if ( thermal - > tshut_mode > 1 ) {
dev_err ( dev , " Invalid tshut mode specified: %d \n " ,
thermal - > tshut_mode ) ;
return - EINVAL ;
}
if ( of_property_read_u32 ( np , " rockchip,hw-tshut-polarity " ,
& tshut_polarity ) ) {
dev_warn ( dev ,
" Missing tshut-polarity property, using default (%s) \n " ,
thermal - > chip - > tshut_polarity = = TSHUT_LOW_ACTIVE ?
" low " : " high " ) ;
thermal - > tshut_polarity = thermal - > chip - > tshut_polarity ;
} else {
thermal - > tshut_polarity = tshut_polarity ;
}
if ( thermal - > tshut_polarity > 1 ) {
dev_err ( dev , " Invalid tshut-polarity specified: %d \n " ,
thermal - > tshut_polarity ) ;
return - EINVAL ;
}
2016-04-18 06:35:56 +03:00
/* The tsadc wont to handle the error in here since some SoCs didn't
* need this property .
*/
thermal - > grf = syscon_regmap_lookup_by_phandle ( np , " rockchip,grf " ) ;
2016-10-11 05:07:34 +03:00
if ( IS_ERR ( thermal - > grf ) )
dev_warn ( dev , " Missing rockchip,grf property \n " ) ;
2016-04-18 06:35:56 +03:00
2014-11-24 07:58:59 +03:00
return 0 ;
}
static int
rockchip_thermal_register_sensor ( struct platform_device * pdev ,
struct rockchip_thermal_data * thermal ,
struct rockchip_thermal_sensor * sensor ,
2015-11-05 08:17:58 +03:00
int id )
2014-11-24 07:58:59 +03:00
{
const struct rockchip_tsadc_chip * tsadc = thermal - > chip ;
int error ;
tsadc - > set_tshut_mode ( id , thermal - > regs , thermal - > tshut_mode ) ;
2016-12-12 14:05:33 +03:00
error = tsadc - > set_tshut_temp ( & tsadc - > table , id , thermal - > regs ,
2015-11-09 07:48:56 +03:00
thermal - > tshut_temp ) ;
2016-12-12 14:05:33 +03:00
if ( error )
dev_err ( & pdev - > dev , " %s: invalid tshut=%d, error=%d \n " ,
__func__ , thermal - > tshut_temp , error ) ;
2014-11-24 07:58:59 +03:00
sensor - > thermal = thermal ;
sensor - > id = id ;
2022-08-05 01:43:19 +03:00
sensor - > tzd = devm_thermal_of_zone_register ( & pdev - > dev , id , sensor ,
& rockchip_of_thermal_ops ) ;
2014-11-24 07:58:59 +03:00
if ( IS_ERR ( sensor - > tzd ) ) {
error = PTR_ERR ( sensor - > tzd ) ;
dev_err ( & pdev - > dev , " failed to register sensor %d: %d \n " ,
id , error ) ;
return error ;
}
return 0 ;
}
2015-12-03 11:48:39 +03:00
/**
2023-01-13 09:45:00 +03:00
* rockchip_thermal_reset_controller - Reset TSADC Controller , reset all tsadc registers .
2019-11-20 18:45:16 +03:00
* @ reset : the reset controller of tsadc
2014-11-24 07:58:59 +03:00
*/
static void rockchip_thermal_reset_controller ( struct reset_control * reset )
{
reset_control_assert ( reset ) ;
usleep_range ( 10 , 20 ) ;
reset_control_deassert ( reset ) ;
}
static int rockchip_thermal_probe ( struct platform_device * pdev )
{
struct device_node * np = pdev - > dev . of_node ;
struct rockchip_thermal_data * thermal ;
int irq ;
2016-03-10 00:10:28 +03:00
int i ;
2014-11-24 07:58:59 +03:00
int error ;
irq = platform_get_irq ( pdev , 0 ) ;
2020-04-05 19:35:16 +03:00
if ( irq < 0 )
2014-11-24 07:58:59 +03:00
return - EINVAL ;
thermal = devm_kzalloc ( & pdev - > dev , sizeof ( struct rockchip_thermal_data ) ,
GFP_KERNEL ) ;
if ( ! thermal )
return - ENOMEM ;
thermal - > pdev = pdev ;
2023-03-08 14:22:47 +03:00
thermal - > chip = device_get_match_data ( & pdev - > dev ) ;
2014-11-24 07:58:59 +03:00
if ( ! thermal - > chip )
return - EINVAL ;
2023-03-08 14:22:51 +03:00
thermal - > sensors = devm_kcalloc ( & pdev - > dev , thermal - > chip - > chn_num ,
sizeof ( * thermal - > sensors ) , GFP_KERNEL ) ;
if ( ! thermal - > sensors )
return - ENOMEM ;
2023-01-18 11:39:30 +03:00
thermal - > regs = devm_platform_get_and_ioremap_resource ( pdev , 0 , NULL ) ;
2014-11-24 07:58:59 +03:00
if ( IS_ERR ( thermal - > regs ) )
return PTR_ERR ( thermal - > regs ) ;
2023-03-24 06:08:55 +03:00
thermal - > reset = devm_reset_control_array_get_exclusive ( & pdev - > dev ) ;
2023-03-08 14:22:49 +03:00
if ( IS_ERR ( thermal - > reset ) )
return dev_err_probe ( & pdev - > dev , PTR_ERR ( thermal - > reset ) ,
" failed to get tsadc reset. \n " ) ;
2014-11-24 07:58:59 +03:00
2023-03-08 14:22:48 +03:00
thermal - > clk = devm_clk_get_enabled ( & pdev - > dev , " tsadc " ) ;
2023-03-08 14:22:49 +03:00
if ( IS_ERR ( thermal - > clk ) )
return dev_err_probe ( & pdev - > dev , PTR_ERR ( thermal - > clk ) ,
" failed to get tsadc clock. \n " ) ;
2014-11-24 07:58:59 +03:00
2023-03-08 14:22:48 +03:00
thermal - > pclk = devm_clk_get_enabled ( & pdev - > dev , " apb_pclk " ) ;
2023-03-08 14:22:49 +03:00
if ( IS_ERR ( thermal - > pclk ) )
return dev_err_probe ( & pdev - > dev , PTR_ERR ( thermal - > pclk ) ,
" failed to get apb_pclk clock. \n " ) ;
2014-11-24 07:58:59 +03:00
rockchip_thermal_reset_controller ( thermal - > reset ) ;
error = rockchip_configure_from_dt ( & pdev - > dev , np , thermal ) ;
2023-03-08 14:22:49 +03:00
if ( error )
return dev_err_probe ( & pdev - > dev , error ,
" failed to parse device tree data \n " ) ;
2014-11-24 07:58:59 +03:00
2016-04-18 06:35:56 +03:00
thermal - > chip - > initialize ( thermal - > grf , thermal - > regs ,
thermal - > tshut_polarity ) ;
2014-11-24 07:58:59 +03:00
2015-11-05 08:17:58 +03:00
for ( i = 0 ; i < thermal - > chip - > chn_num ; i + + ) {
error = rockchip_thermal_register_sensor ( pdev , thermal ,
& thermal - > sensors [ i ] ,
2023-03-08 14:22:50 +03:00
thermal - > chip - > chn_offset + i ) ;
2023-03-08 14:22:49 +03:00
if ( error )
return dev_err_probe ( & pdev - > dev , error ,
" failed to register sensor[%d]. \n " , i ) ;
2014-11-24 07:58:59 +03:00
}
error = devm_request_threaded_irq ( & pdev - > dev , irq , NULL ,
& rockchip_thermal_alarm_irq_thread ,
IRQF_ONESHOT ,
" rockchip_thermal " , thermal ) ;
2023-03-08 14:22:49 +03:00
if ( error )
return dev_err_probe ( & pdev - > dev , error ,
" failed to request tsadc irq. \n " ) ;
2014-11-24 07:58:59 +03:00
thermal - > chip - > control ( thermal - > regs , true ) ;
2019-12-12 09:17:02 +03:00
for ( i = 0 ; i < thermal - > chip - > chn_num ; i + + ) {
2014-11-24 07:58:59 +03:00
rockchip_thermal_toggle_sensor ( & thermal - > sensors [ i ] , true ) ;
2019-12-12 09:17:02 +03:00
error = thermal_add_hwmon_sysfs ( thermal - > sensors [ i ] . tzd ) ;
if ( error )
dev_warn ( & pdev - > dev ,
" failed to register sensor %d with hwmon: %d \n " ,
i , error ) ;
}
2014-11-24 07:58:59 +03:00
platform_set_drvdata ( pdev , thermal ) ;
return 0 ;
}
static int rockchip_thermal_remove ( struct platform_device * pdev )
{
struct rockchip_thermal_data * thermal = platform_get_drvdata ( pdev ) ;
int i ;
2015-11-05 08:17:58 +03:00
for ( i = 0 ; i < thermal - > chip - > chn_num ; i + + ) {
2014-11-24 07:58:59 +03:00
struct rockchip_thermal_sensor * sensor = & thermal - > sensors [ i ] ;
2019-12-12 09:17:02 +03:00
thermal_remove_hwmon_sysfs ( sensor - > tzd ) ;
2014-11-24 07:58:59 +03:00
rockchip_thermal_toggle_sensor ( sensor , false ) ;
}
thermal - > chip - > control ( thermal - > regs , false ) ;
return 0 ;
}
static int __maybe_unused rockchip_thermal_suspend ( struct device * dev )
{
2018-10-21 23:00:49 +03:00
struct rockchip_thermal_data * thermal = dev_get_drvdata ( dev ) ;
2014-11-24 07:58:59 +03:00
int i ;
2015-11-05 08:17:58 +03:00
for ( i = 0 ; i < thermal - > chip - > chn_num ; i + + )
2014-11-24 07:58:59 +03:00
rockchip_thermal_toggle_sensor ( & thermal - > sensors [ i ] , false ) ;
thermal - > chip - > control ( thermal - > regs , false ) ;
clk_disable ( thermal - > pclk ) ;
clk_disable ( thermal - > clk ) ;
2019-05-22 17:12:36 +03:00
pinctrl_pm_select_sleep_state ( dev ) ;
2015-10-23 14:25:27 +03:00
2014-11-24 07:58:59 +03:00
return 0 ;
}
static int __maybe_unused rockchip_thermal_resume ( struct device * dev )
{
2018-10-21 23:00:49 +03:00
struct rockchip_thermal_data * thermal = dev_get_drvdata ( dev ) ;
2014-11-24 07:58:59 +03:00
int i ;
int error ;
error = clk_enable ( thermal - > clk ) ;
if ( error )
return error ;
error = clk_enable ( thermal - > pclk ) ;
2016-04-18 06:35:53 +03:00
if ( error ) {
clk_disable ( thermal - > clk ) ;
2014-11-24 07:58:59 +03:00
return error ;
2016-04-18 06:35:53 +03:00
}
2014-11-24 07:58:59 +03:00
rockchip_thermal_reset_controller ( thermal - > reset ) ;
2016-04-18 06:35:56 +03:00
thermal - > chip - > initialize ( thermal - > grf , thermal - > regs ,
thermal - > tshut_polarity ) ;
2014-11-24 07:58:59 +03:00
2015-11-05 08:17:58 +03:00
for ( i = 0 ; i < thermal - > chip - > chn_num ; i + + ) {
int id = thermal - > sensors [ i ] . id ;
2014-11-24 07:58:59 +03:00
thermal - > chip - > set_tshut_mode ( id , thermal - > regs ,
thermal - > tshut_mode ) ;
2016-12-12 14:05:33 +03:00
error = thermal - > chip - > set_tshut_temp ( & thermal - > chip - > table ,
2015-11-09 07:48:56 +03:00
id , thermal - > regs ,
2014-11-24 07:58:59 +03:00
thermal - > tshut_temp ) ;
2016-12-12 14:05:33 +03:00
if ( error )
2018-10-21 23:00:49 +03:00
dev_err ( dev , " %s: invalid tshut=%d, error=%d \n " ,
2016-12-12 14:05:33 +03:00
__func__ , thermal - > tshut_temp , error ) ;
2014-11-24 07:58:59 +03:00
}
thermal - > chip - > control ( thermal - > regs , true ) ;
2015-11-05 08:17:58 +03:00
for ( i = 0 ; i < thermal - > chip - > chn_num ; i + + )
2014-11-24 07:58:59 +03:00
rockchip_thermal_toggle_sensor ( & thermal - > sensors [ i ] , true ) ;
2019-05-22 17:12:36 +03:00
pinctrl_pm_select_default_state ( dev ) ;
2015-10-23 14:25:27 +03:00
2014-11-24 07:58:59 +03:00
return 0 ;
}
static SIMPLE_DEV_PM_OPS ( rockchip_thermal_pm_ops ,
rockchip_thermal_suspend , rockchip_thermal_resume ) ;
static struct platform_driver rockchip_thermal_driver = {
. driver = {
. name = " rockchip-thermal " ,
. pm = & rockchip_thermal_pm_ops ,
. of_match_table = of_rockchip_thermal_match ,
} ,
. probe = rockchip_thermal_probe ,
. remove = rockchip_thermal_remove ,
} ;
module_platform_driver ( rockchip_thermal_driver ) ;
MODULE_DESCRIPTION ( " ROCKCHIP THERMAL Driver " ) ;
MODULE_AUTHOR ( " Rockchip, Inc. " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_ALIAS ( " platform:rockchip-thermal " ) ;