^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) * rfd77402.c - Support for RF Digital RFD77402 Time-of-Flight (distance) sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright 2017 Peter Meerwald-Stadler <pmeerw@pmeerw.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * 7-bit I2C slave address 0x4c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * TODO: interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * https://media.digikey.com/pdf/Data%20Sheets/RF%20Digital%20PDFs/RFD77402.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/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/iio/iio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define RFD77402_DRV_NAME "rfd77402"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define RFD77402_ICSR 0x00 /* Interrupt Control Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define RFD77402_ICSR_INT_MODE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define RFD77402_ICSR_INT_POL BIT(3)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define RFD77402_ICSR_RESULT BIT(4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define RFD77402_ICSR_M2H_MSG BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define RFD77402_ICSR_H2M_MSG BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define RFD77402_ICSR_RESET BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define RFD77402_CMD_R 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define RFD77402_CMD_SINGLE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define RFD77402_CMD_STANDBY 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define RFD77402_CMD_MCPU_OFF 0x11
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define RFD77402_CMD_MCPU_ON 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define RFD77402_CMD_RESET BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define RFD77402_CMD_VALID BIT(7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define RFD77402_STATUS_R 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define RFD77402_STATUS_PM_MASK GENMASK(4, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define RFD77402_STATUS_STANDBY 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define RFD77402_STATUS_MCPU_OFF 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define RFD77402_STATUS_MCPU_ON 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define RFD77402_RESULT_R 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define RFD77402_RESULT_DIST_MASK GENMASK(12, 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define RFD77402_RESULT_ERR_MASK GENMASK(14, 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define RFD77402_RESULT_VALID BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define RFD77402_PMU_CFG 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define RFD77402_PMU_MCPU_INIT BIT(9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define RFD77402_I2C_INIT_CFG 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define RFD77402_I2C_ADDR_INCR BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define RFD77402_I2C_DATA_INCR BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) #define RFD77402_I2C_HOST_DEBUG BIT(5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define RFD77402_I2C_MCPU_DEBUG BIT(6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define RFD77402_CMD_CFGR_A 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define RFD77402_CMD_CFGR_B 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define RFD77402_HFCFG_0 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define RFD77402_HFCFG_1 0x22
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define RFD77402_HFCFG_2 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define RFD77402_HFCFG_3 0x26
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define RFD77402_MOD_CHIP_ID 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* magic configuration values from datasheet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) static const struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) u8 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) u16 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) } rf77402_tof_config[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {RFD77402_CMD_CFGR_A, 0xe100},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {RFD77402_CMD_CFGR_B, 0x10ff},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {RFD77402_HFCFG_0, 0x07d0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {RFD77402_HFCFG_1, 0x5008},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {RFD77402_HFCFG_2, 0xa041},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {RFD77402_HFCFG_3, 0x45d4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct rfd77402_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) /* Serialize reads from the sensor */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct mutex lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static const struct iio_chan_spec rfd77402_channels[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .type = IIO_DISTANCE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) BIT(IIO_CHAN_INFO_SCALE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int rfd77402_set_state(struct rfd77402_data *data, u8 state, u16 check)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ret = i2c_smbus_write_byte_data(data->client, RFD77402_CMD_R,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) state | RFD77402_CMD_VALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) usleep_range(10000, 20000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ret = i2c_smbus_read_word_data(data->client, RFD77402_STATUS_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if ((ret & RFD77402_STATUS_PM_MASK) != check)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static int rfd77402_measure(struct rfd77402_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) int tries = 10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ret = rfd77402_set_state(data, RFD77402_CMD_MCPU_ON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) RFD77402_STATUS_MCPU_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) ret = i2c_smbus_write_byte_data(data->client, RFD77402_CMD_R,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) RFD77402_CMD_SINGLE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) RFD77402_CMD_VALID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) while (tries-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) ret = i2c_smbus_read_byte_data(data->client, RFD77402_ICSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) if (ret & RFD77402_ICSR_RESULT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) msleep(20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (tries < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) ret = i2c_smbus_read_word_data(data->client, RFD77402_RESULT_R);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if ((ret & RFD77402_RESULT_ERR_MASK) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) !(ret & RFD77402_RESULT_VALID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return (ret & RFD77402_RESULT_DIST_MASK) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) rfd77402_set_state(data, RFD77402_CMD_MCPU_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) RFD77402_STATUS_MCPU_OFF);
^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)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int rfd77402_read_raw(struct iio_dev *indio_dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct iio_chan_spec const *chan,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) int *val, int *val2, long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct rfd77402_data *data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) switch (mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) case IIO_CHAN_INFO_RAW:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) mutex_lock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ret = rfd77402_measure(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) mutex_unlock(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) *val = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return IIO_VAL_INT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) case IIO_CHAN_INFO_SCALE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /* 1 LSB is 1 mm */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) *val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) *val2 = 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return IIO_VAL_INT_PLUS_MICRO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static const struct iio_info rfd77402_info = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) .read_raw = rfd77402_read_raw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) static int rfd77402_init(struct rfd77402_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) ret = rfd77402_set_state(data, RFD77402_CMD_STANDBY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) RFD77402_STATUS_STANDBY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) /* configure INT pad as push-pull, active low */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ret = i2c_smbus_write_byte_data(data->client, RFD77402_ICSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) RFD77402_ICSR_INT_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* I2C configuration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) ret = i2c_smbus_write_word_data(data->client, RFD77402_I2C_INIT_CFG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) RFD77402_I2C_ADDR_INCR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) RFD77402_I2C_DATA_INCR |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) RFD77402_I2C_HOST_DEBUG |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) RFD77402_I2C_MCPU_DEBUG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) /* set initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ret = i2c_smbus_write_word_data(data->client, RFD77402_PMU_CFG, 0x0500);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ret = rfd77402_set_state(data, RFD77402_CMD_MCPU_OFF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) RFD77402_STATUS_MCPU_OFF);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) /* set initialization */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) ret = i2c_smbus_write_word_data(data->client, RFD77402_PMU_CFG, 0x0600);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) ret = rfd77402_set_state(data, RFD77402_CMD_MCPU_ON,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) RFD77402_STATUS_MCPU_ON);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) for (i = 0; i < ARRAY_SIZE(rf77402_tof_config); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) ret = i2c_smbus_write_word_data(data->client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) rf77402_tof_config[i].reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) rf77402_tof_config[i].val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) ret = rfd77402_set_state(data, RFD77402_CMD_STANDBY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) RFD77402_STATUS_STANDBY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) static int rfd77402_powerdown(struct rfd77402_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) return rfd77402_set_state(data, RFD77402_CMD_STANDBY,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) RFD77402_STATUS_STANDBY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) static int rfd77402_probe(struct i2c_client *client,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) const struct i2c_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) struct rfd77402_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) struct iio_dev *indio_dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) ret = i2c_smbus_read_word_data(client, RFD77402_MOD_CHIP_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (ret != 0xad01 && ret != 0xad02) /* known chip ids */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) if (!indio_dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) data = iio_priv(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) i2c_set_clientdata(client, indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) data->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) mutex_init(&data->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) indio_dev->info = &rfd77402_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) indio_dev->channels = rfd77402_channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) indio_dev->num_channels = ARRAY_SIZE(rfd77402_channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) indio_dev->name = RFD77402_DRV_NAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) indio_dev->modes = INDIO_DIRECT_MODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ret = rfd77402_init(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ret = iio_device_register(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) goto err_powerdown;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) err_powerdown:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) rfd77402_powerdown(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) static int rfd77402_remove(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct iio_dev *indio_dev = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) iio_device_unregister(indio_dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) rfd77402_powerdown(iio_priv(indio_dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int rfd77402_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) struct rfd77402_data *data = iio_priv(i2c_get_clientdata(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) to_i2c_client(dev)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return rfd77402_powerdown(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) static int rfd77402_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) struct rfd77402_data *data = iio_priv(i2c_get_clientdata(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) to_i2c_client(dev)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return rfd77402_init(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) static SIMPLE_DEV_PM_OPS(rfd77402_pm_ops, rfd77402_suspend, rfd77402_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) static const struct i2c_device_id rfd77402_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) { "rfd77402", 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) MODULE_DEVICE_TABLE(i2c, rfd77402_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) static struct i2c_driver rfd77402_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) .name = RFD77402_DRV_NAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .pm = &rfd77402_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) .probe = rfd77402_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) .remove = rfd77402_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .id_table = rfd77402_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) module_i2c_driver(rfd77402_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) MODULE_AUTHOR("Peter Meerwald-Stadler <pmeerw@pmeerw.net>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) MODULE_DESCRIPTION("RFD77402 Time-of-Flight sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) MODULE_LICENSE("GPL");