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

iio: light: opt3001: enable operation w/o IRQ

Enable operation of the TI OPT3001 light sensor without having an
interrupt line available to connect the INT pin to.

In this operation mode, we issue a conversion request and simply wait
for the conversion time available as timeout value, determined from
integration time configuration and the worst-case time given in the data
sheet (sect. 6.5, table on p. 5):

short integration time (100ms): 110ms + 3ms = 113ms
long integration time (800ms): 880ms + 3ms = 883ms

This change is transparent as behaviour defaults to using the interrupt
method if an interrupt no. is configured via device tree. Interrupt-less
operation mode is performed when no valid interrupt no. is given.

Signed-off-by: Alexander Koch <mail@alexanderkoch.net>
Signed-off-by: Michael Hornung <mhornung.linux@gmail.com>
Tested-by: Andreas Dannenberg <dannenberg@ti.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>

authored by

Alexander Koch and committed by
Jonathan Cameron
ac663db3 84e8d090

+95 -42
+95 -42
drivers/iio/light/opt3001.c
··· 70 70 71 71 /* 72 72 * Time to wait for conversion result to be ready. The device datasheet 73 - * worst-case max value is 880ms. Add some slack to be on the safe side. 73 + * sect. 6.5 states results are ready after total integration time plus 3ms. 74 + * This results in worst-case max values of 113ms or 883ms, respectively. 75 + * Add some slack to be on the safe side. 74 76 */ 75 - #define OPT3001_RESULT_READY_TIMEOUT msecs_to_jiffies(1000) 77 + #define OPT3001_RESULT_READY_SHORT 150 78 + #define OPT3001_RESULT_READY_LONG 1000 76 79 77 80 struct opt3001 { 78 81 struct i2c_client *client; ··· 95 92 96 93 u8 high_thresh_exp; 97 94 u8 low_thresh_exp; 95 + 96 + bool use_irq; 98 97 }; 99 98 100 99 struct opt3001_scale { ··· 235 230 u16 reg; 236 231 u8 exponent; 237 232 u16 value; 233 + long timeout; 238 234 239 - /* 240 - * Enable the end-of-conversion interrupt mechanism. Note that doing 241 - * so will overwrite the low-level limit value however we will restore 242 - * this value later on. 243 - */ 244 - ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT, 245 - OPT3001_LOW_LIMIT_EOC_ENABLE); 246 - if (ret < 0) { 247 - dev_err(opt->dev, "failed to write register %02x\n", 248 - OPT3001_LOW_LIMIT); 249 - return ret; 235 + if (opt->use_irq) { 236 + /* 237 + * Enable the end-of-conversion interrupt mechanism. Note that 238 + * doing so will overwrite the low-level limit value however we 239 + * will restore this value later on. 240 + */ 241 + ret = i2c_smbus_write_word_swapped(opt->client, 242 + OPT3001_LOW_LIMIT, 243 + OPT3001_LOW_LIMIT_EOC_ENABLE); 244 + if (ret < 0) { 245 + dev_err(opt->dev, "failed to write register %02x\n", 246 + OPT3001_LOW_LIMIT); 247 + return ret; 248 + } 249 + 250 + /* Allow IRQ to access the device despite lock being set */ 251 + opt->ok_to_ignore_lock = true; 250 252 } 251 253 252 - /* Reset data-ready indicator flag (will be set in the IRQ routine) */ 254 + /* Reset data-ready indicator flag */ 253 255 opt->result_ready = false; 254 - 255 - /* Allow IRQ to access the device despite lock being set */ 256 - opt->ok_to_ignore_lock = true; 257 256 258 257 /* Configure for single-conversion mode and start a new conversion */ 259 258 ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); ··· 278 269 goto err; 279 270 } 280 271 281 - /* Wait for the IRQ to indicate the conversion is complete */ 282 - ret = wait_event_timeout(opt->result_ready_queue, opt->result_ready, 283 - OPT3001_RESULT_READY_TIMEOUT); 272 + if (opt->use_irq) { 273 + /* Wait for the IRQ to indicate the conversion is complete */ 274 + ret = wait_event_timeout(opt->result_ready_queue, 275 + opt->result_ready, 276 + msecs_to_jiffies(OPT3001_RESULT_READY_LONG)); 277 + } else { 278 + /* Sleep for result ready time */ 279 + timeout = (opt->int_time == OPT3001_INT_TIME_SHORT) ? 280 + OPT3001_RESULT_READY_SHORT : OPT3001_RESULT_READY_LONG; 281 + msleep(timeout); 282 + 283 + /* Check result ready flag */ 284 + ret = i2c_smbus_read_word_swapped(opt->client, 285 + OPT3001_CONFIGURATION); 286 + if (ret < 0) { 287 + dev_err(opt->dev, "failed to read register %02x\n", 288 + OPT3001_CONFIGURATION); 289 + goto err; 290 + } 291 + 292 + if (!(ret & OPT3001_CONFIGURATION_CRF)) { 293 + ret = -ETIMEDOUT; 294 + goto err; 295 + } 296 + 297 + /* Obtain value */ 298 + ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT); 299 + if (ret < 0) { 300 + dev_err(opt->dev, "failed to read register %02x\n", 301 + OPT3001_RESULT); 302 + goto err; 303 + } 304 + opt->result = ret; 305 + opt->result_ready = true; 306 + } 284 307 285 308 err: 286 - /* Disallow IRQ to access the device while lock is active */ 287 - opt->ok_to_ignore_lock = false; 309 + if (opt->use_irq) 310 + /* Disallow IRQ to access the device while lock is active */ 311 + opt->ok_to_ignore_lock = false; 288 312 289 313 if (ret == 0) 290 314 return -ETIMEDOUT; 291 315 else if (ret < 0) 292 316 return ret; 293 317 294 - /* 295 - * Disable the end-of-conversion interrupt mechanism by restoring the 296 - * low-level limit value (clearing OPT3001_LOW_LIMIT_EOC_ENABLE). Note 297 - * that selectively clearing those enable bits would affect the actual 298 - * limit value due to bit-overlap and therefore can't be done. 299 - */ 300 - value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa; 301 - ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT, 302 - value); 303 - if (ret < 0) { 304 - dev_err(opt->dev, "failed to write register %02x\n", 305 - OPT3001_LOW_LIMIT); 306 - return ret; 318 + if (opt->use_irq) { 319 + /* 320 + * Disable the end-of-conversion interrupt mechanism by 321 + * restoring the low-level limit value (clearing 322 + * OPT3001_LOW_LIMIT_EOC_ENABLE). Note that selectively clearing 323 + * those enable bits would affect the actual limit value due to 324 + * bit-overlap and therefore can't be done. 325 + */ 326 + value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa; 327 + ret = i2c_smbus_write_word_swapped(opt->client, 328 + OPT3001_LOW_LIMIT, 329 + value); 330 + if (ret < 0) { 331 + dev_err(opt->dev, "failed to write register %02x\n", 332 + OPT3001_LOW_LIMIT); 333 + return ret; 334 + } 307 335 } 308 336 309 337 exponent = OPT3001_REG_EXPONENT(opt->result); ··· 782 736 return ret; 783 737 } 784 738 785 - ret = request_threaded_irq(irq, NULL, opt3001_irq, 786 - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 787 - "opt3001", iio); 788 - if (ret) { 789 - dev_err(dev, "failed to request IRQ #%d\n", irq); 790 - return ret; 739 + /* Make use of INT pin only if valid IRQ no. is given */ 740 + if (irq > 0) { 741 + ret = request_threaded_irq(irq, NULL, opt3001_irq, 742 + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 743 + "opt3001", iio); 744 + if (ret) { 745 + dev_err(dev, "failed to request IRQ #%d\n", irq); 746 + return ret; 747 + } 748 + opt->use_irq = true; 749 + } else { 750 + dev_dbg(opt->dev, "enabling interrupt-less operation\n"); 791 751 } 792 752 793 753 return 0; ··· 806 754 int ret; 807 755 u16 reg; 808 756 809 - free_irq(client->irq, iio); 757 + if (opt->use_irq) 758 + free_irq(client->irq, iio); 810 759 811 760 ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); 812 761 if (ret < 0) {