Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <hdegoede@redhat.com>
Link: https://lore.kernel.org/r/20240326113700.56725-3-hdegoede@redhat.com
Cc: <Stable@vger.kernel.org>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Hans de Goede and committed by
Jonathan Cameron
6b8cffdc 57a15927

+68
+68
drivers/iio/accel/mxc4005.c
··· 5 5 * Copyright (c) 2014, Intel Corporation. 6 6 */ 7 7 8 + #include <linux/delay.h> 8 9 #include <linux/module.h> 9 10 #include <linux/i2c.h> 10 11 #include <linux/iio/iio.h> ··· 37 36 38 37 #define MXC4005_REG_INT_CLR1 0x01 39 38 #define MXC4005_REG_INT_CLR1_BIT_DRDYC 0x01 39 + #define MXC4005_REG_INT_CLR1_SW_RST 0x10 40 40 41 41 #define MXC4005_REG_CONTROL 0x0D 42 42 #define MXC4005_REG_CONTROL_MASK_FSR GENMASK(6, 5) 43 43 #define MXC4005_CONTROL_FSR_SHIFT 5 44 44 45 45 #define MXC4005_REG_DEVICE_ID 0x0E 46 + 47 + /* Datasheet does not specify a reset time, this is a conservative guess */ 48 + #define MXC4005_RESET_TIME_US 2000 46 49 47 50 enum mxc4005_axis { 48 51 AXIS_X, ··· 71 66 s64 timestamp __aligned(8); 72 67 } scan; 73 68 bool trigger_enabled; 69 + unsigned int control; 70 + unsigned int int_mask1; 74 71 }; 75 72 76 73 /* ··· 356 349 return ret; 357 350 } 358 351 352 + data->int_mask1 = val; 359 353 data->trigger_enabled = state; 360 354 mutex_unlock(&data->mutex); 361 355 ··· 391 383 } 392 384 393 385 dev_dbg(data->dev, "MXC4005 chip id %02x\n", reg); 386 + 387 + ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1, 388 + MXC4005_REG_INT_CLR1_SW_RST); 389 + if (ret < 0) 390 + return dev_err_probe(data->dev, ret, "resetting chip\n"); 391 + 392 + fsleep(MXC4005_RESET_TIME_US); 394 393 395 394 ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0); 396 395 if (ret < 0) ··· 494 479 return devm_iio_device_register(&client->dev, indio_dev); 495 480 } 496 481 482 + static int mxc4005_suspend(struct device *dev) 483 + { 484 + struct iio_dev *indio_dev = dev_get_drvdata(dev); 485 + struct mxc4005_data *data = iio_priv(indio_dev); 486 + int ret; 487 + 488 + /* Save control to restore it on resume */ 489 + ret = regmap_read(data->regmap, MXC4005_REG_CONTROL, &data->control); 490 + if (ret < 0) 491 + dev_err(data->dev, "failed to read reg_control\n"); 492 + 493 + return ret; 494 + } 495 + 496 + static int mxc4005_resume(struct device *dev) 497 + { 498 + struct iio_dev *indio_dev = dev_get_drvdata(dev); 499 + struct mxc4005_data *data = iio_priv(indio_dev); 500 + int ret; 501 + 502 + ret = regmap_write(data->regmap, MXC4005_REG_INT_CLR1, 503 + MXC4005_REG_INT_CLR1_SW_RST); 504 + if (ret) { 505 + dev_err(data->dev, "failed to reset chip: %d\n", ret); 506 + return ret; 507 + } 508 + 509 + fsleep(MXC4005_RESET_TIME_US); 510 + 511 + ret = regmap_write(data->regmap, MXC4005_REG_CONTROL, data->control); 512 + if (ret) { 513 + dev_err(data->dev, "failed to restore control register\n"); 514 + return ret; 515 + } 516 + 517 + ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK0, 0); 518 + if (ret) { 519 + dev_err(data->dev, "failed to restore interrupt 0 mask\n"); 520 + return ret; 521 + } 522 + 523 + ret = regmap_write(data->regmap, MXC4005_REG_INT_MASK1, data->int_mask1); 524 + if (ret) { 525 + dev_err(data->dev, "failed to restore interrupt 1 mask\n"); 526 + return ret; 527 + } 528 + 529 + return 0; 530 + } 531 + 532 + static DEFINE_SIMPLE_DEV_PM_OPS(mxc4005_pm_ops, mxc4005_suspend, mxc4005_resume); 533 + 497 534 static const struct acpi_device_id mxc4005_acpi_match[] = { 498 535 {"MXC4005", 0}, 499 536 {"MXC6655", 0}, ··· 573 506 .name = MXC4005_DRV_NAME, 574 507 .acpi_match_table = mxc4005_acpi_match, 575 508 .of_match_table = mxc4005_of_match, 509 + .pm = pm_sleep_ptr(&mxc4005_pm_ops), 576 510 }, 577 511 .probe = mxc4005_probe, 578 512 .id_table = mxc4005_id,