iio: pressure: dps310: Reset chip if MEAS_CFG is corrupt
Subsystems (2)
Eddie James
maintainerv4 cover iio: pressure: dps310: Reset chip if MEAS_CFG is corrupt
Corruption of the MEAS_CFG register has been observed soon after system boot. In order to recover this scenario, check MEAS_CFG if measurement isn't ready, and if it's incorrect, reset the DPS310 and execute the startup procedure. Include a patch to move the startup procedure into a function.
Changes since v3:
- Don't check regmap* return codes for < 0
- Fix comment spelling
Changes since v2:
- Add some comments
- Fix the clunky control flow
Changes since v1:
- Separate into two patches
- Rename 'dps310_verify_meas_cfg' to 'dps310_check_reset_meas_cfg'
Eddie James (2):
iio: pressure: dps310: Refactor startup procedure
iio: pressure: dps310: Reset chip if MEAS_CFG is corrupt
drivers/iio/pressure/dps310.c | 276 +++++++++++++++++++++------------- 1 file changed, 172 insertions(+), 104 deletions(-)
Signature · 1 line
2.31.1
Eddie James
maintainerPATCH v4 1/2 iio: pressure: dps310: Refactor startup procedure
Move the startup procedure into a function, and correct a missing check on the return code for writing the PRS_CFG register.
--- drivers/iio/pressure/dps310.c | 188 ++++++++++++++++++---------------- 1 file changed, 99 insertions(+), 89 deletions(-)
drivers/iio/pressure/dps310.c +99 -89
@@ -159,6 +159,102 @@ static int dps310_get_coefs(struct dps310_data *data)return 0 ; } +/* +* Some versions of the chip will read temperatures in the ~60C range when +* it's actually ~20C. This is the manufacturer recommended workaround +* to correct the issue. The registers used below are undocumented. +*/ +static int dps310_temp_workaround (struct dps310_data *data) +{ +int rc; +int reg; + + rc =regmap_read (data->regmap,0x32 , ®); +if (rc) +return rc; + +/* +* If bit 1 is set then the device is okay, and the workaround does not +* need to be applied +*/ +if (reg &BIT (1 )) +return 0 ; + + rc =regmap_write (data->regmap,0x0e ,0xA5 ); +if (rc) +return rc; + + rc =regmap_write (data->regmap,0x0f ,0x96 ); +if (rc) +return rc; + + rc =regmap_write (data->regmap,0x62 ,0x02 ); +if (rc) +return rc; + + rc =regmap_write (data->regmap,0x0e ,0x00 ); +if (rc) +return rc; + +return regmap_write (data->regmap,0x0f ,0x00 ); +} + +static int dps310_startup (struct dps310_data *data) +{ +int rc; +int ready; + +/* +* Set up pressure sensor in single sample, one measurement per second +* mode +*/ + rc =regmap_write (data->regmap,DPS310_PRS_CFG ,0 ); +if (rc) +return rc; + +/* +* Set up external (MEMS) temperature sensor in single sample, one +* measurement per second mode +*/ + rc =regmap_write (data->regmap,DPS310_TMP_CFG ,DPS310_TMP_EXT ); +if (rc) +return rc; + +/* Temp and pressure shifts are disabled when PRC <= 8 */ + rc =regmap_write_bits (data->regmap,DPS310_CFG_REG , +DPS310_PRS_SHIFT_EN |DPS310_TMP_SHIFT_EN ,0 ); +if (rc) +return rc; + +/* MEAS_CFG doesn't update correctly unless first written with 0 */ + rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , +DPS310_MEAS_CTRL_BITS ,0 ); +if (rc) +return rc; + +/* Turn on temperature and pressure measurement in the background */ + rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , +DPS310_MEAS_CTRL_BITS ,DPS310_PRS_EN | +DPS310_TEMP_EN |DPS310_BACKGROUND ); +if (rc) +return rc; + +/* +* Calibration coefficients required for reporting temperature. +* They are available 40ms after the device has started +*/ + rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , ready, + ready &DPS310_COEF_RDY ,10000 ,40000 ); +if (rc) +return rc; + + rc =dps310_get_coefs (data); +if (rc) +return rc; + +return dps310_temp_workaround (data); +} +static int dps310_get_pres_precision (struct dps310_data *data) {int rc;
@@ -677,52 +773,12 @@ static const struct iio_info dps310_info = { .write_raw = dps310_write_raw, }; -/* -* Some verions of chip will read temperatures in the ~60C range when -* its actually ~20C. This is the manufacturer recommended workaround -* to correct the issue. The registers used below are undocumented. -*/ -static int dps310_temp_workaround (struct dps310_data *data) -{ -int rc; -int reg; - - rc =regmap_read (data->regmap,0x32 , ®); -if (rc <0 ) -return rc; - -/* -* If bit 1 is set then the device is okay, and the workaround does not -* need to be applied -*/ -if (reg &BIT (1 )) -return 0 ; - - rc =regmap_write (data->regmap,0x0e ,0xA5 ); -if (rc <0 ) -return rc; - - rc =regmap_write (data->regmap,0x0f ,0x96 ); -if (rc <0 ) -return rc; - - rc =regmap_write (data->regmap,0x62 ,0x02 ); -if (rc <0 ) -return rc; - - rc =regmap_write (data->regmap,0x0e ,0x00 ); -if (rc <0 ) -return rc; - -return regmap_write (data->regmap,0x0f ,0x00 ); -} -static int dps310_probe (struct i2c_client *client,const struct i2c_device_id *id) {struct dps310_data *data;struct iio_dev *iio; -int rc, ready; +int rc; iio =devm_iio_device_alloc (&client->dev,sizeof (*data));if (!iio)
@@ -747,54 +803,8 @@ static int dps310_probe(struct i2c_client *client,if (rc)return rc; -/* -* Set up pressure sensor in single sample, one measurement per second -* mode -*/ - rc =regmap_write (data->regmap,DPS310_PRS_CFG ,0 ); - -/* -* Set up external (MEMS) temperature sensor in single sample, one -* measurement per second mode -*/ - rc =regmap_write (data->regmap,DPS310_TMP_CFG ,DPS310_TMP_EXT ); -if (rc <0 ) -return rc; - -/* Temp and pressure shifts are disabled when PRC <= 8 */ - rc =regmap_write_bits (data->regmap,DPS310_CFG_REG , -DPS310_PRS_SHIFT_EN |DPS310_TMP_SHIFT_EN ,0 ); -if (rc <0 ) -return rc; - -/* MEAS_CFG doesn't update correctly unless first written with 0 */ - rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , -DPS310_MEAS_CTRL_BITS ,0 ); -if (rc <0 ) -return rc; - -/* Turn on temperature and pressure measurement in the background */ - rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , -DPS310_MEAS_CTRL_BITS ,DPS310_PRS_EN | -DPS310_TEMP_EN |DPS310_BACKGROUND ); -if (rc <0 ) -return rc; - -/* -* Calibration coefficients required for reporting temperature. -* They are available 40ms after the device has started -*/ - rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , ready, - ready &DPS310_COEF_RDY ,10000 ,40000 ); -if (rc <0 ) -return rc; - - rc =dps310_get_coefs (data); -if (rc <0 ) -return rc; - - rc =dps310_temp_workaround (data); -if (rc <0 ) + rc =dps310_startup (data); +if (rc)return rc; rc =devm_iio_device_register (&client->dev, iio);
Signature · 1 line
2.31.1
Re: [PATCH v4 1/2] iio: pressure: dps310: Refactor startup procedure
Quoted 3 lines · Eddie James
Move the startup procedure into a function, and correct a missing check on the return code for writing the
PRS_CFGregister.
Code looks good, one remark below.
Quoted 32 lines
Signed-off-by Eddie James <[email protected]>Reviewed-by Joel Stanley <[email protected]>--- drivers/iio/pressure/dps310.c | 188 ++++++++++++++++++---------------- 1 file changed, 99 insertions(+), 89 deletions(-)drivers/iio/pressure/dps310.c +18
-0@@ -159,6 +159,102 @@ static int dps310_get_coefs(struct dps310_data *data)return 0 ; } +/* +* Some versions of the chip will read temperatures in the ~60C range when +* it's actually ~20C. This is the manufacturer recommended workaround +* to correct the issue. The registers used below are undocumented. +*/ +static int dps310_temp_workaround (struct dps310_data *data) +{ +int rc; +int reg; + + rc =regmap_read (data->regmap,0x32 , ®); +if (rc) +return rc; + +/* +* If bit 1 is set then the device is okay, and the workaround does not +* need to be applied +*/
drivers/iio/pressure/dps310.c static int dps310_get_coefs(struct dps310_data *data) · line 189
Quoted 10 lines
drivers/iio/pressure/dps310.c +10
-0+if (reg &BIT (1 )) +return 0 ; + + rc =regmap_write (data->regmap,0x0e ,0xA5 ); +if (rc) +return rc; + + rc =regmap_write (data->regmap,0x0f ,0x96 ); +if (rc) +return rc;
This code already exists, but still want to ask, is it really byte-registers here and not be16/le16 one? In such a case perhaps bulk write can be used to reflect it better?
drivers/iio/pressure/dps310.c static int dps310_get_coefs(struct dps310_data *data) · line 199
Quoted 9 lines
drivers/iio/pressure/dps310.c +9
-0+ rc =regmap_write (data->regmap,0x62 ,0x02 ); +if (rc) +return rc; + + rc =regmap_write (data->regmap,0x0e ,0x00 ); +if (rc) +return rc; + +return regmap_write (data->regmap,0x0f ,0x00 );
Ditto.
Quoted 175 lines
drivers/iio/pressure/dps310.c +61
-90+} + +static int dps310_startup (struct dps310_data *data) +{ +int rc; +int ready; + +/* +* Set up pressure sensor in single sample, one measurement per second +* mode +*/ + rc =regmap_write (data->regmap,DPS310_PRS_CFG ,0 ); +if (rc) +return rc; + +/* +* Set up external (MEMS) temperature sensor in single sample, one +* measurement per second mode +*/ + rc =regmap_write (data->regmap,DPS310_TMP_CFG ,DPS310_TMP_EXT ); +if (rc) +return rc; + +/* Temp and pressure shifts are disabled when PRC <= 8 */ + rc =regmap_write_bits (data->regmap,DPS310_CFG_REG , +DPS310_PRS_SHIFT_EN |DPS310_TMP_SHIFT_EN ,0 ); +if (rc) +return rc; + +/* MEAS_CFG doesn't update correctly unless first written with 0 */ + rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , +DPS310_MEAS_CTRL_BITS ,0 ); +if (rc) +return rc; + +/* Turn on temperature and pressure measurement in the background */ + rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , +DPS310_MEAS_CTRL_BITS ,DPS310_PRS_EN | +DPS310_TEMP_EN |DPS310_BACKGROUND ); +if (rc) +return rc; + +/* +* Calibration coefficients required for reporting temperature. +* They are available 40ms after the device has started +*/ + rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , ready, + ready &DPS310_COEF_RDY ,10000 ,40000 ); +if (rc) +return rc; + + rc =dps310_get_coefs (data); +if (rc) +return rc; + +return dps310_temp_workaround (data); +} +static int dps310_get_pres_precision (struct dps310_data *data) {int rc;@@ -677,52 +773,12 @@ static const struct iio_info dps310_info = { .write_raw = dps310_write_raw, }; -/* -* Some verions of chip will read temperatures in the ~60C range when -* its actually ~20C. This is the manufacturer recommended workaround -* to correct the issue. The registers used below are undocumented. -*/ -static int dps310_temp_workaround (struct dps310_data *data) -{ -int rc; -int reg; - - rc =regmap_read (data->regmap,0x32 , ®); -if (rc <0 ) -return rc; - -/* -* If bit 1 is set then the device is okay, and the workaround does not -* need to be applied -*/ -if (reg &BIT (1 )) -return 0 ; - - rc =regmap_write (data->regmap,0x0e ,0xA5 ); -if (rc <0 ) -return rc; - - rc =regmap_write (data->regmap,0x0f ,0x96 ); -if (rc <0 ) -return rc; - - rc =regmap_write (data->regmap,0x62 ,0x02 ); -if (rc <0 ) -return rc; - - rc =regmap_write (data->regmap,0x0e ,0x00 ); -if (rc <0 ) -return rc; - -return regmap_write (data->regmap,0x0f ,0x00 ); -} -static int dps310_probe (struct i2c_client *client,const struct i2c_device_id *id) {struct dps310_data *data;struct iio_dev *iio; -int rc, ready; +int rc; iio =devm_iio_device_alloc (&client->dev,sizeof (*data));if (!iio)@@ -747,54 +803,8 @@ static int dps310_probe(struct i2c_client *client,if (rc)return rc; -/* -* Set up pressure sensor in single sample, one measurement per second -* mode -*/ - rc =regmap_write (data->regmap,DPS310_PRS_CFG ,0 ); - -/* -* Set up external (MEMS) temperature sensor in single sample, one -* measurement per second mode -*/ - rc =regmap_write (data->regmap,DPS310_TMP_CFG ,DPS310_TMP_EXT ); -if (rc <0 ) -return rc; - -/* Temp and pressure shifts are disabled when PRC <= 8 */ - rc =regmap_write_bits (data->regmap,DPS310_CFG_REG , -DPS310_PRS_SHIFT_EN |DPS310_TMP_SHIFT_EN ,0 ); -if (rc <0 ) -return rc; - -/* MEAS_CFG doesn't update correctly unless first written with 0 */ - rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , -DPS310_MEAS_CTRL_BITS ,0 ); -if (rc <0 ) -return rc; - -/* Turn on temperature and pressure measurement in the background */ - rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , -DPS310_MEAS_CTRL_BITS ,DPS310_PRS_EN | -DPS310_TEMP_EN |DPS310_BACKGROUND ); -if (rc <0 ) -return rc; - -/* -* Calibration coefficients required for reporting temperature. -* They are available 40ms after the device has started -*/ - rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , ready, - ready &DPS310_COEF_RDY ,10000 ,40000 ); -if (rc <0 ) -return rc; - - rc =dps310_get_coefs (data); -if (rc <0 ) -return rc; - - rc =dps310_temp_workaround (data); -if (rc <0 ) + rc =dps310_startup (data); +if (rc)return rc; rc =devm_iio_device_register (&client->dev, iio); --2.31.1
Signature · 2 lines
With Best Regards, Andy Shevchenko
Eddie James
maintainerRe: [PATCH v4 1/2] iio: pressure: dps310: Refactor startup procedure
Quoted 43 lines · Andy Shevchenko
Quoted 2 lines · Eddie James
Move the startup procedure into a function, and correct a missing check on the return code for writing the
PRS_CFGregister.Code looks good, one remark below.
Reviewed-by Andy Shevchenko <[email protected]>Quoted 37 lines
Signed-off-by Eddie James <[email protected]>Reviewed-by Joel Stanley <[email protected]>--- drivers/iio/pressure/dps310.c | 188 ++++++++++++++++++---------------- 1 file changed, 99 insertions(+), 89 deletions(-)drivers/iio/pressure/dps310.c +23
-0@@ -159,6 +159,102 @@ static int dps310_get_coefs(struct dps310_data *data)return 0 ; } +/* +* Some versions of the chip will read temperatures in the ~60C range when +* it's actually ~20C. This is the manufacturer recommended workaround +* to correct the issue. The registers used below are undocumented. +*/ +static int dps310_temp_workaround (struct dps310_data *data) +{ +int rc; +int reg; + + rc =regmap_read (data->regmap,0x32 , ®); +if (rc) +return rc; + +/* +* If bit 1 is set then the device is okay, and the workaround does not +* need to be applied +*/ +if (reg &BIT (1 )) +return 0 ; + + rc =regmap_write (data->regmap,0x0e ,0xA5 ); +if (rc)
Quoted 8 lines
drivers/iio/pressure/dps310.c static int dps310_get_coefs(struct dps310_data *data) · line 189
Quoted 5 lines
drivers/iio/pressure/dps310.c +5
-0+return rc; + + rc =regmap_write (data->regmap,0x0f ,0x96 ); +if (rc) +return rc;This code already exists, but still want to ask, is it really byte-registers here and not be16/le16 one? In such a case perhaps bulk write can be used to reflect it better?
The temperature and pressure regs are 24 bits big endian, and all the rest are 8 bits. I think the existing approach is best.
Thanks Andy!
Quoted 188 lines
drivers/iio/pressure/dps310.c static int dps310_get_coefs(struct dps310_data *data) · line 199
Quoted 10 lines
drivers/iio/pressure/dps310.c +9
-0+ rc =regmap_write (data->regmap,0x62 ,0x02 ); +if (rc) +return rc; + + rc =regmap_write (data->regmap,0x0e ,0x00 ); +if (rc) +return rc; + +return regmap_write (data->regmap,0x0f ,0x00 );Ditto.
Quoted 175 lines
drivers/iio/pressure/dps310.c +61
-90+} + +static int dps310_startup (struct dps310_data *data) +{ +int rc; +int ready; + +/* +* Set up pressure sensor in single sample, one measurement per second +* mode +*/ + rc =regmap_write (data->regmap,DPS310_PRS_CFG ,0 ); +if (rc) +return rc; + +/* +* Set up external (MEMS) temperature sensor in single sample, one +* measurement per second mode +*/ + rc =regmap_write (data->regmap,DPS310_TMP_CFG ,DPS310_TMP_EXT ); +if (rc) +return rc; + +/* Temp and pressure shifts are disabled when PRC <= 8 */ + rc =regmap_write_bits (data->regmap,DPS310_CFG_REG , +DPS310_PRS_SHIFT_EN |DPS310_TMP_SHIFT_EN ,0 ); +if (rc) +return rc; + +/* MEAS_CFG doesn't update correctly unless first written with 0 */ + rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , +DPS310_MEAS_CTRL_BITS ,0 ); +if (rc) +return rc; + +/* Turn on temperature and pressure measurement in the background */ + rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , +DPS310_MEAS_CTRL_BITS ,DPS310_PRS_EN | +DPS310_TEMP_EN |DPS310_BACKGROUND ); +if (rc) +return rc; + +/* +* Calibration coefficients required for reporting temperature. +* They are available 40ms after the device has started +*/ + rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , ready, + ready &DPS310_COEF_RDY ,10000 ,40000 ); +if (rc) +return rc; + + rc =dps310_get_coefs (data); +if (rc) +return rc; + +return dps310_temp_workaround (data); +} +static int dps310_get_pres_precision (struct dps310_data *data) {int rc;@@ -677,52 +773,12 @@ static const struct iio_info dps310_info = { .write_raw = dps310_write_raw, }; -/* -* Some verions of chip will read temperatures in the ~60C range when -* its actually ~20C. This is the manufacturer recommended workaround -* to correct the issue. The registers used below are undocumented. -*/ -static int dps310_temp_workaround (struct dps310_data *data) -{ -int rc; -int reg; - - rc =regmap_read (data->regmap,0x32 , ®); -if (rc <0 ) -return rc; - -/* -* If bit 1 is set then the device is okay, and the workaround does not -* need to be applied -*/ -if (reg &BIT (1 )) -return 0 ; - - rc =regmap_write (data->regmap,0x0e ,0xA5 ); -if (rc <0 ) -return rc; - - rc =regmap_write (data->regmap,0x0f ,0x96 ); -if (rc <0 ) -return rc; - - rc =regmap_write (data->regmap,0x62 ,0x02 ); -if (rc <0 ) -return rc; - - rc =regmap_write (data->regmap,0x0e ,0x00 ); -if (rc <0 ) -return rc; - -return regmap_write (data->regmap,0x0f ,0x00 ); -} -static int dps310_probe (struct i2c_client *client,const struct i2c_device_id *id) {struct dps310_data *data;struct iio_dev *iio; -int rc, ready; +int rc; iio =devm_iio_device_alloc (&client->dev,sizeof (*data));if (!iio)@@ -747,54 +803,8 @@ static int dps310_probe(struct i2c_client *client,if (rc)return rc; -/* -* Set up pressure sensor in single sample, one measurement per second -* mode -*/ - rc =regmap_write (data->regmap,DPS310_PRS_CFG ,0 ); - -/* -* Set up external (MEMS) temperature sensor in single sample, one -* measurement per second mode -*/ - rc =regmap_write (data->regmap,DPS310_TMP_CFG ,DPS310_TMP_EXT ); -if (rc <0 ) -return rc; - -/* Temp and pressure shifts are disabled when PRC <= 8 */ - rc =regmap_write_bits (data->regmap,DPS310_CFG_REG , -DPS310_PRS_SHIFT_EN |DPS310_TMP_SHIFT_EN ,0 ); -if (rc <0 ) -return rc; - -/* MEAS_CFG doesn't update correctly unless first written with 0 */ - rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , -DPS310_MEAS_CTRL_BITS ,0 ); -if (rc <0 ) -return rc; - -/* Turn on temperature and pressure measurement in the background */ - rc =regmap_write_bits (data->regmap,DPS310_MEAS_CFG , -DPS310_MEAS_CTRL_BITS ,DPS310_PRS_EN | -DPS310_TEMP_EN |DPS310_BACKGROUND ); -if (rc <0 ) -return rc; - -/* -* Calibration coefficients required for reporting temperature. -* They are available 40ms after the device has started -*/ - rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , ready, - ready &DPS310_COEF_RDY ,10000 ,40000 ); -if (rc <0 ) -return rc; - - rc =dps310_get_coefs (data); -if (rc <0 ) -return rc; - - rc =dps310_temp_workaround (data); -if (rc <0 ) + rc =dps310_startup (data); +if (rc)return rc; rc =devm_iio_device_register (&client->dev, iio); --2.31.1
Re: [PATCH v4 1/2] iio: pressure: dps310: Refactor startup procedure
Quoted 2 lines · Eddie James
Quoted 1 line · Andy Shevchenko
On Wed, Aug 10, 2022 at 12:12 AM Eddie James <[email protected]> wrote:
...
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/iio/pressure/dps310.c +7
-0+ rc =regmap_write (data->regmap,0x0e ,0xA5 ); +if (rc) +return rc; + + rc =regmap_write (data->regmap,0x0f ,0x96 ); +if (rc) +return rc;
Quoted 6 lines
Quoted 3 lines
This code already exists, but still want to ask, is it really byte-registers here and not be16/le16 one? In such a case perhaps bulk write can be used to reflect it better?
The temperature and pressure regs are 24 bits big endian, and all the rest are 8 bits. I think the existing approach is best.
It doesn't look like you got what I was meaning... Or I misunderstood what you said.
The code above writes two byte values to two sequential registers which make me think that they are 16-bit registers at offset 0x0e.
...
Quoted 5 lines
Quoted 5 lines
drivers/iio/pressure/dps310.c static int dps310_get_coefs(struct dps310_data *data) · line 199
Quoted 5 lines
drivers/iio/pressure/dps310.c +5
-0+ rc =regmap_write (data->regmap,0x0e ,0x00 ); +if (rc) +return rc; + +return regmap_write (data->regmap,0x0f ,0x00 );
Ditto.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Jonathan Cameron
maintainerRe: [PATCH v4 1/2] iio: pressure: dps310: Refactor startup procedure
Quoted 17 lines · On Fri, 19 Aug 2022 12:42:00 +0300 Andy Shevchenko <[email protected]>…
Quoted 2 lines · Eddie James
Quoted 1 line · Andy Shevchenko
On Wed, Aug 10, 2022 at 12:12 AM Eddie James <[email protected]> wrote:
...
Quoted 11 lines
Quoted 10 lines
drivers/iio/pressure/dps310.c static int dps310_get_coefs(struct dps310_data *data) · line 189
Quoted 7 lines
drivers/iio/pressure/dps310.c +7
-0+ rc =regmap_write (data->regmap,0x0e ,0xA5 ); +if (rc) +return rc; + + rc =regmap_write (data->regmap,0x0f ,0x96 ); +if (rc) +return rc;This code already exists, but still want to ask, is it really byte-registers here and not be16/le16 one? In such a case perhaps bulk write can be used to reflect it better?
Quoted 8 lines
Quoted 2 lines
The temperature and pressure regs are 24 bits big endian, and all the rest are 8 bits. I think the existing approach is best.
It doesn't look like you got what I was meaning... Or I misunderstood what you said.
The code above writes two byte values to two sequential registers which make me think that they are 16-bit registers at offset
0x0e.
Given they are undocumented, this is guessing territory. Probably best to just leave them as is.
You could do a bulk write on an array though as that implies nothing about what's in the registers -just that they happen to be next to each other.
Quoted 11 lines
...
Quoted 5 lines
Quoted 5 lines
drivers/iio/pressure/dps310.c static int dps310_get_coefs(struct dps310_data *data) · line 199
Quoted 5 lines
drivers/iio/pressure/dps310.c +5
-0+ rc =regmap_write (data->regmap,0x0e ,0x00 ); +if (rc) +return rc; + +return regmap_write (data->regmap,0x0f ,0x00 );Ditto.
Eddie James
maintainerRe: [PATCH v4 1/2] iio: pressure: dps310: Refactor startup procedure
Quoted 23 lines · Jonathan Cameron
Quoted 20 lines · On Fri, 19 Aug 2022 12:42:00 +0300 Andy Shevchenko <[email protected]>…
Quoted 2 lines · Eddie James
Quoted 1 line · Andy Shevchenko
On Wed, Aug 10, 2022 at 12:12 AM Eddie James <[email protected]> wrote:
...
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/iio/pressure/dps310.c +7
-0+ rc =regmap_write (data->regmap,0x0e ,0xA5 ); +if (rc) +return rc; + + rc =regmap_write (data->regmap,0x0f ,0x96 ); +if (rc) +return rc;Quoted 5 lines
Quoted 3 lines
This code already exists, but still want to ask, is it really byte-registers here and not be16/le16 one? In such a case perhaps bulk write can be used to reflect it better?
The temperature and pressure regs are 24 bits big endian, and all the rest are 8 bits. I think the existing approach is best.
It doesn't look like you got what I was meaning... Or I misunderstood what you said.
Quoted 7 lines
Quoted 2 lines
The code above writes two byte values to two sequential registers which make me think that they are 16-bit registers at offset
0x0e.Given they are undocumented, this is guessing territory. Probably best to just leave them as is.
You could do a bulk write on an array though as that implies nothing about what's in the registers -just that they happen to be next to each other.
Indeed. Is it worth it to switch to bulk write for two 2-byte writes? I'm inclined to say no and will leave this as-is for v6, but if you think it is, I can switch it.
Thanks,
Eddie
Quoted 10 lines
Quoted 10 lines
...
Quoted 5 lines
Quoted 5 lines
drivers/iio/pressure/dps310.c static int dps310_get_coefs(struct dps310_data *data) · line 199
Quoted 5 lines
drivers/iio/pressure/dps310.c +5
-0+ rc =regmap_write (data->regmap,0x0e ,0x00 ); +if (rc) +return rc; + +return regmap_write (data->regmap,0x0f ,0x00 );Ditto.
Jonathan Cameron
maintainerRe: [PATCH v4 1/2] iio: pressure: dps310: Refactor startup procedure
Quoted 33 lines · On Tue, 6 Sep 2022 14:48:20 -0500 Eddie James <[email protected]> wrote:
Quoted 23 lines · Jonathan Cameron
Quoted 20 lines · On Fri, 19 Aug 2022 12:42:00 +0300 Andy Shevchenko <[email protected]>…
Quoted 2 lines · Eddie James
Quoted 1 line · Andy Shevchenko
On Wed, Aug 10, 2022 at 12:12 AM Eddie James <[email protected]> wrote:
...
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
drivers/iio/pressure/dps310.c +7
-0+ rc =regmap_write (data->regmap,0x0e ,0xA5 ); +if (rc) +return rc; + + rc =regmap_write (data->regmap,0x0f ,0x96 ); +if (rc) +return rc;Quoted 5 lines
Quoted 3 lines
This code already exists, but still want to ask, is it really byte-registers here and not be16/le16 one? In such a case perhaps bulk write can be used to reflect it better?
The temperature and pressure regs are 24 bits big endian, and all the rest are 8 bits. I think the existing approach is best.
It doesn't look like you got what I was meaning... Or I misunderstood what you said.
Quoted 7 lines
Quoted 2 lines
The code above writes two byte values to two sequential registers which make me think that they are 16-bit registers at offset
0x0e.Given they are undocumented, this is guessing territory. Probably best to just leave them as is.
You could do a bulk write on an array though as that implies nothing about what's in the registers -just that they happen to be next to each other.
Quoted 4 lines
Indeed. Is it worth it to switch to bulk write for two 2-byte writes? I'm inclined to say no and will leave this as-is for v6, but if you think it is, I can switch it.
As far as I'm concerned, fine either way.
Jonathan
Quoted 16 lines
Thanks,
Eddie
Quoted 10 lines
Quoted 10 lines
...
Quoted 5 lines
Quoted 5 lines
drivers/iio/pressure/dps310.c static int dps310_get_coefs(struct dps310_data *data) · line 199
Quoted 5 lines
drivers/iio/pressure/dps310.c +5
-0+ rc =regmap_write (data->regmap,0x0e ,0x00 ); +if (rc) +return rc; + +return regmap_write (data->regmap,0x0f ,0x00 );Ditto.
Eddie James
maintainerPATCH v4 2/2 iio: pressure: dps310: Reset chip if MEAS_CFG is corrupt
In reply to Eddie JamesCorruption of the MEAS_CFG register has been observed soon after system boot. In order to recover this scenario, check MEAS_CFG if measurement isn't ready, and if it's incorrect, reset the DPS310 and execute the startup procedure.
--- drivers/iio/pressure/dps310.c | 88 +++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 15 deletions(-)
drivers/iio/pressure/dps310.c +73 -15
@@ -393,6 +393,44 @@ static int dps310_get_temp_k(struct dps310_data *data)return scale_factors[ilog2 (rc)]; } +/* +* Called with lock held. Returns a negative value on error, a positive value +* when the device is not ready, and zero when the device is ready. +*/ +static int dps310_check_reset_meas_cfg (struct dps310_data *data,int ready_bit) +{ +int meas_cfg; +int rc =regmap_read (data->regmap,DPS310_MEAS_CFG , &meas_cfg); + +if (rc <0 ) +return rc; + +/* Device is ready, proceed to measurement */ +if (meas_cfg & ready_bit) +return 0 ; + +/* Device is OK, just not ready */ +if (meas_cfg & (DPS310_PRS_EN |DPS310_TEMP_EN |DPS310_BACKGROUND )) +return 1 ; + +/* DPS310 register state corrupt, better start from scratch */ + rc =regmap_write (data->regmap,DPS310_RESET ,DPS310_RESET_MAGIC ); +if (rc <0 ) +return rc; + +/* Wait for device chip access: 2.5ms in specification */ +usleep_range (2500 ,12000 ); + +/* Reinitialize the chip */ + rc =dps310_startup (data); +if (rc) +return rc; + +dev_info (&data->client->dev, +"recovered from corrupted MEAS_CFG=%02x\n" , meas_cfg); +return 1 ; +} +static int dps310_read_pres_raw (struct dps310_data *data) {int rc;
@@ -405,16 +443,26 @@ static int dps310_read_pres_raw(struct dps310_data *data)if (mutex_lock_interruptible (&data->lock))return -EINTR ; - rate =dps310_get_pres_samp_freq (data); - timeout =DPS310_POLL_TIMEOUT_US (rate); - -/* Poll for sensor readiness; base the timeout upon the sample rate. */ - rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , ready, - ready &DPS310_PRS_RDY , -DPS310_POLL_SLEEP_US (timeout), timeout); -if (rc) + rc =dps310_check_reset_meas_cfg (data,DPS310_PRS_RDY ); +if (rc <0 ) goto done; +if (rc >0 ) { + rate =dps310_get_pres_samp_freq (data); + timeout =DPS310_POLL_TIMEOUT_US (rate); + +/* +* Poll for sensor readiness; base the timeout upon the sample +* rate. +*/ + rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , + ready, ready &DPS310_PRS_RDY , +DPS310_POLL_SLEEP_US (timeout), + timeout); +if (rc) + goto done; + } + rc =regmap_bulk_read (data->regmap,DPS310_PRS_BASE , val,sizeof (val));if (rc <0 ) goto done;
@@ -454,16 +502,26 @@ static int dps310_read_temp_raw(struct dps310_data *data)if (mutex_lock_interruptible (&data->lock))return -EINTR ; - rate =dps310_get_temp_samp_freq (data); - timeout =DPS310_POLL_TIMEOUT_US (rate); - -/* Poll for sensor readiness; base the timeout upon the sample rate. */ - rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , ready, - ready &DPS310_TMP_RDY , -DPS310_POLL_SLEEP_US (timeout), timeout); + rc =dps310_check_reset_meas_cfg (data,DPS310_TMP_RDY );if (rc <0 ) goto done; +if (rc >0 ) { + rate =dps310_get_temp_samp_freq (data); + timeout =DPS310_POLL_TIMEOUT_US (rate); + +/* +* Poll for sensor readiness; base the timeout upon the sample +* rate. +*/ + rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , + ready, ready &DPS310_TMP_RDY , +DPS310_POLL_SLEEP_US (timeout), + timeout); +if (rc <0 ) + goto done; + } + rc =dps310_read_temp_ready (data); done:
Signature · 1 line
2.31.1
Quoted 5 lines · Eddie James
Corruption of the
MEAS_CFGregister has been observed soon after system boot. In order to recover this scenario, checkMEAS_CFGif measurement isn't ready, and if it's incorrect, reset the DPS310 and execute the startup procedure.
Looks like both patches miss the Fixes tag. Can you add them?
...
drivers/iio/pressure/dps310.c static int dps310_get_temp_k(struct dps310_data *data) · line 406
Quoted 12 lines
drivers/iio/pressure/dps310.c +11
-0+/* +* Called with lock held. Returns a negative value on error, a positive value +* when the device is not ready, and zero when the device is ready. +*/ +static int dps310_check_reset_meas_cfg (struct dps310_data *data,int ready_bit) +{ +int meas_cfg; +int rc =regmap_read (data->regmap,DPS310_MEAS_CFG , &meas_cfg); + +if (rc <0 ) +return rc;
Please, split definition and assignment.
Quoted 50 lines
drivers/iio/pressure/dps310.c +33
-8+/* Device is ready, proceed to measurement */ +if (meas_cfg & ready_bit) +return 0 ; + +/* Device is OK, just not ready */ +if (meas_cfg & (DPS310_PRS_EN |DPS310_TEMP_EN |DPS310_BACKGROUND )) +return 1 ; + +/* DPS310 register state corrupt, better start from scratch */ + rc =regmap_write (data->regmap,DPS310_RESET ,DPS310_RESET_MAGIC ); +if (rc <0 ) +return rc; + +/* Wait for device chip access: 2.5ms in specification */ +usleep_range (2500 ,12000 ); + +/* Reinitialize the chip */ + rc =dps310_startup (data); +if (rc) +return rc; + +dev_info (&data->client->dev, +"recovered from corrupted MEAS_CFG=%02x\n" , meas_cfg); +return 1 ; +} +static int dps310_read_pres_raw (struct dps310_data *data) {int rc;@@ -405,16 +443,26 @@ static int dps310_read_pres_raw(struct dps310_data *data)if (mutex_lock_interruptible (&data->lock))return -EINTR ; - rate =dps310_get_pres_samp_freq (data); - timeout =DPS310_POLL_TIMEOUT_US (rate); - -/* Poll for sensor readiness; base the timeout upon the sample rate. */ - rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , ready, - ready &DPS310_PRS_RDY , -DPS310_POLL_SLEEP_US (timeout), timeout); -if (rc) + rc =dps310_check_reset_meas_cfg (data,DPS310_PRS_RDY ); +if (rc <0 ) goto done; +if (rc >0 ) { + rate =dps310_get_pres_samp_freq (data); + timeout =DPS310_POLL_TIMEOUT_US (rate); + +/*
drivers/iio/pressure/dps310.c static int dps310_read_pres_raw(struct dps310_data *data) · line 464
Quoted 10 lines
drivers/iio/pressure/dps310.c +10
-0+* Poll for sensor readiness; base the timeout upon the sample +* rate. +*/ + rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , + ready, ready &DPS310_PRS_RDY , +DPS310_POLL_SLEEP_US (timeout), + timeout); +if (rc) + goto done; + }
If you split the condition body to a helper, it can be rewritten like (also note special definition for positive returned numbers):
rc = ..._reset_meas_cfg(...);
if (rc == DPS310_MEAS_NOT_READY)
rc = ..._new_helper_func(...);
if (rc)
goto done;and looking at this it might be worth considering calling that conditional in the middle in the _reset_meas_cfg(), so the latter will return either 0 or negative error code.
drivers/iio/pressure/dps310.c static int dps310_read_temp_raw(struct dps310_data *data) · line 510
Quoted 6 lines
drivers/iio/pressure/dps310.c +3
-0+ rc =dps310_check_reset_meas_cfg (data,DPS310_TMP_RDY );if (rc <0 ) goto done; +if (rc >0 ) { + rate =dps310_get_temp_samp_freq (data);
Okay, I see this function is different, but still you may realize a helper from below and something like above suggestion can still be achieved.
drivers/iio/pressure/dps310.c static int dps310_read_temp_raw(struct dps310_data *data) · line 521
Quoted 11 lines
drivers/iio/pressure/dps310.c +11
-0+ timeout =DPS310_POLL_TIMEOUT_US (rate); + +/* +* Poll for sensor readiness; base the timeout upon the sample +* rate. +*/ + rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , + ready, ready &DPS310_TMP_RDY , +DPS310_POLL_SLEEP_US (timeout), + timeout); +if (rc <0 )
Why out of a sudden ' < 0'?
Review
Quoted 2 lines
(quoted diff) +2
-0+ goto done; + }
As per above.
Quoted 1 line
rc = dps310_read_temp_ready(data);
Signature · 2 lines
With Best Regards, Andy Shevchenko
Eddie James
maintainerQuoted 6 lines · Andy Shevchenko
Quoted 4 lines · Eddie James
Corruption of the
MEAS_CFGregister has been observed soon after system boot. In order to recover this scenario, checkMEAS_CFGif measurement isn't ready, and if it's incorrect, reset the DPS310 and execute the startup procedure.Looks like both patches miss the Fixes tag. Can you add them?
Well this isn't really a software fix - there's no identifiable bug in the driver. Just trying to recover the chip in this observed mystery scenario.
Quoted 15 lines
...
drivers/iio/pressure/dps310.c static int dps310_get_temp_k(struct dps310_data *data) · line 406
Quoted 11 lines
drivers/iio/pressure/dps310.c +11
-0+/* +* Called with lock held. Returns a negative value on error, a positive value +* when the device is not ready, and zero when the device is ready. +*/ +static int dps310_check_reset_meas_cfg (struct dps310_data *data,int ready_bit) +{ +int meas_cfg; +int rc =regmap_read (data->regmap,DPS310_MEAS_CFG , &meas_cfg); + +if (rc <0 ) +return rc;Please, split definition and assignment.
Ack.
Quoted 70 lines
Quoted 51 lines
drivers/iio/pressure/dps310.c +33
-8+/* Device is ready, proceed to measurement */ +if (meas_cfg & ready_bit) +return 0 ; + +/* Device is OK, just not ready */ +if (meas_cfg & (DPS310_PRS_EN |DPS310_TEMP_EN |DPS310_BACKGROUND )) +return 1 ; + +/* DPS310 register state corrupt, better start from scratch */ + rc =regmap_write (data->regmap,DPS310_RESET ,DPS310_RESET_MAGIC ); +if (rc <0 ) +return rc; + +/* Wait for device chip access: 2.5ms in specification */ +usleep_range (2500 ,12000 ); + +/* Reinitialize the chip */ + rc =dps310_startup (data); +if (rc) +return rc; + +dev_info (&data->client->dev, +"recovered from corrupted MEAS_CFG=%02x\n" , meas_cfg); +return 1 ; +} +static int dps310_read_pres_raw (struct dps310_data *data) {int rc;@@ -405,16 +443,26 @@ static int dps310_read_pres_raw(struct dps310_data *data)if (mutex_lock_interruptible (&data->lock))return -EINTR ; - rate =dps310_get_pres_samp_freq (data); - timeout =DPS310_POLL_TIMEOUT_US (rate); - -/* Poll for sensor readiness; base the timeout upon the sample rate. */ - rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , ready, - ready &DPS310_PRS_RDY , -DPS310_POLL_SLEEP_US (timeout), timeout); -if (rc) + rc =dps310_check_reset_meas_cfg (data,DPS310_PRS_RDY ); +if (rc <0 ) goto done; +if (rc >0 ) { + rate =dps310_get_pres_samp_freq (data); + timeout =DPS310_POLL_TIMEOUT_US (rate); + +/* drivers/iio/pressure/dps310.c static int dps310_read_pres_raw(struct dps310_data *data) · line 464
Quoted 10 lines
drivers/iio/pressure/dps310.c +10
-0+* Poll for sensor readiness; base the timeout upon the sample +* rate. +*/ + rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , + ready, ready &DPS310_PRS_RDY , +DPS310_POLL_SLEEP_US (timeout), + timeout); +if (rc) + goto done; + }If you split the condition body to a helper, it can be rewritten like (also note special definition for positive returned numbers):
rc = ..._reset_meas_cfg(...); if (rc == DPS310_MEAS_NOT_READY) rc = ..._new_helper_func(...); if (rc) goto done;
Quoted 3 lines
and looking at this it might be worth considering calling that conditional in the middle in the
_reset_meas_cfg(), so the latter will return either 0 or negative error code.
To be honest that looks more complicated than the way it is now? And I don't think I can make it common between the temp and pressure without some complicated macro business.
Quoted 22 lines
drivers/iio/pressure/dps310.c static int dps310_read_temp_raw(struct dps310_data *data) · line 510
Quoted 7 lines
drivers/iio/pressure/dps310.c +3
-0+ rc =dps310_check_reset_meas_cfg (data,DPS310_TMP_RDY );if (rc <0 ) goto done; +if (rc >0 ) { + rate =dps310_get_temp_samp_freq (data);Okay, I see this function is different, but still you may realize a helper from below and something like above suggestion can still be achieved.
drivers/iio/pressure/dps310.c static int dps310_read_temp_raw(struct dps310_data *data) · line 521
Quoted 11 lines
drivers/iio/pressure/dps310.c +11
-0+ timeout =DPS310_POLL_TIMEOUT_US (rate); + +/* +* Poll for sensor readiness; base the timeout upon the sample +* rate. +*/ + rc =regmap_read_poll_timeout (data->regmap,DPS310_MEAS_CFG , + ready, ready &DPS310_TMP_RDY , +DPS310_POLL_SLEEP_US (timeout), + timeout); +if (rc <0 )
Quoted 1 line
Why out of a sudden ' < 0'?
Good point, I'll fix that.
Quoted 7 lines
Review
Quoted 3 lines
(quoted diff) +2
-0+ goto done; + }As per above.
Quoted 1 line
rc = dps310_read_temp_ready(data);
Jonathan Cameron
maintainerQuoted 6 lines · On Mon, 15 Aug 2022 08:59:03 -0500 Eddie James <[email protected]> wrote:
Quoted 5 lines · Andy Shevchenko
Quoted 4 lines · Eddie James
Corruption of the
MEAS_CFGregister has been observed soon after system boot. In order to recover this scenario, checkMEAS_CFGif measurement isn't ready, and if it's incorrect, reset the DPS310 and execute the startup procedure.
Quoted 6 lines
Quoted 1 line
Looks like both patches miss the Fixes tag. Can you add them?
Well this isn't really a software fix - there's no identifiable bug in the driver. Just trying to recover the chip in this observed mystery scenario.
The tag is useful as well for where to backport this to. Probably just tag the driver introduction.
Your description makes it clear we aren't finding faults in the driver - just that it didn't cover this undocumented case!
Jonathan