Skip to content

Commit 6b8cffd

Browse files
jwrdegoedejic23
authored andcommitted
iio: accel: mxc4005: Reset chip on probe() and resume()
On some designs the chip is not properly reset when powered up at boot or after a suspend/resume cycle. Use the sw-reset feature to ensure that the chip is in a clean state after probe() / resume() and in the case of resume() restore the settings (scale, trigger-enabled). Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218578 Signed-off-by: Hans de Goede <[email protected]> Link: https://lore.kernel.org/r/[email protected] Cc: <[email protected]> Signed-off-by: Jonathan Cameron <[email protected]>
1 parent 57a1592 commit 6b8cffd

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

drivers/iio/accel/mxc4005.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Copyright (c) 2014, Intel Corporation.
66
*/
77

8+
#include <linux/delay.h>
89
#include <linux/module.h>
910
#include <linux/i2c.h>
1011
#include <linux/iio/iio.h>
@@ -36,13 +37,17 @@
3637

3738
#define MXC4005_REG_INT_CLR1 0x01
3839
#define MXC4005_REG_INT_CLR1_BIT_DRDYC 0x01
40+
#define MXC4005_REG_INT_CLR1_SW_RST 0x10
3941

4042
#define MXC4005_REG_CONTROL 0x0D
4143
#define MXC4005_REG_CONTROL_MASK_FSR GENMASK(6, 5)
4244
#define MXC4005_CONTROL_FSR_SHIFT 5
4345

4446
#define MXC4005_REG_DEVICE_ID 0x0E
4547

48+
/* Datasheet does not specify a reset time, this is a conservative guess */
49+
#define MXC4005_RESET_TIME_US 2000
50+
4651
enum mxc4005_axis {
4752
AXIS_X,
4853
AXIS_Y,
@@ -66,6 +71,8 @@ struct mxc4005_data {
6671
s64 timestamp __aligned(8);
6772
} scan;
6873
bool trigger_enabled;
74+
unsigned int control;
75+
unsigned int int_mask1;
6976
};
7077

7178
/*
@@ -349,6 +356,7 @@ static int mxc4005_set_trigger_state(struct iio_trigger *trig,
349356
return ret;
350357
}
351358

359+
data->int_mask1 = val;
352360
data->trigger_enabled = state;
353361
mutex_unlock(&data->mutex);
354362

@@ -384,6 +392,13 @@ static int mxc4005_chip_init(struct mxc4005_data *data)
384392

385393
dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg);
386394

395+
ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
396+
MXC4005_REG_INT_CLR1_SW_RST);
397+
if (ret < 0)
398+
return dev_err_probe(data->dev, ret, "resetting chip\n");
399+
400+
fsleep(MXC4005_RESET_TIME_US);
401+
387402
ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
388403
if (ret < 0)
389404
return dev_err_probe(data->dev, ret, "writing INT_MASK0\n");
@@ -479,6 +494,58 @@ static int mxc4005_probe(struct i2c_client *client)
479494
return devm_iio_device_register(&client->dev, indio_dev);
480495
}
481496

497+
static int mxc4005_suspend(struct device *dev)
498+
{
499+
struct iio_dev *indio_dev = dev_get_drvdata(dev);
500+
struct mxc4005_data *data = iio_priv(indio_dev);
501+
int ret;
502+
503+
/* Save control to restore it on resume */
504+
ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &data->control);
505+
if (ret < 0)
506+
dev_err(data->dev, "failed to read reg_control\n");
507+
508+
return ret;
509+
}
510+
511+
static int mxc4005_resume(struct device *dev)
512+
{
513+
struct iio_dev *indio_dev = dev_get_drvdata(dev);
514+
struct mxc4005_data *data = iio_priv(indio_dev);
515+
int ret;
516+
517+
ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1,
518+
MXC4005_REG_INT_CLR1_SW_RST);
519+
if (ret) {
520+
dev_err(data->dev, "failed to reset chip: %d\n", ret);
521+
return ret;
522+
}
523+
524+
fsleep(MXC4005_RESET_TIME_US);
525+
526+
ret = regmap_write(data->regmap, MXC4005_REG_CONTROL, data->control);
527+
if (ret) {
528+
dev_err(data->dev, "failed to restore control register\n");
529+
return ret;
530+
}
531+
532+
ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0);
533+
if (ret) {
534+
dev_err(data->dev, "failed to restore interrupt 0 mask\n");
535+
return ret;
536+
}
537+
538+
ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, data->int_mask1);
539+
if (ret) {
540+
dev_err(data->dev, "failed to restore interrupt 1 mask\n");
541+
return ret;
542+
}
543+
544+
return 0;
545+
}
546+
547+
static DEFINE_SIMPLE_DEV_PM_OPS(mxc4005_pm_ops, mxc4005_suspend, mxc4005_resume);
548+
482549
static const struct acpi_device_id mxc4005_acpi_match[] = {
483550
{"MXC4005", 0},
484551
{"MXC6655", 0},
@@ -506,6 +573,7 @@ static struct i2c_driver mxc4005_driver = {
506573
.name = MXC4005_DRV_NAME,
507574
.acpi_match_table = mxc4005_acpi_match,
508575
.of_match_table = mxc4005_of_match,
576+
.pm = pm_sleep_ptr(&mxc4005_pm_ops),
509577
},
510578
.probe = mxc4005_probe,
511579
.id_table = mxc4005_id,

0 commit comments

Comments
 (0)