347 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * mpl3115.c - Support for Freescale MPL3115A2 pressure/temperature sensor4 *5 * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>6 *7 * (7-bit I2C slave address 0x60)8 *9 * TODO: FIFO buffer, altimeter mode, oversampling, continuous mode,10 * interrupts, user offset correction, raw mode11 */12 13#include <linux/module.h>14#include <linux/i2c.h>15#include <linux/iio/iio.h>16#include <linux/iio/sysfs.h>17#include <linux/iio/trigger_consumer.h>18#include <linux/iio/buffer.h>19#include <linux/iio/triggered_buffer.h>20#include <linux/delay.h>21 22#define MPL3115_STATUS 0x0023#define MPL3115_OUT_PRESS 0x01 /* MSB first, 20 bit */24#define MPL3115_OUT_TEMP 0x04 /* MSB first, 12 bit */25#define MPL3115_WHO_AM_I 0x0c26#define MPL3115_CTRL_REG1 0x2627 28#define MPL3115_DEVICE_ID 0xc429 30#define MPL3115_STATUS_PRESS_RDY BIT(2)31#define MPL3115_STATUS_TEMP_RDY BIT(1)32 33#define MPL3115_CTRL_RESET BIT(2) /* software reset */34#define MPL3115_CTRL_OST BIT(1) /* initiate measurement */35#define MPL3115_CTRL_ACTIVE BIT(0) /* continuous measurement */36#define MPL3115_CTRL_OS_258MS (BIT(5) | BIT(4)) /* 64x oversampling */37 38struct mpl3115_data {39 struct i2c_client *client;40 struct mutex lock;41 u8 ctrl_reg1;42};43 44static int mpl3115_request(struct mpl3115_data *data)45{46 int ret, tries = 15;47 48 /* trigger measurement */49 ret = i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,50 data->ctrl_reg1 | MPL3115_CTRL_OST);51 if (ret < 0)52 return ret;53 54 while (tries-- > 0) {55 ret = i2c_smbus_read_byte_data(data->client, MPL3115_CTRL_REG1);56 if (ret < 0)57 return ret;58 /* wait for data ready, i.e. OST cleared */59 if (!(ret & MPL3115_CTRL_OST))60 break;61 msleep(20);62 }63 64 if (tries < 0) {65 dev_err(&data->client->dev, "data not ready\n");66 return -EIO;67 }68 69 return 0;70}71 72static int mpl3115_read_raw(struct iio_dev *indio_dev,73 struct iio_chan_spec const *chan,74 int *val, int *val2, long mask)75{76 struct mpl3115_data *data = iio_priv(indio_dev);77 int ret;78 79 switch (mask) {80 case IIO_CHAN_INFO_RAW:81 ret = iio_device_claim_direct_mode(indio_dev);82 if (ret)83 return ret;84 85 switch (chan->type) {86 case IIO_PRESSURE: { /* in 0.25 pascal / LSB */87 __be32 tmp = 0;88 89 mutex_lock(&data->lock);90 ret = mpl3115_request(data);91 if (ret < 0) {92 mutex_unlock(&data->lock);93 break;94 }95 ret = i2c_smbus_read_i2c_block_data(data->client,96 MPL3115_OUT_PRESS, 3, (u8 *) &tmp);97 mutex_unlock(&data->lock);98 if (ret < 0)99 break;100 *val = be32_to_cpu(tmp) >> chan->scan_type.shift;101 ret = IIO_VAL_INT;102 break;103 }104 case IIO_TEMP: { /* in 0.0625 celsius / LSB */105 __be16 tmp;106 107 mutex_lock(&data->lock);108 ret = mpl3115_request(data);109 if (ret < 0) {110 mutex_unlock(&data->lock);111 break;112 }113 ret = i2c_smbus_read_i2c_block_data(data->client,114 MPL3115_OUT_TEMP, 2, (u8 *) &tmp);115 mutex_unlock(&data->lock);116 if (ret < 0)117 break;118 *val = sign_extend32(be16_to_cpu(tmp) >> chan->scan_type.shift,119 chan->scan_type.realbits - 1);120 ret = IIO_VAL_INT;121 break;122 }123 default:124 ret = -EINVAL;125 break;126 }127 128 iio_device_release_direct_mode(indio_dev);129 return ret;130 131 case IIO_CHAN_INFO_SCALE:132 switch (chan->type) {133 case IIO_PRESSURE:134 *val = 0;135 *val2 = 250; /* want kilopascal */136 return IIO_VAL_INT_PLUS_MICRO;137 case IIO_TEMP:138 *val = 0;139 *val2 = 62500;140 return IIO_VAL_INT_PLUS_MICRO;141 default:142 return -EINVAL;143 }144 }145 return -EINVAL;146}147 148static irqreturn_t mpl3115_trigger_handler(int irq, void *p)149{150 struct iio_poll_func *pf = p;151 struct iio_dev *indio_dev = pf->indio_dev;152 struct mpl3115_data *data = iio_priv(indio_dev);153 /*154 * 32-bit channel + 16-bit channel + padding + ts155 * Note that it is possible for only one of the first 2156 * channels to be enabled. If that happens, the first element157 * of the buffer may be either 16 or 32-bits. As such we cannot158 * use a simple structure definition to express this data layout.159 */160 u8 buffer[16] __aligned(8);161 int ret, pos = 0;162 163 mutex_lock(&data->lock);164 ret = mpl3115_request(data);165 if (ret < 0) {166 mutex_unlock(&data->lock);167 goto done;168 }169 170 memset(buffer, 0, sizeof(buffer));171 if (test_bit(0, indio_dev->active_scan_mask)) {172 ret = i2c_smbus_read_i2c_block_data(data->client,173 MPL3115_OUT_PRESS, 3, &buffer[pos]);174 if (ret < 0) {175 mutex_unlock(&data->lock);176 goto done;177 }178 pos += 4;179 }180 181 if (test_bit(1, indio_dev->active_scan_mask)) {182 ret = i2c_smbus_read_i2c_block_data(data->client,183 MPL3115_OUT_TEMP, 2, &buffer[pos]);184 if (ret < 0) {185 mutex_unlock(&data->lock);186 goto done;187 }188 }189 mutex_unlock(&data->lock);190 191 iio_push_to_buffers_with_timestamp(indio_dev, buffer,192 iio_get_time_ns(indio_dev));193 194done:195 iio_trigger_notify_done(indio_dev->trig);196 return IRQ_HANDLED;197}198 199static const struct iio_chan_spec mpl3115_channels[] = {200 {201 .type = IIO_PRESSURE,202 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),203 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),204 .scan_index = 0,205 .scan_type = {206 .sign = 'u',207 .realbits = 20,208 .storagebits = 32,209 .shift = 12,210 .endianness = IIO_BE,211 }212 },213 {214 .type = IIO_TEMP,215 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),216 .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),217 .scan_index = 1,218 .scan_type = {219 .sign = 's',220 .realbits = 12,221 .storagebits = 16,222 .shift = 4,223 .endianness = IIO_BE,224 }225 },226 IIO_CHAN_SOFT_TIMESTAMP(2),227};228 229static const struct iio_info mpl3115_info = {230 .read_raw = &mpl3115_read_raw,231};232 233static int mpl3115_probe(struct i2c_client *client)234{235 const struct i2c_device_id *id = i2c_client_get_device_id(client);236 struct mpl3115_data *data;237 struct iio_dev *indio_dev;238 int ret;239 240 ret = i2c_smbus_read_byte_data(client, MPL3115_WHO_AM_I);241 if (ret < 0)242 return ret;243 if (ret != MPL3115_DEVICE_ID)244 return -ENODEV;245 246 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));247 if (!indio_dev)248 return -ENOMEM;249 250 data = iio_priv(indio_dev);251 data->client = client;252 mutex_init(&data->lock);253 254 i2c_set_clientdata(client, indio_dev);255 indio_dev->info = &mpl3115_info;256 indio_dev->name = id->name;257 indio_dev->modes = INDIO_DIRECT_MODE;258 indio_dev->channels = mpl3115_channels;259 indio_dev->num_channels = ARRAY_SIZE(mpl3115_channels);260 261 /* software reset, I2C transfer is aborted (fails) */262 i2c_smbus_write_byte_data(client, MPL3115_CTRL_REG1,263 MPL3115_CTRL_RESET);264 msleep(50);265 266 data->ctrl_reg1 = MPL3115_CTRL_OS_258MS;267 ret = i2c_smbus_write_byte_data(client, MPL3115_CTRL_REG1,268 data->ctrl_reg1);269 if (ret < 0)270 return ret;271 272 ret = iio_triggered_buffer_setup(indio_dev, NULL,273 mpl3115_trigger_handler, NULL);274 if (ret < 0)275 return ret;276 277 ret = iio_device_register(indio_dev);278 if (ret < 0)279 goto buffer_cleanup;280 return 0;281 282buffer_cleanup:283 iio_triggered_buffer_cleanup(indio_dev);284 return ret;285}286 287static int mpl3115_standby(struct mpl3115_data *data)288{289 return i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,290 data->ctrl_reg1 & ~MPL3115_CTRL_ACTIVE);291}292 293static void mpl3115_remove(struct i2c_client *client)294{295 struct iio_dev *indio_dev = i2c_get_clientdata(client);296 297 iio_device_unregister(indio_dev);298 iio_triggered_buffer_cleanup(indio_dev);299 mpl3115_standby(iio_priv(indio_dev));300}301 302static int mpl3115_suspend(struct device *dev)303{304 return mpl3115_standby(iio_priv(i2c_get_clientdata(305 to_i2c_client(dev))));306}307 308static int mpl3115_resume(struct device *dev)309{310 struct mpl3115_data *data = iio_priv(i2c_get_clientdata(311 to_i2c_client(dev)));312 313 return i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,314 data->ctrl_reg1);315}316 317static DEFINE_SIMPLE_DEV_PM_OPS(mpl3115_pm_ops, mpl3115_suspend,318 mpl3115_resume);319 320static const struct i2c_device_id mpl3115_id[] = {321 { "mpl3115" },322 { }323};324MODULE_DEVICE_TABLE(i2c, mpl3115_id);325 326static const struct of_device_id mpl3115_of_match[] = {327 { .compatible = "fsl,mpl3115" },328 { }329};330MODULE_DEVICE_TABLE(of, mpl3115_of_match);331 332static struct i2c_driver mpl3115_driver = {333 .driver = {334 .name = "mpl3115",335 .of_match_table = mpl3115_of_match,336 .pm = pm_sleep_ptr(&mpl3115_pm_ops),337 },338 .probe = mpl3115_probe,339 .remove = mpl3115_remove,340 .id_table = mpl3115_id,341};342module_i2c_driver(mpl3115_driver);343 344MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");345MODULE_DESCRIPTION("Freescale MPL3115 pressure/temperature driver");346MODULE_LICENSE("GPL");347