537 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Common library for ADIS16XXX devices4 *5 * Copyright 2012 Analog Devices Inc.6 * Author: Lars-Peter Clausen <lars@metafoo.de>7 */8 9#include <linux/delay.h>10#include <linux/gpio/consumer.h>11#include <linux/mutex.h>12#include <linux/device.h>13#include <linux/kernel.h>14#include <linux/spi/spi.h>15#include <linux/module.h>16#include <linux/unaligned.h>17 18#include <linux/iio/iio.h>19#include <linux/iio/imu/adis.h>20 21#define ADIS_MSC_CTRL_DATA_RDY_EN BIT(2)22#define ADIS_MSC_CTRL_DATA_RDY_POL_HIGH BIT(1)23#define ADIS_MSC_CTRL_DATA_RDY_DIO2 BIT(0)24#define ADIS_GLOB_CMD_SW_RESET BIT(7)25 26/**27 * __adis_write_reg() - write N bytes to register (unlocked version)28 * @adis: The adis device29 * @reg: The address of the lower of the two registers30 * @value: The value to write to device (up to 4 bytes)31 * @size: The size of the @value (in bytes)32 */33int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int value,34 unsigned int size)35{36 unsigned int page = reg / ADIS_PAGE_SIZE;37 int ret, i;38 struct spi_message msg;39 struct spi_transfer xfers[] = {40 {41 .tx_buf = adis->tx,42 .bits_per_word = 8,43 .len = 2,44 .cs_change = 1,45 .delay.value = adis->data->write_delay,46 .delay.unit = SPI_DELAY_UNIT_USECS,47 }, {48 .tx_buf = adis->tx + 2,49 .bits_per_word = 8,50 .len = 2,51 .cs_change = 1,52 .delay.value = adis->data->write_delay,53 .delay.unit = SPI_DELAY_UNIT_USECS,54 }, {55 .tx_buf = adis->tx + 4,56 .bits_per_word = 8,57 .len = 2,58 .cs_change = 1,59 .delay.value = adis->data->write_delay,60 .delay.unit = SPI_DELAY_UNIT_USECS,61 }, {62 .tx_buf = adis->tx + 6,63 .bits_per_word = 8,64 .len = 2,65 .delay.value = adis->data->write_delay,66 .delay.unit = SPI_DELAY_UNIT_USECS,67 }, {68 .tx_buf = adis->tx + 8,69 .bits_per_word = 8,70 .len = 2,71 .delay.value = adis->data->write_delay,72 .delay.unit = SPI_DELAY_UNIT_USECS,73 },74 };75 76 spi_message_init(&msg);77 78 if (adis->current_page != page) {79 adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);80 adis->tx[1] = page;81 spi_message_add_tail(&xfers[0], &msg);82 }83 84 switch (size) {85 case 4:86 adis->tx[8] = ADIS_WRITE_REG(reg + 3);87 adis->tx[9] = (value >> 24) & 0xff;88 adis->tx[6] = ADIS_WRITE_REG(reg + 2);89 adis->tx[7] = (value >> 16) & 0xff;90 fallthrough;91 case 2:92 adis->tx[4] = ADIS_WRITE_REG(reg + 1);93 adis->tx[5] = (value >> 8) & 0xff;94 fallthrough;95 case 1:96 adis->tx[2] = ADIS_WRITE_REG(reg);97 adis->tx[3] = value & 0xff;98 break;99 default:100 return -EINVAL;101 }102 103 xfers[size].cs_change = 0;104 105 for (i = 1; i <= size; i++)106 spi_message_add_tail(&xfers[i], &msg);107 108 ret = spi_sync(adis->spi, &msg);109 if (ret) {110 dev_err(&adis->spi->dev, "Failed to write register 0x%02X: %d\n",111 reg, ret);112 } else {113 adis->current_page = page;114 }115 116 return ret;117}118EXPORT_SYMBOL_NS_GPL(__adis_write_reg, IIO_ADISLIB);119 120/**121 * __adis_read_reg() - read N bytes from register (unlocked version)122 * @adis: The adis device123 * @reg: The address of the lower of the two registers124 * @val: The value read back from the device125 * @size: The size of the @val buffer126 */127int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val,128 unsigned int size)129{130 unsigned int page = reg / ADIS_PAGE_SIZE;131 struct spi_message msg;132 int ret;133 struct spi_transfer xfers[] = {134 {135 .tx_buf = adis->tx,136 .bits_per_word = 8,137 .len = 2,138 .cs_change = 1,139 .delay.value = adis->data->write_delay,140 .delay.unit = SPI_DELAY_UNIT_USECS,141 }, {142 .tx_buf = adis->tx + 2,143 .bits_per_word = 8,144 .len = 2,145 .cs_change = 1,146 .delay.value = adis->data->read_delay,147 .delay.unit = SPI_DELAY_UNIT_USECS,148 }, {149 .tx_buf = adis->tx + 4,150 .rx_buf = adis->rx,151 .bits_per_word = 8,152 .len = 2,153 .cs_change = 1,154 .delay.value = adis->data->read_delay,155 .delay.unit = SPI_DELAY_UNIT_USECS,156 }, {157 .rx_buf = adis->rx + 2,158 .bits_per_word = 8,159 .len = 2,160 .delay.value = adis->data->read_delay,161 .delay.unit = SPI_DELAY_UNIT_USECS,162 },163 };164 165 spi_message_init(&msg);166 167 if (adis->current_page != page) {168 adis->tx[0] = ADIS_WRITE_REG(ADIS_REG_PAGE_ID);169 adis->tx[1] = page;170 spi_message_add_tail(&xfers[0], &msg);171 }172 173 switch (size) {174 case 4:175 adis->tx[2] = ADIS_READ_REG(reg + 2);176 adis->tx[3] = 0;177 spi_message_add_tail(&xfers[1], &msg);178 fallthrough;179 case 2:180 adis->tx[4] = ADIS_READ_REG(reg);181 adis->tx[5] = 0;182 spi_message_add_tail(&xfers[2], &msg);183 spi_message_add_tail(&xfers[3], &msg);184 break;185 default:186 return -EINVAL;187 }188 189 ret = spi_sync(adis->spi, &msg);190 if (ret) {191 dev_err(&adis->spi->dev, "Failed to read register 0x%02X: %d\n",192 reg, ret);193 return ret;194 }195 196 adis->current_page = page;197 198 switch (size) {199 case 4:200 *val = get_unaligned_be32(adis->rx);201 break;202 case 2:203 *val = get_unaligned_be16(adis->rx + 2);204 break;205 }206 207 return ret;208}209EXPORT_SYMBOL_NS_GPL(__adis_read_reg, IIO_ADISLIB);210/**211 * __adis_update_bits_base() - ADIS Update bits function - Unlocked version212 * @adis: The adis device213 * @reg: The address of the lower of the two registers214 * @mask: Bitmask to change215 * @val: Value to be written216 * @size: Size of the register to update217 *218 * Updates the desired bits of @reg in accordance with @mask and @val.219 */220int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask,221 const u32 val, u8 size)222{223 int ret;224 u32 __val;225 226 ret = __adis_read_reg(adis, reg, &__val, size);227 if (ret)228 return ret;229 230 __val = (__val & ~mask) | (val & mask);231 232 return __adis_write_reg(adis, reg, __val, size);233}234EXPORT_SYMBOL_NS_GPL(__adis_update_bits_base, IIO_ADISLIB);235 236#ifdef CONFIG_DEBUG_FS237 238int adis_debugfs_reg_access(struct iio_dev *indio_dev, unsigned int reg,239 unsigned int writeval, unsigned int *readval)240{241 struct adis *adis = iio_device_get_drvdata(indio_dev);242 243 if (readval) {244 u16 val16;245 int ret;246 247 ret = adis_read_reg_16(adis, reg, &val16);248 if (ret == 0)249 *readval = val16;250 251 return ret;252 }253 254 return adis_write_reg_16(adis, reg, writeval);255}256EXPORT_SYMBOL_NS(adis_debugfs_reg_access, IIO_ADISLIB);257 258#endif259 260/**261 * __adis_enable_irq() - Enable or disable data ready IRQ (unlocked)262 * @adis: The adis device263 * @enable: Whether to enable the IRQ264 *265 * Returns 0 on success, negative error code otherwise266 */267int __adis_enable_irq(struct adis *adis, bool enable)268{269 int ret;270 u16 msc;271 272 if (adis->data->enable_irq)273 return adis->data->enable_irq(adis, enable);274 275 if (adis->data->unmasked_drdy) {276 if (enable)277 enable_irq(adis->spi->irq);278 else279 disable_irq(adis->spi->irq);280 281 return 0;282 }283 284 ret = __adis_read_reg_16(adis, adis->data->msc_ctrl_reg, &msc);285 if (ret)286 return ret;287 288 msc |= ADIS_MSC_CTRL_DATA_RDY_POL_HIGH;289 msc &= ~ADIS_MSC_CTRL_DATA_RDY_DIO2;290 if (enable)291 msc |= ADIS_MSC_CTRL_DATA_RDY_EN;292 else293 msc &= ~ADIS_MSC_CTRL_DATA_RDY_EN;294 295 return __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc);296}297EXPORT_SYMBOL_NS(__adis_enable_irq, IIO_ADISLIB);298 299/**300 * __adis_check_status() - Check the device for error conditions (unlocked)301 * @adis: The adis device302 *303 * Returns 0 on success, a negative error code otherwise304 */305int __adis_check_status(struct adis *adis)306{307 u16 status;308 int ret;309 int i;310 311 ret = __adis_read_reg_16(adis, adis->data->diag_stat_reg, &status);312 if (ret)313 return ret;314 315 status &= adis->data->status_error_mask;316 317 if (status == 0)318 return 0;319 320 for (i = 0; i < 16; ++i) {321 if (status & BIT(i)) {322 dev_err(&adis->spi->dev, "%s.\n",323 adis->data->status_error_msgs[i]);324 }325 }326 327 return -EIO;328}329EXPORT_SYMBOL_NS_GPL(__adis_check_status, IIO_ADISLIB);330 331/**332 * __adis_reset() - Reset the device (unlocked version)333 * @adis: The adis device334 *335 * Returns 0 on success, a negative error code otherwise336 */337int __adis_reset(struct adis *adis)338{339 int ret;340 const struct adis_timeout *timeouts = adis->data->timeouts;341 342 ret = __adis_write_reg_8(adis, adis->data->glob_cmd_reg,343 ADIS_GLOB_CMD_SW_RESET);344 if (ret) {345 dev_err(&adis->spi->dev, "Failed to reset device: %d\n", ret);346 return ret;347 }348 349 msleep(timeouts->sw_reset_ms);350 351 return 0;352}353EXPORT_SYMBOL_NS_GPL(__adis_reset, IIO_ADIS_LIB);354 355static int adis_self_test(struct adis *adis)356{357 int ret;358 const struct adis_timeout *timeouts = adis->data->timeouts;359 360 ret = __adis_write_reg_16(adis, adis->data->self_test_reg,361 adis->data->self_test_mask);362 if (ret) {363 dev_err(&adis->spi->dev, "Failed to initiate self test: %d\n",364 ret);365 return ret;366 }367 368 msleep(timeouts->self_test_ms);369 370 ret = __adis_check_status(adis);371 372 if (adis->data->self_test_no_autoclear)373 __adis_write_reg_16(adis, adis->data->self_test_reg, 0x00);374 375 return ret;376}377 378/**379 * __adis_initial_startup() - Device initial setup380 * @adis: The adis device381 *382 * The function performs a HW reset via a reset pin that should be specified383 * via GPIOLIB. If no pin is configured a SW reset will be performed.384 * The RST pin for the ADIS devices should be configured as ACTIVE_LOW.385 *386 * After the self-test operation is performed, the function will also check387 * that the product ID is as expected. This assumes that drivers providing388 * 'prod_id_reg' will also provide the 'prod_id'.389 *390 * Returns 0 if the device is operational, a negative error code otherwise.391 *392 * This function should be called early on in the device initialization sequence393 * to ensure that the device is in a sane and known state and that it is usable.394 */395int __adis_initial_startup(struct adis *adis)396{397 const struct adis_timeout *timeouts = adis->data->timeouts;398 struct gpio_desc *gpio;399 u16 prod_id;400 int ret;401 402 /* check if the device has rst pin low */403 gpio = devm_gpiod_get_optional(&adis->spi->dev, "reset", GPIOD_OUT_HIGH);404 if (IS_ERR(gpio))405 return PTR_ERR(gpio);406 407 if (gpio) {408 usleep_range(10, 12);409 /* bring device out of reset */410 gpiod_set_value_cansleep(gpio, 0);411 msleep(timeouts->reset_ms);412 } else {413 ret = __adis_reset(adis);414 if (ret)415 return ret;416 }417 418 ret = adis_self_test(adis);419 if (ret)420 return ret;421 422 /*423 * don't bother calling this if we can't unmask the IRQ as in this case424 * the IRQ is most likely not yet requested and we will request it425 * with 'IRQF_NO_AUTOEN' anyways.426 */427 if (!adis->data->unmasked_drdy)428 __adis_enable_irq(adis, false);429 430 if (!adis->data->prod_id_reg)431 return 0;432 433 ret = adis_read_reg_16(adis, adis->data->prod_id_reg, &prod_id);434 if (ret)435 return ret;436 437 if (prod_id != adis->data->prod_id)438 dev_warn(&adis->spi->dev,439 "Device ID(%u) and product ID(%u) do not match.\n",440 adis->data->prod_id, prod_id);441 442 return 0;443}444EXPORT_SYMBOL_NS_GPL(__adis_initial_startup, IIO_ADISLIB);445 446/**447 * adis_single_conversion() - Performs a single sample conversion448 * @indio_dev: The IIO device449 * @chan: The IIO channel450 * @error_mask: Mask for the error bit451 * @val: Result of the conversion452 *453 * Returns IIO_VAL_INT on success, a negative error code otherwise.454 *455 * The function performs a single conversion on a given channel and post456 * processes the value accordingly to the channel spec. If a error_mask is given457 * the function will check if the mask is set in the returned raw value. If it458 * is set the function will perform a self-check. If the device does not report459 * a error bit in the channels raw value set error_mask to 0.460 */461int adis_single_conversion(struct iio_dev *indio_dev,462 const struct iio_chan_spec *chan,463 unsigned int error_mask, int *val)464{465 struct adis *adis = iio_device_get_drvdata(indio_dev);466 unsigned int uval;467 int ret;468 469 guard(mutex)(&adis->state_lock);470 471 ret = __adis_read_reg(adis, chan->address, &uval,472 chan->scan_type.storagebits / 8);473 if (ret)474 return ret;475 476 if (uval & error_mask) {477 ret = __adis_check_status(adis);478 if (ret)479 return ret;480 }481 482 if (chan->scan_type.sign == 's')483 *val = sign_extend32(uval, chan->scan_type.realbits - 1);484 else485 *val = uval & ((1 << chan->scan_type.realbits) - 1);486 487 return IIO_VAL_INT;488}489EXPORT_SYMBOL_NS_GPL(adis_single_conversion, IIO_ADISLIB);490 491/**492 * adis_init() - Initialize adis device structure493 * @adis: The adis device494 * @indio_dev: The iio device495 * @spi: The spi device496 * @data: Chip specific data497 *498 * Returns 0 on success, a negative error code otherwise.499 *500 * This function must be called, before any other adis helper function may be501 * called.502 */503int adis_init(struct adis *adis, struct iio_dev *indio_dev,504 struct spi_device *spi, const struct adis_data *data)505{506 if (!data || !data->timeouts) {507 dev_err(&spi->dev, "No config data or timeouts not defined!\n");508 return -EINVAL;509 }510 511 mutex_init(&adis->state_lock);512 513 if (!spi->cs_inactive.value) {514 spi->cs_inactive.value = data->cs_change_delay;515 spi->cs_inactive.unit = SPI_DELAY_UNIT_USECS;516 }517 518 adis->spi = spi;519 adis->data = data;520 iio_device_set_drvdata(indio_dev, adis);521 522 if (data->has_paging) {523 /* Need to set the page before first read/write */524 adis->current_page = -1;525 } else {526 /* Page will always be 0 */527 adis->current_page = 0;528 }529 530 return 0;531}532EXPORT_SYMBOL_NS_GPL(adis_init, IIO_ADISLIB);533 534MODULE_LICENSE("GPL");535MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");536MODULE_DESCRIPTION("Common library code for ADIS16XXX devices");537