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