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:
parent
f8aefe8f0d
commit
bc48adbe38
1 changed files with 102 additions and 44 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue