2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2016-04-19 10:22:01 +03:00
/*
* Generic ADC thermal driver
*
* Copyright ( C ) 2016 NVIDIA CORPORATION . All rights reserved .
*
* Author : Laxman Dewangan < ldewangan @ nvidia . com >
*/
# include <linux/iio/consumer.h>
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# include <linux/slab.h>
# include <linux/thermal.h>
struct gadc_thermal_info {
struct device * dev ;
struct thermal_zone_device * tz_dev ;
struct iio_channel * channel ;
s32 * lookup_table ;
int nlookup_table ;
} ;
static int gadc_thermal_adc_to_temp ( struct gadc_thermal_info * gti , int val )
{
2018-12-24 10:26:44 +03:00
int temp , temp_hi , temp_lo , adc_hi , adc_lo ;
2016-04-19 10:22:01 +03:00
int i ;
2019-04-18 19:37:32 +03:00
if ( ! gti - > lookup_table )
return val ;
2016-04-19 10:22:01 +03:00
for ( i = 0 ; i < gti - > nlookup_table ; i + + ) {
if ( val > = gti - > lookup_table [ 2 * i + 1 ] )
break ;
}
if ( i = = 0 ) {
temp = gti - > lookup_table [ 0 ] ;
2018-12-24 10:26:44 +03:00
} else if ( i > = gti - > nlookup_table ) {
2016-04-19 10:22:01 +03:00
temp = gti - > lookup_table [ 2 * ( gti - > nlookup_table - 1 ) ] ;
} else {
adc_hi = gti - > lookup_table [ 2 * i - 1 ] ;
adc_lo = gti - > lookup_table [ 2 * i + 1 ] ;
2018-12-24 10:26:44 +03:00
temp_hi = gti - > lookup_table [ 2 * i - 2 ] ;
temp_lo = gti - > lookup_table [ 2 * i ] ;
temp = temp_hi + mult_frac ( temp_lo - temp_hi , val - adc_hi ,
adc_lo - adc_hi ) ;
2016-04-19 10:22:01 +03:00
}
return temp ;
}
2022-08-05 01:43:21 +03:00
static int gadc_thermal_get_temp ( struct thermal_zone_device * tz , int * temp )
2016-04-19 10:22:01 +03:00
{
2022-08-05 01:43:21 +03:00
struct gadc_thermal_info * gti = tz - > devdata ;
2016-04-19 10:22:01 +03:00
int val ;
int ret ;
ret = iio_read_channel_processed ( gti - > channel , & val ) ;
if ( ret < 0 ) {
dev_err ( gti - > dev , " IIO channel read failed %d \n " , ret ) ;
return ret ;
}
* temp = gadc_thermal_adc_to_temp ( gti , val ) ;
return 0 ;
}
2022-08-05 01:43:21 +03:00
static const struct thermal_zone_device_ops gadc_thermal_ops = {
2016-04-19 10:22:01 +03:00
. get_temp = gadc_thermal_get_temp ,
} ;
static int gadc_thermal_read_linear_lookup_table ( struct device * dev ,
struct gadc_thermal_info * gti )
{
struct device_node * np = dev - > of_node ;
2020-01-08 02:20:44 +03:00
enum iio_chan_type chan_type ;
2016-04-19 10:22:01 +03:00
int ntable ;
int ret ;
ntable = of_property_count_elems_of_size ( np , " temperature-lookup-table " ,
sizeof ( u32 ) ) ;
2019-04-18 19:37:32 +03:00
if ( ntable < = 0 ) {
2020-01-08 02:20:44 +03:00
ret = iio_get_channel_type ( gti - > channel , & chan_type ) ;
if ( ret | | chan_type ! = IIO_TEMP )
dev_notice ( dev ,
" no lookup table, assuming DAC channel returns milliCelcius \n " ) ;
2019-04-18 19:37:32 +03:00
return 0 ;
2016-04-19 10:22:01 +03:00
}
if ( ntable % 2 ) {
dev_err ( dev , " Pair of temperature vs ADC read value missing \n " ) ;
return - EINVAL ;
}
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:07:58 +03:00
gti - > lookup_table = devm_kcalloc ( dev ,
ntable , sizeof ( * gti - > lookup_table ) ,
GFP_KERNEL ) ;
2016-04-19 10:22:01 +03:00
if ( ! gti - > lookup_table )
return - ENOMEM ;
ret = of_property_read_u32_array ( np , " temperature-lookup-table " ,
( u32 * ) gti - > lookup_table , ntable ) ;
if ( ret < 0 ) {
dev_err ( dev , " Failed to read temperature lookup table: %d \n " ,
ret ) ;
return ret ;
}
gti - > nlookup_table = ntable / 2 ;
return 0 ;
}
static int gadc_thermal_probe ( struct platform_device * pdev )
{
struct gadc_thermal_info * gti ;
int ret ;
if ( ! pdev - > dev . of_node ) {
dev_err ( & pdev - > dev , " Only DT based supported \n " ) ;
return - ENODEV ;
}
gti = devm_kzalloc ( & pdev - > dev , sizeof ( * gti ) , GFP_KERNEL ) ;
if ( ! gti )
return - ENOMEM ;
2017-10-19 20:05:59 +03:00
gti - > channel = devm_iio_channel_get ( & pdev - > dev , " sensor-channel " ) ;
2016-04-19 10:22:01 +03:00
if ( IS_ERR ( gti - > channel ) ) {
ret = PTR_ERR ( gti - > channel ) ;
2019-09-10 10:59:07 +03:00
if ( ret ! = - EPROBE_DEFER )
dev_err ( & pdev - > dev , " IIO channel not found: %d \n " , ret ) ;
2016-04-19 10:22:01 +03:00
return ret ;
}
2020-01-08 02:20:43 +03:00
ret = gadc_thermal_read_linear_lookup_table ( & pdev - > dev , gti ) ;
if ( ret < 0 )
return ret ;
gti - > dev = & pdev - > dev ;
platform_set_drvdata ( pdev , gti ) ;
2022-08-05 01:43:21 +03:00
gti - > tz_dev = devm_thermal_of_zone_register ( & pdev - > dev , 0 , gti ,
& gadc_thermal_ops ) ;
2016-04-19 10:22:01 +03:00
if ( IS_ERR ( gti - > tz_dev ) ) {
ret = PTR_ERR ( gti - > tz_dev ) ;
2019-09-10 10:59:07 +03:00
if ( ret ! = - EPROBE_DEFER )
dev_err ( & pdev - > dev ,
" Thermal zone sensor register failed: %d \n " ,
ret ) ;
2017-10-19 20:05:59 +03:00
return ret ;
2016-04-19 10:22:01 +03:00
}
return 0 ;
}
static const struct of_device_id of_adc_thermal_match [ ] = {
{ . compatible = " generic-adc-thermal " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , of_adc_thermal_match ) ;
static struct platform_driver gadc_thermal_driver = {
. driver = {
. name = " generic-adc-thermal " ,
. of_match_table = of_adc_thermal_match ,
} ,
. probe = gadc_thermal_probe ,
} ;
module_platform_driver ( gadc_thermal_driver ) ;
MODULE_AUTHOR ( " Laxman Dewangan <ldewangan@nvidia.com> " ) ;
MODULE_DESCRIPTION ( " Generic ADC thermal driver using IIO framework with DT " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;