^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * ltc2496.c - Driver for Analog Devices/Linear Technology LTC2496 ADC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Based on ltc2497.c which has
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2017 Analog Devices Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Licensed under the GPL-2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/2496fc.pdf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/spi/spi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/iio/driver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "ltc2497.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct ltc2496_driverdata {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* this must be the first member */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct ltc2497core_driverdata common_ddata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct spi_device *spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * DMA (thus cache coherency maintenance) requires the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * transfer buffers to live in their own cache lines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned char rxbuf[3] ____cacheline_aligned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) unsigned char txbuf[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static int ltc2496_result_and_measure(struct ltc2497core_driverdata *ddata,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) u8 address, int *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct ltc2496_driverdata *st =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) container_of(ddata, struct ltc2496_driverdata, common_ddata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) struct spi_transfer t = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) .tx_buf = st->txbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) .rx_buf = st->rxbuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) .len = sizeof(st->txbuf),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) st->txbuf[0] = LTC2497_ENABLE | address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) ret = spi_sync_transfer(st->spi, &t, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) dev_err(&st->spi->dev, "spi_sync_transfer failed: %pe\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) ERR_PTR(ret));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *val = ((st->rxbuf[0] & 0x3f) << 12 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) st->rxbuf[1] << 4 | st->rxbuf[2] >> 4) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) (1 << 17);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) static int ltc2496_probe(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct ltc2496_driverdata *st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) struct device *dev = &spi->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) st = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) spi_set_drvdata(spi, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) st->spi = spi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) st->common_ddata.result_and_measure = ltc2496_result_and_measure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) return ltc2497core_probe(dev, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static int ltc2496_remove(struct spi_device *spi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct iio_dev *indio_dev = spi_get_drvdata(spi);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ltc2497core_remove(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) static const struct of_device_id ltc2496_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) { .compatible = "lltc,ltc2496", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) MODULE_DEVICE_TABLE(of, ltc2496_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static struct spi_driver ltc2496_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) .name = "ltc2496",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) .of_match_table = ltc2496_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .probe = ltc2496_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .remove = ltc2496_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) module_spi_driver(ltc2496_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) MODULE_AUTHOR("Uwe Kleine-König <u.kleine-könig@pengutronix.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) MODULE_DESCRIPTION("Linear Technology LTC2496 ADC driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) MODULE_LICENSE("GPL v2");