2018-08-02 18:43:53 -07:00
// SPDX-License-Identifier: GPL-2.0
/*
2020-05-28 22:24:26 +05:30
* Copyright ( c ) 2018 , 2020 , The Linux Foundation . All rights reserved .
2018-08-02 18:43:53 -07:00
*/
# include <linux/bitops.h>
# include <linux/completion.h>
# include <linux/delay.h>
# include <linux/err.h>
2020-12-04 05:54:59 +03:00
# include <linux/iio/adc/qcom-vadc-common.h>
2018-08-02 18:43:53 -07:00
# include <linux/iio/iio.h>
# include <linux/interrupt.h>
# include <linux/kernel.h>
# include <linux/log2.h>
# include <linux/math64.h>
# include <linux/module.h>
2022-07-15 14:29:00 +02:00
# include <linux/mod_devicetable.h>
2018-08-02 18:43:53 -07:00
# include <linux/platform_device.h>
2022-07-15 14:29:00 +02:00
# include <linux/property.h>
2018-08-02 18:43:53 -07:00
# include <linux/regmap.h>
# include <linux/slab.h>
# include <dt-bindings/iio/qcom,spmi-vadc.h>
# define ADC5_USR_REVISION1 0x0
# define ADC5_USR_STATUS1 0x8
2020-05-28 22:24:26 +05:30
# define ADC5_USR_STATUS1_CONV_FAULT BIT(7)
2018-08-02 18:43:53 -07:00
# define ADC5_USR_STATUS1_REQ_STS BIT(1)
# define ADC5_USR_STATUS1_EOC BIT(0)
# define ADC5_USR_STATUS1_REQ_STS_EOC_MASK 0x3
# define ADC5_USR_STATUS2 0x9
# define ADC5_USR_STATUS2_CONV_SEQ_MASK 0x70
# define ADC5_USR_STATUS2_CONV_SEQ_MASK_SHIFT 0x5
# define ADC5_USR_IBAT_MEAS 0xf
# define ADC5_USR_IBAT_MEAS_SUPPORTED BIT(0)
# define ADC5_USR_DIG_PARAM 0x42
# define ADC5_USR_DIG_PARAM_CAL_VAL BIT(6)
# define ADC5_USR_DIG_PARAM_CAL_VAL_SHIFT 6
# define ADC5_USR_DIG_PARAM_CAL_SEL 0x30
# define ADC5_USR_DIG_PARAM_CAL_SEL_SHIFT 4
# define ADC5_USR_DIG_PARAM_DEC_RATIO_SEL 0xc
# define ADC5_USR_DIG_PARAM_DEC_RATIO_SEL_SHIFT 2
# define ADC5_USR_FAST_AVG_CTL 0x43
# define ADC5_USR_FAST_AVG_CTL_EN BIT(7)
# define ADC5_USR_FAST_AVG_CTL_SAMPLES_MASK 0x7
# define ADC5_USR_CH_SEL_CTL 0x44
# define ADC5_USR_DELAY_CTL 0x45
# define ADC5_USR_HW_SETTLE_DELAY_MASK 0xf
# define ADC5_USR_EN_CTL1 0x46
# define ADC5_USR_EN_CTL1_ADC_EN BIT(7)
# define ADC5_USR_CONV_REQ 0x47
# define ADC5_USR_CONV_REQ_REQ BIT(7)
# define ADC5_USR_DATA0 0x50
# define ADC5_USR_DATA1 0x51
# define ADC5_USR_IBAT_DATA0 0x52
# define ADC5_USR_IBAT_DATA1 0x53
2020-05-28 22:24:26 +05:30
# define ADC_CHANNEL_OFFSET 0x8
# define ADC_CHANNEL_MASK GENMASK(7, 0)
2018-08-02 18:43:53 -07:00
/*
* Conversion time varies based on the decimation , clock rate , fast average
* samples and measurements queued across different VADC peripherals .
* Set the timeout to a max of 100 ms .
*/
# define ADC5_CONV_TIME_MIN_US 263
# define ADC5_CONV_TIME_MAX_US 264
# define ADC5_CONV_TIME_RETRY 400
# define ADC5_CONV_TIMEOUT msecs_to_jiffies(100)
/* Digital version >= 5.3 supports hw_settle_2 */
# define ADC5_HW_SETTLE_DIFF_MINOR 3
# define ADC5_HW_SETTLE_DIFF_MAJOR 5
2020-05-28 22:24:26 +05:30
/* For PMIC7 */
# define ADC_APP_SID 0x40
# define ADC_APP_SID_MASK GENMASK(3, 0)
# define ADC7_CONV_TIMEOUT msecs_to_jiffies(10)
2018-08-02 18:43:53 -07:00
enum adc5_cal_method {
ADC5_NO_CAL = 0 ,
ADC5_RATIOMETRIC_CAL ,
ADC5_ABSOLUTE_CAL
} ;
enum adc5_cal_val {
ADC5_TIMER_CAL = 0 ,
ADC5_NEW_CAL
} ;
/**
* struct adc5_channel_prop - ADC channel property .
* @ channel : channel number , refer to the channel list .
* @ cal_method : calibration method .
* @ cal_val : calibration value
* @ decimation : sampling rate supported for the channel .
2020-05-28 22:24:26 +05:30
* @ sid : slave id of PMIC owning the channel , for PMIC7 .
2018-08-02 18:43:53 -07:00
* @ prescale : channel scaling performed on the input signal .
* @ hw_settle_time : the time between AMUX being configured and the
* start of conversion .
* @ avg_samples : ability to provide single result from the ADC
* that is an average of multiple measurements .
* @ scale_fn_type : Represents the scaling function to convert voltage
* physical units desired by the client for the channel .
* @ datasheet_name : Channel name used in device tree .
*/
struct adc5_channel_prop {
unsigned int channel ;
enum adc5_cal_method cal_method ;
enum adc5_cal_val cal_val ;
unsigned int decimation ;
2020-05-28 22:24:26 +05:30
unsigned int sid ;
2018-08-02 18:43:53 -07:00
unsigned int prescale ;
unsigned int hw_settle_time ;
unsigned int avg_samples ;
enum vadc_scale_fn_type scale_fn_type ;
const char * datasheet_name ;
} ;
/**
* struct adc5_chip - ADC private structure .
* @ regmap : SPMI ADC5 peripheral register map field .
* @ dev : SPMI ADC5 device .
* @ base : base address for the ADC peripheral .
* @ nchannels : number of ADC channels .
* @ chan_props : array of ADC channel properties .
* @ iio_chans : array of IIO channels specification .
* @ poll_eoc : use polling instead of interrupt .
* @ complete : ADC result notification after interrupt is received .
* @ lock : ADC lock for access to the peripheral .
* @ data : software configuration data .
*/
struct adc5_chip {
struct regmap * regmap ;
struct device * dev ;
u16 base ;
unsigned int nchannels ;
struct adc5_channel_prop * chan_props ;
struct iio_chan_spec * iio_chans ;
bool poll_eoc ;
struct completion complete ;
struct mutex lock ;
const struct adc5_data * data ;
} ;
static int adc5_read ( struct adc5_chip * adc , u16 offset , u8 * data , int len )
{
return regmap_bulk_read ( adc - > regmap , adc - > base + offset , data , len ) ;
}
static int adc5_write ( struct adc5_chip * adc , u16 offset , u8 * data , int len )
{
return regmap_bulk_write ( adc - > regmap , adc - > base + offset , data , len ) ;
}
2020-05-28 22:24:26 +05:30
static int adc5_masked_write ( struct adc5_chip * adc , u16 offset , u8 mask , u8 val )
{
return regmap_update_bits ( adc - > regmap , adc - > base + offset , mask , val ) ;
}
2018-08-02 18:43:53 -07:00
static int adc5_read_voltage_data ( struct adc5_chip * adc , u16 * data )
{
int ret ;
u8 rslt_lsb , rslt_msb ;
ret = adc5_read ( adc , ADC5_USR_DATA0 , & rslt_lsb , sizeof ( rslt_lsb ) ) ;
if ( ret )
return ret ;
ret = adc5_read ( adc , ADC5_USR_DATA1 , & rslt_msb , sizeof ( rslt_lsb ) ) ;
if ( ret )
return ret ;
* data = ( rslt_msb < < 8 ) | rslt_lsb ;
if ( * data = = ADC5_USR_DATA_CHECK ) {
2020-05-28 22:24:28 +05:30
dev_err ( adc - > dev , " Invalid data:0x%x \n " , * data ) ;
2018-08-02 18:43:53 -07:00
return - EINVAL ;
}
2020-05-28 22:24:28 +05:30
dev_dbg ( adc - > dev , " voltage raw code:0x%x \n " , * data ) ;
2018-08-02 18:43:53 -07:00
return 0 ;
}
static int adc5_poll_wait_eoc ( struct adc5_chip * adc )
{
unsigned int count , retry = ADC5_CONV_TIME_RETRY ;
u8 status1 ;
int ret ;
for ( count = 0 ; count < retry ; count + + ) {
ret = adc5_read ( adc , ADC5_USR_STATUS1 , & status1 ,
sizeof ( status1 ) ) ;
if ( ret )
return ret ;
status1 & = ADC5_USR_STATUS1_REQ_STS_EOC_MASK ;
if ( status1 = = ADC5_USR_STATUS1_EOC )
return 0 ;
usleep_range ( ADC5_CONV_TIME_MIN_US , ADC5_CONV_TIME_MAX_US ) ;
}
return - ETIMEDOUT ;
}
static void adc5_update_dig_param ( struct adc5_chip * adc ,
struct adc5_channel_prop * prop , u8 * data )
{
/* Update calibration value */
* data & = ~ ADC5_USR_DIG_PARAM_CAL_VAL ;
* data | = ( prop - > cal_val < < ADC5_USR_DIG_PARAM_CAL_VAL_SHIFT ) ;
/* Update calibration select */
* data & = ~ ADC5_USR_DIG_PARAM_CAL_SEL ;
* data | = ( prop - > cal_method < < ADC5_USR_DIG_PARAM_CAL_SEL_SHIFT ) ;
/* Update decimation ratio select */
* data & = ~ ADC5_USR_DIG_PARAM_DEC_RATIO_SEL ;
* data | = ( prop - > decimation < < ADC5_USR_DIG_PARAM_DEC_RATIO_SEL_SHIFT ) ;
}
static int adc5_configure ( struct adc5_chip * adc ,
struct adc5_channel_prop * prop )
{
int ret ;
u8 buf [ 6 ] ;
/* Read registers 0x42 through 0x46 */
ret = adc5_read ( adc , ADC5_USR_DIG_PARAM , buf , sizeof ( buf ) ) ;
2020-05-28 22:24:27 +05:30
if ( ret )
2018-08-02 18:43:53 -07:00
return ret ;
/* Digital param selection */
adc5_update_dig_param ( adc , prop , & buf [ 0 ] ) ;
/* Update fast average sample value */
buf [ 1 ] & = ( u8 ) ~ ADC5_USR_FAST_AVG_CTL_SAMPLES_MASK ;
buf [ 1 ] | = prop - > avg_samples ;
/* Select ADC channel */
buf [ 2 ] = prop - > channel ;
/* Select HW settle delay for channel */
buf [ 3 ] & = ( u8 ) ~ ADC5_USR_HW_SETTLE_DELAY_MASK ;
buf [ 3 ] | = prop - > hw_settle_time ;
/* Select ADC enable */
buf [ 4 ] | = ADC5_USR_EN_CTL1_ADC_EN ;
/* Select CONV request */
buf [ 5 ] | = ADC5_USR_CONV_REQ_REQ ;
if ( ! adc - > poll_eoc )
reinit_completion ( & adc - > complete ) ;
return adc5_write ( adc , ADC5_USR_DIG_PARAM , buf , sizeof ( buf ) ) ;
}
2020-05-28 22:24:26 +05:30
static int adc7_configure ( struct adc5_chip * adc ,
struct adc5_channel_prop * prop )
{
int ret ;
u8 conv_req = 0 , buf [ 4 ] ;
ret = adc5_masked_write ( adc , ADC_APP_SID , ADC_APP_SID_MASK , prop - > sid ) ;
if ( ret )
return ret ;
ret = adc5_read ( adc , ADC5_USR_DIG_PARAM , buf , sizeof ( buf ) ) ;
if ( ret )
return ret ;
/* Digital param selection */
adc5_update_dig_param ( adc , prop , & buf [ 0 ] ) ;
/* Update fast average sample value */
buf [ 1 ] & = ~ ADC5_USR_FAST_AVG_CTL_SAMPLES_MASK ;
buf [ 1 ] | = prop - > avg_samples ;
/* Select ADC channel */
buf [ 2 ] = prop - > channel ;
/* Select HW settle delay for channel */
buf [ 3 ] & = ~ ADC5_USR_HW_SETTLE_DELAY_MASK ;
buf [ 3 ] | = prop - > hw_settle_time ;
/* Select CONV request */
conv_req = ADC5_USR_CONV_REQ_REQ ;
if ( ! adc - > poll_eoc )
reinit_completion ( & adc - > complete ) ;
ret = adc5_write ( adc , ADC5_USR_DIG_PARAM , buf , sizeof ( buf ) ) ;
if ( ret )
return ret ;
return adc5_write ( adc , ADC5_USR_CONV_REQ , & conv_req , 1 ) ;
}
2018-08-02 18:43:53 -07:00
static int adc5_do_conversion ( struct adc5_chip * adc ,
struct adc5_channel_prop * prop ,
struct iio_chan_spec const * chan ,
u16 * data_volt , u16 * data_cur )
{
int ret ;
mutex_lock ( & adc - > lock ) ;
ret = adc5_configure ( adc , prop ) ;
if ( ret ) {
2020-05-28 22:24:28 +05:30
dev_err ( adc - > dev , " ADC configure failed with %d \n " , ret ) ;
2018-08-02 18:43:53 -07:00
goto unlock ;
}
if ( adc - > poll_eoc ) {
ret = adc5_poll_wait_eoc ( adc ) ;
2020-05-28 22:24:27 +05:30
if ( ret ) {
2020-05-28 22:24:28 +05:30
dev_err ( adc - > dev , " EOC bit not set \n " ) ;
2018-08-02 18:43:53 -07:00
goto unlock ;
}
} else {
ret = wait_for_completion_timeout ( & adc - > complete ,
ADC5_CONV_TIMEOUT ) ;
if ( ! ret ) {
2020-05-28 22:24:28 +05:30
dev_dbg ( adc - > dev , " Did not get completion timeout. \n " ) ;
2018-08-02 18:43:53 -07:00
ret = adc5_poll_wait_eoc ( adc ) ;
2020-05-28 22:24:27 +05:30
if ( ret ) {
2020-05-28 22:24:28 +05:30
dev_err ( adc - > dev , " EOC bit not set \n " ) ;
2018-08-02 18:43:53 -07:00
goto unlock ;
}
}
}
ret = adc5_read_voltage_data ( adc , data_volt ) ;
unlock :
mutex_unlock ( & adc - > lock ) ;
return ret ;
}
2020-05-28 22:24:26 +05:30
static int adc7_do_conversion ( struct adc5_chip * adc ,
struct adc5_channel_prop * prop ,
struct iio_chan_spec const * chan ,
u16 * data_volt , u16 * data_cur )
{
int ret ;
u8 status ;
mutex_lock ( & adc - > lock ) ;
ret = adc7_configure ( adc , prop ) ;
if ( ret ) {
dev_err ( adc - > dev , " ADC configure failed with %d \n " , ret ) ;
goto unlock ;
}
/* No support for polling mode at present */
wait_for_completion_timeout ( & adc - > complete , ADC7_CONV_TIMEOUT ) ;
ret = adc5_read ( adc , ADC5_USR_STATUS1 , & status , 1 ) ;
if ( ret )
goto unlock ;
if ( status & ADC5_USR_STATUS1_CONV_FAULT ) {
dev_err ( adc - > dev , " Unexpected conversion fault \n " ) ;
ret = - EIO ;
goto unlock ;
}
ret = adc5_read_voltage_data ( adc , data_volt ) ;
unlock :
mutex_unlock ( & adc - > lock ) ;
return ret ;
}
2020-06-23 12:59:59 +05:30
typedef int ( * adc_do_conversion ) ( struct adc5_chip * adc ,
struct adc5_channel_prop * prop ,
struct iio_chan_spec const * chan ,
u16 * data_volt , u16 * data_cur ) ;
2018-08-02 18:43:53 -07:00
static irqreturn_t adc5_isr ( int irq , void * dev_id )
{
struct adc5_chip * adc = dev_id ;
complete ( & adc - > complete ) ;
return IRQ_HANDLED ;
}
2022-07-15 14:29:00 +02:00
static int adc5_fwnode_xlate ( struct iio_dev * indio_dev ,
const struct fwnode_reference_args * iiospec )
2018-08-02 18:43:53 -07:00
{
struct adc5_chip * adc = iio_priv ( indio_dev ) ;
int i ;
for ( i = 0 ; i < adc - > nchannels ; i + + )
if ( adc - > chan_props [ i ] . channel = = iiospec - > args [ 0 ] )
return i ;
return - EINVAL ;
}
2022-07-15 14:29:00 +02:00
static int adc7_fwnode_xlate ( struct iio_dev * indio_dev ,
const struct fwnode_reference_args * iiospec )
2020-05-28 22:24:26 +05:30
{
struct adc5_chip * adc = iio_priv ( indio_dev ) ;
int i , v_channel ;
for ( i = 0 ; i < adc - > nchannels ; i + + ) {
v_channel = ( adc - > chan_props [ i ] . sid < < ADC_CHANNEL_OFFSET ) |
adc - > chan_props [ i ] . channel ;
if ( v_channel = = iiospec - > args [ 0 ] )
return i ;
}
return - EINVAL ;
}
2020-06-23 12:59:59 +05:30
static int adc_read_raw_common ( struct iio_dev * indio_dev ,
2018-08-02 18:43:53 -07:00
struct iio_chan_spec const * chan , int * val , int * val2 ,
2020-06-23 12:59:59 +05:30
long mask , adc_do_conversion do_conv )
2018-08-02 18:43:53 -07:00
{
struct adc5_chip * adc = iio_priv ( indio_dev ) ;
struct adc5_channel_prop * prop ;
u16 adc_code_volt , adc_code_cur ;
int ret ;
prop = & adc - > chan_props [ chan - > address ] ;
switch ( mask ) {
case IIO_CHAN_INFO_PROCESSED :
2020-06-23 12:59:59 +05:30
ret = do_conv ( adc , prop , chan ,
& adc_code_volt , & adc_code_cur ) ;
2018-08-02 18:43:53 -07:00
if ( ret )
return ret ;
ret = qcom_adc5_hw_scale ( prop - > scale_fn_type ,
2020-12-04 05:54:57 +03:00
prop - > prescale ,
2018-08-02 18:43:53 -07:00
adc - > data ,
adc_code_volt , val ) ;
if ( ret )
return ret ;
return IIO_VAL_INT ;
default :
return - EINVAL ;
}
}
2020-06-23 12:59:59 +05:30
static int adc5_read_raw ( struct iio_dev * indio_dev ,
2020-05-28 22:24:26 +05:30
struct iio_chan_spec const * chan , int * val , int * val2 ,
long mask )
{
2020-06-23 12:59:59 +05:30
return adc_read_raw_common ( indio_dev , chan , val , val2 ,
mask , adc5_do_conversion ) ;
}
2020-05-28 22:24:26 +05:30
2020-06-23 12:59:59 +05:30
static int adc7_read_raw ( struct iio_dev * indio_dev ,
struct iio_chan_spec const * chan , int * val , int * val2 ,
long mask )
{
return adc_read_raw_common ( indio_dev , chan , val , val2 ,
mask , adc7_do_conversion ) ;
2020-05-28 22:24:26 +05:30
}
2018-08-02 18:43:53 -07:00
static const struct iio_info adc5_info = {
. read_raw = adc5_read_raw ,
2022-07-15 14:29:00 +02:00
. fwnode_xlate = adc5_fwnode_xlate ,
2018-08-02 18:43:53 -07:00
} ;
2020-05-28 22:24:26 +05:30
static const struct iio_info adc7_info = {
. read_raw = adc7_read_raw ,
2022-07-15 14:29:00 +02:00
. fwnode_xlate = adc7_fwnode_xlate ,
2020-05-28 22:24:26 +05:30
} ;
2018-08-02 18:43:53 -07:00
struct adc5_channels {
const char * datasheet_name ;
unsigned int prescale_index ;
enum iio_chan_type type ;
long info_mask ;
enum vadc_scale_fn_type scale_fn_type ;
} ;
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
/* In these definitions, _pre refers to an index into adc5_prescale_ratios. */
2018-08-02 18:43:53 -07:00
# define ADC5_CHAN(_dname, _type, _mask, _pre, _scale) \
{ \
. datasheet_name = _dname , \
. prescale_index = _pre , \
. type = _type , \
. info_mask = _mask , \
. scale_fn_type = _scale , \
} , \
# define ADC5_CHAN_TEMP(_dname, _pre, _scale) \
ADC5_CHAN ( _dname , IIO_TEMP , \
BIT ( IIO_CHAN_INFO_PROCESSED ) , \
_pre , _scale ) \
# define ADC5_CHAN_VOLT(_dname, _pre, _scale) \
ADC5_CHAN ( _dname , IIO_VOLTAGE , \
BIT ( IIO_CHAN_INFO_PROCESSED ) , \
_pre , _scale ) \
static const struct adc5_channels adc5_chans_pmic [ ADC5_MAX_CHANNEL ] = {
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_REF_GND ] = ADC5_CHAN_VOLT ( " ref_gnd " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_1P25VREF ] = ADC5_CHAN_VOLT ( " vref_1p25 " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_VPH_PWR ] = ADC5_CHAN_VOLT ( " vph_pwr " , 1 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_VBAT_SNS ] = ADC5_CHAN_VOLT ( " vbat_sns " , 1 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
2022-08-05 15:57:26 +02:00
[ ADC5_VCOIN ] = ADC5_CHAN_VOLT ( " vcoin " , 1 ,
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_DIE_TEMP ] = ADC5_CHAN_TEMP ( " die_temp " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_PMIC_THERM )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_USB_IN_I ] = ADC5_CHAN_VOLT ( " usb_in_i_uv " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_USB_IN_V_16 ] = ADC5_CHAN_VOLT ( " usb_in_v_div_16 " , 8 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_CHG_TEMP ] = ADC5_CHAN_TEMP ( " chg_temp " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_PM5_CHG_TEMP )
/* Charger prescales SBUx and MID_CHG to fit within 1.8V upper unit */
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_SBUx ] = ADC5_CHAN_VOLT ( " chg_sbux " , 1 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_MID_CHG_DIV6 ] = ADC5_CHAN_VOLT ( " chg_mid_chg " , 3 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_XO_THERM_100K_PU ] = ADC5_CHAN_TEMP ( " xo_therm " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_XOTHERM )
2023-01-06 16:39:41 +01:00
[ ADC5_BAT_ID_100K_PU ] = ADC5_CHAN_TEMP ( " bat_id " , 0 ,
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_AMUX_THM1_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm1_100k_pu " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_THERM_100K_PULLUP )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_AMUX_THM2_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm2_100k_pu " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_THERM_100K_PULLUP )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_AMUX_THM3_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm3_100k_pu " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_THERM_100K_PULLUP )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_AMUX_THM2 ] = ADC5_CHAN_TEMP ( " amux_thm2 " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_PM5_SMB_TEMP )
2022-08-05 15:57:26 +02:00
[ ADC5_GPIO1_100K_PU ] = ADC5_CHAN_TEMP ( " gpio1_100k_pu " , 0 ,
SCALE_HW_CALIB_THERM_100K_PULLUP )
[ ADC5_GPIO3_100K_PU ] = ADC5_CHAN_TEMP ( " gpio3_100k_pu " , 0 ,
SCALE_HW_CALIB_THERM_100K_PULLUP )
[ ADC5_GPIO4_100K_PU ] = ADC5_CHAN_TEMP ( " gpio4_100k_pu " , 0 ,
SCALE_HW_CALIB_THERM_100K_PULLUP )
2018-08-02 18:43:53 -07:00
} ;
2020-05-28 22:24:26 +05:30
static const struct adc5_channels adc7_chans_pmic [ ADC5_MAX_CHANNEL ] = {
[ ADC7_REF_GND ] = ADC5_CHAN_VOLT ( " ref_gnd " , 0 ,
SCALE_HW_CALIB_DEFAULT )
[ ADC7_1P25VREF ] = ADC5_CHAN_VOLT ( " vref_1p25 " , 0 ,
SCALE_HW_CALIB_DEFAULT )
[ ADC7_VPH_PWR ] = ADC5_CHAN_VOLT ( " vph_pwr " , 1 ,
SCALE_HW_CALIB_DEFAULT )
[ ADC7_VBAT_SNS ] = ADC5_CHAN_VOLT ( " vbat_sns " , 3 ,
SCALE_HW_CALIB_DEFAULT )
[ ADC7_DIE_TEMP ] = ADC5_CHAN_TEMP ( " die_temp " , 0 ,
SCALE_HW_CALIB_PMIC_THERM_PM7 )
[ ADC7_AMUX_THM1_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm1_pu2 " , 0 ,
SCALE_HW_CALIB_THERM_100K_PU_PM7 )
[ ADC7_AMUX_THM2_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm2_pu2 " , 0 ,
SCALE_HW_CALIB_THERM_100K_PU_PM7 )
[ ADC7_AMUX_THM3_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm3_pu2 " , 0 ,
SCALE_HW_CALIB_THERM_100K_PU_PM7 )
[ ADC7_AMUX_THM4_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm4_pu2 " , 0 ,
SCALE_HW_CALIB_THERM_100K_PU_PM7 )
[ ADC7_AMUX_THM5_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm5_pu2 " , 0 ,
SCALE_HW_CALIB_THERM_100K_PU_PM7 )
[ ADC7_AMUX_THM6_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm6_pu2 " , 0 ,
SCALE_HW_CALIB_THERM_100K_PU_PM7 )
[ ADC7_GPIO1_100K_PU ] = ADC5_CHAN_TEMP ( " gpio1_pu2 " , 0 ,
SCALE_HW_CALIB_THERM_100K_PU_PM7 )
[ ADC7_GPIO2_100K_PU ] = ADC5_CHAN_TEMP ( " gpio2_pu2 " , 0 ,
SCALE_HW_CALIB_THERM_100K_PU_PM7 )
[ ADC7_GPIO3_100K_PU ] = ADC5_CHAN_TEMP ( " gpio3_pu2 " , 0 ,
SCALE_HW_CALIB_THERM_100K_PU_PM7 )
[ ADC7_GPIO4_100K_PU ] = ADC5_CHAN_TEMP ( " gpio4_pu2 " , 0 ,
SCALE_HW_CALIB_THERM_100K_PU_PM7 )
} ;
2018-08-02 18:43:53 -07:00
static const struct adc5_channels adc5_chans_rev2 [ ADC5_MAX_CHANNEL ] = {
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_REF_GND ] = ADC5_CHAN_VOLT ( " ref_gnd " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_1P25VREF ] = ADC5_CHAN_VOLT ( " vref_1p25 " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
2022-08-19 00:18:13 +02:00
[ ADC5_VREF_VADC ] = ADC5_CHAN_VOLT ( " vref_vadc " , 0 ,
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_VPH_PWR ] = ADC5_CHAN_VOLT ( " vph_pwr " , 1 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_VBAT_SNS ] = ADC5_CHAN_VOLT ( " vbat_sns " , 1 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_VCOIN ] = ADC5_CHAN_VOLT ( " vcoin " , 1 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_DEFAULT )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_DIE_TEMP ] = ADC5_CHAN_TEMP ( " die_temp " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_PMIC_THERM )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_AMUX_THM1_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm1_100k_pu " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_THERM_100K_PULLUP )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_AMUX_THM2_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm2_100k_pu " , 0 ,
2018-08-10 12:47:02 -07:00
SCALE_HW_CALIB_THERM_100K_PULLUP )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_AMUX_THM3_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm3_100k_pu " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_THERM_100K_PULLUP )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_AMUX_THM4_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm4_100k_pu " , 0 ,
2018-08-10 12:47:02 -07:00
SCALE_HW_CALIB_THERM_100K_PULLUP )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_AMUX_THM5_100K_PU ] = ADC5_CHAN_TEMP ( " amux_thm5_100k_pu " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_THERM_100K_PULLUP )
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
[ ADC5_XO_THERM_100K_PU ] = ADC5_CHAN_TEMP ( " xo_therm_100k_pu " , 0 ,
2018-08-02 18:43:53 -07:00
SCALE_HW_CALIB_THERM_100K_PULLUP )
} ;
2022-07-15 14:29:00 +02:00
static int adc5_get_fw_channel_data ( struct adc5_chip * adc ,
2018-08-02 18:43:53 -07:00
struct adc5_channel_prop * prop ,
2022-07-15 14:29:00 +02:00
struct fwnode_handle * fwnode ,
2018-08-02 18:43:53 -07:00
const struct adc5_data * data )
{
2022-07-15 14:29:00 +02:00
const char * name = fwnode_get_name ( fwnode ) , * channel_name ;
2018-08-02 18:43:53 -07:00
u32 chan , value , varr [ 2 ] ;
2020-05-28 22:24:26 +05:30
u32 sid = 0 ;
2018-08-02 18:43:53 -07:00
int ret ;
struct device * dev = adc - > dev ;
2022-07-15 14:29:00 +02:00
ret = fwnode_property_read_u32 ( fwnode , " reg " , & chan ) ;
2018-08-02 18:43:53 -07:00
if ( ret ) {
dev_err ( dev , " invalid channel number %s \n " , name ) ;
return ret ;
}
2020-05-28 22:24:26 +05:30
/* Value read from "reg" is virtual channel number */
/* virtual channel number = sid << 8 | channel number */
if ( adc - > data - > info = = & adc7_info ) {
sid = chan > > ADC_CHANNEL_OFFSET ;
chan = chan & ADC_CHANNEL_MASK ;
}
2018-08-27 14:14:53 -07:00
if ( chan > ADC5_PARALLEL_ISENSE_VBAT_IDATA | |
! data - > adc_chans [ chan ] . datasheet_name ) {
2018-08-02 18:43:53 -07:00
dev_err ( dev , " %s invalid channel number %d \n " , name , chan ) ;
return - EINVAL ;
}
/* the channel has DT description */
prop - > channel = chan ;
2020-05-28 22:24:26 +05:30
prop - > sid = sid ;
2018-08-02 18:43:53 -07:00
2022-07-15 14:29:00 +02:00
ret = fwnode_property_read_string ( fwnode , " label " , & channel_name ) ;
if ( ret )
channel_name = name ;
2018-08-02 18:43:53 -07:00
prop - > datasheet_name = channel_name ;
2022-07-15 14:29:00 +02:00
ret = fwnode_property_read_u32 ( fwnode , " qcom,decimation " , & value ) ;
2018-08-02 18:43:53 -07:00
if ( ! ret ) {
2020-12-04 05:54:57 +03:00
ret = qcom_adc5_decimation_from_dt ( value , data - > decimation ) ;
2018-08-02 18:43:53 -07:00
if ( ret < 0 ) {
dev_err ( dev , " %02x invalid decimation %d \n " ,
chan , value ) ;
return ret ;
}
prop - > decimation = ret ;
} else {
prop - > decimation = ADC5_DECIMATION_DEFAULT ;
}
2022-07-15 14:29:00 +02:00
ret = fwnode_property_read_u32_array ( fwnode , " qcom,pre-scaling " , varr , 2 ) ;
2018-08-02 18:43:53 -07:00
if ( ! ret ) {
2020-12-04 05:54:57 +03:00
ret = qcom_adc5_prescaling_from_dt ( varr [ 0 ] , varr [ 1 ] ) ;
2018-08-02 18:43:53 -07:00
if ( ret < 0 ) {
dev_err ( dev , " %02x invalid pre-scaling <%d %d> \n " ,
chan , varr [ 0 ] , varr [ 1 ] ) ;
return ret ;
}
prop - > prescale = ret ;
iio: adc: qcom-spmi-adc5: Initialize prescale properly
adc5_get_dt_data uses a local, prop, feeds it to adc5_get_dt_channel_data,
and then puts the result into adc->chan_props. The problem is
adc5_get_dt_channel_data may not initialize that structure fully, so a
garbage value is used for prescale if the optional "qcom,pre-scaling" is
not defined in DT. adc5_read_raw then uses this as an array index,
generating a crash that looks like this:
[ 6.683186] Unable to handle kernel paging request at virtual address ffffff90e78c7964
Call trace:
qcom_vadc_scale_code_voltage_factor+0x74/0x104
qcom_vadc_scale_hw_calib_die_temp+0x20/0x60
qcom_adc5_hw_scale+0x78/0xa4
adc5_read_raw+0x3d0/0x65c
iio_channel_read+0x240/0x30c
iio_read_channel_processed+0x10c/0x150
qpnp_tm_get_temp+0xc0/0x40c
of_thermal_get_temp+0x7c/0x98
thermal_zone_get_temp+0xac/0xd8
thermal_zone_device_update+0xc0/0x38c
qpnp_tm_probe+0x624/0x81c
platform_drv_probe+0xe4/0x11c
really_probe+0x188/0x3fc
driver_probe_device+0xb8/0x188
__device_attach_driver+0x114/0x180
bus_for_each_drv+0xd8/0x118
__device_attach+0x180/0x27c
device_initial_probe+0x20/0x2c
bus_probe_device+0x78/0x124
deferred_probe_work_func+0xfc/0x138
process_one_work+0x3d8/0x8b0
process_scheduled_works+0x48/0x6c
worker_thread+0x488/0x7cc
kthread+0x24c/0x264
ret_from_fork+0x10/0x18
Unfortunately, when I went to add the initializer for this and tried to
boot it, my machine shut down immediately, complaining that it was
hotter than the sun. It appears that adc5_chans_pmic and adc5_chans_rev2
were initializing prescale_index as if it were directly a divisor,
rather than the index into adc5_prescale_ratios that it is.
Fix the uninitialized value, and change the static initialization to use
indices into adc5_prescale_ratios.
Signed-off-by: Evan Green <evgreen@chromium.org>
Reviewed-by: Matthias Kaehlcke <mka@chromium.org>
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
2018-12-04 11:14:19 -08:00
} else {
prop - > prescale =
adc - > data - > adc_chans [ prop - > channel ] . prescale_index ;
2018-08-02 18:43:53 -07:00
}
2022-07-15 14:29:00 +02:00
ret = fwnode_property_read_u32 ( fwnode , " qcom,hw-settle-time " , & value ) ;
2018-08-02 18:43:53 -07:00
if ( ! ret ) {
u8 dig_version [ 2 ] ;
ret = adc5_read ( adc , ADC5_USR_REVISION1 , dig_version ,
sizeof ( dig_version ) ) ;
2020-05-28 22:24:27 +05:30
if ( ret ) {
2018-08-02 18:43:53 -07:00
dev_err ( dev , " Invalid dig version read %d \n " , ret ) ;
return ret ;
}
2020-05-28 22:24:28 +05:30
dev_dbg ( dev , " dig_ver:minor:%d, major:%d \n " , dig_version [ 0 ] ,
2018-08-02 18:43:53 -07:00
dig_version [ 1 ] ) ;
/* Digital controller >= 5.3 have hw_settle_2 option */
2020-05-28 22:24:26 +05:30
if ( ( dig_version [ 0 ] > = ADC5_HW_SETTLE_DIFF_MINOR & &
dig_version [ 1 ] > = ADC5_HW_SETTLE_DIFF_MAJOR ) | |
adc - > data - > info = = & adc7_info )
2020-12-04 05:54:57 +03:00
ret = qcom_adc5_hw_settle_time_from_dt ( value , data - > hw_settle_2 ) ;
2018-08-02 18:43:53 -07:00
else
2020-12-04 05:54:57 +03:00
ret = qcom_adc5_hw_settle_time_from_dt ( value , data - > hw_settle_1 ) ;
2018-08-02 18:43:53 -07:00
if ( ret < 0 ) {
dev_err ( dev , " %02x invalid hw-settle-time %d us \n " ,
chan , value ) ;
return ret ;
}
prop - > hw_settle_time = ret ;
} else {
prop - > hw_settle_time = VADC_DEF_HW_SETTLE_TIME ;
}
2022-07-15 14:29:00 +02:00
ret = fwnode_property_read_u32 ( fwnode , " qcom,avg-samples " , & value ) ;
2018-08-02 18:43:53 -07:00
if ( ! ret ) {
2020-12-04 05:54:57 +03:00
ret = qcom_adc5_avg_samples_from_dt ( value ) ;
2018-08-02 18:43:53 -07:00
if ( ret < 0 ) {
dev_err ( dev , " %02x invalid avg-samples %d \n " ,
chan , value ) ;
return ret ;
}
prop - > avg_samples = ret ;
} else {
prop - > avg_samples = VADC_DEF_AVG_SAMPLES ;
}
2022-07-15 14:29:00 +02:00
if ( fwnode_property_read_bool ( fwnode , " qcom,ratiometric " ) )
2018-08-02 18:43:53 -07:00
prop - > cal_method = ADC5_RATIOMETRIC_CAL ;
else
prop - > cal_method = ADC5_ABSOLUTE_CAL ;
/*
* Default to using timer calibration . Using a fresh calibration value
* for every conversion will increase the overall time for a request .
*/
prop - > cal_val = ADC5_TIMER_CAL ;
dev_dbg ( dev , " %02x name %s \n " , chan , name ) ;
return 0 ;
}
static const struct adc5_data adc5_data_pmic = {
. full_scale_code_volt = 0x70e4 ,
. full_scale_code_cur = 0x2710 ,
. adc_chans = adc5_chans_pmic ,
2020-05-28 22:24:25 +05:30
. info = & adc5_info ,
2018-08-02 18:43:53 -07:00
. decimation = ( unsigned int [ ADC5_DECIMATION_SAMPLES_MAX ] )
{ 250 , 420 , 840 } ,
. hw_settle_1 = ( unsigned int [ VADC_HW_SETTLE_SAMPLES_MAX ] )
{ 15 , 100 , 200 , 300 , 400 , 500 , 600 , 700 ,
800 , 900 , 1 , 2 , 4 , 6 , 8 , 10 } ,
. hw_settle_2 = ( unsigned int [ VADC_HW_SETTLE_SAMPLES_MAX ] )
{ 15 , 100 , 200 , 300 , 400 , 500 , 600 , 700 ,
1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 } ,
} ;
2020-05-28 22:24:26 +05:30
static const struct adc5_data adc7_data_pmic = {
. full_scale_code_volt = 0x70e4 ,
. adc_chans = adc7_chans_pmic ,
. info = & adc7_info ,
. decimation = ( unsigned int [ ADC5_DECIMATION_SAMPLES_MAX ] )
{ 85 , 340 , 1360 } ,
. hw_settle_2 = ( unsigned int [ VADC_HW_SETTLE_SAMPLES_MAX ] )
{ 15 , 100 , 200 , 300 , 400 , 500 , 600 , 700 ,
1000 , 2000 , 4000 , 8000 , 16000 , 32000 ,
64000 , 128000 } ,
} ;
2018-08-02 18:43:53 -07:00
static const struct adc5_data adc5_data_pmic_rev2 = {
. full_scale_code_volt = 0x4000 ,
. full_scale_code_cur = 0x1800 ,
. adc_chans = adc5_chans_rev2 ,
2020-05-28 22:24:25 +05:30
. info = & adc5_info ,
2018-08-02 18:43:53 -07:00
. decimation = ( unsigned int [ ADC5_DECIMATION_SAMPLES_MAX ] )
{ 256 , 512 , 1024 } ,
. hw_settle_1 = ( unsigned int [ VADC_HW_SETTLE_SAMPLES_MAX ] )
{ 0 , 100 , 200 , 300 , 400 , 500 , 600 , 700 ,
800 , 900 , 1 , 2 , 4 , 6 , 8 , 10 } ,
. hw_settle_2 = ( unsigned int [ VADC_HW_SETTLE_SAMPLES_MAX ] )
{ 15 , 100 , 200 , 300 , 400 , 500 , 600 , 700 ,
1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 } ,
} ;
static const struct of_device_id adc5_match_table [ ] = {
{
. compatible = " qcom,spmi-adc5 " ,
. data = & adc5_data_pmic ,
} ,
2020-05-28 22:24:26 +05:30
{
. compatible = " qcom,spmi-adc7 " ,
. data = & adc7_data_pmic ,
} ,
2018-08-02 18:43:53 -07:00
{
. compatible = " qcom,spmi-adc-rev2 " ,
. data = & adc5_data_pmic_rev2 ,
} ,
{ }
} ;
2019-04-16 16:49:27 -07:00
MODULE_DEVICE_TABLE ( of , adc5_match_table ) ;
2018-08-02 18:43:53 -07:00
2022-07-15 14:29:00 +02:00
static int adc5_get_fw_data ( struct adc5_chip * adc )
2018-08-02 18:43:53 -07:00
{
const struct adc5_channels * adc_chan ;
struct iio_chan_spec * iio_chan ;
struct adc5_channel_prop prop , * chan_props ;
2022-07-15 14:29:00 +02:00
struct fwnode_handle * child ;
2018-08-02 18:43:53 -07:00
unsigned int index = 0 ;
int ret ;
2022-07-15 14:29:00 +02:00
adc - > nchannels = device_get_child_node_count ( adc - > dev ) ;
2018-08-02 18:43:53 -07:00
if ( ! adc - > nchannels )
return - EINVAL ;
adc - > iio_chans = devm_kcalloc ( adc - > dev , adc - > nchannels ,
sizeof ( * adc - > iio_chans ) , GFP_KERNEL ) ;
if ( ! adc - > iio_chans )
return - ENOMEM ;
adc - > chan_props = devm_kcalloc ( adc - > dev , adc - > nchannels ,
sizeof ( * adc - > chan_props ) , GFP_KERNEL ) ;
if ( ! adc - > chan_props )
return - ENOMEM ;
chan_props = adc - > chan_props ;
iio_chan = adc - > iio_chans ;
2022-07-15 14:29:00 +02:00
adc - > data = device_get_match_data ( adc - > dev ) ;
2020-12-04 05:55:00 +03:00
if ( ! adc - > data )
adc - > data = & adc5_data_pmic ;
2018-08-02 18:43:53 -07:00
2022-07-15 14:29:00 +02:00
device_for_each_child_node ( adc - > dev , child ) {
ret = adc5_get_fw_channel_data ( adc , & prop , child , adc - > data ) ;
2018-08-02 18:43:53 -07:00
if ( ret ) {
2022-07-15 14:29:00 +02:00
fwnode_handle_put ( child ) ;
2018-08-02 18:43:53 -07:00
return ret ;
}
prop . scale_fn_type =
2020-12-04 05:55:00 +03:00
adc - > data - > adc_chans [ prop . channel ] . scale_fn_type ;
2018-08-02 18:43:53 -07:00
* chan_props = prop ;
2020-12-04 05:55:00 +03:00
adc_chan = & adc - > data - > adc_chans [ prop . channel ] ;
2018-08-02 18:43:53 -07:00
iio_chan - > channel = prop . channel ;
iio_chan - > datasheet_name = prop . datasheet_name ;
iio_chan - > extend_name = prop . datasheet_name ;
iio_chan - > info_mask_separate = adc_chan - > info_mask ;
iio_chan - > type = adc_chan - > type ;
iio_chan - > address = index ;
iio_chan + + ;
chan_props + + ;
index + + ;
}
return 0 ;
}
static int adc5_probe ( struct platform_device * pdev )
{
struct device * dev = & pdev - > dev ;
struct iio_dev * indio_dev ;
struct adc5_chip * adc ;
struct regmap * regmap ;
int ret , irq_eoc ;
u32 reg ;
regmap = dev_get_regmap ( dev - > parent , NULL ) ;
if ( ! regmap )
return - ENODEV ;
2022-07-15 14:29:00 +02:00
ret = device_property_read_u32 ( dev , " reg " , & reg ) ;
2018-08-02 18:43:53 -07:00
if ( ret < 0 )
return ret ;
indio_dev = devm_iio_device_alloc ( dev , sizeof ( * adc ) ) ;
if ( ! indio_dev )
return - ENOMEM ;
adc = iio_priv ( indio_dev ) ;
adc - > regmap = regmap ;
adc - > dev = dev ;
adc - > base = reg ;
2020-05-28 22:24:26 +05:30
2018-08-02 18:43:53 -07:00
init_completion ( & adc - > complete ) ;
mutex_init ( & adc - > lock ) ;
2022-07-15 14:29:00 +02:00
ret = adc5_get_fw_data ( adc ) ;
2022-12-16 20:09:45 +01:00
if ( ret )
return dev_err_probe ( dev , ret , " adc get dt data failed \n " ) ;
2018-08-02 18:43:53 -07:00
irq_eoc = platform_get_irq ( pdev , 0 ) ;
if ( irq_eoc < 0 ) {
if ( irq_eoc = = - EPROBE_DEFER | | irq_eoc = = - EINVAL )
return irq_eoc ;
adc - > poll_eoc = true ;
} else {
ret = devm_request_irq ( dev , irq_eoc , adc5_isr , 0 ,
" pm-adc5 " , adc ) ;
if ( ret )
return ret ;
}
indio_dev - > name = pdev - > name ;
indio_dev - > modes = INDIO_DIRECT_MODE ;
2020-05-28 22:24:25 +05:30
indio_dev - > info = adc - > data - > info ;
2018-08-02 18:43:53 -07:00
indio_dev - > channels = adc - > iio_chans ;
indio_dev - > num_channels = adc - > nchannels ;
return devm_iio_device_register ( dev , indio_dev ) ;
}
static struct platform_driver adc5_driver = {
. driver = {
2020-09-10 16:59:51 +03:00
. name = " qcom-spmi-adc5 " ,
2018-08-02 18:43:53 -07:00
. of_match_table = adc5_match_table ,
} ,
. probe = adc5_probe ,
} ;
module_platform_driver ( adc5_driver ) ;
MODULE_ALIAS ( " platform:qcom-spmi-adc5 " ) ;
MODULE_DESCRIPTION ( " Qualcomm Technologies Inc. PMIC5 ADC driver " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;