A number of Linkstation models from Buffalo Technology with PPC, ARM, and 
also MIPS (I think) CPUs have a power-management controller connected to a 
UART. Among other things that chip controlls power and reset buttons. 
Working on a standby support for one of these systems (ppc mpc8241 based), 
the only suitable wakeup source there is the power button, which means, I 
have to configure one of the two system UARTs to not be suspendsd. Using 
the device_*_wakeup API doesn't quite work because both serial ports share 
one device. The below patch proposes a new port flag UPF_MAY_WAKEUP to 
configure such UARTs. It also adds support for a new "can-wakeup" serial 
node property to the legacy_serial driver.

Signed-off-by: Guennadi Liakhovetski <[EMAIL PROTECTED]>

diff --git a/arch/powerpc/kernel/legacy_serial.c 
b/arch/powerpc/kernel/legacy_serial.c
index cea8045..888d9bb 100644
--- a/arch/powerpc/kernel/legacy_serial.c
+++ b/arch/powerpc/kernel/legacy_serial.c
@@ -51,6 +51,9 @@ static int __init add_legacy_port(struct device_node *np, int 
want_index,
        /* get default speed if present */
        spd = of_get_property(np, "current-speed", NULL);
 
+       if (of_find_property(np, "can-wakeup", NULL))
+               flags |= UPF_MAY_WAKEUP;
+
        /* If we have a location index, then try to use it */
        if (want_index >= 0 && want_index < MAX_LEGACY_SERIAL_PORTS)
                index = want_index;
diff --git a/arch/powerpc/kernel/of_platform.c 
b/arch/powerpc/kernel/of_platform.c
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 0b3ec38..77dd552 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -130,6 +130,7 @@ struct uart_8250_port {
        unsigned char           mcr_mask;       /* mask of user bits */
        unsigned char           mcr_force;      /* mask of forced bits */
        unsigned char           lsr_break_flag;
+       char                    suspended;
 
        /*
         * We provide a per-port pm hook.
@@ -2680,8 +2681,14 @@ static int serial8250_suspend(struct platform_device 
*dev, pm_message_t state)
        for (i = 0; i < UART_NR; i++) {
                struct uart_8250_port *up = &serial8250_ports[i];
 
-               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
-                       uart_suspend_port(&serial8250_reg, &up->port);
+               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) 
{
+                       if (up->port.flags & UPF_MAY_WAKEUP)
+                               enable_irq_wake(up->port.irq);
+                       else {
+                               uart_suspend_port(&serial8250_reg, &up->port);
+                               up->suspended = 1;
+                       }
+               }
        }
 
        return 0;
@@ -2694,8 +2701,13 @@ static int serial8250_resume(struct platform_device *dev)
        for (i = 0; i < UART_NR; i++) {
                struct uart_8250_port *up = &serial8250_ports[i];
 
-               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev)
-                       serial8250_resume_port(i);
+               if (up->port.type != PORT_UNKNOWN && up->port.dev == &dev->dev) 
{
+                       if (up->suspended) {
+                               serial8250_resume_port(i);
+                               up->suspended = 0;
+                       } else
+                               disable_irq_wake(up->port.irq);
+               }
        }
 
        return 0;
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 773d8d8..d585967 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -272,6 +272,7 @@ struct uart_port {
 #define UPF_LOW_LATENCY                ((__force upf_t) (1 << 13))
 #define UPF_BUGGY_UART         ((__force upf_t) (1 << 14))
 #define UPF_MAGIC_MULTIPLIER   ((__force upf_t) (1 << 16))
+#define UPF_MAY_WAKEUP         ((__force upf_t) (1 << 17))
 #define UPF_CONS_FLOW          ((__force upf_t) (1 << 23))
 #define UPF_SHARE_IRQ          ((__force upf_t) (1 << 24))
 #define UPF_BOOT_AUTOCONF      ((__force upf_t) (1 << 28))

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-dev

Reply via email to