Table of Contents

Power Management

Power management is a tricky thing to understand - and even harder thing to implement properly. The words and states that is used to describe the hardware is not the same as the states used to describe the software. The software/hardware interaction is normally defined by the Advanced Configuration and Power Interface (ACPI). ACPI defines common interfaces for hardware recognition, motherboard and device configuration and power management, and is supported by the Linux kernel natively.

ACPI Information

The ACPI specification promotes the concept that systems should manage energy consumption by transitioning unused devices into lower power states including placing the entire system in a low-power state (sleeping state) when possible. A system is broken down into classes:

global states
The ACPI global system states apply to the entire system, and are visible to the user. They are working, sleeping, soft off, and mechanical off.
device states
Device power states are states of particular devices; as such, they are generally not visible to the user. For example, some devices may be in the off state even though the system as a whole is in the working state. Device states apply to any device on any bus.
processor states
This balances processor performance against power consumption and thermal states by manipulating the processor's performance controls. The ACPI specification defines a working state, labeled G0 (S0), in which the processor executes instructions. Processor sleeping states, labeled C1 through C3, are also defined. In the sleeping states, the processor executes no instructions, thus reducing power consumption and, potentially, operating temperatures. The ACPI specification also defines processor performance states, where the processor (while in C0) executes instructions, but with lower performance and (potentially) lower power consumption and operating temperature.

ACPI States

While the Global System is working (on), the processor can be in any number of states, from executing instructions at full rate (G0/C0/P0), to executing instructions at a reduced rate (G0/C0/P4), to waiting for interrupts to occur in a low power mode (G0/C1).

Device states are independent of the system, and are states of particular devices. Device states apply to any device on any bus.

Hardware support

The Blackfin processor provides several operating modes, each with different performance/power/latency profiles. In addition to overall clock management and gating clocks to each of the peripherals, the processor provides the control functions to dynamically alter the processor core supply voltage to further reduce power dissipation. The power states available to the hardware are:

Not all hardware states are available in the Linux kernel.

Besides the Power Management States there is also Support for CPU frequency and Voltage Scaling

While adding Suspend-MEM support we found that a few Blackfin EZKIT/STAMP development boards lost SDRAM data integrity after entering Hibernate Mode. We found some heavy Over- and Undershoot on the SDRAM SCKE Strobe preventing the SDRAM to enter Self Refresh properly.

Failing Boards:

