[PATCH 1/1] iio: accel: bma400: add PM_SLEEP support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



 - Add system sleep ops if CONFIG_PM_SLEEP is set.
 - Add attribute for setting the power mode of the
   device.

Signed-off-by: Dan Robertson <dan@xxxxxxxxxxxxxxx>
---
 drivers/iio/accel/bma400.h      |   3 +
 drivers/iio/accel/bma400_core.c | 132 ++++++++++++++++++++++++--------
 drivers/iio/accel/bma400_i2c.c  |   1 +
 drivers/iio/accel/bma400_spi.c  |   1 +
 4 files changed, 107 insertions(+), 30 deletions(-)

diff --git a/drivers/iio/accel/bma400.h b/drivers/iio/accel/bma400.h
index 5ad10db9819f..e9dd9e918aac 100644
--- a/drivers/iio/accel/bma400.h
+++ b/drivers/iio/accel/bma400.h
@@ -10,6 +10,7 @@
 #define _BMA400_H_
 
 #include <linux/bits.h>
+#include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 
 /*
@@ -96,4 +97,6 @@ int bma400_probe(struct device *dev, struct regmap *regmap, const char *name);
 
 int bma400_remove(struct device *dev);
 
+extern const struct dev_pm_ops bma400_pm_ops;
+
 #endif
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index cc77f89c048b..5af57b8e1fd7 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -147,36 +147,6 @@ bma400_accel_get_mount_matrix(const struct iio_dev *indio_dev,
 	return &data->orientation;
 }
 
-static const struct iio_chan_spec_ext_info bma400_ext_info[] = {
-	IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bma400_accel_get_mount_matrix),
-	{ }
-};
-
-#define BMA400_ACC_CHANNEL(_axis) { \
-	.type = IIO_ACCEL, \
-	.modified = 1, \
-	.channel2 = IIO_MOD_##_axis, \
-	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
-	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
-		BIT(IIO_CHAN_INFO_SCALE) | \
-		BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
-	.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
-		BIT(IIO_CHAN_INFO_SCALE) | \
-		BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
-	.ext_info = bma400_ext_info, \
-}
-
-static const struct iio_chan_spec bma400_channels[] = {
-	BMA400_ACC_CHANNEL(X),
-	BMA400_ACC_CHANNEL(Y),
-	BMA400_ACC_CHANNEL(Z),
-	{
-		.type = IIO_TEMP,
-		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
-		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ),
-	},
-};
-
 static int bma400_get_temp_reg(struct bma400_data *data, int *val, int *val2)
 {
 	unsigned int raw_temp;
@@ -542,6 +512,73 @@ static int bma400_set_power_mode(struct bma400_data *data,
 	return 0;
 }
 
+static const char * const bma400_power_modes[] = {
+	"sleep",
+	"low-power",
+	"normal"
+};
+
+int bma400_power_mode_enum_get(struct iio_dev *dev,
+			       const struct iio_chan_spec *chan)
+{
+	struct bma400_data *data = iio_priv(dev);
+
+	return data->power_mode;
+}
+
+int bma400_power_mode_enum_set(struct iio_dev *dev,
+			       const struct iio_chan_spec *chan,
+			       unsigned int mode)
+{
+	struct bma400_data *data = iio_priv(dev);
+	int ret;
+
+	mutex_lock(&data->mutex);
+	ret = bma400_set_power_mode(data, mode);
+	mutex_unlock(&data->mutex);
+
+	return ret;
+}
+
+static const struct iio_enum bma400_power_mode_enum = {
+	.items = bma400_power_modes,
+	.num_items = ARRAY_SIZE(bma400_power_modes),
+	.get = bma400_power_mode_enum_get,
+	.set = bma400_power_mode_enum_set,
+};
+
+static const struct iio_chan_spec_ext_info bma400_ext_info[] = {
+	IIO_ENUM("power_mode", true, &bma400_power_mode_enum),
+	IIO_ENUM_AVAILABLE("power_mode", &bma400_power_mode_enum),
+	IIO_MOUNT_MATRIX(IIO_SHARED_BY_DIR, bma400_accel_get_mount_matrix),
+	{ }
+};
+
+#define BMA400_ACC_CHANNEL(_axis) { \
+	.type = IIO_ACCEL, \
+	.modified = 1, \
+	.channel2 = IIO_MOD_##_axis, \
+	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+		BIT(IIO_CHAN_INFO_SCALE) | \
+		BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+	.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+		BIT(IIO_CHAN_INFO_SCALE) | \
+		BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+	.ext_info = bma400_ext_info, \
+}
+
+static const struct iio_chan_spec bma400_channels[] = {
+	BMA400_ACC_CHANNEL(X),
+	BMA400_ACC_CHANNEL(Y),
+	BMA400_ACC_CHANNEL(Z),
+	{
+		.type = IIO_TEMP,
+		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+	},
+};
+
 static void bma400_init_tables(void)
 {
 	int raw;
@@ -848,6 +885,41 @@ int bma400_remove(struct device *dev)
 }
 EXPORT_SYMBOL(bma400_remove);
 
+#ifdef CONFIG_PM_SLEEP
+static int bma400_suspend(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct bma400_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->mutex);
+	ret = bma400_set_power_mode(data, POWER_MODE_SLEEP);
+	mutex_unlock(&data->mutex);
+
+	return ret;
+}
+
+static int bma400_resume(struct device *dev)
+{
+	struct iio_dev *indio_dev = dev_get_drvdata(dev);
+	struct bma400_data *data = iio_priv(indio_dev);
+	int ret;
+
+	mutex_lock(&data->mutex);
+	ret = bma400_set_power_mode(data, POWER_MODE_NORMAL);
+	mutex_unlock(&data->mutex);
+
+	return ret;
+}
+#endif
+
+const struct dev_pm_ops bma400_pm_ops = {
+#ifdef CONFIG_PM_SLEEP
+	SET_SYSTEM_SLEEP_PM_OPS(bma400_suspend, bma400_resume)
+#endif
+};
+EXPORT_SYMBOL(bma400_pm_ops);
+
 MODULE_AUTHOR("Dan Robertson <dan@xxxxxxxxxxxxxxx>");
 MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor core");
 MODULE_LICENSE("GPL");
diff --git a/drivers/iio/accel/bma400_i2c.c b/drivers/iio/accel/bma400_i2c.c
index 9dcb7cc9996e..52a779d53629 100644
--- a/drivers/iio/accel/bma400_i2c.c
+++ b/drivers/iio/accel/bma400_i2c.c
@@ -48,6 +48,7 @@ static struct i2c_driver bma400_i2c_driver = {
 	.driver = {
 		.name = "bma400",
 		.of_match_table = bma400_of_i2c_match,
+		.pm = &bma400_pm_ops
 	},
 	.probe    = bma400_i2c_probe,
 	.remove   = bma400_i2c_remove,
diff --git a/drivers/iio/accel/bma400_spi.c b/drivers/iio/accel/bma400_spi.c
index 7c2825904e08..358bd26ac4cd 100644
--- a/drivers/iio/accel/bma400_spi.c
+++ b/drivers/iio/accel/bma400_spi.c
@@ -108,6 +108,7 @@ static struct spi_driver bma400_spi_driver = {
 	.driver = {
 		.name = "bma400",
 		.of_match_table = bma400_of_spi_match,
+		.pm = &bma400_pm_ops
 	},
 	.probe    = bma400_spi_probe,
 	.remove   = bma400_spi_remove,




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Input]     [Linux Kernel]     [Linux SCSI]     [X.org]

  Powered by Linux