Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 308757
b: refs/heads/master
c: cd99758
h: refs/heads/master
i:
  308755: c40292f
v: v3
  • Loading branch information
Mark Brown authored and Samuel Ortiz committed May 20, 2012
1 parent 02e87b5 commit efd4da9
Show file tree
Hide file tree
Showing 14 changed files with 132 additions and 85 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4492c4c3ff7bbb5fd400f021532643a3493f0723
refs/heads/master: cd99758ba3bde64347a8ece381cbae2fb5c745b2
6 changes: 2 additions & 4 deletions trunk/drivers/gpio/gpio-wm831x.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,8 @@ static int wm831x_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
struct wm831x_gpio *wm831x_gpio = to_wm831x_gpio(chip);
struct wm831x *wm831x = wm831x_gpio->wm831x;

if (!wm831x->irq_base)
return -EINVAL;

return wm831x->irq_base + WM831X_IRQ_GPIO_1 + offset;
return irq_create_mapping(wm831x->irq_domain,
WM831X_IRQ_GPIO_1 + offset);
}

static int wm831x_gpio_set_debounce(struct gpio_chip *chip, unsigned offset,
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/input/misc/wm831x-on.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev)
{
struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
struct wm831x_on *wm831x_on;
int irq = platform_get_irq(pdev, 0);
int irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
int ret;

wm831x_on = kzalloc(sizeof(struct wm831x_on), GFP_KERNEL);
Expand Down
9 changes: 5 additions & 4 deletions trunk/drivers/input/touchscreen/wm831x-ts.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,15 +260,16 @@ static __devinit 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"));
if (pdata && pdata->data_irq)
wm831x_ts->data_irq = pdata->data_irq;
else
wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA");

wm831x_ts->pd_irq = wm831x_irq(wm831x,
platform_get_irq_byname(pdev, "TCHPD"));
if (pdata && pdata->pd_irq)
wm831x_ts->pd_irq = pdata->pd_irq;
else
wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD");

if (pdata)
wm831x_ts->pressure = pdata->pressure;
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/mfd/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ config MFD_WM831X_I2C
select MFD_CORE
select MFD_WM831X
select REGMAP_I2C
select IRQ_DOMAIN
depends on I2C=y && GENERIC_HARDIRQS
help
Support for the Wolfson Microelecronics WM831x and WM832x PMICs
Expand All @@ -508,6 +509,7 @@ config MFD_WM831X_SPI
select MFD_CORE
select MFD_WM831X
select REGMAP_SPI
select IRQ_DOMAIN
depends on SPI_MASTER && GENERIC_HARDIRQS
help
Support for the Wolfson Microelecronics WM831x and WM832x PMICs
Expand Down
6 changes: 3 additions & 3 deletions trunk/drivers/mfd/wm831x-auxadc.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,11 +280,11 @@ void wm831x_auxadc_init(struct wm831x *wm831x)
mutex_init(&wm831x->auxadc_lock);
INIT_LIST_HEAD(&wm831x->auxadc_pending);

if (wm831x->irq && wm831x->irq_base) {
if (wm831x->irq) {
wm831x->auxadc_read = wm831x_auxadc_read_irq;

ret = request_threaded_irq(wm831x->irq_base +
WM831X_IRQ_AUXADC_DATA,
ret = request_threaded_irq(wm831x_irq(wm831x,
WM831X_IRQ_AUXADC_DATA),
NULL, wm831x_auxadc_irq, 0,
"auxadc", wm831x);
if (ret < 0) {
Expand Down
19 changes: 9 additions & 10 deletions trunk/drivers/mfd/wm831x-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1813,27 +1813,27 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
case WM8310:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8310_devs, ARRAY_SIZE(wm8310_devs),
NULL, wm831x->irq_base);
NULL, 0);
break;

case WM8311:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8311_devs, ARRAY_SIZE(wm8311_devs),
NULL, wm831x->irq_base);
NULL, 0);
if (!pdata || !pdata->disable_touch)
mfd_add_devices(wm831x->dev, wm831x_num,
touch_devs, ARRAY_SIZE(touch_devs),
NULL, wm831x->irq_base);
NULL, 0);
break;

case WM8312:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8312_devs, ARRAY_SIZE(wm8312_devs),
NULL, wm831x->irq_base);
NULL, 0);
if (!pdata || !pdata->disable_touch)
mfd_add_devices(wm831x->dev, wm831x_num,
touch_devs, ARRAY_SIZE(touch_devs),
NULL, wm831x->irq_base);
NULL, 0);
break;

case WM8320:
Expand All @@ -1842,7 +1842,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
case WM8326:
ret = mfd_add_devices(wm831x->dev, wm831x_num,
wm8320_devs, ARRAY_SIZE(wm8320_devs),
NULL, wm831x->irq_base);
NULL, 0);
break;

default:
Expand All @@ -1867,7 +1867,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
if (ret & WM831X_XTAL_ENA) {
ret = mfd_add_devices(wm831x->dev, wm831x_num,
rtc_devs, ARRAY_SIZE(rtc_devs),
NULL, wm831x->irq_base);
NULL, 0);
if (ret != 0) {
dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret);
goto err_irq;
Expand All @@ -1880,7 +1880,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
/* Treat errors as non-critical */
ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs,
ARRAY_SIZE(backlight_devs), NULL,
wm831x->irq_base);
0);
if (ret < 0)
dev_err(wm831x->dev, "Failed to add backlight: %d\n",
ret);
Expand Down Expand Up @@ -1909,8 +1909,7 @@ void wm831x_device_exit(struct wm831x *wm831x)
{
wm831x_otp_exit(wm831x);
mfd_remove_devices(wm831x->dev);
if (wm831x->irq_base)
free_irq(wm831x->irq_base + WM831X_IRQ_AUXADC_DATA, wm831x);
free_irq(wm831x_irq(wm831x, WM831X_IRQ_AUXADC_DATA), wm831x);
wm831x_irq_exit(wm831x);
}

Expand Down
101 changes: 64 additions & 37 deletions trunk/drivers/mfd/wm831x-irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/irq.h>
#include <linux/mfd/core.h>
#include <linux/interrupt.h>
#include <linux/irqdomain.h>

#include <linux/mfd/wm831x/core.h>
#include <linux/mfd/wm831x/pdata.h>
Expand Down Expand Up @@ -328,7 +329,7 @@ static inline int irq_data_to_status_reg(struct wm831x_irq_data *irq_data)
static inline struct wm831x_irq_data *irq_to_wm831x_irq(struct wm831x *wm831x,
int irq)
{
return &wm831x_irqs[irq - wm831x->irq_base];
return &wm831x_irqs[irq];
}

static void wm831x_irq_lock(struct irq_data *data)
Expand Down Expand Up @@ -374,7 +375,7 @@ static void wm831x_irq_enable(struct irq_data *data)
{
struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x,
data->irq);
data->hwirq);

wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
}
Expand All @@ -383,7 +384,7 @@ static void wm831x_irq_disable(struct irq_data *data)
{
struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x,
data->irq);
data->hwirq);

wm831x->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
}
Expand All @@ -393,7 +394,7 @@ static int wm831x_irq_set_type(struct irq_data *data, unsigned int type)
struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
int irq;

irq = data->irq - wm831x->irq_base;
irq = data->hwirq;

if (irq < WM831X_IRQ_GPIO_1 || irq > WM831X_IRQ_GPIO_11) {
/* Ignore internal-only IRQs */
Expand Down Expand Up @@ -469,9 +470,11 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
* descriptors.
*/
if (primary & WM831X_TCHPD_INT)
handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHPD);
handle_nested_irq(irq_find_mapping(wm831x->irq_domain,
WM831X_IRQ_TCHPD));
if (primary & WM831X_TCHDATA_INT)
handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHDATA);
handle_nested_irq(irq_find_mapping(wm831x->irq_domain,
WM831X_IRQ_TCHDATA));
primary &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);

for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) {
Expand Down Expand Up @@ -507,7 +510,8 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
}

if (*status & wm831x_irqs[i].mask)
handle_nested_irq(wm831x->irq_base + i);
handle_nested_irq(irq_find_mapping(wm831x->irq_domain,
i));

/* Simulate an edge triggered IRQ by polling the input
* status. This is sucky but improves interoperability.
Expand All @@ -516,7 +520,8 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
wm831x->gpio_level[i - WM831X_IRQ_GPIO_1]) {
ret = wm831x_reg_read(wm831x, WM831X_GPIO_LEVEL);
while (ret & 1 << (i - WM831X_IRQ_GPIO_1)) {
handle_nested_irq(wm831x->irq_base + i);
handle_nested_irq(irq_find_mapping(wm831x->irq_domain,
i));
ret = wm831x_reg_read(wm831x,
WM831X_GPIO_LEVEL);
}
Expand All @@ -527,10 +532,34 @@ static irqreturn_t wm831x_irq_thread(int irq, void *data)
return IRQ_HANDLED;
}

static int wm831x_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
irq_set_chip_data(virq, h->host_data);
irq_set_chip_and_handler(virq, &wm831x_irq_chip, handle_edge_irq);
irq_set_nested_thread(virq, 1);

/* ARM needs us to explicitly flag the IRQ as valid
* and will set them noprobe when we do so. */
#ifdef CONFIG_ARM
set_irq_flags(virq, IRQF_VALID);
#else
irq_set_noprobe(virq);
#endif

return 0;
}

static struct irq_domain_ops wm831x_irq_domain_ops = {
.map = wm831x_irq_map,
.xlate = irq_domain_xlate_twocell,
};

