thermal: rockchip: add tsadc calibration for rv1126 soc

Get the calibration parameters for each chip by reading the OTP,
Calculate temperature using calibration parameters.

Signed-off-by: Elaine Zhang <zhangqing@rock-chips.com>
Change-Id: I05cfb65ae95dcefc7fc52ed91326c7da9d27de55
This commit is contained in:
Elaine Zhang 2020-06-22 16:35:15 +08:00 committed by Tao Huang
commit bc48adbe38

View file

@ -26,6 +26,7 @@
#include <linux/thermal.h>
#include <linux/mfd/syscon.h>
#include <linux/pinctrl/consumer.h>
#include <linux/nvmem-consumer.h>
/**
* If the temperature over a period of time High,
@ -83,6 +84,9 @@ struct chip_tsadc_table {
const struct tsadc_table *id;
unsigned int length;
u32 data_mask;
/* Tsadc is linear, using linear parameters */
int kNum;
int bNum;
enum adc_sort_mode mode;
};
@ -99,6 +103,8 @@ struct chip_tsadc_table {
* @set_alarm_temp: set the high temperature interrupt
* @set_tshut_temp: set the hardware-controlled shutdown temperature
* @set_tshut_mode: set the hardware-controlled shutdown mode
* @get_trim_code: get the trim code by otp value
* @trim_temp: get trim temp by trim code
* @table: the chip-specific conversion table
*/
struct rockchip_tsadc_chip {
@ -126,6 +132,9 @@ struct rockchip_tsadc_chip {
int chn, void __iomem *reg, int temp);
void (*set_tshut_mode)(struct regmap *grf, int chn,
void __iomem *reg, enum tshut_mode m);
int (*get_trim_code)(struct platform_device *pdev,
int code, int trim_base);
int (*trim_temp)(struct platform_device *pdev);
/* Per-table methods */
struct chip_tsadc_table table;
@ -171,6 +180,7 @@ struct rockchip_thermal_data {
void __iomem *regs;
int tshut_temp;
int trim;
enum tshut_mode tshut_mode;
enum tshut_polarity tshut_polarity;
struct pinctrl *pinctrl;
@ -237,7 +247,7 @@ struct rockchip_thermal_data {
#define RV1126_GRF0_TSADC_CON 0x0100
#define RV1126_GRF0_TSADC_TRM (0xff00ff << 0)
#define RV1126_GRF0_TSADC_TRM (0xff0077 << 0)
#define RV1126_GRF0_TSADC_SHUT_2CRU (0x30003 << 10)
#define RV1126_GRF0_TSADC_SHUT_2GPIO (0x70007 << 12)
@ -315,45 +325,6 @@ static const struct tsadc_table rv1108_table[] = {
{TSADCV2_DATA_MASK, 125000},
};
static const struct tsadc_table rv1126_code_table[] = {
{0, -40000},
{2623, -40000},
{2635, -35000},
{2646, -30000},
{2657, -25000},
{2669, -20000},
{2680, -15000},
{2691, -10000},
{2703, -5000},
{2714, 0},
{2725, 5000},
{2737, 10000},
{2748, 15000},
{2759, 20000},
{2770, 25000},
{2782, 30000},
{2793, 35000},
{2804, 40000},
{2816, 45000},
{2827, 50000},
{2838, 55000},
{2850, 60000},
{2861, 65000},
{2872, 70000},
{2884, 75000},
{2895, 80000},
{2906, 85000},
{2918, 90000},
{2929, 95000},
{2940, 100000},
{2952, 105000},
{2963, 110000},
{2974, 115000},
{2985, 120000},
{2997, 125000},
{TSADCV2_DATA_MASK, 125000},
};
static const struct tsadc_table rk1808_code_table[] = {
{0, -40000},
{3455, -40000},
@ -595,6 +566,9 @@ static u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table,
unsigned int denom;
u32 error = table->data_mask;
if (table->kNum)
return (((temp / 1000) * table->kNum) / 1000 + table->bNum);
low = 0;
high = (table->length - 1) - 1; /* ignore the last check for table */
mid = (high + low) / 2;
@ -648,6 +622,13 @@ static int rk_tsadcv2_code_to_temp(const struct chip_tsadc_table *table,
unsigned int num;
unsigned long denom;
if (table->kNum) {
*temp = ((code - table->bNum) * 10000 / table->kNum) * 100;
if (*temp < MIN_TEMP || *temp > MAX_TEMP)
return -EAGAIN;
return 0;
}
WARN_ON(table->length < 2);
switch (table->mode) {
@ -1083,6 +1064,27 @@ static void rk_tsadcv3_tshut_mode(struct regmap *grf, int chn,
writel_relaxed(val, regs + TSADCV2_INT_EN);
}
static int rk_tsadcv1_get_trim_code(struct platform_device *pdev,
int code, int trim_base)
{
struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
const struct chip_tsadc_table *table = &thermal->chip->table;
u32 base_code;
int trim_code;
base_code = trim_base * table->kNum / 1000 + table->bNum;
trim_code = code - base_code - 10;
return trim_code;
}
static int rk_tsadcv1_trim_temp(struct platform_device *pdev)
{
struct rockchip_thermal_data *thermal = platform_get_drvdata(pdev);
return thermal->trim * 500;
}
static const struct rockchip_tsadc_chip rv1108_tsadc_data = {
.chn_id[SENSOR_CPU] = 0, /* cpu sensor is channel 0 */
.chn_num = 1, /* one channel for tsadc */
@ -1122,10 +1124,12 @@ static const struct rockchip_tsadc_chip rv1126_tsadc_data = {
.set_alarm_temp = rk_tsadcv2_alarm_temp,
.set_tshut_temp = rk_tsadcv2_tshut_temp,
.set_tshut_mode = rk_tsadcv3_tshut_mode,
.get_trim_code = rk_tsadcv1_get_trim_code,
.trim_temp = rk_tsadcv1_trim_temp,
.table = {
.id = rv1126_code_table,
.length = ARRAY_SIZE(rv1126_code_table),
.kNum = 2263,
.bNum = 2704,
.data_mask = TSADCV2_DATA_MASK,
.mode = ADC_INCREMENT,
},
@ -1432,6 +1436,9 @@ static int rockchip_thermal_set_trips(void *_sensor, int low, int high)
dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n",
__func__, sensor->id, low, high);
if (tsadc->trim_temp)
high += tsadc->trim_temp(thermal->pdev);
return tsadc->set_alarm_temp(&tsadc->table,
sensor->id, thermal->regs, high);
}
@ -1445,6 +1452,8 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
retval = tsadc->get_temp(&tsadc->table,
sensor->id, thermal->regs, out_temp);
if (tsadc->trim_temp)
*out_temp -= tsadc->trim_temp(thermal->pdev);
dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n",
sensor->id, *out_temp, retval);
@ -1470,11 +1479,38 @@ static void thermal_pinctrl_select_gpio(struct rockchip_thermal_data *thermal)
thermal->gpio_state);
}
static int rockchip_get_efuse_value(struct device_node *np, char *porp_name,
int *value)
{
struct nvmem_cell *cell;
unsigned char *buf;
size_t len;
cell = of_nvmem_cell_get(np, porp_name);
if (IS_ERR(cell))
return PTR_ERR(cell);
buf = (unsigned char *)nvmem_cell_read(cell, &len);
nvmem_cell_put(cell);
if (IS_ERR(buf))
return PTR_ERR(buf);
*value = buf[0];
kfree(buf);
return 0;
}
static int rockchip_configure_from_dt(struct device *dev,
struct device_node *np,
struct rockchip_thermal_data *thermal)
{
const struct rockchip_tsadc_chip *tsadc = thermal->chip;
u32 shut_temp, tshut_mode, tshut_polarity;
int trim_l = 0, trim_h = 0, trim_bsae = 0;
if (of_property_read_u32(np, "rockchip,hw-tshut-temp", &shut_temp)) {
dev_warn(dev,
@ -1530,6 +1566,29 @@ static int rockchip_configure_from_dt(struct device *dev,
if (IS_ERR(thermal->grf))
dev_warn(dev, "Missing rockchip,grf property\n");
if (tsadc->trim_temp && tsadc->get_trim_code) {
/* The tsadc wont to handle the error in here
* since some SoCs didn't need this property.
* rv1126 need trim tsadc.
*/
if (rockchip_get_efuse_value(np, "trim_l", &trim_l))
dev_warn(dev, "Missing trim_l property\n");
if (rockchip_get_efuse_value(np, "trim_h", &trim_h))
dev_warn(dev, "Missing trim_h property\n");
if (rockchip_get_efuse_value(np, "trim_base", &trim_bsae))
dev_warn(dev, "Missing trim_base property\n");
if (trim_l && trim_h && trim_bsae) {
thermal->trim = tsadc->get_trim_code(thermal->pdev,
(trim_h << 8) |
trim_l,
trim_bsae);
dev_info(dev, "tsadc trimmed value = %d\n",
thermal->trim);
thermal->tshut_temp += tsadc->trim_temp(thermal->pdev);
}
}
return 0;
}
@ -1665,6 +1724,7 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
error);
return error;
}
platform_set_drvdata(pdev, thermal);
thermal->chip->control(thermal->regs, false);
@ -1725,8 +1785,6 @@ static int rockchip_thermal_probe(struct platform_device *pdev)
for (i = 0; i < thermal->chip->chn_num; i++)
rockchip_thermal_toggle_sensor(&thermal->sensors[i], true);
platform_set_drvdata(pdev, thermal);
thermal->panic_nb.notifier_call = rockchip_thermal_panic;
atomic_notifier_chain_register(&panic_notifier_list,
&thermal->panic_nb);