1 /* 2 * ADIS16130 Digital Output, High Precision Angular Rate Sensor driver 3 * 4 * Copyright 2010 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later. 7 */ 8 9 #include <linux/mutex.h> 10 #include <linux/kernel.h> 11 #include <linux/spi/spi.h> 12 #include <linux/module.h> 13 14 #include <linux/iio/iio.h> 15 16 #define ADIS16130_CON 0x0 17 #define ADIS16130_CON_RD (1 << 6) 18 #define ADIS16130_IOP 0x1 19 20 /* 1 = data-ready signal low when unread data on all channels; */ 21 #define ADIS16130_IOP_ALL_RDY (1 << 3) 22 #define ADIS16130_IOP_SYNC (1 << 0) /* 1 = synchronization enabled */ 23 #define ADIS16130_RATEDATA 0x8 /* Gyroscope output, rate of rotation */ 24 #define ADIS16130_TEMPDATA 0xA /* Temperature output */ 25 #define ADIS16130_RATECS 0x28 /* Gyroscope channel setup */ 26 #define ADIS16130_RATECS_EN (1 << 3) /* 1 = channel enable; */ 27 #define ADIS16130_TEMPCS 0x2A /* Temperature channel setup */ 28 #define ADIS16130_TEMPCS_EN (1 << 3) 29 #define ADIS16130_RATECONV 0x30 30 #define ADIS16130_TEMPCONV 0x32 31 #define ADIS16130_MODE 0x38 32 #define ADIS16130_MODE_24BIT (1 << 1) /* 1 = 24-bit resolution; */ 33 34 /** 35 * struct adis16130_state - device instance specific data 36 * @us: actual spi_device to write data 37 * @buf_lock: mutex to protect tx and rx 38 * @buf: unified tx/rx buffer 39 **/ 40 struct adis16130_state { 41 struct spi_device *us; 42 struct mutex buf_lock; 43 u8 buf[4] ____cacheline_aligned; 44 }; 45 46 static int adis16130_spi_read(struct iio_dev *indio_dev, u8 reg_addr, u32 *val) 47 { 48 int ret; 49 struct adis16130_state *st = iio_priv(indio_dev); 50 struct spi_message msg; 51 struct spi_transfer xfer = { 52 .tx_buf = st->buf, 53 .rx_buf = st->buf, 54 .len = 4, 55 }; 56 57 mutex_lock(&st->buf_lock); 58 59 st->buf[0] = ADIS16130_CON_RD | reg_addr; 60 st->buf[1] = st->buf[2] = st->buf[3] = 0; 61 62 spi_message_init(&msg); 63 spi_message_add_tail(&xfer, &msg); 64 ret = spi_sync(st->us, &msg); 65 66 if (ret == 0) 67 *val = (st->buf[1] << 16) | (st->buf[2] << 8) | st->buf[3]; 68 mutex_unlock(&st->buf_lock); 69 70 return ret; 71 } 72 73 static int adis16130_read_raw(struct iio_dev *indio_dev, 74 struct iio_chan_spec const *chan, 75 int *val, int *val2, 76 long mask) 77 { 78 int ret; 79 u32 temp; 80 81 switch (mask) { 82 case IIO_CHAN_INFO_RAW: 83 /* Take the iio_dev status lock */ 84 mutex_lock(&indio_dev->mlock); 85 ret = adis16130_spi_read(indio_dev, chan->address, &temp); 86 mutex_unlock(&indio_dev->mlock); 87 if (ret) 88 return ret; 89 *val = temp; 90 return IIO_VAL_INT; 91 case IIO_CHAN_INFO_SCALE: 92 switch (chan->type) { 93 case IIO_ANGL_VEL: 94 /* 0 degree = 838860, 250 degree = 14260608 */ 95 *val = 250; 96 *val2 = 336440817; /* RAD_TO_DEGREE(14260608 - 8388608) */ 97 return IIO_VAL_FRACTIONAL; 98 case IIO_TEMP: 99 /* 0C = 8036283, 105C = 9516048 */ 100 *val = 105000; 101 *val2 = 9516048 - 8036283; 102 return IIO_VAL_FRACTIONAL; 103 default: 104 return -EINVAL; 105 } 106 break; 107 case IIO_CHAN_INFO_OFFSET: 108 switch (chan->type) { 109 case IIO_ANGL_VEL: 110 *val = -8388608; 111 return IIO_VAL_INT; 112 case IIO_TEMP: 113 *val = -8036283; 114 return IIO_VAL_INT; 115 default: 116 return -EINVAL; 117 } 118 break; 119 } 120 121 return -EINVAL; 122 } 123 124 static const struct iio_chan_spec adis16130_channels[] = { 125 { 126 .type = IIO_ANGL_VEL, 127 .modified = 1, 128 .channel2 = IIO_MOD_Z, 129 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 130 BIT(IIO_CHAN_INFO_SCALE) | 131 BIT(IIO_CHAN_INFO_OFFSET), 132 .address = ADIS16130_RATEDATA, 133 }, { 134 .type = IIO_TEMP, 135 .indexed = 1, 136 .channel = 0, 137 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 138 BIT(IIO_CHAN_INFO_SCALE) | 139 BIT(IIO_CHAN_INFO_OFFSET), 140 .address = ADIS16130_TEMPDATA, 141 } 142 }; 143 144 static const struct iio_info adis16130_info = { 145 .read_raw = &adis16130_read_raw, 146 .driver_module = THIS_MODULE, 147 }; 148 149 static int adis16130_probe(struct spi_device *spi) 150 { 151 int ret; 152 struct adis16130_state *st; 153 struct iio_dev *indio_dev; 154 155 /* setup the industrialio driver allocated elements */ 156 indio_dev = iio_device_alloc(sizeof(*st)); 157 if (indio_dev == NULL) { 158 ret = -ENOMEM; 159 goto error_ret; 160 } 161 st = iio_priv(indio_dev); 162 /* this is only used for removal purposes */ 163 spi_set_drvdata(spi, indio_dev); 164 st->us = spi; 165 mutex_init(&st->buf_lock); 166 indio_dev->name = spi->dev.driver->name; 167 indio_dev->channels = adis16130_channels; 168 indio_dev->num_channels = ARRAY_SIZE(adis16130_channels); 169 indio_dev->dev.parent = &spi->dev; 170 indio_dev->info = &adis16130_info; 171 indio_dev->modes = INDIO_DIRECT_MODE; 172 173 ret = iio_device_register(indio_dev); 174 if (ret) 175 goto error_free_dev; 176 177 return 0; 178 179 error_free_dev: 180 iio_device_free(indio_dev); 181 182 error_ret: 183 return ret; 184 } 185 186 static int adis16130_remove(struct spi_device *spi) 187 { 188 iio_device_unregister(spi_get_drvdata(spi)); 189 iio_device_free(spi_get_drvdata(spi)); 190 191 return 0; 192 } 193 194 static struct spi_driver adis16130_driver = { 195 .driver = { 196 .name = "adis16130", 197 .owner = THIS_MODULE, 198 }, 199 .probe = adis16130_probe, 200 .remove = adis16130_remove, 201 }; 202 module_spi_driver(adis16130_driver); 203 204 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); 205 MODULE_DESCRIPTION("Analog Devices ADIS16130 High Precision Angular Rate"); 206 MODULE_LICENSE("GPL v2"); 207 MODULE_ALIAS("spi:adis16130"); 208