int wm831x_irq_init(struct wm831x *wm831x, int irq)
{
struct wm831x_pdata *pdata = wm831x->dev->platform_data;
int i, cur_irq, ret;
struct irq_domain *domain;
int i, ret, irq_base;

mutex_init(&wm831x->irq_lock);

Expand All @@ -543,18 +572,33 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
}

/* Try to dynamically allocate IRQs if no base is specified */
if (!pdata || !pdata->irq_base)
wm831x->irq_base = -1;
if (pdata && pdata->irq_base) {
irq_base = irq_alloc_descs(pdata->irq_base, 0,
WM831X_NUM_IRQS, 0);
if (irq_base < 0) {
dev_warn(wm831x->dev, "Failed to allocate IRQs: %d\n",
irq_base);
irq_base = 0;
}
} else {
irq_base = 0;
}

if (irq_base)
domain = irq_domain_add_legacy(wm831x->dev->of_node,
ARRAY_SIZE(wm831x_irqs),
irq_base, 0,
&wm831x_irq_domain_ops,
wm831x);
else
wm831x->irq_base = pdata->irq_base;
domain = irq_domain_add_linear(wm831x->dev->of_node,
ARRAY_SIZE(wm831x_irqs),
&wm831x_irq_domain_ops,
wm831x);

wm831x->irq_base = irq_alloc_descs(wm831x->irq_base, 0,
WM831X_NUM_IRQS, 0);
if (wm831x->irq_base < 0) {
dev_warn(wm831x->dev, "Failed to allocate IRQs: %d\n",
wm831x->irq_base);
wm831x->irq_base = 0;
return 0;
if (!domain) {
dev_warn(wm831x->dev, "Failed to allocate IRQ domain\n");
return -EINVAL;
}

if (pdata && pdata->irq_cmos)
Expand All @@ -566,24 +610,7 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
WM831X_IRQ_OD, i);

wm831x->irq = irq;

/* Register them with genirq */
for (cur_irq = wm831x->irq_base;
cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base;
cur_irq++) {
irq_set_chip_data(cur_irq, wm831x);
irq_set_chip_and_handler(cur_irq, &wm831x_irq_chip,
handle_edge_irq);
irq_set_nested_thread(cur_irq, 1);

/* ARM needs us to explicitly flag the IRQ as valid
* and will set them noprobe when we do so. */
#ifdef CONFIG_ARM
set_irq_flags(cur_irq, IRQF_VALID);
#else
irq_set_noprobe(cur_irq);
#endif
}
wm831x->irq_domain = domain;

if (irq) {
/* Try to flag /IRQ as a wake source; there are a number of
Expand Down
21 changes: 13 additions & 8 deletions trunk/drivers/power/wm831x_power.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
goto err_usb;
}

irq = platform_get_irq_byname(pdev, "SYSLO");
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq,
IRQF_TRIGGER_RISING, "System power low",
power);
Expand All @@ -575,7 +575,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
goto err_battery;
}

irq = platform_get_irq_byname(pdev, "PWR SRC");
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC"));
ret = request_threaded_irq(irq, NULL, wm831x_pwr_src_irq,
IRQF_TRIGGER_RISING, "Power source",
power);
Expand All @@ -586,7 +586,9 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
}

for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
irq = wm831x_irq(wm831x,
platform_get_irq_byname(pdev,
wm831x_bat_irqs[i]));
ret = request_threaded_irq(irq, NULL, wm831x_bat_irq,
IRQF_TRIGGER_RISING,
wm831x_bat_irqs[i],
Expand All @@ -606,10 +608,10 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
free_irq(irq, power);
}
irq = platform_get_irq_byname(pdev, "PWR SRC");
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC"));
free_irq(irq, power);
err_syslo:
irq = platform_get_irq_byname(pdev, "SYSLO");
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
free_irq(irq, power);
err_battery:
if (power->have_battery)
Expand All @@ -626,17 +628,20 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
static __devexit int wm831x_power_remove(struct platform_device *pdev)
{
struct wm831x_power *wm831x_power = platform_get_drvdata(pdev);
struct wm831x *wm831x = wm831x_power->wm831x;
int irq, i;

for (i = 0; i < ARRAY_SIZE(wm831x_bat_irqs); i++) {
irq = platform_get_irq_byname(pdev, wm831x_bat_irqs[i]);
irq = wm831x_irq(wm831x,
platform_get_irq_byname(pdev,
wm831x_bat_irqs[i]));
free_irq(irq, wm831x_power);
}

irq = platform_get_irq_byname(pdev, "PWR SRC");
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "PWR SRC"));
free_irq(irq, wm831x_power);

irq = platform_get_irq_byname(pdev, "SYSLO");
irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "SYSLO"));
free_irq(irq, wm831x_power);

if (wm831x_power->have_battery)
Expand Down
Loading

0 comments on commit efd4da9

Please sign in to comment.