Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iio: proximity: add driver for ST VL53L1X ToF sensor

Add support for the STMicroelectronics VL53L1X Time-of-Flight
ranging sensor with I2C interface.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Siratul Islam <email@sirat.me>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Siratul Islam and committed by
Jonathan Cameron
128e5ebe 2c9225e8

+773
+1
MAINTAINERS
··· 25110 25110 L: linux-iio@vger.kernel.org 25111 25111 S: Maintained 25112 25112 F: Documentation/devicetree/bindings/iio/proximity/st,vl53l0x.yaml 25113 + F: drivers/iio/proximity/vl53l1x-i2c.c 25113 25114 25114 25115 STABLE BRANCH 25115 25116 M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+15
drivers/iio/proximity/Kconfig
··· 244 244 To compile this driver as a module, choose M here: the 245 245 module will be called vl53l0x-i2c. 246 246 247 + config VL53L1X_I2C 248 + tristate "STMicroelectronics VL53L1X ToF ranger sensor (I2C)" 249 + depends on I2C 250 + select IIO_BUFFER 251 + select IIO_TRIGGERED_BUFFER 252 + select REGMAP_I2C 253 + select RESET_CONTROLLER 254 + help 255 + Say Y here to build a driver for STMicroelectronics VL53L1X 256 + ToF ranger sensors with i2c interface. 257 + This driver can be used to measure the distance of objects. 258 + 259 + To compile this driver as a module, choose M here: the 260 + module will be called vl53l1x-i2c. 261 + 247 262 config AW96103 248 263 tristate "AW96103/AW96105 Awinic proximity sensor" 249 264 select REGMAP_I2C
+1
drivers/iio/proximity/Makefile
··· 23 23 obj-$(CONFIG_SX9500) += sx9500.o 24 24 obj-$(CONFIG_VCNL3020) += vcnl3020.o 25 25 obj-$(CONFIG_VL53L0X_I2C) += vl53l0x-i2c.o 26 + obj-$(CONFIG_VL53L1X_I2C) += vl53l1x-i2c.o 26 27 obj-$(CONFIG_AW96103) += aw96103.o 27 28
+756
drivers/iio/proximity/vl53l1x-i2c.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause 2 + /* 3 + * Support for ST VL53L1X FlightSense ToF Ranging Sensor on a i2c bus. 4 + * 5 + * Copyright (C) 2026 Siratul Islam <email@sirat.me> 6 + * 7 + * Datasheet available at 8 + * <https://www.st.com/resource/en/datasheet/vl53l1x.pdf> 9 + * 10 + * Default 7-bit i2c slave address 0x29. 11 + * 12 + * The VL53L1X requires a firmware configuration blob to be loaded at boot. 13 + * Register values for the default configuration are taken from 14 + * ST's VL53L1X Ultra Lite Driver (STSW-IMG009). 15 + */ 16 + 17 + #include <linux/array_size.h> 18 + #include <linux/bits.h> 19 + #include <linux/bitfield.h> 20 + #include <linux/completion.h> 21 + #include <linux/delay.h> 22 + #include <linux/dev_printk.h> 23 + #include <linux/err.h> 24 + #include <linux/i2c.h> 25 + #include <linux/interrupt.h> 26 + #include <linux/math.h> 27 + #include <linux/mod_devicetable.h> 28 + #include <linux/module.h> 29 + #include <linux/regmap.h> 30 + #include <linux/regulator/consumer.h> 31 + #include <linux/reset.h> 32 + #include <linux/time.h> 33 + #include <linux/types.h> 34 + 35 + #include <asm/byteorder.h> 36 + 37 + #include <linux/iio/buffer.h> 38 + #include <linux/iio/iio.h> 39 + #include <linux/iio/trigger.h> 40 + #include <linux/iio/trigger_consumer.h> 41 + #include <linux/iio/triggered_buffer.h> 42 + 43 + #define VL53L1X_REG_SOFT_RESET 0x0000 44 + #define VL53L1X_REG_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND 0x0008 45 + #define VL53L1X_REG_VHV_CONFIG__INIT 0x000B 46 + #define VL53L1X_REG_GPIO_HV_MUX__CTRL 0x0030 47 + #define VL53L1X_REG_GPIO__TIO_HV_STATUS 0x0031 48 + #define VL53L1X_REG_SYSTEM__INTERRUPT_CONFIG_GPIO 0x0046 49 + #define VL53L1X_REG_PHASECAL_CONFIG__TIMEOUT_MACROP 0x004B 50 + #define VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_A 0x005E 51 + #define VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_A 0x0060 52 + #define VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_B 0x0061 53 + #define VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_B 0x0063 54 + #define VL53L1X_REG_RANGE_CONFIG__VALID_PHASE_HIGH 0x0069 55 + #define VL53L1X_REG_SYSTEM__INTERMEASUREMENT_PERIOD 0x006C 56 + #define VL53L1X_REG_SD_CONFIG__WOI_SD0 0x0078 57 + #define VL53L1X_REG_SD_CONFIG__WOI_SD1 0x0079 58 + #define VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD0 0x007A 59 + #define VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD1 0x007B 60 + #define VL53L1X_REG_SYSTEM__INTERRUPT_CLEAR 0x0086 61 + #define VL53L1X_REG_SYSTEM__MODE_START 0x0087 62 + #define VL53L1X_REG_RESULT__RANGE_STATUS 0x0089 63 + #define VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 0x0096 64 + #define VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL 0x00DE 65 + #define VL53L1X_REG_FIRMWARE__SYSTEM_STATUS 0x00E5 66 + #define VL53L1X_REG_IDENTIFICATION__MODEL_ID 0x010F 67 + #define VL53L1X_REG_DEFAULT_CONFIG 0x002D 68 + 69 + #define VL53L1X_MODEL_ID_VAL 0xEACC 70 + 71 + #define VL53L1X_MODE_START_TIMED 0x40 72 + #define VL53L1X_MODE_START_STOP 0x00 73 + 74 + #define VL53L1X_INT_NEW_SAMPLE_READY 0x02 75 + 76 + #define VL53L1X_GPIO_HV_MUX_POLARITY BIT(4) 77 + 78 + #define VL53L1X_VHV_LOOP_BOUND_TWO 0x09 79 + 80 + #define VL53L1X_RANGE_STATUS_MASK GENMASK(4, 0) 81 + #define VL53L1X_RANGE_STATUS_VALID 9 82 + 83 + #define VL53L1X_OSC_CALIBRATE_MASK GENMASK(9, 0) 84 + 85 + /* Inter-measurement period uses PLL divider with 1.075 oscillator correction */ 86 + static const struct u32_fract vl53l1x_osc_correction = { 87 + .numerator = 1075, 88 + .denominator = 1000, 89 + }; 90 + 91 + enum vl53l1x_distance_mode { 92 + VL53L1X_SHORT, 93 + VL53L1X_LONG, 94 + }; 95 + 96 + struct vl53l1x_data { 97 + struct regmap *regmap; 98 + struct completion completion; 99 + struct reset_control *xshut_reset; 100 + enum vl53l1x_distance_mode distance_mode; 101 + u8 gpio_polarity; 102 + int irq; 103 + }; 104 + 105 + static const struct regmap_range vl53l1x_volatile_ranges[] = { 106 + regmap_reg_range(VL53L1X_REG_GPIO__TIO_HV_STATUS, 107 + VL53L1X_REG_GPIO__TIO_HV_STATUS), 108 + regmap_reg_range(VL53L1X_REG_RESULT__RANGE_STATUS, 109 + VL53L1X_REG_RESULT__RANGE_STATUS), 110 + regmap_reg_range(VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0, 111 + VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0 + 1), 112 + regmap_reg_range(VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL, 113 + VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL + 1), 114 + regmap_reg_range(VL53L1X_REG_FIRMWARE__SYSTEM_STATUS, 115 + VL53L1X_REG_FIRMWARE__SYSTEM_STATUS), 116 + }; 117 + 118 + static const struct regmap_access_table vl53l1x_volatile_table = { 119 + .yes_ranges = vl53l1x_volatile_ranges, 120 + .n_yes_ranges = ARRAY_SIZE(vl53l1x_volatile_ranges), 121 + }; 122 + 123 + static const struct regmap_range vl53l1x_write_only_ranges[] = { 124 + regmap_reg_range(VL53L1X_REG_SOFT_RESET, VL53L1X_REG_SOFT_RESET), 125 + regmap_reg_range(VL53L1X_REG_SYSTEM__INTERRUPT_CLEAR, 126 + VL53L1X_REG_SYSTEM__MODE_START), 127 + }; 128 + 129 + static const struct regmap_access_table vl53l1x_readable_table = { 130 + .no_ranges = vl53l1x_write_only_ranges, 131 + .n_no_ranges = ARRAY_SIZE(vl53l1x_write_only_ranges), 132 + }; 133 + 134 + static const struct regmap_config vl53l1x_regmap_config = { 135 + .reg_bits = 16, 136 + .val_bits = 8, 137 + /* MODEL_ID is 16-bit. +1 covers the second byte at 0x0110 */ 138 + .max_register = VL53L1X_REG_IDENTIFICATION__MODEL_ID + 1, 139 + .cache_type = REGCACHE_MAPLE, 140 + .volatile_table = &vl53l1x_volatile_table, 141 + .rd_table = &vl53l1x_readable_table, 142 + }; 143 + 144 + static int vl53l1x_read_u16(struct vl53l1x_data *data, u16 reg, u16 *val) 145 + { 146 + __be16 buf; 147 + int ret; 148 + 149 + ret = regmap_bulk_read(data->regmap, reg, &buf, sizeof(buf)); 150 + if (ret) 151 + return ret; 152 + 153 + *val = be16_to_cpu(buf); 154 + return 0; 155 + } 156 + 157 + static int vl53l1x_write_u16(struct vl53l1x_data *data, u16 reg, u16 val) 158 + { 159 + __be16 buf = cpu_to_be16(val); 160 + 161 + return regmap_bulk_write(data->regmap, reg, &buf, sizeof(buf)); 162 + } 163 + 164 + static int vl53l1x_write_u32(struct vl53l1x_data *data, u16 reg, u32 val) 165 + { 166 + __be32 buf = cpu_to_be32(val); 167 + 168 + return regmap_bulk_write(data->regmap, reg, &buf, sizeof(buf)); 169 + } 170 + 171 + static int vl53l1x_clear_irq(struct vl53l1x_data *data) 172 + { 173 + return regmap_write(data->regmap, VL53L1X_REG_SYSTEM__INTERRUPT_CLEAR, 0x01); 174 + } 175 + 176 + static int vl53l1x_start_ranging(struct vl53l1x_data *data) 177 + { 178 + int ret; 179 + 180 + ret = vl53l1x_clear_irq(data); 181 + if (ret) 182 + return ret; 183 + 184 + return regmap_write(data->regmap, VL53L1X_REG_SYSTEM__MODE_START, 185 + VL53L1X_MODE_START_TIMED); 186 + } 187 + 188 + static int vl53l1x_stop_ranging(struct vl53l1x_data *data) 189 + { 190 + return regmap_write(data->regmap, VL53L1X_REG_SYSTEM__MODE_START, 191 + VL53L1X_MODE_START_STOP); 192 + } 193 + 194 + /* 195 + * Default configuration blob from ST's VL53L1X Ultra Lite Driver 196 + * (STSW-IMG009). 197 + */ 198 + static const u8 vl53l1x_default_config[] = { 199 + 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x08, /* reg 0x2d..0x34 */ 200 + 0x00, 0x08, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, /* reg 0x35..0x3c */ 201 + 0x00, 0xFF, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x00, /* reg 0x3d..0x44 */ 202 + 0x00, 0x20, 0x0B, 0x00, 0x00, 0x02, 0x0A, 0x21, /* reg 0x45..0x4c */ 203 + 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0xC8, /* reg 0x4d..0x54 */ 204 + 0x00, 0x00, 0x38, 0xFF, 0x01, 0x00, 0x08, 0x00, /* reg 0x55..0x5c */ 205 + 0x00, 0x01, 0xCC, 0x0F, 0x01, 0xF1, 0x0D, 0x01, /* reg 0x5d..0x64 */ 206 + 0x68, 0x00, 0x80, 0x08, 0xB8, 0x00, 0x00, 0x00, /* reg 0x65..0x6c */ 207 + 0x00, 0x0F, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, /* reg 0x6d..0x74 */ 208 + 0x00, 0x00, 0x01, 0x0F, 0x0D, 0x0E, 0x0E, 0x00, /* reg 0x75..0x7c */ 209 + 0x00, 0x02, 0xC7, 0xFF, 0x9B, 0x00, 0x00, 0x00, /* reg 0x7d..0x84 */ 210 + 0x01, 0x00, 0x00, /* reg 0x85..0x87 */ 211 + }; 212 + 213 + static int vl53l1x_chip_init(struct vl53l1x_data *data) 214 + { 215 + struct device *dev = regmap_get_device(data->regmap); 216 + unsigned int val; 217 + u16 model_id; 218 + int ret; 219 + 220 + if (!data->xshut_reset) { 221 + ret = regmap_write(data->regmap, VL53L1X_REG_SOFT_RESET, 0x00); 222 + if (ret) 223 + return ret; 224 + fsleep(100); /* conservative reset pulse, no spec */ 225 + 226 + ret = regmap_write(data->regmap, VL53L1X_REG_SOFT_RESET, 0x01); 227 + if (ret) 228 + return ret; 229 + fsleep(1000); /* conservative boot wait, no spec */ 230 + } 231 + 232 + ret = regmap_read_poll_timeout(data->regmap, 233 + VL53L1X_REG_FIRMWARE__SYSTEM_STATUS, val, 234 + val & BIT(0), 235 + 1 * USEC_PER_MSEC, 236 + 100 * USEC_PER_MSEC); 237 + if (ret) 238 + return dev_err_probe(dev, ret, "firmware boot timeout\n"); 239 + 240 + ret = vl53l1x_read_u16(data, VL53L1X_REG_IDENTIFICATION__MODEL_ID, 241 + &model_id); 242 + if (ret) 243 + return ret; 244 + 245 + if (model_id != VL53L1X_MODEL_ID_VAL) 246 + dev_info(dev, "unknown model id: 0x%04x, continuing\n", model_id); 247 + 248 + ret = regmap_bulk_write(data->regmap, VL53L1X_REG_DEFAULT_CONFIG, 249 + vl53l1x_default_config, 250 + sizeof(vl53l1x_default_config)); 251 + if (ret) 252 + return ret; 253 + 254 + ret = regmap_read(data->regmap, VL53L1X_REG_GPIO_HV_MUX__CTRL, &val); 255 + if (ret) 256 + return ret; 257 + data->gpio_polarity = !!(val & VL53L1X_GPIO_HV_MUX_POLARITY); 258 + 259 + /* Initial ranging cycle for VHV calibration */ 260 + ret = vl53l1x_start_ranging(data); 261 + if (ret) 262 + return ret; 263 + 264 + /* 1ms poll, 1s timeout covers max timing budgets (per ST Ultra Lite Driver) */ 265 + ret = regmap_read_poll_timeout(data->regmap, 266 + VL53L1X_REG_GPIO__TIO_HV_STATUS, val, 267 + (val & 1) != data->gpio_polarity, 268 + 1 * USEC_PER_MSEC, 269 + 1000 * USEC_PER_MSEC); 270 + if (ret) 271 + return ret; 272 + 273 + ret = vl53l1x_clear_irq(data); 274 + if (ret) 275 + return ret; 276 + 277 + ret = vl53l1x_stop_ranging(data); 278 + if (ret) 279 + return ret; 280 + 281 + ret = regmap_write(data->regmap, 282 + VL53L1X_REG_VHV_CONFIG__TIMEOUT_MACROP_LOOP_BOUND, 283 + VL53L1X_VHV_LOOP_BOUND_TWO); 284 + if (ret) 285 + return ret; 286 + 287 + return regmap_write(data->regmap, VL53L1X_REG_VHV_CONFIG__INIT, 0x00); 288 + } 289 + 290 + static const struct reg_sequence vl53l1x_mode_short[] = { 291 + { VL53L1X_REG_PHASECAL_CONFIG__TIMEOUT_MACROP, 0x14 }, 292 + { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_A, 0x07 }, 293 + { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_B, 0x05 }, 294 + { VL53L1X_REG_RANGE_CONFIG__VALID_PHASE_HIGH, 0x38 }, 295 + { VL53L1X_REG_SD_CONFIG__WOI_SD0, 0x07 }, 296 + { VL53L1X_REG_SD_CONFIG__WOI_SD1, 0x05 }, 297 + { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD0, 0x06 }, 298 + { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD1, 0x06 }, 299 + }; 300 + 301 + static const struct reg_sequence vl53l1x_mode_long[] = { 302 + { VL53L1X_REG_PHASECAL_CONFIG__TIMEOUT_MACROP, 0x0A }, 303 + { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_A, 0x0F }, 304 + { VL53L1X_REG_RANGE_CONFIG__VCSEL_PERIOD_B, 0x0D }, 305 + { VL53L1X_REG_RANGE_CONFIG__VALID_PHASE_HIGH, 0xB8 }, 306 + { VL53L1X_REG_SD_CONFIG__WOI_SD0, 0x0F }, 307 + { VL53L1X_REG_SD_CONFIG__WOI_SD1, 0x0D }, 308 + { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD0, 0x0E }, 309 + { VL53L1X_REG_SD_CONFIG__INITIAL_PHASE_SD1, 0x0E }, 310 + }; 311 + 312 + static const struct { 313 + const struct reg_sequence *regs; 314 + size_t num_regs; 315 + } vl53l1x_mode_configs[] = { 316 + [VL53L1X_SHORT] = { vl53l1x_mode_short, ARRAY_SIZE(vl53l1x_mode_short) }, 317 + [VL53L1X_LONG] = { vl53l1x_mode_long, ARRAY_SIZE(vl53l1x_mode_long) }, 318 + }; 319 + 320 + static int vl53l1x_set_distance_mode(struct vl53l1x_data *data, 321 + enum vl53l1x_distance_mode mode) 322 + { 323 + int ret; 324 + 325 + if (mode >= ARRAY_SIZE(vl53l1x_mode_configs)) 326 + return -EINVAL; 327 + 328 + ret = regmap_multi_reg_write(data->regmap, 329 + vl53l1x_mode_configs[mode].regs, 330 + vl53l1x_mode_configs[mode].num_regs); 331 + if (ret) 332 + return ret; 333 + 334 + data->distance_mode = mode; 335 + return 0; 336 + } 337 + 338 + /* 339 + * The timing budget controls how long the sensor spends collecting 340 + * a single range measurement. Pre-computed TIMEOUT_MACROP register 341 + * values from ST's VL53L1X Ultra Lite Driver. 342 + */ 343 + static int vl53l1x_set_timing_budget(struct vl53l1x_data *data, u16 budget_ms) 344 + { 345 + u16 timeout_a, timeout_b; 346 + int ret; 347 + 348 + switch (data->distance_mode) { 349 + case VL53L1X_SHORT: 350 + switch (budget_ms) { 351 + case 15: 352 + timeout_a = 0x001D; 353 + timeout_b = 0x0027; 354 + break; 355 + case 20: 356 + timeout_a = 0x0051; 357 + timeout_b = 0x006E; 358 + break; 359 + case 33: 360 + timeout_a = 0x00D6; 361 + timeout_b = 0x006E; 362 + break; 363 + case 50: 364 + timeout_a = 0x01AE; 365 + timeout_b = 0x01E8; 366 + break; 367 + case 100: 368 + timeout_a = 0x02E1; 369 + timeout_b = 0x0388; 370 + break; 371 + case 200: 372 + timeout_a = 0x03E1; 373 + timeout_b = 0x0496; 374 + break; 375 + case 500: 376 + timeout_a = 0x0591; 377 + timeout_b = 0x05C1; 378 + break; 379 + default: 380 + return -EINVAL; 381 + } 382 + break; 383 + case VL53L1X_LONG: 384 + switch (budget_ms) { 385 + case 20: 386 + timeout_a = 0x001E; 387 + timeout_b = 0x0022; 388 + break; 389 + case 33: 390 + timeout_a = 0x0060; 391 + timeout_b = 0x006E; 392 + break; 393 + case 50: 394 + timeout_a = 0x00AD; 395 + timeout_b = 0x00C6; 396 + break; 397 + case 100: 398 + timeout_a = 0x01CC; 399 + timeout_b = 0x01EA; 400 + break; 401 + case 200: 402 + timeout_a = 0x02D9; 403 + timeout_b = 0x02F8; 404 + break; 405 + case 500: 406 + timeout_a = 0x048F; 407 + timeout_b = 0x04A4; 408 + break; 409 + default: 410 + return -EINVAL; 411 + } 412 + break; 413 + default: 414 + return -EINVAL; 415 + } 416 + 417 + ret = vl53l1x_write_u16(data, VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_A, 418 + timeout_a); 419 + if (ret) 420 + return ret; 421 + 422 + return vl53l1x_write_u16(data, VL53L1X_REG_RANGE_CONFIG__TIMEOUT_MACROP_B, 423 + timeout_b); 424 + } 425 + 426 + static int vl53l1x_set_inter_measurement_ms(struct vl53l1x_data *data, 427 + u16 period_ms) 428 + { 429 + u16 osc_calibrate_val; 430 + u16 clock_pll; 431 + u32 inter_meas; 432 + int ret; 433 + 434 + ret = vl53l1x_read_u16(data, VL53L1X_REG_RESULT__OSC_CALIBRATE_VAL, 435 + &osc_calibrate_val); 436 + if (ret) 437 + return ret; 438 + 439 + clock_pll = osc_calibrate_val & VL53L1X_OSC_CALIBRATE_MASK; 440 + inter_meas = (clock_pll * period_ms * vl53l1x_osc_correction.numerator) / 441 + vl53l1x_osc_correction.denominator; 442 + 443 + return vl53l1x_write_u32(data, 444 + VL53L1X_REG_SYSTEM__INTERMEASUREMENT_PERIOD, 445 + inter_meas); 446 + } 447 + 448 + static int vl53l1x_read_proximity(struct vl53l1x_data *data, int *val) 449 + { 450 + unsigned int range_status; 451 + u16 distance; 452 + int ret; 453 + 454 + if (data->irq) { 455 + reinit_completion(&data->completion); 456 + 457 + ret = vl53l1x_clear_irq(data); 458 + if (ret) 459 + return ret; 460 + 461 + if (!wait_for_completion_timeout(&data->completion, HZ)) 462 + return -ETIMEDOUT; 463 + } else { 464 + unsigned int rdy; 465 + 466 + /* 1ms poll, 1s timeout covers max timing budgets (per ST Ultra Lite Driver) */ 467 + ret = regmap_read_poll_timeout(data->regmap, 468 + VL53L1X_REG_GPIO__TIO_HV_STATUS, rdy, 469 + (rdy & 1) != data->gpio_polarity, 470 + 1 * USEC_PER_MSEC, 471 + 1000 * USEC_PER_MSEC); 472 + if (ret) 473 + return ret; 474 + } 475 + 476 + ret = regmap_read(data->regmap, VL53L1X_REG_RESULT__RANGE_STATUS, 477 + &range_status); 478 + if (ret) 479 + goto clear_irq; 480 + 481 + if (FIELD_GET(VL53L1X_RANGE_STATUS_MASK, range_status) != 482 + VL53L1X_RANGE_STATUS_VALID) { 483 + ret = -EIO; 484 + goto clear_irq; 485 + } 486 + 487 + ret = vl53l1x_read_u16(data, 488 + VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0, 489 + &distance); 490 + if (ret) 491 + goto clear_irq; 492 + 493 + *val = distance; 494 + 495 + clear_irq: 496 + vl53l1x_clear_irq(data); 497 + return ret; 498 + } 499 + 500 + static const struct iio_chan_spec vl53l1x_channels[] = { 501 + { 502 + .type = IIO_DISTANCE, 503 + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 504 + BIT(IIO_CHAN_INFO_SCALE), 505 + .scan_index = 0, 506 + .scan_type = { 507 + .sign = 'u', 508 + .realbits = 16, 509 + .storagebits = 16, 510 + }, 511 + }, 512 + IIO_CHAN_SOFT_TIMESTAMP(1), 513 + }; 514 + 515 + static int vl53l1x_read_raw(struct iio_dev *indio_dev, 516 + const struct iio_chan_spec *chan, 517 + int *val, int *val2, long mask) 518 + { 519 + struct vl53l1x_data *data = iio_priv(indio_dev); 520 + int ret; 521 + 522 + if (chan->type != IIO_DISTANCE) 523 + return -EINVAL; 524 + 525 + switch (mask) { 526 + case IIO_CHAN_INFO_RAW: 527 + if (!iio_device_claim_direct(indio_dev)) 528 + return -EBUSY; 529 + ret = vl53l1x_read_proximity(data, val); 530 + iio_device_release_direct(indio_dev); 531 + if (ret) 532 + return ret; 533 + return IIO_VAL_INT; 534 + case IIO_CHAN_INFO_SCALE: 535 + *val = 0; 536 + *val2 = 1000; 537 + return IIO_VAL_INT_PLUS_MICRO; 538 + default: 539 + return -EINVAL; 540 + } 541 + } 542 + 543 + static const struct iio_info vl53l1x_info = { 544 + .read_raw = vl53l1x_read_raw, 545 + .validate_trigger = iio_validate_own_trigger, 546 + }; 547 + 548 + static irqreturn_t vl53l1x_trigger_handler(int irq, void *priv) 549 + { 550 + struct iio_poll_func *pf = priv; 551 + struct iio_dev *indio_dev = pf->indio_dev; 552 + struct vl53l1x_data *data = iio_priv(indio_dev); 553 + struct { 554 + u16 distance; 555 + aligned_s64 timestamp; 556 + } scan = { }; 557 + unsigned int range_status; 558 + int ret; 559 + 560 + ret = regmap_read(data->regmap, VL53L1X_REG_RESULT__RANGE_STATUS, 561 + &range_status); 562 + if (ret) 563 + goto notify_and_clear_irq; 564 + if (FIELD_GET(VL53L1X_RANGE_STATUS_MASK, range_status) != 565 + VL53L1X_RANGE_STATUS_VALID) 566 + goto notify_and_clear_irq; 567 + 568 + ret = vl53l1x_read_u16(data, 569 + VL53L1X_REG_RESULT__FINAL_CROSSTALK_CORRECTED_RANGE_MM_SD0, 570 + &scan.distance); 571 + if (ret) 572 + goto notify_and_clear_irq; 573 + 574 + iio_push_to_buffers_with_ts(indio_dev, &scan, sizeof(scan), 575 + iio_get_time_ns(indio_dev)); 576 + 577 + notify_and_clear_irq: 578 + iio_trigger_notify_done(indio_dev->trig); 579 + vl53l1x_clear_irq(data); 580 + 581 + return IRQ_HANDLED; 582 + } 583 + 584 + static irqreturn_t vl53l1x_irq_handler(int irq, void *priv) 585 + { 586 + struct iio_dev *indio_dev = priv; 587 + struct vl53l1x_data *data = iio_priv(indio_dev); 588 + 589 + if (iio_buffer_enabled(indio_dev)) 590 + iio_trigger_poll(indio_dev->trig); 591 + else 592 + complete(&data->completion); 593 + 594 + return IRQ_HANDLED; 595 + } 596 + 597 + static const struct iio_trigger_ops vl53l1x_trigger_ops = { 598 + .validate_device = iio_trigger_validate_own_device, 599 + }; 600 + 601 + static void vl53l1x_stop_ranging_action(void *priv) 602 + { 603 + vl53l1x_stop_ranging(priv); 604 + } 605 + 606 + static int vl53l1x_configure_irq(struct device *dev, int irq, 607 + struct iio_dev *indio_dev) 608 + { 609 + struct vl53l1x_data *data = iio_priv(indio_dev); 610 + int ret; 611 + 612 + ret = devm_request_irq(dev, irq, vl53l1x_irq_handler, IRQF_NO_THREAD, 613 + indio_dev->name, indio_dev); 614 + if (ret) 615 + return ret; 616 + 617 + ret = regmap_write(data->regmap, VL53L1X_REG_SYSTEM__INTERRUPT_CONFIG_GPIO, 618 + VL53L1X_INT_NEW_SAMPLE_READY); 619 + if (ret) 620 + return dev_err_probe(dev, ret, "failed to configure IRQ\n"); 621 + 622 + return 0; 623 + } 624 + 625 + static int vl53l1x_probe(struct i2c_client *client) 626 + { 627 + struct device *dev = &client->dev; 628 + struct vl53l1x_data *data; 629 + struct iio_dev *indio_dev; 630 + int ret; 631 + 632 + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); 633 + if (!indio_dev) 634 + return -ENOMEM; 635 + 636 + data = iio_priv(indio_dev); 637 + data->irq = client->irq; 638 + 639 + data->regmap = devm_regmap_init_i2c(client, &vl53l1x_regmap_config); 640 + if (IS_ERR(data->regmap)) 641 + return dev_err_probe(dev, PTR_ERR(data->regmap), 642 + "regmap initialization failed\n"); 643 + 644 + ret = devm_regulator_get_enable(dev, "vdd"); 645 + if (ret) 646 + return dev_err_probe(dev, ret, "Failed to enable VDD regulator\n"); 647 + 648 + /* 649 + * XSHUT held low puts the chip in hardware standby. All register 650 + * state is lost on de-assert so this is functionally a reset. 651 + */ 652 + data->xshut_reset = devm_reset_control_get_optional_exclusive_deasserted(dev, NULL); 653 + if (IS_ERR(data->xshut_reset)) 654 + return dev_err_probe(dev, PTR_ERR(data->xshut_reset), 655 + "Cannot get reset control\n"); 656 + 657 + /* 658 + * 1.2 ms max boot duration. 659 + * Datasheet Section 3.6 "Power up and boot sequence". 660 + */ 661 + fsleep(1200); 662 + 663 + ret = vl53l1x_chip_init(data); 664 + if (ret) 665 + return ret; 666 + 667 + ret = vl53l1x_set_distance_mode(data, VL53L1X_LONG); 668 + if (ret) 669 + return ret; 670 + 671 + /* 50 ms timing budget (per ST Ultra Lite Driver) */ 672 + ret = vl53l1x_set_timing_budget(data, 50); 673 + if (ret) 674 + return ret; 675 + 676 + /* 50 ms inter-measurement period (per ST Ultra Lite Driver) */ 677 + ret = vl53l1x_set_inter_measurement_ms(data, 50); 678 + if (ret) 679 + return ret; 680 + 681 + /* 682 + * The hardware only supports "autonomous" continuous ranging mode. 683 + * Start ranging here and leave it running for the lifetime of 684 + * the device. Both direct reads and the buffer path rely on this. 685 + */ 686 + ret = vl53l1x_start_ranging(data); 687 + if (ret) 688 + return ret; 689 + 690 + ret = devm_add_action_or_reset(dev, vl53l1x_stop_ranging_action, data); 691 + if (ret) 692 + return ret; 693 + 694 + indio_dev->name = "vl53l1x"; 695 + indio_dev->info = &vl53l1x_info; 696 + indio_dev->channels = vl53l1x_channels; 697 + indio_dev->num_channels = ARRAY_SIZE(vl53l1x_channels); 698 + indio_dev->modes = INDIO_DIRECT_MODE; 699 + 700 + if (client->irq) { 701 + struct iio_trigger *trig; 702 + 703 + init_completion(&data->completion); 704 + 705 + trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name, 706 + iio_device_id(indio_dev)); 707 + if (!trig) 708 + return -ENOMEM; 709 + 710 + trig->ops = &vl53l1x_trigger_ops; 711 + iio_trigger_set_drvdata(trig, indio_dev); 712 + ret = devm_iio_trigger_register(dev, trig); 713 + if (ret) 714 + return ret; 715 + 716 + indio_dev->trig = iio_trigger_get(trig); 717 + 718 + ret = vl53l1x_configure_irq(dev, client->irq, indio_dev); 719 + if (ret) 720 + return ret; 721 + 722 + ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL, 723 + &vl53l1x_trigger_handler, 724 + NULL); 725 + if (ret) 726 + return ret; 727 + } 728 + 729 + return devm_iio_device_register(dev, indio_dev); 730 + } 731 + 732 + static const struct i2c_device_id vl53l1x_id[] = { 733 + { "vl53l1x" }, 734 + { } 735 + }; 736 + MODULE_DEVICE_TABLE(i2c, vl53l1x_id); 737 + 738 + static const struct of_device_id st_vl53l1x_dt_match[] = { 739 + { .compatible = "st,vl53l1x" }, 740 + { } 741 + }; 742 + MODULE_DEVICE_TABLE(of, st_vl53l1x_dt_match); 743 + 744 + static struct i2c_driver vl53l1x_driver = { 745 + .driver = { 746 + .name = "vl53l1x-i2c", 747 + .of_match_table = st_vl53l1x_dt_match, 748 + }, 749 + .probe = vl53l1x_probe, 750 + .id_table = vl53l1x_id, 751 + }; 752 + module_i2c_driver(vl53l1x_driver); 753 + 754 + MODULE_AUTHOR("Siratul Islam <email@sirat.me>"); 755 + MODULE_DESCRIPTION("ST VL53L1X ToF ranging sensor driver"); 756 + MODULE_LICENSE("Dual BSD/GPL");