diff options
author | Rocky Hao <rocky.hao@rock-chips.com> | 2017-09-01 16:43:38 +0800 |
---|---|---|
committer | Huang, Tao <huangtao@rock-chips.com> | 2017-10-25 14:35:31 +0800 |
commit | a9e988c63a1ed61f70dd44159edfa96cc8d0a590 (patch) | |
tree | 65bb431dd6ddacf38e58f8ac21f15787a57b1c5b /drivers/thermal/rockchip_thermal.c | |
parent | 646e27e0f57619acf2328d05f30638c247d4231f (diff) |
thermal: rockchip: rk3288: fix temperature-jump issue
Due to 32k clock jitter, tsadc will wrongly report a very
high temperature, that is a temperature-jump. This may lead
to an abnormal OS reboot. A filter function is added to
predict the true temperature.
Change-Id: I5b5641efe8e64b4058a604f274350b1e94584fa6
Signed-off-by: Rocky Hao <rocky.hao@rock-chips.com>
Diffstat (limited to 'drivers/thermal/rockchip_thermal.c')
-rw-r--r-- | drivers/thermal/rockchip_thermal.c | 87 |
1 files changed, 86 insertions, 1 deletions
diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index 0360d87d189e..f98c93309990 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -227,6 +227,15 @@ struct rockchip_thermal_data { #define GRF_TSADC_VCM_EN_L (0x10001 << 7) #define GRF_TSADC_VCM_EN_H (0x10001 << 7) +#define MIN_TEMP (-40000) +#define MAX_TEMP (125000) + +#define BASE (1024) +#define BASE_SHIFT (10) +#define START_DEBOUNCE_COUNT (100) +#define HIGHER_DEBOUNCE_TEMP (30) +#define LOWER_DEBOUNCE_TEMP (15) + /** * struct tsadc_table - code to temperature conversion table * @code: the value of adc channel @@ -685,6 +694,82 @@ static int rk_tsadcv2_get_temp(struct chip_tsadc_table table, return rk_tsadcv2_code_to_temp(table, val, temp); } +static int predict_temp(int temp) +{ + /* + * The deviation of prediction. the temperature will not change rapidly, + * so this cov_q is small + */ + int cov_q = 18; + /* + * The deviation of tsadc's reading, deviation of tsadc is very big when + * abnormal temperature is get + */ + int cov_r = 542; + + int gain; + int temp_mid; + int temp_now; + int prob_mid; + int prob_now; + static int temp_last = 25; + static int prob_last = 20; + static int bounding_cnt; + + /* + * Before START_DEBOUNCE_COUNT's samples of temperature, we consider + * tsadc is stable, i.e. after that, the temperature may be not stable + * and may have abnormal reading, so we set a bounding temperature. If + * the reading from tsadc is too big, we set the delta temperature of + * DEBOUNCE_TEMP/3 comparing to the last temperature. + */ + + if (bounding_cnt++ > START_DEBOUNCE_COUNT) { + bounding_cnt = START_DEBOUNCE_COUNT; + if (temp - temp_last > HIGHER_DEBOUNCE_TEMP) + temp = temp_last + HIGHER_DEBOUNCE_TEMP / 3; + if (temp_last - temp > LOWER_DEBOUNCE_TEMP) + temp = temp_last - LOWER_DEBOUNCE_TEMP / 3; + } + + temp_mid = temp_last; + + /* calculate the probability of this time's prediction */ + prob_mid = prob_last + cov_q; + + /* calculate the Kalman Gain */ + gain = (prob_mid * BASE) / (prob_mid + cov_r); + + /* calculate the prediction of temperature */ + temp_now = temp_mid + (gain * (temp - temp_mid) >> BASE_SHIFT); + + /* + * Base on this time's Kalman Gain, ajust our probability of prediction + * for next time calculation + */ + prob_now = ((BASE - gain) * prob_mid) >> BASE_SHIFT; + + prob_last = prob_now; + temp_last = temp_now; + + return temp_last; +} + +static int rk_tsadcv3_get_temp(struct chip_tsadc_table table, + int chn, void __iomem *regs, int *temp) +{ + u32 val; + int ret; + + val = readl_relaxed(regs + TSADCV2_DATA(chn)); + + ret = rk_tsadcv2_code_to_temp(table, val, temp); + if (!ret) + *temp = predict_temp(*temp); + + return ret; +} + static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table, int chn, void __iomem *regs, int temp) { @@ -773,7 +858,7 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = { .initialize = rk_tsadcv2_initialize, .irq_ack = rk_tsadcv2_irq_ack, .control = rk_tsadcv2_control, - .get_temp = rk_tsadcv2_get_temp, + .get_temp = rk_tsadcv3_get_temp, .set_alarm_temp = rk_tsadcv2_alarm_temp, .set_tshut_temp = rk_tsadcv2_tshut_temp, .set_tshut_mode = rk_tsadcv2_tshut_mode, |