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 130 enum 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 140 static const u8 adis16203_addresses[] = { 141 [ADIS16203_SCAN_INCLI_X] = ADIS16203_INCL_NULL, 142 }; 143 144 static 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 157 static 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 208 static 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 220 static 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 226 static 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 234 static 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 240 static 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 259 static 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 295 static const struct of_device_id adis16203_of_match[] = { 296 { .compatible = "adi,adis16203" }, 297 { }, 298 }; 299 300 MODULE_DEVICE_TABLE(of, adis16203_of_match); 301 302 static struct spi_driver adis16203_driver = { 303 .driver = { 304 .name = "adis16203", 305 .of_match_table = adis16203_of_match, 306 }, 307 .probe = adis16203_probe, 308 }; 309 module_spi_driver(adis16203_driver); 310 311 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 312 MODULE_DESCRIPTION("Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer"); 313 MODULE_LICENSE("GPL v2"); 314 MODULE_ALIAS("spi:adis16203"); 315 MODULE_IMPORT_NS(IIO_ADISLIB); 316