From 5d1646d90e1f2cceb9f0828f4b28318cd0ec7744 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 12:05:51 +0200 Subject: Adding upstream version 5.10.209. Signed-off-by: Daniel Baumann --- drivers/iio/pressure/ms5611_spi.c | 142 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 drivers/iio/pressure/ms5611_spi.c (limited to 'drivers/iio/pressure/ms5611_spi.c') diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c new file mode 100644 index 000000000..3039fe8aa --- /dev/null +++ b/drivers/iio/pressure/ms5611_spi.c @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MS5611 pressure and temperature sensor driver (SPI bus) + * + * Copyright (c) Tomasz Duszynski + * + */ + +#include +#include +#include +#include + +#include + +#include "ms5611.h" + +static int ms5611_spi_reset(struct ms5611_state *st) +{ + u8 cmd = MS5611_RESET; + + return spi_write_then_read(st->client, &cmd, 1, NULL, 0); +} + +static int ms5611_spi_read_prom_word(struct ms5611_state *st, int index, + u16 *word) +{ + int ret; + + ret = spi_w8r16be(st->client, MS5611_READ_PROM_WORD + (index << 1)); + if (ret < 0) + return ret; + + *word = ret; + + return 0; +} + +static int ms5611_spi_read_adc(struct ms5611_state *st, s32 *val) +{ + int ret; + u8 buf[3] = { MS5611_READ_ADC }; + + ret = spi_write_then_read(st->client, buf, 1, buf, 3); + if (ret < 0) + return ret; + + *val = get_unaligned_be24(&buf[0]); + + return 0; +} + +static int ms5611_spi_read_adc_temp_and_pressure(struct ms5611_state *st, + s32 *temp, s32 *pressure) +{ + int ret; + const struct ms5611_osr *osr = st->temp_osr; + + /* + * Warning: &osr->cmd MUST be aligned on a word boundary since used as + * 2nd argument (void*) of spi_write_then_read. + */ + ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0); + if (ret < 0) + return ret; + + usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL)); + ret = ms5611_spi_read_adc(st, temp); + if (ret < 0) + return ret; + + osr = st->pressure_osr; + ret = spi_write_then_read(st->client, &osr->cmd, 1, NULL, 0); + if (ret < 0) + return ret; + + usleep_range(osr->conv_usec, osr->conv_usec + (osr->conv_usec / 10UL)); + return ms5611_spi_read_adc(st, pressure); +} + +static int ms5611_spi_probe(struct spi_device *spi) +{ + int ret; + struct ms5611_state *st; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + spi_set_drvdata(spi, indio_dev); + + spi->mode = SPI_MODE_0; + spi->max_speed_hz = min(spi->max_speed_hz, 20000000U); + spi->bits_per_word = 8; + ret = spi_setup(spi); + if (ret < 0) + return ret; + + st = iio_priv(indio_dev); + st->reset = ms5611_spi_reset; + st->read_prom_word = ms5611_spi_read_prom_word; + st->read_adc_temp_and_pressure = ms5611_spi_read_adc_temp_and_pressure; + st->client = spi; + + return ms5611_probe(indio_dev, &spi->dev, spi_get_device_id(spi)->name, + spi_get_device_id(spi)->driver_data); +} + +static int ms5611_spi_remove(struct spi_device *spi) +{ + return ms5611_remove(spi_get_drvdata(spi)); +} + +static const struct of_device_id ms5611_spi_matches[] = { + { .compatible = "meas,ms5611" }, + { .compatible = "meas,ms5607" }, + { } +}; +MODULE_DEVICE_TABLE(of, ms5611_spi_matches); + +static const struct spi_device_id ms5611_id[] = { + { "ms5611", MS5611 }, + { "ms5607", MS5607 }, + { } +}; +MODULE_DEVICE_TABLE(spi, ms5611_id); + +static struct spi_driver ms5611_driver = { + .driver = { + .name = "ms5611", + .of_match_table = ms5611_spi_matches + }, + .id_table = ms5611_id, + .probe = ms5611_spi_probe, + .remove = ms5611_spi_remove, +}; +module_spi_driver(ms5611_driver); + +MODULE_AUTHOR("Tomasz Duszynski "); +MODULE_DESCRIPTION("MS5611 spi driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3