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