From 3093e78ebab100ada1c724c9f751d9da39602a97 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 1 Apr 2009 14:11:07 +0000 Subject: clocksource: sh_cmt: use remove_irq() and remove clockevent workaround Update the sh_cmt driver to make use of recent irq and clockevent changes: - use remove_irq() together with setup_irq() - remove mult workaround since WARN_ON() now has been moved Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/clocksource/sh_cmt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 7783b42..1c92c39 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c @@ -465,7 +465,6 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, ced->set_mode = sh_cmt_clock_event_mode; pr_info("sh_cmt: %s used for clock events\n", ced->name); - ced->mult = 1; /* work around misplaced WARN_ON() in clockevents.c */ clockevents_register_device(ced); } @@ -557,7 +556,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) cfg->clockevent_rating, cfg->clocksource_rating); err2: - free_irq(irq, p); + remove_irq(irq, &p->irqaction); err1: iounmap(p->mapbase); err0: -- cgit v1.1 From f7dd2548c471b1c7758611f6cd6393367d7ff649 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 1 Apr 2009 14:20:58 +0000 Subject: sh: intc: install enable, disable and shutdown callbacks Modify the intc code to install a disable callback. The current solution without a disable callback results in use of the generic default_disable() function. This function is a no-op so suspend_device_irqs() will not disable any intc interrupts at suspend time without this patch. Also, install enable and shutdown callbacks while at it. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/sh/intc.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 2269fbc..b75f701 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -707,6 +707,9 @@ void __init register_intc_controller(struct intc_desc *desc) d->chip.mask = intc_disable; d->chip.unmask = intc_enable; d->chip.mask_ack = intc_disable; + d->chip.enable = intc_enable; + d->chip.disable = intc_disable; + d->chip.shutdown = intc_disable; d->chip.set_type = intc_set_sense; #if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A) -- cgit v1.1 From 2dcec7a988a1895540460a0bf5603bab63d5a3ed Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 1 Apr 2009 14:30:59 +0000 Subject: sh: intc: set_irq_wake() support Add set_irq_wake() support to intc using sysdev and suspend. The intc controllers are put on a list at registration time and registered as sysdev devices later on during the boot. The sysdev class suspend callback is used to find irqs with wakeup enabled belonging to our intc controller. Such irqs are simply enabled so wakeup interrupts may reach the cpu. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/sh/intc.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) (limited to 'drivers') diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index b75f701..7fb9b5c 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ @@ -40,6 +42,8 @@ struct intc_handle_int { }; struct intc_desc_int { + struct list_head list; + struct sys_device sysdev; unsigned long *reg; #ifdef CONFIG_SMP unsigned long *smp; @@ -52,6 +56,8 @@ struct intc_desc_int { struct irq_chip chip; }; +static LIST_HEAD(intc_list); + #ifdef CONFIG_SMP #define IS_SMP(x) x.smp #define INTC_REG(d, x, c) (d->reg[(x)] + ((d->smp[(x)] & 0xff) * c)) @@ -232,6 +238,11 @@ static void intc_disable(unsigned int irq) } } +static int intc_set_wake(unsigned int irq, unsigned int on) +{ + return 0; /* allow wakeup, but setup hardware in intc_suspend() */ +} + #if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A) static void intc_mask_ack(unsigned int irq) { @@ -664,6 +675,9 @@ void __init register_intc_controller(struct intc_desc *desc) d = alloc_bootmem(sizeof(*d)); + INIT_LIST_HEAD(&d->list); + list_add(&d->list, &intc_list); + d->nr_reg = desc->mask_regs ? desc->nr_mask_regs * 2 : 0; d->nr_reg += desc->prio_regs ? desc->nr_prio_regs * 2 : 0; d->nr_reg += desc->sense_regs ? desc->nr_sense_regs : 0; @@ -711,6 +725,7 @@ void __init register_intc_controller(struct intc_desc *desc) d->chip.disable = intc_disable; d->chip.shutdown = intc_disable; d->chip.set_type = intc_set_sense; + d->chip.set_wake = intc_set_wake; #if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4A) if (desc->ack_regs) { @@ -761,3 +776,53 @@ void __init register_intc_controller(struct intc_desc *desc) intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect)); } } + +static int intc_suspend(struct sys_device *dev, pm_message_t state) +{ + struct intc_desc_int *d; + struct irq_desc *desc; + int irq; + + /* get intc controller associated with this sysdev */ + d = container_of(dev, struct intc_desc_int, sysdev); + + /* enable wakeup irqs belonging to this intc controller */ + for_each_irq_desc(irq, desc) { + if ((desc->status & IRQ_WAKEUP) && (desc->chip == &d->chip)) + intc_enable(irq); + } + + return 0; +} + +static struct sysdev_class intc_sysdev_class = { + .name = "intc", + .suspend = intc_suspend, +}; + +/* register this intc as sysdev to allow suspend/resume */ +static int __init register_intc_sysdevs(void) +{ + struct intc_desc_int *d; + int error; + int id = 0; + + error = sysdev_class_register(&intc_sysdev_class); + if (!error) { + list_for_each_entry(d, &intc_list, list) { + d->sysdev.id = id; + d->sysdev.cls = &intc_sysdev_class; + error = sysdev_register(&d->sysdev); + if (error) + break; + id++; + } + } + + if (error) + pr_warning("intc: sysdev registration error\n"); + + return error; +} + +device_initcall(register_intc_sysdevs); -- cgit v1.1 From 4ba50df685e85b9d912a290d9614ffbeb4d9f060 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 1 Apr 2009 14:39:20 +0000 Subject: input: sh_keysc: use enable/disable_irq_wake() Modify the sh_keysc driver to use enable/disable_irq_wake() during suspend and resume. These functions are used to enable the sh_keysc interrupt in the interrupt controller so the keypad can be used to wakeup the system from suspend. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/input/keyboard/sh_keysc.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index e1480fb..cea70e6 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -259,12 +259,15 @@ static int sh_keysc_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct sh_keysc_priv *priv = platform_get_drvdata(pdev); + int irq = platform_get_irq(pdev, 0); unsigned short value; value = ioread16(priv->iomem_base + KYCR1_OFFS); - if (device_may_wakeup(dev)) + if (device_may_wakeup(dev)) { value |= 0x80; + enable_irq_wake(irq); + } else value &= ~0x80; @@ -272,8 +275,20 @@ static int sh_keysc_suspend(struct device *dev) return 0; } +static int sh_keysc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + int irq = platform_get_irq(pdev, 0); + + if (device_may_wakeup(dev)) + disable_irq_wake(irq); + + return 0; +} + static struct dev_pm_ops sh_keysc_dev_pm_ops = { .suspend = sh_keysc_suspend, + .resume = sh_keysc_resume, }; struct platform_driver sh_keysc_device_driver = { -- cgit v1.1 From faa9fa8e448ba4c0a9d61778fd3cda1313bf1533 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 1 Apr 2009 14:45:17 +0000 Subject: rtc: rtc-sh: use set_irq_wake() Modify the sh_rtc driver to use set_irq_wake() during suspend and resume. These functions are used to enable the rtc interrupts in the interrupt controller so the rtc can be used to wakeup the system from suspend. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/rtc/rtc-sh.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 4898f7f..9b1ff12 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -795,10 +795,46 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev) return 0; } + +static void sh_rtc_set_irq_wake(struct device *dev, int enabled) +{ + struct platform_device *pdev = to_platform_device(dev); + struct sh_rtc *rtc = platform_get_drvdata(pdev); + + set_irq_wake(rtc->periodic_irq, enabled); + if (rtc->carry_irq > 0) { + set_irq_wake(rtc->carry_irq, enabled); + set_irq_wake(rtc->alarm_irq, enabled); + } + +} + +static int sh_rtc_suspend(struct device *dev) +{ + if (device_may_wakeup(dev)) + sh_rtc_set_irq_wake(dev, 1); + + return 0; +} + +static int sh_rtc_resume(struct device *dev) +{ + if (device_may_wakeup(dev)) + sh_rtc_set_irq_wake(dev, 0); + + return 0; +} + +static struct dev_pm_ops sh_rtc_dev_pm_ops = { + .suspend = sh_rtc_suspend, + .resume = sh_rtc_resume, +}; + static struct platform_driver sh_rtc_platform_driver = { .driver = { .name = DRV_NAME, .owner = THIS_MODULE, + .pm = &sh_rtc_dev_pm_ops, }, .probe = sh_rtc_probe, .remove = __devexit_p(sh_rtc_remove), -- cgit v1.1 From 0935ade0bf6baf9c5f23024102737bdaf7075abc Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 1 Apr 2009 14:49:41 +0000 Subject: input: migor_ts: add wakeup support Add wakeup support to the migor_ts driver. If user space has enabled wakeup, use set_irq_wake() during suspend and resume. With this patch the migor_ts driver can be used to wake the system from suspend. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/input/touchscreen/migor_ts.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index 504ca11..141dd58 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c @@ -198,6 +198,7 @@ static int migor_ts_probe(struct i2c_client *client, goto err2; } + device_init_wakeup(&client->dev, 1); return 0; err2: @@ -224,6 +225,26 @@ static int migor_ts_remove(struct i2c_client *client) return 0; } +static int migor_ts_suspend(struct i2c_client *client, pm_message_t mesg) +{ + struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); + + if (device_may_wakeup(&client->dev)) + enable_irq_wake(priv->irq); + + return 0; +} + +static int migor_ts_resume(struct i2c_client *client) +{ + struct migor_ts_priv *priv = dev_get_drvdata(&client->dev); + + if (device_may_wakeup(&client->dev)) + disable_irq_wake(priv->irq); + + return 0; +} + static const struct i2c_device_id migor_ts_id[] = { { "migor_ts", 0 }, { } @@ -236,6 +257,8 @@ static struct i2c_driver migor_ts_driver = { }, .probe = migor_ts_probe, .remove = migor_ts_remove, + .suspend = migor_ts_suspend, + .resume = migor_ts_resume, .id_table = migor_ts_id, }; -- cgit v1.1