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

mag3110.c (15337B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * mag3110.c - Support for Freescale MAG3110 magnetometer sensor
      4 *
      5 * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net>
      6 *
      7 * (7-bit I2C slave address 0x0e)
      8 *
      9 * TODO: irq, user offset, oversampling, continuous mode
     10 */
     11
     12#include <linux/module.h>
     13#include <linux/i2c.h>
     14#include <linux/iio/iio.h>
     15#include <linux/iio/sysfs.h>
     16#include <linux/iio/trigger_consumer.h>
     17#include <linux/iio/buffer.h>
     18#include <linux/iio/triggered_buffer.h>
     19#include <linux/delay.h>
     20#include <linux/regulator/consumer.h>
     21
     22#define MAG3110_STATUS 0x00
     23#define MAG3110_OUT_X 0x01 /* MSB first */
     24#define MAG3110_OUT_Y 0x03
     25#define MAG3110_OUT_Z 0x05
     26#define MAG3110_WHO_AM_I 0x07
     27#define MAG3110_SYSMOD 0x08
     28#define MAG3110_OFF_X 0x09 /* MSB first */
     29#define MAG3110_OFF_Y 0x0b
     30#define MAG3110_OFF_Z 0x0d
     31#define MAG3110_DIE_TEMP 0x0f
     32#define MAG3110_CTRL_REG1 0x10
     33#define MAG3110_CTRL_REG2 0x11
     34
     35#define MAG3110_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
     36
     37#define MAG3110_CTRL_DR_MASK (BIT(7) | BIT(6) | BIT(5))
     38#define MAG3110_CTRL_DR_SHIFT 5
     39#define MAG3110_CTRL_DR_DEFAULT 0
     40
     41#define MAG3110_SYSMOD_MODE_MASK GENMASK(1, 0)
     42
     43#define MAG3110_CTRL_TM BIT(1) /* trigger single measurement */
     44#define MAG3110_CTRL_AC BIT(0) /* continuous measurements */
     45
     46#define MAG3110_CTRL_AUTO_MRST_EN BIT(7) /* magnetic auto-reset */
     47#define MAG3110_CTRL_RAW BIT(5) /* measurements not user-offset corrected */
     48
     49#define MAG3110_DEVICE_ID 0xc4
     50
     51/* Each client has this additional data */
     52struct mag3110_data {
     53	struct i2c_client *client;
     54	struct mutex lock;
     55	u8 ctrl_reg1;
     56	int sleep_val;
     57	struct regulator *vdd_reg;
     58	struct regulator *vddio_reg;
     59	/* Ensure natural alignment of timestamp */
     60	struct {
     61		__be16 channels[3];
     62		u8 temperature;
     63		s64 ts __aligned(8);
     64	} scan;
     65};
     66
     67static int mag3110_request(struct mag3110_data *data)
     68{
     69	int ret, tries = 150;
     70
     71	if ((data->ctrl_reg1 & MAG3110_CTRL_AC) == 0) {
     72		/* trigger measurement */
     73		ret = i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
     74			data->ctrl_reg1 | MAG3110_CTRL_TM);
     75		if (ret < 0)
     76			return ret;
     77	}
     78
     79	while (tries-- > 0) {
     80		ret = i2c_smbus_read_byte_data(data->client, MAG3110_STATUS);
     81		if (ret < 0)
     82			return ret;
     83		/* wait for data ready */
     84		if ((ret & MAG3110_STATUS_DRDY) == MAG3110_STATUS_DRDY)
     85			break;
     86
     87		if (data->sleep_val <= 20)
     88			usleep_range(data->sleep_val * 250, data->sleep_val * 500);
     89		else
     90			msleep(20);
     91	}
     92
     93	if (tries < 0) {
     94		dev_err(&data->client->dev, "data not ready\n");
     95		return -EIO;
     96	}
     97
     98	return 0;
     99}
    100
    101static int mag3110_read(struct mag3110_data *data, __be16 buf[3])
    102{
    103	int ret;
    104
    105	mutex_lock(&data->lock);
    106	ret = mag3110_request(data);
    107	if (ret < 0) {
    108		mutex_unlock(&data->lock);
    109		return ret;
    110	}
    111	ret = i2c_smbus_read_i2c_block_data(data->client,
    112		MAG3110_OUT_X, 3 * sizeof(__be16), (u8 *) buf);
    113	mutex_unlock(&data->lock);
    114
    115	return ret;
    116}
    117
    118static ssize_t mag3110_show_int_plus_micros(char *buf,
    119	const int (*vals)[2], int n)
    120{
    121	size_t len = 0;
    122
    123	while (n-- > 0)
    124		len += scnprintf(buf + len, PAGE_SIZE - len,
    125			"%d.%06d ", vals[n][0], vals[n][1]);
    126
    127	/* replace trailing space by newline */
    128	buf[len - 1] = '\n';
    129
    130	return len;
    131}
    132
    133static int mag3110_get_int_plus_micros_index(const int (*vals)[2], int n,
    134					int val, int val2)
    135{
    136	while (n-- > 0)
    137		if (val == vals[n][0] && val2 == vals[n][1])
    138			return n;
    139
    140	return -EINVAL;
    141}
    142
    143static const int mag3110_samp_freq[8][2] = {
    144	{80, 0}, {40, 0}, {20, 0}, {10, 0}, {5, 0}, {2, 500000},
    145	{1, 250000}, {0, 625000}
    146};
    147
    148static ssize_t mag3110_show_samp_freq_avail(struct device *dev,
    149				struct device_attribute *attr, char *buf)
    150{
    151	return mag3110_show_int_plus_micros(buf, mag3110_samp_freq, 8);
    152}
    153
    154static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(mag3110_show_samp_freq_avail);
    155
    156static int mag3110_get_samp_freq_index(struct mag3110_data *data,
    157	int val, int val2)
    158{
    159	return mag3110_get_int_plus_micros_index(mag3110_samp_freq, 8, val,
    160		val2);
    161}
    162
    163static int mag3110_calculate_sleep(struct mag3110_data *data)
    164{
    165	int ret, i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT;
    166
    167	if (mag3110_samp_freq[i][0] > 0)
    168		ret = 1000 / mag3110_samp_freq[i][0];
    169	else
    170		ret = 1000;
    171
    172	return ret == 0 ? 1 : ret;
    173}
    174
    175static int mag3110_standby(struct mag3110_data *data)
    176{
    177	return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
    178		data->ctrl_reg1 & ~MAG3110_CTRL_AC);
    179}
    180
    181static int mag3110_wait_standby(struct mag3110_data *data)
    182{
    183	int ret, tries = 30;
    184
    185	/*
    186	 * Takes up to 1/ODR to come out of active mode into stby
    187	 * Longest expected period is 12.5seconds.
    188	 * We'll sleep for 500ms between checks
    189	 */
    190	while (tries-- > 0) {
    191		ret = i2c_smbus_read_byte_data(data->client, MAG3110_SYSMOD);
    192		if (ret < 0) {
    193			dev_err(&data->client->dev, "i2c error\n");
    194			return ret;
    195		}
    196		/* wait for standby */
    197		if ((ret & MAG3110_SYSMOD_MODE_MASK) == 0)
    198			break;
    199
    200		msleep_interruptible(500);
    201	}
    202
    203	if (tries < 0) {
    204		dev_err(&data->client->dev, "device not entering standby mode\n");
    205		return -EIO;
    206	}
    207
    208	return 0;
    209}
    210
    211static int mag3110_active(struct mag3110_data *data)
    212{
    213	return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
    214					 data->ctrl_reg1);
    215}
    216
    217/* returns >0 if active, 0 if in standby and <0 on error */
    218static int mag3110_is_active(struct mag3110_data *data)
    219{
    220	int reg;
    221
    222	reg = i2c_smbus_read_byte_data(data->client, MAG3110_CTRL_REG1);
    223	if (reg < 0)
    224		return reg;
    225
    226	return reg & MAG3110_CTRL_AC;
    227}
    228
    229static int mag3110_change_config(struct mag3110_data *data, u8 reg, u8 val)
    230{
    231	int ret;
    232	int is_active;
    233
    234	mutex_lock(&data->lock);
    235
    236	is_active = mag3110_is_active(data);
    237	if (is_active < 0) {
    238		ret = is_active;
    239		goto fail;
    240	}
    241
    242	/* config can only be changed when in standby */
    243	if (is_active > 0) {
    244		ret = mag3110_standby(data);
    245		if (ret < 0)
    246			goto fail;
    247	}
    248
    249	/*
    250	 * After coming out of active we must wait for the part
    251	 * to transition to STBY. This can take up to 1 /ODR to occur
    252	 */
    253	ret = mag3110_wait_standby(data);
    254	if (ret < 0)
    255		goto fail;
    256
    257	ret = i2c_smbus_write_byte_data(data->client, reg, val);
    258	if (ret < 0)
    259		goto fail;
    260
    261	if (is_active > 0) {
    262		ret = mag3110_active(data);
    263		if (ret < 0)
    264			goto fail;
    265	}
    266
    267	ret = 0;
    268fail:
    269	mutex_unlock(&data->lock);
    270
    271	return ret;
    272}
    273
    274static int mag3110_read_raw(struct iio_dev *indio_dev,
    275			    struct iio_chan_spec const *chan,
    276			    int *val, int *val2, long mask)
    277{
    278	struct mag3110_data *data = iio_priv(indio_dev);
    279	__be16 buffer[3];
    280	int i, ret;
    281
    282	switch (mask) {
    283	case IIO_CHAN_INFO_RAW:
    284		ret = iio_device_claim_direct_mode(indio_dev);
    285		if (ret)
    286			return ret;
    287
    288		switch (chan->type) {
    289		case IIO_MAGN: /* in 0.1 uT / LSB */
    290			ret = mag3110_read(data, buffer);
    291			if (ret < 0)
    292				goto release;
    293			*val = sign_extend32(
    294				be16_to_cpu(buffer[chan->scan_index]),
    295					    chan->scan_type.realbits - 1);
    296			ret = IIO_VAL_INT;
    297			break;
    298		case IIO_TEMP: /* in 1 C / LSB */
    299			mutex_lock(&data->lock);
    300			ret = mag3110_request(data);
    301			if (ret < 0) {
    302				mutex_unlock(&data->lock);
    303				goto release;
    304			}
    305			ret = i2c_smbus_read_byte_data(data->client,
    306				MAG3110_DIE_TEMP);
    307			mutex_unlock(&data->lock);
    308			if (ret < 0)
    309				goto release;
    310			*val = sign_extend32(ret,
    311					     chan->scan_type.realbits - 1);
    312			ret = IIO_VAL_INT;
    313			break;
    314		default:
    315			ret = -EINVAL;
    316		}
    317release:
    318		iio_device_release_direct_mode(indio_dev);
    319		return ret;
    320
    321	case IIO_CHAN_INFO_SCALE:
    322		switch (chan->type) {
    323		case IIO_MAGN:
    324			*val = 0;
    325			*val2 = 1000;
    326			return IIO_VAL_INT_PLUS_MICRO;
    327		case IIO_TEMP:
    328			*val = 1000;
    329			return IIO_VAL_INT;
    330		default:
    331			return -EINVAL;
    332		}
    333	case IIO_CHAN_INFO_SAMP_FREQ:
    334		i = data->ctrl_reg1 >> MAG3110_CTRL_DR_SHIFT;
    335		*val = mag3110_samp_freq[i][0];
    336		*val2 = mag3110_samp_freq[i][1];
    337		return IIO_VAL_INT_PLUS_MICRO;
    338	case IIO_CHAN_INFO_CALIBBIAS:
    339		ret = i2c_smbus_read_word_swapped(data->client,
    340			MAG3110_OFF_X +	2 * chan->scan_index);
    341		if (ret < 0)
    342			return ret;
    343		*val = sign_extend32(ret >> 1, 14);
    344		return IIO_VAL_INT;
    345	}
    346	return -EINVAL;
    347}
    348
    349static int mag3110_write_raw(struct iio_dev *indio_dev,
    350			     struct iio_chan_spec const *chan,
    351			     int val, int val2, long mask)
    352{
    353	struct mag3110_data *data = iio_priv(indio_dev);
    354	int rate, ret;
    355
    356	ret = iio_device_claim_direct_mode(indio_dev);
    357	if (ret)
    358		return ret;
    359
    360	switch (mask) {
    361	case IIO_CHAN_INFO_SAMP_FREQ:
    362		rate = mag3110_get_samp_freq_index(data, val, val2);
    363		if (rate < 0) {
    364			ret = -EINVAL;
    365			break;
    366		}
    367		data->ctrl_reg1 &= 0xff & ~MAG3110_CTRL_DR_MASK
    368					& ~MAG3110_CTRL_AC;
    369		data->ctrl_reg1 |= rate << MAG3110_CTRL_DR_SHIFT;
    370		data->sleep_val = mag3110_calculate_sleep(data);
    371		if (data->sleep_val < 40)
    372			data->ctrl_reg1 |= MAG3110_CTRL_AC;
    373
    374		ret = mag3110_change_config(data, MAG3110_CTRL_REG1,
    375					    data->ctrl_reg1);
    376		break;
    377	case IIO_CHAN_INFO_CALIBBIAS:
    378		if (val < -10000 || val > 10000) {
    379			ret = -EINVAL;
    380			break;
    381		}
    382		ret = i2c_smbus_write_word_swapped(data->client,
    383			MAG3110_OFF_X + 2 * chan->scan_index, val << 1);
    384		break;
    385	default:
    386		ret = -EINVAL;
    387		break;
    388	}
    389	iio_device_release_direct_mode(indio_dev);
    390	return ret;
    391}
    392
    393static irqreturn_t mag3110_trigger_handler(int irq, void *p)
    394{
    395	struct iio_poll_func *pf = p;
    396	struct iio_dev *indio_dev = pf->indio_dev;
    397	struct mag3110_data *data = iio_priv(indio_dev);
    398	int ret;
    399
    400	ret = mag3110_read(data, data->scan.channels);
    401	if (ret < 0)
    402		goto done;
    403
    404	if (test_bit(3, indio_dev->active_scan_mask)) {
    405		ret = i2c_smbus_read_byte_data(data->client,
    406			MAG3110_DIE_TEMP);
    407		if (ret < 0)
    408			goto done;
    409		data->scan.temperature = ret;
    410	}
    411
    412	iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
    413		iio_get_time_ns(indio_dev));
    414
    415done:
    416	iio_trigger_notify_done(indio_dev->trig);
    417	return IRQ_HANDLED;
    418}
    419
    420#define MAG3110_CHANNEL(axis, idx) { \
    421	.type = IIO_MAGN, \
    422	.modified = 1, \
    423	.channel2 = IIO_MOD_##axis, \
    424	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
    425		BIT(IIO_CHAN_INFO_CALIBBIAS), \
    426	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
    427		BIT(IIO_CHAN_INFO_SCALE), \
    428	.scan_index = idx, \
    429	.scan_type = { \
    430		.sign = 's', \
    431		.realbits = 16, \
    432		.storagebits = 16, \
    433		.endianness = IIO_BE, \
    434	}, \
    435}
    436
    437static const struct iio_chan_spec mag3110_channels[] = {
    438	MAG3110_CHANNEL(X, 0),
    439	MAG3110_CHANNEL(Y, 1),
    440	MAG3110_CHANNEL(Z, 2),
    441	{
    442		.type = IIO_TEMP,
    443		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
    444			BIT(IIO_CHAN_INFO_SCALE),
    445		.scan_index = 3,
    446		.scan_type = {
    447			.sign = 's',
    448			.realbits = 8,
    449			.storagebits = 8,
    450			},
    451	},
    452	IIO_CHAN_SOFT_TIMESTAMP(4),
    453};
    454
    455static struct attribute *mag3110_attributes[] = {
    456	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
    457	NULL
    458};
    459
    460static const struct attribute_group mag3110_group = {
    461	.attrs = mag3110_attributes,
    462};
    463
    464static const struct iio_info mag3110_info = {
    465	.attrs = &mag3110_group,
    466	.read_raw = &mag3110_read_raw,
    467	.write_raw = &mag3110_write_raw,
    468};
    469
    470static const unsigned long mag3110_scan_masks[] = {0x7, 0xf, 0};
    471
    472static int mag3110_probe(struct i2c_client *client,
    473			 const struct i2c_device_id *id)
    474{
    475	struct mag3110_data *data;
    476	struct iio_dev *indio_dev;
    477	int ret;
    478
    479	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
    480	if (!indio_dev)
    481		return -ENOMEM;
    482
    483	data = iio_priv(indio_dev);
    484
    485	data->vdd_reg = devm_regulator_get(&client->dev, "vdd");
    486	if (IS_ERR(data->vdd_reg))
    487		return dev_err_probe(&client->dev, PTR_ERR(data->vdd_reg),
    488				     "failed to get VDD regulator!\n");
    489
    490	data->vddio_reg = devm_regulator_get(&client->dev, "vddio");
    491	if (IS_ERR(data->vddio_reg))
    492		return dev_err_probe(&client->dev, PTR_ERR(data->vddio_reg),
    493				     "failed to get VDDIO regulator!\n");
    494
    495	ret = regulator_enable(data->vdd_reg);
    496	if (ret) {
    497		dev_err(&client->dev, "failed to enable VDD regulator!\n");
    498		return ret;
    499	}
    500
    501	ret = regulator_enable(data->vddio_reg);
    502	if (ret) {
    503		dev_err(&client->dev, "failed to enable VDDIO regulator!\n");
    504		goto disable_regulator_vdd;
    505	}
    506
    507	ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I);
    508	if (ret < 0)
    509		goto disable_regulators;
    510	if (ret != MAG3110_DEVICE_ID) {
    511		ret = -ENODEV;
    512		goto disable_regulators;
    513	}
    514
    515	data->client = client;
    516	mutex_init(&data->lock);
    517
    518	i2c_set_clientdata(client, indio_dev);
    519	indio_dev->info = &mag3110_info;
    520	indio_dev->name = id->name;
    521	indio_dev->modes = INDIO_DIRECT_MODE;
    522	indio_dev->channels = mag3110_channels;
    523	indio_dev->num_channels = ARRAY_SIZE(mag3110_channels);
    524	indio_dev->available_scan_masks = mag3110_scan_masks;
    525
    526	data->ctrl_reg1 = MAG3110_CTRL_DR_DEFAULT << MAG3110_CTRL_DR_SHIFT;
    527	data->sleep_val = mag3110_calculate_sleep(data);
    528	if (data->sleep_val < 40)
    529		data->ctrl_reg1 |= MAG3110_CTRL_AC;
    530
    531	ret = mag3110_change_config(data, MAG3110_CTRL_REG1, data->ctrl_reg1);
    532	if (ret < 0)
    533		goto disable_regulators;
    534
    535	ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2,
    536		MAG3110_CTRL_AUTO_MRST_EN);
    537	if (ret < 0)
    538		goto standby_on_error;
    539
    540	ret = iio_triggered_buffer_setup(indio_dev, NULL,
    541		mag3110_trigger_handler, NULL);
    542	if (ret < 0)
    543		goto standby_on_error;
    544
    545	ret = iio_device_register(indio_dev);
    546	if (ret < 0)
    547		goto buffer_cleanup;
    548	return 0;
    549
    550buffer_cleanup:
    551	iio_triggered_buffer_cleanup(indio_dev);
    552standby_on_error:
    553	mag3110_standby(iio_priv(indio_dev));
    554disable_regulators:
    555	regulator_disable(data->vddio_reg);
    556disable_regulator_vdd:
    557	regulator_disable(data->vdd_reg);
    558
    559	return ret;
    560}
    561
    562static int mag3110_remove(struct i2c_client *client)
    563{
    564	struct iio_dev *indio_dev = i2c_get_clientdata(client);
    565	struct mag3110_data *data = iio_priv(indio_dev);
    566
    567	iio_device_unregister(indio_dev);
    568	iio_triggered_buffer_cleanup(indio_dev);
    569	mag3110_standby(iio_priv(indio_dev));
    570	regulator_disable(data->vddio_reg);
    571	regulator_disable(data->vdd_reg);
    572
    573	return 0;
    574}
    575
    576static int mag3110_suspend(struct device *dev)
    577{
    578	struct mag3110_data *data = iio_priv(i2c_get_clientdata(
    579		to_i2c_client(dev)));
    580	int ret;
    581
    582	ret = mag3110_standby(iio_priv(i2c_get_clientdata(
    583		to_i2c_client(dev))));
    584	if (ret)
    585		return ret;
    586
    587	ret = regulator_disable(data->vddio_reg);
    588	if (ret) {
    589		dev_err(dev, "failed to disable VDDIO regulator\n");
    590		return ret;
    591	}
    592
    593	ret = regulator_disable(data->vdd_reg);
    594	if (ret) {
    595		dev_err(dev, "failed to disable VDD regulator\n");
    596		return ret;
    597	}
    598
    599	return 0;
    600}
    601
    602static int mag3110_resume(struct device *dev)
    603{
    604	struct mag3110_data *data = iio_priv(i2c_get_clientdata(
    605		to_i2c_client(dev)));
    606	int ret;
    607
    608	ret = regulator_enable(data->vdd_reg);
    609	if (ret) {
    610		dev_err(dev, "failed to enable VDD regulator\n");
    611		return ret;
    612	}
    613
    614	ret = regulator_enable(data->vddio_reg);
    615	if (ret) {
    616		dev_err(dev, "failed to enable VDDIO regulator\n");
    617		regulator_disable(data->vdd_reg);
    618		return ret;
    619	}
    620
    621	return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1,
    622		data->ctrl_reg1);
    623}
    624
    625static DEFINE_SIMPLE_DEV_PM_OPS(mag3110_pm_ops, mag3110_suspend,
    626				mag3110_resume);
    627
    628static const struct i2c_device_id mag3110_id[] = {
    629	{ "mag3110", 0 },
    630	{ }
    631};
    632MODULE_DEVICE_TABLE(i2c, mag3110_id);
    633
    634static const struct of_device_id mag3110_of_match[] = {
    635	{ .compatible = "fsl,mag3110" },
    636	{ }
    637};
    638MODULE_DEVICE_TABLE(of, mag3110_of_match);
    639
    640static struct i2c_driver mag3110_driver = {
    641	.driver = {
    642		.name	= "mag3110",
    643		.of_match_table = mag3110_of_match,
    644		.pm	= pm_sleep_ptr(&mag3110_pm_ops),
    645	},
    646	.probe = mag3110_probe,
    647	.remove = mag3110_remove,
    648	.id_table = mag3110_id,
    649};
    650module_i2c_driver(mag3110_driver);
    651
    652MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
    653MODULE_DESCRIPTION("Freescale MAG3110 magnetometer driver");
    654MODULE_LICENSE("GPL");