cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mpl3115.c (8313B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * mpl3115.c - Support for Freescale MPL3115A2 pressure/temperature sensor
      4 *
      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 mode
     11 */
     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 0x00
     23#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 0x0c
     26#define MPL3115_CTRL_REG1 0x26
     27
     28#define MPL3115_DEVICE_ID 0xc4
     29
     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 + ts
    155	 * Note that it is possible for only one of the first 2
    156	 * channels to be enabled. If that happens, the first element
    157	 * of the buffer may be either 16 or 32-bits.  As such we cannot
    158	 * 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			 const struct i2c_device_id *id)
    235{
    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 int 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	return 0;
    302}
    303
    304static int mpl3115_suspend(struct device *dev)
    305{
    306	return mpl3115_standby(iio_priv(i2c_get_clientdata(
    307		to_i2c_client(dev))));
    308}
    309
    310static int mpl3115_resume(struct device *dev)
    311{
    312	struct mpl3115_data *data = iio_priv(i2c_get_clientdata(
    313		to_i2c_client(dev)));
    314
    315	return i2c_smbus_write_byte_data(data->client, MPL3115_CTRL_REG1,
    316		data->ctrl_reg1);
    317}
    318
    319static DEFINE_SIMPLE_DEV_PM_OPS(mpl3115_pm_ops, mpl3115_suspend,
    320				mpl3115_resume);
    321
    322static const struct i2c_device_id mpl3115_id[] = {
    323	{ "mpl3115", 0 },
    324	{ }
    325};
    326MODULE_DEVICE_TABLE(i2c, mpl3115_id);
    327
    328static const struct of_device_id mpl3115_of_match[] = {
    329	{ .compatible = "fsl,mpl3115" },
    330	{ }
    331};
    332MODULE_DEVICE_TABLE(of, mpl3115_of_match);
    333
    334static struct i2c_driver mpl3115_driver = {
    335	.driver = {
    336		.name	= "mpl3115",
    337		.of_match_table = mpl3115_of_match,
    338		.pm	= pm_sleep_ptr(&mpl3115_pm_ops),
    339	},
    340	.probe = mpl3115_probe,
    341	.remove = mpl3115_remove,
    342	.id_table = mpl3115_id,
    343};
    344module_i2c_driver(mpl3115_driver);
    345
    346MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
    347MODULE_DESCRIPTION("Freescale MPL3115 pressure/temperature driver");
    348MODULE_LICENSE("GPL");