BoardStatus
BF537-EZKit Rev 1.3 Silicon Rev. 0.2 (Ser# 557684) Failed
BF537-EZKit Rev 2.2 Silicon Rev. 0.3 (Ser# 570385) Failed
BF537-EZKit Rev 2.2 Silicon Rev. 0.3 (Ser# 570380) Failed
BF537-STAMP Rev 1.3 Silicon Rev. 0.2 (Ser# 556262) Failed

A simple hardware workaround on the SCKE Strobe made the issue go away:

Add a 6.8k Ohm resistor between SCKE (J2-81) and GND (J2-87).

Supported Power Management States

The kernel supports three power management states generically, though each is dependent on platform support code to implement the low-level details for each state. Blackfin Linux currently offers Standby.

This state offers high power savings, while providing a very low-latency transition back to a working system. No operating state is lost (the CPU retains power), so the system easily starts up again where it left off. From a Blackfin hardware perspective - the processor is in Full On, but the Clocks are slowed down to consume almost no power.

We try to put devices in a low-power state equivalent to D1, which also offers low power savings, but low resume latency. Not all devices support D1, and those that don't are left on.

A transition from Standby to the On state should take only a few milliseconds.

Enabling Power Management Support

Linux Kernel Configuration ->
    Power management options  ->

 [*] Power Management support
 [ ]   Legacy Power Management API (DEPRECATED)
 [ ]   Power Management Debug Support
 [*] Suspend to RAM and standby
     Standby Power Saving Mode (Sleep Deeper)  --->
 [*] Allow Wakeup from Standby by GPIO
 (2)   GPIO number
       GPIO Polarity (Active High)  --->
 --- Possible Suspend Mem / Hibernate Wake-Up Sources
 [ ] Allow Wake-Up from on-chip PHY or PH6 GP

Wakeup Source

BF5xx wake up setting

There are two different options controlling the Wakeup

Cause Wakeup Event by Interrupt

Wakeup Events:

For dynamic power management, any of the peripherals can be configured to wake up the core from its idled state to process the interrupt and resume form standby, simply by enabling the appropriate bit in the system interrupt wakeup-enable register (refer to Hardware Reference Manual SIC_IWR).

If a peripheral interrupt source is enabled in SIC_IWR and the core is idled, the interrupt causes the DPMC to initiate the core wakeup sequence in order to process the interrupt.

The linux kernel API provides these three functions to enable or disable wakeup capabilities of interrupts:

int set_irq_wake(irq, state);
int disable_irq_wake(unsigned int irq)

file: include/linux/interrupt.h

scm failed with exit code 1:
file does not exist in git
int enable_irq_wake(unsigned int irq)

file: include/linux/interrupt.h

scm failed with exit code 1:
file does not exist in git

Example:

Following patch enables irq wake for all gpio-keys push buttons.

Index: drivers/input/keyboard/gpio_keys.c
===================================================================
--- drivers/input/keyboard/gpio_keys.c  (revision 4154)
+++ drivers/input/keyboard/gpio_keys.c  (working copy)
@@ -100,7 +100,7 @@
                                irq, error);
                        goto fail;
                }
-
+               enable_irq_wake(irq);
                input_set_capability(input, type, button->code);
        }

In current kernel versions this feature has been added to the gpio-keys driver

This feature can be enabled by:

root:/sys/devices/platform/gpio-keys.0/power> echo enabled > wakeup

Cause Wakeup Event by GPIO

This option adds some extra code that allows specifying any Blackfin GPIO to be configured as Wakeup Strobe.

There is an alternative Blackfin specific API for GPIO wakeups:

This API allows GPIO wakeups without using the Linux interrupt API. It also allows configuring a Wakeup as EDGE or Both EDGE sensitive while the Linux kernel interrupt is configured level sensitive.

#define PM_WAKE_RISING	0x1
#define PM_WAKE_FALLING	0x2
#define PM_WAKE_HIGH	0x4
#define PM_WAKE_LOW	0x8
#define PM_WAKE_BOTH_EDGES	(PM_WAKE_RISING | PM_WAKE_FALLING)
#define PM_WAKE_IGNORE	0xF0
 
int gpio_pm_wakeup_request(unsigned gpio, unsigned char type);
void gpio_pm_wakeup_free(unsigned gpio);

This API was removed before the Blackfin Linux:2010R1 Release

BF60x wake up setting

The table below shows the HIBERNATE and DEEP SLEEP wake-up sources for the BF60x.

DPM_WAKE_EN,DPM_WAKE_POL,&DPM_WAKE_STAT BitAssigned SourceDEEP SLEEP?HIBERNATE?
WS0 PA_15 Yes Yes
WS1 PB_15 Yes Yes
WS2 PC_15 Yes Yes
WS3 PD_06 (ETH0_PHYINT) Yes Yes
WS4 PE_12 (ETH1_PHYINT) Yes Yes
WS5 PG_04 (CAN0_RX) Yes Yes
WS6 PG_13 Yes Yes
WS7 USB No Yes
WS30:WS8 RESERVED NA NA

Enable BF60x wakeup source & configure wakeup polarity

 [*] Suspend to RAM and standby                                                         │ │  
  │ │      [ ] Run-time PM core functionality                                           │ │  
  │ │      [ ] Power Management Debug Support                                           │ │  
  │ │          *** Possible Suspend Mem / Hibernate Wake-Up Sources ***                 │ │  
  │ │      [ ] Allow Wake-Up from PA15                                                  │ │  
  │ │      [ ] Allow Wake-Up from PB15                                                  │ │  
  │ │      [ ] Allow Wake-Up from PC15                                                  │ │  
  │ │      [ ] Allow Wake-Up from PD06(ETH0_PHYINT)                                     │ │  
  │ │      [*] Allow Wake-Up from PE12(ETH1_PHYINT, PUSH BUTTON)                        │ │  
  │ │      (1)   Wake-up priority                                                       │ │  
  │ │      [ ] Allow Wake-Up from PG04(CAN0_RX)                                         │ │  
  │ │      [ ] Allow Wake-Up from PG13                                                  │ │  
  │ │      [ ] Allow Wake-Up from (USB)                                                 │ │ 

Power Management Interface

The power management subsystem provides a unified sysfs interface to userspace, regardless of what architecture or platform one is running. The interface exists in /sys/power/ directory (assuming sysfs is mounted at /sys).

/sys/power/state controls system power state. Reading from this file returns what states are supported, which is hard-coded to 'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and 'disk' (Suspend-to-Disk).

Blackfin Linux supports:

Mode Description
standby Blackfin sleep or sleep_deeper
mem Blackfin Hibernate Suspend-to-Mem
disk NOT AVAILABLE

Writing to this file one of those strings causes the system to transition into that state. Please see the file Documentation/power/states.txt for a description of each of those states.

Putting the system into Standby from Command Line

root:~> echo standby > /sys/power/state
Syncing filesystems ... done.
Freezing user space processes ... (elapsed 0.00 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.00 seconds) done.
Suspending console(s)

* Wakeup Event *

Restarting tasks ... done.
root:~>

Putting the system into Standby using Busybox rtcwake tool

The RTC wake up tool applies only to BF5xx chips that have the RTC peripheral.

RTC Wakeup in 10 Seconds

root:/> rtcwake -s 10 -m standby
wakeup from "standby" at Thu Jan  1 01:45:31 1970
Syncing filesystems ... done.
Freezing user space processes ... (elapsed 0.00 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.00 seconds) done.
Suspending console(s)
Restarting tasks ... done.
root:/>

Putting the system into Suspend Mem from Command Line

root:~> echo mem > /sys/power/state
Syncing filesystems ... done.
Freezing user space processes ... (elapsed 0.00 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.00 seconds) done.
Suspending console(s)

* Wakeup Event *

Restarting tasks ... done.
root:~>

Putting the system into Suspend Mem using Busybox rtcwake tool

The RTC wake up tool applies only to BF5xx chips that have the RTC peripheral.

RTC Wakeup in 10 Seconds

root:/> rtcwake -s 10 -m mem
wakeup from "mem" at Thu Jan  1 01:45:31 1970
Syncing filesystems ... done.
Freezing user space processes ... (elapsed 0.00 seconds) done.
Freezing remaining freezable tasks ... (elapsed 0.00 seconds) done.
Suspending console(s)
Restarting tasks ... done.
root:/>

Writing to /sys/power/state from User Applications

#include <stdio.h>
#include <getopt.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
 
static void suspend_system(const char *suspend)
{
	char	buf[20];
	int	f = open("/sys/power/state", O_WRONLY);
	int	len;
	ssize_t	n;
	if (f < 0) {
		perror("open /sys/power/state");
		return;
	}
	len = sprintf(buf, "%s\n", suspend) - 1;
	len = strlen(buf);
	n = write(f, buf, len);
 
	/* this executes after wake from suspend */
	if (n < 0)
		perror("write /sys/power/state");
	else if (n != len)
		fprintf(stderr, "short write to %s\n", "/sys/power/state");
	close(f);
}
 
int main(int argc, char **argv)
{
  static char		*suspend = "standby";
 
  printf("Going into %s ...\n",suspend);
 
	  suspend_system(suspend);
 
  printf("Awakeing from %s ...\n",suspend);
 
 return 0;
}

POWER Wake up times

The power wake up times are different among Linux system core driver, Linux generic peripheral driver and Linux application.

In 2012R1 Linux distribution for BF60X:

Component hibernate to memory standby(sleep)
Linux system core driver < 3ms < 1ms
Linux peripheral driver 3ms ~ 14ms 1ms ~ 12ms
Linux application > 51ms > 49ms

POWER DISSIPATION/CONSUMPTION

Many operating conditions can affect power dissipation/consumption. System designers should refer to Estimating Power for ADSP-BF531/BF532/BF533 Blackfin Processors (EE-229) on the Analog Devices website (www.analog.com)

EE229 This document provides detailed information

In general:

Derived Power Consumption (PDDTOT)

Internal Power Consumption (PDDINT)

External Power Consumption (PDDEXT, PDDRTC)

Power Management Operating Modes

The Standby/sleep mode reduces dynamic power dissipation by disabling the clock to the processor core (CCLK).

Furthermore, Standby/sleep_deeper sets the internal power supply voltage (VDDINT) to 0.85 V to provide the greatest power savings, while preserving the processor state.

The PLL and system clock (SCLK) continue to operate at a very low frequency of about 3.3 MHz. To preserve data integrity in the SDRAM, the SDRAM is put into Self Refresh Mode. Typically an external event such as GPIO interrupt or RTC activity wakes up the processor.

Measurements shown in the chart are typical values and may vary. Test platform was a BF537-STAMP running linux-2.6.24.7-ADI-2008R2-pre-svn5073 IO (External) Current and Voltage has been measured across R148. Core (Internal) Current and Voltage has been measured across R61.

Many operating conditions can affect power dissipation. System designers should refer to EE-297: Estimating Power for the ADSP-BF534/BF536/BF537 Blackfin Processors.” This document will provide detailed information for optimizing your design for lowest power.

1) , 2) , 3) , 4) , 5) , 6) depends on the Blackfin - check your HRM