diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2011-06-02 14:18:53 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2011-07-31 17:28:20 -0400 |
commit | e69b6de181167a132eee7c38c7e4b47dea3d8e49 (patch) | |
tree | 2c0fceff037fa76791155bbbf6bec8d75a5bbc1e /drivers/mfd/wm831x-core.c | |
parent | c1a82780b41e78f31636c49279ce940afe60a453 (diff) |
mfd: Refactor wm831x AUXADC handling into a separate file
In preparation for some additional work on the wm831x AUXADC code move the
support into a separate file. This is a simple code motion patch, there
should be no functional changes.
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/wm831x-core.c')
-rw-r--r-- | drivers/mfd/wm831x-core.c | 167 |
1 files changed, 1 insertions, 166 deletions
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 480abc18f9f3..772fe584f3b8 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -306,161 +306,6 @@ out: | |||
306 | } | 306 | } |
307 | EXPORT_SYMBOL_GPL(wm831x_set_bits); | 307 | EXPORT_SYMBOL_GPL(wm831x_set_bits); |
308 | 308 | ||
309 | /** | ||
310 | * wm831x_auxadc_read: Read a value from the WM831x AUXADC | ||
311 | * | ||
312 | * @wm831x: Device to read from. | ||
313 | * @input: AUXADC input to read. | ||
314 | */ | ||
315 | int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) | ||
316 | { | ||
317 | int ret, src, irq_masked, timeout; | ||
318 | |||
319 | /* Are we using the interrupt? */ | ||
320 | irq_masked = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_1_MASK); | ||
321 | irq_masked &= WM831X_AUXADC_DATA_EINT; | ||
322 | |||
323 | mutex_lock(&wm831x->auxadc_lock); | ||
324 | |||
325 | ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, | ||
326 | WM831X_AUX_ENA, WM831X_AUX_ENA); | ||
327 | if (ret < 0) { | ||
328 | dev_err(wm831x->dev, "Failed to enable AUXADC: %d\n", ret); | ||
329 | goto out; | ||
330 | } | ||
331 | |||
332 | /* We force a single source at present */ | ||
333 | src = input; | ||
334 | ret = wm831x_reg_write(wm831x, WM831X_AUXADC_SOURCE, | ||
335 | 1 << src); | ||
336 | if (ret < 0) { | ||
337 | dev_err(wm831x->dev, "Failed to set AUXADC source: %d\n", ret); | ||
338 | goto out; | ||
339 | } | ||
340 | |||
341 | /* Clear any notification from a very late arriving interrupt */ | ||
342 | try_wait_for_completion(&wm831x->auxadc_done); | ||
343 | |||
344 | ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, | ||
345 | WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA); | ||
346 | if (ret < 0) { | ||
347 | dev_err(wm831x->dev, "Failed to start AUXADC: %d\n", ret); | ||
348 | goto disable; | ||
349 | } | ||
350 | |||
351 | if (irq_masked) { | ||
352 | /* If we're not using interrupts then poll the | ||
353 | * interrupt status register */ | ||
354 | timeout = 5; | ||
355 | while (timeout) { | ||
356 | msleep(1); | ||
357 | |||
358 | ret = wm831x_reg_read(wm831x, | ||
359 | WM831X_INTERRUPT_STATUS_1); | ||
360 | if (ret < 0) { | ||
361 | dev_err(wm831x->dev, | ||
362 | "ISR 1 read failed: %d\n", ret); | ||
363 | goto disable; | ||
364 | } | ||
365 | |||
366 | /* Did it complete? */ | ||
367 | if (ret & WM831X_AUXADC_DATA_EINT) { | ||
368 | wm831x_reg_write(wm831x, | ||
369 | WM831X_INTERRUPT_STATUS_1, | ||
370 | WM831X_AUXADC_DATA_EINT); | ||
371 | break; | ||
372 | } else { | ||
373 | dev_err(wm831x->dev, | ||
374 | "AUXADC conversion timeout\n"); | ||
375 | ret = -EBUSY; | ||
376 | goto disable; | ||
377 | } | ||
378 | } | ||
379 | |||
380 | ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); | ||
381 | if (ret < 0) { | ||
382 | dev_err(wm831x->dev, | ||
383 | "Failed to read AUXADC data: %d\n", ret); | ||
384 | goto disable; | ||
385 | } | ||
386 | |||
387 | wm831x->auxadc_data = ret; | ||
388 | |||
389 | } else { | ||
390 | /* If we are using interrupts then wait for the | ||
391 | * interrupt to complete. Use an extremely long | ||
392 | * timeout to handle situations with heavy load where | ||
393 | * the notification of the interrupt may be delayed by | ||
394 | * threaded IRQ handling. */ | ||
395 | if (!wait_for_completion_timeout(&wm831x->auxadc_done, | ||
396 | msecs_to_jiffies(500))) { | ||
397 | dev_err(wm831x->dev, "Timed out waiting for AUXADC\n"); | ||
398 | ret = -EBUSY; | ||
399 | goto disable; | ||
400 | } | ||
401 | } | ||
402 | |||
403 | src = ((wm831x->auxadc_data & WM831X_AUX_DATA_SRC_MASK) | ||
404 | >> WM831X_AUX_DATA_SRC_SHIFT) - 1; | ||
405 | |||
406 | if (src == 14) | ||
407 | src = WM831X_AUX_CAL; | ||
408 | |||
409 | if (src != input) { | ||
410 | dev_err(wm831x->dev, "Data from source %d not %d\n", | ||
411 | src, input); | ||
412 | ret = -EINVAL; | ||
413 | } else { | ||
414 | ret = wm831x->auxadc_data & WM831X_AUX_DATA_MASK; | ||
415 | } | ||
416 | |||
417 | disable: | ||
418 | wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0); | ||
419 | out: | ||
420 | mutex_unlock(&wm831x->auxadc_lock); | ||
421 | return ret; | ||
422 | } | ||
423 | EXPORT_SYMBOL_GPL(wm831x_auxadc_read); | ||
424 | |||
425 | static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data) | ||
426 | { | ||
427 | struct wm831x *wm831x = irq_data; | ||
428 | int ret; | ||
429 | |||
430 | ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); | ||
431 | if (ret < 0) { | ||
432 | dev_err(wm831x->dev, | ||
433 | "Failed to read AUXADC data: %d\n", ret); | ||
434 | wm831x->auxadc_data = 0xffff; | ||
435 | } else { | ||
436 | wm831x->auxadc_data = ret; | ||
437 | } | ||
438 | |||
439 | complete(&wm831x->auxadc_done); | ||
440 | |||
441 | return IRQ_HANDLED; | ||
442 | } | ||
443 | |||
444 | /** | ||
445 | * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC | ||
446 | * | ||
447 | * @wm831x: Device to read from. | ||
448 | * @input: AUXADC input to read. | ||
449 | */ | ||
450 | int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input) | ||
451 | { | ||
452 | int ret; | ||
453 | |||
454 | ret = wm831x_auxadc_read(wm831x, input); | ||
455 | if (ret < 0) | ||
456 | return ret; | ||
457 | |||
458 | ret *= 1465; | ||
459 | |||
460 | return ret; | ||
461 | } | ||
462 | EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv); | ||
463 | |||
464 | static struct resource wm831x_dcdc1_resources[] = { | 309 | static struct resource wm831x_dcdc1_resources[] = { |
465 | { | 310 | { |
466 | .start = WM831X_DC1_CONTROL_1, | 311 | .start = WM831X_DC1_CONTROL_1, |
@@ -1447,8 +1292,6 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1447 | 1292 | ||
1448 | mutex_init(&wm831x->io_lock); | 1293 | mutex_init(&wm831x->io_lock); |
1449 | mutex_init(&wm831x->key_lock); | 1294 | mutex_init(&wm831x->key_lock); |
1450 | mutex_init(&wm831x->auxadc_lock); | ||
1451 | init_completion(&wm831x->auxadc_done); | ||
1452 | dev_set_drvdata(wm831x->dev, wm831x); | 1295 | dev_set_drvdata(wm831x->dev, wm831x); |
1453 | 1296 | ||
1454 | ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); | 1297 | ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); |
@@ -1603,15 +1446,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1603 | if (ret != 0) | 1446 | if (ret != 0) |
1604 | goto err; | 1447 | goto err; |
1605 | 1448 | ||
1606 | if (wm831x->irq_base) { | 1449 | wm831x_auxadc_init(wm831x); |
1607 | ret = request_threaded_irq(wm831x->irq_base + | ||
1608 | WM831X_IRQ_AUXADC_DATA, | ||
1609 | NULL, wm831x_auxadc_irq, 0, | ||
1610 | "auxadc", wm831x); | ||
1611 | if (ret < 0) | ||
1612 | dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n", | ||
1613 | ret); | ||
1614 | } | ||
1615 | 1450 | ||
1616 | /* The core device is up, instantiate the subdevices. */ | 1451 | /* The core device is up, instantiate the subdevices. */ |
1617 | switch (parent) { | 1452 | switch (parent) { |