Loading drivers/thermal/rockchip_thermal.c +100 −53 Original line number Diff line number Diff line Loading @@ -118,11 +118,11 @@ struct rockchip_tsadc_chip { void (*control)(void __iomem *reg, bool on); /* Per-sensor methods */ int (*get_temp)(struct chip_tsadc_table table, int (*get_temp)(const struct chip_tsadc_table *table, int chn, void __iomem *reg, int *temp); void (*set_alarm_temp)(struct chip_tsadc_table table, int (*set_alarm_temp)(const struct chip_tsadc_table *table, int chn, void __iomem *reg, int temp); void (*set_tshut_temp)(struct chip_tsadc_table table, int (*set_tshut_temp)(const struct chip_tsadc_table *table, int chn, void __iomem *reg, int temp); void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m); Loading Loading @@ -317,6 +317,7 @@ static const struct tsadc_table rk3288_code_table[] = { {3452, 115000}, {3437, 120000}, {3421, 125000}, {0, 125000}, }; static const struct tsadc_table rk3368_code_table[] = { Loading Loading @@ -397,59 +398,80 @@ static const struct tsadc_table rk3399_code_table[] = { {TSADCV3_DATA_MASK, 125000}, }; static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table, static u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table, int temp) { int high, low, mid; u32 error = 0; unsigned long num; unsigned int denom; u32 error = table->data_mask; low = 0; high = table.length - 1; high = (table->length - 1) - 1; /* ignore the last check for table */ mid = (high + low) / 2; /* Return mask code data when the temp is over table range */ if (temp < table.id[low].temp || temp > table.id[high].temp) { error = table.data_mask; if (temp < table->id[low].temp || temp > table->id[high].temp) goto exit; } while (low <= high) { if (temp == table.id[mid].temp) return table.id[mid].code; else if (temp < table.id[mid].temp) if (temp == table->id[mid].temp) return table->id[mid].code; else if (temp < table->id[mid].temp) high = mid - 1; else low = mid + 1; mid = (low + high) / 2; } /* * The conversion code granularity provided by the table. Let's * assume that the relationship between temperature and * analog value between 2 table entries is linear and interpolate * to produce less granular result. */ num = abs(table->id[mid + 1].code - table->id[mid].code); num *= temp - table->id[mid].temp; denom = table->id[mid + 1].temp - table->id[mid].temp; switch (table->mode) { case ADC_DECREMENT: return table->id[mid].code - (num / denom); case ADC_INCREMENT: return table->id[mid].code + (num / denom); default: pr_err("%s: unknown table mode: %d\n", __func__, table->mode); return error; } exit: pr_err("Invalid the conversion, error=%d\n", error); pr_err("%s: invalid temperature, temp=%d error=%d\n", __func__, temp, error); return error; } static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, int *temp) static int rk_tsadcv2_code_to_temp(const struct chip_tsadc_table *table, u32 code, int *temp) { unsigned int low = 1; unsigned int high = table.length - 1; unsigned int high = table->length - 1; unsigned int mid = (low + high) / 2; unsigned int num; unsigned long denom; WARN_ON(table.length < 2); WARN_ON(table->length < 2); switch (table.mode) { switch (table->mode) { case ADC_DECREMENT: code &= table.data_mask; if (code < table.id[high].code) code &= table->data_mask; if (code <= table->id[high].code) return -EAGAIN; /* Incorrect reading */ while (low <= high) { if (code >= table.id[mid].code && code < table.id[mid - 1].code) if (code >= table->id[mid].code && code < table->id[mid - 1].code) break; else if (code < table.id[mid].code) else if (code < table->id[mid].code) low = mid + 1; else high = mid - 1; Loading @@ -458,15 +480,15 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, } break; case ADC_INCREMENT: code &= table.data_mask; if (code < table.id[low].code) code &= table->data_mask; if (code < table->id[low].code) return -EAGAIN; /* Incorrect reading */ while (low <= high) { if (code <= table.id[mid].code && code > table.id[mid - 1].code) if (code <= table->id[mid].code && code > table->id[mid - 1].code) break; else if (code > table.id[mid].code) else if (code > table->id[mid].code) low = mid + 1; else high = mid - 1; Loading @@ -475,7 +497,8 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, } break; default: pr_err("Invalid the conversion table\n"); pr_err("%s: unknown table mode: %d\n", __func__, table->mode); return -EINVAL; } /* Loading @@ -484,10 +507,10 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, * temperature between 2 table entries is linear and interpolate * to produce less granular result. */ num = table.id[mid].temp - table.id[mid - 1].temp; num *= abs(table.id[mid - 1].code - code); denom = abs(table.id[mid - 1].code - table.id[mid].code); *temp = table.id[mid - 1].temp + (num / denom); num = table->id[mid].temp - table->id[mid - 1].temp; num *= abs(table->id[mid - 1].code - code); denom = abs(table->id[mid - 1].code - table->id[mid].code); *temp = table->id[mid - 1].temp + (num / denom); return 0; } Loading Loading @@ -638,7 +661,7 @@ static void rk_tsadcv3_control(void __iomem *regs, bool enable) writel_relaxed(val, regs + TSADCV2_AUTO_CON); } static int rk_tsadcv2_get_temp(struct chip_tsadc_table table, static int rk_tsadcv2_get_temp(const struct chip_tsadc_table *table, int chn, void __iomem *regs, int *temp) { u32 val; Loading @@ -648,39 +671,57 @@ static int rk_tsadcv2_get_temp(struct chip_tsadc_table table, return rk_tsadcv2_code_to_temp(table, val, temp); } static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table, static int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table, int chn, void __iomem *regs, int temp) { u32 alarm_value, int_en; u32 alarm_value; u32 int_en, int_clr; /* * In some cases, some sensors didn't need the trip points, the * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm * in the end, ignore this case and disable the high temperature * interrupt. */ if (temp == INT_MAX) { int_clr = readl_relaxed(regs + TSADCV2_INT_EN); int_clr &= ~TSADCV2_INT_SRC_EN(chn); writel_relaxed(int_clr, regs + TSADCV2_INT_EN); return 0; } /* Make sure the value is valid */ alarm_value = rk_tsadcv2_temp_to_code(table, temp); if (alarm_value == table.data_mask) return; if (alarm_value == table->data_mask) return -ERANGE; writel_relaxed(alarm_value & table.data_mask, writel_relaxed(alarm_value & table->data_mask, regs + TSADCV2_COMP_INT(chn)); int_en = readl_relaxed(regs + TSADCV2_INT_EN); int_en |= TSADCV2_INT_SRC_EN(chn); writel_relaxed(int_en, regs + TSADCV2_INT_EN); return 0; } static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table, static int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table, int chn, void __iomem *regs, int temp) { u32 tshut_value, val; /* Make sure the value is valid */ tshut_value = rk_tsadcv2_temp_to_code(table, temp); if (tshut_value == table.data_mask) return; if (tshut_value == table->data_mask) return -ERANGE; writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn)); /* TSHUT will be valid */ val = readl_relaxed(regs + TSADCV2_AUTO_CON); writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON); return 0; } static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, Loading Loading @@ -883,10 +924,8 @@ 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); tsadc->set_alarm_temp(tsadc->table, return tsadc->set_alarm_temp(&tsadc->table, sensor->id, thermal->regs, high); return 0; } static int rockchip_thermal_get_temp(void *_sensor, int *out_temp) Loading @@ -896,7 +935,7 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp) const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip; int retval; retval = tsadc->get_temp(tsadc->table, retval = tsadc->get_temp(&tsadc->table, sensor->id, thermal->regs, out_temp); dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n", sensor->id, *out_temp, retval); Loading Loading @@ -982,8 +1021,12 @@ rockchip_thermal_register_sensor(struct platform_device *pdev, int error; tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode); tsadc->set_tshut_temp(tsadc->table, id, thermal->regs, error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs, thermal->tshut_temp); if (error) dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n", __func__, thermal->tshut_temp, error); sensor->thermal = thermal; sensor->id = id; Loading Loading @@ -1196,9 +1239,13 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev) thermal->chip->set_tshut_mode(id, thermal->regs, thermal->tshut_mode); thermal->chip->set_tshut_temp(thermal->chip->table, error = thermal->chip->set_tshut_temp(&thermal->chip->table, id, thermal->regs, thermal->tshut_temp); if (error) dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n", __func__, thermal->tshut_temp, error); } thermal->chip->control(thermal->regs, true); Loading Loading
drivers/thermal/rockchip_thermal.c +100 −53 Original line number Diff line number Diff line Loading @@ -118,11 +118,11 @@ struct rockchip_tsadc_chip { void (*control)(void __iomem *reg, bool on); /* Per-sensor methods */ int (*get_temp)(struct chip_tsadc_table table, int (*get_temp)(const struct chip_tsadc_table *table, int chn, void __iomem *reg, int *temp); void (*set_alarm_temp)(struct chip_tsadc_table table, int (*set_alarm_temp)(const struct chip_tsadc_table *table, int chn, void __iomem *reg, int temp); void (*set_tshut_temp)(struct chip_tsadc_table table, int (*set_tshut_temp)(const struct chip_tsadc_table *table, int chn, void __iomem *reg, int temp); void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m); Loading Loading @@ -317,6 +317,7 @@ static const struct tsadc_table rk3288_code_table[] = { {3452, 115000}, {3437, 120000}, {3421, 125000}, {0, 125000}, }; static const struct tsadc_table rk3368_code_table[] = { Loading Loading @@ -397,59 +398,80 @@ static const struct tsadc_table rk3399_code_table[] = { {TSADCV3_DATA_MASK, 125000}, }; static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table, static u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table, int temp) { int high, low, mid; u32 error = 0; unsigned long num; unsigned int denom; u32 error = table->data_mask; low = 0; high = table.length - 1; high = (table->length - 1) - 1; /* ignore the last check for table */ mid = (high + low) / 2; /* Return mask code data when the temp is over table range */ if (temp < table.id[low].temp || temp > table.id[high].temp) { error = table.data_mask; if (temp < table->id[low].temp || temp > table->id[high].temp) goto exit; } while (low <= high) { if (temp == table.id[mid].temp) return table.id[mid].code; else if (temp < table.id[mid].temp) if (temp == table->id[mid].temp) return table->id[mid].code; else if (temp < table->id[mid].temp) high = mid - 1; else low = mid + 1; mid = (low + high) / 2; } /* * The conversion code granularity provided by the table. Let's * assume that the relationship between temperature and * analog value between 2 table entries is linear and interpolate * to produce less granular result. */ num = abs(table->id[mid + 1].code - table->id[mid].code); num *= temp - table->id[mid].temp; denom = table->id[mid + 1].temp - table->id[mid].temp; switch (table->mode) { case ADC_DECREMENT: return table->id[mid].code - (num / denom); case ADC_INCREMENT: return table->id[mid].code + (num / denom); default: pr_err("%s: unknown table mode: %d\n", __func__, table->mode); return error; } exit: pr_err("Invalid the conversion, error=%d\n", error); pr_err("%s: invalid temperature, temp=%d error=%d\n", __func__, temp, error); return error; } static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, int *temp) static int rk_tsadcv2_code_to_temp(const struct chip_tsadc_table *table, u32 code, int *temp) { unsigned int low = 1; unsigned int high = table.length - 1; unsigned int high = table->length - 1; unsigned int mid = (low + high) / 2; unsigned int num; unsigned long denom; WARN_ON(table.length < 2); WARN_ON(table->length < 2); switch (table.mode) { switch (table->mode) { case ADC_DECREMENT: code &= table.data_mask; if (code < table.id[high].code) code &= table->data_mask; if (code <= table->id[high].code) return -EAGAIN; /* Incorrect reading */ while (low <= high) { if (code >= table.id[mid].code && code < table.id[mid - 1].code) if (code >= table->id[mid].code && code < table->id[mid - 1].code) break; else if (code < table.id[mid].code) else if (code < table->id[mid].code) low = mid + 1; else high = mid - 1; Loading @@ -458,15 +480,15 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, } break; case ADC_INCREMENT: code &= table.data_mask; if (code < table.id[low].code) code &= table->data_mask; if (code < table->id[low].code) return -EAGAIN; /* Incorrect reading */ while (low <= high) { if (code <= table.id[mid].code && code > table.id[mid - 1].code) if (code <= table->id[mid].code && code > table->id[mid - 1].code) break; else if (code > table.id[mid].code) else if (code > table->id[mid].code) low = mid + 1; else high = mid - 1; Loading @@ -475,7 +497,8 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, } break; default: pr_err("Invalid the conversion table\n"); pr_err("%s: unknown table mode: %d\n", __func__, table->mode); return -EINVAL; } /* Loading @@ -484,10 +507,10 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, * temperature between 2 table entries is linear and interpolate * to produce less granular result. */ num = table.id[mid].temp - table.id[mid - 1].temp; num *= abs(table.id[mid - 1].code - code); denom = abs(table.id[mid - 1].code - table.id[mid].code); *temp = table.id[mid - 1].temp + (num / denom); num = table->id[mid].temp - table->id[mid - 1].temp; num *= abs(table->id[mid - 1].code - code); denom = abs(table->id[mid - 1].code - table->id[mid].code); *temp = table->id[mid - 1].temp + (num / denom); return 0; } Loading Loading @@ -638,7 +661,7 @@ static void rk_tsadcv3_control(void __iomem *regs, bool enable) writel_relaxed(val, regs + TSADCV2_AUTO_CON); } static int rk_tsadcv2_get_temp(struct chip_tsadc_table table, static int rk_tsadcv2_get_temp(const struct chip_tsadc_table *table, int chn, void __iomem *regs, int *temp) { u32 val; Loading @@ -648,39 +671,57 @@ static int rk_tsadcv2_get_temp(struct chip_tsadc_table table, return rk_tsadcv2_code_to_temp(table, val, temp); } static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table, static int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table, int chn, void __iomem *regs, int temp) { u32 alarm_value, int_en; u32 alarm_value; u32 int_en, int_clr; /* * In some cases, some sensors didn't need the trip points, the * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm * in the end, ignore this case and disable the high temperature * interrupt. */ if (temp == INT_MAX) { int_clr = readl_relaxed(regs + TSADCV2_INT_EN); int_clr &= ~TSADCV2_INT_SRC_EN(chn); writel_relaxed(int_clr, regs + TSADCV2_INT_EN); return 0; } /* Make sure the value is valid */ alarm_value = rk_tsadcv2_temp_to_code(table, temp); if (alarm_value == table.data_mask) return; if (alarm_value == table->data_mask) return -ERANGE; writel_relaxed(alarm_value & table.data_mask, writel_relaxed(alarm_value & table->data_mask, regs + TSADCV2_COMP_INT(chn)); int_en = readl_relaxed(regs + TSADCV2_INT_EN); int_en |= TSADCV2_INT_SRC_EN(chn); writel_relaxed(int_en, regs + TSADCV2_INT_EN); return 0; } static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table, static int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table, int chn, void __iomem *regs, int temp) { u32 tshut_value, val; /* Make sure the value is valid */ tshut_value = rk_tsadcv2_temp_to_code(table, temp); if (tshut_value == table.data_mask) return; if (tshut_value == table->data_mask) return -ERANGE; writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn)); /* TSHUT will be valid */ val = readl_relaxed(regs + TSADCV2_AUTO_CON); writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON); return 0; } static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs, Loading Loading @@ -883,10 +924,8 @@ 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); tsadc->set_alarm_temp(tsadc->table, return tsadc->set_alarm_temp(&tsadc->table, sensor->id, thermal->regs, high); return 0; } static int rockchip_thermal_get_temp(void *_sensor, int *out_temp) Loading @@ -896,7 +935,7 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp) const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip; int retval; retval = tsadc->get_temp(tsadc->table, retval = tsadc->get_temp(&tsadc->table, sensor->id, thermal->regs, out_temp); dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n", sensor->id, *out_temp, retval); Loading Loading @@ -982,8 +1021,12 @@ rockchip_thermal_register_sensor(struct platform_device *pdev, int error; tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode); tsadc->set_tshut_temp(tsadc->table, id, thermal->regs, error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs, thermal->tshut_temp); if (error) dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n", __func__, thermal->tshut_temp, error); sensor->thermal = thermal; sensor->id = id; Loading Loading @@ -1196,9 +1239,13 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev) thermal->chip->set_tshut_mode(id, thermal->regs, thermal->tshut_mode); thermal->chip->set_tshut_temp(thermal->chip->table, error = thermal->chip->set_tshut_temp(&thermal->chip->table, id, thermal->regs, thermal->tshut_temp); if (error) dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n", __func__, thermal->tshut_temp, error); } thermal->chip->control(thermal->regs, true); Loading