adis16203.c (8504B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * ADIS16203 Programmable 360 Degrees Inclinometer 4 * 5 * Copyright 2010 Analog Devices Inc. 6 */ 7 8#include <linux/device.h> 9 10#include <linux/iio/iio.h> 11#include <linux/iio/imu/adis.h> 12 13#include <linux/kernel.h> 14#include <linux/module.h> 15#include <linux/spi/spi.h> 16 17#define ADIS16203_STARTUP_DELAY 220 /* ms */ 18 19/* Flash memory write count */ 20#define ADIS16203_FLASH_CNT 0x00 21 22/* Output, power supply */ 23#define ADIS16203_SUPPLY_OUT 0x02 24 25/* Output, auxiliary ADC input */ 26#define ADIS16203_AUX_ADC 0x08 27 28/* Output, temperature */ 29#define ADIS16203_TEMP_OUT 0x0A 30 31/* Output, x-axis inclination */ 32#define ADIS16203_XINCL_OUT 0x0C 33 34/* Output, y-axis inclination */ 35#define ADIS16203_YINCL_OUT 0x0E 36 37/* Incline null calibration */ 38#define ADIS16203_INCL_NULL 0x18 39 40/* Alarm 1 amplitude threshold */ 41#define ADIS16203_ALM_MAG1 0x20 42 43/* Alarm 2 amplitude threshold */ 44#define ADIS16203_ALM_MAG2 0x22 45 46/* Alarm 1, sample period */ 47#define ADIS16203_ALM_SMPL1 0x24 48 49/* Alarm 2, sample period */ 50#define ADIS16203_ALM_SMPL2 0x26 51 52/* Alarm control */ 53#define ADIS16203_ALM_CTRL 0x28 54 55/* Auxiliary DAC data */ 56#define ADIS16203_AUX_DAC 0x30 57 58/* General-purpose digital input/output control */ 59#define ADIS16203_GPIO_CTRL 0x32 60 61/* Miscellaneous control */ 62#define ADIS16203_MSC_CTRL 0x34 63 64/* Internal sample period (rate) control */ 65#define ADIS16203_SMPL_PRD 0x36 66 67/* Operation, filter configuration */ 68#define ADIS16203_AVG_CNT 0x38 69 70/* Operation, sleep mode control */ 71#define ADIS16203_SLP_CNT 0x3A 72 73/* Diagnostics, system status register */ 74#define ADIS16203_DIAG_STAT 0x3C 75 76/* Operation, system command register */ 77#define ADIS16203_GLOB_CMD 0x3E 78 79/* MSC_CTRL */ 80 81/* Self-test at power-on: 1 = disabled, 0 = enabled */ 82#define ADIS16203_MSC_CTRL_PWRUP_SELF_TEST BIT(10) 83 84/* Reverses rotation of both inclination outputs */ 85#define ADIS16203_MSC_CTRL_REVERSE_ROT_EN BIT(9) 86 87/* Self-test enable */ 88#define ADIS16203_MSC_CTRL_SELF_TEST_EN BIT(8) 89 90/* Data-ready enable: 1 = enabled, 0 = disabled */ 91#define ADIS16203_MSC_CTRL_DATA_RDY_EN BIT(2) 92 93/* Data-ready polarity: 1 = active high, 0 = active low */ 94#define ADIS16203_MSC_CTRL_ACTIVE_HIGH BIT(1) 95 96/* Data-ready line selection: 1 = DIO1, 0 = DIO0 */ 97#define ADIS16203_MSC_CTRL_DATA_RDY_DIO1 BIT(0) 98 99/* DIAG_STAT */ 100 101/* Alarm 2 status: 1 = alarm active, 0 = alarm inactive */ 102#define ADIS16203_DIAG_STAT_ALARM2 BIT(9) 103 104/* Alarm 1 status: 1 = alarm active, 0 = alarm inactive */ 105#define ADIS16203_DIAG_STAT_ALARM1 BIT(8) 106 107/* Self-test diagnostic error flag */ 108#define ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT 5 109 110/* SPI communications failure */ 111#define ADIS16203_DIAG_STAT_SPI_FAIL_BIT 3 112 113/* Flash update failure */ 114#define ADIS16203_DIAG_STAT_FLASH_UPT_BIT 2 115 116/* Power supply above 3.625 V */ 117#define ADIS16203_DIAG_STAT_POWER_HIGH_BIT 1 118 119/* Power supply below 2.975 V */ 120#define ADIS16203_DIAG_STAT_POWER_LOW_BIT 0 121 122/* GLOB_CMD */ 123 124#define ADIS16203_GLOB_CMD_SW_RESET BIT(7) 125#define ADIS16203_GLOB_CMD_CLEAR_STAT BIT(4) 126#define ADIS16203_GLOB_CMD_FACTORY_CAL BIT(1) 127 128#define ADIS16203_ERROR_ACTIVE BIT(14) 129 130enum adis16203_scan { 131 ADIS16203_SCAN_INCLI_X, 132 ADIS16203_SCAN_INCLI_Y, 133 ADIS16203_SCAN_SUPPLY, 134 ADIS16203_SCAN_AUX_ADC, 135 ADIS16203_SCAN_TEMP, 136}; 137 138#define DRIVER_NAME "adis16203" 139 140static const u8 adis16203_addresses[] = { 141 [ADIS16203_SCAN_INCLI_X] = ADIS16203_INCL_NULL, 142}; 143 144static int adis16203_write_raw(struct iio_dev *indio_dev, 145 struct iio_chan_spec const *chan, 146 int val, 147 int val2, 148 long mask) 149{ 150 struct adis *st = iio_priv(indio_dev); 151 /* currently only one writable parameter which keeps this simple */ 152 u8 addr = adis16203_addresses[chan->scan_index]; 153 154 return adis_write_reg_16(st, addr, val & 0x3FFF); 155} 156 157static int adis16203_read_raw(struct iio_dev *indio_dev, 158 struct iio_chan_spec const *chan, 159 int *val, int *val2, 160 long mask) 161{ 162 struct adis *st = iio_priv(indio_dev); 163 int ret; 164 u8 addr; 165 s16 val16; 166 167 switch (mask) { 168 case IIO_CHAN_INFO_RAW: 169 return adis_single_conversion(indio_dev, chan, 170 ADIS16203_ERROR_ACTIVE, val); 171 case IIO_CHAN_INFO_SCALE: 172 switch (chan->type) { 173 case IIO_VOLTAGE: 174 if (chan->channel == 0) { 175 *val = 1; 176 *val2 = 220000; /* 1.22 mV */ 177 } else { 178 *val = 0; 179 *val2 = 610000; /* 0.61 mV */ 180 } 181 return IIO_VAL_INT_PLUS_MICRO; 182 case IIO_TEMP: 183 *val = -470; /* -0.47 C */ 184 *val2 = 0; 185 return IIO_VAL_INT_PLUS_MICRO; 186 case IIO_INCLI: 187 *val = 0; 188 *val2 = 25000; /* 0.025 degree */ 189 return IIO_VAL_INT_PLUS_MICRO; 190 default: 191 return -EINVAL; 192 } 193 case IIO_CHAN_INFO_OFFSET: 194 *val = 25000 / -470 - 1278; /* 25 C = 1278 */ 195 return IIO_VAL_INT; 196 case IIO_CHAN_INFO_CALIBBIAS: 197 addr = adis16203_addresses[chan->scan_index]; 198 ret = adis_read_reg_16(st, addr, &val16); 199 if (ret) 200 return ret; 201 *val = sign_extend32(val16, 13); 202 return IIO_VAL_INT; 203 default: 204 return -EINVAL; 205 } 206} 207 208static const struct iio_chan_spec adis16203_channels[] = { 209 ADIS_SUPPLY_CHAN(ADIS16203_SUPPLY_OUT, ADIS16203_SCAN_SUPPLY, 0, 12), 210 ADIS_AUX_ADC_CHAN(ADIS16203_AUX_ADC, ADIS16203_SCAN_AUX_ADC, 0, 12), 211 ADIS_INCLI_CHAN(X, ADIS16203_XINCL_OUT, ADIS16203_SCAN_INCLI_X, 212 BIT(IIO_CHAN_INFO_CALIBBIAS), 0, 14), 213 /* Fixme: Not what it appears to be - see data sheet */ 214 ADIS_INCLI_CHAN(Y, ADIS16203_YINCL_OUT, ADIS16203_SCAN_INCLI_Y, 215 0, 0, 14), 216 ADIS_TEMP_CHAN(ADIS16203_TEMP_OUT, ADIS16203_SCAN_TEMP, 0, 12), 217 IIO_CHAN_SOFT_TIMESTAMP(5), 218}; 219 220static const struct iio_info adis16203_info = { 221 .read_raw = adis16203_read_raw, 222 .write_raw = adis16203_write_raw, 223 .update_scan_mode = adis_update_scan_mode, 224}; 225 226static const char * const adis16203_status_error_msgs[] = { 227 [ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT] = "Self test failure", 228 [ADIS16203_DIAG_STAT_SPI_FAIL_BIT] = "SPI failure", 229 [ADIS16203_DIAG_STAT_FLASH_UPT_BIT] = "Flash update failed", 230 [ADIS16203_DIAG_STAT_POWER_HIGH_BIT] = "Power supply above 3.625V", 231 [ADIS16203_DIAG_STAT_POWER_LOW_BIT] = "Power supply below 2.975V", 232}; 233 234static const struct adis_timeout adis16203_timeouts = { 235 .reset_ms = ADIS16203_STARTUP_DELAY, 236 .sw_reset_ms = ADIS16203_STARTUP_DELAY, 237 .self_test_ms = ADIS16203_STARTUP_DELAY 238}; 239 240static const struct adis_data adis16203_data = { 241 .read_delay = 20, 242 .msc_ctrl_reg = ADIS16203_MSC_CTRL, 243 .glob_cmd_reg = ADIS16203_GLOB_CMD, 244 .diag_stat_reg = ADIS16203_DIAG_STAT, 245 246 .self_test_mask = ADIS16203_MSC_CTRL_SELF_TEST_EN, 247 .self_test_reg = ADIS16203_MSC_CTRL, 248 .self_test_no_autoclear = true, 249 .timeouts = &adis16203_timeouts, 250 251 .status_error_msgs = adis16203_status_error_msgs, 252 .status_error_mask = BIT(ADIS16203_DIAG_STAT_SELFTEST_FAIL_BIT) | 253 BIT(ADIS16203_DIAG_STAT_SPI_FAIL_BIT) | 254 BIT(ADIS16203_DIAG_STAT_FLASH_UPT_BIT) | 255 BIT(ADIS16203_DIAG_STAT_POWER_HIGH_BIT) | 256 BIT(ADIS16203_DIAG_STAT_POWER_LOW_BIT), 257}; 258 259static int adis16203_probe(struct spi_device *spi) 260{ 261 int ret; 262 struct iio_dev *indio_dev; 263 struct adis *st; 264 265 /* setup the industrialio driver allocated elements */ 266 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 267 if (!indio_dev) 268 return -ENOMEM; 269 st = iio_priv(indio_dev); 270 /* this is only used for removal purposes */ 271 spi_set_drvdata(spi, indio_dev); 272 273 indio_dev->name = spi->dev.driver->name; 274 indio_dev->channels = adis16203_channels; 275 indio_dev->num_channels = ARRAY_SIZE(adis16203_channels); 276 indio_dev->info = &adis16203_info; 277 indio_dev->modes = INDIO_DIRECT_MODE; 278 279 ret = adis_init(st, indio_dev, spi, &adis16203_data); 280 if (ret) 281 return ret; 282 283 ret = devm_adis_setup_buffer_and_trigger(st, indio_dev, NULL); 284 if (ret) 285 return ret; 286 287 /* Get the device into a sane initial state */ 288 ret = adis_initial_startup(st); 289 if (ret) 290 return ret; 291 292 return devm_iio_device_register(&spi->dev, indio_dev); 293} 294 295static const struct of_device_id adis16203_of_match[] = { 296 { .compatible = "adi,adis16203" }, 297 { }, 298}; 299 300MODULE_DEVICE_TABLE(of, adis16203_of_match); 301 302static struct spi_driver adis16203_driver = { 303 .driver = { 304 .name = "adis16203", 305 .of_match_table = adis16203_of_match, 306 }, 307 .probe = adis16203_probe, 308}; 309module_spi_driver(adis16203_driver); 310 311MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 312MODULE_DESCRIPTION("Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer"); 313MODULE_LICENSE("GPL v2"); 314MODULE_ALIAS("spi:adis16203"); 315MODULE_IMPORT_NS(IIO_ADISLIB);