diff options
-rw-r--r-- | drivers/gpio/gpio-wm831x.c | 6 | ||||
-rw-r--r-- | drivers/input/misc/wm831x-on.c | 2 | ||||
-rw-r--r-- | drivers/input/touchscreen/wm831x-ts.c | 9 | ||||
-rw-r--r-- | drivers/mfd/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mfd/wm831x-auxadc.c | 6 | ||||
-rw-r--r-- | drivers/mfd/wm831x-core.c | 19 | ||||
-rw-r--r-- | drivers/mfd/wm831x-irq.c | 101 | ||||
-rw-r--r-- | drivers/power/wm831x_power.c | 21 | ||||
-rw-r--r-- | drivers/regulator/wm831x-dcdc.c | 24 | ||||
-rw-r--r-- | drivers/regulator/wm831x-isink.c | 4 | ||||
-rw-r--r-- | drivers/regulator/wm831x-ldo.c | 10 | ||||
-rw-r--r-- | drivers/rtc/rtc-wm831x.c | 2 | ||||
-rw-r--r-- | include/linux/mfd/wm831x/core.h | 9 |
13 files changed, 131 insertions, 84 deletions
diff --git a/drivers/gpio/gpio-wm831x.c b/drivers/gpio/gpio-wm831x.c index deb949e75ec1..e56a2165641c 100644 --- a/drivers/gpio/gpio-wm831x.c +++ b/drivers/gpio/gpio-wm831x.c | |||
@@ -102,10 +102,8 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | |||
102 | struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); | 102 | struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip); |
103 | struct wm831x *wm831x = wm831x_gpio->wm831x; | 103 | struct wm831x *wm831x = wm831x_gpio->wm831x; |
104 | 104 | ||
105 | if (!wm831x->irq_base) | 105 | return irq_create_mapping(wm831x->irq_domain, |
106 | return -EINVAL; | 106 | WM831X_IRQ_GPIO_1 + offset); |
107 | |||
108 | return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset; | ||
109 | } | 107 | } |
110 | 108 | ||
111 | static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, | 109 | static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset, |
diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index 47f18d6bce46..6790a812a1db 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c | |||
@@ -73,7 +73,7 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) | |||
73 | { | 73 | { |
74 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | 74 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); |
75 | struct wm831x_on *wm831x_on; | 75 | struct wm831x_on *wm831x_on; |
76 | int irq = platform_get_irq(pdev, 0); | 76 | int irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0)); |
77 | int ret; | 77 | int ret; |
78 | 78 | ||
79 | wm831x_on = kzalloc(sizeof(struct wm831x_on), GFP_KERNEL); | 79 | wm831x_on = kzalloc(sizeof(struct wm831x_on), GFP_KERNEL); |
diff --git a/drivers/input/touchscreen/wm831x-ts.c b/drivers/input/touchscreen/wm831x-ts.c index 4bc851a9dc3d..e83410721e38 100644 --- a/drivers/input/touchscreen/wm831x-ts.c +++ b/drivers/input/touchscreen/wm831x-ts.c | |||
@@ -260,15 +260,16 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev) | |||
260 | * If we have a direct IRQ use it, otherwise use the interrupt | 260 | * If we have a direct IRQ use it, otherwise use the interrupt |
261 | * from the WM831x IRQ controller. | 261 | * from the WM831x IRQ controller. |
262 | */ | 262 | */ |
263 | wm831x_ts->data_irq = wm831x_irq(wm831x, | ||
264 | platform_get_irq_byname(pdev, | ||
265 | "TCHDATA")); | ||
263 | if (pdata && pdata->data_irq) | 266 | if (pdata && pdata->data_irq) |
264 | wm831x_ts->data_irq = pdata->data_irq; | 267 | wm831x_ts->data_irq = pdata->data_irq; |
265 | else | ||
266 | wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA"); | ||
267 | 268 | ||
269 | wm831x_ts->pd_irq = wm831x_irq(wm831x, | ||
270 | platform_get_irq_byname(pdev, "TCHPD")); | ||
268 | if (pdata && pdata->pd_irq) | 271 | if (pdata && pdata->pd_irq) |
269 | wm831x_ts->pd_irq = pdata->pd_irq; | 272 | wm831x_ts->pd_irq = pdata->pd_irq; |
270 | else | ||
271 | wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD"); | ||
272 | 273 | ||
273 | if (pdata) | 274 | if (pdata) |
274 | wm831x_ts->pressure = pdata->pressure; | 275 | wm831x_ts->pressure = pdata->pressure; |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index a0e1b834af61..8325c44c04c6 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -496,6 +496,7 @@ config MFD_WM831X_I2C | |||
496 | select MFD_CORE | 496 | select MFD_CORE |
497 | select MFD_WM831X | 497 | select MFD_WM831X |
498 | select REGMAP_I2C | 498 | select REGMAP_I2C |
499 | select IRQ_DOMAIN | ||
499 | depends on I2C=y && GENERIC_HARDIRQS | 500 | depends on I2C=y && GENERIC_HARDIRQS |
500 | help | 501 | help |
501 | Support for the Wolfson Microelecronics WM831x and WM832x PMICs | 502 | Support for the Wolfson Microelecronics WM831x and WM832x PMICs |
@@ -508,6 +509,7 @@ config MFD_WM831X_SPI | |||
508 | select MFD_CORE | 509 | select MFD_CORE |
509 | select MFD_WM831X | 510 | select MFD_WM831X |
510 | select REGMAP_SPI | 511 | select REGMAP_SPI |
512 | select IRQ_DOMAIN | ||
511 | depends on SPI_MASTER && GENERIC_HARDIRQS | 513 | depends on SPI_MASTER && GENERIC_HARDIRQS |
512 | help | 514 | help |
513 | Support for the Wolfson Microelecronics WM831x and WM832x PMICs | 515 | Support for the Wolfson Microelecronics WM831x and WM832x PMICs |
diff --git a/drivers/mfd/wm831x-auxadc.c b/drivers/mfd/wm831x-auxadc.c index 87210954a066..6ee3018d8653 100644 --- a/drivers/mfd/wm831x-auxadc.c +++ b/drivers/mfd/wm831x-auxadc.c | |||
@@ -280,11 +280,11 @@ void wm831x_auxadc_init(struct wm831x *wm831x) | |||
280 | mutex_init(&wm831x->auxadc_lock); | 280 | mutex_init(&wm831x->auxadc_lock); |
281 | INIT_LIST_HEAD(&wm831x->auxadc_pending); | 281 | INIT_LIST_HEAD(&wm831x->auxadc_pending); |
282 | 282 | ||
283 | if (wm831x->irq && wm831x->irq_base) { | 283 | if (wm831x->irq) { |
284 | wm831x->auxadc_read = wm831x_auxadc_read_irq; | 284 | wm831x->auxadc_read = wm831x_auxadc_read_irq; |
285 | 285 | ||
286 | ret = request_threaded_irq(wm831x->irq_base + | 286 | ret = request_threaded_irq(wm831x_irq(wm831x, |
287 | WM831X_IRQ_AUXADC_DATA, | 287 | WM831X_IRQ_AUXADC_DATA), |
288 | NULL, wm831x_auxadc_irq, 0, | 288 | NULL, wm831x_auxadc_irq, 0, |
289 | "auxadc", wm831x); | 289 | "auxadc", wm831x); |
290 | if (ret < 0) { | 290 | if (ret < 0) { |
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index 476e4d31a823..946698fd2dc6 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -1813,27 +1813,27 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1813 | case WM8310: | 1813 | case WM8310: |
1814 | ret = mfd_add_devices(wm831x->dev, wm831x_num, | 1814 | ret = mfd_add_devices(wm831x->dev, wm831x_num, |
1815 | wm8310_devs, ARRAY_SIZE(wm8310_devs), | 1815 | wm8310_devs, ARRAY_SIZE(wm8310_devs), |
1816 | NULL, wm831x->irq_base); | 1816 | NULL, 0); |
1817 | break; | 1817 | break; |
1818 | 1818 | ||
1819 | case WM8311: | 1819 | case WM8311: |
1820 | ret = mfd_add_devices(wm831x->dev, wm831x_num, | 1820 | ret = mfd_add_devices(wm831x->dev, wm831x_num, |
1821 | wm8311_devs, ARRAY_SIZE(wm8311_devs), | 1821 | wm8311_devs, ARRAY_SIZE(wm8311_devs), |
1822 | NULL, wm831x->irq_base); | 1822 | NULL, 0); |
1823 | if (!pdata || !pdata->disable_touch) | 1823 | if (!pdata || !pdata->disable_touch) |
1824 | mfd_add_devices(wm831x->dev, wm831x_num, | 1824 | mfd_add_devices(wm831x->dev, wm831x_num, |
1825 | touch_devs, ARRAY_SIZE(touch_devs), | 1825 | touch_devs, ARRAY_SIZE(touch_devs), |
1826 | NULL, wm831x->irq_base); | 1826 | NULL, 0); |
1827 | break; | 1827 | break; |
1828 | 1828 | ||
1829 | case WM8312: | 1829 | case WM8312: |
1830 | ret = mfd_add_devices(wm831x->dev, wm831x_num, | 1830 | ret = mfd_add_devices(wm831x->dev, wm831x_num, |
1831 | wm8312_devs, ARRAY_SIZE(wm8312_devs), | 1831 | wm8312_devs, ARRAY_SIZE(wm8312_devs), |
1832 | NULL, wm831x->irq_base); | 1832 | NULL, 0); |
1833 | if (!pdata || !pdata->disable_touch) | 1833 | if (!pdata || !pdata->disable_touch) |
1834 | mfd_add_devices(wm831x->dev, wm831x_num, | 1834 | mfd_add_devices(wm831x->dev, wm831x_num, |
1835 | touch_devs, ARRAY_SIZE(touch_devs), | 1835 | touch_devs, ARRAY_SIZE(touch_devs), |
1836 | NULL, wm831x->irq_base); | 1836 | NULL, 0); |
1837 | break; | 1837 | break; |
1838 | 1838 | ||
1839 | case WM8320: | 1839 | case WM8320: |
@@ -1842,7 +1842,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1842 | case WM8326: | 1842 | case WM8326: |
1843 | ret = mfd_add_devices(wm831x->dev, wm831x_num, | 1843 | ret = mfd_add_devices(wm831x->dev, wm831x_num, |
1844 | wm8320_devs, ARRAY_SIZE(wm8320_devs), | 1844 | wm8320_devs, ARRAY_SIZE(wm8320_devs), |
1845 | NULL, wm831x->irq_base); | 1845 | NULL, 0); |
1846 | break; | 1846 | break; |
1847 | 1847 | ||
1848 | default: | 1848 | default: |
@@ -1867,7 +1867,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1867 | if (ret & WM831X_XTAL_ENA) { | 1867 | if (ret & WM831X_XTAL_ENA) { |
1868 | ret = mfd_add_devices(wm831x->dev, wm831x_num, | 1868 | ret = mfd_add_devices(wm831x->dev, wm831x_num, |
1869 | rtc_devs, ARRAY_SIZE(rtc_devs), | 1869 | rtc_devs, ARRAY_SIZE(rtc_devs), |
1870 | NULL, wm831x->irq_base); | 1870 | NULL, 0); |
1871 | if (ret != 0) { | 1871 | if (ret != 0) { |
1872 | dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret); | 1872 | dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret); |
1873 | goto err_irq; | 1873 | goto err_irq; |
@@ -1880,7 +1880,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1880 | /* Treat errors as non-critical */ | 1880 | /* Treat errors as non-critical */ |
1881 | ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs, | 1881 | ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs, |
1882 | ARRAY_SIZE(backlight_devs), NULL, | 1882 | ARRAY_SIZE(backlight_devs), NULL, |
1883 | wm831x->irq_base); | 1883 | 0); |
1884 | if (ret < 0) | 1884 | if (ret < 0) |
1885 | dev_err(wm831x->dev, "Failed to add backlight: %d\n", | 1885 | dev_err(wm831x->dev, "Failed to add backlight: %d\n", |
1886 | ret); | 1886 | ret); |
@@ -1909,8 +1909,7 @@ void wm831x_device_exit(struct wm831x *wm831x) | |||
1909 | { | 1909 | { |
1910 | wm831x_otp_exit(wm831x); | 1910 | wm831x_otp_exit(wm831x); |
1911 | mfd_remove_devices(wm831x->dev); | 1911 | mfd_remove_devices(wm831x->dev); |
1912 | if (wm831x->irq_base) | 1912 | free_irq(wm831x_irq(wm831x, WM831X_IRQ_AUXADC_DATA), wm831x); |
1913 | free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x); | ||
1914 | wm831x_irq_exit(wm831x); | 1913 | wm831x_irq_exit(wm831x); |
1915 | } | 1914 | } |
1916 | 1915 | ||
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index 2be9628074bd..ecc9d6d62fad 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/mfd/core.h> | 19 | #include <linux/mfd/core.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/irqdomain.h> | ||
21 | 22 | ||
22 | #include <linux/mfd/wm831x/core.h> | 23 | #include <linux/mfd/wm831x/core.h> |
23 | #include <linux/mfd/wm831x/pdata.h> | 24 | #include <linux/mfd/wm831x/pdata.h> |
@@ -328,7 +329,7 @@ static inline int irq_data_to_status_reg(struct wm831x_irq_data *irq_data) | |||
328 | static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x, | 329 | static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x, |
329 | int irq) | 330 | int irq) |
330 | { | 331 | { |
331 | return &wm831x_irqs[irq - wm831x->irq_base]; | 332 | return &wm831x_irqs[irq]; |
332 | } | 333 | } |
333 | 334 | ||
334 | static void wm831x_irq_lock(struct irq_data *data) | 335 | static void wm831x_irq_lock(struct irq_data *data) |
@@ -374,7 +375,7 @@ static void wm831x_irq_enable(struct irq_data *data) | |||
374 | { | 375 | { |
375 | struct wm831x *wm831x = irq_data_get_irq_chip_data(data); | 376 | struct wm831x *wm831x = irq_data_get_irq_chip_data(data); |
376 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, | 377 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, |
377 | data->irq); | 378 | data->hwirq); |
378 | 379 | ||
379 | wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; | 380 | wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask; |
380 | } | 381 | } |
@@ -383,7 +384,7 @@ static void wm831x_irq_disable(struct irq_data *data) | |||
383 | { | 384 | { |
384 | struct wm831x *wm831x = irq_data_get_irq_chip_data(data); | 385 | struct wm831x *wm831x = irq_data_get_irq_chip_data(data); |
385 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, | 386 | struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x, |
386 | data->irq); | 387 | data->hwirq); |
387 | 388 | ||
388 | wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; | 389 | wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask; |
389 | } | 390 | } |
@@ -393,7 +394,7 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type) | |||
393 | struct wm831x *wm831x = irq_data_get_irq_chip_data(data); | 394 | struct wm831x *wm831x = irq_data_get_irq_chip_data(data); |
394 | int irq; | 395 | int irq; |
395 | 396 | ||
396 | irq = data->irq - wm831x->irq_base; | 397 | irq = data->hwirq; |
397 | 398 | ||
398 | if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) { | 399 | if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) { |
399 | /* Ignore internal-only IRQs */ | 400 | /* Ignore internal-only IRQs */ |
@@ -469,9 +470,11 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) | |||
469 | * descriptors. | 470 | * descriptors. |
470 | */ | 471 | */ |
471 | if (primary & WM831X_TCHPD_INT) | 472 | if (primary & WM831X_TCHPD_INT) |
472 | handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHPD); | 473 | handle_nested_irq(irq_find_mapping(wm831x->irq_domain, |
474 | WM831X_IRQ_TCHPD)); | ||
473 | if (primary & WM831X_TCHDATA_INT) | 475 | if (primary & WM831X_TCHDATA_INT) |
474 | handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHDATA); | 476 | handle_nested_irq(irq_find_mapping(wm831x->irq_domain, |
477 | WM831X_IRQ_TCHDATA)); | ||
475 | primary &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT); | 478 | primary &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT); |
476 | 479 | ||
477 | for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) { | 480 | for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) { |
@@ -507,7 +510,8 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) | |||
507 | } | 510 | } |
508 | 511 | ||
509 | if (*status & wm831x_irqs[i].mask) | 512 | if (*status & wm831x_irqs[i].mask) |
510 | handle_nested_irq(wm831x->irq_base + i); | 513 | handle_nested_irq(irq_find_mapping(wm831x->irq_domain, |
514 | i)); | ||
511 | 515 | ||
512 | /* Simulate an edge triggered IRQ by polling the input | 516 | /* Simulate an edge triggered IRQ by polling the input |
513 | * status. This is sucky but improves interoperability. | 517 | * status. This is sucky but improves interoperability. |
@@ -516,7 +520,8 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data) | |||
516 | wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) { | 520 | wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) { |
517 | ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL); | 521 | ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL); |
518 | while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) { | 522 | while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) { |
519 | handle_nested_irq(wm831x->irq_base + i); | 523 | handle_nested_irq(irq_find_mapping(wm831x->irq_domain, |
524 | i)); | ||
520 | ret = wm831x_reg_read(wm831x, | 525 | ret = wm831x_reg_read(wm831x, |
521 | WM831X_GPIO_LEVEL); | 526 | WM831X_GPIO_LEVEL); |
522 | } | 527 | } |
@@ -527,10 +532,34 @@ out: | |||
527 | return IRQ_HANDLED; | 532 | return IRQ_HANDLED; |
528 | } | 533 | } |
529 | 534 | ||
535 | static int wm831x_irq_map(struct irq_domain *h, unsigned int virq, | ||
536 | irq_hw_number_t hw) | ||
537 | { | ||
538 | irq_set_chip_data(virq, h->host_data); | ||
539 | irq_set_chip_and_handler(virq, &wm831x_irq_chip, handle_edge_irq); | ||
540 | irq_set_nested_thread(virq, 1); | ||
541 | |||
542 | /* ARM needs us to explicitly flag the IRQ as valid | ||
543 | * and will set them noprobe when we do so. */ | ||
544 | #ifdef CONFIG_ARM | ||
545 | set_irq_flags(virq, IRQF_VALID); | ||
546 | #else | ||
547 | irq_set_noprobe(virq); | ||
548 | #endif | ||
549 | |||
550 | return 0; | ||
551 | } | ||
552 | |||
553 | static struct irq_domain_ops wm831x_irq_domain_ops = { | ||
554 | .map = wm831x_irq_map, | ||
555 | .xlate = irq_domain_xlate_twocell, | ||
556 | }; | ||
557 | |||
530 | int wm831x_irq_init(struct wm831x *wm831x, int irq) | 558 | int wm831x_irq_init(struct wm831x *wm831x, int irq) |
531 | { | 559 | { |
532 | struct wm831x_pdata *pdata = wm831x->dev->platform_data; | 560 | struct wm831x_pdata *pdata = wm831x->dev->platform_data; |
533 | int i, cur_irq, ret; | 561 | struct irq_domain *domain; |
562 | int i, ret, irq_base; | ||
534 | 563 | ||
535 | mutex_init(&wm831x->irq_lock); | 564 | mutex_init(&wm831x->irq_lock); |
536 | 565 | ||
@@ -543,18 +572,33 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
543 | } | 572 | } |
544 | 573 | ||
545 | /* Try to dynamically allocate IRQs if no base is specified */ | 574 | /* Try to dynamically allocate IRQs if no base is specified */ |
546 | if (!pdata || !pdata->irq_base) | 575 | if (pdata && pdata->irq_base) { |
547 | wm831x->irq_base = -1; | 576 | irq_base = irq_alloc_descs(pdata->irq_base, 0, |
577 | WM831X_NUM_IRQS, 0); | ||
578 | if (irq_base < 0) { | ||
579 | dev_warn(wm831x->dev, "Failed to allocate IRQs: %d\n", | ||
580 | irq_base); | ||
581 | irq_base = 0; | ||
582 | } | ||
583 | } else { | ||
584 | irq_base = 0; | ||
585 | } | ||
586 | |||
587 | if (irq_base) | ||
588 | domain = irq_domain_add_legacy(wm831x->dev->of_node, | ||
589 | ARRAY_SIZE(wm831x_irqs), | ||
590 | irq_base, 0, | ||
591 | &wm831x_irq_domain_ops, | ||
592 | wm831x); | ||
548 | else | 593 | else |
549 | wm831x->irq_base = pdata->irq_base; | 594 | domain = irq_domain_add_linear(wm831x->dev->of_node, |
595 | ARRAY_SIZE(wm831x_irqs), | ||
596 | &wm831x_irq_domain_ops, | ||
597 | wm831x); | ||
550 | 598 | ||
551 | wm831x->irq_base = irq_alloc_descs(wm831x->irq_base, 0, | 599 | if (!domain) { |
552 | WM831X_NUM_IRQS, 0); | 600 | dev_warn(wm831x->dev, "Failed to allocate IRQ domain\n"); |
553 | if (wm831x->irq_base < 0) { | 601 | return -EINVAL; |
554 | dev_warn(wm831x->dev, "Failed to allocate IRQs: %d\n", | ||
555 | wm831x->irq_base); | ||
556 | wm831x->irq_base = 0; | ||
557 | return 0; | ||
558 | } | 602 | } |
559 | 603 | ||
560 | if (pdata && pdata->irq_cmos) | 604 | if (pdata && pdata->irq_cmos) |
@@ -566,24 +610,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
566 | WM831X_IRQ_OD, i); | 610 | WM831X_IRQ_OD, i); |
567 | 611 | ||
568 | wm831x->irq = irq; | 612 | wm831x->irq = irq; |
569 | 613 | wm831x->irq_domain = domain; | |
570 | /* Register them with genirq */ | ||
571 | for (cur_irq = wm831x->irq_base; | ||
572 | cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base; | ||
573 | cur_irq++) { | ||
574 | irq_set_chip_data(cur_irq, wm831x); | ||
575 | irq_set_chip_and_handler(cur_irq, &wm831x_irq_chip, | ||
576 | handle_edge_irq); | ||
577 | irq_set_nested_thread(cur_irq, 1); | ||
578 | |||
579 | /* ARM needs us to explicitly flag the IRQ as valid | ||
580 | * and will set them noprobe when we do so. */ | ||
581 | #ifdef CONFIG_ARM | ||
582 | set_irq_flags(cur_irq, IRQF_VALID); | ||
583 | #else | ||
584 | irq_set_noprobe(cur_irq); | ||
585 | #endif | ||
586 | } | ||
587 | 614 | ||
588 | if (irq) { | 615 | if (irq) { |
589 | /* Try to flag /IRQ as a wake source; there are a number of | 616 | /* Try to flag /IRQ as a wake source; there are a number of |
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c index 987332b71d8d..fc1ad9551182 100644 --- a/drivers/power/wm831x_power.c +++ b/drivers/power/wm831x_power.c | |||
@@ -565,7 +565,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
565 | goto err_usb; | 565 | goto err_usb; |
566 | } | 566 | } |
567 | 567 | ||
568 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 568 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); |
569 | ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, | 569 | ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq, |
570 | IRQF_TRIGGER_RISING, "System power low", | 570 | IRQF_TRIGGER_RISING, "System power low", |
571 | power); | 571 | power); |
@@ -575,7 +575,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
575 | goto err_battery; | 575 | goto err_battery; |
576 | } | 576 | } |
577 | 577 | ||
578 | irq = platform_get_irq_byname(pdev, "PWR SRC"); | 578 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); |
579 | ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq, | 579 | ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq, |
580 | IRQF_TRIGGER_RISING, "Power source", | 580 | IRQF_TRIGGER_RISING, "Power source", |
581 | power); | 581 | power); |
@@ -586,7 +586,9 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev) | |||
586 | } | 586 | } |
587 | 587 | ||
588 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { | 588 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { |
589 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); | 589 | irq = wm831x_irq(wm831x, |
590 | platform_get_irq_byname(pdev, | ||
591 | wm831x_bat_irqs[i])); | ||
590 | ret = request_threaded_irq(irq, NULL, wm831x_bat_irq, | 592 | ret = request_threaded_irq(irq, NULL, wm831x_bat_irq, |
591 | IRQF_TRIGGER_RISING, | 593 | IRQF_TRIGGER_RISING, |
592 | wm831x_bat_irqs[i], | 594 | wm831x_bat_irqs[i], |
@@ -606,10 +608,10 @@ err_bat_irq: | |||
606 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); | 608 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); |
607 | free_irq(irq, power); | 609 | free_irq(irq, power); |
608 | } | 610 | } |
609 | irq = platform_get_irq_byname(pdev, "PWR SRC"); | 611 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); |
610 | free_irq(irq, power); | 612 | free_irq(irq, power); |
611 | err_syslo: | 613 | err_syslo: |
612 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 614 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); |
613 | free_irq(irq, power); | 615 | free_irq(irq, power); |
614 | err_battery: | 616 | err_battery: |
615 | if (power->have_battery) | 617 | if (power->have_battery) |
@@ -626,17 +628,20 @@ err_kmalloc: | |||
626 | static __devexit int wm831x_power_remove(struct platform_device *pdev) | 628 | static __devexit int wm831x_power_remove(struct platform_device *pdev) |
627 | { | 629 | { |
628 | struct wm831x_power *wm831x_power = platform_get_drvdata(pdev); | 630 | struct wm831x_power *wm831x_power = platform_get_drvdata(pdev); |
631 | struct wm831x *wm831x = wm831x_power->wm831x; | ||
629 | int irq, i; | 632 | int irq, i; |
630 | 633 | ||
631 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { | 634 | for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) { |
632 | irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]); | 635 | irq = wm831x_irq(wm831x, |
636 | platform_get_irq_byname(pdev, | ||
637 | wm831x_bat_irqs[i])); | ||
633 | free_irq(irq, wm831x_power); | 638 | free_irq(irq, wm831x_power); |
634 | } | 639 | } |
635 | 640 | ||
636 | irq = platform_get_irq_byname(pdev, "PWR SRC"); | 641 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC")); |
637 | free_irq(irq, wm831x_power); | 642 | free_irq(irq, wm831x_power); |
638 | 643 | ||
639 | irq = platform_get_irq_byname(pdev, "SYSLO"); | 644 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO")); |
640 | free_irq(irq, wm831x_power); | 645 | free_irq(irq, wm831x_power); |
641 | 646 | ||
642 | if (wm831x_power->have_battery) | 647 | if (wm831x_power->have_battery) |
diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index ff810e787eac..33b2f20a2932 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c | |||
@@ -565,7 +565,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) | |||
565 | goto err; | 565 | goto err; |
566 | } | 566 | } |
567 | 567 | ||
568 | irq = platform_get_irq_byname(pdev, "UV"); | 568 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); |
569 | ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, | 569 | ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, |
570 | IRQF_TRIGGER_RISING, dcdc->name, dcdc); | 570 | IRQF_TRIGGER_RISING, dcdc->name, dcdc); |
571 | if (ret != 0) { | 571 | if (ret != 0) { |
@@ -574,7 +574,7 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) | |||
574 | goto err_regulator; | 574 | goto err_regulator; |
575 | } | 575 | } |
576 | 576 | ||
577 | irq = platform_get_irq_byname(pdev, "HC"); | 577 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC")); |
578 | ret = request_threaded_irq(irq, NULL, wm831x_dcdc_oc_irq, | 578 | ret = request_threaded_irq(irq, NULL, wm831x_dcdc_oc_irq, |
579 | IRQF_TRIGGER_RISING, dcdc->name, dcdc); | 579 | IRQF_TRIGGER_RISING, dcdc->name, dcdc); |
580 | if (ret != 0) { | 580 | if (ret != 0) { |
@@ -588,7 +588,8 @@ static __devinit int wm831x_buckv_probe(struct platform_device *pdev) | |||
588 | return 0; | 588 | return 0; |
589 | 589 | ||
590 | err_uv: | 590 | err_uv: |
591 | free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); | 591 | free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")), |
592 | dcdc); | ||
592 | err_regulator: | 593 | err_regulator: |
593 | regulator_unregister(dcdc->regulator); | 594 | regulator_unregister(dcdc->regulator); |
594 | err: | 595 | err: |
@@ -600,11 +601,14 @@ err: | |||
600 | static __devexit int wm831x_buckv_remove(struct platform_device *pdev) | 601 | static __devexit int wm831x_buckv_remove(struct platform_device *pdev) |
601 | { | 602 | { |
602 | struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); | 603 | struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev); |
604 | struct wm831x *wm831x = dcdc->wm831x; | ||
603 | 605 | ||
604 | platform_set_drvdata(pdev, NULL); | 606 | platform_set_drvdata(pdev, NULL); |
605 | 607 | ||
606 | free_irq(platform_get_irq_byname(pdev, "HC"), dcdc); | 608 | free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC")), |
607 | free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); | 609 | dcdc); |
610 | free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")), | ||
611 | dcdc); | ||
608 | regulator_unregister(dcdc->regulator); | 612 | regulator_unregister(dcdc->regulator); |
609 | if (dcdc->dvs_gpio) | 613 | if (dcdc->dvs_gpio) |
610 | gpio_free(dcdc->dvs_gpio); | 614 | gpio_free(dcdc->dvs_gpio); |
@@ -758,7 +762,7 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev) | |||
758 | goto err; | 762 | goto err; |
759 | } | 763 | } |
760 | 764 | ||
761 | irq = platform_get_irq_byname(pdev, "UV"); | 765 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); |
762 | ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, | 766 | ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, |
763 | IRQF_TRIGGER_RISING, dcdc->name, dcdc); | 767 | IRQF_TRIGGER_RISING, dcdc->name, dcdc); |
764 | if (ret != 0) { | 768 | if (ret != 0) { |
@@ -783,7 +787,8 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev) | |||
783 | 787 | ||
784 | platform_set_drvdata(pdev, NULL); | 788 | platform_set_drvdata(pdev, NULL); |
785 | 789 | ||
786 | free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); | 790 | free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")), |
791 | dcdc); | ||
787 | regulator_unregister(dcdc->regulator); | 792 | regulator_unregister(dcdc->regulator); |
788 | 793 | ||
789 | return 0; | 794 | return 0; |
@@ -883,7 +888,7 @@ static __devinit int wm831x_boostp_probe(struct platform_device *pdev) | |||
883 | goto err; | 888 | goto err; |
884 | } | 889 | } |
885 | 890 | ||
886 | irq = platform_get_irq_byname(pdev, "UV"); | 891 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); |
887 | ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, | 892 | ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq, |
888 | IRQF_TRIGGER_RISING, dcdc->name, | 893 | IRQF_TRIGGER_RISING, dcdc->name, |
889 | dcdc); | 894 | dcdc); |
@@ -910,7 +915,8 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev) | |||
910 | 915 | ||
911 | platform_set_drvdata(pdev, NULL); | 916 | platform_set_drvdata(pdev, NULL); |
912 | 917 | ||
913 | free_irq(platform_get_irq_byname(pdev, "UV"), dcdc); | 918 | free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")), |
919 | dcdc); | ||
914 | regulator_unregister(dcdc->regulator); | 920 | regulator_unregister(dcdc->regulator); |
915 | kfree(dcdc); | 921 | kfree(dcdc); |
916 | 922 | ||
diff --git a/drivers/regulator/wm831x-isink.c b/drivers/regulator/wm831x-isink.c index b414e09c5620..1596947f603f 100644 --- a/drivers/regulator/wm831x-isink.c +++ b/drivers/regulator/wm831x-isink.c | |||
@@ -198,7 +198,7 @@ static __devinit int wm831x_isink_probe(struct platform_device *pdev) | |||
198 | goto err; | 198 | goto err; |
199 | } | 199 | } |
200 | 200 | ||
201 | irq = platform_get_irq(pdev, 0); | 201 | irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0)); |
202 | ret = request_threaded_irq(irq, NULL, wm831x_isink_irq, | 202 | ret = request_threaded_irq(irq, NULL, wm831x_isink_irq, |
203 | IRQF_TRIGGER_RISING, isink->name, isink); | 203 | IRQF_TRIGGER_RISING, isink->name, isink); |
204 | if (ret != 0) { | 204 | if (ret != 0) { |
@@ -223,7 +223,7 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev) | |||
223 | 223 | ||
224 | platform_set_drvdata(pdev, NULL); | 224 | platform_set_drvdata(pdev, NULL); |
225 | 225 | ||
226 | free_irq(platform_get_irq(pdev, 0), isink); | 226 | free_irq(wm831x_irq(isink->wm831x, platform_get_irq(pdev, 0)), isink); |
227 | 227 | ||
228 | regulator_unregister(isink->regulator); | 228 | regulator_unregister(isink->regulator); |
229 | 229 | ||
diff --git a/drivers/regulator/wm831x-ldo.c b/drivers/regulator/wm831x-ldo.c index 641e9f6499d1..b09ba05ada6d 100644 --- a/drivers/regulator/wm831x-ldo.c +++ b/drivers/regulator/wm831x-ldo.c | |||
@@ -359,7 +359,7 @@ static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev) | |||
359 | goto err; | 359 | goto err; |
360 | } | 360 | } |
361 | 361 | ||
362 | irq = platform_get_irq_byname(pdev, "UV"); | 362 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); |
363 | ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq, | 363 | ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq, |
364 | IRQF_TRIGGER_RISING, ldo->name, | 364 | IRQF_TRIGGER_RISING, ldo->name, |
365 | ldo); | 365 | ldo); |
@@ -385,7 +385,8 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev) | |||
385 | 385 | ||
386 | platform_set_drvdata(pdev, NULL); | 386 | platform_set_drvdata(pdev, NULL); |
387 | 387 | ||
388 | free_irq(platform_get_irq_byname(pdev, "UV"), ldo); | 388 | free_irq(wm831x_irq(ldo->wm831x, |
389 | platform_get_irq_byname(pdev, "UV")), ldo); | ||
389 | regulator_unregister(ldo->regulator); | 390 | regulator_unregister(ldo->regulator); |
390 | 391 | ||
391 | return 0; | 392 | return 0; |
@@ -624,7 +625,7 @@ static __devinit int wm831x_aldo_probe(struct platform_device *pdev) | |||
624 | goto err; | 625 | goto err; |
625 | } | 626 | } |
626 | 627 | ||
627 | irq = platform_get_irq_byname(pdev, "UV"); | 628 | irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")); |
628 | ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq, | 629 | ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq, |
629 | IRQF_TRIGGER_RISING, ldo->name, ldo); | 630 | IRQF_TRIGGER_RISING, ldo->name, ldo); |
630 | if (ret != 0) { | 631 | if (ret != 0) { |
@@ -647,7 +648,8 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev) | |||
647 | { | 648 | { |
648 | struct wm831x_ldo *ldo = platform_get_drvdata(pdev); | 649 | struct wm831x_ldo *ldo = platform_get_drvdata(pdev); |
649 | 650 | ||
650 | free_irq(platform_get_irq_byname(pdev, "UV"), ldo); | 651 | free_irq(wm831x_irq(ldo->wm831x, platform_get_irq_byname(pdev, "UV")), |
652 | ldo); | ||
651 | regulator_unregister(ldo->regulator); | 653 | regulator_unregister(ldo->regulator); |
652 | 654 | ||
653 | return 0; | 655 | return 0; |
diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 3b6e6a67e765..59c6245e0421 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c | |||
@@ -396,7 +396,7 @@ static int wm831x_rtc_probe(struct platform_device *pdev) | |||
396 | { | 396 | { |
397 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); | 397 | struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); |
398 | struct wm831x_rtc *wm831x_rtc; | 398 | struct wm831x_rtc *wm831x_rtc; |
399 | int alm_irq = platform_get_irq_byname(pdev, "ALM"); | 399 | int alm_irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "ALM")); |
400 | int ret = 0; | 400 | int ret = 0; |
401 | 401 | ||
402 | wm831x_rtc = devm_kzalloc(&pdev->dev, sizeof(*wm831x_rtc), GFP_KERNEL); | 402 | wm831x_rtc = devm_kzalloc(&pdev->dev, sizeof(*wm831x_rtc), GFP_KERNEL); |
diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h index 4b1211859f74..736191cc7e00 100644 --- a/include/linux/mfd/wm831x/core.h +++ b/include/linux/mfd/wm831x/core.h | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/completion.h> | 18 | #include <linux/completion.h> |
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/irqdomain.h> | ||
20 | #include <linux/list.h> | 21 | #include <linux/list.h> |
21 | #include <linux/regmap.h> | 22 | #include <linux/regmap.h> |
22 | 23 | ||
@@ -338,6 +339,7 @@ | |||
338 | #define WM831X_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */ | 339 | #define WM831X_FLL_CLK_SRC_WIDTH 2 /* FLL_CLK_SRC - [1:0] */ |
339 | 340 | ||
340 | struct regulator_dev; | 341 | struct regulator_dev; |
342 | struct irq_domain; | ||
341 | 343 | ||
342 | #define WM831X_NUM_IRQ_REGS 5 | 344 | #define WM831X_NUM_IRQ_REGS 5 |
343 | #define WM831X_NUM_GPIO_REGS 16 | 345 | #define WM831X_NUM_GPIO_REGS 16 |
@@ -367,7 +369,7 @@ struct wm831x { | |||
367 | 369 | ||
368 | int irq; /* Our chip IRQ */ | 370 | int irq; /* Our chip IRQ */ |
369 | struct mutex irq_lock; | 371 | struct mutex irq_lock; |
370 | int irq_base; | 372 | struct irq_domain *irq_domain; |
371 | int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */ | 373 | int irq_masks_cur[WM831X_NUM_IRQ_REGS]; /* Currently active value */ |
372 | int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */ | 374 | int irq_masks_cache[WM831X_NUM_IRQ_REGS]; /* Cached hardware value */ |
373 | 375 | ||
@@ -417,6 +419,11 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq); | |||
417 | void wm831x_irq_exit(struct wm831x *wm831x); | 419 | void wm831x_irq_exit(struct wm831x *wm831x); |
418 | void wm831x_auxadc_init(struct wm831x *wm831x); | 420 | void wm831x_auxadc_init(struct wm831x *wm831x); |
419 | 421 | ||
422 | static inline int wm831x_irq(struct wm831x *wm831x, int irq) | ||
423 | { | ||
424 | return irq_create_mapping(wm831x->irq_domain, irq); | ||
425 | } | ||
426 | |||
420 | extern struct regmap_config wm831x_regmap_config; | 427 | extern struct regmap_config wm831x_regmap_config; |
421 | 428 | ||
422 | #endif | 429 | #endif |