13d0407baSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
23d0407baSopenharmony_ci/*
33d0407baSopenharmony_ci * Copyright (c) 2014-2016, Fuzhou Rockchip Electronics Co., Ltd
43d0407baSopenharmony_ci * Caesar Wang <wxt@rock-chips.com>
53d0407baSopenharmony_ci */
63d0407baSopenharmony_ci
73d0407baSopenharmony_ci#include <linux/clk.h>
83d0407baSopenharmony_ci#include <linux/delay.h>
93d0407baSopenharmony_ci#include <linux/interrupt.h>
103d0407baSopenharmony_ci#include <linux/io.h>
113d0407baSopenharmony_ci#include <linux/module.h>
123d0407baSopenharmony_ci#include <linux/of.h>
133d0407baSopenharmony_ci#include <linux/of_address.h>
143d0407baSopenharmony_ci#include <linux/of_irq.h>
153d0407baSopenharmony_ci#include <linux/platform_device.h>
163d0407baSopenharmony_ci#include <linux/regmap.h>
173d0407baSopenharmony_ci#include <linux/reset.h>
183d0407baSopenharmony_ci#include <linux/thermal.h>
193d0407baSopenharmony_ci#include <linux/mfd/syscon.h>
203d0407baSopenharmony_ci#include <linux/pinctrl/consumer.h>
213d0407baSopenharmony_ci#include <linux/nvmem-consumer.h>
223d0407baSopenharmony_ci
233d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_TWO 2
243d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_EIGHT 8
253d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_TEN 10
263d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_FIFTEEN 15
273d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_TWENTY 20
283d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_THIRTYTWO 32
293d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_NINETY 90
303d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_ONEHUNDRED 100
313d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_TWOHUNDRED 200
323d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_FIVEHUNDRED 500
333d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_ONETHOUSAND 1000
343d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_TENTHOUSAND 10000
353d0407baSopenharmony_ci#define ROCKCHIP_THERMAL_NINETYFIVETHOUSAND 95000
363d0407baSopenharmony_ci
373d0407baSopenharmony_ci/*
383d0407baSopenharmony_ci * If the temperature over a period of time High,
393d0407baSopenharmony_ci * the resulting TSHUT gave CRU module,let it reset the entire chip,
403d0407baSopenharmony_ci * or via GPIO give PMIC.
413d0407baSopenharmony_ci */
423d0407baSopenharmony_cienum tshut_mode {
433d0407baSopenharmony_ci    TSHUT_MODE_CRU = 0,
443d0407baSopenharmony_ci    TSHUT_MODE_OTP,
453d0407baSopenharmony_ci};
463d0407baSopenharmony_ci
473d0407baSopenharmony_ci/*
483d0407baSopenharmony_ci * The system Temperature Sensors tshut(tshut) polarity
493d0407baSopenharmony_ci * the bit 8 is tshut polarity.
503d0407baSopenharmony_ci * 0: low active, 1: high active
513d0407baSopenharmony_ci */
523d0407baSopenharmony_cienum tshut_polarity {
533d0407baSopenharmony_ci    TSHUT_LOW_ACTIVE = 0,
543d0407baSopenharmony_ci    TSHUT_HIGH_ACTIVE,
553d0407baSopenharmony_ci};
563d0407baSopenharmony_ci
573d0407baSopenharmony_ci/*
583d0407baSopenharmony_ci * The system has two Temperature Sensors.
593d0407baSopenharmony_ci * sensor0 is for CPU, and sensor1 is for GPU.
603d0407baSopenharmony_ci */
613d0407baSopenharmony_cienum sensor_id {
623d0407baSopenharmony_ci    SENSOR_CPU = 0,
633d0407baSopenharmony_ci    SENSOR_GPU,
643d0407baSopenharmony_ci};
653d0407baSopenharmony_ci
663d0407baSopenharmony_ci/*
673d0407baSopenharmony_ci * The conversion table has the adc value and temperature.
683d0407baSopenharmony_ci * ADC_DECREMENT: the adc value is of diminishing.(e.g. rk3288_code_table)
693d0407baSopenharmony_ci * ADC_INCREMENT: the adc value is incremental.(e.g. rk3368_code_table)
703d0407baSopenharmony_ci */
713d0407baSopenharmony_cienum adc_sort_mode {
723d0407baSopenharmony_ci    ADC_DECREMENT = 0,
733d0407baSopenharmony_ci    ADC_INCREMENT,
743d0407baSopenharmony_ci};
753d0407baSopenharmony_ci
763d0407baSopenharmony_ci#include "thermal_hwmon.h"
773d0407baSopenharmony_ci
783d0407baSopenharmony_ci/**
793d0407baSopenharmony_ci * The max sensors is two in rockchip SoCs.
803d0407baSopenharmony_ci * Two sensors: CPU and GPU sensor.
813d0407baSopenharmony_ci */
823d0407baSopenharmony_ci#define SOC_MAX_SENSORS 2
833d0407baSopenharmony_ci
843d0407baSopenharmony_ci/**
853d0407baSopenharmony_ci * struct chip_tsadc_table - hold information about chip-specific differences
863d0407baSopenharmony_ci * @id: conversion table
873d0407baSopenharmony_ci * @length: size of conversion table
883d0407baSopenharmony_ci * @data_mask: mask to apply on data inputs
893d0407baSopenharmony_ci * @kNum: linear parameter k
903d0407baSopenharmony_ci * @bNum: linear parameter b
913d0407baSopenharmony_ci * @mode: sort mode of this adc variant (incrementing or decrementing)
923d0407baSopenharmony_ci */
933d0407baSopenharmony_cistruct chip_tsadc_table {
943d0407baSopenharmony_ci    const struct tsadc_table *id;
953d0407baSopenharmony_ci    unsigned int length;
963d0407baSopenharmony_ci    u32 data_mask;
973d0407baSopenharmony_ci    /* Tsadc is linear, using linear parameters */
983d0407baSopenharmony_ci    int kNum;
993d0407baSopenharmony_ci    int bNum;
1003d0407baSopenharmony_ci    enum adc_sort_mode mode;
1013d0407baSopenharmony_ci};
1023d0407baSopenharmony_ci
1033d0407baSopenharmony_ci/**
1043d0407baSopenharmony_ci * struct rockchip_tsadc_chip - hold the private data of tsadc chip
1053d0407baSopenharmony_ci * @chn_id: array of sensor ids of chip corresponding to the channel
1063d0407baSopenharmony_ci * @chn_num: the channel number of tsadc chip
1073d0407baSopenharmony_ci * @tshut_temp: the hardware-controlled shutdown temperature value
1083d0407baSopenharmony_ci * @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO)
1093d0407baSopenharmony_ci * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
1103d0407baSopenharmony_ci * @initialize: SoC special initialize tsadc controller method
1113d0407baSopenharmony_ci * @irq_ack: clear the interrupt
1123d0407baSopenharmony_ci * @control: enable/disable method for the tsadc controller
1133d0407baSopenharmony_ci * @get_temp: get the temperature
1143d0407baSopenharmony_ci * @set_alarm_temp: set the high temperature interrupt
1153d0407baSopenharmony_ci * @set_tshut_temp: set the hardware-controlled shutdown temperature
1163d0407baSopenharmony_ci * @set_tshut_mode: set the hardware-controlled shutdown mode
1173d0407baSopenharmony_ci * @get_trim_code: get the trim code by otp value
1183d0407baSopenharmony_ci * @trim_temp: get trim temp by trim code
1193d0407baSopenharmony_ci * @table: the chip-specific conversion table
1203d0407baSopenharmony_ci */
1213d0407baSopenharmony_cistruct rockchip_tsadc_chip {
1223d0407baSopenharmony_ci    /* The sensor id of chip correspond to the ADC channel */
1233d0407baSopenharmony_ci    int chn_id[SOC_MAX_SENSORS];
1243d0407baSopenharmony_ci    int chn_num;
1253d0407baSopenharmony_ci
1263d0407baSopenharmony_ci    /* The hardware-controlled tshut property */
1273d0407baSopenharmony_ci    int tshut_temp;
1283d0407baSopenharmony_ci    enum tshut_mode tshut_mode;
1293d0407baSopenharmony_ci    enum tshut_polarity tshut_polarity;
1303d0407baSopenharmony_ci
1313d0407baSopenharmony_ci    /* Chip-wide methods */
1323d0407baSopenharmony_ci    void (*initialize)(struct regmap *grf, void __iomem *reg, enum tshut_polarity p);
1333d0407baSopenharmony_ci    void (*irq_ack)(void __iomem *reg);
1343d0407baSopenharmony_ci    void (*control)(void __iomem *reg, bool on);
1353d0407baSopenharmony_ci
1363d0407baSopenharmony_ci    /* Per-sensor methods */
1373d0407baSopenharmony_ci    int (*get_temp)(const struct chip_tsadc_table *table, int chn, void __iomem *reg, int *temp);
1383d0407baSopenharmony_ci    int (*set_alarm_temp)(const struct chip_tsadc_table *table, int chn, void __iomem *reg, int temp);
1393d0407baSopenharmony_ci    int (*set_tshut_temp)(const struct chip_tsadc_table *table, int chn, void __iomem *reg, int temp);
1403d0407baSopenharmony_ci    void (*set_tshut_mode)(struct regmap *grf, int chn, void __iomem *reg, enum tshut_mode m);
1413d0407baSopenharmony_ci    int (*get_trim_code)(struct platform_device *pdev, int code, int trim_base);
1423d0407baSopenharmony_ci    int (*trim_temp)(struct platform_device *pdev);
1433d0407baSopenharmony_ci
1443d0407baSopenharmony_ci    /* Per-table methods */
1453d0407baSopenharmony_ci    struct chip_tsadc_table table;
1463d0407baSopenharmony_ci};
1473d0407baSopenharmony_ci
1483d0407baSopenharmony_ci/**
1493d0407baSopenharmony_ci * struct rockchip_thermal_sensor - hold the information of thermal sensor
1503d0407baSopenharmony_ci * @thermal:  pointer to the platform/configuration data
1513d0407baSopenharmony_ci * @tzd: pointer to a thermal zone
1523d0407baSopenharmony_ci * @id: identifier of the thermal sensor
1533d0407baSopenharmony_ci */
1543d0407baSopenharmony_cistruct rockchip_thermal_sensor {
1553d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal;
1563d0407baSopenharmony_ci    struct thermal_zone_device *tzd;
1573d0407baSopenharmony_ci    int id;
1583d0407baSopenharmony_ci};
1593d0407baSopenharmony_ci
1603d0407baSopenharmony_ci/**
1613d0407baSopenharmony_ci * struct rockchip_thermal_data - hold the private data of thermal driver
1623d0407baSopenharmony_ci * @chip: pointer to the platform/configuration data
1633d0407baSopenharmony_ci * @pdev: platform device of thermal
1643d0407baSopenharmony_ci * @reset: the reset controller of tsadc
1653d0407baSopenharmony_ci * @sensors: array of thermal sensors
1663d0407baSopenharmony_ci * @clk: the bulk clk of tsadc, include controller clock and peripherals bus clock
1673d0407baSopenharmony_ci * @num_clks: the number of tsadc clks
1683d0407baSopenharmony_ci * @grf: the general register file will be used to do static set by software
1693d0407baSopenharmony_ci * @regs: the base address of tsadc controller
1703d0407baSopenharmony_ci * @tshut_temp: the hardware-controlled shutdown temperature value
1713d0407baSopenharmony_ci * @trim: trimmed value
1723d0407baSopenharmony_ci * @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO)
1733d0407baSopenharmony_ci * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
1743d0407baSopenharmony_ci * @pinctrl: the pinctrl of tsadc
1753d0407baSopenharmony_ci * @gpio_state: pinctrl select gpio function
1763d0407baSopenharmony_ci * @otp_state: pinctrl select otp out function
1773d0407baSopenharmony_ci * @panic_nb: panic notifier block
1783d0407baSopenharmony_ci */
1793d0407baSopenharmony_cistruct rockchip_thermal_data {
1803d0407baSopenharmony_ci    const struct rockchip_tsadc_chip *chip;
1813d0407baSopenharmony_ci    struct platform_device *pdev;
1823d0407baSopenharmony_ci    struct reset_control *reset;
1833d0407baSopenharmony_ci
1843d0407baSopenharmony_ci    struct rockchip_thermal_sensor sensors[SOC_MAX_SENSORS];
1853d0407baSopenharmony_ci
1863d0407baSopenharmony_ci    struct clk_bulk_data *clks;
1873d0407baSopenharmony_ci    int num_clks;
1883d0407baSopenharmony_ci
1893d0407baSopenharmony_ci    struct regmap *grf;
1903d0407baSopenharmony_ci    void __iomem *regs;
1913d0407baSopenharmony_ci
1923d0407baSopenharmony_ci    int tshut_temp;
1933d0407baSopenharmony_ci    int trim;
1943d0407baSopenharmony_ci    enum tshut_mode tshut_mode;
1953d0407baSopenharmony_ci    enum tshut_polarity tshut_polarity;
1963d0407baSopenharmony_ci    struct pinctrl *pinctrl;
1973d0407baSopenharmony_ci    struct pinctrl_state *gpio_state;
1983d0407baSopenharmony_ci    struct pinctrl_state *otp_state;
1993d0407baSopenharmony_ci
2003d0407baSopenharmony_ci    struct notifier_block panic_nb;
2013d0407baSopenharmony_ci};
2023d0407baSopenharmony_ci
2033d0407baSopenharmony_ci/**
2043d0407baSopenharmony_ci * TSADC Sensor Register description:
2053d0407baSopenharmony_ci *
2063d0407baSopenharmony_ci * TSADCV2_* are used for RK3288 SoCs, the other chips can reuse it.
2073d0407baSopenharmony_ci * TSADCV3_* are used for newer SoCs than RK3288. (e.g: RK3228, RK3399)
2083d0407baSopenharmony_ci *
2093d0407baSopenharmony_ci */
2103d0407baSopenharmony_ci#define TSADCV2_USER_CON 0x00
2113d0407baSopenharmony_ci#define TSADCV2_AUTO_CON 0x04
2123d0407baSopenharmony_ci#define TSADCV2_INT_EN 0x08
2133d0407baSopenharmony_ci#define TSADCV2_INT_PD 0x0c
2143d0407baSopenharmony_ci#define TSADCV2_DATA(chn) (0x20 + (chn)*0x04)
2153d0407baSopenharmony_ci#define TSADCV2_COMP_INT(chn) (0x30 + (chn)*0x04)
2163d0407baSopenharmony_ci#define TSADCV2_COMP_SHUT(chn) (0x40 + (chn)*0x04)
2173d0407baSopenharmony_ci#define TSADCV2_HIGHT_INT_DEBOUNCE 0x60
2183d0407baSopenharmony_ci#define TSADCV2_HIGHT_TSHUT_DEBOUNCE 0x64
2193d0407baSopenharmony_ci#define TSADCV2_AUTO_PERIOD 0x68
2203d0407baSopenharmony_ci#define TSADCV2_AUTO_PERIOD_HT 0x6c
2213d0407baSopenharmony_ci
2223d0407baSopenharmony_ci#define TSADCV2_AUTO_EN BIT(0)
2233d0407baSopenharmony_ci#define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn))
2243d0407baSopenharmony_ci#define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8)
2253d0407baSopenharmony_ci
2263d0407baSopenharmony_ci#define TSADCV3_AUTO_Q_SEL_EN BIT(1)
2273d0407baSopenharmony_ci
2283d0407baSopenharmony_ci#define TSADCV2_INT_SRC_EN(chn) BIT(chn)
2293d0407baSopenharmony_ci#define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn))
2303d0407baSopenharmony_ci#define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn))
2313d0407baSopenharmony_ci
2323d0407baSopenharmony_ci#define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8)
2333d0407baSopenharmony_ci#define TSADCV3_INT_PD_CLEAR_MASK ~BIT(16)
2343d0407baSopenharmony_ci
2353d0407baSopenharmony_ci#define TSADCV2_DATA_MASK 0xfff
2363d0407baSopenharmony_ci#define TSADCV3_DATA_MASK 0x3ff
2373d0407baSopenharmony_ci
2383d0407baSopenharmony_ci#define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4
2393d0407baSopenharmony_ci#define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT 4
2403d0407baSopenharmony_ci#define TSADCV2_AUTO_PERIOD_TIME 250     /* 250ms */
2413d0407baSopenharmony_ci#define TSADCV2_AUTO_PERIOD_HT_TIME 50   /* 50ms */
2423d0407baSopenharmony_ci#define TSADCV3_AUTO_PERIOD_TIME 1875    /* 2.5ms */
2433d0407baSopenharmony_ci#define TSADCV3_AUTO_PERIOD_HT_TIME 1875 /* 2.5ms */
2443d0407baSopenharmony_ci#define TSADCV5_AUTO_PERIOD_TIME 1622    /* 2.5ms */
2453d0407baSopenharmony_ci#define TSADCV5_AUTO_PERIOD_HT_TIME 1622 /* 2.5ms */
2463d0407baSopenharmony_ci
2473d0407baSopenharmony_ci#define TSADCV2_USER_INTER_PD_SOC 0x340 /* 13 clocks */
2483d0407baSopenharmony_ci#define TSADCV5_USER_INTER_PD_SOC 0xfc0 /* 97us, at least 90us */
2493d0407baSopenharmony_ci
2503d0407baSopenharmony_ci#define GRF_SARADC_TESTBIT 0x0e644
2513d0407baSopenharmony_ci#define GRF_TSADC_TESTBIT_L 0x0e648
2523d0407baSopenharmony_ci#define GRF_TSADC_TESTBIT_H 0x0e64c
2533d0407baSopenharmony_ci
2543d0407baSopenharmony_ci#define PX30_GRF_SOC_CON2 0x0408
2553d0407baSopenharmony_ci
2563d0407baSopenharmony_ci#define RK1808_BUS_GRF_SOC_CON0 0x0400
2573d0407baSopenharmony_ci
2583d0407baSopenharmony_ci#define RK3568_GRF_TSADC_CON 0x0600
2593d0407baSopenharmony_ci#define RK3568_GRF_TSADC_ANA_REG0 (0x10001 << 0)
2603d0407baSopenharmony_ci#define RK3568_GRF_TSADC_ANA_REG1 (0x10001 << 1)
2613d0407baSopenharmony_ci#define RK3568_GRF_TSADC_ANA_REG2 (0x10001 << 2)
2623d0407baSopenharmony_ci#define RK3568_GRF_TSADC_TSEN (0x10001 << 8)
2633d0407baSopenharmony_ci
2643d0407baSopenharmony_ci#define RV1126_GRF0_TSADC_CON 0x0100
2653d0407baSopenharmony_ci
2663d0407baSopenharmony_ci#define RV1126_GRF0_TSADC_TRM (0xff0077 << 0)
2673d0407baSopenharmony_ci#define RV1126_GRF0_TSADC_SHUT_2CRU (0x30003 << 10)
2683d0407baSopenharmony_ci#define RV1126_GRF0_TSADC_SHUT_2GPIO (0x70007 << 12)
2693d0407baSopenharmony_ci
2703d0407baSopenharmony_ci#define GRF_SARADC_TESTBIT_ON (0x10001 << 2)
2713d0407baSopenharmony_ci#define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2)
2723d0407baSopenharmony_ci#define GRF_TSADC_BANDGAP_CHOPPER_EN (0x10001 << 2)
2733d0407baSopenharmony_ci#define GRF_TSADC_VCM_EN_L (0x10001 << 7)
2743d0407baSopenharmony_ci#define GRF_TSADC_VCM_EN_H (0x10001 << 7)
2753d0407baSopenharmony_ci
2763d0407baSopenharmony_ci#define GRF_CON_TSADC_CH_INV (0x10001 << 1)
2773d0407baSopenharmony_ci
2783d0407baSopenharmony_ci#define MIN_TEMP (-40000)
2793d0407baSopenharmony_ci#define LOWEST_TEMP (-273000)
2803d0407baSopenharmony_ci#define MAX_TEMP (125000)
2813d0407baSopenharmony_ci#define MAX_ENV_TEMP (85000)
2823d0407baSopenharmony_ci
2833d0407baSopenharmony_ci/**
2843d0407baSopenharmony_ci * struct tsadc_table - code to temperature conversion table
2853d0407baSopenharmony_ci * @code: the value of adc channel
2863d0407baSopenharmony_ci * @temp: the temperature
2873d0407baSopenharmony_ci * Note:
2883d0407baSopenharmony_ci * code to temperature mapping of the temperature sensor is a piece wise linear
2893d0407baSopenharmony_ci * curve.Any temperature, code faling between to 2 give temperatures can be
2903d0407baSopenharmony_ci * linearly interpolated.
2913d0407baSopenharmony_ci * Code to Temperature mapping should be updated based on manufacturer results.
2923d0407baSopenharmony_ci */
2933d0407baSopenharmony_cistruct tsadc_table {
2943d0407baSopenharmony_ci    u32 code;
2953d0407baSopenharmony_ci    int temp;
2963d0407baSopenharmony_ci};
2973d0407baSopenharmony_ci
2983d0407baSopenharmony_cistatic const struct tsadc_table rv1108_table[] = {
2993d0407baSopenharmony_ci    {0, -40000},   {374, -40000}, {382, -35000}, {389, -30000}, {397, -25000}, {405, -20000},
3003d0407baSopenharmony_ci    {413, -15000}, {421, -10000}, {429, -5000},  {436, 0},      {444, 5000},   {452, 10000},
3013d0407baSopenharmony_ci    {460, 15000},  {468, 20000},  {476, 25000},  {483, 30000},  {491, 35000},  {499, 40000},
3023d0407baSopenharmony_ci    {507, 45000},  {515, 50000},  {523, 55000},  {531, 60000},  {539, 65000},  {547, 70000},
3033d0407baSopenharmony_ci    {555, 75000},  {562, 80000},  {570, 85000},  {578, 90000},  {586, 95000},  {594, 100000},
3043d0407baSopenharmony_ci    {602, 105000}, {610, 110000}, {618, 115000}, {626, 120000}, {634, 125000}, {TSADCV2_DATA_MASK, 125000},
3053d0407baSopenharmony_ci};
3063d0407baSopenharmony_ci
3073d0407baSopenharmony_cistatic const struct tsadc_table rk1808_code_table[] = {
3083d0407baSopenharmony_ci    {0, -40000},    {3455, -40000}, {3463, -35000}, {3471, -30000}, {3479, -25000}, {3487, -20000},
3093d0407baSopenharmony_ci    {3495, -15000}, {3503, -10000}, {3511, -5000},  {3519, 0},      {3527, 5000},   {3535, 10000},
3103d0407baSopenharmony_ci    {3543, 15000},  {3551, 20000},  {3559, 25000},  {3567, 30000},  {3576, 35000},  {3584, 40000},
3113d0407baSopenharmony_ci    {3592, 45000},  {3600, 50000},  {3609, 55000},  {3617, 60000},  {3625, 65000},  {3633, 70000},
3123d0407baSopenharmony_ci    {3642, 75000},  {3650, 80000},  {3659, 85000},  {3667, 90000},  {3675, 95000},  {3684, 100000},
3133d0407baSopenharmony_ci    {3692, 105000}, {3701, 110000}, {3709, 115000}, {3718, 120000}, {3726, 125000}, {TSADCV2_DATA_MASK, 125000},
3143d0407baSopenharmony_ci};
3153d0407baSopenharmony_ci
3163d0407baSopenharmony_cistatic const struct tsadc_table rk3228_code_table[] = {
3173d0407baSopenharmony_ci    {0, -40000},   {588, -40000}, {593, -35000}, {598, -30000}, {603, -25000}, {608, -20000},
3183d0407baSopenharmony_ci    {613, -15000}, {618, -10000}, {623, -5000},  {629, 0},      {634, 5000},   {639, 10000},
3193d0407baSopenharmony_ci    {644, 15000},  {649, 20000},  {654, 25000},  {660, 30000},  {665, 35000},  {670, 40000},
3203d0407baSopenharmony_ci    {675, 45000},  {681, 50000},  {686, 55000},  {691, 60000},  {696, 65000},  {702, 70000},
3213d0407baSopenharmony_ci    {707, 75000},  {712, 80000},  {717, 85000},  {723, 90000},  {728, 95000},  {733, 100000},
3223d0407baSopenharmony_ci    {738, 105000}, {744, 110000}, {749, 115000}, {754, 120000}, {760, 125000}, {TSADCV2_DATA_MASK, 125000},
3233d0407baSopenharmony_ci};
3243d0407baSopenharmony_ci
3253d0407baSopenharmony_cistatic const struct tsadc_table rk3288_code_table[] = {
3263d0407baSopenharmony_ci    {TSADCV2_DATA_MASK, -40000},
3273d0407baSopenharmony_ci    {3800, -40000},
3283d0407baSopenharmony_ci    {3792, -35000},
3293d0407baSopenharmony_ci    {3783, -30000},
3303d0407baSopenharmony_ci    {3774, -25000},
3313d0407baSopenharmony_ci    {3765, -20000},
3323d0407baSopenharmony_ci    {3756, -15000},
3333d0407baSopenharmony_ci    {3747, -10000},
3343d0407baSopenharmony_ci    {3737, -5000},
3353d0407baSopenharmony_ci    {3728, 0},
3363d0407baSopenharmony_ci    {3718, 5000},
3373d0407baSopenharmony_ci    {3708, 10000},
3383d0407baSopenharmony_ci    {3698, 15000},
3393d0407baSopenharmony_ci    {3688, 20000},
3403d0407baSopenharmony_ci    {3678, 25000},
3413d0407baSopenharmony_ci    {3667, 30000},
3423d0407baSopenharmony_ci    {3656, 35000},
3433d0407baSopenharmony_ci    {3645, 40000},
3443d0407baSopenharmony_ci    {3634, 45000},
3453d0407baSopenharmony_ci    {3623, 50000},
3463d0407baSopenharmony_ci    {3611, 55000},
3473d0407baSopenharmony_ci    {3600, 60000},
3483d0407baSopenharmony_ci    {3588, 65000},
3493d0407baSopenharmony_ci    {3575, 70000},
3503d0407baSopenharmony_ci    {3563, 75000},
3513d0407baSopenharmony_ci    {3550, 80000},
3523d0407baSopenharmony_ci    {3537, 85000},
3533d0407baSopenharmony_ci    {3524, 90000},
3543d0407baSopenharmony_ci    {3510, 95000},
3553d0407baSopenharmony_ci    {3496, 100000},
3563d0407baSopenharmony_ci    {3482, 105000},
3573d0407baSopenharmony_ci    {3467, 110000},
3583d0407baSopenharmony_ci    {3452, 115000},
3593d0407baSopenharmony_ci    {3437, 120000},
3603d0407baSopenharmony_ci    {3421, 125000},
3613d0407baSopenharmony_ci    {0, 125000},
3623d0407baSopenharmony_ci};
3633d0407baSopenharmony_ci
3643d0407baSopenharmony_cistatic const struct tsadc_table rk3328_code_table[] = {
3653d0407baSopenharmony_ci    {0, -40000},   {296, -40000}, {304, -35000}, {313, -30000}, {331, -20000},
3663d0407baSopenharmony_ci    {340, -15000}, {349, -10000}, {359, -5000},  {368, 0},      {378, 5000},
3673d0407baSopenharmony_ci    {388, 10000},  {398, 15000},  {408, 20000},  {418, 25000},  {429, 30000},
3683d0407baSopenharmony_ci    {440, 35000},  {451, 40000},  {462, 45000},  {473, 50000},  {485, 55000},
3693d0407baSopenharmony_ci    {496, 60000},  {508, 65000},  {521, 70000},  {533, 75000},  {546, 80000},
3703d0407baSopenharmony_ci    {559, 85000},  {572, 90000},  {586, 95000},  {600, 100000}, {614, 105000},
3713d0407baSopenharmony_ci    {629, 110000}, {644, 115000}, {659, 120000}, {675, 125000}, {TSADCV2_DATA_MASK, 125000},
3723d0407baSopenharmony_ci};
3733d0407baSopenharmony_ci
3743d0407baSopenharmony_cistatic const struct tsadc_table rk3368_code_table[] = {
3753d0407baSopenharmony_ci    {0, -40000},   {106, -40000}, {108, -35000}, {110, -30000}, {112, -25000}, {114, -20000},
3763d0407baSopenharmony_ci    {116, -15000}, {118, -10000}, {120, -5000},  {122, 0},      {124, 5000},   {126, 10000},
3773d0407baSopenharmony_ci    {128, 15000},  {130, 20000},  {132, 25000},  {134, 30000},  {136, 35000},  {138, 40000},
3783d0407baSopenharmony_ci    {140, 45000},  {142, 50000},  {144, 55000},  {146, 60000},  {148, 65000},  {150, 70000},
3793d0407baSopenharmony_ci    {152, 75000},  {154, 80000},  {156, 85000},  {158, 90000},  {160, 95000},  {162, 100000},
3803d0407baSopenharmony_ci    {163, 105000}, {165, 110000}, {167, 115000}, {169, 120000}, {171, 125000}, {TSADCV3_DATA_MASK, 125000},
3813d0407baSopenharmony_ci};
3823d0407baSopenharmony_ci
3833d0407baSopenharmony_cistatic const struct tsadc_table rk3399_code_table[] = {
3843d0407baSopenharmony_ci    {0, -40000},   {402, -40000}, {410, -35000}, {419, -30000}, {427, -25000}, {436, -20000},
3853d0407baSopenharmony_ci    {444, -15000}, {453, -10000}, {461, -5000},  {470, 0},      {478, 5000},   {487, 10000},
3863d0407baSopenharmony_ci    {496, 15000},  {504, 20000},  {513, 25000},  {521, 30000},  {530, 35000},  {538, 40000},
3873d0407baSopenharmony_ci    {547, 45000},  {555, 50000},  {564, 55000},  {573, 60000},  {581, 65000},  {590, 70000},
3883d0407baSopenharmony_ci    {599, 75000},  {607, 80000},  {616, 85000},  {624, 90000},  {633, 95000},  {642, 100000},
3893d0407baSopenharmony_ci    {650, 105000}, {659, 110000}, {668, 115000}, {677, 120000}, {685, 125000}, {TSADCV3_DATA_MASK, 125000},
3903d0407baSopenharmony_ci};
3913d0407baSopenharmony_ci
3923d0407baSopenharmony_cistatic const struct tsadc_table rk3568_code_table[] = {
3933d0407baSopenharmony_ci    {0, -40000},    {1584, -40000}, {1620, -35000}, {1652, -30000}, {1688, -25000}, {1720, -20000},
3943d0407baSopenharmony_ci    {1756, -15000}, {1788, -10000}, {1824, -5000},  {1856, 0},      {1892, 5000},   {1924, 10000},
3953d0407baSopenharmony_ci    {1956, 15000},  {1992, 20000},  {2024, 25000},  {2060, 30000},  {2092, 35000},  {2128, 40000},
3963d0407baSopenharmony_ci    {2160, 45000},  {2196, 50000},  {2228, 55000},  {2264, 60000},  {2300, 65000},  {2332, 70000},
3973d0407baSopenharmony_ci    {2368, 75000},  {2400, 80000},  {2436, 85000},  {2468, 90000},  {2500, 95000},  {2536, 100000},
3983d0407baSopenharmony_ci    {2572, 105000}, {2604, 110000}, {2636, 115000}, {2672, 120000}, {2704, 125000}, {TSADCV2_DATA_MASK, 125000},
3993d0407baSopenharmony_ci};
4003d0407baSopenharmony_ci
4013d0407baSopenharmony_cistatic u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table, int temp)
4023d0407baSopenharmony_ci{
4033d0407baSopenharmony_ci    int high, low, mid;
4043d0407baSopenharmony_ci    unsigned long num;
4053d0407baSopenharmony_ci    unsigned int denom;
4063d0407baSopenharmony_ci    u32 error = table->data_mask;
4073d0407baSopenharmony_ci
4083d0407baSopenharmony_ci    if (table->kNum) {
4093d0407baSopenharmony_ci        return (((temp / ROCKCHIP_THERMAL_ONETHOUSAND) * table->kNum) / ROCKCHIP_THERMAL_ONETHOUSAND + table->bNum);
4103d0407baSopenharmony_ci    }
4113d0407baSopenharmony_ci
4123d0407baSopenharmony_ci    low = 0;
4133d0407baSopenharmony_ci    high = (table->length - 1) - 1; /* ignore the last check for table */
4143d0407baSopenharmony_ci    mid = (high + low) / ROCKCHIP_THERMAL_TWO;
4153d0407baSopenharmony_ci
4163d0407baSopenharmony_ci    /* Return mask code data when the temp is over table range */
4173d0407baSopenharmony_ci    if (temp < table->id[low].temp || temp > table->id[high].temp) {
4183d0407baSopenharmony_ci        goto exit;
4193d0407baSopenharmony_ci    }
4203d0407baSopenharmony_ci
4213d0407baSopenharmony_ci    while (low <= high) {
4223d0407baSopenharmony_ci        if (temp == table->id[mid].temp) {
4233d0407baSopenharmony_ci            return table->id[mid].code;
4243d0407baSopenharmony_ci        } else if (temp < table->id[mid].temp) {
4253d0407baSopenharmony_ci            high = mid - 1;
4263d0407baSopenharmony_ci        } else {
4273d0407baSopenharmony_ci            low = mid + 1;
4283d0407baSopenharmony_ci        }
4293d0407baSopenharmony_ci        mid = (low + high) / ROCKCHIP_THERMAL_TWO;
4303d0407baSopenharmony_ci    }
4313d0407baSopenharmony_ci
4323d0407baSopenharmony_ci    /*
4333d0407baSopenharmony_ci     * The conversion code granularity provided by the table. Let's
4343d0407baSopenharmony_ci     * assume that the relationship between temperature and
4353d0407baSopenharmony_ci     * analog value between 2 table entries is linear and interpolate
4363d0407baSopenharmony_ci     * to produce less granular result.
4373d0407baSopenharmony_ci     */
4383d0407baSopenharmony_ci    num = abs(table->id[mid + 1].code - table->id[mid].code);
4393d0407baSopenharmony_ci    num *= temp - table->id[mid].temp;
4403d0407baSopenharmony_ci    denom = table->id[mid + 1].temp - table->id[mid].temp;
4413d0407baSopenharmony_ci
4423d0407baSopenharmony_ci    switch (table->mode) {
4433d0407baSopenharmony_ci        case ADC_DECREMENT:
4443d0407baSopenharmony_ci            return table->id[mid].code - (num / denom);
4453d0407baSopenharmony_ci        case ADC_INCREMENT:
4463d0407baSopenharmony_ci            return table->id[mid].code + (num / denom);
4473d0407baSopenharmony_ci        default:
4483d0407baSopenharmony_ci            pr_err("%s: unknown table mode: %d\n", __func__, table->mode);
4493d0407baSopenharmony_ci            return error;
4503d0407baSopenharmony_ci    }
4513d0407baSopenharmony_ci
4523d0407baSopenharmony_ciexit:
4533d0407baSopenharmony_ci    pr_err("%s: invalid temperature, temp=%d error=%d\n", __func__, temp, error);
4543d0407baSopenharmony_ci    return error;
4553d0407baSopenharmony_ci}
4563d0407baSopenharmony_ci
4573d0407baSopenharmony_cistatic int rk_tsadcv2_code_to_temp(const struct chip_tsadc_table *table, u32 code, int *temp)
4583d0407baSopenharmony_ci{
4593d0407baSopenharmony_ci    unsigned int low = 1;
4603d0407baSopenharmony_ci    unsigned int high = table->length - 1;
4613d0407baSopenharmony_ci    unsigned int mid = (low + high) / ROCKCHIP_THERMAL_TWO;
4623d0407baSopenharmony_ci    unsigned int num;
4633d0407baSopenharmony_ci    unsigned long denom;
4643d0407baSopenharmony_ci
4653d0407baSopenharmony_ci    if (table->kNum) {
4663d0407baSopenharmony_ci        *temp = (((int)code - table->bNum) * ROCKCHIP_THERMAL_TENTHOUSAND / table->kNum) * ROCKCHIP_THERMAL_ONEHUNDRED;
4673d0407baSopenharmony_ci        if (*temp < MIN_TEMP || *temp > MAX_TEMP) {
4683d0407baSopenharmony_ci            return -EAGAIN;
4693d0407baSopenharmony_ci        }
4703d0407baSopenharmony_ci        return 0;
4713d0407baSopenharmony_ci    }
4723d0407baSopenharmony_ci
4733d0407baSopenharmony_ci    WARN_ON(table->length < ROCKCHIP_THERMAL_TWO);
4743d0407baSopenharmony_ci
4753d0407baSopenharmony_ci    switch (table->mode) {
4763d0407baSopenharmony_ci        case ADC_DECREMENT:
4773d0407baSopenharmony_ci            code &= table->data_mask;
4783d0407baSopenharmony_ci            if (code <= table->id[high].code) {
4793d0407baSopenharmony_ci                return -EAGAIN; /* Incorrect reading */
4803d0407baSopenharmony_ci            }
4813d0407baSopenharmony_ci
4823d0407baSopenharmony_ci            while (low <= high) {
4833d0407baSopenharmony_ci                if (code >= table->id[mid].code && code < table->id[mid - 1].code) {
4843d0407baSopenharmony_ci                    break;
4853d0407baSopenharmony_ci                } else if (code < table->id[mid].code) {
4863d0407baSopenharmony_ci                    low = mid + 1;
4873d0407baSopenharmony_ci                } else {
4883d0407baSopenharmony_ci                    high = mid - 1;
4893d0407baSopenharmony_ci                }
4903d0407baSopenharmony_ci
4913d0407baSopenharmony_ci                mid = (low + high) / ROCKCHIP_THERMAL_TWO;
4923d0407baSopenharmony_ci            }
4933d0407baSopenharmony_ci            break;
4943d0407baSopenharmony_ci        case ADC_INCREMENT:
4953d0407baSopenharmony_ci            code &= table->data_mask;
4963d0407baSopenharmony_ci            if (code < table->id[low].code) {
4973d0407baSopenharmony_ci                return -EAGAIN; /* Incorrect reading */
4983d0407baSopenharmony_ci            }
4993d0407baSopenharmony_ci
5003d0407baSopenharmony_ci            while (low <= high) {
5013d0407baSopenharmony_ci                if (code <= table->id[mid].code && code > table->id[mid - 1].code) {
5023d0407baSopenharmony_ci                    break;
5033d0407baSopenharmony_ci                } else if (code > table->id[mid].code) {
5043d0407baSopenharmony_ci                    low = mid + 1;
5053d0407baSopenharmony_ci                } else {
5063d0407baSopenharmony_ci                    high = mid - 1;
5073d0407baSopenharmony_ci                }
5083d0407baSopenharmony_ci
5093d0407baSopenharmony_ci                mid = (low + high) / ROCKCHIP_THERMAL_TWO;
5103d0407baSopenharmony_ci            }
5113d0407baSopenharmony_ci            break;
5123d0407baSopenharmony_ci        default:
5133d0407baSopenharmony_ci            pr_err("%s: unknown table mode: %d\n", __func__, table->mode);
5143d0407baSopenharmony_ci            return -EINVAL;
5153d0407baSopenharmony_ci    }
5163d0407baSopenharmony_ci
5173d0407baSopenharmony_ci    /*
5183d0407baSopenharmony_ci     * The 5C granularity provided by the table is too much. Let's
5193d0407baSopenharmony_ci     * assume that the relationship between sensor readings and
5203d0407baSopenharmony_ci     * temperature between 2 table entries is linear and interpolate
5213d0407baSopenharmony_ci     * to produce less granular result.
5223d0407baSopenharmony_ci     */
5233d0407baSopenharmony_ci    num = table->id[mid].temp - table->id[mid - 1].temp;
5243d0407baSopenharmony_ci    num *= abs(table->id[mid - 1].code - code);
5253d0407baSopenharmony_ci    denom = abs(table->id[mid - 1].code - table->id[mid].code);
5263d0407baSopenharmony_ci    *temp = table->id[mid - 1].temp + (num / denom);
5273d0407baSopenharmony_ci
5283d0407baSopenharmony_ci    return 0;
5293d0407baSopenharmony_ci}
5303d0407baSopenharmony_ci
5313d0407baSopenharmony_ci/**
5323d0407baSopenharmony_ci * rk_tsadcv2_initialize - initialize TASDC Controller.
5333d0407baSopenharmony_ci * @grf: the general register file will be used to do static set by software
5343d0407baSopenharmony_ci * @regs: the base address of tsadc controller
5353d0407baSopenharmony_ci * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
5363d0407baSopenharmony_ci *
5373d0407baSopenharmony_ci * (1) Set TSADC_V2_AUTO_PERIOD:
5383d0407baSopenharmony_ci *     Configure the interleave between every two accessing of
5393d0407baSopenharmony_ci *     TSADC in normal operation.
5403d0407baSopenharmony_ci *
5413d0407baSopenharmony_ci * (2) Set TSADCV2_AUTO_PERIOD_HT:
5423d0407baSopenharmony_ci *     Configure the interleave between every two accessing of
5433d0407baSopenharmony_ci *     TSADC after the temperature is higher than COM_SHUT or COM_INT.
5443d0407baSopenharmony_ci *
5453d0407baSopenharmony_ci * (3) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE:
5463d0407baSopenharmony_ci *     If the temperature is higher than COMP_INT or COMP_SHUT for
5473d0407baSopenharmony_ci *     "debounce" times, TSADC controller will generate interrupt or TSHUT.
5483d0407baSopenharmony_ci */
5493d0407baSopenharmony_cistatic void rk_tsadcv2_initialize(struct regmap *grf, void __iomem *regs, enum tshut_polarity tshut_polarity)
5503d0407baSopenharmony_ci{
5513d0407baSopenharmony_ci    if (tshut_polarity == TSHUT_HIGH_ACTIVE) {
5523d0407baSopenharmony_ci        writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH, regs + TSADCV2_AUTO_CON);
5533d0407baSopenharmony_ci    } else {
5543d0407baSopenharmony_ci        writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH, regs + TSADCV2_AUTO_CON);
5553d0407baSopenharmony_ci    }
5563d0407baSopenharmony_ci
5573d0407baSopenharmony_ci    writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
5583d0407baSopenharmony_ci    writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT, regs + TSADCV2_HIGHT_INT_DEBOUNCE);
5593d0407baSopenharmony_ci    writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME, regs + TSADCV2_AUTO_PERIOD_HT);
5603d0407baSopenharmony_ci    writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
5613d0407baSopenharmony_ci}
5623d0407baSopenharmony_ci
5633d0407baSopenharmony_ci/**
5643d0407baSopenharmony_ci * rk_tsadcv3_initialize - initialize TASDC Controller.
5653d0407baSopenharmony_ci * @grf: the general register file will be used to do static set by software
5663d0407baSopenharmony_ci * @regs: the base address of tsadc controller
5673d0407baSopenharmony_ci * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH)
5683d0407baSopenharmony_ci *
5693d0407baSopenharmony_ci * (1) The tsadc control power sequence.
5703d0407baSopenharmony_ci *
5713d0407baSopenharmony_ci * (2) Set TSADC_V2_AUTO_PERIOD:
5723d0407baSopenharmony_ci *     Configure the interleave between every two accessing of
5733d0407baSopenharmony_ci *     TSADC in normal operation.
5743d0407baSopenharmony_ci *
5753d0407baSopenharmony_ci * (2) Set TSADCV2_AUTO_PERIOD_HT:
5763d0407baSopenharmony_ci *     Configure the interleave between every two accessing of
5773d0407baSopenharmony_ci *     TSADC after the temperature is higher than COM_SHUT or COM_INT.
5783d0407baSopenharmony_ci *
5793d0407baSopenharmony_ci * (3) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE:
5803d0407baSopenharmony_ci *     If the temperature is higher than COMP_INT or COMP_SHUT for
5813d0407baSopenharmony_ci *     "debounce" times, TSADC controller will generate interrupt or TSHUT.
5823d0407baSopenharmony_ci */
5833d0407baSopenharmony_cistatic void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs, enum tshut_polarity tshut_polarity)
5843d0407baSopenharmony_ci{
5853d0407baSopenharmony_ci    /* The tsadc control power sequence */
5863d0407baSopenharmony_ci    if (IS_ERR(grf)) {
5873d0407baSopenharmony_ci        /* Set interleave value to workround ic time sync issue */
5883d0407baSopenharmony_ci        writel_relaxed(TSADCV2_USER_INTER_PD_SOC, regs + TSADCV2_USER_CON);
5893d0407baSopenharmony_ci
5903d0407baSopenharmony_ci        writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
5913d0407baSopenharmony_ci        writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT, regs + TSADCV2_HIGHT_INT_DEBOUNCE);
5923d0407baSopenharmony_ci        writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME, regs + TSADCV2_AUTO_PERIOD_HT);
5933d0407baSopenharmony_ci        writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
5943d0407baSopenharmony_ci
5953d0407baSopenharmony_ci    } else {
5963d0407baSopenharmony_ci        /* Enable the voltage common mode feature */
5973d0407baSopenharmony_ci        regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_VCM_EN_L);
5983d0407baSopenharmony_ci        regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_VCM_EN_H);
5993d0407baSopenharmony_ci
6003d0407baSopenharmony_ci        usleep_range(ROCKCHIP_THERMAL_FIFTEEN, ROCKCHIP_THERMAL_ONEHUNDRED); /* The spec note says at least 15 us */
6013d0407baSopenharmony_ci        regmap_write(grf, GRF_SARADC_TESTBIT, GRF_SARADC_TESTBIT_ON);
6023d0407baSopenharmony_ci        regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_TESTBIT_H_ON);
6033d0407baSopenharmony_ci        usleep_range(ROCKCHIP_THERMAL_NINETY, ROCKCHIP_THERMAL_TWOHUNDRED); /* The spec note says at least 90 us */
6043d0407baSopenharmony_ci
6053d0407baSopenharmony_ci        writel_relaxed(TSADCV3_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
6063d0407baSopenharmony_ci        writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT, regs + TSADCV2_HIGHT_INT_DEBOUNCE);
6073d0407baSopenharmony_ci        writel_relaxed(TSADCV3_AUTO_PERIOD_HT_TIME, regs + TSADCV2_AUTO_PERIOD_HT);
6083d0407baSopenharmony_ci        writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
6093d0407baSopenharmony_ci    }
6103d0407baSopenharmony_ci
6113d0407baSopenharmony_ci    if (tshut_polarity == TSHUT_HIGH_ACTIVE) {
6123d0407baSopenharmony_ci        writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH, regs + TSADCV2_AUTO_CON);
6133d0407baSopenharmony_ci    } else {
6143d0407baSopenharmony_ci        writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH, regs + TSADCV2_AUTO_CON);
6153d0407baSopenharmony_ci    }
6163d0407baSopenharmony_ci}
6173d0407baSopenharmony_ci
6183d0407baSopenharmony_cistatic void rk_tsadcv4_initialize(struct regmap *grf, void __iomem *regs, enum tshut_polarity tshut_polarity)
6193d0407baSopenharmony_ci{
6203d0407baSopenharmony_ci    rk_tsadcv2_initialize(grf, regs, tshut_polarity);
6213d0407baSopenharmony_ci    regmap_write(grf, PX30_GRF_SOC_CON2, GRF_CON_TSADC_CH_INV);
6223d0407baSopenharmony_ci}
6233d0407baSopenharmony_ci
6243d0407baSopenharmony_cistatic void rk_tsadcv5_initialize(struct regmap *grf, void __iomem *regs, enum tshut_polarity tshut_polarity)
6253d0407baSopenharmony_ci{
6263d0407baSopenharmony_ci    if (tshut_polarity == TSHUT_HIGH_ACTIVE) {
6273d0407baSopenharmony_ci        writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH, regs + TSADCV2_AUTO_CON);
6283d0407baSopenharmony_ci    } else {
6293d0407baSopenharmony_ci        writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH, regs + TSADCV2_AUTO_CON);
6303d0407baSopenharmony_ci    }
6313d0407baSopenharmony_ci
6323d0407baSopenharmony_ci    writel_relaxed(TSADCV5_USER_INTER_PD_SOC, regs + TSADCV2_USER_CON);
6333d0407baSopenharmony_ci
6343d0407baSopenharmony_ci    writel_relaxed(TSADCV5_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
6353d0407baSopenharmony_ci    writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT, regs + TSADCV2_HIGHT_INT_DEBOUNCE);
6363d0407baSopenharmony_ci    writel_relaxed(TSADCV5_AUTO_PERIOD_HT_TIME, regs + TSADCV2_AUTO_PERIOD_HT);
6373d0407baSopenharmony_ci    writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
6383d0407baSopenharmony_ci
6393d0407baSopenharmony_ci    if (!IS_ERR(grf)) {
6403d0407baSopenharmony_ci        regmap_write(grf, RK1808_BUS_GRF_SOC_CON0, GRF_TSADC_BANDGAP_CHOPPER_EN);
6413d0407baSopenharmony_ci    }
6423d0407baSopenharmony_ci}
6433d0407baSopenharmony_ci
6443d0407baSopenharmony_cistatic void rk_tsadcv6_initialize(struct regmap *grf, void __iomem *regs, enum tshut_polarity tshut_polarity)
6453d0407baSopenharmony_ci{
6463d0407baSopenharmony_ci    rk_tsadcv2_initialize(grf, regs, tshut_polarity);
6473d0407baSopenharmony_ci
6483d0407baSopenharmony_ci    if (!IS_ERR(grf)) {
6493d0407baSopenharmony_ci        regmap_write(grf, RV1126_GRF0_TSADC_CON, RV1126_GRF0_TSADC_TRM);
6503d0407baSopenharmony_ci    }
6513d0407baSopenharmony_ci}
6523d0407baSopenharmony_ci
6533d0407baSopenharmony_cistatic void rk_tsadcv7_initialize(struct regmap *grf, void __iomem *regs, enum tshut_polarity tshut_polarity)
6543d0407baSopenharmony_ci{
6553d0407baSopenharmony_ci    writel_relaxed(TSADCV5_USER_INTER_PD_SOC, regs + TSADCV2_USER_CON);
6563d0407baSopenharmony_ci    writel_relaxed(TSADCV5_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD);
6573d0407baSopenharmony_ci    writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT, regs + TSADCV2_HIGHT_INT_DEBOUNCE);
6583d0407baSopenharmony_ci    writel_relaxed(TSADCV5_AUTO_PERIOD_HT_TIME, regs + TSADCV2_AUTO_PERIOD_HT);
6593d0407baSopenharmony_ci    writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE);
6603d0407baSopenharmony_ci
6613d0407baSopenharmony_ci    if (tshut_polarity == TSHUT_HIGH_ACTIVE) {
6623d0407baSopenharmony_ci        writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH, regs + TSADCV2_AUTO_CON);
6633d0407baSopenharmony_ci    } else {
6643d0407baSopenharmony_ci        writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH, regs + TSADCV2_AUTO_CON);
6653d0407baSopenharmony_ci    }
6663d0407baSopenharmony_ci
6673d0407baSopenharmony_ci    if (!IS_ERR(grf)) {
6683d0407baSopenharmony_ci        regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_TSEN);
6693d0407baSopenharmony_ci        udelay(ROCKCHIP_THERMAL_FIFTEEN);
6703d0407baSopenharmony_ci        regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG0);
6713d0407baSopenharmony_ci        regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG1);
6723d0407baSopenharmony_ci        regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG2);
6733d0407baSopenharmony_ci        usleep_range(ROCKCHIP_THERMAL_ONEHUNDRED, ROCKCHIP_THERMAL_TWOHUNDRED);
6743d0407baSopenharmony_ci    }
6753d0407baSopenharmony_ci}
6763d0407baSopenharmony_ci
6773d0407baSopenharmony_cistatic void rk_tsadcv2_irq_ack(void __iomem *regs)
6783d0407baSopenharmony_ci{
6793d0407baSopenharmony_ci    u32 val;
6803d0407baSopenharmony_ci
6813d0407baSopenharmony_ci    val = readl_relaxed(regs + TSADCV2_INT_PD);
6823d0407baSopenharmony_ci    writel_relaxed(val & TSADCV2_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
6833d0407baSopenharmony_ci}
6843d0407baSopenharmony_ci
6853d0407baSopenharmony_cistatic void rk_tsadcv3_irq_ack(void __iomem *regs)
6863d0407baSopenharmony_ci{
6873d0407baSopenharmony_ci    u32 val;
6883d0407baSopenharmony_ci
6893d0407baSopenharmony_ci    val = readl_relaxed(regs + TSADCV2_INT_PD);
6903d0407baSopenharmony_ci    writel_relaxed(val & TSADCV3_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD);
6913d0407baSopenharmony_ci}
6923d0407baSopenharmony_ci
6933d0407baSopenharmony_cistatic void rk_tsadcv2_control(void __iomem *regs, bool enable)
6943d0407baSopenharmony_ci{
6953d0407baSopenharmony_ci    u32 val;
6963d0407baSopenharmony_ci
6973d0407baSopenharmony_ci    val = readl_relaxed(regs + TSADCV2_AUTO_CON);
6983d0407baSopenharmony_ci    if (enable) {
6993d0407baSopenharmony_ci        val |= TSADCV2_AUTO_EN;
7003d0407baSopenharmony_ci    } else {
7013d0407baSopenharmony_ci        val &= ~TSADCV2_AUTO_EN;
7023d0407baSopenharmony_ci    }
7033d0407baSopenharmony_ci
7043d0407baSopenharmony_ci    writel_relaxed(val, regs + TSADCV2_AUTO_CON);
7053d0407baSopenharmony_ci}
7063d0407baSopenharmony_ci
7073d0407baSopenharmony_ci/**
7083d0407baSopenharmony_ci * rk_tsadcv3_control - the tsadc controller is enabled or disabled.
7093d0407baSopenharmony_ci * @regs: the base address of tsadc controller
7103d0407baSopenharmony_ci * @enable: boolean flag to enable the controller
7113d0407baSopenharmony_ci *
7123d0407baSopenharmony_ci * NOTE: TSADC controller works at auto mode, and some SoCs need set the
7133d0407baSopenharmony_ci * tsadc_q_sel bit on TSADCV2_AUTO_CON[1]. The (1024 - tsadc_q) as output
7143d0407baSopenharmony_ci * adc value if setting this bit to enable.
7153d0407baSopenharmony_ci */
7163d0407baSopenharmony_cistatic void rk_tsadcv3_control(void __iomem *regs, bool enable)
7173d0407baSopenharmony_ci{
7183d0407baSopenharmony_ci    u32 val;
7193d0407baSopenharmony_ci
7203d0407baSopenharmony_ci    val = readl_relaxed(regs + TSADCV2_AUTO_CON);
7213d0407baSopenharmony_ci    if (enable) {
7223d0407baSopenharmony_ci        val |= TSADCV2_AUTO_EN | TSADCV3_AUTO_Q_SEL_EN;
7233d0407baSopenharmony_ci    } else {
7243d0407baSopenharmony_ci        val &= ~TSADCV2_AUTO_EN;
7253d0407baSopenharmony_ci    }
7263d0407baSopenharmony_ci
7273d0407baSopenharmony_ci    writel_relaxed(val, regs + TSADCV2_AUTO_CON);
7283d0407baSopenharmony_ci}
7293d0407baSopenharmony_ci
7303d0407baSopenharmony_cistatic int rk_tsadcv2_get_temp(const struct chip_tsadc_table *table, int chn, void __iomem *regs, int *temp)
7313d0407baSopenharmony_ci{
7323d0407baSopenharmony_ci    u32 val;
7333d0407baSopenharmony_ci
7343d0407baSopenharmony_ci    val = readl_relaxed(regs + TSADCV2_DATA(chn));
7353d0407baSopenharmony_ci
7363d0407baSopenharmony_ci    return rk_tsadcv2_code_to_temp(table, val, temp);
7373d0407baSopenharmony_ci}
7383d0407baSopenharmony_ci
7393d0407baSopenharmony_cistatic int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table, int chn, void __iomem *regs, int temp)
7403d0407baSopenharmony_ci{
7413d0407baSopenharmony_ci    u32 alarm_value;
7423d0407baSopenharmony_ci    u32 int_en, int_clr;
7433d0407baSopenharmony_ci
7443d0407baSopenharmony_ci    /*
7453d0407baSopenharmony_ci     * In some cases, some sensors didn't need the trip points, the
7463d0407baSopenharmony_ci     * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm
7473d0407baSopenharmony_ci     * in the end, ignore this case and disable the high temperature
7483d0407baSopenharmony_ci     * interrupt.
7493d0407baSopenharmony_ci     */
7503d0407baSopenharmony_ci    if (temp == INT_MAX) {
7513d0407baSopenharmony_ci        int_clr = readl_relaxed(regs + TSADCV2_INT_EN);
7523d0407baSopenharmony_ci        int_clr &= ~TSADCV2_INT_SRC_EN(chn);
7533d0407baSopenharmony_ci        writel_relaxed(int_clr, regs + TSADCV2_INT_EN);
7543d0407baSopenharmony_ci        return 0;
7553d0407baSopenharmony_ci    }
7563d0407baSopenharmony_ci
7573d0407baSopenharmony_ci    /* Make sure the value is valid */
7583d0407baSopenharmony_ci    alarm_value = rk_tsadcv2_temp_to_code(table, temp);
7593d0407baSopenharmony_ci    if (alarm_value == table->data_mask) {
7603d0407baSopenharmony_ci        return -ERANGE;
7613d0407baSopenharmony_ci    }
7623d0407baSopenharmony_ci
7633d0407baSopenharmony_ci    writel_relaxed(alarm_value & table->data_mask, regs + TSADCV2_COMP_INT(chn));
7643d0407baSopenharmony_ci
7653d0407baSopenharmony_ci    int_en = readl_relaxed(regs + TSADCV2_INT_EN);
7663d0407baSopenharmony_ci    int_en |= TSADCV2_INT_SRC_EN(chn);
7673d0407baSopenharmony_ci    writel_relaxed(int_en, regs + TSADCV2_INT_EN);
7683d0407baSopenharmony_ci
7693d0407baSopenharmony_ci    return 0;
7703d0407baSopenharmony_ci}
7713d0407baSopenharmony_ci
7723d0407baSopenharmony_cistatic int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table, int chn, void __iomem *regs, int temp)
7733d0407baSopenharmony_ci{
7743d0407baSopenharmony_ci    u32 tshut_value, val;
7753d0407baSopenharmony_ci
7763d0407baSopenharmony_ci    /* Make sure the value is valid */
7773d0407baSopenharmony_ci    tshut_value = rk_tsadcv2_temp_to_code(table, temp);
7783d0407baSopenharmony_ci    if (tshut_value == table->data_mask) {
7793d0407baSopenharmony_ci        return -ERANGE;
7803d0407baSopenharmony_ci    }
7813d0407baSopenharmony_ci
7823d0407baSopenharmony_ci    writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn));
7833d0407baSopenharmony_ci
7843d0407baSopenharmony_ci    /* TSHUT will be valid */
7853d0407baSopenharmony_ci    val = readl_relaxed(regs + TSADCV2_AUTO_CON);
7863d0407baSopenharmony_ci    writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON);
7873d0407baSopenharmony_ci
7883d0407baSopenharmony_ci    return 0;
7893d0407baSopenharmony_ci}
7903d0407baSopenharmony_ci
7913d0407baSopenharmony_cistatic void rk_tsadcv2_tshut_mode(struct regmap *grf, int chn, void __iomem *regs, enum tshut_mode mode)
7923d0407baSopenharmony_ci{
7933d0407baSopenharmony_ci    u32 val;
7943d0407baSopenharmony_ci
7953d0407baSopenharmony_ci    val = readl_relaxed(regs + TSADCV2_INT_EN);
7963d0407baSopenharmony_ci    if (mode == TSHUT_MODE_OTP) {
7973d0407baSopenharmony_ci        val &= ~TSADCV2_SHUT_2CRU_SRC_EN(chn);
7983d0407baSopenharmony_ci        val |= TSADCV2_SHUT_2GPIO_SRC_EN(chn);
7993d0407baSopenharmony_ci    } else {
8003d0407baSopenharmony_ci        val &= ~TSADCV2_SHUT_2GPIO_SRC_EN(chn);
8013d0407baSopenharmony_ci        val |= TSADCV2_SHUT_2CRU_SRC_EN(chn);
8023d0407baSopenharmony_ci    }
8033d0407baSopenharmony_ci
8043d0407baSopenharmony_ci    writel_relaxed(val, regs + TSADCV2_INT_EN);
8053d0407baSopenharmony_ci}
8063d0407baSopenharmony_ci
8073d0407baSopenharmony_cistatic void rk_tsadcv3_tshut_mode(struct regmap *grf, int chn, void __iomem *regs, enum tshut_mode mode)
8083d0407baSopenharmony_ci{
8093d0407baSopenharmony_ci    u32 val;
8103d0407baSopenharmony_ci
8113d0407baSopenharmony_ci    val = readl_relaxed(regs + TSADCV2_INT_EN);
8123d0407baSopenharmony_ci    if (mode == TSHUT_MODE_OTP) {
8133d0407baSopenharmony_ci        val &= ~TSADCV2_SHUT_2CRU_SRC_EN(chn);
8143d0407baSopenharmony_ci        val |= TSADCV2_SHUT_2GPIO_SRC_EN(chn);
8153d0407baSopenharmony_ci        if (!IS_ERR(grf)) {
8163d0407baSopenharmony_ci            regmap_write(grf, RV1126_GRF0_TSADC_CON, RV1126_GRF0_TSADC_SHUT_2GPIO);
8173d0407baSopenharmony_ci        }
8183d0407baSopenharmony_ci    } else {
8193d0407baSopenharmony_ci        val &= ~TSADCV2_SHUT_2GPIO_SRC_EN(chn);
8203d0407baSopenharmony_ci        val |= TSADCV2_SHUT_2CRU_SRC_EN(chn);
8213d0407baSopenharmony_ci        if (!IS_ERR(grf)) {
8223d0407baSopenharmony_ci            regmap_write(grf, RV1126_GRF0_TSADC_CON, RV1126_GRF0_TSADC_SHUT_2CRU);
8233d0407baSopenharmony_ci        }
8243d0407baSopenharmony_ci    }
8253d0407baSopenharmony_ci
8263d0407baSopenharmony_ci    writel_relaxed(val, regs + TSADCV2_INT_EN);
8273d0407baSopenharmony_ci}
8283d0407baSopenharmony_ci
8293d0407baSopenharmony_cistatic int rk_tsadcv1_get_trim_code(struct platform_device *pdev, int code, int trim_base)
8303d0407baSopenharmony_ci{
8313d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
8323d0407baSopenharmony_ci    const struct chip_tsadc_table *table = &thermal->chip->table;
8333d0407baSopenharmony_ci    u32 base_code;
8343d0407baSopenharmony_ci    int trim_code;
8353d0407baSopenharmony_ci
8363d0407baSopenharmony_ci    base_code = trim_base * table->kNum / ROCKCHIP_THERMAL_ONETHOUSAND + table->bNum;
8373d0407baSopenharmony_ci    trim_code = code - base_code - ROCKCHIP_THERMAL_TEN;
8383d0407baSopenharmony_ci
8393d0407baSopenharmony_ci    return trim_code;
8403d0407baSopenharmony_ci}
8413d0407baSopenharmony_ci
8423d0407baSopenharmony_cistatic int rk_tsadcv1_trim_temp(struct platform_device *pdev)
8433d0407baSopenharmony_ci{
8443d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
8453d0407baSopenharmony_ci
8463d0407baSopenharmony_ci    return thermal->trim * ROCKCHIP_THERMAL_FIVEHUNDRED;
8473d0407baSopenharmony_ci}
8483d0407baSopenharmony_ci
8493d0407baSopenharmony_cistatic const struct rockchip_tsadc_chip px30_tsadc_data = {
8503d0407baSopenharmony_ci    .chn_id[SENSOR_CPU] = 0,         /* cpu sensor is channel 0 */
8513d0407baSopenharmony_ci    .chn_id[SENSOR_GPU] = 1,         /* gpu sensor is channel 1 */
8523d0407baSopenharmony_ci    .chn_num = ROCKCHIP_THERMAL_TWO, /* 2 channels for tsadc */
8533d0407baSopenharmony_ci
8543d0407baSopenharmony_ci    .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */
8553d0407baSopenharmony_ci    .tshut_temp = ROCKCHIP_THERMAL_NINETYFIVETHOUSAND,
8563d0407baSopenharmony_ci
8573d0407baSopenharmony_ci    .initialize = rk_tsadcv4_initialize,
8583d0407baSopenharmony_ci    .irq_ack = rk_tsadcv3_irq_ack,
8593d0407baSopenharmony_ci    .control = rk_tsadcv3_control,
8603d0407baSopenharmony_ci    .get_temp = rk_tsadcv2_get_temp,
8613d0407baSopenharmony_ci    .set_alarm_temp = rk_tsadcv2_alarm_temp,
8623d0407baSopenharmony_ci    .set_tshut_temp = rk_tsadcv2_tshut_temp,
8633d0407baSopenharmony_ci    .set_tshut_mode = rk_tsadcv2_tshut_mode,
8643d0407baSopenharmony_ci
8653d0407baSopenharmony_ci    .table =
8663d0407baSopenharmony_ci        {
8673d0407baSopenharmony_ci            .id = rk3328_code_table,
8683d0407baSopenharmony_ci            .length = ARRAY_SIZE(rk3328_code_table),
8693d0407baSopenharmony_ci            .data_mask = TSADCV2_DATA_MASK,
8703d0407baSopenharmony_ci            .mode = ADC_INCREMENT,
8713d0407baSopenharmony_ci        },
8723d0407baSopenharmony_ci};
8733d0407baSopenharmony_ci
8743d0407baSopenharmony_cistatic const struct rockchip_tsadc_chip rv1108_tsadc_data = {
8753d0407baSopenharmony_ci    .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
8763d0407baSopenharmony_ci    .chn_num = 1,            /* one channel for tsadc */
8773d0407baSopenharmony_ci
8783d0407baSopenharmony_ci    .tshut_mode = TSHUT_MODE_OTP,       /* default TSHUT via GPIO give PMIC */
8793d0407baSopenharmony_ci    .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
8803d0407baSopenharmony_ci    .tshut_temp = ROCKCHIP_THERMAL_NINETYFIVETHOUSAND,
8813d0407baSopenharmony_ci
8823d0407baSopenharmony_ci    .initialize = rk_tsadcv2_initialize,
8833d0407baSopenharmony_ci    .irq_ack = rk_tsadcv3_irq_ack,
8843d0407baSopenharmony_ci    .control = rk_tsadcv3_control,
8853d0407baSopenharmony_ci    .get_temp = rk_tsadcv2_get_temp,
8863d0407baSopenharmony_ci    .set_alarm_temp = rk_tsadcv2_alarm_temp,
8873d0407baSopenharmony_ci    .set_tshut_temp = rk_tsadcv2_tshut_temp,
8883d0407baSopenharmony_ci    .set_tshut_mode = rk_tsadcv2_tshut_mode,
8893d0407baSopenharmony_ci
8903d0407baSopenharmony_ci    .table =
8913d0407baSopenharmony_ci        {
8923d0407baSopenharmony_ci            .id = rv1108_table,
8933d0407baSopenharmony_ci            .length = ARRAY_SIZE(rv1108_table),
8943d0407baSopenharmony_ci            .data_mask = TSADCV2_DATA_MASK,
8953d0407baSopenharmony_ci            .mode = ADC_INCREMENT,
8963d0407baSopenharmony_ci        },
8973d0407baSopenharmony_ci};
8983d0407baSopenharmony_ci
8993d0407baSopenharmony_cistatic const struct rockchip_tsadc_chip rv1126_tsadc_data = {
9003d0407baSopenharmony_ci    .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
9013d0407baSopenharmony_ci    .chn_num = 1,            /* one channel for tsadc */
9023d0407baSopenharmony_ci
9033d0407baSopenharmony_ci    .tshut_mode = TSHUT_MODE_CRU,       /* default TSHUT via CRU */
9043d0407baSopenharmony_ci    .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
9053d0407baSopenharmony_ci    .tshut_temp = ROCKCHIP_THERMAL_NINETYFIVETHOUSAND,
9063d0407baSopenharmony_ci
9073d0407baSopenharmony_ci    .initialize = rk_tsadcv6_initialize,
9083d0407baSopenharmony_ci    .irq_ack = rk_tsadcv3_irq_ack,
9093d0407baSopenharmony_ci    .control = rk_tsadcv2_control,
9103d0407baSopenharmony_ci    .get_temp = rk_tsadcv2_get_temp,
9113d0407baSopenharmony_ci    .set_alarm_temp = rk_tsadcv2_alarm_temp,
9123d0407baSopenharmony_ci    .set_tshut_temp = rk_tsadcv2_tshut_temp,
9133d0407baSopenharmony_ci    .set_tshut_mode = rk_tsadcv3_tshut_mode,
9143d0407baSopenharmony_ci    .get_trim_code = rk_tsadcv1_get_trim_code,
9153d0407baSopenharmony_ci    .trim_temp = rk_tsadcv1_trim_temp,
9163d0407baSopenharmony_ci
9173d0407baSopenharmony_ci    .table =
9183d0407baSopenharmony_ci        {
9193d0407baSopenharmony_ci            .kNum = 2263,
9203d0407baSopenharmony_ci            .bNum = 2704,
9213d0407baSopenharmony_ci            .data_mask = TSADCV2_DATA_MASK,
9223d0407baSopenharmony_ci            .mode = ADC_INCREMENT,
9233d0407baSopenharmony_ci        },
9243d0407baSopenharmony_ci};
9253d0407baSopenharmony_ci
9263d0407baSopenharmony_cistatic const struct rockchip_tsadc_chip rk1808_tsadc_data = {
9273d0407baSopenharmony_ci    .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
9283d0407baSopenharmony_ci    .chn_num = 1,            /* one channel for tsadc */
9293d0407baSopenharmony_ci
9303d0407baSopenharmony_ci    .tshut_mode = TSHUT_MODE_OTP,       /* default TSHUT via GPIO give PMIC */
9313d0407baSopenharmony_ci    .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
9323d0407baSopenharmony_ci    .tshut_temp = ROCKCHIP_THERMAL_NINETYFIVETHOUSAND,
9333d0407baSopenharmony_ci
9343d0407baSopenharmony_ci    .initialize = rk_tsadcv5_initialize,
9353d0407baSopenharmony_ci    .irq_ack = rk_tsadcv3_irq_ack,
9363d0407baSopenharmony_ci    .control = rk_tsadcv3_control,
9373d0407baSopenharmony_ci    .get_temp = rk_tsadcv2_get_temp,
9383d0407baSopenharmony_ci    .set_alarm_temp = rk_tsadcv2_alarm_temp,
9393d0407baSopenharmony_ci    .set_tshut_temp = rk_tsadcv2_tshut_temp,
9403d0407baSopenharmony_ci    .set_tshut_mode = rk_tsadcv2_tshut_mode,
9413d0407baSopenharmony_ci
9423d0407baSopenharmony_ci    .table =
9433d0407baSopenharmony_ci        {
9443d0407baSopenharmony_ci            .id = rk1808_code_table,
9453d0407baSopenharmony_ci            .length = ARRAY_SIZE(rk1808_code_table),
9463d0407baSopenharmony_ci            .data_mask = TSADCV2_DATA_MASK,
9473d0407baSopenharmony_ci            .mode = ADC_INCREMENT,
9483d0407baSopenharmony_ci        },
9493d0407baSopenharmony_ci};
9503d0407baSopenharmony_ci
9513d0407baSopenharmony_cistatic const struct rockchip_tsadc_chip rk3228_tsadc_data = {
9523d0407baSopenharmony_ci    .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
9533d0407baSopenharmony_ci    .chn_num = 1,            /* one channel for tsadc */
9543d0407baSopenharmony_ci
9553d0407baSopenharmony_ci    .tshut_mode = TSHUT_MODE_OTP,       /* default TSHUT via GPIO give PMIC */
9563d0407baSopenharmony_ci    .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
9573d0407baSopenharmony_ci    .tshut_temp = ROCKCHIP_THERMAL_NINETYFIVETHOUSAND,
9583d0407baSopenharmony_ci
9593d0407baSopenharmony_ci    .initialize = rk_tsadcv2_initialize,
9603d0407baSopenharmony_ci    .irq_ack = rk_tsadcv3_irq_ack,
9613d0407baSopenharmony_ci    .control = rk_tsadcv3_control,
9623d0407baSopenharmony_ci    .get_temp = rk_tsadcv2_get_temp,
9633d0407baSopenharmony_ci    .set_alarm_temp = rk_tsadcv2_alarm_temp,
9643d0407baSopenharmony_ci    .set_tshut_temp = rk_tsadcv2_tshut_temp,
9653d0407baSopenharmony_ci    .set_tshut_mode = rk_tsadcv2_tshut_mode,
9663d0407baSopenharmony_ci
9673d0407baSopenharmony_ci    .table =
9683d0407baSopenharmony_ci        {
9693d0407baSopenharmony_ci            .id = rk3228_code_table,
9703d0407baSopenharmony_ci            .length = ARRAY_SIZE(rk3228_code_table),
9713d0407baSopenharmony_ci            .data_mask = TSADCV3_DATA_MASK,
9723d0407baSopenharmony_ci            .mode = ADC_INCREMENT,
9733d0407baSopenharmony_ci        },
9743d0407baSopenharmony_ci};
9753d0407baSopenharmony_ci
9763d0407baSopenharmony_cistatic const struct rockchip_tsadc_chip rk3288_tsadc_data = {
9773d0407baSopenharmony_ci    .chn_id[SENSOR_CPU] = 1,                    /* cpu sensor is channel 1 */
9783d0407baSopenharmony_ci    .chn_id[SENSOR_GPU] = ROCKCHIP_THERMAL_TWO, /* gpu sensor is channel 2 */
9793d0407baSopenharmony_ci    .chn_num = ROCKCHIP_THERMAL_TWO,            /* two channels for tsadc */
9803d0407baSopenharmony_ci
9813d0407baSopenharmony_ci    .tshut_mode = TSHUT_MODE_OTP,       /* default TSHUT via GPIO give PMIC */
9823d0407baSopenharmony_ci    .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
9833d0407baSopenharmony_ci    .tshut_temp = ROCKCHIP_THERMAL_NINETYFIVETHOUSAND,
9843d0407baSopenharmony_ci
9853d0407baSopenharmony_ci    .initialize = rk_tsadcv2_initialize,
9863d0407baSopenharmony_ci    .irq_ack = rk_tsadcv2_irq_ack,
9873d0407baSopenharmony_ci    .control = rk_tsadcv2_control,
9883d0407baSopenharmony_ci    .get_temp = rk_tsadcv2_get_temp,
9893d0407baSopenharmony_ci    .set_alarm_temp = rk_tsadcv2_alarm_temp,
9903d0407baSopenharmony_ci    .set_tshut_temp = rk_tsadcv2_tshut_temp,
9913d0407baSopenharmony_ci    .set_tshut_mode = rk_tsadcv2_tshut_mode,
9923d0407baSopenharmony_ci
9933d0407baSopenharmony_ci    .table =
9943d0407baSopenharmony_ci        {
9953d0407baSopenharmony_ci            .id = rk3288_code_table,
9963d0407baSopenharmony_ci            .length = ARRAY_SIZE(rk3288_code_table),
9973d0407baSopenharmony_ci            .data_mask = TSADCV2_DATA_MASK,
9983d0407baSopenharmony_ci            .mode = ADC_DECREMENT,
9993d0407baSopenharmony_ci        },
10003d0407baSopenharmony_ci};
10013d0407baSopenharmony_ci
10023d0407baSopenharmony_cistatic const struct rockchip_tsadc_chip rk3328_tsadc_data = {
10033d0407baSopenharmony_ci    .chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
10043d0407baSopenharmony_ci    .chn_num = 1,            /* one channels for tsadc */
10053d0407baSopenharmony_ci
10063d0407baSopenharmony_ci    .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */
10073d0407baSopenharmony_ci    .tshut_temp = ROCKCHIP_THERMAL_NINETYFIVETHOUSAND,
10083d0407baSopenharmony_ci
10093d0407baSopenharmony_ci    .initialize = rk_tsadcv2_initialize,
10103d0407baSopenharmony_ci    .irq_ack = rk_tsadcv3_irq_ack,
10113d0407baSopenharmony_ci    .control = rk_tsadcv3_control,
10123d0407baSopenharmony_ci    .get_temp = rk_tsadcv2_get_temp,
10133d0407baSopenharmony_ci    .set_alarm_temp = rk_tsadcv2_alarm_temp,
10143d0407baSopenharmony_ci    .set_tshut_temp = rk_tsadcv2_tshut_temp,
10153d0407baSopenharmony_ci    .set_tshut_mode = rk_tsadcv2_tshut_mode,
10163d0407baSopenharmony_ci
10173d0407baSopenharmony_ci    .table =
10183d0407baSopenharmony_ci        {
10193d0407baSopenharmony_ci            .id = rk3328_code_table,
10203d0407baSopenharmony_ci            .length = ARRAY_SIZE(rk3328_code_table),
10213d0407baSopenharmony_ci            .data_mask = TSADCV2_DATA_MASK,
10223d0407baSopenharmony_ci            .mode = ADC_INCREMENT,
10233d0407baSopenharmony_ci        },
10243d0407baSopenharmony_ci};
10253d0407baSopenharmony_ci
10263d0407baSopenharmony_cistatic const struct rockchip_tsadc_chip rk3366_tsadc_data = {
10273d0407baSopenharmony_ci    .chn_id[SENSOR_CPU] = 0,         /* cpu sensor is channel 0 */
10283d0407baSopenharmony_ci    .chn_id[SENSOR_GPU] = 1,         /* gpu sensor is channel 1 */
10293d0407baSopenharmony_ci    .chn_num = ROCKCHIP_THERMAL_TWO, /* two channels for tsadc */
10303d0407baSopenharmony_ci
10313d0407baSopenharmony_ci    .tshut_mode = TSHUT_MODE_OTP,       /* default TSHUT via GPIO give PMIC */
10323d0407baSopenharmony_ci    .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
10333d0407baSopenharmony_ci    .tshut_temp = ROCKCHIP_THERMAL_NINETYFIVETHOUSAND,
10343d0407baSopenharmony_ci
10353d0407baSopenharmony_ci    .initialize = rk_tsadcv3_initialize,
10363d0407baSopenharmony_ci    .irq_ack = rk_tsadcv3_irq_ack,
10373d0407baSopenharmony_ci    .control = rk_tsadcv3_control,
10383d0407baSopenharmony_ci    .get_temp = rk_tsadcv2_get_temp,
10393d0407baSopenharmony_ci    .set_alarm_temp = rk_tsadcv2_alarm_temp,
10403d0407baSopenharmony_ci    .set_tshut_temp = rk_tsadcv2_tshut_temp,
10413d0407baSopenharmony_ci    .set_tshut_mode = rk_tsadcv2_tshut_mode,
10423d0407baSopenharmony_ci
10433d0407baSopenharmony_ci    .table =
10443d0407baSopenharmony_ci        {
10453d0407baSopenharmony_ci            .id = rk3228_code_table,
10463d0407baSopenharmony_ci            .length = ARRAY_SIZE(rk3228_code_table),
10473d0407baSopenharmony_ci            .data_mask = TSADCV3_DATA_MASK,
10483d0407baSopenharmony_ci            .mode = ADC_INCREMENT,
10493d0407baSopenharmony_ci        },
10503d0407baSopenharmony_ci};
10513d0407baSopenharmony_ci
10523d0407baSopenharmony_cistatic const struct rockchip_tsadc_chip rk3368_tsadc_data = {
10533d0407baSopenharmony_ci    .chn_id[SENSOR_CPU] = 0,         /* cpu sensor is channel 0 */
10543d0407baSopenharmony_ci    .chn_id[SENSOR_GPU] = 1,         /* gpu sensor is channel 1 */
10553d0407baSopenharmony_ci    .chn_num = ROCKCHIP_THERMAL_TWO, /* two channels for tsadc */
10563d0407baSopenharmony_ci
10573d0407baSopenharmony_ci    .tshut_mode = TSHUT_MODE_OTP,       /* default TSHUT via GPIO give PMIC */
10583d0407baSopenharmony_ci    .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
10593d0407baSopenharmony_ci    .tshut_temp = ROCKCHIP_THERMAL_NINETYFIVETHOUSAND,
10603d0407baSopenharmony_ci
10613d0407baSopenharmony_ci    .initialize = rk_tsadcv2_initialize,
10623d0407baSopenharmony_ci    .irq_ack = rk_tsadcv2_irq_ack,
10633d0407baSopenharmony_ci    .control = rk_tsadcv2_control,
10643d0407baSopenharmony_ci    .get_temp = rk_tsadcv2_get_temp,
10653d0407baSopenharmony_ci    .set_alarm_temp = rk_tsadcv2_alarm_temp,
10663d0407baSopenharmony_ci    .set_tshut_temp = rk_tsadcv2_tshut_temp,
10673d0407baSopenharmony_ci    .set_tshut_mode = rk_tsadcv2_tshut_mode,
10683d0407baSopenharmony_ci
10693d0407baSopenharmony_ci    .table =
10703d0407baSopenharmony_ci        {
10713d0407baSopenharmony_ci            .id = rk3368_code_table,
10723d0407baSopenharmony_ci            .length = ARRAY_SIZE(rk3368_code_table),
10733d0407baSopenharmony_ci            .data_mask = TSADCV3_DATA_MASK,
10743d0407baSopenharmony_ci            .mode = ADC_INCREMENT,
10753d0407baSopenharmony_ci        },
10763d0407baSopenharmony_ci};
10773d0407baSopenharmony_ci
10783d0407baSopenharmony_cistatic const struct rockchip_tsadc_chip rk3399_tsadc_data = {
10793d0407baSopenharmony_ci    .chn_id[SENSOR_CPU] = 0,         /* cpu sensor is channel 0 */
10803d0407baSopenharmony_ci    .chn_id[SENSOR_GPU] = 1,         /* gpu sensor is channel 1 */
10813d0407baSopenharmony_ci    .chn_num = ROCKCHIP_THERMAL_TWO, /* two channels for tsadc */
10823d0407baSopenharmony_ci
10833d0407baSopenharmony_ci    .tshut_mode = TSHUT_MODE_OTP,       /* default TSHUT via GPIO give PMIC */
10843d0407baSopenharmony_ci    .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
10853d0407baSopenharmony_ci    .tshut_temp = ROCKCHIP_THERMAL_NINETYFIVETHOUSAND,
10863d0407baSopenharmony_ci
10873d0407baSopenharmony_ci    .initialize = rk_tsadcv3_initialize,
10883d0407baSopenharmony_ci    .irq_ack = rk_tsadcv3_irq_ack,
10893d0407baSopenharmony_ci    .control = rk_tsadcv3_control,
10903d0407baSopenharmony_ci    .get_temp = rk_tsadcv2_get_temp,
10913d0407baSopenharmony_ci    .set_alarm_temp = rk_tsadcv2_alarm_temp,
10923d0407baSopenharmony_ci    .set_tshut_temp = rk_tsadcv2_tshut_temp,
10933d0407baSopenharmony_ci    .set_tshut_mode = rk_tsadcv2_tshut_mode,
10943d0407baSopenharmony_ci
10953d0407baSopenharmony_ci    .table =
10963d0407baSopenharmony_ci        {
10973d0407baSopenharmony_ci            .id = rk3399_code_table,
10983d0407baSopenharmony_ci            .length = ARRAY_SIZE(rk3399_code_table),
10993d0407baSopenharmony_ci            .data_mask = TSADCV3_DATA_MASK,
11003d0407baSopenharmony_ci            .mode = ADC_INCREMENT,
11013d0407baSopenharmony_ci        },
11023d0407baSopenharmony_ci};
11033d0407baSopenharmony_ci
11043d0407baSopenharmony_cistatic const struct rockchip_tsadc_chip rk3568_tsadc_data = {
11053d0407baSopenharmony_ci    .chn_id[SENSOR_CPU] = 0,         /* cpu sensor is channel 0 */
11063d0407baSopenharmony_ci    .chn_id[SENSOR_GPU] = 1,         /* gpu sensor is channel 1 */
11073d0407baSopenharmony_ci    .chn_num = ROCKCHIP_THERMAL_TWO, /* two channels for tsadc */
11083d0407baSopenharmony_ci
11093d0407baSopenharmony_ci    .tshut_mode = TSHUT_MODE_OTP,       /* default TSHUT via GPIO give PMIC */
11103d0407baSopenharmony_ci    .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */
11113d0407baSopenharmony_ci    .tshut_temp = ROCKCHIP_THERMAL_NINETYFIVETHOUSAND,
11123d0407baSopenharmony_ci
11133d0407baSopenharmony_ci    .initialize = rk_tsadcv7_initialize,
11143d0407baSopenharmony_ci    .irq_ack = rk_tsadcv3_irq_ack,
11153d0407baSopenharmony_ci    .control = rk_tsadcv3_control,
11163d0407baSopenharmony_ci    .get_temp = rk_tsadcv2_get_temp,
11173d0407baSopenharmony_ci    .set_alarm_temp = rk_tsadcv2_alarm_temp,
11183d0407baSopenharmony_ci    .set_tshut_temp = rk_tsadcv2_tshut_temp,
11193d0407baSopenharmony_ci    .set_tshut_mode = rk_tsadcv2_tshut_mode,
11203d0407baSopenharmony_ci
11213d0407baSopenharmony_ci    .table =
11223d0407baSopenharmony_ci        {
11233d0407baSopenharmony_ci            .id = rk3568_code_table,
11243d0407baSopenharmony_ci            .length = ARRAY_SIZE(rk3568_code_table),
11253d0407baSopenharmony_ci            .data_mask = TSADCV2_DATA_MASK,
11263d0407baSopenharmony_ci            .mode = ADC_INCREMENT,
11273d0407baSopenharmony_ci        },
11283d0407baSopenharmony_ci};
11293d0407baSopenharmony_ci
11303d0407baSopenharmony_cistatic const struct of_device_id of_rockchip_thermal_match[] = {
11313d0407baSopenharmony_ci    {
11323d0407baSopenharmony_ci        .compatible = "rockchip,px30-tsadc",
11333d0407baSopenharmony_ci        .data = (void *)&px30_tsadc_data,
11343d0407baSopenharmony_ci    },
11353d0407baSopenharmony_ci    {
11363d0407baSopenharmony_ci        .compatible = "rockchip,rv1108-tsadc",
11373d0407baSopenharmony_ci        .data = (void *)&rv1108_tsadc_data,
11383d0407baSopenharmony_ci    },
11393d0407baSopenharmony_ci    {
11403d0407baSopenharmony_ci        .compatible = "rockchip,rv1126-tsadc",
11413d0407baSopenharmony_ci        .data = (void *)&rv1126_tsadc_data,
11423d0407baSopenharmony_ci    },
11433d0407baSopenharmony_ci    {
11443d0407baSopenharmony_ci        .compatible = "rockchip,rk1808-tsadc",
11453d0407baSopenharmony_ci        .data = (void *)&rk1808_tsadc_data,
11463d0407baSopenharmony_ci    },
11473d0407baSopenharmony_ci    {
11483d0407baSopenharmony_ci        .compatible = "rockchip,rk3228-tsadc",
11493d0407baSopenharmony_ci        .data = (void *)&rk3228_tsadc_data,
11503d0407baSopenharmony_ci    },
11513d0407baSopenharmony_ci    {
11523d0407baSopenharmony_ci        .compatible = "rockchip,rk3288-tsadc",
11533d0407baSopenharmony_ci        .data = (void *)&rk3288_tsadc_data,
11543d0407baSopenharmony_ci    },
11553d0407baSopenharmony_ci    {
11563d0407baSopenharmony_ci        .compatible = "rockchip,rk3328-tsadc",
11573d0407baSopenharmony_ci        .data = (void *)&rk3328_tsadc_data,
11583d0407baSopenharmony_ci    },
11593d0407baSopenharmony_ci    {
11603d0407baSopenharmony_ci        .compatible = "rockchip,rk3366-tsadc",
11613d0407baSopenharmony_ci        .data = (void *)&rk3366_tsadc_data,
11623d0407baSopenharmony_ci    },
11633d0407baSopenharmony_ci    {
11643d0407baSopenharmony_ci        .compatible = "rockchip,rk3368-tsadc",
11653d0407baSopenharmony_ci        .data = (void *)&rk3368_tsadc_data,
11663d0407baSopenharmony_ci    },
11673d0407baSopenharmony_ci    {
11683d0407baSopenharmony_ci        .compatible = "rockchip,rk3399-tsadc",
11693d0407baSopenharmony_ci        .data = (void *)&rk3399_tsadc_data,
11703d0407baSopenharmony_ci    },
11713d0407baSopenharmony_ci    {
11723d0407baSopenharmony_ci        .compatible = "rockchip,rk3568-tsadc",
11733d0407baSopenharmony_ci        .data = (void *)&rk3568_tsadc_data,
11743d0407baSopenharmony_ci    },
11753d0407baSopenharmony_ci    {},
11763d0407baSopenharmony_ci};
11773d0407baSopenharmony_ciMODULE_DEVICE_TABLE(of, of_rockchip_thermal_match);
11783d0407baSopenharmony_ci
11793d0407baSopenharmony_cistatic void rockchip_thermal_toggle_sensor(struct rockchip_thermal_sensor *sensor, bool on)
11803d0407baSopenharmony_ci{
11813d0407baSopenharmony_ci    struct thermal_zone_device *tzd = sensor->tzd;
11823d0407baSopenharmony_ci
11833d0407baSopenharmony_ci    if (on) {
11843d0407baSopenharmony_ci        thermal_zone_device_enable(tzd);
11853d0407baSopenharmony_ci    } else {
11863d0407baSopenharmony_ci        thermal_zone_device_disable(tzd);
11873d0407baSopenharmony_ci    }
11883d0407baSopenharmony_ci}
11893d0407baSopenharmony_ci
11903d0407baSopenharmony_cistatic irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev)
11913d0407baSopenharmony_ci{
11923d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal = dev;
11933d0407baSopenharmony_ci    int i;
11943d0407baSopenharmony_ci
11953d0407baSopenharmony_ci    dev_dbg(&thermal->pdev->dev, "thermal alarm\n");
11963d0407baSopenharmony_ci
11973d0407baSopenharmony_ci    thermal->chip->irq_ack(thermal->regs);
11983d0407baSopenharmony_ci
11993d0407baSopenharmony_ci    for (i = 0; i < thermal->chip->chn_num; i++) {
12003d0407baSopenharmony_ci        thermal_zone_device_update(thermal->sensors[i].tzd, THERMAL_EVENT_UNSPECIFIED);
12013d0407baSopenharmony_ci    }
12023d0407baSopenharmony_ci
12033d0407baSopenharmony_ci    return IRQ_HANDLED;
12043d0407baSopenharmony_ci}
12053d0407baSopenharmony_ci
12063d0407baSopenharmony_cistatic int rockchip_thermal_set_trips(void *_sensor, int low, int high)
12073d0407baSopenharmony_ci{
12083d0407baSopenharmony_ci    struct rockchip_thermal_sensor *sensor = _sensor;
12093d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal = sensor->thermal;
12103d0407baSopenharmony_ci    const struct rockchip_tsadc_chip *tsadc = thermal->chip;
12113d0407baSopenharmony_ci
12123d0407baSopenharmony_ci    dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n", __func__, sensor->id, low, high);
12133d0407baSopenharmony_ci
12143d0407baSopenharmony_ci    if (tsadc->trim_temp) {
12153d0407baSopenharmony_ci        high += tsadc->trim_temp(thermal->pdev);
12163d0407baSopenharmony_ci    }
12173d0407baSopenharmony_ci
12183d0407baSopenharmony_ci    return tsadc->set_alarm_temp(&tsadc->table, sensor->id, thermal->regs, high);
12193d0407baSopenharmony_ci}
12203d0407baSopenharmony_ci
12213d0407baSopenharmony_cistatic int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
12223d0407baSopenharmony_ci{
12233d0407baSopenharmony_ci    struct rockchip_thermal_sensor *sensor = _sensor;
12243d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal = sensor->thermal;
12253d0407baSopenharmony_ci    const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip;
12263d0407baSopenharmony_ci    int retval;
12273d0407baSopenharmony_ci
12283d0407baSopenharmony_ci    retval = tsadc->get_temp(&tsadc->table, sensor->id, thermal->regs, out_temp);
12293d0407baSopenharmony_ci    if (tsadc->trim_temp) {
12303d0407baSopenharmony_ci        *out_temp -= tsadc->trim_temp(thermal->pdev);
12313d0407baSopenharmony_ci    }
12323d0407baSopenharmony_ci    dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n", sensor->id, *out_temp, retval);
12333d0407baSopenharmony_ci
12343d0407baSopenharmony_ci    return retval;
12353d0407baSopenharmony_ci}
12363d0407baSopenharmony_ci
12373d0407baSopenharmony_cistatic const struct thermal_zone_of_device_ops rockchip_of_thermal_ops = {
12383d0407baSopenharmony_ci    .get_temp = rockchip_thermal_get_temp,
12393d0407baSopenharmony_ci    .set_trips = rockchip_thermal_set_trips,
12403d0407baSopenharmony_ci};
12413d0407baSopenharmony_ci
12423d0407baSopenharmony_cistatic void thermal_pinctrl_select_otp(struct rockchip_thermal_data *thermal)
12433d0407baSopenharmony_ci{
12443d0407baSopenharmony_ci    if (!IS_ERR(thermal->pinctrl) && !IS_ERR_OR_NULL(thermal->otp_state)) {
12453d0407baSopenharmony_ci        pinctrl_select_state(thermal->pinctrl, thermal->otp_state);
12463d0407baSopenharmony_ci    }
12473d0407baSopenharmony_ci}
12483d0407baSopenharmony_ci
12493d0407baSopenharmony_cistatic void thermal_pinctrl_select_gpio(struct rockchip_thermal_data *thermal)
12503d0407baSopenharmony_ci{
12513d0407baSopenharmony_ci    if (!IS_ERR(thermal->pinctrl) && !IS_ERR_OR_NULL(thermal->gpio_state)) {
12523d0407baSopenharmony_ci        pinctrl_select_state(thermal->pinctrl, thermal->gpio_state);
12533d0407baSopenharmony_ci    }
12543d0407baSopenharmony_ci}
12553d0407baSopenharmony_ci
12563d0407baSopenharmony_cistatic int rockchip_get_efuse_value(struct device_node *np, char *porp_name, int *value)
12573d0407baSopenharmony_ci{
12583d0407baSopenharmony_ci    struct nvmem_cell *cell;
12593d0407baSopenharmony_ci    unsigned char *buf;
12603d0407baSopenharmony_ci    size_t len;
12613d0407baSopenharmony_ci
12623d0407baSopenharmony_ci    cell = of_nvmem_cell_get(np, porp_name);
12633d0407baSopenharmony_ci    if (IS_ERR(cell)) {
12643d0407baSopenharmony_ci        return PTR_ERR(cell);
12653d0407baSopenharmony_ci    }
12663d0407baSopenharmony_ci
12673d0407baSopenharmony_ci    buf = (unsigned char *)nvmem_cell_read(cell, &len);
12683d0407baSopenharmony_ci
12693d0407baSopenharmony_ci    nvmem_cell_put(cell);
12703d0407baSopenharmony_ci
12713d0407baSopenharmony_ci    if (IS_ERR(buf)) {
12723d0407baSopenharmony_ci        return PTR_ERR(buf);
12733d0407baSopenharmony_ci    }
12743d0407baSopenharmony_ci
12753d0407baSopenharmony_ci    *value = buf[0];
12763d0407baSopenharmony_ci
12773d0407baSopenharmony_ci    kfree(buf);
12783d0407baSopenharmony_ci
12793d0407baSopenharmony_ci    return 0;
12803d0407baSopenharmony_ci}
12813d0407baSopenharmony_ci
12823d0407baSopenharmony_cistatic int rockchip_configure_from_dt(struct device *dev, struct device_node *np, struct rockchip_thermal_data *thermal)
12833d0407baSopenharmony_ci{
12843d0407baSopenharmony_ci    const struct rockchip_tsadc_chip *tsadc = thermal->chip;
12853d0407baSopenharmony_ci    u32 shut_temp, tshut_mode, tshut_polarity;
12863d0407baSopenharmony_ci    int trim_l = 0, trim_h = 0, trim_bsae = 0;
12873d0407baSopenharmony_ci
12883d0407baSopenharmony_ci    if (of_property_read_u32(np, "rockchip,hw-tshut-temp", &shut_temp)) {
12893d0407baSopenharmony_ci        dev_warn(dev, "Missing tshut temp property, using default %d\n", thermal->chip->tshut_temp);
12903d0407baSopenharmony_ci        thermal->tshut_temp = thermal->chip->tshut_temp;
12913d0407baSopenharmony_ci    } else {
12923d0407baSopenharmony_ci        if (shut_temp > INT_MAX) {
12933d0407baSopenharmony_ci            dev_err(dev, "Invalid tshut temperature specified: %d\n", shut_temp);
12943d0407baSopenharmony_ci            return -ERANGE;
12953d0407baSopenharmony_ci        }
12963d0407baSopenharmony_ci        thermal->tshut_temp = shut_temp;
12973d0407baSopenharmony_ci    }
12983d0407baSopenharmony_ci
12993d0407baSopenharmony_ci    if (of_property_read_u32(np, "rockchip,hw-tshut-mode", &tshut_mode)) {
13003d0407baSopenharmony_ci        dev_warn(dev, "Missing tshut mode property, using default (%s)\n",
13013d0407baSopenharmony_ci                 thermal->chip->tshut_mode == TSHUT_MODE_OTP ? "gpio" : "cru");
13023d0407baSopenharmony_ci        thermal->tshut_mode = thermal->chip->tshut_mode;
13033d0407baSopenharmony_ci    } else {
13043d0407baSopenharmony_ci        thermal->tshut_mode = tshut_mode;
13053d0407baSopenharmony_ci    }
13063d0407baSopenharmony_ci
13073d0407baSopenharmony_ci    if (thermal->tshut_mode > 1) {
13083d0407baSopenharmony_ci        dev_err(dev, "Invalid tshut mode specified: %d\n", thermal->tshut_mode);
13093d0407baSopenharmony_ci        return -EINVAL;
13103d0407baSopenharmony_ci    }
13113d0407baSopenharmony_ci
13123d0407baSopenharmony_ci    if (of_property_read_u32(np, "rockchip,hw-tshut-polarity", &tshut_polarity)) {
13133d0407baSopenharmony_ci        dev_warn(dev, "Missing tshut-polarity property, using default (%s)\n",
13143d0407baSopenharmony_ci                 thermal->chip->tshut_polarity == TSHUT_LOW_ACTIVE ? "low" : "high");
13153d0407baSopenharmony_ci        thermal->tshut_polarity = thermal->chip->tshut_polarity;
13163d0407baSopenharmony_ci    } else {
13173d0407baSopenharmony_ci        thermal->tshut_polarity = tshut_polarity;
13183d0407baSopenharmony_ci    }
13193d0407baSopenharmony_ci
13203d0407baSopenharmony_ci    if (thermal->tshut_polarity > 1) {
13213d0407baSopenharmony_ci        dev_err(dev, "Invalid tshut-polarity specified: %d\n", thermal->tshut_polarity);
13223d0407baSopenharmony_ci        return -EINVAL;
13233d0407baSopenharmony_ci    }
13243d0407baSopenharmony_ci
13253d0407baSopenharmony_ci    /* The tsadc wont to handle the error in here since some SoCs didn't
13263d0407baSopenharmony_ci     * need this property.
13273d0407baSopenharmony_ci     */
13283d0407baSopenharmony_ci    thermal->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf");
13293d0407baSopenharmony_ci    if (IS_ERR(thermal->grf)) {
13303d0407baSopenharmony_ci        dev_warn(dev, "Missing rockchip,grf property\n");
13313d0407baSopenharmony_ci    }
13323d0407baSopenharmony_ci
13333d0407baSopenharmony_ci    if (tsadc->trim_temp && tsadc->get_trim_code) {
13343d0407baSopenharmony_ci        /* The tsadc won't to handle the error in here
13353d0407baSopenharmony_ci         * since some SoCs didn't need this property.
13363d0407baSopenharmony_ci         * rv1126 need trim tsadc.
13373d0407baSopenharmony_ci         */
13383d0407baSopenharmony_ci        if (rockchip_get_efuse_value(np, "trim_l", &trim_l)) {
13393d0407baSopenharmony_ci            dev_warn(dev, "Missing trim_l property\n");
13403d0407baSopenharmony_ci        }
13413d0407baSopenharmony_ci        if (rockchip_get_efuse_value(np, "trim_h", &trim_h)) {
13423d0407baSopenharmony_ci            dev_warn(dev, "Missing trim_h property\n");
13433d0407baSopenharmony_ci        }
13443d0407baSopenharmony_ci        if (rockchip_get_efuse_value(np, "trim_base", &trim_bsae)) {
13453d0407baSopenharmony_ci            dev_warn(dev, "Missing trim_base property\n");
13463d0407baSopenharmony_ci        }
13473d0407baSopenharmony_ci
13483d0407baSopenharmony_ci        if (trim_l && trim_h && trim_bsae) {
13493d0407baSopenharmony_ci            thermal->trim = tsadc->get_trim_code(thermal->pdev, (trim_h << ROCKCHIP_THERMAL_EIGHT) | trim_l, trim_bsae);
13503d0407baSopenharmony_ci            dev_info(dev, "tsadc trimmed value = %d\n", thermal->trim);
13513d0407baSopenharmony_ci            thermal->tshut_temp += tsadc->trim_temp(thermal->pdev);
13523d0407baSopenharmony_ci        }
13533d0407baSopenharmony_ci    }
13543d0407baSopenharmony_ci
13553d0407baSopenharmony_ci    return 0;
13563d0407baSopenharmony_ci}
13573d0407baSopenharmony_ci
13583d0407baSopenharmony_cistatic int rockchip_thermal_register_sensor(struct platform_device *pdev, struct rockchip_thermal_data *thermal,
13593d0407baSopenharmony_ci                                            struct rockchip_thermal_sensor *sensor, int id)
13603d0407baSopenharmony_ci{
13613d0407baSopenharmony_ci    const struct rockchip_tsadc_chip *tsadc = thermal->chip;
13623d0407baSopenharmony_ci    int error;
13633d0407baSopenharmony_ci
13643d0407baSopenharmony_ci    tsadc->set_tshut_mode(thermal->grf, id, thermal->regs, thermal->tshut_mode);
13653d0407baSopenharmony_ci
13663d0407baSopenharmony_ci    error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs, thermal->tshut_temp);
13673d0407baSopenharmony_ci    if (error) {
13683d0407baSopenharmony_ci        dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n", __func__, thermal->tshut_temp, error);
13693d0407baSopenharmony_ci    }
13703d0407baSopenharmony_ci
13713d0407baSopenharmony_ci    sensor->thermal = thermal;
13723d0407baSopenharmony_ci    sensor->id = id;
13733d0407baSopenharmony_ci    sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, id, sensor, &rockchip_of_thermal_ops);
13743d0407baSopenharmony_ci    if (IS_ERR(sensor->tzd)) {
13753d0407baSopenharmony_ci        error = PTR_ERR(sensor->tzd);
13763d0407baSopenharmony_ci        dev_err(&pdev->dev, "failed to register sensor %d: %d\n", id, error);
13773d0407baSopenharmony_ci        return error;
13783d0407baSopenharmony_ci    }
13793d0407baSopenharmony_ci
13803d0407baSopenharmony_ci    return 0;
13813d0407baSopenharmony_ci}
13823d0407baSopenharmony_ci
13833d0407baSopenharmony_ci/**
13843d0407baSopenharmony_ci * Reset TSADC Controller, reset all tsadc registers.
13853d0407baSopenharmony_ci * @reset: the reset controller of tsadc
13863d0407baSopenharmony_ci */
13873d0407baSopenharmony_cistatic void rockchip_thermal_reset_controller(struct reset_control *reset)
13883d0407baSopenharmony_ci{
13893d0407baSopenharmony_ci    reset_control_assert(reset);
13903d0407baSopenharmony_ci    usleep_range(ROCKCHIP_THERMAL_TEN, ROCKCHIP_THERMAL_TWENTY);
13913d0407baSopenharmony_ci    reset_control_deassert(reset);
13923d0407baSopenharmony_ci}
13933d0407baSopenharmony_ci
13943d0407baSopenharmony_cistatic void rockchip_dump_temperature(struct rockchip_thermal_data *thermal)
13953d0407baSopenharmony_ci{
13963d0407baSopenharmony_ci    struct platform_device *pdev;
13973d0407baSopenharmony_ci    int i;
13983d0407baSopenharmony_ci
13993d0407baSopenharmony_ci    if (!thermal) {
14003d0407baSopenharmony_ci        return;
14013d0407baSopenharmony_ci    }
14023d0407baSopenharmony_ci
14033d0407baSopenharmony_ci    pdev = thermal->pdev;
14043d0407baSopenharmony_ci
14053d0407baSopenharmony_ci    for (i = 0; i < thermal->chip->chn_num; i++) {
14063d0407baSopenharmony_ci        struct rockchip_thermal_sensor *sensor = &thermal->sensors[i];
14073d0407baSopenharmony_ci        struct thermal_zone_device *tz = sensor->tzd;
14083d0407baSopenharmony_ci
14093d0407baSopenharmony_ci        if (tz->temperature != THERMAL_TEMP_INVALID) {
14103d0407baSopenharmony_ci            dev_warn(&pdev->dev, "channal %d: temperature(%d C)\n", i, tz->temperature / ROCKCHIP_THERMAL_ONETHOUSAND);
14113d0407baSopenharmony_ci        }
14123d0407baSopenharmony_ci    }
14133d0407baSopenharmony_ci
14143d0407baSopenharmony_ci    if (thermal->regs) {
14153d0407baSopenharmony_ci        pr_warn("THERMAL REGS:\n");
14163d0407baSopenharmony_ci        print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, ROCKCHIP_THERMAL_THIRTYTWO, 0x4, thermal->regs, 0x88,
14173d0407baSopenharmony_ci                       false);
14183d0407baSopenharmony_ci    }
14193d0407baSopenharmony_ci}
14203d0407baSopenharmony_ci
14213d0407baSopenharmony_cistatic int rockchip_thermal_panic(struct notifier_block *this, unsigned long ev, void *ptr)
14223d0407baSopenharmony_ci{
14233d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal;
14243d0407baSopenharmony_ci
14253d0407baSopenharmony_ci    thermal = container_of(this, struct rockchip_thermal_data, panic_nb);
14263d0407baSopenharmony_ci    rockchip_dump_temperature(thermal);
14273d0407baSopenharmony_ci
14283d0407baSopenharmony_ci    return NOTIFY_DONE;
14293d0407baSopenharmony_ci}
14303d0407baSopenharmony_ci
14313d0407baSopenharmony_cistatic int rockchip_thermal_probe(struct platform_device *pdev)
14323d0407baSopenharmony_ci{
14333d0407baSopenharmony_ci    struct device_node *np = pdev->dev.of_node;
14343d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal;
14353d0407baSopenharmony_ci    const struct of_device_id *match;
14363d0407baSopenharmony_ci    struct resource *res;
14373d0407baSopenharmony_ci    int irq;
14383d0407baSopenharmony_ci    int i;
14393d0407baSopenharmony_ci    int error;
14403d0407baSopenharmony_ci
14413d0407baSopenharmony_ci    match = of_match_node(of_rockchip_thermal_match, np);
14423d0407baSopenharmony_ci    if (!match) {
14433d0407baSopenharmony_ci        return -ENXIO;
14443d0407baSopenharmony_ci    }
14453d0407baSopenharmony_ci
14463d0407baSopenharmony_ci    irq = platform_get_irq(pdev, 0);
14473d0407baSopenharmony_ci    if (irq < 0) {
14483d0407baSopenharmony_ci        return -EINVAL;
14493d0407baSopenharmony_ci    }
14503d0407baSopenharmony_ci
14513d0407baSopenharmony_ci    thermal = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_thermal_data), GFP_KERNEL);
14523d0407baSopenharmony_ci    if (!thermal) {
14533d0407baSopenharmony_ci        return -ENOMEM;
14543d0407baSopenharmony_ci    }
14553d0407baSopenharmony_ci
14563d0407baSopenharmony_ci    thermal->pdev = pdev;
14573d0407baSopenharmony_ci
14583d0407baSopenharmony_ci    thermal->chip = (const struct rockchip_tsadc_chip *)match->data;
14593d0407baSopenharmony_ci    if (!thermal->chip) {
14603d0407baSopenharmony_ci        return -EINVAL;
14613d0407baSopenharmony_ci    }
14623d0407baSopenharmony_ci
14633d0407baSopenharmony_ci    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
14643d0407baSopenharmony_ci    thermal->regs = devm_ioremap_resource(&pdev->dev, res);
14653d0407baSopenharmony_ci    if (IS_ERR(thermal->regs)) {
14663d0407baSopenharmony_ci        return PTR_ERR(thermal->regs);
14673d0407baSopenharmony_ci    }
14683d0407baSopenharmony_ci
14693d0407baSopenharmony_ci    thermal->reset = devm_reset_control_array_get(&pdev->dev, false, false);
14703d0407baSopenharmony_ci    if (IS_ERR(thermal->reset)) {
14713d0407baSopenharmony_ci        if (PTR_ERR(thermal->reset) != -EPROBE_DEFER) {
14723d0407baSopenharmony_ci            dev_err(&pdev->dev, "failed to get tsadc reset lines\n");
14733d0407baSopenharmony_ci        }
14743d0407baSopenharmony_ci        return PTR_ERR(thermal->reset);
14753d0407baSopenharmony_ci    }
14763d0407baSopenharmony_ci
14773d0407baSopenharmony_ci    thermal->num_clks = devm_clk_bulk_get_all(&pdev->dev, &thermal->clks);
14783d0407baSopenharmony_ci    if (thermal->num_clks < 1) {
14793d0407baSopenharmony_ci        return -ENODEV;
14803d0407baSopenharmony_ci    }
14813d0407baSopenharmony_ci
14823d0407baSopenharmony_ci    error = clk_bulk_prepare_enable(thermal->num_clks, thermal->clks);
14833d0407baSopenharmony_ci    if (error) {
14843d0407baSopenharmony_ci        dev_err(&pdev->dev, "failed to prepare enable tsadc bulk clks: %d\n", error);
14853d0407baSopenharmony_ci        return error;
14863d0407baSopenharmony_ci    }
14873d0407baSopenharmony_ci    platform_set_drvdata(pdev, thermal);
14883d0407baSopenharmony_ci
14893d0407baSopenharmony_ci    thermal->chip->control(thermal->regs, false);
14903d0407baSopenharmony_ci
14913d0407baSopenharmony_ci    rockchip_thermal_reset_controller(thermal->reset);
14923d0407baSopenharmony_ci
14933d0407baSopenharmony_ci    error = rockchip_configure_from_dt(&pdev->dev, np, thermal);
14943d0407baSopenharmony_ci    if (error) {
14953d0407baSopenharmony_ci        dev_err(&pdev->dev, "failed to parse device tree data: %d\n", error);
14963d0407baSopenharmony_ci        goto err_disable_clocks;
14973d0407baSopenharmony_ci    }
14983d0407baSopenharmony_ci
14993d0407baSopenharmony_ci    thermal->chip->initialize(thermal->grf, thermal->regs, thermal->tshut_polarity);
15003d0407baSopenharmony_ci
15013d0407baSopenharmony_ci    if (thermal->tshut_mode == TSHUT_MODE_OTP) {
15023d0407baSopenharmony_ci        thermal->pinctrl = devm_pinctrl_get(&pdev->dev);
15033d0407baSopenharmony_ci        if (IS_ERR(thermal->pinctrl)) {
15043d0407baSopenharmony_ci            dev_err(&pdev->dev, "failed to find thermal pinctrl\n");
15053d0407baSopenharmony_ci        }
15063d0407baSopenharmony_ci
15073d0407baSopenharmony_ci        thermal->gpio_state = pinctrl_lookup_state(thermal->pinctrl, "gpio");
15083d0407baSopenharmony_ci        if (IS_ERR_OR_NULL(thermal->gpio_state)) {
15093d0407baSopenharmony_ci            dev_err(&pdev->dev, "failed to find thermal gpio state\n");
15103d0407baSopenharmony_ci        }
15113d0407baSopenharmony_ci
15123d0407baSopenharmony_ci        thermal->otp_state = pinctrl_lookup_state(thermal->pinctrl, "otpout");
15133d0407baSopenharmony_ci        if (IS_ERR_OR_NULL(thermal->otp_state)) {
15143d0407baSopenharmony_ci            dev_err(&pdev->dev, "failed to find thermal otpout state\n");
15153d0407baSopenharmony_ci        }
15163d0407baSopenharmony_ci
15173d0407baSopenharmony_ci        thermal_pinctrl_select_otp(thermal);
15183d0407baSopenharmony_ci    }
15193d0407baSopenharmony_ci
15203d0407baSopenharmony_ci    for (i = 0; i < thermal->chip->chn_num; i++) {
15213d0407baSopenharmony_ci        error = rockchip_thermal_register_sensor(pdev, thermal, &thermal->sensors[i], thermal->chip->chn_id[i]);
15223d0407baSopenharmony_ci        if (error) {
15233d0407baSopenharmony_ci            dev_err(&pdev->dev, "failed to register sensor[%d] : error = %d\n", i, error);
15243d0407baSopenharmony_ci            goto err_disable_clocks;
15253d0407baSopenharmony_ci        }
15263d0407baSopenharmony_ci    }
15273d0407baSopenharmony_ci
15283d0407baSopenharmony_ci    error = devm_request_threaded_irq(&pdev->dev, irq, NULL, &rockchip_thermal_alarm_irq_thread, IRQF_ONESHOT,
15293d0407baSopenharmony_ci                                      "rockchip_thermal", thermal);
15303d0407baSopenharmony_ci    if (error) {
15313d0407baSopenharmony_ci        dev_err(&pdev->dev, "failed to request tsadc irq: %d\n", error);
15323d0407baSopenharmony_ci        goto err_disable_clocks;
15333d0407baSopenharmony_ci    }
15343d0407baSopenharmony_ci
15353d0407baSopenharmony_ci    thermal->chip->control(thermal->regs, true);
15363d0407baSopenharmony_ci
15373d0407baSopenharmony_ci    for (i = 0; i < thermal->chip->chn_num; i++) {
15383d0407baSopenharmony_ci        rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
15393d0407baSopenharmony_ci        thermal->sensors[i].tzd->tzp->no_hwmon = false;
15403d0407baSopenharmony_ci        error = thermal_add_hwmon_sysfs(thermal->sensors[i].tzd);
15413d0407baSopenharmony_ci        if (error) {
15423d0407baSopenharmony_ci            dev_warn(&pdev->dev, "failed to register sensor %d with hwmon: %d\n", i, error);
15433d0407baSopenharmony_ci        }
15443d0407baSopenharmony_ci    }
15453d0407baSopenharmony_ci
15463d0407baSopenharmony_ci    thermal->panic_nb.notifier_call = rockchip_thermal_panic;
15473d0407baSopenharmony_ci    atomic_notifier_chain_register(&panic_notifier_list, &thermal->panic_nb);
15483d0407baSopenharmony_ci
15493d0407baSopenharmony_ci    dev_info(&pdev->dev, "tsadc is probed successfully!\n");
15503d0407baSopenharmony_ci
15513d0407baSopenharmony_ci    return 0;
15523d0407baSopenharmony_ci
15533d0407baSopenharmony_cierr_disable_clocks:
15543d0407baSopenharmony_ci    clk_bulk_disable_unprepare(thermal->num_clks, thermal->clks);
15553d0407baSopenharmony_ci
15563d0407baSopenharmony_ci    return error;
15573d0407baSopenharmony_ci}
15583d0407baSopenharmony_ci
15593d0407baSopenharmony_cistatic int rockchip_thermal_remove(struct platform_device *pdev)
15603d0407baSopenharmony_ci{
15613d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
15623d0407baSopenharmony_ci    int i;
15633d0407baSopenharmony_ci
15643d0407baSopenharmony_ci    for (i = 0; i < thermal->chip->chn_num; i++) {
15653d0407baSopenharmony_ci        struct rockchip_thermal_sensor *sensor = &thermal->sensors[i];
15663d0407baSopenharmony_ci
15673d0407baSopenharmony_ci        thermal_remove_hwmon_sysfs(sensor->tzd);
15683d0407baSopenharmony_ci        rockchip_thermal_toggle_sensor(sensor, false);
15693d0407baSopenharmony_ci    }
15703d0407baSopenharmony_ci
15713d0407baSopenharmony_ci    thermal->chip->control(thermal->regs, false);
15723d0407baSopenharmony_ci
15733d0407baSopenharmony_ci    clk_bulk_disable_unprepare(thermal->num_clks, thermal->clks);
15743d0407baSopenharmony_ci
15753d0407baSopenharmony_ci    return 0;
15763d0407baSopenharmony_ci}
15773d0407baSopenharmony_ci
15783d0407baSopenharmony_cistatic void rockchip_thermal_shutdown(struct platform_device *pdev)
15793d0407baSopenharmony_ci{
15803d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
15813d0407baSopenharmony_ci    int i;
15823d0407baSopenharmony_ci
15833d0407baSopenharmony_ci    for (i = 0; i < thermal->chip->chn_num; i++) {
15843d0407baSopenharmony_ci        int id = thermal->sensors[i].id;
15853d0407baSopenharmony_ci
15863d0407baSopenharmony_ci        if (thermal->tshut_mode != TSHUT_MODE_CRU) {
15873d0407baSopenharmony_ci            thermal->chip->set_tshut_mode(thermal->grf, id, thermal->regs, TSHUT_MODE_CRU);
15883d0407baSopenharmony_ci        }
15893d0407baSopenharmony_ci    }
15903d0407baSopenharmony_ci    if (thermal->tshut_mode == TSHUT_MODE_OTP) {
15913d0407baSopenharmony_ci        thermal_pinctrl_select_gpio(thermal);
15923d0407baSopenharmony_ci    }
15933d0407baSopenharmony_ci}
15943d0407baSopenharmony_ci
15953d0407baSopenharmony_cistatic int __maybe_unused rockchip_thermal_suspend(struct device *dev)
15963d0407baSopenharmony_ci{
15973d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal = dev_get_drvdata(dev);
15983d0407baSopenharmony_ci    int i;
15993d0407baSopenharmony_ci
16003d0407baSopenharmony_ci    for (i = 0; i < thermal->chip->chn_num; i++) {
16013d0407baSopenharmony_ci        rockchip_thermal_toggle_sensor(&thermal->sensors[i], false);
16023d0407baSopenharmony_ci    }
16033d0407baSopenharmony_ci
16043d0407baSopenharmony_ci    thermal->chip->control(thermal->regs, false);
16053d0407baSopenharmony_ci
16063d0407baSopenharmony_ci    clk_bulk_disable(thermal->num_clks, thermal->clks);
16073d0407baSopenharmony_ci
16083d0407baSopenharmony_ci    if (thermal->tshut_mode == TSHUT_MODE_OTP) {
16093d0407baSopenharmony_ci        thermal_pinctrl_select_gpio(thermal);
16103d0407baSopenharmony_ci    }
16113d0407baSopenharmony_ci
16123d0407baSopenharmony_ci    return 0;
16133d0407baSopenharmony_ci}
16143d0407baSopenharmony_ci
16153d0407baSopenharmony_cistatic int __maybe_unused rockchip_thermal_resume(struct device *dev)
16163d0407baSopenharmony_ci{
16173d0407baSopenharmony_ci    struct rockchip_thermal_data *thermal = dev_get_drvdata(dev);
16183d0407baSopenharmony_ci    int i;
16193d0407baSopenharmony_ci    int error;
16203d0407baSopenharmony_ci
16213d0407baSopenharmony_ci    error = clk_bulk_enable(thermal->num_clks, thermal->clks);
16223d0407baSopenharmony_ci    if (error) {
16233d0407baSopenharmony_ci        dev_err(dev, "failed to enable tsadc bulk clks: %d\n", error);
16243d0407baSopenharmony_ci        return error;
16253d0407baSopenharmony_ci    }
16263d0407baSopenharmony_ci
16273d0407baSopenharmony_ci    rockchip_thermal_reset_controller(thermal->reset);
16283d0407baSopenharmony_ci
16293d0407baSopenharmony_ci    thermal->chip->initialize(thermal->grf, thermal->regs, thermal->tshut_polarity);
16303d0407baSopenharmony_ci
16313d0407baSopenharmony_ci    for (i = 0; i < thermal->chip->chn_num; i++) {
16323d0407baSopenharmony_ci        int id = thermal->sensors[i].id;
16333d0407baSopenharmony_ci
16343d0407baSopenharmony_ci        thermal->chip->set_tshut_mode(thermal->grf, id, thermal->regs, thermal->tshut_mode);
16353d0407baSopenharmony_ci
16363d0407baSopenharmony_ci        error = thermal->chip->set_tshut_temp(&thermal->chip->table, id, thermal->regs, thermal->tshut_temp);
16373d0407baSopenharmony_ci        if (error) {
16383d0407baSopenharmony_ci            dev_err(dev, "%s: invalid tshut=%d, error=%d\n", __func__, thermal->tshut_temp, error);
16393d0407baSopenharmony_ci        }
16403d0407baSopenharmony_ci    }
16413d0407baSopenharmony_ci
16423d0407baSopenharmony_ci    thermal->chip->control(thermal->regs, true);
16433d0407baSopenharmony_ci
16443d0407baSopenharmony_ci    for (i = 0; i < thermal->chip->chn_num; i++) {
16453d0407baSopenharmony_ci        rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
16463d0407baSopenharmony_ci    }
16473d0407baSopenharmony_ci
16483d0407baSopenharmony_ci    if (thermal->tshut_mode == TSHUT_MODE_OTP) {
16493d0407baSopenharmony_ci        thermal_pinctrl_select_otp(thermal);
16503d0407baSopenharmony_ci    }
16513d0407baSopenharmony_ci
16523d0407baSopenharmony_ci    return 0;
16533d0407baSopenharmony_ci}
16543d0407baSopenharmony_ci
16553d0407baSopenharmony_cistatic SIMPLE_DEV_PM_OPS(rockchip_thermal_pm_ops, rockchip_thermal_suspend, rockchip_thermal_resume);
16563d0407baSopenharmony_ci
16573d0407baSopenharmony_cistatic struct platform_driver rockchip_thermal_driver = {
16583d0407baSopenharmony_ci    .driver =
16593d0407baSopenharmony_ci        {
16603d0407baSopenharmony_ci            .name = "rockchip-thermal",
16613d0407baSopenharmony_ci            .pm = &rockchip_thermal_pm_ops,
16623d0407baSopenharmony_ci            .of_match_table = of_rockchip_thermal_match,
16633d0407baSopenharmony_ci        },
16643d0407baSopenharmony_ci    .probe = rockchip_thermal_probe,
16653d0407baSopenharmony_ci    .remove = rockchip_thermal_remove,
16663d0407baSopenharmony_ci    .shutdown = rockchip_thermal_shutdown,
16673d0407baSopenharmony_ci};
16683d0407baSopenharmony_ci
16693d0407baSopenharmony_cimodule_platform_driver(rockchip_thermal_driver);
16703d0407baSopenharmony_ci
16713d0407baSopenharmony_ciMODULE_DESCRIPTION("ROCKCHIP THERMAL Driver");
16723d0407baSopenharmony_ciMODULE_AUTHOR("Rockchip, Inc.");
16733d0407baSopenharmony_ciMODULE_LICENSE("GPL v2");
16743d0407baSopenharmony_ciMODULE_ALIAS("platform:rockchip-thermal");
1675