diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c
index 891f498ea..f8e49ac27 100644
--- a/drivers/input/misc/wm831x-on.c
+++ b/drivers/input/misc/wm831x-on.c
@@ -25,6 +25,7 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/workqueue.h>
+#include <linux/devm-helpers.h>
#include <linux/mfd/wm831x/core.h>
struct wm831x_on {@@ -72,9 +73,12 @@ static int wm831x_on_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_on *wm831x_on;
- int irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
+ int irq = platform_get_irq(pdev, 0);
int ret;
+ if (irq < 0)
+ return irq;
+
wm831x_on = devm_kzalloc_obj(&pdev->dev, struct wm831x_on);
if (!wm831x_on) {
dev_err(&pdev->dev, "Can't allocate data\n");@@ -82,13 +86,11 @@ static int wm831x_on_probe(struct platform_device *pdev)
}
wm831x_on->wm831x = wm831x;
- INIT_DELAYED_WORK(&wm831x_on->work, wm831x_poll_on);
wm831x_on->dev = devm_input_allocate_device(&pdev->dev);
if (!wm831x_on->dev) {
dev_err(&pdev->dev, "Can't allocate input dev\n");
- ret = -ENOMEM;
- goto err;
+ return -ENOMEM;
}
wm831x_on->dev->evbit[0] = BIT_MASK(EV_KEY);@@ -96,43 +98,28 @@ static int wm831x_on_probe(struct platform_device *pdev)
wm831x_on->dev->name = "wm831x_on";
wm831x_on->dev->phys = "wm831x_on/input0";
- ret = request_threaded_irq(irq, NULL, wm831x_on_irq,
- IRQF_TRIGGER_RISING | IRQF_ONESHOT,
- "wm831x_on",
- wm831x_on);
- if (ret < 0) {
- dev_err(&pdev->dev, "Unable to request IRQ: %d\n", ret);
- goto err_input_dev;
- }
ret = input_register_device(wm831x_on->dev);
if (ret) {
dev_dbg(&pdev->dev, "Can't register input device: %d\n", ret);
- goto err_irq;
+ return ret;
}
- platform_set_drvdata(pdev, wm831x_on);
+ ret = devm_delayed_work_autocancel(&pdev->dev, &wm831x_on->work,
+ wm831x_poll_on);
+ if (ret)
+ return ret;
- return 0;
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, wm831x_on_irq,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ "wm831x_on", wm831x_on);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret, "Unable to request IRQ\n");
-err_irq:
- free_irq(irq, wm831x_on);
-err_input_dev:
-err:
- return ret;
-}
-
-static void wm831x_on_remove(struct platform_device *pdev)
-{
- struct wm831x_on *wm831x_on = platform_get_drvdata(pdev);
- int irq = platform_get_irq(pdev, 0);
-
- free_irq(irq, wm831x_on);
- cancel_delayed_work_sync(&wm831x_on->work);
+ return 0;
}
static struct platform_driver wm831x_on_driver = {
.probe = wm831x_on_probe,
- .remove = wm831x_on_remove,
.driver = {
.name = "wm831x-on",
},diff --git a/drivers/input/touchscreen/wm831x-ts.c
--- a/drivers/input/touchscreen/wm831x-ts.c
+++ b/drivers/input/touchscreen/wm831x-ts.c
@@ -255,14 +255,11 @@ static int wm831x_ts_probe(struct platform_device *pdev)
* If we have a direct IRQ use it, otherwise use the interrupt
* from the WM831x IRQ controller.
*/
- wm831x_ts->data_irq = wm831x_irq(wm831x,
- platform_get_irq_byname(pdev,
- "TCHDATA"));
+ wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA");
if (pdata && pdata->data_irq)
wm831x_ts->data_irq = pdata->data_irq;
- wm831x_ts->pd_irq = wm831x_irq(wm831x,
- platform_get_irq_byname(pdev, "TCHPD"));
+ wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD");
if (pdata && pdata->pd_irq)
wm831x_ts->pd_irq = pdata->pd_irq;
diff --git a/drivers/mfd/wm831x-auxadc.c b/drivers/mfd/wm831x-auxadc.c
index 6280d4f38..e3357918b 100644
--- a/drivers/mfd/wm831x-auxadc.c
+++ b/drivers/mfd/wm831x-auxadc.c
@@ -285,3 +285,10 @@ void wm831x_auxadc_init(struct wm831x *wm831x)
if (!wm831x->auxadc_read)
wm831x->auxadc_read = wm831x_auxadc_read_polled;
}
+
+void wm831x_auxadc_exit(struct wm831x *wm831x)
+{
+ if (wm831x->auxadc_read == wm831x_auxadc_read_irq)
+ free_irq(irq_find_mapping(wm831x->irq_domain,
+ WM831X_IRQ_AUXADC_DATA), wm831x);
+}diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c
index df8e76e00..008e19f33 100644
--- a/drivers/mfd/wm831x-core.c
+++ b/drivers/mfd/wm831x-core.c
@@ -662,14 +662,6 @@ static const struct resource
@@ -876,8 +868,6 @@ static const struct mfd_cell wm8310_devs[] = {
},
{
.name = "wm831x-gpio",
- .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
- .resources = wm831x_gpio_resources,
},
{
.name = "wm831x-hwmon",@@ -1030,8 +1020,6 @@ static const struct mfd_cell wm8311_devs[] = {
},
{
.name = "wm831x-gpio",
- .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
- .resources = wm831x_gpio_resources,
},
{
.name = "wm831x-hwmon",@@ -1160,8 +1148,6 @@ static const struct mfd_cell wm8312_devs[] = {
},
{
.name = "wm831x-gpio",
- .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
- .resources = wm831x_gpio_resources,
},
{
.name = "wm831x-hwmon",@@ -1306,8 +1292,6 @@ static const struct mfd_cell wm8320_devs[] = {
},
{
.name = "wm831x-gpio",
- .num_resources = ARRAY_SIZE(wm831x_gpio_resources),
- .resources = wm831x_gpio_resources,
},
{
.name = "wm831x-hwmon",@@ -1622,27 +1606,27 @@ int wm831x_device_init(struct wm831x *wm831x, int irq)
case WM8310:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8310_devs, ARRAY_SIZE(wm8310_devs),
- NULL, 0, NULL);
+ NULL, 0, wm831x->irq_domain);
break;
case WM8311:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8311_devs, ARRAY_SIZE(wm8311_devs),
- NULL, 0, NULL);
- if (!pdata->disable_touch)
- mfd_add_devices(wm831x->dev, wm831x_num,
- touch_devs, ARRAY_SIZE(touch_devs),
- NULL, 0, NULL);
+ NULL, 0, wm831x->irq_domain);
+ if (!ret && !pdata->disable_touch)
+ ret = mfd_add_devices(wm831x->dev, wm831x_num,
+ touch_devs, ARRAY_SIZE(touch_devs),
+ NULL, 0, wm831x->irq_domain);
break;
case WM8312:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8312_devs, ARRAY_SIZE(wm8312_devs),
- NULL, 0, NULL);
- if (!pdata->disable_touch)
- mfd_add_devices(wm831x->dev, wm831x_num,
- touch_devs, ARRAY_SIZE(touch_devs),
- NULL, 0, NULL);
+ NULL, 0, wm831x->irq_domain);
+ if (!ret && !pdata->disable_touch)
+ ret = mfd_add_devices(wm831x->dev, wm831x_num,
+ touch_devs, ARRAY_SIZE(touch_devs),
+ NULL, 0, wm831x->irq_domain);
break;
case WM8320:
@@ -1651,7 +1635,7 @@ int wm831x_device_init(struct wm831x *wm831x, int irq)
case WM8326:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8320_devs, ARRAY_SIZE(wm8320_devs),
- NULL, 0, NULL);
+ NULL, 0, wm831x->irq_domain);
break;
default:
@@ -1676,7 +1660,7 @@ int wm831x_device_init(struct wm831x *wm831x, int irq)
if (ret & WM831X_XTAL_ENA) {
ret = mfd_add_devices(wm831x->dev, wm831x_num,
rtc_devs, ARRAY_SIZE(rtc_devs),
- NULL, 0, NULL);
+ NULL, 0, wm831x->irq_domain);
if (ret != 0) {
dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret);
goto err_irq;@@ -1689,7 +1673,7 @@ int wm831x_device_init(struct wm831x *wm831x, int irq)
/* Treat errors as non-critical */
ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs,
ARRAY_SIZE(backlight_devs), NULL,
- 0, NULL);
+ 0, wm831x->irq_domain);
if (ret < 0)
dev_err(wm831x->dev, "Failed to add backlight: %d\n",
ret);
@@ -1708,7 +1692,10 @@ int wm831x_device_init(struct wm831x *wm831x, int irq)
return 0;
err_irq:
+ mfd_remove_devices(wm831x->dev);
+ wm831x_auxadc_exit(wm831x);
wm831x_irq_exit(wm831x);
+ return ret;
err:
mfd_remove_devices(wm831x->dev);
return ret;
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c
index defd5f173..200802612 100644
--- a/drivers/mfd/wm831x-irq.c
+++ b/drivers/mfd/wm831x-irq.c
@@ -595,6 +595,8 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
if (!domain) {
dev_warn(wm831x->dev, "Failed to allocate IRQ domain\n");
+ if (irq_base)
+ irq_free_descs(irq_base, WM831X_NUM_IRQS);
return -EINVAL;
}
@@ -606,10 +608,20 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
wm831x_set_bits(wm831x, WM831X_IRQ_CONFIG,
WM831X_IRQ_OD, i);
- wm831x->irq = irq;
wm831x->irq_domain = domain;
if (irq) {
+ ret = request_threaded_irq(irq, NULL, wm831x_irq_thread,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ "wm831x", wm831x);
+ if (ret != 0) {
+ dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n",
+ irq, ret);
+ wm831x_irq_exit(wm831x);
+ return ret;
+ }
+ wm831x->irq = irq;
+
/* Try to flag /IRQ as a wake source; there are a number of
* unconditional wake sources in the PMIC so this isn't
* conditional but we don't actually care *too* much if it@@ -620,15 +632,8 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
dev_warn(wm831x->dev,
"Can't enable IRQ as wake source: %d\n",
ret);
- }
-
- ret = request_threaded_irq(irq, NULL, wm831x_irq_thread,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- "wm831x", wm831x);
- if (ret != 0) {
- dev_err(wm831x->dev, "Failed to request IRQ %d: %d\n",
- irq, ret);
- return ret;
+ } else {
+ wm831x->irq_wake = true;
}
} else {
dev_warn(wm831x->dev,@@ -643,6 +648,15 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
void wm831x_irq_exit(struct wm831x *wm831x)
{
- if (wm831x->irq)
+ int i;
+
+ if (wm831x->irq) {
+ if (wm831x->irq_wake)
+ disable_irq_wake(wm831x->irq);
free_irq(wm831x->irq, wm831x);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++)
+ irq_dispose_mapping(irq_find_mapping(wm831x->irq_domain, i));
+ irq_domain_remove(wm831x->irq_domain);
}diff --git a/drivers/power/supply/wm831x_power.c
--- a/drivers/power/supply/wm831x_power.c
+++ b/drivers/power/supply/wm831x_power.c
@@ -616,7 +616,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
}
- irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
+ irq = platform_get_irq_byname(pdev, "SYSLO");
ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT, "System power low",
power);
@@ -626,7 +626,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
goto err_battery;
}
- irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC"));
+ irq = platform_get_irq_byname(pdev, "PWR SRC");
ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT, "Power source",
power);
@@ -637,9 +637,7 @@ static int wm831x_power_probe(struct platform_device *pdev)
}
for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
- irq = wm831x_irq(wm831x,
- platform_get_irq_byname(pdev,
- wm831x_bat_irqs[i]));
+ irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
ret = request_threaded_irq(irq, NULL, wm831x_bat_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
wm831x_bat_irqs[i],@@ -686,10 +684,10 @@ static int wm831x_power_probe(struct
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c
index 2036735f0..5ce7cbb36 100644
--- a/drivers/regulator/wm831x-dcdc.c
+++ b/drivers/regulator/wm831x-dcdc.c
@@ -470,7 +470,7 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
goto err;
}
- irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
+ irq = platform_get_irq_byname(pdev, "UV");
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
wm831x_dcdc_uv_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -481,7 +481,7 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
goto err;
}
- irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC"));
+ irq = platform_get_irq_byname(pdev, "HC");
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
wm831x_dcdc_oc_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -608,7 +608,7 @@ static int wm831x_buckp_probe(struct platform_device *pdev)
goto err;
}
- irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
+ irq = platform_get_irq_byname(pdev, "UV");
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
wm831x_dcdc_uv_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -726,7 +726,7 @@ static int wm831x_boostp_probe(struct platform_device *pdev)
return ret;
}
- irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
+ irq = platform_get_irq_byname(pdev, "UV");
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
wm831x_dcdc_uv_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c
index 5afd3094b..5c1cbaf66 100644
--- a/drivers/regulator/wm831x-isink.c
+++ b/drivers/regulator/wm831x-isink.c
@@ -160,7 +160,7 @@ static int wm831x_isink_probe(struct platform_device *pdev)
goto err;
}
- irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
+ irq = platform_get_irq(pdev, 0);
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
wm831x_isink_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c
index 34a6d6cf7..7c91edb3f 100644
--- a/drivers/regulator/wm831x-ldo.c
+++ b/drivers/regulator/wm831x-ldo.c
@@ -279,7 +279,7 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
goto err;
}
- irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
+ irq = platform_get_irq_byname(pdev, "UV");
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
wm831x_ldo_uv_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
@@ -490,7 +490,7 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
goto err;
}
- irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
+ irq = platform_get_irq_byname(pdev, "UV");
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
wm831x_ldo_uv_irq,
IRQF_TRIGGER_RISING | IRQF_ONESHOT,
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c
index 1943cb1eb..35b09747d 100644
--- a/drivers/rtc/rtc-wm831x.c
+++ b/drivers/rtc/rtc-wm831x.c
@@ -402,7 +402,7 @@ static int wm831x_rtc_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_rtc *wm831x_rtc;
- int alm_irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "ALM"));
+ int alm_irq = platform_get_irq_byname(pdev, "ALM");
int ret = 0;
wm831x_rtc = devm_kzalloc_obj(&pdev->dev, *wm831x_rtc);diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h
index 511bcad87..0e34a39b6 100644
--- a/include/linux/mfd/wm831x/core.h
+++ b/include/linux/mfd/wm831x/core.h
@@ -368,6 +368,7 @@ struct wm831x {
enum wm831x_parent type;
int irq; /* Our chip IRQ */
+ bool irq_wake;
struct mutex irq_lock;
struct irq_domain *irq_domain;
int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */@@ -418,6 +419,7 @@ void wm831x_device_shutdown(struct wm831x *wm831x);
int wm831x_irq_init(struct wm831x *wm831x, int irq);
void wm831x_irq_exit(struct wm831x *wm831x);
void wm831x_auxadc_init(struct wm831x *wm831x);
+void wm831x_auxadc_exit(struct wm831x *wm831x);
static inline int wm831x_irq(struct wm831x *wm831x, int irq)
{