162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2014-2016, Fuzhou Rockchip Electronics Co., Ltd 462306a36Sopenharmony_ci * Caesar Wang <wxt@rock-chips.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/clk.h> 862306a36Sopenharmony_ci#include <linux/delay.h> 962306a36Sopenharmony_ci#include <linux/interrupt.h> 1062306a36Sopenharmony_ci#include <linux/io.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/of.h> 1362306a36Sopenharmony_ci#include <linux/of_address.h> 1462306a36Sopenharmony_ci#include <linux/of_irq.h> 1562306a36Sopenharmony_ci#include <linux/platform_device.h> 1662306a36Sopenharmony_ci#include <linux/regmap.h> 1762306a36Sopenharmony_ci#include <linux/reset.h> 1862306a36Sopenharmony_ci#include <linux/thermal.h> 1962306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 2062306a36Sopenharmony_ci#include <linux/pinctrl/consumer.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci/* 2362306a36Sopenharmony_ci * If the temperature over a period of time High, 2462306a36Sopenharmony_ci * the resulting TSHUT gave CRU module,let it reset the entire chip, 2562306a36Sopenharmony_ci * or via GPIO give PMIC. 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_cienum tshut_mode { 2862306a36Sopenharmony_ci TSHUT_MODE_CRU = 0, 2962306a36Sopenharmony_ci TSHUT_MODE_GPIO, 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/* 3362306a36Sopenharmony_ci * The system Temperature Sensors tshut(tshut) polarity 3462306a36Sopenharmony_ci * the bit 8 is tshut polarity. 3562306a36Sopenharmony_ci * 0: low active, 1: high active 3662306a36Sopenharmony_ci */ 3762306a36Sopenharmony_cienum tshut_polarity { 3862306a36Sopenharmony_ci TSHUT_LOW_ACTIVE = 0, 3962306a36Sopenharmony_ci TSHUT_HIGH_ACTIVE, 4062306a36Sopenharmony_ci}; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* 4362306a36Sopenharmony_ci * The conversion table has the adc value and temperature. 4462306a36Sopenharmony_ci * ADC_DECREMENT: the adc value is of diminishing.(e.g. rk3288_code_table) 4562306a36Sopenharmony_ci * ADC_INCREMENT: the adc value is incremental.(e.g. rk3368_code_table) 4662306a36Sopenharmony_ci */ 4762306a36Sopenharmony_cienum adc_sort_mode { 4862306a36Sopenharmony_ci ADC_DECREMENT = 0, 4962306a36Sopenharmony_ci ADC_INCREMENT, 5062306a36Sopenharmony_ci}; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci#include "thermal_hwmon.h" 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/** 5562306a36Sopenharmony_ci * struct chip_tsadc_table - hold information about chip-specific differences 5662306a36Sopenharmony_ci * @id: conversion table 5762306a36Sopenharmony_ci * @length: size of conversion table 5862306a36Sopenharmony_ci * @data_mask: mask to apply on data inputs 5962306a36Sopenharmony_ci * @mode: sort mode of this adc variant (incrementing or decrementing) 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_cistruct chip_tsadc_table { 6262306a36Sopenharmony_ci const struct tsadc_table *id; 6362306a36Sopenharmony_ci unsigned int length; 6462306a36Sopenharmony_ci u32 data_mask; 6562306a36Sopenharmony_ci enum adc_sort_mode mode; 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/** 6962306a36Sopenharmony_ci * struct rockchip_tsadc_chip - hold the private data of tsadc chip 7062306a36Sopenharmony_ci * @chn_offset: the channel offset of the first channel 7162306a36Sopenharmony_ci * @chn_num: the channel number of tsadc chip 7262306a36Sopenharmony_ci * @tshut_temp: the hardware-controlled shutdown temperature value 7362306a36Sopenharmony_ci * @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO) 7462306a36Sopenharmony_ci * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH) 7562306a36Sopenharmony_ci * @initialize: SoC special initialize tsadc controller method 7662306a36Sopenharmony_ci * @irq_ack: clear the interrupt 7762306a36Sopenharmony_ci * @control: enable/disable method for the tsadc controller 7862306a36Sopenharmony_ci * @get_temp: get the temperature 7962306a36Sopenharmony_ci * @set_alarm_temp: set the high temperature interrupt 8062306a36Sopenharmony_ci * @set_tshut_temp: set the hardware-controlled shutdown temperature 8162306a36Sopenharmony_ci * @set_tshut_mode: set the hardware-controlled shutdown mode 8262306a36Sopenharmony_ci * @table: the chip-specific conversion table 8362306a36Sopenharmony_ci */ 8462306a36Sopenharmony_cistruct rockchip_tsadc_chip { 8562306a36Sopenharmony_ci /* The sensor id of chip correspond to the ADC channel */ 8662306a36Sopenharmony_ci int chn_offset; 8762306a36Sopenharmony_ci int chn_num; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci /* The hardware-controlled tshut property */ 9062306a36Sopenharmony_ci int tshut_temp; 9162306a36Sopenharmony_ci enum tshut_mode tshut_mode; 9262306a36Sopenharmony_ci enum tshut_polarity tshut_polarity; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci /* Chip-wide methods */ 9562306a36Sopenharmony_ci void (*initialize)(struct regmap *grf, 9662306a36Sopenharmony_ci void __iomem *reg, enum tshut_polarity p); 9762306a36Sopenharmony_ci void (*irq_ack)(void __iomem *reg); 9862306a36Sopenharmony_ci void (*control)(void __iomem *reg, bool on); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci /* Per-sensor methods */ 10162306a36Sopenharmony_ci int (*get_temp)(const struct chip_tsadc_table *table, 10262306a36Sopenharmony_ci int chn, void __iomem *reg, int *temp); 10362306a36Sopenharmony_ci int (*set_alarm_temp)(const struct chip_tsadc_table *table, 10462306a36Sopenharmony_ci int chn, void __iomem *reg, int temp); 10562306a36Sopenharmony_ci int (*set_tshut_temp)(const struct chip_tsadc_table *table, 10662306a36Sopenharmony_ci int chn, void __iomem *reg, int temp); 10762306a36Sopenharmony_ci void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci /* Per-table methods */ 11062306a36Sopenharmony_ci struct chip_tsadc_table table; 11162306a36Sopenharmony_ci}; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci/** 11462306a36Sopenharmony_ci * struct rockchip_thermal_sensor - hold the information of thermal sensor 11562306a36Sopenharmony_ci * @thermal: pointer to the platform/configuration data 11662306a36Sopenharmony_ci * @tzd: pointer to a thermal zone 11762306a36Sopenharmony_ci * @id: identifier of the thermal sensor 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_cistruct rockchip_thermal_sensor { 12062306a36Sopenharmony_ci struct rockchip_thermal_data *thermal; 12162306a36Sopenharmony_ci struct thermal_zone_device *tzd; 12262306a36Sopenharmony_ci int id; 12362306a36Sopenharmony_ci}; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci/** 12662306a36Sopenharmony_ci * struct rockchip_thermal_data - hold the private data of thermal driver 12762306a36Sopenharmony_ci * @chip: pointer to the platform/configuration data 12862306a36Sopenharmony_ci * @pdev: platform device of thermal 12962306a36Sopenharmony_ci * @reset: the reset controller of tsadc 13062306a36Sopenharmony_ci * @sensors: array of thermal sensors 13162306a36Sopenharmony_ci * @clk: the controller clock is divided by the exteral 24MHz 13262306a36Sopenharmony_ci * @pclk: the advanced peripherals bus clock 13362306a36Sopenharmony_ci * @grf: the general register file will be used to do static set by software 13462306a36Sopenharmony_ci * @regs: the base address of tsadc controller 13562306a36Sopenharmony_ci * @tshut_temp: the hardware-controlled shutdown temperature value 13662306a36Sopenharmony_ci * @tshut_mode: the hardware-controlled shutdown mode (0:CRU 1:GPIO) 13762306a36Sopenharmony_ci * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH) 13862306a36Sopenharmony_ci */ 13962306a36Sopenharmony_cistruct rockchip_thermal_data { 14062306a36Sopenharmony_ci const struct rockchip_tsadc_chip *chip; 14162306a36Sopenharmony_ci struct platform_device *pdev; 14262306a36Sopenharmony_ci struct reset_control *reset; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci struct rockchip_thermal_sensor *sensors; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci struct clk *clk; 14762306a36Sopenharmony_ci struct clk *pclk; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci struct regmap *grf; 15062306a36Sopenharmony_ci void __iomem *regs; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci int tshut_temp; 15362306a36Sopenharmony_ci enum tshut_mode tshut_mode; 15462306a36Sopenharmony_ci enum tshut_polarity tshut_polarity; 15562306a36Sopenharmony_ci}; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci/* 15862306a36Sopenharmony_ci * TSADC Sensor Register description: 15962306a36Sopenharmony_ci * 16062306a36Sopenharmony_ci * TSADCV2_* are used for RK3288 SoCs, the other chips can reuse it. 16162306a36Sopenharmony_ci * TSADCV3_* are used for newer SoCs than RK3288. (e.g: RK3228, RK3399) 16262306a36Sopenharmony_ci * 16362306a36Sopenharmony_ci */ 16462306a36Sopenharmony_ci#define TSADCV2_USER_CON 0x00 16562306a36Sopenharmony_ci#define TSADCV2_AUTO_CON 0x04 16662306a36Sopenharmony_ci#define TSADCV2_INT_EN 0x08 16762306a36Sopenharmony_ci#define TSADCV2_INT_PD 0x0c 16862306a36Sopenharmony_ci#define TSADCV3_AUTO_SRC_CON 0x0c 16962306a36Sopenharmony_ci#define TSADCV3_HT_INT_EN 0x14 17062306a36Sopenharmony_ci#define TSADCV3_HSHUT_GPIO_INT_EN 0x18 17162306a36Sopenharmony_ci#define TSADCV3_HSHUT_CRU_INT_EN 0x1c 17262306a36Sopenharmony_ci#define TSADCV3_INT_PD 0x24 17362306a36Sopenharmony_ci#define TSADCV3_HSHUT_PD 0x28 17462306a36Sopenharmony_ci#define TSADCV2_DATA(chn) (0x20 + (chn) * 0x04) 17562306a36Sopenharmony_ci#define TSADCV2_COMP_INT(chn) (0x30 + (chn) * 0x04) 17662306a36Sopenharmony_ci#define TSADCV2_COMP_SHUT(chn) (0x40 + (chn) * 0x04) 17762306a36Sopenharmony_ci#define TSADCV3_DATA(chn) (0x2c + (chn) * 0x04) 17862306a36Sopenharmony_ci#define TSADCV3_COMP_INT(chn) (0x6c + (chn) * 0x04) 17962306a36Sopenharmony_ci#define TSADCV3_COMP_SHUT(chn) (0x10c + (chn) * 0x04) 18062306a36Sopenharmony_ci#define TSADCV2_HIGHT_INT_DEBOUNCE 0x60 18162306a36Sopenharmony_ci#define TSADCV2_HIGHT_TSHUT_DEBOUNCE 0x64 18262306a36Sopenharmony_ci#define TSADCV3_HIGHT_INT_DEBOUNCE 0x14c 18362306a36Sopenharmony_ci#define TSADCV3_HIGHT_TSHUT_DEBOUNCE 0x150 18462306a36Sopenharmony_ci#define TSADCV2_AUTO_PERIOD 0x68 18562306a36Sopenharmony_ci#define TSADCV2_AUTO_PERIOD_HT 0x6c 18662306a36Sopenharmony_ci#define TSADCV3_AUTO_PERIOD 0x154 18762306a36Sopenharmony_ci#define TSADCV3_AUTO_PERIOD_HT 0x158 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci#define TSADCV2_AUTO_EN BIT(0) 19062306a36Sopenharmony_ci#define TSADCV2_AUTO_EN_MASK BIT(16) 19162306a36Sopenharmony_ci#define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn)) 19262306a36Sopenharmony_ci#define TSADCV3_AUTO_SRC_EN(chn) BIT(chn) 19362306a36Sopenharmony_ci#define TSADCV3_AUTO_SRC_EN_MASK(chn) BIT(16 + chn) 19462306a36Sopenharmony_ci#define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8) 19562306a36Sopenharmony_ci#define TSADCV2_AUTO_TSHUT_POLARITY_MASK BIT(24) 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci#define TSADCV3_AUTO_Q_SEL_EN BIT(1) 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci#define TSADCV2_INT_SRC_EN(chn) BIT(chn) 20062306a36Sopenharmony_ci#define TSADCV2_INT_SRC_EN_MASK(chn) BIT(16 + (chn)) 20162306a36Sopenharmony_ci#define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn)) 20262306a36Sopenharmony_ci#define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn)) 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci#define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8) 20562306a36Sopenharmony_ci#define TSADCV3_INT_PD_CLEAR_MASK ~BIT(16) 20662306a36Sopenharmony_ci#define TSADCV4_INT_PD_CLEAR_MASK 0xffffffff 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci#define TSADCV2_DATA_MASK 0xfff 20962306a36Sopenharmony_ci#define TSADCV3_DATA_MASK 0x3ff 21062306a36Sopenharmony_ci#define TSADCV4_DATA_MASK 0x1ff 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci#define TSADCV2_HIGHT_INT_DEBOUNCE_COUNT 4 21362306a36Sopenharmony_ci#define TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT 4 21462306a36Sopenharmony_ci#define TSADCV2_AUTO_PERIOD_TIME 250 /* 250ms */ 21562306a36Sopenharmony_ci#define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* 50ms */ 21662306a36Sopenharmony_ci#define TSADCV3_AUTO_PERIOD_TIME 1875 /* 2.5ms */ 21762306a36Sopenharmony_ci#define TSADCV3_AUTO_PERIOD_HT_TIME 1875 /* 2.5ms */ 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci#define TSADCV5_AUTO_PERIOD_TIME 1622 /* 2.5ms */ 22062306a36Sopenharmony_ci#define TSADCV5_AUTO_PERIOD_HT_TIME 1622 /* 2.5ms */ 22162306a36Sopenharmony_ci#define TSADCV6_AUTO_PERIOD_TIME 5000 /* 2.5ms */ 22262306a36Sopenharmony_ci#define TSADCV6_AUTO_PERIOD_HT_TIME 5000 /* 2.5ms */ 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci#define TSADCV2_USER_INTER_PD_SOC 0x340 /* 13 clocks */ 22562306a36Sopenharmony_ci#define TSADCV5_USER_INTER_PD_SOC 0xfc0 /* 97us, at least 90us */ 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci#define GRF_SARADC_TESTBIT 0x0e644 22862306a36Sopenharmony_ci#define GRF_TSADC_TESTBIT_L 0x0e648 22962306a36Sopenharmony_ci#define GRF_TSADC_TESTBIT_H 0x0e64c 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci#define PX30_GRF_SOC_CON2 0x0408 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci#define RK3568_GRF_TSADC_CON 0x0600 23462306a36Sopenharmony_ci#define RK3568_GRF_TSADC_ANA_REG0 (0x10001 << 0) 23562306a36Sopenharmony_ci#define RK3568_GRF_TSADC_ANA_REG1 (0x10001 << 1) 23662306a36Sopenharmony_ci#define RK3568_GRF_TSADC_ANA_REG2 (0x10001 << 2) 23762306a36Sopenharmony_ci#define RK3568_GRF_TSADC_TSEN (0x10001 << 8) 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci#define RK3588_GRF0_TSADC_CON 0x0100 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci#define RK3588_GRF0_TSADC_TRM (0xff0077 << 0) 24262306a36Sopenharmony_ci#define RK3588_GRF0_TSADC_SHUT_2CRU (0x30003 << 10) 24362306a36Sopenharmony_ci#define RK3588_GRF0_TSADC_SHUT_2GPIO (0x70007 << 12) 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci#define GRF_SARADC_TESTBIT_ON (0x10001 << 2) 24662306a36Sopenharmony_ci#define GRF_TSADC_TESTBIT_H_ON (0x10001 << 2) 24762306a36Sopenharmony_ci#define GRF_TSADC_VCM_EN_L (0x10001 << 7) 24862306a36Sopenharmony_ci#define GRF_TSADC_VCM_EN_H (0x10001 << 7) 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci#define GRF_CON_TSADC_CH_INV (0x10001 << 1) 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci/** 25362306a36Sopenharmony_ci * struct tsadc_table - code to temperature conversion table 25462306a36Sopenharmony_ci * @code: the value of adc channel 25562306a36Sopenharmony_ci * @temp: the temperature 25662306a36Sopenharmony_ci * Note: 25762306a36Sopenharmony_ci * code to temperature mapping of the temperature sensor is a piece wise linear 25862306a36Sopenharmony_ci * curve.Any temperature, code faling between to 2 give temperatures can be 25962306a36Sopenharmony_ci * linearly interpolated. 26062306a36Sopenharmony_ci * Code to Temperature mapping should be updated based on manufacturer results. 26162306a36Sopenharmony_ci */ 26262306a36Sopenharmony_cistruct tsadc_table { 26362306a36Sopenharmony_ci u32 code; 26462306a36Sopenharmony_ci int temp; 26562306a36Sopenharmony_ci}; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cistatic const struct tsadc_table rv1108_table[] = { 26862306a36Sopenharmony_ci {0, -40000}, 26962306a36Sopenharmony_ci {374, -40000}, 27062306a36Sopenharmony_ci {382, -35000}, 27162306a36Sopenharmony_ci {389, -30000}, 27262306a36Sopenharmony_ci {397, -25000}, 27362306a36Sopenharmony_ci {405, -20000}, 27462306a36Sopenharmony_ci {413, -15000}, 27562306a36Sopenharmony_ci {421, -10000}, 27662306a36Sopenharmony_ci {429, -5000}, 27762306a36Sopenharmony_ci {436, 0}, 27862306a36Sopenharmony_ci {444, 5000}, 27962306a36Sopenharmony_ci {452, 10000}, 28062306a36Sopenharmony_ci {460, 15000}, 28162306a36Sopenharmony_ci {468, 20000}, 28262306a36Sopenharmony_ci {476, 25000}, 28362306a36Sopenharmony_ci {483, 30000}, 28462306a36Sopenharmony_ci {491, 35000}, 28562306a36Sopenharmony_ci {499, 40000}, 28662306a36Sopenharmony_ci {507, 45000}, 28762306a36Sopenharmony_ci {515, 50000}, 28862306a36Sopenharmony_ci {523, 55000}, 28962306a36Sopenharmony_ci {531, 60000}, 29062306a36Sopenharmony_ci {539, 65000}, 29162306a36Sopenharmony_ci {547, 70000}, 29262306a36Sopenharmony_ci {555, 75000}, 29362306a36Sopenharmony_ci {562, 80000}, 29462306a36Sopenharmony_ci {570, 85000}, 29562306a36Sopenharmony_ci {578, 90000}, 29662306a36Sopenharmony_ci {586, 95000}, 29762306a36Sopenharmony_ci {594, 100000}, 29862306a36Sopenharmony_ci {602, 105000}, 29962306a36Sopenharmony_ci {610, 110000}, 30062306a36Sopenharmony_ci {618, 115000}, 30162306a36Sopenharmony_ci {626, 120000}, 30262306a36Sopenharmony_ci {634, 125000}, 30362306a36Sopenharmony_ci {TSADCV2_DATA_MASK, 125000}, 30462306a36Sopenharmony_ci}; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_cistatic const struct tsadc_table rk3228_code_table[] = { 30762306a36Sopenharmony_ci {0, -40000}, 30862306a36Sopenharmony_ci {588, -40000}, 30962306a36Sopenharmony_ci {593, -35000}, 31062306a36Sopenharmony_ci {598, -30000}, 31162306a36Sopenharmony_ci {603, -25000}, 31262306a36Sopenharmony_ci {608, -20000}, 31362306a36Sopenharmony_ci {613, -15000}, 31462306a36Sopenharmony_ci {618, -10000}, 31562306a36Sopenharmony_ci {623, -5000}, 31662306a36Sopenharmony_ci {629, 0}, 31762306a36Sopenharmony_ci {634, 5000}, 31862306a36Sopenharmony_ci {639, 10000}, 31962306a36Sopenharmony_ci {644, 15000}, 32062306a36Sopenharmony_ci {649, 20000}, 32162306a36Sopenharmony_ci {654, 25000}, 32262306a36Sopenharmony_ci {660, 30000}, 32362306a36Sopenharmony_ci {665, 35000}, 32462306a36Sopenharmony_ci {670, 40000}, 32562306a36Sopenharmony_ci {675, 45000}, 32662306a36Sopenharmony_ci {681, 50000}, 32762306a36Sopenharmony_ci {686, 55000}, 32862306a36Sopenharmony_ci {691, 60000}, 32962306a36Sopenharmony_ci {696, 65000}, 33062306a36Sopenharmony_ci {702, 70000}, 33162306a36Sopenharmony_ci {707, 75000}, 33262306a36Sopenharmony_ci {712, 80000}, 33362306a36Sopenharmony_ci {717, 85000}, 33462306a36Sopenharmony_ci {723, 90000}, 33562306a36Sopenharmony_ci {728, 95000}, 33662306a36Sopenharmony_ci {733, 100000}, 33762306a36Sopenharmony_ci {738, 105000}, 33862306a36Sopenharmony_ci {744, 110000}, 33962306a36Sopenharmony_ci {749, 115000}, 34062306a36Sopenharmony_ci {754, 120000}, 34162306a36Sopenharmony_ci {760, 125000}, 34262306a36Sopenharmony_ci {TSADCV2_DATA_MASK, 125000}, 34362306a36Sopenharmony_ci}; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic const struct tsadc_table rk3288_code_table[] = { 34662306a36Sopenharmony_ci {TSADCV2_DATA_MASK, -40000}, 34762306a36Sopenharmony_ci {3800, -40000}, 34862306a36Sopenharmony_ci {3792, -35000}, 34962306a36Sopenharmony_ci {3783, -30000}, 35062306a36Sopenharmony_ci {3774, -25000}, 35162306a36Sopenharmony_ci {3765, -20000}, 35262306a36Sopenharmony_ci {3756, -15000}, 35362306a36Sopenharmony_ci {3747, -10000}, 35462306a36Sopenharmony_ci {3737, -5000}, 35562306a36Sopenharmony_ci {3728, 0}, 35662306a36Sopenharmony_ci {3718, 5000}, 35762306a36Sopenharmony_ci {3708, 10000}, 35862306a36Sopenharmony_ci {3698, 15000}, 35962306a36Sopenharmony_ci {3688, 20000}, 36062306a36Sopenharmony_ci {3678, 25000}, 36162306a36Sopenharmony_ci {3667, 30000}, 36262306a36Sopenharmony_ci {3656, 35000}, 36362306a36Sopenharmony_ci {3645, 40000}, 36462306a36Sopenharmony_ci {3634, 45000}, 36562306a36Sopenharmony_ci {3623, 50000}, 36662306a36Sopenharmony_ci {3611, 55000}, 36762306a36Sopenharmony_ci {3600, 60000}, 36862306a36Sopenharmony_ci {3588, 65000}, 36962306a36Sopenharmony_ci {3575, 70000}, 37062306a36Sopenharmony_ci {3563, 75000}, 37162306a36Sopenharmony_ci {3550, 80000}, 37262306a36Sopenharmony_ci {3537, 85000}, 37362306a36Sopenharmony_ci {3524, 90000}, 37462306a36Sopenharmony_ci {3510, 95000}, 37562306a36Sopenharmony_ci {3496, 100000}, 37662306a36Sopenharmony_ci {3482, 105000}, 37762306a36Sopenharmony_ci {3467, 110000}, 37862306a36Sopenharmony_ci {3452, 115000}, 37962306a36Sopenharmony_ci {3437, 120000}, 38062306a36Sopenharmony_ci {3421, 125000}, 38162306a36Sopenharmony_ci {0, 125000}, 38262306a36Sopenharmony_ci}; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_cistatic const struct tsadc_table rk3328_code_table[] = { 38562306a36Sopenharmony_ci {0, -40000}, 38662306a36Sopenharmony_ci {296, -40000}, 38762306a36Sopenharmony_ci {304, -35000}, 38862306a36Sopenharmony_ci {313, -30000}, 38962306a36Sopenharmony_ci {331, -20000}, 39062306a36Sopenharmony_ci {340, -15000}, 39162306a36Sopenharmony_ci {349, -10000}, 39262306a36Sopenharmony_ci {359, -5000}, 39362306a36Sopenharmony_ci {368, 0}, 39462306a36Sopenharmony_ci {378, 5000}, 39562306a36Sopenharmony_ci {388, 10000}, 39662306a36Sopenharmony_ci {398, 15000}, 39762306a36Sopenharmony_ci {408, 20000}, 39862306a36Sopenharmony_ci {418, 25000}, 39962306a36Sopenharmony_ci {429, 30000}, 40062306a36Sopenharmony_ci {440, 35000}, 40162306a36Sopenharmony_ci {451, 40000}, 40262306a36Sopenharmony_ci {462, 45000}, 40362306a36Sopenharmony_ci {473, 50000}, 40462306a36Sopenharmony_ci {485, 55000}, 40562306a36Sopenharmony_ci {496, 60000}, 40662306a36Sopenharmony_ci {508, 65000}, 40762306a36Sopenharmony_ci {521, 70000}, 40862306a36Sopenharmony_ci {533, 75000}, 40962306a36Sopenharmony_ci {546, 80000}, 41062306a36Sopenharmony_ci {559, 85000}, 41162306a36Sopenharmony_ci {572, 90000}, 41262306a36Sopenharmony_ci {586, 95000}, 41362306a36Sopenharmony_ci {600, 100000}, 41462306a36Sopenharmony_ci {614, 105000}, 41562306a36Sopenharmony_ci {629, 110000}, 41662306a36Sopenharmony_ci {644, 115000}, 41762306a36Sopenharmony_ci {659, 120000}, 41862306a36Sopenharmony_ci {675, 125000}, 41962306a36Sopenharmony_ci {TSADCV2_DATA_MASK, 125000}, 42062306a36Sopenharmony_ci}; 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_cistatic const struct tsadc_table rk3368_code_table[] = { 42362306a36Sopenharmony_ci {0, -40000}, 42462306a36Sopenharmony_ci {106, -40000}, 42562306a36Sopenharmony_ci {108, -35000}, 42662306a36Sopenharmony_ci {110, -30000}, 42762306a36Sopenharmony_ci {112, -25000}, 42862306a36Sopenharmony_ci {114, -20000}, 42962306a36Sopenharmony_ci {116, -15000}, 43062306a36Sopenharmony_ci {118, -10000}, 43162306a36Sopenharmony_ci {120, -5000}, 43262306a36Sopenharmony_ci {122, 0}, 43362306a36Sopenharmony_ci {124, 5000}, 43462306a36Sopenharmony_ci {126, 10000}, 43562306a36Sopenharmony_ci {128, 15000}, 43662306a36Sopenharmony_ci {130, 20000}, 43762306a36Sopenharmony_ci {132, 25000}, 43862306a36Sopenharmony_ci {134, 30000}, 43962306a36Sopenharmony_ci {136, 35000}, 44062306a36Sopenharmony_ci {138, 40000}, 44162306a36Sopenharmony_ci {140, 45000}, 44262306a36Sopenharmony_ci {142, 50000}, 44362306a36Sopenharmony_ci {144, 55000}, 44462306a36Sopenharmony_ci {146, 60000}, 44562306a36Sopenharmony_ci {148, 65000}, 44662306a36Sopenharmony_ci {150, 70000}, 44762306a36Sopenharmony_ci {152, 75000}, 44862306a36Sopenharmony_ci {154, 80000}, 44962306a36Sopenharmony_ci {156, 85000}, 45062306a36Sopenharmony_ci {158, 90000}, 45162306a36Sopenharmony_ci {160, 95000}, 45262306a36Sopenharmony_ci {162, 100000}, 45362306a36Sopenharmony_ci {163, 105000}, 45462306a36Sopenharmony_ci {165, 110000}, 45562306a36Sopenharmony_ci {167, 115000}, 45662306a36Sopenharmony_ci {169, 120000}, 45762306a36Sopenharmony_ci {171, 125000}, 45862306a36Sopenharmony_ci {TSADCV3_DATA_MASK, 125000}, 45962306a36Sopenharmony_ci}; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic const struct tsadc_table rk3399_code_table[] = { 46262306a36Sopenharmony_ci {0, -40000}, 46362306a36Sopenharmony_ci {402, -40000}, 46462306a36Sopenharmony_ci {410, -35000}, 46562306a36Sopenharmony_ci {419, -30000}, 46662306a36Sopenharmony_ci {427, -25000}, 46762306a36Sopenharmony_ci {436, -20000}, 46862306a36Sopenharmony_ci {444, -15000}, 46962306a36Sopenharmony_ci {453, -10000}, 47062306a36Sopenharmony_ci {461, -5000}, 47162306a36Sopenharmony_ci {470, 0}, 47262306a36Sopenharmony_ci {478, 5000}, 47362306a36Sopenharmony_ci {487, 10000}, 47462306a36Sopenharmony_ci {496, 15000}, 47562306a36Sopenharmony_ci {504, 20000}, 47662306a36Sopenharmony_ci {513, 25000}, 47762306a36Sopenharmony_ci {521, 30000}, 47862306a36Sopenharmony_ci {530, 35000}, 47962306a36Sopenharmony_ci {538, 40000}, 48062306a36Sopenharmony_ci {547, 45000}, 48162306a36Sopenharmony_ci {555, 50000}, 48262306a36Sopenharmony_ci {564, 55000}, 48362306a36Sopenharmony_ci {573, 60000}, 48462306a36Sopenharmony_ci {581, 65000}, 48562306a36Sopenharmony_ci {590, 70000}, 48662306a36Sopenharmony_ci {599, 75000}, 48762306a36Sopenharmony_ci {607, 80000}, 48862306a36Sopenharmony_ci {616, 85000}, 48962306a36Sopenharmony_ci {624, 90000}, 49062306a36Sopenharmony_ci {633, 95000}, 49162306a36Sopenharmony_ci {642, 100000}, 49262306a36Sopenharmony_ci {650, 105000}, 49362306a36Sopenharmony_ci {659, 110000}, 49462306a36Sopenharmony_ci {668, 115000}, 49562306a36Sopenharmony_ci {677, 120000}, 49662306a36Sopenharmony_ci {685, 125000}, 49762306a36Sopenharmony_ci {TSADCV3_DATA_MASK, 125000}, 49862306a36Sopenharmony_ci}; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_cistatic const struct tsadc_table rk3568_code_table[] = { 50162306a36Sopenharmony_ci {0, -40000}, 50262306a36Sopenharmony_ci {1584, -40000}, 50362306a36Sopenharmony_ci {1620, -35000}, 50462306a36Sopenharmony_ci {1652, -30000}, 50562306a36Sopenharmony_ci {1688, -25000}, 50662306a36Sopenharmony_ci {1720, -20000}, 50762306a36Sopenharmony_ci {1756, -15000}, 50862306a36Sopenharmony_ci {1788, -10000}, 50962306a36Sopenharmony_ci {1824, -5000}, 51062306a36Sopenharmony_ci {1856, 0}, 51162306a36Sopenharmony_ci {1892, 5000}, 51262306a36Sopenharmony_ci {1924, 10000}, 51362306a36Sopenharmony_ci {1956, 15000}, 51462306a36Sopenharmony_ci {1992, 20000}, 51562306a36Sopenharmony_ci {2024, 25000}, 51662306a36Sopenharmony_ci {2060, 30000}, 51762306a36Sopenharmony_ci {2092, 35000}, 51862306a36Sopenharmony_ci {2128, 40000}, 51962306a36Sopenharmony_ci {2160, 45000}, 52062306a36Sopenharmony_ci {2196, 50000}, 52162306a36Sopenharmony_ci {2228, 55000}, 52262306a36Sopenharmony_ci {2264, 60000}, 52362306a36Sopenharmony_ci {2300, 65000}, 52462306a36Sopenharmony_ci {2332, 70000}, 52562306a36Sopenharmony_ci {2368, 75000}, 52662306a36Sopenharmony_ci {2400, 80000}, 52762306a36Sopenharmony_ci {2436, 85000}, 52862306a36Sopenharmony_ci {2468, 90000}, 52962306a36Sopenharmony_ci {2500, 95000}, 53062306a36Sopenharmony_ci {2536, 100000}, 53162306a36Sopenharmony_ci {2572, 105000}, 53262306a36Sopenharmony_ci {2604, 110000}, 53362306a36Sopenharmony_ci {2636, 115000}, 53462306a36Sopenharmony_ci {2672, 120000}, 53562306a36Sopenharmony_ci {2704, 125000}, 53662306a36Sopenharmony_ci {TSADCV2_DATA_MASK, 125000}, 53762306a36Sopenharmony_ci}; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_cistatic const struct tsadc_table rk3588_code_table[] = { 54062306a36Sopenharmony_ci {0, -40000}, 54162306a36Sopenharmony_ci {215, -40000}, 54262306a36Sopenharmony_ci {285, 25000}, 54362306a36Sopenharmony_ci {350, 85000}, 54462306a36Sopenharmony_ci {395, 125000}, 54562306a36Sopenharmony_ci {TSADCV4_DATA_MASK, 125000}, 54662306a36Sopenharmony_ci}; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_cistatic u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table, 54962306a36Sopenharmony_ci int temp) 55062306a36Sopenharmony_ci{ 55162306a36Sopenharmony_ci int high, low, mid; 55262306a36Sopenharmony_ci unsigned long num; 55362306a36Sopenharmony_ci unsigned int denom; 55462306a36Sopenharmony_ci u32 error = table->data_mask; 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci low = 0; 55762306a36Sopenharmony_ci high = (table->length - 1) - 1; /* ignore the last check for table */ 55862306a36Sopenharmony_ci mid = (high + low) / 2; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci /* Return mask code data when the temp is over table range */ 56162306a36Sopenharmony_ci if (temp < table->id[low].temp || temp > table->id[high].temp) 56262306a36Sopenharmony_ci goto exit; 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci while (low <= high) { 56562306a36Sopenharmony_ci if (temp == table->id[mid].temp) 56662306a36Sopenharmony_ci return table->id[mid].code; 56762306a36Sopenharmony_ci else if (temp < table->id[mid].temp) 56862306a36Sopenharmony_ci high = mid - 1; 56962306a36Sopenharmony_ci else 57062306a36Sopenharmony_ci low = mid + 1; 57162306a36Sopenharmony_ci mid = (low + high) / 2; 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci /* 57562306a36Sopenharmony_ci * The conversion code granularity provided by the table. Let's 57662306a36Sopenharmony_ci * assume that the relationship between temperature and 57762306a36Sopenharmony_ci * analog value between 2 table entries is linear and interpolate 57862306a36Sopenharmony_ci * to produce less granular result. 57962306a36Sopenharmony_ci */ 58062306a36Sopenharmony_ci num = abs(table->id[mid + 1].code - table->id[mid].code); 58162306a36Sopenharmony_ci num *= temp - table->id[mid].temp; 58262306a36Sopenharmony_ci denom = table->id[mid + 1].temp - table->id[mid].temp; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci switch (table->mode) { 58562306a36Sopenharmony_ci case ADC_DECREMENT: 58662306a36Sopenharmony_ci return table->id[mid].code - (num / denom); 58762306a36Sopenharmony_ci case ADC_INCREMENT: 58862306a36Sopenharmony_ci return table->id[mid].code + (num / denom); 58962306a36Sopenharmony_ci default: 59062306a36Sopenharmony_ci pr_err("%s: unknown table mode: %d\n", __func__, table->mode); 59162306a36Sopenharmony_ci return error; 59262306a36Sopenharmony_ci } 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ciexit: 59562306a36Sopenharmony_ci pr_err("%s: invalid temperature, temp=%d error=%d\n", 59662306a36Sopenharmony_ci __func__, temp, error); 59762306a36Sopenharmony_ci return error; 59862306a36Sopenharmony_ci} 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic int rk_tsadcv2_code_to_temp(const struct chip_tsadc_table *table, 60162306a36Sopenharmony_ci u32 code, int *temp) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci unsigned int low = 1; 60462306a36Sopenharmony_ci unsigned int high = table->length - 1; 60562306a36Sopenharmony_ci unsigned int mid = (low + high) / 2; 60662306a36Sopenharmony_ci unsigned int num; 60762306a36Sopenharmony_ci unsigned long denom; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci WARN_ON(table->length < 2); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci switch (table->mode) { 61262306a36Sopenharmony_ci case ADC_DECREMENT: 61362306a36Sopenharmony_ci code &= table->data_mask; 61462306a36Sopenharmony_ci if (code <= table->id[high].code) 61562306a36Sopenharmony_ci return -EAGAIN; /* Incorrect reading */ 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci while (low <= high) { 61862306a36Sopenharmony_ci if (code >= table->id[mid].code && 61962306a36Sopenharmony_ci code < table->id[mid - 1].code) 62062306a36Sopenharmony_ci break; 62162306a36Sopenharmony_ci else if (code < table->id[mid].code) 62262306a36Sopenharmony_ci low = mid + 1; 62362306a36Sopenharmony_ci else 62462306a36Sopenharmony_ci high = mid - 1; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci mid = (low + high) / 2; 62762306a36Sopenharmony_ci } 62862306a36Sopenharmony_ci break; 62962306a36Sopenharmony_ci case ADC_INCREMENT: 63062306a36Sopenharmony_ci code &= table->data_mask; 63162306a36Sopenharmony_ci if (code < table->id[low].code) 63262306a36Sopenharmony_ci return -EAGAIN; /* Incorrect reading */ 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci while (low <= high) { 63562306a36Sopenharmony_ci if (code <= table->id[mid].code && 63662306a36Sopenharmony_ci code > table->id[mid - 1].code) 63762306a36Sopenharmony_ci break; 63862306a36Sopenharmony_ci else if (code > table->id[mid].code) 63962306a36Sopenharmony_ci low = mid + 1; 64062306a36Sopenharmony_ci else 64162306a36Sopenharmony_ci high = mid - 1; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci mid = (low + high) / 2; 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci break; 64662306a36Sopenharmony_ci default: 64762306a36Sopenharmony_ci pr_err("%s: unknown table mode: %d\n", __func__, table->mode); 64862306a36Sopenharmony_ci return -EINVAL; 64962306a36Sopenharmony_ci } 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci /* 65262306a36Sopenharmony_ci * The 5C granularity provided by the table is too much. Let's 65362306a36Sopenharmony_ci * assume that the relationship between sensor readings and 65462306a36Sopenharmony_ci * temperature between 2 table entries is linear and interpolate 65562306a36Sopenharmony_ci * to produce less granular result. 65662306a36Sopenharmony_ci */ 65762306a36Sopenharmony_ci num = table->id[mid].temp - table->id[mid - 1].temp; 65862306a36Sopenharmony_ci num *= abs(table->id[mid - 1].code - code); 65962306a36Sopenharmony_ci denom = abs(table->id[mid - 1].code - table->id[mid].code); 66062306a36Sopenharmony_ci *temp = table->id[mid - 1].temp + (num / denom); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci return 0; 66362306a36Sopenharmony_ci} 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci/** 66662306a36Sopenharmony_ci * rk_tsadcv2_initialize - initialize TASDC Controller. 66762306a36Sopenharmony_ci * @grf: the general register file will be used to do static set by software 66862306a36Sopenharmony_ci * @regs: the base address of tsadc controller 66962306a36Sopenharmony_ci * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH) 67062306a36Sopenharmony_ci * 67162306a36Sopenharmony_ci * (1) Set TSADC_V2_AUTO_PERIOD: 67262306a36Sopenharmony_ci * Configure the interleave between every two accessing of 67362306a36Sopenharmony_ci * TSADC in normal operation. 67462306a36Sopenharmony_ci * 67562306a36Sopenharmony_ci * (2) Set TSADCV2_AUTO_PERIOD_HT: 67662306a36Sopenharmony_ci * Configure the interleave between every two accessing of 67762306a36Sopenharmony_ci * TSADC after the temperature is higher than COM_SHUT or COM_INT. 67862306a36Sopenharmony_ci * 67962306a36Sopenharmony_ci * (3) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE: 68062306a36Sopenharmony_ci * If the temperature is higher than COMP_INT or COMP_SHUT for 68162306a36Sopenharmony_ci * "debounce" times, TSADC controller will generate interrupt or TSHUT. 68262306a36Sopenharmony_ci */ 68362306a36Sopenharmony_cistatic void rk_tsadcv2_initialize(struct regmap *grf, void __iomem *regs, 68462306a36Sopenharmony_ci enum tshut_polarity tshut_polarity) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci if (tshut_polarity == TSHUT_HIGH_ACTIVE) 68762306a36Sopenharmony_ci writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH, 68862306a36Sopenharmony_ci regs + TSADCV2_AUTO_CON); 68962306a36Sopenharmony_ci else 69062306a36Sopenharmony_ci writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH, 69162306a36Sopenharmony_ci regs + TSADCV2_AUTO_CON); 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD); 69462306a36Sopenharmony_ci writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT, 69562306a36Sopenharmony_ci regs + TSADCV2_HIGHT_INT_DEBOUNCE); 69662306a36Sopenharmony_ci writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME, 69762306a36Sopenharmony_ci regs + TSADCV2_AUTO_PERIOD_HT); 69862306a36Sopenharmony_ci writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, 69962306a36Sopenharmony_ci regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE); 70062306a36Sopenharmony_ci} 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci/** 70362306a36Sopenharmony_ci * rk_tsadcv3_initialize - initialize TASDC Controller. 70462306a36Sopenharmony_ci * @grf: the general register file will be used to do static set by software 70562306a36Sopenharmony_ci * @regs: the base address of tsadc controller 70662306a36Sopenharmony_ci * @tshut_polarity: the hardware-controlled active polarity (0:LOW 1:HIGH) 70762306a36Sopenharmony_ci * 70862306a36Sopenharmony_ci * (1) The tsadc control power sequence. 70962306a36Sopenharmony_ci * 71062306a36Sopenharmony_ci * (2) Set TSADC_V2_AUTO_PERIOD: 71162306a36Sopenharmony_ci * Configure the interleave between every two accessing of 71262306a36Sopenharmony_ci * TSADC in normal operation. 71362306a36Sopenharmony_ci * 71462306a36Sopenharmony_ci * (2) Set TSADCV2_AUTO_PERIOD_HT: 71562306a36Sopenharmony_ci * Configure the interleave between every two accessing of 71662306a36Sopenharmony_ci * TSADC after the temperature is higher than COM_SHUT or COM_INT. 71762306a36Sopenharmony_ci * 71862306a36Sopenharmony_ci * (3) Set TSADCV2_HIGH_INT_DEBOUNCE and TSADC_HIGHT_TSHUT_DEBOUNCE: 71962306a36Sopenharmony_ci * If the temperature is higher than COMP_INT or COMP_SHUT for 72062306a36Sopenharmony_ci * "debounce" times, TSADC controller will generate interrupt or TSHUT. 72162306a36Sopenharmony_ci */ 72262306a36Sopenharmony_cistatic void rk_tsadcv3_initialize(struct regmap *grf, void __iomem *regs, 72362306a36Sopenharmony_ci enum tshut_polarity tshut_polarity) 72462306a36Sopenharmony_ci{ 72562306a36Sopenharmony_ci /* The tsadc control power sequence */ 72662306a36Sopenharmony_ci if (IS_ERR(grf)) { 72762306a36Sopenharmony_ci /* Set interleave value to workround ic time sync issue */ 72862306a36Sopenharmony_ci writel_relaxed(TSADCV2_USER_INTER_PD_SOC, regs + 72962306a36Sopenharmony_ci TSADCV2_USER_CON); 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci writel_relaxed(TSADCV2_AUTO_PERIOD_TIME, 73262306a36Sopenharmony_ci regs + TSADCV2_AUTO_PERIOD); 73362306a36Sopenharmony_ci writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT, 73462306a36Sopenharmony_ci regs + TSADCV2_HIGHT_INT_DEBOUNCE); 73562306a36Sopenharmony_ci writel_relaxed(TSADCV2_AUTO_PERIOD_HT_TIME, 73662306a36Sopenharmony_ci regs + TSADCV2_AUTO_PERIOD_HT); 73762306a36Sopenharmony_ci writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, 73862306a36Sopenharmony_ci regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE); 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci } else { 74162306a36Sopenharmony_ci /* Enable the voltage common mode feature */ 74262306a36Sopenharmony_ci regmap_write(grf, GRF_TSADC_TESTBIT_L, GRF_TSADC_VCM_EN_L); 74362306a36Sopenharmony_ci regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_VCM_EN_H); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci usleep_range(15, 100); /* The spec note says at least 15 us */ 74662306a36Sopenharmony_ci regmap_write(grf, GRF_SARADC_TESTBIT, GRF_SARADC_TESTBIT_ON); 74762306a36Sopenharmony_ci regmap_write(grf, GRF_TSADC_TESTBIT_H, GRF_TSADC_TESTBIT_H_ON); 74862306a36Sopenharmony_ci usleep_range(90, 200); /* The spec note says at least 90 us */ 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci writel_relaxed(TSADCV3_AUTO_PERIOD_TIME, 75162306a36Sopenharmony_ci regs + TSADCV2_AUTO_PERIOD); 75262306a36Sopenharmony_ci writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT, 75362306a36Sopenharmony_ci regs + TSADCV2_HIGHT_INT_DEBOUNCE); 75462306a36Sopenharmony_ci writel_relaxed(TSADCV3_AUTO_PERIOD_HT_TIME, 75562306a36Sopenharmony_ci regs + TSADCV2_AUTO_PERIOD_HT); 75662306a36Sopenharmony_ci writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, 75762306a36Sopenharmony_ci regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE); 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci if (tshut_polarity == TSHUT_HIGH_ACTIVE) 76162306a36Sopenharmony_ci writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH, 76262306a36Sopenharmony_ci regs + TSADCV2_AUTO_CON); 76362306a36Sopenharmony_ci else 76462306a36Sopenharmony_ci writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH, 76562306a36Sopenharmony_ci regs + TSADCV2_AUTO_CON); 76662306a36Sopenharmony_ci} 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_cistatic void rk_tsadcv4_initialize(struct regmap *grf, void __iomem *regs, 76962306a36Sopenharmony_ci enum tshut_polarity tshut_polarity) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci rk_tsadcv2_initialize(grf, regs, tshut_polarity); 77262306a36Sopenharmony_ci regmap_write(grf, PX30_GRF_SOC_CON2, GRF_CON_TSADC_CH_INV); 77362306a36Sopenharmony_ci} 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_cistatic void rk_tsadcv7_initialize(struct regmap *grf, void __iomem *regs, 77662306a36Sopenharmony_ci enum tshut_polarity tshut_polarity) 77762306a36Sopenharmony_ci{ 77862306a36Sopenharmony_ci writel_relaxed(TSADCV5_USER_INTER_PD_SOC, regs + TSADCV2_USER_CON); 77962306a36Sopenharmony_ci writel_relaxed(TSADCV5_AUTO_PERIOD_TIME, regs + TSADCV2_AUTO_PERIOD); 78062306a36Sopenharmony_ci writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT, 78162306a36Sopenharmony_ci regs + TSADCV2_HIGHT_INT_DEBOUNCE); 78262306a36Sopenharmony_ci writel_relaxed(TSADCV5_AUTO_PERIOD_HT_TIME, 78362306a36Sopenharmony_ci regs + TSADCV2_AUTO_PERIOD_HT); 78462306a36Sopenharmony_ci writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, 78562306a36Sopenharmony_ci regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE); 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci if (tshut_polarity == TSHUT_HIGH_ACTIVE) 78862306a36Sopenharmony_ci writel_relaxed(0U | TSADCV2_AUTO_TSHUT_POLARITY_HIGH, 78962306a36Sopenharmony_ci regs + TSADCV2_AUTO_CON); 79062306a36Sopenharmony_ci else 79162306a36Sopenharmony_ci writel_relaxed(0U & ~TSADCV2_AUTO_TSHUT_POLARITY_HIGH, 79262306a36Sopenharmony_ci regs + TSADCV2_AUTO_CON); 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_ci /* 79562306a36Sopenharmony_ci * The general register file will is optional 79662306a36Sopenharmony_ci * and might not be available. 79762306a36Sopenharmony_ci */ 79862306a36Sopenharmony_ci if (!IS_ERR(grf)) { 79962306a36Sopenharmony_ci regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_TSEN); 80062306a36Sopenharmony_ci /* 80162306a36Sopenharmony_ci * RK3568 TRM, section 18.5. requires a delay no less 80262306a36Sopenharmony_ci * than 10us between the rising edge of tsadc_tsen_en 80362306a36Sopenharmony_ci * and the rising edge of tsadc_ana_reg_0/1/2. 80462306a36Sopenharmony_ci */ 80562306a36Sopenharmony_ci udelay(15); 80662306a36Sopenharmony_ci regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG0); 80762306a36Sopenharmony_ci regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG1); 80862306a36Sopenharmony_ci regmap_write(grf, RK3568_GRF_TSADC_CON, RK3568_GRF_TSADC_ANA_REG2); 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci /* 81162306a36Sopenharmony_ci * RK3568 TRM, section 18.5. requires a delay no less 81262306a36Sopenharmony_ci * than 90us after the rising edge of tsadc_ana_reg_0/1/2. 81362306a36Sopenharmony_ci */ 81462306a36Sopenharmony_ci usleep_range(100, 200); 81562306a36Sopenharmony_ci } 81662306a36Sopenharmony_ci} 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_cistatic void rk_tsadcv8_initialize(struct regmap *grf, void __iomem *regs, 81962306a36Sopenharmony_ci enum tshut_polarity tshut_polarity) 82062306a36Sopenharmony_ci{ 82162306a36Sopenharmony_ci writel_relaxed(TSADCV6_AUTO_PERIOD_TIME, regs + TSADCV3_AUTO_PERIOD); 82262306a36Sopenharmony_ci writel_relaxed(TSADCV6_AUTO_PERIOD_HT_TIME, 82362306a36Sopenharmony_ci regs + TSADCV3_AUTO_PERIOD_HT); 82462306a36Sopenharmony_ci writel_relaxed(TSADCV2_HIGHT_INT_DEBOUNCE_COUNT, 82562306a36Sopenharmony_ci regs + TSADCV3_HIGHT_INT_DEBOUNCE); 82662306a36Sopenharmony_ci writel_relaxed(TSADCV2_HIGHT_TSHUT_DEBOUNCE_COUNT, 82762306a36Sopenharmony_ci regs + TSADCV3_HIGHT_TSHUT_DEBOUNCE); 82862306a36Sopenharmony_ci if (tshut_polarity == TSHUT_HIGH_ACTIVE) 82962306a36Sopenharmony_ci writel_relaxed(TSADCV2_AUTO_TSHUT_POLARITY_HIGH | 83062306a36Sopenharmony_ci TSADCV2_AUTO_TSHUT_POLARITY_MASK, 83162306a36Sopenharmony_ci regs + TSADCV2_AUTO_CON); 83262306a36Sopenharmony_ci else 83362306a36Sopenharmony_ci writel_relaxed(TSADCV2_AUTO_TSHUT_POLARITY_MASK, 83462306a36Sopenharmony_ci regs + TSADCV2_AUTO_CON); 83562306a36Sopenharmony_ci} 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_cistatic void rk_tsadcv2_irq_ack(void __iomem *regs) 83862306a36Sopenharmony_ci{ 83962306a36Sopenharmony_ci u32 val; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci val = readl_relaxed(regs + TSADCV2_INT_PD); 84262306a36Sopenharmony_ci writel_relaxed(val & TSADCV2_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD); 84362306a36Sopenharmony_ci} 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_cistatic void rk_tsadcv3_irq_ack(void __iomem *regs) 84662306a36Sopenharmony_ci{ 84762306a36Sopenharmony_ci u32 val; 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci val = readl_relaxed(regs + TSADCV2_INT_PD); 85062306a36Sopenharmony_ci writel_relaxed(val & TSADCV3_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD); 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_cistatic void rk_tsadcv4_irq_ack(void __iomem *regs) 85462306a36Sopenharmony_ci{ 85562306a36Sopenharmony_ci u32 val; 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci val = readl_relaxed(regs + TSADCV3_INT_PD); 85862306a36Sopenharmony_ci writel_relaxed(val & TSADCV4_INT_PD_CLEAR_MASK, regs + TSADCV3_INT_PD); 85962306a36Sopenharmony_ci val = readl_relaxed(regs + TSADCV3_HSHUT_PD); 86062306a36Sopenharmony_ci writel_relaxed(val & TSADCV3_INT_PD_CLEAR_MASK, 86162306a36Sopenharmony_ci regs + TSADCV3_HSHUT_PD); 86262306a36Sopenharmony_ci} 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_cistatic void rk_tsadcv2_control(void __iomem *regs, bool enable) 86562306a36Sopenharmony_ci{ 86662306a36Sopenharmony_ci u32 val; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci val = readl_relaxed(regs + TSADCV2_AUTO_CON); 86962306a36Sopenharmony_ci if (enable) 87062306a36Sopenharmony_ci val |= TSADCV2_AUTO_EN; 87162306a36Sopenharmony_ci else 87262306a36Sopenharmony_ci val &= ~TSADCV2_AUTO_EN; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci writel_relaxed(val, regs + TSADCV2_AUTO_CON); 87562306a36Sopenharmony_ci} 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci/** 87862306a36Sopenharmony_ci * rk_tsadcv3_control - the tsadc controller is enabled or disabled. 87962306a36Sopenharmony_ci * @regs: the base address of tsadc controller 88062306a36Sopenharmony_ci * @enable: boolean flag to enable the controller 88162306a36Sopenharmony_ci * 88262306a36Sopenharmony_ci * NOTE: TSADC controller works at auto mode, and some SoCs need set the 88362306a36Sopenharmony_ci * tsadc_q_sel bit on TSADCV2_AUTO_CON[1]. The (1024 - tsadc_q) as output 88462306a36Sopenharmony_ci * adc value if setting this bit to enable. 88562306a36Sopenharmony_ci */ 88662306a36Sopenharmony_cistatic void rk_tsadcv3_control(void __iomem *regs, bool enable) 88762306a36Sopenharmony_ci{ 88862306a36Sopenharmony_ci u32 val; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci val = readl_relaxed(regs + TSADCV2_AUTO_CON); 89162306a36Sopenharmony_ci if (enable) 89262306a36Sopenharmony_ci val |= TSADCV2_AUTO_EN | TSADCV3_AUTO_Q_SEL_EN; 89362306a36Sopenharmony_ci else 89462306a36Sopenharmony_ci val &= ~TSADCV2_AUTO_EN; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci writel_relaxed(val, regs + TSADCV2_AUTO_CON); 89762306a36Sopenharmony_ci} 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_cistatic void rk_tsadcv4_control(void __iomem *regs, bool enable) 90062306a36Sopenharmony_ci{ 90162306a36Sopenharmony_ci u32 val; 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci if (enable) 90462306a36Sopenharmony_ci val = TSADCV2_AUTO_EN | TSADCV2_AUTO_EN_MASK; 90562306a36Sopenharmony_ci else 90662306a36Sopenharmony_ci val = TSADCV2_AUTO_EN_MASK; 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci writel_relaxed(val, regs + TSADCV2_AUTO_CON); 90962306a36Sopenharmony_ci} 91062306a36Sopenharmony_ci 91162306a36Sopenharmony_cistatic int rk_tsadcv2_get_temp(const struct chip_tsadc_table *table, 91262306a36Sopenharmony_ci int chn, void __iomem *regs, int *temp) 91362306a36Sopenharmony_ci{ 91462306a36Sopenharmony_ci u32 val; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci val = readl_relaxed(regs + TSADCV2_DATA(chn)); 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci return rk_tsadcv2_code_to_temp(table, val, temp); 91962306a36Sopenharmony_ci} 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_cistatic int rk_tsadcv4_get_temp(const struct chip_tsadc_table *table, 92262306a36Sopenharmony_ci int chn, void __iomem *regs, int *temp) 92362306a36Sopenharmony_ci{ 92462306a36Sopenharmony_ci u32 val; 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci val = readl_relaxed(regs + TSADCV3_DATA(chn)); 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci return rk_tsadcv2_code_to_temp(table, val, temp); 92962306a36Sopenharmony_ci} 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_cistatic int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table, 93262306a36Sopenharmony_ci int chn, void __iomem *regs, int temp) 93362306a36Sopenharmony_ci{ 93462306a36Sopenharmony_ci u32 alarm_value; 93562306a36Sopenharmony_ci u32 int_en, int_clr; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci /* 93862306a36Sopenharmony_ci * In some cases, some sensors didn't need the trip points, the 93962306a36Sopenharmony_ci * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm 94062306a36Sopenharmony_ci * in the end, ignore this case and disable the high temperature 94162306a36Sopenharmony_ci * interrupt. 94262306a36Sopenharmony_ci */ 94362306a36Sopenharmony_ci if (temp == INT_MAX) { 94462306a36Sopenharmony_ci int_clr = readl_relaxed(regs + TSADCV2_INT_EN); 94562306a36Sopenharmony_ci int_clr &= ~TSADCV2_INT_SRC_EN(chn); 94662306a36Sopenharmony_ci writel_relaxed(int_clr, regs + TSADCV2_INT_EN); 94762306a36Sopenharmony_ci return 0; 94862306a36Sopenharmony_ci } 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci /* Make sure the value is valid */ 95162306a36Sopenharmony_ci alarm_value = rk_tsadcv2_temp_to_code(table, temp); 95262306a36Sopenharmony_ci if (alarm_value == table->data_mask) 95362306a36Sopenharmony_ci return -ERANGE; 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci writel_relaxed(alarm_value & table->data_mask, 95662306a36Sopenharmony_ci regs + TSADCV2_COMP_INT(chn)); 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci int_en = readl_relaxed(regs + TSADCV2_INT_EN); 95962306a36Sopenharmony_ci int_en |= TSADCV2_INT_SRC_EN(chn); 96062306a36Sopenharmony_ci writel_relaxed(int_en, regs + TSADCV2_INT_EN); 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci return 0; 96362306a36Sopenharmony_ci} 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_cistatic int rk_tsadcv3_alarm_temp(const struct chip_tsadc_table *table, 96662306a36Sopenharmony_ci int chn, void __iomem *regs, int temp) 96762306a36Sopenharmony_ci{ 96862306a36Sopenharmony_ci u32 alarm_value; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci /* 97162306a36Sopenharmony_ci * In some cases, some sensors didn't need the trip points, the 97262306a36Sopenharmony_ci * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm 97362306a36Sopenharmony_ci * in the end, ignore this case and disable the high temperature 97462306a36Sopenharmony_ci * interrupt. 97562306a36Sopenharmony_ci */ 97662306a36Sopenharmony_ci if (temp == INT_MAX) { 97762306a36Sopenharmony_ci writel_relaxed(TSADCV2_INT_SRC_EN_MASK(chn), 97862306a36Sopenharmony_ci regs + TSADCV3_HT_INT_EN); 97962306a36Sopenharmony_ci return 0; 98062306a36Sopenharmony_ci } 98162306a36Sopenharmony_ci /* Make sure the value is valid */ 98262306a36Sopenharmony_ci alarm_value = rk_tsadcv2_temp_to_code(table, temp); 98362306a36Sopenharmony_ci if (alarm_value == table->data_mask) 98462306a36Sopenharmony_ci return -ERANGE; 98562306a36Sopenharmony_ci writel_relaxed(alarm_value & table->data_mask, 98662306a36Sopenharmony_ci regs + TSADCV3_COMP_INT(chn)); 98762306a36Sopenharmony_ci writel_relaxed(TSADCV2_INT_SRC_EN(chn) | TSADCV2_INT_SRC_EN_MASK(chn), 98862306a36Sopenharmony_ci regs + TSADCV3_HT_INT_EN); 98962306a36Sopenharmony_ci return 0; 99062306a36Sopenharmony_ci} 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_cistatic int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table, 99362306a36Sopenharmony_ci int chn, void __iomem *regs, int temp) 99462306a36Sopenharmony_ci{ 99562306a36Sopenharmony_ci u32 tshut_value, val; 99662306a36Sopenharmony_ci 99762306a36Sopenharmony_ci /* Make sure the value is valid */ 99862306a36Sopenharmony_ci tshut_value = rk_tsadcv2_temp_to_code(table, temp); 99962306a36Sopenharmony_ci if (tshut_value == table->data_mask) 100062306a36Sopenharmony_ci return -ERANGE; 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn)); 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci /* TSHUT will be valid */ 100562306a36Sopenharmony_ci val = readl_relaxed(regs + TSADCV2_AUTO_CON); 100662306a36Sopenharmony_ci writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON); 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci return 0; 100962306a36Sopenharmony_ci} 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_cistatic int rk_tsadcv3_tshut_temp(const struct chip_tsadc_table *table, 101262306a36Sopenharmony_ci int chn, void __iomem *regs, int temp) 101362306a36Sopenharmony_ci{ 101462306a36Sopenharmony_ci u32 tshut_value; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci /* Make sure the value is valid */ 101762306a36Sopenharmony_ci tshut_value = rk_tsadcv2_temp_to_code(table, temp); 101862306a36Sopenharmony_ci if (tshut_value == table->data_mask) 101962306a36Sopenharmony_ci return -ERANGE; 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci writel_relaxed(tshut_value, regs + TSADCV3_COMP_SHUT(chn)); 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci /* TSHUT will be valid */ 102462306a36Sopenharmony_ci writel_relaxed(TSADCV3_AUTO_SRC_EN(chn) | TSADCV3_AUTO_SRC_EN_MASK(chn), 102562306a36Sopenharmony_ci regs + TSADCV3_AUTO_SRC_CON); 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci return 0; 102862306a36Sopenharmony_ci} 102962306a36Sopenharmony_ci 103062306a36Sopenharmony_cistatic void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, 103162306a36Sopenharmony_ci enum tshut_mode mode) 103262306a36Sopenharmony_ci{ 103362306a36Sopenharmony_ci u32 val; 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci val = readl_relaxed(regs + TSADCV2_INT_EN); 103662306a36Sopenharmony_ci if (mode == TSHUT_MODE_GPIO) { 103762306a36Sopenharmony_ci val &= ~TSADCV2_SHUT_2CRU_SRC_EN(chn); 103862306a36Sopenharmony_ci val |= TSADCV2_SHUT_2GPIO_SRC_EN(chn); 103962306a36Sopenharmony_ci } else { 104062306a36Sopenharmony_ci val &= ~TSADCV2_SHUT_2GPIO_SRC_EN(chn); 104162306a36Sopenharmony_ci val |= TSADCV2_SHUT_2CRU_SRC_EN(chn); 104262306a36Sopenharmony_ci } 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci writel_relaxed(val, regs + TSADCV2_INT_EN); 104562306a36Sopenharmony_ci} 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_cistatic void rk_tsadcv3_tshut_mode(int chn, void __iomem *regs, 104862306a36Sopenharmony_ci enum tshut_mode mode) 104962306a36Sopenharmony_ci{ 105062306a36Sopenharmony_ci u32 val_gpio, val_cru; 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci if (mode == TSHUT_MODE_GPIO) { 105362306a36Sopenharmony_ci val_gpio = TSADCV2_INT_SRC_EN(chn) | TSADCV2_INT_SRC_EN_MASK(chn); 105462306a36Sopenharmony_ci val_cru = TSADCV2_INT_SRC_EN_MASK(chn); 105562306a36Sopenharmony_ci } else { 105662306a36Sopenharmony_ci val_cru = TSADCV2_INT_SRC_EN(chn) | TSADCV2_INT_SRC_EN_MASK(chn); 105762306a36Sopenharmony_ci val_gpio = TSADCV2_INT_SRC_EN_MASK(chn); 105862306a36Sopenharmony_ci } 105962306a36Sopenharmony_ci writel_relaxed(val_gpio, regs + TSADCV3_HSHUT_GPIO_INT_EN); 106062306a36Sopenharmony_ci writel_relaxed(val_cru, regs + TSADCV3_HSHUT_CRU_INT_EN); 106162306a36Sopenharmony_ci} 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_cistatic const struct rockchip_tsadc_chip px30_tsadc_data = { 106462306a36Sopenharmony_ci /* cpu, gpu */ 106562306a36Sopenharmony_ci .chn_offset = 0, 106662306a36Sopenharmony_ci .chn_num = 2, /* 2 channels for tsadc */ 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */ 106962306a36Sopenharmony_ci .tshut_temp = 95000, 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci .initialize = rk_tsadcv4_initialize, 107262306a36Sopenharmony_ci .irq_ack = rk_tsadcv3_irq_ack, 107362306a36Sopenharmony_ci .control = rk_tsadcv3_control, 107462306a36Sopenharmony_ci .get_temp = rk_tsadcv2_get_temp, 107562306a36Sopenharmony_ci .set_alarm_temp = rk_tsadcv2_alarm_temp, 107662306a36Sopenharmony_ci .set_tshut_temp = rk_tsadcv2_tshut_temp, 107762306a36Sopenharmony_ci .set_tshut_mode = rk_tsadcv2_tshut_mode, 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci .table = { 108062306a36Sopenharmony_ci .id = rk3328_code_table, 108162306a36Sopenharmony_ci .length = ARRAY_SIZE(rk3328_code_table), 108262306a36Sopenharmony_ci .data_mask = TSADCV2_DATA_MASK, 108362306a36Sopenharmony_ci .mode = ADC_INCREMENT, 108462306a36Sopenharmony_ci }, 108562306a36Sopenharmony_ci}; 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_cistatic const struct rockchip_tsadc_chip rv1108_tsadc_data = { 108862306a36Sopenharmony_ci /* cpu */ 108962306a36Sopenharmony_ci .chn_offset = 0, 109062306a36Sopenharmony_ci .chn_num = 1, /* one channel for tsadc */ 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ 109362306a36Sopenharmony_ci .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ 109462306a36Sopenharmony_ci .tshut_temp = 95000, 109562306a36Sopenharmony_ci 109662306a36Sopenharmony_ci .initialize = rk_tsadcv2_initialize, 109762306a36Sopenharmony_ci .irq_ack = rk_tsadcv3_irq_ack, 109862306a36Sopenharmony_ci .control = rk_tsadcv3_control, 109962306a36Sopenharmony_ci .get_temp = rk_tsadcv2_get_temp, 110062306a36Sopenharmony_ci .set_alarm_temp = rk_tsadcv2_alarm_temp, 110162306a36Sopenharmony_ci .set_tshut_temp = rk_tsadcv2_tshut_temp, 110262306a36Sopenharmony_ci .set_tshut_mode = rk_tsadcv2_tshut_mode, 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci .table = { 110562306a36Sopenharmony_ci .id = rv1108_table, 110662306a36Sopenharmony_ci .length = ARRAY_SIZE(rv1108_table), 110762306a36Sopenharmony_ci .data_mask = TSADCV2_DATA_MASK, 110862306a36Sopenharmony_ci .mode = ADC_INCREMENT, 110962306a36Sopenharmony_ci }, 111062306a36Sopenharmony_ci}; 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_cistatic const struct rockchip_tsadc_chip rk3228_tsadc_data = { 111362306a36Sopenharmony_ci /* cpu */ 111462306a36Sopenharmony_ci .chn_offset = 0, 111562306a36Sopenharmony_ci .chn_num = 1, /* one channel for tsadc */ 111662306a36Sopenharmony_ci 111762306a36Sopenharmony_ci .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ 111862306a36Sopenharmony_ci .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ 111962306a36Sopenharmony_ci .tshut_temp = 95000, 112062306a36Sopenharmony_ci 112162306a36Sopenharmony_ci .initialize = rk_tsadcv2_initialize, 112262306a36Sopenharmony_ci .irq_ack = rk_tsadcv3_irq_ack, 112362306a36Sopenharmony_ci .control = rk_tsadcv3_control, 112462306a36Sopenharmony_ci .get_temp = rk_tsadcv2_get_temp, 112562306a36Sopenharmony_ci .set_alarm_temp = rk_tsadcv2_alarm_temp, 112662306a36Sopenharmony_ci .set_tshut_temp = rk_tsadcv2_tshut_temp, 112762306a36Sopenharmony_ci .set_tshut_mode = rk_tsadcv2_tshut_mode, 112862306a36Sopenharmony_ci 112962306a36Sopenharmony_ci .table = { 113062306a36Sopenharmony_ci .id = rk3228_code_table, 113162306a36Sopenharmony_ci .length = ARRAY_SIZE(rk3228_code_table), 113262306a36Sopenharmony_ci .data_mask = TSADCV3_DATA_MASK, 113362306a36Sopenharmony_ci .mode = ADC_INCREMENT, 113462306a36Sopenharmony_ci }, 113562306a36Sopenharmony_ci}; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_cistatic const struct rockchip_tsadc_chip rk3288_tsadc_data = { 113862306a36Sopenharmony_ci /* cpu, gpu */ 113962306a36Sopenharmony_ci .chn_offset = 1, 114062306a36Sopenharmony_ci .chn_num = 2, /* two channels for tsadc */ 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ 114362306a36Sopenharmony_ci .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ 114462306a36Sopenharmony_ci .tshut_temp = 95000, 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci .initialize = rk_tsadcv2_initialize, 114762306a36Sopenharmony_ci .irq_ack = rk_tsadcv2_irq_ack, 114862306a36Sopenharmony_ci .control = rk_tsadcv2_control, 114962306a36Sopenharmony_ci .get_temp = rk_tsadcv2_get_temp, 115062306a36Sopenharmony_ci .set_alarm_temp = rk_tsadcv2_alarm_temp, 115162306a36Sopenharmony_ci .set_tshut_temp = rk_tsadcv2_tshut_temp, 115262306a36Sopenharmony_ci .set_tshut_mode = rk_tsadcv2_tshut_mode, 115362306a36Sopenharmony_ci 115462306a36Sopenharmony_ci .table = { 115562306a36Sopenharmony_ci .id = rk3288_code_table, 115662306a36Sopenharmony_ci .length = ARRAY_SIZE(rk3288_code_table), 115762306a36Sopenharmony_ci .data_mask = TSADCV2_DATA_MASK, 115862306a36Sopenharmony_ci .mode = ADC_DECREMENT, 115962306a36Sopenharmony_ci }, 116062306a36Sopenharmony_ci}; 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_cistatic const struct rockchip_tsadc_chip rk3328_tsadc_data = { 116362306a36Sopenharmony_ci /* cpu */ 116462306a36Sopenharmony_ci .chn_offset = 0, 116562306a36Sopenharmony_ci .chn_num = 1, /* one channels for tsadc */ 116662306a36Sopenharmony_ci 116762306a36Sopenharmony_ci .tshut_mode = TSHUT_MODE_CRU, /* default TSHUT via CRU */ 116862306a36Sopenharmony_ci .tshut_temp = 95000, 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci .initialize = rk_tsadcv2_initialize, 117162306a36Sopenharmony_ci .irq_ack = rk_tsadcv3_irq_ack, 117262306a36Sopenharmony_ci .control = rk_tsadcv3_control, 117362306a36Sopenharmony_ci .get_temp = rk_tsadcv2_get_temp, 117462306a36Sopenharmony_ci .set_alarm_temp = rk_tsadcv2_alarm_temp, 117562306a36Sopenharmony_ci .set_tshut_temp = rk_tsadcv2_tshut_temp, 117662306a36Sopenharmony_ci .set_tshut_mode = rk_tsadcv2_tshut_mode, 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci .table = { 117962306a36Sopenharmony_ci .id = rk3328_code_table, 118062306a36Sopenharmony_ci .length = ARRAY_SIZE(rk3328_code_table), 118162306a36Sopenharmony_ci .data_mask = TSADCV2_DATA_MASK, 118262306a36Sopenharmony_ci .mode = ADC_INCREMENT, 118362306a36Sopenharmony_ci }, 118462306a36Sopenharmony_ci}; 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_cistatic const struct rockchip_tsadc_chip rk3366_tsadc_data = { 118762306a36Sopenharmony_ci /* cpu, gpu */ 118862306a36Sopenharmony_ci .chn_offset = 0, 118962306a36Sopenharmony_ci .chn_num = 2, /* two channels for tsadc */ 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ 119262306a36Sopenharmony_ci .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ 119362306a36Sopenharmony_ci .tshut_temp = 95000, 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci .initialize = rk_tsadcv3_initialize, 119662306a36Sopenharmony_ci .irq_ack = rk_tsadcv3_irq_ack, 119762306a36Sopenharmony_ci .control = rk_tsadcv3_control, 119862306a36Sopenharmony_ci .get_temp = rk_tsadcv2_get_temp, 119962306a36Sopenharmony_ci .set_alarm_temp = rk_tsadcv2_alarm_temp, 120062306a36Sopenharmony_ci .set_tshut_temp = rk_tsadcv2_tshut_temp, 120162306a36Sopenharmony_ci .set_tshut_mode = rk_tsadcv2_tshut_mode, 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci .table = { 120462306a36Sopenharmony_ci .id = rk3228_code_table, 120562306a36Sopenharmony_ci .length = ARRAY_SIZE(rk3228_code_table), 120662306a36Sopenharmony_ci .data_mask = TSADCV3_DATA_MASK, 120762306a36Sopenharmony_ci .mode = ADC_INCREMENT, 120862306a36Sopenharmony_ci }, 120962306a36Sopenharmony_ci}; 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_cistatic const struct rockchip_tsadc_chip rk3368_tsadc_data = { 121262306a36Sopenharmony_ci /* cpu, gpu */ 121362306a36Sopenharmony_ci .chn_offset = 0, 121462306a36Sopenharmony_ci .chn_num = 2, /* two channels for tsadc */ 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ 121762306a36Sopenharmony_ci .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ 121862306a36Sopenharmony_ci .tshut_temp = 95000, 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci .initialize = rk_tsadcv2_initialize, 122162306a36Sopenharmony_ci .irq_ack = rk_tsadcv2_irq_ack, 122262306a36Sopenharmony_ci .control = rk_tsadcv2_control, 122362306a36Sopenharmony_ci .get_temp = rk_tsadcv2_get_temp, 122462306a36Sopenharmony_ci .set_alarm_temp = rk_tsadcv2_alarm_temp, 122562306a36Sopenharmony_ci .set_tshut_temp = rk_tsadcv2_tshut_temp, 122662306a36Sopenharmony_ci .set_tshut_mode = rk_tsadcv2_tshut_mode, 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci .table = { 122962306a36Sopenharmony_ci .id = rk3368_code_table, 123062306a36Sopenharmony_ci .length = ARRAY_SIZE(rk3368_code_table), 123162306a36Sopenharmony_ci .data_mask = TSADCV3_DATA_MASK, 123262306a36Sopenharmony_ci .mode = ADC_INCREMENT, 123362306a36Sopenharmony_ci }, 123462306a36Sopenharmony_ci}; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_cistatic const struct rockchip_tsadc_chip rk3399_tsadc_data = { 123762306a36Sopenharmony_ci /* cpu, gpu */ 123862306a36Sopenharmony_ci .chn_offset = 0, 123962306a36Sopenharmony_ci .chn_num = 2, /* two channels for tsadc */ 124062306a36Sopenharmony_ci 124162306a36Sopenharmony_ci .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ 124262306a36Sopenharmony_ci .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ 124362306a36Sopenharmony_ci .tshut_temp = 95000, 124462306a36Sopenharmony_ci 124562306a36Sopenharmony_ci .initialize = rk_tsadcv3_initialize, 124662306a36Sopenharmony_ci .irq_ack = rk_tsadcv3_irq_ack, 124762306a36Sopenharmony_ci .control = rk_tsadcv3_control, 124862306a36Sopenharmony_ci .get_temp = rk_tsadcv2_get_temp, 124962306a36Sopenharmony_ci .set_alarm_temp = rk_tsadcv2_alarm_temp, 125062306a36Sopenharmony_ci .set_tshut_temp = rk_tsadcv2_tshut_temp, 125162306a36Sopenharmony_ci .set_tshut_mode = rk_tsadcv2_tshut_mode, 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci .table = { 125462306a36Sopenharmony_ci .id = rk3399_code_table, 125562306a36Sopenharmony_ci .length = ARRAY_SIZE(rk3399_code_table), 125662306a36Sopenharmony_ci .data_mask = TSADCV3_DATA_MASK, 125762306a36Sopenharmony_ci .mode = ADC_INCREMENT, 125862306a36Sopenharmony_ci }, 125962306a36Sopenharmony_ci}; 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_cistatic const struct rockchip_tsadc_chip rk3568_tsadc_data = { 126262306a36Sopenharmony_ci /* cpu, gpu */ 126362306a36Sopenharmony_ci .chn_offset = 0, 126462306a36Sopenharmony_ci .chn_num = 2, /* two channels for tsadc */ 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ 126762306a36Sopenharmony_ci .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ 126862306a36Sopenharmony_ci .tshut_temp = 95000, 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci .initialize = rk_tsadcv7_initialize, 127162306a36Sopenharmony_ci .irq_ack = rk_tsadcv3_irq_ack, 127262306a36Sopenharmony_ci .control = rk_tsadcv3_control, 127362306a36Sopenharmony_ci .get_temp = rk_tsadcv2_get_temp, 127462306a36Sopenharmony_ci .set_alarm_temp = rk_tsadcv2_alarm_temp, 127562306a36Sopenharmony_ci .set_tshut_temp = rk_tsadcv2_tshut_temp, 127662306a36Sopenharmony_ci .set_tshut_mode = rk_tsadcv2_tshut_mode, 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci .table = { 127962306a36Sopenharmony_ci .id = rk3568_code_table, 128062306a36Sopenharmony_ci .length = ARRAY_SIZE(rk3568_code_table), 128162306a36Sopenharmony_ci .data_mask = TSADCV2_DATA_MASK, 128262306a36Sopenharmony_ci .mode = ADC_INCREMENT, 128362306a36Sopenharmony_ci }, 128462306a36Sopenharmony_ci}; 128562306a36Sopenharmony_ci 128662306a36Sopenharmony_cistatic const struct rockchip_tsadc_chip rk3588_tsadc_data = { 128762306a36Sopenharmony_ci /* top, big_core0, big_core1, little_core, center, gpu, npu */ 128862306a36Sopenharmony_ci .chn_offset = 0, 128962306a36Sopenharmony_ci .chn_num = 7, /* seven channels for tsadc */ 129062306a36Sopenharmony_ci .tshut_mode = TSHUT_MODE_GPIO, /* default TSHUT via GPIO give PMIC */ 129162306a36Sopenharmony_ci .tshut_polarity = TSHUT_LOW_ACTIVE, /* default TSHUT LOW ACTIVE */ 129262306a36Sopenharmony_ci .tshut_temp = 95000, 129362306a36Sopenharmony_ci .initialize = rk_tsadcv8_initialize, 129462306a36Sopenharmony_ci .irq_ack = rk_tsadcv4_irq_ack, 129562306a36Sopenharmony_ci .control = rk_tsadcv4_control, 129662306a36Sopenharmony_ci .get_temp = rk_tsadcv4_get_temp, 129762306a36Sopenharmony_ci .set_alarm_temp = rk_tsadcv3_alarm_temp, 129862306a36Sopenharmony_ci .set_tshut_temp = rk_tsadcv3_tshut_temp, 129962306a36Sopenharmony_ci .set_tshut_mode = rk_tsadcv3_tshut_mode, 130062306a36Sopenharmony_ci .table = { 130162306a36Sopenharmony_ci .id = rk3588_code_table, 130262306a36Sopenharmony_ci .length = ARRAY_SIZE(rk3588_code_table), 130362306a36Sopenharmony_ci .data_mask = TSADCV4_DATA_MASK, 130462306a36Sopenharmony_ci .mode = ADC_INCREMENT, 130562306a36Sopenharmony_ci }, 130662306a36Sopenharmony_ci}; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_cistatic const struct of_device_id of_rockchip_thermal_match[] = { 130962306a36Sopenharmony_ci { .compatible = "rockchip,px30-tsadc", 131062306a36Sopenharmony_ci .data = (void *)&px30_tsadc_data, 131162306a36Sopenharmony_ci }, 131262306a36Sopenharmony_ci { 131362306a36Sopenharmony_ci .compatible = "rockchip,rv1108-tsadc", 131462306a36Sopenharmony_ci .data = (void *)&rv1108_tsadc_data, 131562306a36Sopenharmony_ci }, 131662306a36Sopenharmony_ci { 131762306a36Sopenharmony_ci .compatible = "rockchip,rk3228-tsadc", 131862306a36Sopenharmony_ci .data = (void *)&rk3228_tsadc_data, 131962306a36Sopenharmony_ci }, 132062306a36Sopenharmony_ci { 132162306a36Sopenharmony_ci .compatible = "rockchip,rk3288-tsadc", 132262306a36Sopenharmony_ci .data = (void *)&rk3288_tsadc_data, 132362306a36Sopenharmony_ci }, 132462306a36Sopenharmony_ci { 132562306a36Sopenharmony_ci .compatible = "rockchip,rk3328-tsadc", 132662306a36Sopenharmony_ci .data = (void *)&rk3328_tsadc_data, 132762306a36Sopenharmony_ci }, 132862306a36Sopenharmony_ci { 132962306a36Sopenharmony_ci .compatible = "rockchip,rk3366-tsadc", 133062306a36Sopenharmony_ci .data = (void *)&rk3366_tsadc_data, 133162306a36Sopenharmony_ci }, 133262306a36Sopenharmony_ci { 133362306a36Sopenharmony_ci .compatible = "rockchip,rk3368-tsadc", 133462306a36Sopenharmony_ci .data = (void *)&rk3368_tsadc_data, 133562306a36Sopenharmony_ci }, 133662306a36Sopenharmony_ci { 133762306a36Sopenharmony_ci .compatible = "rockchip,rk3399-tsadc", 133862306a36Sopenharmony_ci .data = (void *)&rk3399_tsadc_data, 133962306a36Sopenharmony_ci }, 134062306a36Sopenharmony_ci { 134162306a36Sopenharmony_ci .compatible = "rockchip,rk3568-tsadc", 134262306a36Sopenharmony_ci .data = (void *)&rk3568_tsadc_data, 134362306a36Sopenharmony_ci }, 134462306a36Sopenharmony_ci { 134562306a36Sopenharmony_ci .compatible = "rockchip,rk3588-tsadc", 134662306a36Sopenharmony_ci .data = (void *)&rk3588_tsadc_data, 134762306a36Sopenharmony_ci }, 134862306a36Sopenharmony_ci { /* end */ }, 134962306a36Sopenharmony_ci}; 135062306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, of_rockchip_thermal_match); 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_cistatic void 135362306a36Sopenharmony_cirockchip_thermal_toggle_sensor(struct rockchip_thermal_sensor *sensor, bool on) 135462306a36Sopenharmony_ci{ 135562306a36Sopenharmony_ci struct thermal_zone_device *tzd = sensor->tzd; 135662306a36Sopenharmony_ci 135762306a36Sopenharmony_ci if (on) 135862306a36Sopenharmony_ci thermal_zone_device_enable(tzd); 135962306a36Sopenharmony_ci else 136062306a36Sopenharmony_ci thermal_zone_device_disable(tzd); 136162306a36Sopenharmony_ci} 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_cistatic irqreturn_t rockchip_thermal_alarm_irq_thread(int irq, void *dev) 136462306a36Sopenharmony_ci{ 136562306a36Sopenharmony_ci struct rockchip_thermal_data *thermal = dev; 136662306a36Sopenharmony_ci int i; 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci dev_dbg(&thermal->pdev->dev, "thermal alarm\n"); 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci thermal->chip->irq_ack(thermal->regs); 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci for (i = 0; i < thermal->chip->chn_num; i++) 137362306a36Sopenharmony_ci thermal_zone_device_update(thermal->sensors[i].tzd, 137462306a36Sopenharmony_ci THERMAL_EVENT_UNSPECIFIED); 137562306a36Sopenharmony_ci 137662306a36Sopenharmony_ci return IRQ_HANDLED; 137762306a36Sopenharmony_ci} 137862306a36Sopenharmony_ci 137962306a36Sopenharmony_cistatic int rockchip_thermal_set_trips(struct thermal_zone_device *tz, int low, int high) 138062306a36Sopenharmony_ci{ 138162306a36Sopenharmony_ci struct rockchip_thermal_sensor *sensor = thermal_zone_device_priv(tz); 138262306a36Sopenharmony_ci struct rockchip_thermal_data *thermal = sensor->thermal; 138362306a36Sopenharmony_ci const struct rockchip_tsadc_chip *tsadc = thermal->chip; 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n", 138662306a36Sopenharmony_ci __func__, sensor->id, low, high); 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci return tsadc->set_alarm_temp(&tsadc->table, 138962306a36Sopenharmony_ci sensor->id, thermal->regs, high); 139062306a36Sopenharmony_ci} 139162306a36Sopenharmony_ci 139262306a36Sopenharmony_cistatic int rockchip_thermal_get_temp(struct thermal_zone_device *tz, int *out_temp) 139362306a36Sopenharmony_ci{ 139462306a36Sopenharmony_ci struct rockchip_thermal_sensor *sensor = thermal_zone_device_priv(tz); 139562306a36Sopenharmony_ci struct rockchip_thermal_data *thermal = sensor->thermal; 139662306a36Sopenharmony_ci const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip; 139762306a36Sopenharmony_ci int retval; 139862306a36Sopenharmony_ci 139962306a36Sopenharmony_ci retval = tsadc->get_temp(&tsadc->table, 140062306a36Sopenharmony_ci sensor->id, thermal->regs, out_temp); 140162306a36Sopenharmony_ci return retval; 140262306a36Sopenharmony_ci} 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_cistatic const struct thermal_zone_device_ops rockchip_of_thermal_ops = { 140562306a36Sopenharmony_ci .get_temp = rockchip_thermal_get_temp, 140662306a36Sopenharmony_ci .set_trips = rockchip_thermal_set_trips, 140762306a36Sopenharmony_ci}; 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_cistatic int rockchip_configure_from_dt(struct device *dev, 141062306a36Sopenharmony_ci struct device_node *np, 141162306a36Sopenharmony_ci struct rockchip_thermal_data *thermal) 141262306a36Sopenharmony_ci{ 141362306a36Sopenharmony_ci u32 shut_temp, tshut_mode, tshut_polarity; 141462306a36Sopenharmony_ci 141562306a36Sopenharmony_ci if (of_property_read_u32(np, "rockchip,hw-tshut-temp", &shut_temp)) { 141662306a36Sopenharmony_ci dev_warn(dev, 141762306a36Sopenharmony_ci "Missing tshut temp property, using default %d\n", 141862306a36Sopenharmony_ci thermal->chip->tshut_temp); 141962306a36Sopenharmony_ci thermal->tshut_temp = thermal->chip->tshut_temp; 142062306a36Sopenharmony_ci } else { 142162306a36Sopenharmony_ci if (shut_temp > INT_MAX) { 142262306a36Sopenharmony_ci dev_err(dev, "Invalid tshut temperature specified: %d\n", 142362306a36Sopenharmony_ci shut_temp); 142462306a36Sopenharmony_ci return -ERANGE; 142562306a36Sopenharmony_ci } 142662306a36Sopenharmony_ci thermal->tshut_temp = shut_temp; 142762306a36Sopenharmony_ci } 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci if (of_property_read_u32(np, "rockchip,hw-tshut-mode", &tshut_mode)) { 143062306a36Sopenharmony_ci dev_warn(dev, 143162306a36Sopenharmony_ci "Missing tshut mode property, using default (%s)\n", 143262306a36Sopenharmony_ci thermal->chip->tshut_mode == TSHUT_MODE_GPIO ? 143362306a36Sopenharmony_ci "gpio" : "cru"); 143462306a36Sopenharmony_ci thermal->tshut_mode = thermal->chip->tshut_mode; 143562306a36Sopenharmony_ci } else { 143662306a36Sopenharmony_ci thermal->tshut_mode = tshut_mode; 143762306a36Sopenharmony_ci } 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci if (thermal->tshut_mode > 1) { 144062306a36Sopenharmony_ci dev_err(dev, "Invalid tshut mode specified: %d\n", 144162306a36Sopenharmony_ci thermal->tshut_mode); 144262306a36Sopenharmony_ci return -EINVAL; 144362306a36Sopenharmony_ci } 144462306a36Sopenharmony_ci 144562306a36Sopenharmony_ci if (of_property_read_u32(np, "rockchip,hw-tshut-polarity", 144662306a36Sopenharmony_ci &tshut_polarity)) { 144762306a36Sopenharmony_ci dev_warn(dev, 144862306a36Sopenharmony_ci "Missing tshut-polarity property, using default (%s)\n", 144962306a36Sopenharmony_ci thermal->chip->tshut_polarity == TSHUT_LOW_ACTIVE ? 145062306a36Sopenharmony_ci "low" : "high"); 145162306a36Sopenharmony_ci thermal->tshut_polarity = thermal->chip->tshut_polarity; 145262306a36Sopenharmony_ci } else { 145362306a36Sopenharmony_ci thermal->tshut_polarity = tshut_polarity; 145462306a36Sopenharmony_ci } 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci if (thermal->tshut_polarity > 1) { 145762306a36Sopenharmony_ci dev_err(dev, "Invalid tshut-polarity specified: %d\n", 145862306a36Sopenharmony_ci thermal->tshut_polarity); 145962306a36Sopenharmony_ci return -EINVAL; 146062306a36Sopenharmony_ci } 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci /* The tsadc wont to handle the error in here since some SoCs didn't 146362306a36Sopenharmony_ci * need this property. 146462306a36Sopenharmony_ci */ 146562306a36Sopenharmony_ci thermal->grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); 146662306a36Sopenharmony_ci if (IS_ERR(thermal->grf)) 146762306a36Sopenharmony_ci dev_warn(dev, "Missing rockchip,grf property\n"); 146862306a36Sopenharmony_ci 146962306a36Sopenharmony_ci return 0; 147062306a36Sopenharmony_ci} 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_cistatic int 147362306a36Sopenharmony_cirockchip_thermal_register_sensor(struct platform_device *pdev, 147462306a36Sopenharmony_ci struct rockchip_thermal_data *thermal, 147562306a36Sopenharmony_ci struct rockchip_thermal_sensor *sensor, 147662306a36Sopenharmony_ci int id) 147762306a36Sopenharmony_ci{ 147862306a36Sopenharmony_ci const struct rockchip_tsadc_chip *tsadc = thermal->chip; 147962306a36Sopenharmony_ci int error; 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode); 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs, 148462306a36Sopenharmony_ci thermal->tshut_temp); 148562306a36Sopenharmony_ci if (error) 148662306a36Sopenharmony_ci dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n", 148762306a36Sopenharmony_ci __func__, thermal->tshut_temp, error); 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_ci sensor->thermal = thermal; 149062306a36Sopenharmony_ci sensor->id = id; 149162306a36Sopenharmony_ci sensor->tzd = devm_thermal_of_zone_register(&pdev->dev, id, sensor, 149262306a36Sopenharmony_ci &rockchip_of_thermal_ops); 149362306a36Sopenharmony_ci if (IS_ERR(sensor->tzd)) { 149462306a36Sopenharmony_ci error = PTR_ERR(sensor->tzd); 149562306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to register sensor %d: %d\n", 149662306a36Sopenharmony_ci id, error); 149762306a36Sopenharmony_ci return error; 149862306a36Sopenharmony_ci } 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci return 0; 150162306a36Sopenharmony_ci} 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci/** 150462306a36Sopenharmony_ci * rockchip_thermal_reset_controller - Reset TSADC Controller, reset all tsadc registers. 150562306a36Sopenharmony_ci * @reset: the reset controller of tsadc 150662306a36Sopenharmony_ci */ 150762306a36Sopenharmony_cistatic void rockchip_thermal_reset_controller(struct reset_control *reset) 150862306a36Sopenharmony_ci{ 150962306a36Sopenharmony_ci reset_control_assert(reset); 151062306a36Sopenharmony_ci usleep_range(10, 20); 151162306a36Sopenharmony_ci reset_control_deassert(reset); 151262306a36Sopenharmony_ci} 151362306a36Sopenharmony_ci 151462306a36Sopenharmony_cistatic int rockchip_thermal_probe(struct platform_device *pdev) 151562306a36Sopenharmony_ci{ 151662306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 151762306a36Sopenharmony_ci struct rockchip_thermal_data *thermal; 151862306a36Sopenharmony_ci int irq; 151962306a36Sopenharmony_ci int i; 152062306a36Sopenharmony_ci int error; 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci irq = platform_get_irq(pdev, 0); 152362306a36Sopenharmony_ci if (irq < 0) 152462306a36Sopenharmony_ci return -EINVAL; 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci thermal = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_thermal_data), 152762306a36Sopenharmony_ci GFP_KERNEL); 152862306a36Sopenharmony_ci if (!thermal) 152962306a36Sopenharmony_ci return -ENOMEM; 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci thermal->pdev = pdev; 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ci thermal->chip = device_get_match_data(&pdev->dev); 153462306a36Sopenharmony_ci if (!thermal->chip) 153562306a36Sopenharmony_ci return -EINVAL; 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci thermal->sensors = devm_kcalloc(&pdev->dev, thermal->chip->chn_num, 153862306a36Sopenharmony_ci sizeof(*thermal->sensors), GFP_KERNEL); 153962306a36Sopenharmony_ci if (!thermal->sensors) 154062306a36Sopenharmony_ci return -ENOMEM; 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_ci thermal->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL); 154362306a36Sopenharmony_ci if (IS_ERR(thermal->regs)) 154462306a36Sopenharmony_ci return PTR_ERR(thermal->regs); 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci thermal->reset = devm_reset_control_array_get_exclusive(&pdev->dev); 154762306a36Sopenharmony_ci if (IS_ERR(thermal->reset)) 154862306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(thermal->reset), 154962306a36Sopenharmony_ci "failed to get tsadc reset.\n"); 155062306a36Sopenharmony_ci 155162306a36Sopenharmony_ci thermal->clk = devm_clk_get_enabled(&pdev->dev, "tsadc"); 155262306a36Sopenharmony_ci if (IS_ERR(thermal->clk)) 155362306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(thermal->clk), 155462306a36Sopenharmony_ci "failed to get tsadc clock.\n"); 155562306a36Sopenharmony_ci 155662306a36Sopenharmony_ci thermal->pclk = devm_clk_get_enabled(&pdev->dev, "apb_pclk"); 155762306a36Sopenharmony_ci if (IS_ERR(thermal->pclk)) 155862306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(thermal->pclk), 155962306a36Sopenharmony_ci "failed to get apb_pclk clock.\n"); 156062306a36Sopenharmony_ci 156162306a36Sopenharmony_ci rockchip_thermal_reset_controller(thermal->reset); 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci error = rockchip_configure_from_dt(&pdev->dev, np, thermal); 156462306a36Sopenharmony_ci if (error) 156562306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, error, 156662306a36Sopenharmony_ci "failed to parse device tree data\n"); 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci thermal->chip->initialize(thermal->grf, thermal->regs, 156962306a36Sopenharmony_ci thermal->tshut_polarity); 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_ci for (i = 0; i < thermal->chip->chn_num; i++) { 157262306a36Sopenharmony_ci error = rockchip_thermal_register_sensor(pdev, thermal, 157362306a36Sopenharmony_ci &thermal->sensors[i], 157462306a36Sopenharmony_ci thermal->chip->chn_offset + i); 157562306a36Sopenharmony_ci if (error) 157662306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, error, 157762306a36Sopenharmony_ci "failed to register sensor[%d].\n", i); 157862306a36Sopenharmony_ci } 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci error = devm_request_threaded_irq(&pdev->dev, irq, NULL, 158162306a36Sopenharmony_ci &rockchip_thermal_alarm_irq_thread, 158262306a36Sopenharmony_ci IRQF_ONESHOT, 158362306a36Sopenharmony_ci "rockchip_thermal", thermal); 158462306a36Sopenharmony_ci if (error) 158562306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, error, 158662306a36Sopenharmony_ci "failed to request tsadc irq.\n"); 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci thermal->chip->control(thermal->regs, true); 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_ci for (i = 0; i < thermal->chip->chn_num; i++) { 159162306a36Sopenharmony_ci rockchip_thermal_toggle_sensor(&thermal->sensors[i], true); 159262306a36Sopenharmony_ci error = thermal_add_hwmon_sysfs(thermal->sensors[i].tzd); 159362306a36Sopenharmony_ci if (error) 159462306a36Sopenharmony_ci dev_warn(&pdev->dev, 159562306a36Sopenharmony_ci "failed to register sensor %d with hwmon: %d\n", 159662306a36Sopenharmony_ci i, error); 159762306a36Sopenharmony_ci } 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci platform_set_drvdata(pdev, thermal); 160062306a36Sopenharmony_ci 160162306a36Sopenharmony_ci return 0; 160262306a36Sopenharmony_ci} 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_cistatic int rockchip_thermal_remove(struct platform_device *pdev) 160562306a36Sopenharmony_ci{ 160662306a36Sopenharmony_ci struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev); 160762306a36Sopenharmony_ci int i; 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci for (i = 0; i < thermal->chip->chn_num; i++) { 161062306a36Sopenharmony_ci struct rockchip_thermal_sensor *sensor = &thermal->sensors[i]; 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci thermal_remove_hwmon_sysfs(sensor->tzd); 161362306a36Sopenharmony_ci rockchip_thermal_toggle_sensor(sensor, false); 161462306a36Sopenharmony_ci } 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_ci thermal->chip->control(thermal->regs, false); 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci return 0; 161962306a36Sopenharmony_ci} 162062306a36Sopenharmony_ci 162162306a36Sopenharmony_cistatic int __maybe_unused rockchip_thermal_suspend(struct device *dev) 162262306a36Sopenharmony_ci{ 162362306a36Sopenharmony_ci struct rockchip_thermal_data *thermal = dev_get_drvdata(dev); 162462306a36Sopenharmony_ci int i; 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci for (i = 0; i < thermal->chip->chn_num; i++) 162762306a36Sopenharmony_ci rockchip_thermal_toggle_sensor(&thermal->sensors[i], false); 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ci thermal->chip->control(thermal->regs, false); 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ci clk_disable(thermal->pclk); 163262306a36Sopenharmony_ci clk_disable(thermal->clk); 163362306a36Sopenharmony_ci 163462306a36Sopenharmony_ci pinctrl_pm_select_sleep_state(dev); 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci return 0; 163762306a36Sopenharmony_ci} 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_cistatic int __maybe_unused rockchip_thermal_resume(struct device *dev) 164062306a36Sopenharmony_ci{ 164162306a36Sopenharmony_ci struct rockchip_thermal_data *thermal = dev_get_drvdata(dev); 164262306a36Sopenharmony_ci int i; 164362306a36Sopenharmony_ci int error; 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci error = clk_enable(thermal->clk); 164662306a36Sopenharmony_ci if (error) 164762306a36Sopenharmony_ci return error; 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ci error = clk_enable(thermal->pclk); 165062306a36Sopenharmony_ci if (error) { 165162306a36Sopenharmony_ci clk_disable(thermal->clk); 165262306a36Sopenharmony_ci return error; 165362306a36Sopenharmony_ci } 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci rockchip_thermal_reset_controller(thermal->reset); 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci thermal->chip->initialize(thermal->grf, thermal->regs, 165862306a36Sopenharmony_ci thermal->tshut_polarity); 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci for (i = 0; i < thermal->chip->chn_num; i++) { 166162306a36Sopenharmony_ci int id = thermal->sensors[i].id; 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci thermal->chip->set_tshut_mode(id, thermal->regs, 166462306a36Sopenharmony_ci thermal->tshut_mode); 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci error = thermal->chip->set_tshut_temp(&thermal->chip->table, 166762306a36Sopenharmony_ci id, thermal->regs, 166862306a36Sopenharmony_ci thermal->tshut_temp); 166962306a36Sopenharmony_ci if (error) 167062306a36Sopenharmony_ci dev_err(dev, "%s: invalid tshut=%d, error=%d\n", 167162306a36Sopenharmony_ci __func__, thermal->tshut_temp, error); 167262306a36Sopenharmony_ci } 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci thermal->chip->control(thermal->regs, true); 167562306a36Sopenharmony_ci 167662306a36Sopenharmony_ci for (i = 0; i < thermal->chip->chn_num; i++) 167762306a36Sopenharmony_ci rockchip_thermal_toggle_sensor(&thermal->sensors[i], true); 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci pinctrl_pm_select_default_state(dev); 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci return 0; 168262306a36Sopenharmony_ci} 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_cistatic SIMPLE_DEV_PM_OPS(rockchip_thermal_pm_ops, 168562306a36Sopenharmony_ci rockchip_thermal_suspend, rockchip_thermal_resume); 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_cistatic struct platform_driver rockchip_thermal_driver = { 168862306a36Sopenharmony_ci .driver = { 168962306a36Sopenharmony_ci .name = "rockchip-thermal", 169062306a36Sopenharmony_ci .pm = &rockchip_thermal_pm_ops, 169162306a36Sopenharmony_ci .of_match_table = of_rockchip_thermal_match, 169262306a36Sopenharmony_ci }, 169362306a36Sopenharmony_ci .probe = rockchip_thermal_probe, 169462306a36Sopenharmony_ci .remove = rockchip_thermal_remove, 169562306a36Sopenharmony_ci}; 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_cimodule_platform_driver(rockchip_thermal_driver); 169862306a36Sopenharmony_ci 169962306a36Sopenharmony_ciMODULE_DESCRIPTION("ROCKCHIP THERMAL Driver"); 170062306a36Sopenharmony_ciMODULE_AUTHOR("Rockchip, Inc."); 170162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 170262306a36Sopenharmony_ciMODULE_ALIAS("platform:rockchip-thermal"); 1703