^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * All Sensors DLH series low voltage digital pressure sensors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2019 AVL DiTEST GmbH
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Tomislav Denis <tomislav.denis@avl.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Datasheet: https://www.allsensors.com/cad/DS-0355_Rev_B.PDF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/i2c.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/buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/iio/trigger_consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/iio/triggered_buffer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) /* Commands */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define DLH_START_SINGLE 0xAA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /* Status bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define DLH_STATUS_OK 0x40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* DLH data format */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define DLH_NUM_READ_BYTES 7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define DLH_NUM_DATA_BYTES 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define DLH_NUM_PR_BITS 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define DLH_NUM_TEMP_BITS 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /* DLH timings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define DLH_SINGLE_DUT_MS 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) enum dhl_ids {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) dlhl60d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) dlhl60g,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct dlh_info {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u8 osdig; /* digital offset factor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) unsigned int fss; /* full scale span (inch H2O) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct dlh_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) struct dlh_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) bool use_interrupt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct completion completion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) u8 rx_buf[DLH_NUM_READ_BYTES] ____cacheline_aligned;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) static struct dlh_info dlh_info_tbl[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) [dlhl60d] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .osdig = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) .fss = 120,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) [dlhl60g] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) .osdig = 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) .fss = 60,
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static int dlh_cmd_start_single(struct dlh_state *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ret = i2c_smbus_write_byte(st->client, DLH_START_SINGLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) dev_err(&st->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) "%s: I2C write byte failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static int dlh_cmd_read_data(struct dlh_state *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) ret = i2c_master_recv(st->client, st->rx_buf, DLH_NUM_READ_BYTES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) dev_err(&st->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) "%s: I2C read block failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (st->rx_buf[0] != DLH_STATUS_OK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) dev_err(&st->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) "%s: invalid status 0x%02x\n", __func__, st->rx_buf[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) return -EBUSY;
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static int dlh_start_capture_and_read(struct dlh_state *st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (st->use_interrupt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) reinit_completion(&st->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ret = dlh_cmd_start_single(st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (st->use_interrupt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) ret = wait_for_completion_timeout(&st->completion,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) msecs_to_jiffies(DLH_SINGLE_DUT_MS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) dev_err(&st->client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) "%s: conversion timed out\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) mdelay(DLH_SINGLE_DUT_MS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) return dlh_cmd_read_data(st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static int dlh_read_direct(struct dlh_state *st,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) unsigned int *pressure, unsigned int *temperature)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ret = dlh_start_capture_and_read(st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) *pressure = get_unaligned_be32(&st->rx_buf[1]) >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) *temperature = get_unaligned_be32(&st->rx_buf[3]) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) GENMASK(DLH_NUM_TEMP_BITS - 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static int dlh_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) struct iio_chan_spec const *channel, int *value,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int *value2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct dlh_state *st = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) unsigned int pressure, temperature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) s64 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) s32 rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) ret = iio_device_claim_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) ret = dlh_read_direct(st, &pressure, &temperature);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) iio_device_release_direct_mode(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) switch (channel->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) case IIO_PRESSURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) *value = pressure;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) case IIO_TEMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) *value = temperature;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) switch (channel->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) case IIO_PRESSURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) tmp = div_s64(125LL * st->info.fss * 24909 * 100,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 1 << DLH_NUM_PR_BITS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) tmp = div_s64_rem(tmp, 1000000000LL, &rem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) *value = tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) *value2 = rem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return IIO_VAL_INT_PLUS_NANO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) case IIO_TEMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) *value = 125 * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) *value2 = DLH_NUM_TEMP_BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) return IIO_VAL_FRACTIONAL_LOG2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) case IIO_CHAN_INFO_OFFSET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) switch (channel->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) case IIO_PRESSURE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) *value = -125 * st->info.fss * 24909;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) *value2 = 100 * st->info.osdig * 100000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return IIO_VAL_FRACTIONAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) case IIO_TEMP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) *value = -40 * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static const struct iio_info dlh_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .read_raw = dlh_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static const struct iio_chan_spec dlh_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .type = IIO_PRESSURE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .indexed = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .info_mask_shared_by_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) BIT(IIO_CHAN_INFO_SCALE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) BIT(IIO_CHAN_INFO_OFFSET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) .scan_index = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) .scan_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) .sign = 'u',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) .realbits = DLH_NUM_PR_BITS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) .storagebits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) .shift = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) .endianness = IIO_BE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .type = IIO_TEMP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .indexed = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) .info_mask_shared_by_type =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) BIT(IIO_CHAN_INFO_SCALE) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) BIT(IIO_CHAN_INFO_OFFSET),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) .scan_index = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) .scan_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) .sign = 'u',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) .realbits = DLH_NUM_TEMP_BITS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) .storagebits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) .shift = 8,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .endianness = IIO_BE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static irqreturn_t dlh_trigger_handler(int irq, void *private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) struct iio_poll_func *pf = private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct iio_dev *indio_dev = pf->indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct dlh_state *st = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) unsigned int chn, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) __be32 tmp_buf[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) ret = dlh_start_capture_and_read(st);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) for_each_set_bit(chn, indio_dev->active_scan_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) indio_dev->masklength) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) memcpy(tmp_buf + i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) &st->rx_buf[1] + chn * DLH_NUM_DATA_BYTES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) DLH_NUM_DATA_BYTES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) iio_push_to_buffers(indio_dev, tmp_buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) iio_trigger_notify_done(indio_dev->trig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static irqreturn_t dlh_interrupt(int irq, void *private)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) struct iio_dev *indio_dev = private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) struct dlh_state *st = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) complete(&st->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) static int dlh_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct dlh_state *st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) if (!i2c_check_functionality(client->adapter,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) dev_err(&client->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) "adapter doesn't support required i2c functionality\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) return -EOPNOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (!indio_dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) dev_err(&client->dev, "failed to allocate iio device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) i2c_set_clientdata(client, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) st = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) st->info = dlh_info_tbl[id->driver_data];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) st->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) st->use_interrupt = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) indio_dev->name = id->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) indio_dev->info = &dlh_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) indio_dev->channels = dlh_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) indio_dev->num_channels = ARRAY_SIZE(dlh_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (client->irq > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ret = devm_request_threaded_irq(&client->dev, client->irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) dlh_interrupt, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) IRQF_TRIGGER_RISING | IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) id->name, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) dev_err(&client->dev, "failed to allocate threaded irq");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) st->use_interrupt = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) init_completion(&st->completion);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) NULL, &dlh_trigger_handler, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) dev_err(&client->dev, "failed to setup iio buffer\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) ret = devm_iio_device_register(&client->dev, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) dev_err(&client->dev, "failed to register iio device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) static const struct of_device_id dlh_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) { .compatible = "asc,dlhl60d" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) { .compatible = "asc,dlhl60g" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) MODULE_DEVICE_TABLE(of, dlh_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) static const struct i2c_device_id dlh_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) { "dlhl60d", dlhl60d },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) { "dlhl60g", dlhl60g },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) MODULE_DEVICE_TABLE(i2c, dlh_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static struct i2c_driver dlh_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) .name = "dlhl60d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) .of_match_table = dlh_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) .probe = dlh_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) .id_table = dlh_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) module_i2c_driver(dlh_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) MODULE_AUTHOR("Tomislav Denis <tomislav.denis@avl.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) MODULE_DESCRIPTION("Driver for All Sensors DLH series pressure sensors");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) MODULE_LICENSE("GPL v2");