Requirement
=========
Suspend the device to RAM. It should wake up on any key press from UART.
First Method
=============
This can be done by just adding "no_console_suspend" to bootargs.
By doing this during suspends to RAM, Uart clk src will be kept alive.
Second Method
==============
For this method, hardware should have the capability to wake-up from UART interrupt.
All devices in the device model has two flags to control the wake-up events. They are "can_wakeup" and "wakeup" flags in
struct device {
....
struct dev_pm_info power;
....
}
struct dev_pm_info {
.......
unsigned int can_wakeup:1;
struct wakeup_source *wakeup;
........
}
Flag can_wakeup is initialized by the device driver code by using device_set_wakeup_capable().
And, device_set_wakeup_enable(&dev, 1) will initiallize the struct wakeup_source and add in the list of wake-able sources.
can_wakeup is used to mark whether the hardware can support the wake-up. For most of the devices wake-up will be NULL by default. But used by drivers like power buttons, keyboards and Ethernet.
I want to configure UART as my wake-up source, this patch does it on kernel-3.0.1
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index ab2e6e7..2bae1aa 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2401,7 +2401,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
if (likely(!IS_ERR(tty_dev))) {
device_init_wakeup(tty_dev, 1);
- device_set_wakeup_enable(tty_dev, 0);
+ device_set_wakeup_enable(tty_dev, 1);
} else
printk(KERN_ERR "Cannot register tty device on line %d\n",
uport->line);
Then I tested it with echo mem > /sys/power/state
The device is able to wake-up from my UART1 interrupt which is also my console.
Now my board has many UART. I want to configure the UART2 as wake-able source, but my console is on UART1.
From the command prompt,
cat /dev/ttyS1 &
this done to initialize the UART2 port
And opened UART2 serial port on second instance of minicom. Then entering any character on second minicom wake-up my device.
=========
Suspend the device to RAM. It should wake up on any key press from UART.
First Method
=============
This can be done by just adding "no_console_suspend" to bootargs.
By doing this during suspends to RAM, Uart clk src will be kept alive.
Second Method
==============
For this method, hardware should have the capability to wake-up from UART interrupt.
All devices in the device model has two flags to control the wake-up events. They are "can_wakeup" and "wakeup" flags in
struct device {
....
struct dev_pm_info power;
....
}
struct dev_pm_info {
.......
unsigned int can_wakeup:1;
struct wakeup_source *wakeup;
........
}
Flag can_wakeup is initialized by the device driver code by using device_set_wakeup_capable().
And, device_set_wakeup_enable(&dev, 1) will initiallize the struct wakeup_source and add in the list of wake-able sources.
can_wakeup is used to mark whether the hardware can support the wake-up. For most of the devices wake-up will be NULL by default. But used by drivers like power buttons, keyboards and Ethernet.
I want to configure UART as my wake-up source, this patch does it on kernel-3.0.1
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index ab2e6e7..2bae1aa 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -2401,7 +2401,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev);
if (likely(!IS_ERR(tty_dev))) {
device_init_wakeup(tty_dev, 1);
- device_set_wakeup_enable(tty_dev, 0);
+ device_set_wakeup_enable(tty_dev, 1);
} else
printk(KERN_ERR "Cannot register tty device on line %d\n",
uport->line);
Then I tested it with echo mem > /sys/power/state
The device is able to wake-up from my UART1 interrupt which is also my console.
Now my board has many UART. I want to configure the UART2 as wake-able source, but my console is on UART1.
From the command prompt,
cat /dev/ttyS1 &
this done to initialize the UART2 port
And opened UART2 serial port on second instance of minicom. Then entering any character on second minicom wake-up my device.
4 comments:
That is really good.
In the first method:
the first method causes console_suspend_enabled to be ramained 1. which in turn causes suspend_console() method to return immidiately as soon as it enters the function.
Sorry, I forgot o ask my doubt :)
How this console_suspend_enabled is helping uart clk not to be turned off?
Hi Alok,
Below is the code snippet from kernel/printk.c
int console_suspend_enabled = 1;
EXPORT_SYMBOL(console_suspend_enabled);
static int __init console_suspend_disable(char *str)
{
console_suspend_enabled = 0;
return 1;
}
__setup("no_console_suspend", console_suspend_disable);
So by default console_suspend_enabled = 1, when you pass no_console_suspend as boot argument, kernel will make it 0.
Global variable console_suspend_enabled is used in the serial drivers to see whether it has to suspend or not that uart port which is used as a console during a Suspend to Ram (STR).
A dummy code as below,
8250_suspend()
{
/* Donot suspend the UART port if it is a console */
If(console_suspend_enabled || !uart_console(uport) )
Stop_tx();
Stop_rx();
}
Hope this helps. Sorry for the very late reply.
Hello,
i have customized board based on Beale-Bone Black. i am trying to disable waking up the System from UART0.
echo disabled > /sys/devices/ocp.2/44e09000.serial/tty/ttyO0/power/wakeup
echo disabled > /sys/devices/ocp.2/44e09000.serial/power/wakeup
this is the setting of the currnt wakeup sources:
cat /sys/kernel/debug/wakeup_sources
--------------------------------------------------
name ................
wakeup.gpiokey ................
44e3e00.rtc ................
alarmtimer ................
As you see there is no UART to see!! but i am still able to wake the system up from UART ??
root@milo:~# echo mem > /sys/power/state
[ 5309.439410] PM: Syncing filesystems ... done.
[ 5309.448122] Freezing user space processes ... (elapsed 0.004 seconds) done.
[ 5309.460957] Freezing remaining freezable tasks ... (elapsed 0.001 seconds) done.
[ 5309.470180] Suspending console(s) (use no_console_suspend to debug)
[ 5309.531079] PM: suspend of devices complete after 53.350 msecs
[ 5309.532112] PM: late suspend of devices complete after 1.017 msecs
[ 5309.533249] PM: noirq suspend of devices complete after 1.119 msecs
[ 5309.533326] PM: Successfully put all powerdomains to target state
[ 5309.533326] PM: Wakeup source UART
[ 5309.547912] PM: noirq resume of devices complete after 14.450 msecs
[ 5309.548769] PM: early resume of devices complete after 0.708 msecs
[ 5309.549692] c_can_platform 481d0000.d_can can0: setting BTR=2a01 BRPE=0000
[ 5309.549843] net eth0: initializing cpsw version 1.12 (0)
[ 5309.552140] net eth0: phy found : id is : 0x7c0f1
[ 5309.552202] libphy: PHY 4a101000.mdio:01 not found
[ 5309.552209] net eth0: phy 4a101000.mdio:01 not found on slave 1
[ 5309.774800] PM: resume of devices complete after 226.004 msecs
[ 5309.853396] Restarting tasks ... [ 5309.857207] usb 2-1: USB disconnect, device number 9
As you see in line 10, the system is still waking up from UART0 !!!any idea what is going wrong???
Post a Comment