[PATCH] thermal: rockchip: fix handling of invalid readings
Dmitry Torokhov
dtor at chromium.org
Mon Aug 10 00:59:04 PDT 2015
Hi Caesar,
On Sun, Aug 9, 2015 at 11:30 PM, Caesar Wang <wxt at rock-chips.com> wrote:
> Dear Dmitry,
>
> Thanks your patch.
>
> The code looks like fine,but I don't think the TS-ADC will work on rk3288
> SoC.
What do you mean? It seems to work when I ran it...
>
>
> 在 2015年08月08日 04:59, Dmitry Torokhov 写道:
>>
>> We attempted to signal invalid code by returning -EAGAIN from
>> rk_tsadcv2_code_to_temp(), unfortunately the return value was stuffed
>> directly into the temperature pointer, potentially confusing upper
>> layers with temperature of -EINVAL.
>>
>> Let's split temperature from error/success indicator to avoid such
>> confusion.
>>
>> Also change the way we scan the temperature table to start with the 2nd
>> element so that we do not need to worry that we may reference out of
>> bounds element while doing binary search and keep checking that we end
>> up with 'mid' equal to 0 (since we are looking for the temperature that
>> would fall into interval between the 'mid' and 'mid - 1') .
>>
>> Signed-off-by: Dmitry Torokhov <dtor at chromium.org>
>> ---
>> drivers/thermal/rockchip_thermal.c | 28 +++++++++++++---------------
>> 1 file changed, 13 insertions(+), 15 deletions(-)
>>
>> diff --git a/drivers/thermal/rockchip_thermal.c
>> b/drivers/thermal/rockchip_thermal.c
>> index c89ffb2..93ee307 100644
>> --- a/drivers/thermal/rockchip_thermal.c
>> +++ b/drivers/thermal/rockchip_thermal.c
>> @@ -124,7 +124,7 @@ struct rockchip_thermal_data {
>> #define TSADCV2_AUTO_PERIOD_HT_TIME 50 /* msec */
>> struct tsadc_table {
>> - unsigned long code;
>> + u32 code;
>> long temp;
>> };
>> @@ -164,7 +164,6 @@ static const struct tsadc_table v2_code_table[] = {
>> {3452, 115000},
>> {3437, 120000},
>> {3421, 125000},
>> - {0, 125000},
>> };
>> static u32 rk_tsadcv2_temp_to_code(long temp)
>> @@ -191,19 +190,21 @@ static u32 rk_tsadcv2_temp_to_code(long temp)
>> return 0;
>> }
>> -static int rk_tsadcv2_code_to_temp(u32 code)
>> +static int rk_tsadcv2_code_to_temp(u32 code, int *temp)
>> {
>> - unsigned int low = 0;
>> + unsigned int low = 1;
>> unsigned int high = ARRAY_SIZE(v2_code_table) - 1;
>> unsigned int mid = (low + high) / 2;
>> unsigned int num;
>> unsigned long denom;
>> - /* Invalid code, return -EAGAIN */
>> - if (code > TSADCV2_DATA_MASK)
>> - return -EAGAIN;
>> + BUILD_BUG_ON(ARRAY_SIZE(v2_code_table) < 2);
>> - while (low <= high && mid) {
>> + code &= TSADCV2_DATA_MASK;
>> + if (code < v2_code_table[high].code)
>> + return -EAGAIN; /* Incorrect reading */
>> +
>> + while (low <= high) {
>> if (code >= v2_code_table[mid].code &&
>> code < v2_code_table[mid - 1].code)
>> break;
>> @@ -223,7 +224,9 @@ static int rk_tsadcv2_code_to_temp(u32 code)
>> num = v2_code_table[mid].temp - v2_code_table[mid - 1].temp;
>> num *= v2_code_table[mid - 1].code - code;
>> denom = v2_code_table[mid - 1].code - v2_code_table[mid].code;
>> - return v2_code_table[mid - 1].temp + (num / denom);
>> + *temp = v2_code_table[mid - 1].temp + (num / denom);
>> +
>> + return 0;
>> }
>> /**
>> @@ -281,14 +284,9 @@ static int rk_tsadcv2_get_temp(int chn, void __iomem
>> *regs, int *temp)
>> {
>> u32 val;
>> - /* the A/D value of the channel last conversion need some time */
>> val = readl_relaxed(regs + TSADCV2_DATA(chn));
>> - if (val == 0)
>> - return -EAGAIN;
>> -
>
>
> if we reserve the above code, that will get the ADC value.
But if we pass 0 into rk_tsadcv2_code_to_temp() it will trigger:
>> + if (code < v2_code_table[high].code)
>> + return -EAGAIN; /* Incorrect reading */
and still return -EAGAIN, as it was. There is no behavior change as
far as I can see.
>
>
>> - *temp = rk_tsadcv2_code_to_temp(val);
>> - return 0;
>> + return rk_tsadcv2_code_to_temp(val, temp);
>> }
>> static void rk_tsadcv2_tshut_temp(int chn, void __iomem *regs, long
>> temp)
>
>
Thanks,
Dmitry
More information about the linux-arm-kernel
mailing list