diff options
Diffstat (limited to 'drivers/iio/magnetometer/bmc150_magn.c')
| -rw-r--r-- | drivers/iio/magnetometer/bmc150_magn.c | 115 |
1 files changed, 56 insertions, 59 deletions
diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index d4de16750b10..6a73f6e2f1f0 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -14,7 +14,6 @@ #include <linux/interrupt.h> #include <linux/delay.h> #include <linux/slab.h> -#include <linux/acpi.h> #include <linux/pm.h> #include <linux/pm_runtime.h> #include <linux/iio/iio.h> @@ -25,12 +24,10 @@ #include <linux/iio/trigger_consumer.h> #include <linux/iio/triggered_buffer.h> #include <linux/regmap.h> +#include <linux/regulator/consumer.h> #include "bmc150_magn.h" -#define BMC150_MAGN_DRV_NAME "bmc150_magn" -#define BMC150_MAGN_IRQ_NAME "bmc150_magn_event" - #define BMC150_MAGN_REG_CHIP_ID 0x40 #define BMC150_MAGN_CHIP_ID_VAL 0x32 @@ -135,9 +132,13 @@ struct bmc150_magn_data { */ struct mutex mutex; struct regmap *regmap; + struct regulator_bulk_data regulators[2]; struct iio_mount_matrix orientation; - /* 4 x 32 bits for x, y z, 4 bytes align, 64 bits timestamp */ - s32 buffer[6]; + /* Ensure timestamp is naturally aligned */ + struct { + s32 chans[3]; + aligned_s64 timestamp; + } scan; struct iio_trigger *dready_trig; bool dready_trigger_on; int max_odr; @@ -190,7 +191,7 @@ static bool bmc150_magn_is_writeable_reg(struct device *dev, unsigned int reg) return true; default: return false; - }; + } } static bool bmc150_magn_is_volatile_reg(struct device *dev, unsigned int reg) @@ -221,7 +222,7 @@ const struct regmap_config bmc150_magn_regmap_config = { .writeable_reg = bmc150_magn_is_writeable_reg, .volatile_reg = bmc150_magn_is_volatile_reg, }; -EXPORT_SYMBOL(bmc150_magn_regmap_config); +EXPORT_SYMBOL_NS(bmc150_magn_regmap_config, "IIO_BMC150_MAGN"); static int bmc150_magn_set_power_mode(struct bmc150_magn_data *data, enum bmc150_magn_power_modes mode, @@ -256,25 +257,17 @@ static int bmc150_magn_set_power_mode(struct bmc150_magn_data *data, static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) { -#ifdef CONFIG_PM - int ret; - - if (on) { - ret = pm_runtime_get_sync(data->dev); - } else { - pm_runtime_mark_last_busy(data->dev); - ret = pm_runtime_put_autosuspend(data->dev); - } + int ret = 0; + if (on) + ret = pm_runtime_resume_and_get(data->dev); + else + pm_runtime_put_autosuspend(data->dev); if (ret < 0) { dev_err(data->dev, "failed to change power state to %d\n", on); - if (on) - pm_runtime_put_noidle(data->dev); - return ret; } -#endif return 0; } @@ -673,12 +666,12 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p) int ret; mutex_lock(&data->mutex); - ret = bmc150_magn_read_xyz(data, data->buffer); + ret = bmc150_magn_read_xyz(data, data->scan.chans); if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, - pf->timestamp); + iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan), + pf->timestamp); err: mutex_unlock(&data->mutex); @@ -692,12 +685,24 @@ static int bmc150_magn_init(struct bmc150_magn_data *data) int ret, chip_id; struct bmc150_magn_preset preset; + ret = regulator_bulk_enable(ARRAY_SIZE(data->regulators), + data->regulators); + if (ret < 0) { + dev_err(data->dev, "Failed to enable regulators: %d\n", ret); + return ret; + } + /* + * 3ms power-on time according to datasheet, let's better + * be safe than sorry and set this delay to 5ms. + */ + msleep(5); + ret = bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, false); if (ret < 0) { dev_err(data->dev, "Failed to bring up device from suspend mode\n"); - return ret; + goto err_regulator_disable; } ret = regmap_read(data->regmap, BMC150_MAGN_REG_CHIP_ID, &chip_id); @@ -752,6 +757,8 @@ static int bmc150_magn_init(struct bmc150_magn_data *data) err_poweroff: bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true); +err_regulator_disable: + regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators); return ret; } @@ -766,20 +773,20 @@ static int bmc150_magn_reset_intr(struct bmc150_magn_data *data) return regmap_read(data->regmap, BMC150_MAGN_REG_X_L, &tmp); } -static int bmc150_magn_trig_try_reen(struct iio_trigger *trig) +static void bmc150_magn_trig_reen(struct iio_trigger *trig) { struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct bmc150_magn_data *data = iio_priv(indio_dev); int ret; if (!data->dready_trigger_on) - return 0; + return; mutex_lock(&data->mutex); ret = bmc150_magn_reset_intr(data); mutex_unlock(&data->mutex); - - return ret; + if (ret) + dev_err(data->dev, "Failed to reset interrupt\n"); } static int bmc150_magn_data_rdy_trigger_set_state(struct iio_trigger *trig, @@ -817,7 +824,7 @@ err_unlock: static const struct iio_trigger_ops bmc150_magn_trigger_ops = { .set_trigger_state = bmc150_magn_data_rdy_trigger_set_state, - .try_reenable = bmc150_magn_trig_try_reen, + .reenable = bmc150_magn_trig_reen, }; static int bmc150_magn_buffer_preenable(struct iio_dev *indio_dev) @@ -836,22 +843,9 @@ static int bmc150_magn_buffer_postdisable(struct iio_dev *indio_dev) static const struct iio_buffer_setup_ops bmc150_magn_buffer_setup_ops = { .preenable = bmc150_magn_buffer_preenable, - .postenable = iio_triggered_buffer_postenable, - .predisable = iio_triggered_buffer_predisable, .postdisable = bmc150_magn_buffer_postdisable, }; -static const char *bmc150_magn_match_acpi_device(struct device *dev) -{ - const struct acpi_device_id *id; - - id = acpi_match_device(dev->driver->acpi_match_table, dev); - if (!id) - return NULL; - - return dev_name(dev); -} - int bmc150_magn_probe(struct device *dev, struct regmap *regmap, int irq, const char *name) { @@ -869,13 +863,16 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, data->irq = irq; data->dev = dev; - ret = iio_read_mount_matrix(dev, "mount-matrix", - &data->orientation); + data->regulators[0].supply = "vdd"; + data->regulators[1].supply = "vddio"; + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(data->regulators), + data->regulators); if (ret) - return ret; + return dev_err_probe(dev, ret, "failed to get regulators\n"); - if (!name && ACPI_HANDLE(dev)) - name = bmc150_magn_match_acpi_device(dev); + ret = iio_read_mount_matrix(dev, &data->orientation); + if (ret) + return ret; mutex_init(&data->mutex); @@ -883,7 +880,6 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, if (ret < 0) return ret; - indio_dev->dev.parent = dev; indio_dev->channels = bmc150_magn_channels; indio_dev->num_channels = ARRAY_SIZE(bmc150_magn_channels); indio_dev->available_scan_masks = bmc150_magn_scan_masks; @@ -895,14 +891,13 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, data->dready_trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, - indio_dev->id); + iio_device_id(indio_dev)); if (!data->dready_trig) { ret = -ENOMEM; dev_err(dev, "iio trigger alloc failed\n"); goto err_poweroff; } - data->dready_trig->dev.parent = dev; data->dready_trig->ops = &bmc150_magn_trigger_ops; iio_trigger_set_drvdata(data->dready_trig, indio_dev); ret = iio_trigger_register(data->dready_trig); @@ -915,7 +910,7 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, iio_trigger_generic_data_rdy_poll, NULL, IRQF_TRIGGER_RISING | IRQF_ONESHOT, - BMC150_MAGN_IRQ_NAME, + "bmc150_magn_event", data->dready_trig); if (ret < 0) { dev_err(dev, "request irq %d failed\n", irq); @@ -944,12 +939,15 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, ret = iio_device_register(indio_dev); if (ret < 0) { dev_err(dev, "unable to register iio device\n"); - goto err_buffer_cleanup; + goto err_pm_cleanup; } dev_dbg(dev, "Registered device %s\n", name); return 0; +err_pm_cleanup: + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); err_buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); err_free_irq: @@ -962,9 +960,9 @@ err_poweroff: bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true); return ret; } -EXPORT_SYMBOL(bmc150_magn_probe); +EXPORT_SYMBOL_NS(bmc150_magn_probe, "IIO_BMC150_MAGN"); -int bmc150_magn_remove(struct device *dev) +void bmc150_magn_remove(struct device *dev) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct bmc150_magn_data *data = iio_priv(indio_dev); @@ -973,7 +971,6 @@ int bmc150_magn_remove(struct device *dev) pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); iio_triggered_buffer_cleanup(indio_dev); @@ -987,9 +984,9 @@ int bmc150_magn_remove(struct device *dev) bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true); mutex_unlock(&data->mutex); - return 0; + regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators); } -EXPORT_SYMBOL(bmc150_magn_remove); +EXPORT_SYMBOL_NS(bmc150_magn_remove, "IIO_BMC150_MAGN"); #ifdef CONFIG_PM static int bmc150_magn_runtime_suspend(struct device *dev) @@ -1057,7 +1054,7 @@ const struct dev_pm_ops bmc150_magn_pm_ops = { SET_RUNTIME_PM_OPS(bmc150_magn_runtime_suspend, bmc150_magn_runtime_resume, NULL) }; -EXPORT_SYMBOL(bmc150_magn_pm_ops); +EXPORT_SYMBOL_NS(bmc150_magn_pm_ops, "IIO_BMC150_MAGN"); MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>"); MODULE_LICENSE("GPL v2"); |
