aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Koch <mail@alexanderkoch.net>2016-01-16 11:14:38 -0500
committerJonathan Cameron <jic23@kernel.org>2016-01-30 11:26:47 -0500
commitac663db3678a62f69a2a73126e51a9a302b27ff2 (patch)
treea2ac193d50fda7f870af9d1683fcaa4f71f2f099
parent84e8d090c57522c5f8ae59f5b922bedb929165c7 (diff)
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>
-rw-r--r--drivers/iio/light/opt3001.c137
1 files changed, 95 insertions, 42 deletions
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index b05c484a1646..b776c8ed4387 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -70,9 +70,12 @@
70 70
71/* 71/*
72 * Time to wait for conversion result to be ready. The device datasheet 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
77struct opt3001 { 80struct opt3001 {
78 struct i2c_client *client; 81 struct i2c_client *client;
@@ -92,6 +95,8 @@ struct opt3001 {
92 95
93 u8 high_thresh_exp; 96 u8 high_thresh_exp;
94 u8 low_thresh_exp; 97 u8 low_thresh_exp;
98
99 bool use_irq;
95}; 100};
96 101
97struct opt3001_scale { 102struct opt3001_scale {
@@ -230,26 +235,30 @@ static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2)
230 u16 reg; 235 u16 reg;
231 u8 exponent; 236 u8 exponent;
232 u16 value; 237 u16 value;
238 long timeout;
233 239
234 /* 240 if (opt->use_irq) {
235 * Enable the end-of-conversion interrupt mechanism. Note that doing 241 /*
236 * so will overwrite the low-level limit value however we will restore 242 * Enable the end-of-conversion interrupt mechanism. Note that
237 * this value later on. 243 * doing so will overwrite the low-level limit value however we
238 */ 244 * will restore this value later on.
239 ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT, 245 */
240 OPT3001_LOW_LIMIT_EOC_ENABLE); 246 ret = i2c_smbus_write_word_swapped(opt->client,
241 if (ret < 0) { 247 OPT3001_LOW_LIMIT,
242 dev_err(opt->dev, "failed to write register %02x\n", 248 OPT3001_LOW_LIMIT_EOC_ENABLE);
243 OPT3001_LOW_LIMIT); 249 if (ret < 0) {
244 return ret; 250 dev_err(opt->dev, "failed to write register %02x\n",
251 OPT3001_LOW_LIMIT);
252 return ret;
253 }
254
255 /* Allow IRQ to access the device despite lock being set */
256 opt->ok_to_ignore_lock = true;
245 } 257 }
246 258
247 /* Reset data-ready indicator flag (will be set in the IRQ routine) */ 259 /* Reset data-ready indicator flag */
248 opt->result_ready = false; 260 opt->result_ready = false;
249 261
250 /* Allow IRQ to access the device despite lock being set */
251 opt->ok_to_ignore_lock = true;
252
253 /* Configure for single-conversion mode and start a new conversion */ 262 /* Configure for single-conversion mode and start a new conversion */
254 ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); 263 ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
255 if (ret < 0) { 264 if (ret < 0) {
@@ -269,32 +278,69 @@ static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2)
269 goto err; 278 goto err;
270 } 279 }
271 280
272 /* Wait for the IRQ to indicate the conversion is complete */ 281 if (opt->use_irq) {
273 ret = wait_event_timeout(opt->result_ready_queue, opt->result_ready, 282 /* Wait for the IRQ to indicate the conversion is complete */
274 OPT3001_RESULT_READY_TIMEOUT); 283 ret = wait_event_timeout(opt->result_ready_queue,
284 opt->result_ready,
285 msecs_to_jiffies(OPT3001_RESULT_READY_LONG));
286 } else {
287 /* Sleep for result ready time */
288 timeout = (opt->int_time == OPT3001_INT_TIME_SHORT) ?
289 OPT3001_RESULT_READY_SHORT : OPT3001_RESULT_READY_LONG;
290 msleep(timeout);
291
292 /* Check result ready flag */
293 ret = i2c_smbus_read_word_swapped(opt->client,
294 OPT3001_CONFIGURATION);
295 if (ret < 0) {
296 dev_err(opt->dev, "failed to read register %02x\n",
297 OPT3001_CONFIGURATION);
298 goto err;
299 }
300
301 if (!(ret & OPT3001_CONFIGURATION_CRF)) {
302 ret = -ETIMEDOUT;
303 goto err;
304 }
305
306 /* Obtain value */
307 ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_RESULT);
308 if (ret < 0) {
309 dev_err(opt->dev, "failed to read register %02x\n",
310 OPT3001_RESULT);
311 goto err;
312 }
313 opt->result = ret;
314 opt->result_ready = true;
315 }
275 316
276err: 317err:
277 /* Disallow IRQ to access the device while lock is active */ 318 if (opt->use_irq)
278 opt->ok_to_ignore_lock = false; 319 /* Disallow IRQ to access the device while lock is active */
320 opt->ok_to_ignore_lock = false;
279 321
280 if (ret == 0) 322 if (ret == 0)
281 return -ETIMEDOUT; 323 return -ETIMEDOUT;
282 else if (ret < 0) 324 else if (ret < 0)
283 return ret; 325 return ret;
284 326
285 /* 327 if (opt->use_irq) {
286 * Disable the end-of-conversion interrupt mechanism by restoring the 328 /*
287 * low-level limit value (clearing OPT3001_LOW_LIMIT_EOC_ENABLE). Note 329 * Disable the end-of-conversion interrupt mechanism by
288 * that selectively clearing those enable bits would affect the actual 330 * restoring the low-level limit value (clearing
289 * limit value due to bit-overlap and therefore can't be done. 331 * OPT3001_LOW_LIMIT_EOC_ENABLE). Note that selectively clearing
290 */ 332 * those enable bits would affect the actual limit value due to
291 value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa; 333 * bit-overlap and therefore can't be done.
292 ret = i2c_smbus_write_word_swapped(opt->client, OPT3001_LOW_LIMIT, 334 */
293 value); 335 value = (opt->low_thresh_exp << 12) | opt->low_thresh_mantissa;
294 if (ret < 0) { 336 ret = i2c_smbus_write_word_swapped(opt->client,
295 dev_err(opt->dev, "failed to write register %02x\n", 337 OPT3001_LOW_LIMIT,
296 OPT3001_LOW_LIMIT); 338 value);
297 return ret; 339 if (ret < 0) {
340 dev_err(opt->dev, "failed to write register %02x\n",
341 OPT3001_LOW_LIMIT);
342 return ret;
343 }
298 } 344 }
299 345
300 exponent = OPT3001_REG_EXPONENT(opt->result); 346 exponent = OPT3001_REG_EXPONENT(opt->result);
@@ -736,12 +782,18 @@ static int opt3001_probe(struct i2c_client *client,
736 return ret; 782 return ret;
737 } 783 }
738 784
739 ret = request_threaded_irq(irq, NULL, opt3001_irq, 785 /* Make use of INT pin only if valid IRQ no. is given */
740 IRQF_TRIGGER_FALLING | IRQF_ONESHOT, 786 if (irq > 0) {
741 "opt3001", iio); 787 ret = request_threaded_irq(irq, NULL, opt3001_irq,
742 if (ret) { 788 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
743 dev_err(dev, "failed to request IRQ #%d\n", irq); 789 "opt3001", iio);
744 return ret; 790 if (ret) {
791 dev_err(dev, "failed to request IRQ #%d\n", irq);
792 return ret;
793 }
794 opt->use_irq = true;
795 } else {
796 dev_dbg(opt->dev, "enabling interrupt-less operation\n");
745 } 797 }
746 798
747 return 0; 799 return 0;
@@ -754,7 +806,8 @@ static int opt3001_remove(struct i2c_client *client)
754 int ret; 806 int ret;
755 u16 reg; 807 u16 reg;
756 808
757 free_irq(client->irq, iio); 809 if (opt->use_irq)
810 free_irq(client->irq, iio);
758 811
759 ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION); 812 ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_CONFIGURATION);
760 if (ret < 0) { 813 if (ret < 0) {