diff options
author | Alexander Koch <mail@alexanderkoch.net> | 2016-01-16 11:14:38 -0500 |
---|---|---|
committer | Jonathan Cameron <jic23@kernel.org> | 2016-01-30 11:26:47 -0500 |
commit | ac663db3678a62f69a2a73126e51a9a302b27ff2 (patch) | |
tree | a2ac193d50fda7f870af9d1683fcaa4f71f2f099 | |
parent | 84e8d090c57522c5f8ae59f5b922bedb929165c7 (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.c | 137 |
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 | ||
77 | struct opt3001 { | 80 | struct 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 | ||
97 | struct opt3001_scale { | 102 | struct 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 | ||
276 | err: | 317 | err: |
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) { |