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

iio: imu: st_lsm6dsx: add system power management support

Add system sleep power management support to st_lsm6dsx driver.
In particular during suspend phase each sensor is disabled and
hw fifo is configured in bypass in order to avoid subsequent
I/O operations. The patch has been tested on HiKey board device

Signed-off-by: Lorenzo Bianconi <lorenzo.bianconi@st.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>

authored by

Lorenzo Bianconi and committed by
Jonathan Cameron
d3f77058 535de397

+58
+2
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
··· 135 135 #endif /* CONFIG_SPI_MASTER */ 136 136 }; 137 137 138 + extern const struct dev_pm_ops st_lsm6dsx_pm_ops; 139 + 138 140 int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id, const char *name, 139 141 const struct st_lsm6dsx_transfer_function *tf_ops); 140 142 int st_lsm6dsx_sensor_enable(struct st_lsm6dsx_sensor *sensor);
+54
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
··· 36 36 #include <linux/delay.h> 37 37 #include <linux/iio/iio.h> 38 38 #include <linux/iio/sysfs.h> 39 + #include <linux/pm.h> 39 40 40 41 #include <linux/platform_data/st_sensors_pdata.h> 41 42 ··· 731 730 return 0; 732 731 } 733 732 EXPORT_SYMBOL(st_lsm6dsx_probe); 733 + 734 + #ifdef CONFIG_PM 735 + static int st_lsm6dsx_suspend(struct device *dev) 736 + { 737 + struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); 738 + struct st_lsm6dsx_sensor *sensor; 739 + int i, err = 0; 740 + 741 + for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { 742 + sensor = iio_priv(hw->iio_devs[i]); 743 + if (!(hw->enable_mask & BIT(sensor->id))) 744 + continue; 745 + 746 + err = st_lsm6dsx_write_with_mask(hw, 747 + st_lsm6dsx_odr_table[sensor->id].reg.addr, 748 + st_lsm6dsx_odr_table[sensor->id].reg.mask, 0); 749 + if (err < 0) 750 + return err; 751 + } 752 + 753 + if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS) 754 + err = st_lsm6dsx_flush_fifo(hw); 755 + 756 + return err; 757 + } 758 + 759 + static int st_lsm6dsx_resume(struct device *dev) 760 + { 761 + struct st_lsm6dsx_hw *hw = dev_get_drvdata(dev); 762 + struct st_lsm6dsx_sensor *sensor; 763 + int i, err = 0; 764 + 765 + for (i = 0; i < ST_LSM6DSX_ID_MAX; i++) { 766 + sensor = iio_priv(hw->iio_devs[i]); 767 + if (!(hw->enable_mask & BIT(sensor->id))) 768 + continue; 769 + 770 + err = st_lsm6dsx_set_odr(sensor, sensor->odr); 771 + if (err < 0) 772 + return err; 773 + } 774 + 775 + if (hw->enable_mask) 776 + err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT); 777 + 778 + return err; 779 + } 780 + #endif /* CONFIG_PM */ 781 + 782 + const struct dev_pm_ops st_lsm6dsx_pm_ops = { 783 + SET_SYSTEM_SLEEP_PM_OPS(st_lsm6dsx_suspend, st_lsm6dsx_resume) 784 + }; 785 + EXPORT_SYMBOL(st_lsm6dsx_pm_ops); 734 786 735 787 MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>"); 736 788 MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
+1
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
··· 98 98 static struct i2c_driver st_lsm6dsx_driver = { 99 99 .driver = { 100 100 .name = "st_lsm6dsx_i2c", 101 + .pm = &st_lsm6dsx_pm_ops, 101 102 .of_match_table = of_match_ptr(st_lsm6dsx_i2c_of_match), 102 103 }, 103 104 .probe = st_lsm6dsx_i2c_probe,
+1
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
··· 115 115 static struct spi_driver st_lsm6dsx_driver = { 116 116 .driver = { 117 117 .name = "st_lsm6dsx_spi", 118 + .pm = &st_lsm6dsx_pm_ops, 118 119 .of_match_table = of_match_ptr(st_lsm6dsx_spi_of_match), 119 120 }, 120 121 .probe = st_lsm6dsx_spi_probe,