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

ms5637.c (6600B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * ms5637.c - Support for Measurement-Specialties MS5637, MS5805
      4 *            MS5837 and MS8607 pressure & temperature sensor
      5 *
      6 * Copyright (c) 2015 Measurement-Specialties
      7 *
      8 * (7-bit I2C slave address 0x76)
      9 *
     10 * Datasheet:
     11 *  http://www.meas-spec.com/downloads/MS5637-02BA03.pdf
     12 * Datasheet:
     13 *  http://www.meas-spec.com/downloads/MS5805-02BA01.pdf
     14 * Datasheet:
     15 *  http://www.meas-spec.com/downloads/MS5837-30BA.pdf
     16 * Datasheet:
     17 *  http://www.meas-spec.com/downloads/MS8607-02BA01.pdf
     18 */
     19
     20#include <linux/init.h>
     21#include <linux/device.h>
     22#include <linux/kernel.h>
     23#include <linux/stat.h>
     24#include <linux/module.h>
     25#include <linux/mod_devicetable.h>
     26#include <linux/i2c.h>
     27#include <linux/iio/iio.h>
     28#include <linux/iio/sysfs.h>
     29#include <linux/mutex.h>
     30
     31#include "../common/ms_sensors/ms_sensors_i2c.h"
     32
     33struct ms_tp_data {
     34	const char *name;
     35	const struct ms_tp_hw_data *hw;
     36};
     37
     38static const int ms5637_samp_freq[6] = { 960, 480, 240, 120, 60, 30 };
     39
     40static ssize_t ms5637_show_samp_freq(struct device *dev, struct device_attribute *attr, char *buf)
     41{
     42	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
     43	struct ms_tp_dev *dev_data = iio_priv(indio_dev);
     44	int i, len = 0;
     45
     46	for (i = 0; i <= dev_data->hw->max_res_index; i++)
     47		len += sysfs_emit_at(buf, len, "%u ", ms5637_samp_freq[i]);
     48	sysfs_emit_at(buf, len - 1, "\n");
     49
     50	return len;
     51}
     52
     53static int ms5637_read_raw(struct iio_dev *indio_dev,
     54			   struct iio_chan_spec const *channel, int *val,
     55			   int *val2, long mask)
     56{
     57	int ret;
     58	int temperature;
     59	unsigned int pressure;
     60	struct ms_tp_dev *dev_data = iio_priv(indio_dev);
     61
     62	switch (mask) {
     63	case IIO_CHAN_INFO_PROCESSED:
     64		ret = ms_sensors_read_temp_and_pressure(dev_data,
     65							&temperature,
     66							&pressure);
     67		if (ret)
     68			return ret;
     69
     70		switch (channel->type) {
     71		case IIO_TEMP:	/* in milli °C */
     72			*val = temperature;
     73
     74			return IIO_VAL_INT;
     75		case IIO_PRESSURE:	/* in kPa */
     76			*val = pressure / 1000;
     77			*val2 = (pressure % 1000) * 1000;
     78
     79			return IIO_VAL_INT_PLUS_MICRO;
     80		default:
     81			return -EINVAL;
     82		}
     83	case IIO_CHAN_INFO_SAMP_FREQ:
     84		*val = ms5637_samp_freq[dev_data->res_index];
     85
     86		return IIO_VAL_INT;
     87	default:
     88		return -EINVAL;
     89	}
     90}
     91
     92static int ms5637_write_raw(struct iio_dev *indio_dev,
     93			    struct iio_chan_spec const *chan,
     94			    int val, int val2, long mask)
     95{
     96	struct ms_tp_dev *dev_data = iio_priv(indio_dev);
     97	int i;
     98
     99	switch (mask) {
    100	case IIO_CHAN_INFO_SAMP_FREQ:
    101		i = ARRAY_SIZE(ms5637_samp_freq);
    102		while (i-- > 0)
    103			if (val == ms5637_samp_freq[i])
    104				break;
    105		if (i < 0)
    106			return -EINVAL;
    107		dev_data->res_index = i;
    108
    109		return 0;
    110	default:
    111		return -EINVAL;
    112	}
    113}
    114
    115static const struct iio_chan_spec ms5637_channels[] = {
    116	{
    117		.type = IIO_TEMP,
    118		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
    119		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
    120	},
    121	{
    122		.type = IIO_PRESSURE,
    123		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
    124		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
    125	}
    126};
    127
    128static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(ms5637_show_samp_freq);
    129
    130static struct attribute *ms5637_attributes[] = {
    131	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
    132	NULL,
    133};
    134
    135static const struct attribute_group ms5637_attribute_group = {
    136	.attrs = ms5637_attributes,
    137};
    138
    139static const struct iio_info ms5637_info = {
    140	.read_raw = ms5637_read_raw,
    141	.write_raw = ms5637_write_raw,
    142	.attrs = &ms5637_attribute_group,
    143};
    144
    145static int ms5637_probe(struct i2c_client *client,
    146			const struct i2c_device_id *id)
    147{
    148	const struct ms_tp_data *data;
    149	struct ms_tp_dev *dev_data;
    150	struct iio_dev *indio_dev;
    151	int ret;
    152
    153	if (!i2c_check_functionality(client->adapter,
    154				     I2C_FUNC_SMBUS_READ_WORD_DATA |
    155				     I2C_FUNC_SMBUS_WRITE_BYTE |
    156				     I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
    157		dev_err(&client->dev,
    158			"Adapter does not support some i2c transaction\n");
    159		return -EOPNOTSUPP;
    160	}
    161
    162	if (id)
    163		data = (const struct ms_tp_data *)id->driver_data;
    164	else
    165		data = device_get_match_data(&client->dev);
    166	if (!data)
    167		return -EINVAL;
    168
    169	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*dev_data));
    170	if (!indio_dev)
    171		return -ENOMEM;
    172
    173	dev_data = iio_priv(indio_dev);
    174	dev_data->client = client;
    175	dev_data->res_index = data->hw->max_res_index;
    176	dev_data->hw = data->hw;
    177	mutex_init(&dev_data->lock);
    178
    179	indio_dev->info = &ms5637_info;
    180	indio_dev->name = data->name;
    181	indio_dev->modes = INDIO_DIRECT_MODE;
    182	indio_dev->channels = ms5637_channels;
    183	indio_dev->num_channels = ARRAY_SIZE(ms5637_channels);
    184
    185	i2c_set_clientdata(client, indio_dev);
    186
    187	ret = ms_sensors_reset(client, 0x1E, 3000);
    188	if (ret)
    189		return ret;
    190
    191	ret = ms_sensors_tp_read_prom(dev_data);
    192	if (ret)
    193		return ret;
    194
    195	return devm_iio_device_register(&client->dev, indio_dev);
    196}
    197
    198static const struct ms_tp_hw_data ms5637_hw_data  = {
    199	.prom_len = 7,
    200	.max_res_index = 5
    201};
    202
    203static const struct ms_tp_hw_data ms5803_hw_data  = {
    204	.prom_len = 8,
    205	.max_res_index = 4
    206};
    207
    208static const struct ms_tp_data ms5637_data = { .name = "ms5637", .hw = &ms5637_hw_data };
    209
    210static const struct ms_tp_data ms5803_data = { .name = "ms5803", .hw = &ms5803_hw_data };
    211
    212static const struct ms_tp_data ms5805_data = { .name = "ms5805", .hw = &ms5637_hw_data };
    213
    214static const struct ms_tp_data ms5837_data = { .name = "ms5837", .hw = &ms5637_hw_data };
    215
    216static const struct ms_tp_data ms8607_data = {
    217	.name = "ms8607-temppressure",
    218	.hw = &ms5637_hw_data,
    219};
    220
    221static const struct i2c_device_id ms5637_id[] = {
    222	{"ms5637", (kernel_ulong_t)&ms5637_data },
    223	{"ms5805", (kernel_ulong_t)&ms5805_data },
    224	{"ms5837", (kernel_ulong_t)&ms5837_data },
    225	{"ms8607-temppressure", (kernel_ulong_t)&ms8607_data },
    226	{}
    227};
    228MODULE_DEVICE_TABLE(i2c, ms5637_id);
    229
    230static const struct of_device_id ms5637_of_match[] = {
    231	{ .compatible = "meas,ms5637", .data = &ms5637_data },
    232	{ .compatible = "meas,ms5803", .data = &ms5803_data },
    233	{ .compatible = "meas,ms5805", .data = &ms5805_data },
    234	{ .compatible = "meas,ms5837", .data = &ms5837_data },
    235	{ .compatible = "meas,ms8607-temppressure", .data = &ms8607_data },
    236	{ },
    237};
    238MODULE_DEVICE_TABLE(of, ms5637_of_match);
    239
    240static struct i2c_driver ms5637_driver = {
    241	.probe = ms5637_probe,
    242	.id_table = ms5637_id,
    243	.driver = {
    244		   .name = "ms5637",
    245		   .of_match_table = ms5637_of_match,
    246		   },
    247};
    248
    249module_i2c_driver(ms5637_driver);
    250
    251MODULE_DESCRIPTION("Measurement-Specialties ms5637 temperature & pressure driver");
    252MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
    253MODULE_AUTHOR("Ludovic Tancerel <ludovic.tancerel@maplehightech.com>");
    254MODULE_LICENSE("GPL v2");
    255MODULE_IMPORT_NS(IIO_MEAS_SPEC_SENSORS);