Index: linux-2.6.27/arch/powerpc/platforms/83xx/Kconfig =================================================================== --- linux-2.6.27.orig/arch/powerpc/platforms/83xx/Kconfig +++ linux-2.6.27/arch/powerpc/platforms/83xx/Kconfig @@ -104,6 +104,13 @@ config ASP834x endif + +config WAKEUP_IT + tristate "83xx interrupt for PM wakeup" + help + This enables a driver to be used as a wakeup source . + + # used for usb config PPC_MPC831x bool Index: linux-2.6.27/arch/powerpc/platforms/83xx/Makefile =================================================================== --- linux-2.6.27.orig/arch/powerpc/platforms/83xx/Makefile +++ linux-2.6.27/arch/powerpc/platforms/83xx/Makefile @@ -14,3 +14,4 @@ obj-$(CONFIG_MPC837x_MDS) += mpc837x_mds obj-$(CONFIG_SBC834x) += sbc834x.o obj-$(CONFIG_MPC837x_RDB) += mpc837x_rdb.o obj-$(CONFIG_ASP834x) += asp834x.o +obj-$(CONFIG_WAKEUP_IT) += wakeup-it.o Index: linux-2.6.27/arch/powerpc/platforms/83xx/wakeup-it.c =================================================================== --- /dev/null +++ linux-2.6.27/arch/powerpc/platforms/83xx/wakeup-it.c @@ -0,0 +1,163 @@ +/* + * This support a driver to be used as a wakeup source on the MPC8313. + * + * Copyright (c) 2008 Cenosys + * + * Alexandre Coffignal + * Sylvain Giroudon + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DRIVER_NAME "wakeup-it" + +char suspend = 0; + +static char *wakeup_irq_ids[] = { + "capsense", + "rfid", +}; + +struct wakeup_priv { + int nirq; + int irq[ARRAY_SIZE(wakeup_irq_ids)]; + spinlock_t lock; +}; + +struct wakeup_irq_desc { + char *name; + int index; +}; + +static irqreturn_t wakeup(int irq, void *dev_id) +{ + //printk(KERN_INFO "===== WAKEUP INTERRUPT %d !!\n", irq); + + if ( suspend ) + kernel_restart(NULL); + return IRQ_HANDLED ; +} + + +static void wakeup_free(struct wakeup_priv *priv) +{ + int i; + + for (i = 0; i < priv->nirq; i++) { + free_irq(priv->irq[i], priv); + } + + kfree(priv); +} + + +static int __devinit wakeup_probe(struct of_device *dev, const struct of_device_id *match) +{ + struct device_node *np = dev->node; + struct resource res; + int ret = 0; + struct wakeup_priv *priv; + int i; + + priv = kmalloc(sizeof(struct wakeup_priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->nirq = 0; + spin_lock_init(&priv->lock); + dev_set_drvdata(&dev->dev, priv); + + ret = of_address_to_resource(np, 0, &res); + if (ret) + goto out; + + for (i = 0; i < ARRAY_SIZE(wakeup_irq_ids); i++) { + char *id = wakeup_irq_ids[i]; + char it_name[32]; + int it_num; + + it_num = irq_of_parse_and_map(np, i); + if ( it_num == NO_IRQ ) { + dev_err(&dev->dev, DRIVER_NAME ": interrupt #%d (%s) does not exist in device tree.\n", i, id); + ret = -ENODEV; + goto out; + } + + set_irq_type(it_num, IRQ_TYPE_EDGE_FALLING); + + snprintf(it_name, sizeof(it_name), DRIVER_NAME ":%s", id); + + ret = request_irq(it_num, wakeup, 0, it_name, priv); + if ( ret ) { + printk(KERN_WARNING DRIVER_NAME ": cannot request interrupt %d (%s)\n", it_num, id); + goto out; + } + + printk(KERN_INFO DRIVER_NAME ": accepting wakeup event from %s (%d)\n", id, it_num); + + priv->irq[priv->nirq++] = it_num; + } + + return 0; + +out: + wakeup_free(priv); + return ret; +} + +static int __devexit wakeup_remove(struct of_device *dev) +{ + struct wakeup_priv *priv = dev_get_drvdata(&dev->dev); + wakeup_free(priv); + return 0; +} + +static struct of_device_id wakeup_match[] = { + { + .compatible = "fsl,wakeup-it", + }, + {}, +}; + +static int wakeup_suspend(struct of_device * dev, pm_message_t state) +{ + int ret = 0; + printk(KERN_INFO DRIVER_NAME ": suspend\n"); + suspend=1; + return ret; +} + + +static struct of_platform_driver wakeup_driver = { + .name = DRIVER_NAME, + .match_table = wakeup_match, + .probe = wakeup_probe, + .suspend = wakeup_suspend, + .remove = __devexit_p(wakeup_remove) + +}; + +static int __init wakeup_init(void) +{ + return of_register_platform_driver(&wakeup_driver); +} + +static void __exit wakeup_exit(void) +{ + of_unregister_platform_driver(&wakeup_driver); +} + +module_init(wakeup_init); +module_exit(wakeup_exit);