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

adis16260.c (13116B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * ADIS16260/ADIS16265 Programmable Digital Gyroscope Sensor Driver
      4 *
      5 * Copyright 2010 Analog Devices Inc.
      6 */
      7
      8#include <linux/device.h>
      9#include <linux/kernel.h>
     10#include <linux/spi/spi.h>
     11#include <linux/module.h>
     12
     13#include <linux/iio/iio.h>
     14#include <linux/iio/imu/adis.h>
     15
     16#define ADIS16260_STARTUP_DELAY	220 /* ms */
     17
     18#define ADIS16260_FLASH_CNT  0x00 /* Flash memory write count */
     19#define ADIS16260_SUPPLY_OUT 0x02 /* Power supply measurement */
     20#define ADIS16260_GYRO_OUT   0x04 /* X-axis gyroscope output */
     21#define ADIS16260_AUX_ADC    0x0A /* analog input channel measurement */
     22#define ADIS16260_TEMP_OUT   0x0C /* internal temperature measurement */
     23#define ADIS16260_ANGL_OUT   0x0E /* angle displacement */
     24#define ADIS16260_GYRO_OFF   0x14 /* Calibration, offset/bias adjustment */
     25#define ADIS16260_GYRO_SCALE 0x16 /* Calibration, scale adjustment */
     26#define ADIS16260_ALM_MAG1   0x20 /* Alarm 1 magnitude/polarity setting */
     27#define ADIS16260_ALM_MAG2   0x22 /* Alarm 2 magnitude/polarity setting */
     28#define ADIS16260_ALM_SMPL1  0x24 /* Alarm 1 dynamic rate of change setting */
     29#define ADIS16260_ALM_SMPL2  0x26 /* Alarm 2 dynamic rate of change setting */
     30#define ADIS16260_ALM_CTRL   0x28 /* Alarm control */
     31#define ADIS16260_AUX_DAC    0x30 /* Auxiliary DAC data */
     32#define ADIS16260_GPIO_CTRL  0x32 /* Control, digital I/O line */
     33#define ADIS16260_MSC_CTRL   0x34 /* Control, data ready, self-test settings */
     34#define ADIS16260_SMPL_PRD   0x36 /* Control, internal sample rate */
     35#define ADIS16260_SENS_AVG   0x38 /* Control, dynamic range, filtering */
     36#define ADIS16260_SLP_CNT    0x3A /* Control, sleep mode initiation */
     37#define ADIS16260_DIAG_STAT  0x3C /* Diagnostic, error flags */
     38#define ADIS16260_GLOB_CMD   0x3E /* Control, global commands */
     39#define ADIS16260_LOT_ID1    0x52 /* Lot Identification Code 1 */
     40#define ADIS16260_LOT_ID2    0x54 /* Lot Identification Code 2 */
     41#define ADIS16260_PROD_ID    0x56 /* Product identifier;
     42				   * convert to decimal = 16,265/16,260 */
     43#define ADIS16260_SERIAL_NUM 0x58 /* Serial number */
     44
     45#define ADIS16260_ERROR_ACTIVE			(1<<14)
     46#define ADIS16260_NEW_DATA			(1<<15)
     47
     48/* MSC_CTRL */
     49#define ADIS16260_MSC_CTRL_MEM_TEST		(1<<11)
     50/* Internal self-test enable */
     51#define ADIS16260_MSC_CTRL_INT_SELF_TEST	(1<<10)
     52#define ADIS16260_MSC_CTRL_NEG_SELF_TEST	(1<<9)
     53#define ADIS16260_MSC_CTRL_POS_SELF_TEST	(1<<8)
     54#define ADIS16260_MSC_CTRL_DATA_RDY_EN		(1<<2)
     55#define ADIS16260_MSC_CTRL_DATA_RDY_POL_HIGH	(1<<1)
     56#define ADIS16260_MSC_CTRL_DATA_RDY_DIO2	(1<<0)
     57
     58/* SMPL_PRD */
     59/* Time base (tB): 0 = 1.953 ms, 1 = 60.54 ms */
     60#define ADIS16260_SMPL_PRD_TIME_BASE	(1<<7)
     61#define ADIS16260_SMPL_PRD_DIV_MASK	0x7F
     62
     63/* SLP_CNT */
     64#define ADIS16260_SLP_CNT_POWER_OFF     0x80
     65
     66/* DIAG_STAT */
     67#define ADIS16260_DIAG_STAT_ALARM2	(1<<9)
     68#define ADIS16260_DIAG_STAT_ALARM1	(1<<8)
     69#define ADIS16260_DIAG_STAT_FLASH_CHK_BIT	6
     70#define ADIS16260_DIAG_STAT_SELF_TEST_BIT	5
     71#define ADIS16260_DIAG_STAT_OVERFLOW_BIT	4
     72#define ADIS16260_DIAG_STAT_SPI_FAIL_BIT	3
     73#define ADIS16260_DIAG_STAT_FLASH_UPT_BIT	2
     74#define ADIS16260_DIAG_STAT_POWER_HIGH_BIT	1
     75#define ADIS16260_DIAG_STAT_POWER_LOW_BIT	0
     76
     77/* GLOB_CMD */
     78#define ADIS16260_GLOB_CMD_SW_RESET	(1<<7)
     79#define ADIS16260_GLOB_CMD_FLASH_UPD	(1<<3)
     80#define ADIS16260_GLOB_CMD_DAC_LATCH	(1<<2)
     81#define ADIS16260_GLOB_CMD_FAC_CALIB	(1<<1)
     82#define ADIS16260_GLOB_CMD_AUTO_NULL	(1<<0)
     83
     84#define ADIS16260_SPI_SLOW	(u32)(300 * 1000)
     85#define ADIS16260_SPI_BURST	(u32)(1000 * 1000)
     86#define ADIS16260_SPI_FAST	(u32)(2000 * 1000)
     87
     88/* At the moment triggers are only used for ring buffer
     89 * filling. This may change!
     90 */
     91
     92#define ADIS16260_SCAN_GYRO	0
     93#define ADIS16260_SCAN_SUPPLY	1
     94#define ADIS16260_SCAN_AUX_ADC	2
     95#define ADIS16260_SCAN_TEMP	3
     96#define ADIS16260_SCAN_ANGL	4
     97
     98struct adis16260_chip_info {
     99	unsigned int gyro_max_val;
    100	unsigned int gyro_max_scale;
    101	const struct iio_chan_spec *channels;
    102	unsigned int num_channels;
    103};
    104
    105struct adis16260 {
    106	const struct adis16260_chip_info *info;
    107
    108	struct adis adis;
    109};
    110
    111enum adis16260_type {
    112	ADIS16251,
    113	ADIS16260,
    114	ADIS16266,
    115};
    116
    117static const struct iio_chan_spec adis16260_channels[] = {
    118	ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
    119		BIT(IIO_CHAN_INFO_CALIBBIAS) |
    120		BIT(IIO_CHAN_INFO_CALIBSCALE),
    121		BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
    122	ADIS_INCLI_CHAN(X, ADIS16260_ANGL_OUT, ADIS16260_SCAN_ANGL, 0,
    123		BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
    124	ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
    125		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
    126	ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
    127		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
    128	ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
    129		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
    130	IIO_CHAN_SOFT_TIMESTAMP(5),
    131};
    132
    133static const struct iio_chan_spec adis16266_channels[] = {
    134	ADIS_GYRO_CHAN(X, ADIS16260_GYRO_OUT, ADIS16260_SCAN_GYRO,
    135		BIT(IIO_CHAN_INFO_CALIBBIAS) |
    136		BIT(IIO_CHAN_INFO_CALIBSCALE),
    137		BIT(IIO_CHAN_INFO_SAMP_FREQ), 14),
    138	ADIS_TEMP_CHAN(ADIS16260_TEMP_OUT, ADIS16260_SCAN_TEMP,
    139		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
    140	ADIS_SUPPLY_CHAN(ADIS16260_SUPPLY_OUT, ADIS16260_SCAN_SUPPLY,
    141		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
    142	ADIS_AUX_ADC_CHAN(ADIS16260_AUX_ADC, ADIS16260_SCAN_AUX_ADC,
    143		BIT(IIO_CHAN_INFO_SAMP_FREQ), 12),
    144	IIO_CHAN_SOFT_TIMESTAMP(4),
    145};
    146
    147static const struct adis16260_chip_info adis16260_chip_info_table[] = {
    148	[ADIS16251] = {
    149		.gyro_max_scale = 80,
    150		.gyro_max_val = IIO_RAD_TO_DEGREE(4368),
    151		.channels = adis16260_channels,
    152		.num_channels = ARRAY_SIZE(adis16260_channels),
    153	},
    154	[ADIS16260] = {
    155		.gyro_max_scale = 320,
    156		.gyro_max_val = IIO_RAD_TO_DEGREE(4368),
    157		.channels = adis16260_channels,
    158		.num_channels = ARRAY_SIZE(adis16260_channels),
    159	},
    160	[ADIS16266] = {
    161		.gyro_max_scale = 14000,
    162		.gyro_max_val = IIO_RAD_TO_DEGREE(3357),
    163		.channels = adis16266_channels,
    164		.num_channels = ARRAY_SIZE(adis16266_channels),
    165	},
    166};
    167
    168/* Power down the device */
    169static int adis16260_stop_device(struct iio_dev *indio_dev)
    170{
    171	struct adis16260 *adis16260 = iio_priv(indio_dev);
    172	int ret;
    173	u16 val = ADIS16260_SLP_CNT_POWER_OFF;
    174
    175	ret = adis_write_reg_16(&adis16260->adis, ADIS16260_SLP_CNT, val);
    176	if (ret)
    177		dev_err(&indio_dev->dev, "problem with turning device off: SLP_CNT");
    178
    179	return ret;
    180}
    181
    182static const u8 adis16260_addresses[][2] = {
    183	[ADIS16260_SCAN_GYRO] = { ADIS16260_GYRO_OFF, ADIS16260_GYRO_SCALE },
    184};
    185
    186static int adis16260_read_raw(struct iio_dev *indio_dev,
    187			      struct iio_chan_spec const *chan,
    188			      int *val, int *val2,
    189			      long mask)
    190{
    191	struct adis16260 *adis16260 = iio_priv(indio_dev);
    192	const struct adis16260_chip_info *info = adis16260->info;
    193	struct adis *adis = &adis16260->adis;
    194	int ret;
    195	u8 addr;
    196	s16 val16;
    197
    198	switch (mask) {
    199	case IIO_CHAN_INFO_RAW:
    200		return adis_single_conversion(indio_dev, chan,
    201				ADIS16260_ERROR_ACTIVE, val);
    202	case IIO_CHAN_INFO_SCALE:
    203		switch (chan->type) {
    204		case IIO_ANGL_VEL:
    205			*val = info->gyro_max_scale;
    206			*val2 = info->gyro_max_val;
    207			return IIO_VAL_FRACTIONAL;
    208		case IIO_INCLI:
    209			*val = 0;
    210			*val2 = IIO_DEGREE_TO_RAD(36630);
    211			return IIO_VAL_INT_PLUS_MICRO;
    212		case IIO_VOLTAGE:
    213			if (chan->channel == 0) {
    214				*val = 1;
    215				*val2 = 831500; /* 1.8315 mV */
    216			} else {
    217				*val = 0;
    218				*val2 = 610500; /* 610.5 uV */
    219			}
    220			return IIO_VAL_INT_PLUS_MICRO;
    221		case IIO_TEMP:
    222			*val = 145;
    223			*val2 = 300000; /* 0.1453 C */
    224			return IIO_VAL_INT_PLUS_MICRO;
    225		default:
    226			return -EINVAL;
    227		}
    228	case IIO_CHAN_INFO_OFFSET:
    229		*val = 250000 / 1453; /* 25 C = 0x00 */
    230		return IIO_VAL_INT;
    231	case IIO_CHAN_INFO_CALIBBIAS:
    232		addr = adis16260_addresses[chan->scan_index][0];
    233		ret = adis_read_reg_16(adis, addr, &val16);
    234		if (ret)
    235			return ret;
    236
    237		*val = sign_extend32(val16, 11);
    238		return IIO_VAL_INT;
    239	case IIO_CHAN_INFO_CALIBSCALE:
    240		addr = adis16260_addresses[chan->scan_index][1];
    241		ret = adis_read_reg_16(adis, addr, &val16);
    242		if (ret)
    243			return ret;
    244
    245		*val = val16;
    246		return IIO_VAL_INT;
    247	case IIO_CHAN_INFO_SAMP_FREQ:
    248		ret = adis_read_reg_16(adis, ADIS16260_SMPL_PRD, &val16);
    249		if (ret)
    250			return ret;
    251
    252		if (spi_get_device_id(adis->spi)->driver_data)
    253		/* If an adis16251 */
    254			*val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
    255				8 : 256;
    256		else
    257			*val = (val16 & ADIS16260_SMPL_PRD_TIME_BASE) ?
    258				66 : 2048;
    259		*val /= (val16 & ADIS16260_SMPL_PRD_DIV_MASK) + 1;
    260		return IIO_VAL_INT;
    261	}
    262	return -EINVAL;
    263}
    264
    265static int adis16260_write_raw(struct iio_dev *indio_dev,
    266			       struct iio_chan_spec const *chan,
    267			       int val,
    268			       int val2,
    269			       long mask)
    270{
    271	struct adis16260 *adis16260 = iio_priv(indio_dev);
    272	struct adis *adis = &adis16260->adis;
    273	int ret;
    274	u8 addr;
    275	u8 t;
    276
    277	switch (mask) {
    278	case IIO_CHAN_INFO_CALIBBIAS:
    279		if (val < -2048 || val >= 2048)
    280			return -EINVAL;
    281
    282		addr = adis16260_addresses[chan->scan_index][0];
    283		return adis_write_reg_16(adis, addr, val);
    284	case IIO_CHAN_INFO_CALIBSCALE:
    285		if (val < 0 || val >= 4096)
    286			return -EINVAL;
    287
    288		addr = adis16260_addresses[chan->scan_index][1];
    289		return adis_write_reg_16(adis, addr, val);
    290	case IIO_CHAN_INFO_SAMP_FREQ:
    291		adis_dev_lock(adis);
    292		if (spi_get_device_id(adis->spi)->driver_data)
    293			t = 256 / val;
    294		else
    295			t = 2048 / val;
    296
    297		if (t > ADIS16260_SMPL_PRD_DIV_MASK)
    298			t = ADIS16260_SMPL_PRD_DIV_MASK;
    299		else if (t > 0)
    300			t--;
    301
    302		if (t >= 0x0A)
    303			adis->spi->max_speed_hz = ADIS16260_SPI_SLOW;
    304		else
    305			adis->spi->max_speed_hz = ADIS16260_SPI_FAST;
    306		ret = __adis_write_reg_8(adis, ADIS16260_SMPL_PRD, t);
    307
    308		adis_dev_unlock(adis);
    309		return ret;
    310	}
    311	return -EINVAL;
    312}
    313
    314static const struct iio_info adis16260_info = {
    315	.read_raw = &adis16260_read_raw,
    316	.write_raw = &adis16260_write_raw,
    317	.update_scan_mode = adis_update_scan_mode,
    318};
    319
    320static const char * const adis1620_status_error_msgs[] = {
    321	[ADIS16260_DIAG_STAT_FLASH_CHK_BIT] = "Flash checksum error",
    322	[ADIS16260_DIAG_STAT_SELF_TEST_BIT] = "Self test error",
    323	[ADIS16260_DIAG_STAT_OVERFLOW_BIT] = "Sensor overrange",
    324	[ADIS16260_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure",
    325	[ADIS16260_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed",
    326	[ADIS16260_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 5.25",
    327	[ADIS16260_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 4.75",
    328};
    329
    330static const struct adis_timeout adis16260_timeouts = {
    331	.reset_ms = ADIS16260_STARTUP_DELAY,
    332	.sw_reset_ms = ADIS16260_STARTUP_DELAY,
    333	.self_test_ms = ADIS16260_STARTUP_DELAY,
    334};
    335
    336static const struct adis_data adis16260_data = {
    337	.write_delay = 30,
    338	.read_delay = 30,
    339	.msc_ctrl_reg = ADIS16260_MSC_CTRL,
    340	.glob_cmd_reg = ADIS16260_GLOB_CMD,
    341	.diag_stat_reg = ADIS16260_DIAG_STAT,
    342
    343	.self_test_mask = ADIS16260_MSC_CTRL_MEM_TEST,
    344	.self_test_reg = ADIS16260_MSC_CTRL,
    345	.timeouts = &adis16260_timeouts,
    346
    347	.status_error_msgs = adis1620_status_error_msgs,
    348	.status_error_mask = BIT(ADIS16260_DIAG_STAT_FLASH_CHK_BIT) |
    349		BIT(ADIS16260_DIAG_STAT_SELF_TEST_BIT) |
    350		BIT(ADIS16260_DIAG_STAT_OVERFLOW_BIT) |
    351		BIT(ADIS16260_DIAG_STAT_SPI_FAIL_BIT) |
    352		BIT(ADIS16260_DIAG_STAT_FLASH_UPT_BIT) |
    353		BIT(ADIS16260_DIAG_STAT_POWER_HIGH_BIT) |
    354		BIT(ADIS16260_DIAG_STAT_POWER_LOW_BIT),
    355};
    356
    357static void adis16260_stop(void *data)
    358{
    359	adis16260_stop_device(data);
    360}
    361
    362static int adis16260_probe(struct spi_device *spi)
    363{
    364	const struct spi_device_id *id;
    365	struct adis16260 *adis16260;
    366	struct iio_dev *indio_dev;
    367	int ret;
    368
    369	id = spi_get_device_id(spi);
    370	if (!id)
    371		return -ENODEV;
    372
    373	/* setup the industrialio driver allocated elements */
    374	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adis16260));
    375	if (!indio_dev)
    376		return -ENOMEM;
    377	adis16260 = iio_priv(indio_dev);
    378	/* this is only used for removal purposes */
    379	spi_set_drvdata(spi, indio_dev);
    380
    381	adis16260->info = &adis16260_chip_info_table[id->driver_data];
    382
    383	indio_dev->name = id->name;
    384	indio_dev->info = &adis16260_info;
    385	indio_dev->channels = adis16260->info->channels;
    386	indio_dev->num_channels = adis16260->info->num_channels;
    387	indio_dev->modes = INDIO_DIRECT_MODE;
    388
    389	ret = adis_init(&adis16260->adis, indio_dev, spi, &adis16260_data);
    390	if (ret)
    391		return ret;
    392
    393	ret = devm_adis_setup_buffer_and_trigger(&adis16260->adis, indio_dev, NULL);
    394	if (ret)
    395		return ret;
    396
    397	/* Get the device into a sane initial state */
    398	ret = adis_initial_startup(&adis16260->adis);
    399	if (ret)
    400		return ret;
    401
    402	ret = devm_add_action_or_reset(&spi->dev, adis16260_stop, indio_dev);
    403	if (ret)
    404		return ret;
    405
    406	return devm_iio_device_register(&spi->dev, indio_dev);
    407}
    408
    409/*
    410 * These parts do not need to be differentiated until someone adds
    411 * support for the on chip filtering.
    412 */
    413static const struct spi_device_id adis16260_id[] = {
    414	{"adis16260", ADIS16260},
    415	{"adis16265", ADIS16260},
    416	{"adis16266", ADIS16266},
    417	{"adis16250", ADIS16260},
    418	{"adis16255", ADIS16260},
    419	{"adis16251", ADIS16251},
    420	{}
    421};
    422MODULE_DEVICE_TABLE(spi, adis16260_id);
    423
    424static struct spi_driver adis16260_driver = {
    425	.driver = {
    426		.name = "adis16260",
    427	},
    428	.probe = adis16260_probe,
    429	.id_table = adis16260_id,
    430};
    431module_spi_driver(adis16260_driver);
    432
    433MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
    434MODULE_DESCRIPTION("Analog Devices ADIS16260/5 Digital Gyroscope Sensor");
    435MODULE_LICENSE("GPL v2");
    436MODULE_IMPORT_NS(IIO_ADISLIB);