diff options
Diffstat (limited to 'drivers/mfd/wm831x-core.c')
-rw-r--r-- | drivers/mfd/wm831x-core.c | 259 |
1 files changed, 71 insertions, 188 deletions
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 265f75fc6a25..282e76ab678f 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -295,7 +295,7 @@ int wm831x_set_bits(struct wm831x *wm831x, unsigned short reg, | |||
295 | goto out; | 295 | goto out; |
296 | 296 | ||
297 | r &= ~mask; | 297 | r &= ~mask; |
298 | r |= val; | 298 | r |= val & mask; |
299 | 299 | ||
300 | ret = wm831x_write(wm831x, reg, 2, &r); | 300 | ret = wm831x_write(wm831x, reg, 2, &r); |
301 | 301 | ||
@@ -306,146 +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 | } else { | ||
380 | /* If we are using interrupts then wait for the | ||
381 | * interrupt to complete. Use an extremely long | ||
382 | * timeout to handle situations with heavy load where | ||
383 | * the notification of the interrupt may be delayed by | ||
384 | * threaded IRQ handling. */ | ||
385 | if (!wait_for_completion_timeout(&wm831x->auxadc_done, | ||
386 | msecs_to_jiffies(500))) { | ||
387 | dev_err(wm831x->dev, "Timed out waiting for AUXADC\n"); | ||
388 | ret = -EBUSY; | ||
389 | goto disable; | ||
390 | } | ||
391 | } | ||
392 | |||
393 | ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); | ||
394 | if (ret < 0) { | ||
395 | dev_err(wm831x->dev, "Failed to read AUXADC data: %d\n", ret); | ||
396 | } else { | ||
397 | src = ((ret & WM831X_AUX_DATA_SRC_MASK) | ||
398 | >> WM831X_AUX_DATA_SRC_SHIFT) - 1; | ||
399 | |||
400 | if (src == 14) | ||
401 | src = WM831X_AUX_CAL; | ||
402 | |||
403 | if (src != input) { | ||
404 | dev_err(wm831x->dev, "Data from source %d not %d\n", | ||
405 | src, input); | ||
406 | ret = -EINVAL; | ||
407 | } else { | ||
408 | ret &= WM831X_AUX_DATA_MASK; | ||
409 | } | ||
410 | } | ||
411 | |||
412 | disable: | ||
413 | wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, WM831X_AUX_ENA, 0); | ||
414 | out: | ||
415 | mutex_unlock(&wm831x->auxadc_lock); | ||
416 | return ret; | ||
417 | } | ||
418 | EXPORT_SYMBOL_GPL(wm831x_auxadc_read); | ||
419 | |||
420 | static irqreturn_t wm831x_auxadc_irq(int irq, void *irq_data) | ||
421 | { | ||
422 | struct wm831x *wm831x = irq_data; | ||
423 | |||
424 | complete(&wm831x->auxadc_done); | ||
425 | |||
426 | return IRQ_HANDLED; | ||
427 | } | ||
428 | |||
429 | /** | ||
430 | * wm831x_auxadc_read_uv: Read a voltage from the WM831x AUXADC | ||
431 | * | ||
432 | * @wm831x: Device to read from. | ||
433 | * @input: AUXADC input to read. | ||
434 | */ | ||
435 | int wm831x_auxadc_read_uv(struct wm831x *wm831x, enum wm831x_auxadc input) | ||
436 | { | ||
437 | int ret; | ||
438 | |||
439 | ret = wm831x_auxadc_read(wm831x, input); | ||
440 | if (ret < 0) | ||
441 | return ret; | ||
442 | |||
443 | ret *= 1465; | ||
444 | |||
445 | return ret; | ||
446 | } | ||
447 | EXPORT_SYMBOL_GPL(wm831x_auxadc_read_uv); | ||
448 | |||
449 | static struct resource wm831x_dcdc1_resources[] = { | 309 | static struct resource wm831x_dcdc1_resources[] = { |
450 | { | 310 | { |
451 | .start = WM831X_DC1_CONTROL_1, | 311 | .start = WM831X_DC1_CONTROL_1, |
@@ -872,6 +732,9 @@ static struct mfd_cell wm8310_devs[] = { | |||
872 | .resources = wm831x_dcdc4_resources, | 732 | .resources = wm831x_dcdc4_resources, |
873 | }, | 733 | }, |
874 | { | 734 | { |
735 | .name = "wm831x-clk", | ||
736 | }, | ||
737 | { | ||
875 | .name = "wm831x-epe", | 738 | .name = "wm831x-epe", |
876 | .id = 1, | 739 | .id = 1, |
877 | }, | 740 | }, |
@@ -976,11 +839,6 @@ static struct mfd_cell wm8310_devs[] = { | |||
976 | .resources = wm831x_power_resources, | 839 | .resources = wm831x_power_resources, |
977 | }, | 840 | }, |
978 | { | 841 | { |
979 | .name = "wm831x-rtc", | ||
980 | .num_resources = ARRAY_SIZE(wm831x_rtc_resources), | ||
981 | .resources = wm831x_rtc_resources, | ||
982 | }, | ||
983 | { | ||
984 | .name = "wm831x-status", | 842 | .name = "wm831x-status", |
985 | .id = 1, | 843 | .id = 1, |
986 | .num_resources = ARRAY_SIZE(wm831x_status1_resources), | 844 | .num_resources = ARRAY_SIZE(wm831x_status1_resources), |
@@ -1028,6 +886,9 @@ static struct mfd_cell wm8311_devs[] = { | |||
1028 | .resources = wm831x_dcdc4_resources, | 886 | .resources = wm831x_dcdc4_resources, |
1029 | }, | 887 | }, |
1030 | { | 888 | { |
889 | .name = "wm831x-clk", | ||
890 | }, | ||
891 | { | ||
1031 | .name = "wm831x-epe", | 892 | .name = "wm831x-epe", |
1032 | .id = 1, | 893 | .id = 1, |
1033 | }, | 894 | }, |
@@ -1108,11 +969,6 @@ static struct mfd_cell wm8311_devs[] = { | |||
1108 | .resources = wm831x_power_resources, | 969 | .resources = wm831x_power_resources, |
1109 | }, | 970 | }, |
1110 | { | 971 | { |
1111 | .name = "wm831x-rtc", | ||
1112 | .num_resources = ARRAY_SIZE(wm831x_rtc_resources), | ||
1113 | .resources = wm831x_rtc_resources, | ||
1114 | }, | ||
1115 | { | ||
1116 | .name = "wm831x-status", | 972 | .name = "wm831x-status", |
1117 | .id = 1, | 973 | .id = 1, |
1118 | .num_resources = ARRAY_SIZE(wm831x_status1_resources), | 974 | .num_resources = ARRAY_SIZE(wm831x_status1_resources), |
@@ -1125,11 +981,6 @@ static struct mfd_cell wm8311_devs[] = { | |||
1125 | .resources = wm831x_status2_resources, | 981 | .resources = wm831x_status2_resources, |
1126 | }, | 982 | }, |
1127 | { | 983 | { |
1128 | .name = "wm831x-touch", | ||
1129 | .num_resources = ARRAY_SIZE(wm831x_touch_resources), | ||
1130 | .resources = wm831x_touch_resources, | ||
1131 | }, | ||
1132 | { | ||
1133 | .name = "wm831x-watchdog", | 984 | .name = "wm831x-watchdog", |
1134 | .num_resources = ARRAY_SIZE(wm831x_wdt_resources), | 985 | .num_resources = ARRAY_SIZE(wm831x_wdt_resources), |
1135 | .resources = wm831x_wdt_resources, | 986 | .resources = wm831x_wdt_resources, |
@@ -1165,6 +1016,9 @@ static struct mfd_cell wm8312_devs[] = { | |||
1165 | .resources = wm831x_dcdc4_resources, | 1016 | .resources = wm831x_dcdc4_resources, |
1166 | }, | 1017 | }, |
1167 | { | 1018 | { |
1019 | .name = "wm831x-clk", | ||
1020 | }, | ||
1021 | { | ||
1168 | .name = "wm831x-epe", | 1022 | .name = "wm831x-epe", |
1169 | .id = 1, | 1023 | .id = 1, |
1170 | }, | 1024 | }, |
@@ -1269,11 +1123,6 @@ static struct mfd_cell wm8312_devs[] = { | |||
1269 | .resources = wm831x_power_resources, | 1123 | .resources = wm831x_power_resources, |
1270 | }, | 1124 | }, |
1271 | { | 1125 | { |
1272 | .name = "wm831x-rtc", | ||
1273 | .num_resources = ARRAY_SIZE(wm831x_rtc_resources), | ||
1274 | .resources = wm831x_rtc_resources, | ||
1275 | }, | ||
1276 | { | ||
1277 | .name = "wm831x-status", | 1126 | .name = "wm831x-status", |
1278 | .id = 1, | 1127 | .id = 1, |
1279 | .num_resources = ARRAY_SIZE(wm831x_status1_resources), | 1128 | .num_resources = ARRAY_SIZE(wm831x_status1_resources), |
@@ -1286,11 +1135,6 @@ static struct mfd_cell wm8312_devs[] = { | |||
1286 | .resources = wm831x_status2_resources, | 1135 | .resources = wm831x_status2_resources, |
1287 | }, | 1136 | }, |
1288 | { | 1137 | { |
1289 | .name = "wm831x-touch", | ||
1290 | .num_resources = ARRAY_SIZE(wm831x_touch_resources), | ||
1291 | .resources = wm831x_touch_resources, | ||
1292 | }, | ||
1293 | { | ||
1294 | .name = "wm831x-watchdog", | 1138 | .name = "wm831x-watchdog", |
1295 | .num_resources = ARRAY_SIZE(wm831x_wdt_resources), | 1139 | .num_resources = ARRAY_SIZE(wm831x_wdt_resources), |
1296 | .resources = wm831x_wdt_resources, | 1140 | .resources = wm831x_wdt_resources, |
@@ -1326,6 +1170,9 @@ static struct mfd_cell wm8320_devs[] = { | |||
1326 | .resources = wm8320_dcdc4_buck_resources, | 1170 | .resources = wm8320_dcdc4_buck_resources, |
1327 | }, | 1171 | }, |
1328 | { | 1172 | { |
1173 | .name = "wm831x-clk", | ||
1174 | }, | ||
1175 | { | ||
1329 | .name = "wm831x-gpio", | 1176 | .name = "wm831x-gpio", |
1330 | .num_resources = ARRAY_SIZE(wm831x_gpio_resources), | 1177 | .num_resources = ARRAY_SIZE(wm831x_gpio_resources), |
1331 | .resources = wm831x_gpio_resources, | 1178 | .resources = wm831x_gpio_resources, |
@@ -1405,11 +1252,6 @@ static struct mfd_cell wm8320_devs[] = { | |||
1405 | .resources = wm831x_on_resources, | 1252 | .resources = wm831x_on_resources, |
1406 | }, | 1253 | }, |
1407 | { | 1254 | { |
1408 | .name = "wm831x-rtc", | ||
1409 | .num_resources = ARRAY_SIZE(wm831x_rtc_resources), | ||
1410 | .resources = wm831x_rtc_resources, | ||
1411 | }, | ||
1412 | { | ||
1413 | .name = "wm831x-status", | 1255 | .name = "wm831x-status", |
1414 | .id = 1, | 1256 | .id = 1, |
1415 | .num_resources = ARRAY_SIZE(wm831x_status1_resources), | 1257 | .num_resources = ARRAY_SIZE(wm831x_status1_resources), |
@@ -1428,6 +1270,22 @@ static struct mfd_cell wm8320_devs[] = { | |||
1428 | }, | 1270 | }, |
1429 | }; | 1271 | }; |
1430 | 1272 | ||
1273 | static struct mfd_cell touch_devs[] = { | ||
1274 | { | ||
1275 | .name = "wm831x-touch", | ||
1276 | .num_resources = ARRAY_SIZE(wm831x_touch_resources), | ||
1277 | .resources = wm831x_touch_resources, | ||
1278 | }, | ||
1279 | }; | ||
1280 | |||
1281 | static struct mfd_cell rtc_devs[] = { | ||
1282 | { | ||
1283 | .name = "wm831x-rtc", | ||
1284 | .num_resources = ARRAY_SIZE(wm831x_rtc_resources), | ||
1285 | .resources = wm831x_rtc_resources, | ||
1286 | }, | ||
1287 | }; | ||
1288 | |||
1431 | static struct mfd_cell backlight_devs[] = { | 1289 | static struct mfd_cell backlight_devs[] = { |
1432 | { | 1290 | { |
1433 | .name = "wm831x-backlight", | 1291 | .name = "wm831x-backlight", |
@@ -1440,14 +1298,12 @@ static struct mfd_cell backlight_devs[] = { | |||
1440 | int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | 1298 | int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) |
1441 | { | 1299 | { |
1442 | struct wm831x_pdata *pdata = wm831x->dev->platform_data; | 1300 | struct wm831x_pdata *pdata = wm831x->dev->platform_data; |
1443 | int rev; | 1301 | int rev, wm831x_num; |
1444 | enum wm831x_parent parent; | 1302 | enum wm831x_parent parent; |
1445 | int ret, i; | 1303 | int ret, i; |
1446 | 1304 | ||
1447 | mutex_init(&wm831x->io_lock); | 1305 | mutex_init(&wm831x->io_lock); |
1448 | mutex_init(&wm831x->key_lock); | 1306 | mutex_init(&wm831x->key_lock); |
1449 | mutex_init(&wm831x->auxadc_lock); | ||
1450 | init_completion(&wm831x->auxadc_done); | ||
1451 | dev_set_drvdata(wm831x->dev, wm831x); | 1307 | dev_set_drvdata(wm831x->dev, wm831x); |
1452 | 1308 | ||
1453 | ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); | 1309 | ret = wm831x_reg_read(wm831x, WM831X_PARENT_ID); |
@@ -1592,45 +1448,51 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1592 | } | 1448 | } |
1593 | } | 1449 | } |
1594 | 1450 | ||
1451 | /* Multiply by 10 as we have many subdevices of the same type */ | ||
1452 | if (pdata && pdata->wm831x_num) | ||
1453 | wm831x_num = pdata->wm831x_num * 10; | ||
1454 | else | ||
1455 | wm831x_num = -1; | ||
1456 | |||
1595 | ret = wm831x_irq_init(wm831x, irq); | 1457 | ret = wm831x_irq_init(wm831x, irq); |
1596 | if (ret != 0) | 1458 | if (ret != 0) |
1597 | goto err; | 1459 | goto err; |
1598 | 1460 | ||
1599 | if (wm831x->irq_base) { | 1461 | wm831x_auxadc_init(wm831x); |
1600 | ret = request_threaded_irq(wm831x->irq_base + | ||
1601 | WM831X_IRQ_AUXADC_DATA, | ||
1602 | NULL, wm831x_auxadc_irq, 0, | ||
1603 | "auxadc", wm831x); | ||
1604 | if (ret < 0) | ||
1605 | dev_err(wm831x->dev, "AUXADC IRQ request failed: %d\n", | ||
1606 | ret); | ||
1607 | } | ||
1608 | 1462 | ||
1609 | /* The core device is up, instantiate the subdevices. */ | 1463 | /* The core device is up, instantiate the subdevices. */ |
1610 | switch (parent) { | 1464 | switch (parent) { |
1611 | case WM8310: | 1465 | case WM8310: |
1612 | ret = mfd_add_devices(wm831x->dev, -1, | 1466 | ret = mfd_add_devices(wm831x->dev, wm831x_num, |
1613 | wm8310_devs, ARRAY_SIZE(wm8310_devs), | 1467 | wm8310_devs, ARRAY_SIZE(wm8310_devs), |
1614 | NULL, wm831x->irq_base); | 1468 | NULL, wm831x->irq_base); |
1615 | break; | 1469 | break; |
1616 | 1470 | ||
1617 | case WM8311: | 1471 | case WM8311: |
1618 | ret = mfd_add_devices(wm831x->dev, -1, | 1472 | ret = mfd_add_devices(wm831x->dev, wm831x_num, |
1619 | wm8311_devs, ARRAY_SIZE(wm8311_devs), | 1473 | wm8311_devs, ARRAY_SIZE(wm8311_devs), |
1620 | NULL, wm831x->irq_base); | 1474 | NULL, wm831x->irq_base); |
1475 | if (!pdata || !pdata->disable_touch) | ||
1476 | mfd_add_devices(wm831x->dev, wm831x_num, | ||
1477 | touch_devs, ARRAY_SIZE(touch_devs), | ||
1478 | NULL, wm831x->irq_base); | ||
1621 | break; | 1479 | break; |
1622 | 1480 | ||
1623 | case WM8312: | 1481 | case WM8312: |
1624 | ret = mfd_add_devices(wm831x->dev, -1, | 1482 | ret = mfd_add_devices(wm831x->dev, wm831x_num, |
1625 | wm8312_devs, ARRAY_SIZE(wm8312_devs), | 1483 | wm8312_devs, ARRAY_SIZE(wm8312_devs), |
1626 | NULL, wm831x->irq_base); | 1484 | NULL, wm831x->irq_base); |
1485 | if (!pdata || !pdata->disable_touch) | ||
1486 | mfd_add_devices(wm831x->dev, wm831x_num, | ||
1487 | touch_devs, ARRAY_SIZE(touch_devs), | ||
1488 | NULL, wm831x->irq_base); | ||
1627 | break; | 1489 | break; |
1628 | 1490 | ||
1629 | case WM8320: | 1491 | case WM8320: |
1630 | case WM8321: | 1492 | case WM8321: |
1631 | case WM8325: | 1493 | case WM8325: |
1632 | case WM8326: | 1494 | case WM8326: |
1633 | ret = mfd_add_devices(wm831x->dev, -1, | 1495 | ret = mfd_add_devices(wm831x->dev, wm831x_num, |
1634 | wm8320_devs, ARRAY_SIZE(wm8320_devs), | 1496 | wm8320_devs, ARRAY_SIZE(wm8320_devs), |
1635 | NULL, wm831x->irq_base); | 1497 | NULL, wm831x->irq_base); |
1636 | break; | 1498 | break; |
@@ -1645,9 +1507,30 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1645 | goto err_irq; | 1507 | goto err_irq; |
1646 | } | 1508 | } |
1647 | 1509 | ||
1510 | /* The RTC can only be used if the 32.768kHz crystal is | ||
1511 | * enabled; this can't be controlled by software at runtime. | ||
1512 | */ | ||
1513 | ret = wm831x_reg_read(wm831x, WM831X_CLOCK_CONTROL_2); | ||
1514 | if (ret < 0) { | ||
1515 | dev_err(wm831x->dev, "Failed to read clock status: %d\n", ret); | ||
1516 | goto err_irq; | ||
1517 | } | ||
1518 | |||
1519 | if (ret & WM831X_XTAL_ENA) { | ||
1520 | ret = mfd_add_devices(wm831x->dev, wm831x_num, | ||
1521 | rtc_devs, ARRAY_SIZE(rtc_devs), | ||
1522 | NULL, wm831x->irq_base); | ||
1523 | if (ret != 0) { | ||
1524 | dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret); | ||
1525 | goto err_irq; | ||
1526 | } | ||
1527 | } else { | ||
1528 | dev_info(wm831x->dev, "32.768kHz clock disabled, no RTC\n"); | ||
1529 | } | ||
1530 | |||
1648 | if (pdata && pdata->backlight) { | 1531 | if (pdata && pdata->backlight) { |
1649 | /* Treat errors as non-critical */ | 1532 | /* Treat errors as non-critical */ |
1650 | ret = mfd_add_devices(wm831x->dev, -1, backlight_devs, | 1533 | ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs, |
1651 | ARRAY_SIZE(backlight_devs), NULL, | 1534 | ARRAY_SIZE(backlight_devs), NULL, |
1652 | wm831x->irq_base); | 1535 | wm831x->irq_base); |
1653 | if (ret < 0) | 1536 | if (ret < 0) |