st_lsm9ds0_core.c (3835B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * STMicroelectronics LSM9DS0 IMU driver 4 * 5 * Copyright (C) 2021, Intel Corporation 6 * 7 * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com> 8 */ 9 10#include <linux/device.h> 11#include <linux/err.h> 12#include <linux/module.h> 13#include <linux/regmap.h> 14#include <linux/regulator/consumer.h> 15 16#include <linux/iio/common/st_sensors.h> 17#include <linux/iio/iio.h> 18 19#include "st_lsm9ds0.h" 20 21static int st_lsm9ds0_power_enable(struct device *dev, struct st_lsm9ds0 *lsm9ds0) 22{ 23 int ret; 24 25 /* Regulators not mandatory, but if requested we should enable them. */ 26 lsm9ds0->vdd = devm_regulator_get(dev, "vdd"); 27 if (IS_ERR(lsm9ds0->vdd)) 28 return dev_err_probe(dev, PTR_ERR(lsm9ds0->vdd), 29 "unable to get Vdd supply\n"); 30 31 ret = regulator_enable(lsm9ds0->vdd); 32 if (ret) { 33 dev_warn(dev, "Failed to enable specified Vdd supply\n"); 34 return ret; 35 } 36 37 lsm9ds0->vdd_io = devm_regulator_get(dev, "vddio"); 38 if (IS_ERR(lsm9ds0->vdd_io)) { 39 regulator_disable(lsm9ds0->vdd); 40 return dev_err_probe(dev, PTR_ERR(lsm9ds0->vdd_io), 41 "unable to get Vdd_IO supply\n"); 42 } 43 ret = regulator_enable(lsm9ds0->vdd_io); 44 if (ret) { 45 dev_warn(dev, "Failed to enable specified Vdd_IO supply\n"); 46 regulator_disable(lsm9ds0->vdd); 47 return ret; 48 } 49 50 return 0; 51} 52 53static void st_lsm9ds0_power_disable(void *data) 54{ 55 struct st_lsm9ds0 *lsm9ds0 = data; 56 57 regulator_disable(lsm9ds0->vdd_io); 58 regulator_disable(lsm9ds0->vdd); 59} 60 61static int devm_st_lsm9ds0_power_enable(struct st_lsm9ds0 *lsm9ds0) 62{ 63 struct device *dev = lsm9ds0->dev; 64 int ret; 65 66 ret = st_lsm9ds0_power_enable(dev, lsm9ds0); 67 if (ret) 68 return ret; 69 70 return devm_add_action_or_reset(dev, st_lsm9ds0_power_disable, lsm9ds0); 71} 72 73static int st_lsm9ds0_probe_accel(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap) 74{ 75 const struct st_sensor_settings *settings; 76 struct device *dev = lsm9ds0->dev; 77 struct st_sensor_data *data; 78 79 settings = st_accel_get_settings(lsm9ds0->name); 80 if (!settings) { 81 dev_err(dev, "device name %s not recognized.\n", lsm9ds0->name); 82 return -ENODEV; 83 } 84 85 lsm9ds0->accel = devm_iio_device_alloc(dev, sizeof(*data)); 86 if (!lsm9ds0->accel) 87 return -ENOMEM; 88 89 lsm9ds0->accel->name = lsm9ds0->name; 90 91 data = iio_priv(lsm9ds0->accel); 92 data->sensor_settings = (struct st_sensor_settings *)settings; 93 data->irq = lsm9ds0->irq; 94 data->regmap = regmap; 95 data->vdd = lsm9ds0->vdd; 96 data->vdd_io = lsm9ds0->vdd_io; 97 98 return st_accel_common_probe(lsm9ds0->accel); 99} 100 101static int st_lsm9ds0_probe_magn(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap) 102{ 103 const struct st_sensor_settings *settings; 104 struct device *dev = lsm9ds0->dev; 105 struct st_sensor_data *data; 106 107 settings = st_magn_get_settings(lsm9ds0->name); 108 if (!settings) { 109 dev_err(dev, "device name %s not recognized.\n", lsm9ds0->name); 110 return -ENODEV; 111 } 112 113 lsm9ds0->magn = devm_iio_device_alloc(dev, sizeof(*data)); 114 if (!lsm9ds0->magn) 115 return -ENOMEM; 116 117 lsm9ds0->magn->name = lsm9ds0->name; 118 119 data = iio_priv(lsm9ds0->magn); 120 data->sensor_settings = (struct st_sensor_settings *)settings; 121 data->irq = lsm9ds0->irq; 122 data->regmap = regmap; 123 data->vdd = lsm9ds0->vdd; 124 data->vdd_io = lsm9ds0->vdd_io; 125 126 return st_magn_common_probe(lsm9ds0->magn); 127} 128 129int st_lsm9ds0_probe(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap) 130{ 131 int ret; 132 133 ret = devm_st_lsm9ds0_power_enable(lsm9ds0); 134 if (ret) 135 return ret; 136 137 /* Setup accelerometer device */ 138 ret = st_lsm9ds0_probe_accel(lsm9ds0, regmap); 139 if (ret) 140 return ret; 141 142 /* Setup magnetometer device */ 143 return st_lsm9ds0_probe_magn(lsm9ds0, regmap); 144} 145EXPORT_SYMBOL_NS_GPL(st_lsm9ds0_probe, IIO_ST_SENSORS); 146 147MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>"); 148MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU core driver"); 149MODULE_LICENSE("GPL v2"); 150MODULE_IMPORT_NS(IIO_ST_SENSORS);