* RFC: 405LP sleep
@ 2002-12-19 20:41 Hollis Blanchard
2002-12-19 21:36 ` Todd Poynor
0 siblings, 1 reply; 4+ messages in thread
From: Hollis Blanchard @ 2002-12-19 20:41 UTC (permalink / raw)
To: devel list
[-- Attachment #1: Type: text/plain, Size: 636 bytes --]
I think the patch is too large. You can find it at
http://penguinppc.org/~hollis/405LP-sleep.diff
I've attached the Documentation file here.
-Hollis
-----Forwarded Message-----
From: Hollis Blanchard <hollis@austin.ibm.com>
To: devel list <linuxppc-dev@lists.linuxppc.org>
Subject: RFC: 405LP sleep
Date: 19 Dec 2002 14:08:43 -0600
This patch implements sleep on the IBM 405LP (described in the
Documentation file at the top of the patch).
It's not quite ready to check in, but I'd like it to be very soon. I'm
still looking for the solution to my get_pteptr question btw...
-Hollis
--
PowerPC Linux
IBM Linux Technology Center
[-- Attachment #2: 405LP-sleep.txt --]
[-- Type: text/plain, Size: 6141 bytes --]
Hollis Blanchard, IBM Linux Technology Center
19 Dec 2002
draft
Linux Sleep on the PowerPC 405LP
--------------------------------
The IBM 405LP embedded CPU has three different sleep modes, assisted by a unit
called "APM0". APM has four wakeup interrupt lines which it cascades onto the
UIC as irq 24. When the 405LP enters a sleep mode, the only thing that can
wake it is those four wakeup lines. One wakeup line is connected to the RTC
interrupt line, allowing wakeup when an RTC alarm goes off. The other three
are board-dependent; on Beech one is connected to a physical button.
Sleep Modes
-----------
1. In "clock-suspend" mode the output of the PLL is stopped. No units are
powered down, and so no state is lost. On wakeup, the PLL continues and
processing resumes exactly where it left off.
2. In "power-down" mode, APM signals the power supply to drop power to the CPU
and integrated peripherals. All important state, including GPRs, SPRs, and
DCRs must be saved by software before entering this sleep mode, and restored
after wakeup. SDRAM is not powered off, so state can be saved there as long as
SDRAM is put in self-refresh mode prior to the sleep.
When a wakeup occurs, the chip (CPU and integrated peripherals) is reset,
returning control to the firmware. The firmware must determine that this is a
wakeup (rather than a normal power-on) by polling the APM0_CFG and APM0_SR
registers.
3. In "standby" mode, APM first freezes the PLL. It then transfers all chip
state (excluding core registers and arrays such as the TLB) over the
i2c bus to a nonvolatile storage device (such as an EEPROM). Once that process
is complete, APM signals the power supply to drop power to the CPU
and integrated peripherals.
When a wakeup occurs, the chip (CPU and integrated peripherals) is reset but
held frozen. APM transfers the saved chip state back over the i2c bus. It then
releases the PLL and processing continues from the reset vector, returning
control to the firmware. The firmware must determine that this is a wakeup
(rather than a normal power-on) by polling the APM0_CFG and APM0_SR registers.
Interaction with Linux
----------------------
Note: that because the chip is reset on wakeup in both power-down and standby
modes, the firmware *must* be made APM-aware. Otherwise, a wakeup will simply
reset the chip, losing all state. clock-suspend mode does not require firmware
interaction.
On wake, the firmware must know how to transfer control back to Linux (which
is still resident in RAM). The following structure is used:
struct wakeup_info {
void (*wakeup_func_phys)(u32 apm0_cfg, u32 apm0_sr); /* physical addr */
u32 magic;
...
}
Firmware is aware only of the first two fields. Linux creates and populates
this structure in memory, and writes the pointer to a well-known location
(currently 0xfc physical) for the firmware to read. (Unfortunately there are
no "scratch" registers provided by the APM unit, requiring used of a
predetermined absolute physical address.) The magic number is intended to be a
simple validator ensuring that the contents of SDRAM have not been corrupted.
Currently Linux also saves one other value in the wakeup_info structure: the
(physical) stack pointer.
Linux Sleep Procedure
---------------------
This is a high-level summary; the code is well-documented.
For power-down and standby modes:
One page is allocated in which to save some CPU registers and the DCRs
currently supported by power-down mode (UART and LCD). EBC registers are
always saved even though standby mode will save/restore them, because
firmware may overwrite those registers before returning control to Linux
on wake.
The non-volatile GPRs, all 64 TLB entries, and quite a few SPRs like LR,
MSR, and EVPR are saved to the stack in an assembly routine. The registers
saved here are those that must be restored before returning into C code on
wakeup; i.e. they cannot be saved and restored in C.
The remaining code is touched into the I-cache so that SDRAM can be put into
self-refresh. The sleep command is written to the APM unit, and then the
processor spins in a bdnz loop until either:
1. the APM unit freezes the processor
2. the CTR register decrements to zero, indicating sleep did not take place
Linux Wakeup Procedure
---------------------
The firmware jumps to the address specified by wakeup_info->wakeup_func_phys .
The processor is still in untranslated mode (MSR:IR/DR = 0). The stack pointer
is immediately restored from wakeup_info->wakeup_sp_phys so that SPRs can be
loaded and restored from the stack. Finally, the non-volatile GPRs are
restored, and control returns via an rfi to the C function executed before
sleep, returning to translated mode (MSR:IR/DR = 1). The C function continues
to restore non-essential registers which were not handled in assembly.
The RTC remains active during sleep, but the timebase does not, and obviously
jiffies has not been incremented. To restore the timebase, the pre-sleep RTC
time is subtracted from the current RTC time to get the difference in seconds.
- jiffies are incremented by (seconds elapsed) * HZ.
- the timebase is incremented by (seconds elapsed) * HZ * tb_ticks_per_jiffy
User Interface
--------------
Currently the only interface to the sleep code is via sysctl (and its /proc
interface). The following /proc items are present under /proc/sys/pm :
suspend: (write-only)
triggers sleep
mode: (string)
contains one of "clock-suspend", "power-down", or "standby",
indicating the sleep mode to be used.
rtc_alarm: (integer)
the number of seconds in the future to wake up. If 0, the RTC alarm is
not set (and some other mechanism must be present to wake up the CPU).
cdiv: (integer, for debugging only)
allows the user to override the "cdiv" field of APM0_CFG, which
controls the speed at which CPU state is transferred over the i2c bus.
It should be easy to add an interrupt handler for irq 24, so that pressing the
APM button on Beech triggers both sleep and wakeup.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: RFC: 405LP sleep
2002-12-19 20:41 RFC: 405LP sleep Hollis Blanchard
@ 2002-12-19 21:36 ` Todd Poynor
2002-12-20 23:31 ` Hollis Blanchard
0 siblings, 1 reply; 4+ messages in thread
From: Todd Poynor @ 2002-12-19 21:36 UTC (permalink / raw)
To: Hollis Blanchard; +Cc: devel list
+int alarm_secs;
+int cdiv;
+char mode[16] = "standby"; /* "clock-suspend", "power-down",
"standby" */
+int attempts; /* debugging */
Suggest more unique names for these globals.
+ jiffies += rtc_secs_elapsed * HZ;
If jiffies is jumped forward then can kernel events (such as those
waiting on a kernel timer) be missed? Whether or not timer queues et al
are processed on wakeup, not sure if it's harmful to update the "kernel
time" when the kernel has done nothing during the sleep interval, maybe
causing various timeouts. Has this been tried with applications like X
running and verified not to kill apps on wakeup?
Matt Locke and I have been discussing whether it's best to update wall
clock time but leave jiffies alone, since "kernel time" did not advance
during the sleep interval. It's a little worrisome: the kernel advances
time by 10ms for its own operations, but wallclock time (xtime and RTC)
jumps forward 10 minutes. We've tried this a little bit on a TI OMAP
and haven't seen anything die so far, but I imagine there'll be some
application that isn't happy about the situation no matter what choice
is made.
--
Todd
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: RFC: 405LP sleep
2002-12-19 21:36 ` Todd Poynor
@ 2002-12-20 23:31 ` Hollis Blanchard
2002-12-23 15:03 ` Tom Rini
0 siblings, 1 reply; 4+ messages in thread
From: Hollis Blanchard @ 2002-12-20 23:31 UTC (permalink / raw)
To: Todd Poynor; +Cc: devel list
On Thu, 2002-12-19 at 15:36, Todd Poynor wrote:
>
> Suggest more unique names for these globals.
Well, how about making them static? :)
> + jiffies += rtc_secs_elapsed * HZ;
>
> If jiffies is jumped forward then can kernel events (such as those
> waiting on a kernel timer) be missed?
I certainly *hope* the check is >= rather than == ... :)
> Whether or not timer queues et al
> are processed on wakeup, not sure if it's harmful to update the "kernel
> time" when the kernel has done nothing during the sleep interval, maybe
> causing various timeouts. Has this been tried with applications like X
> running and verified not to kill apps on wakeup?
I have not run anything interesting like X, no.
> Matt Locke and I have been discussing whether it's best to update wall
> clock time but leave jiffies alone, since "kernel time" did not advance
> during the sleep interval. It's a little worrisome: the kernel advances
> time by 10ms for its own operations, but wallclock time (xtime and RTC)
> jumps forward 10 minutes. We've tried this a little bit on a TI OMAP
> and haven't seen anything die so far, but I imagine there'll be some
> application that isn't happy about the situation no matter what choice
> is made.
Before posting I had tried commenting out the jiffies update and it
seemed to run ok both ways. I decided to leave it in though to preserve
the reality of time passing as much as possible.
arch/arm/mach-sa1100/pm.c seems to only update xtime.tv_sec. I'm hoping
Someone Who Knows will comment one way or the other here...
The updated patch, with many cleanups and one important bugfix, has been
posted to http://penguinppc.org/~hollis/405LP-sleep.diff. Aside from the
remaining get_pteptr problem, I think the code is ready to be checked
in. If anyone disagrees please let me know. :)
-Hollis
--
PowerPC Linux
IBM Linux Technology Center
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: RFC: 405LP sleep
2002-12-20 23:31 ` Hollis Blanchard
@ 2002-12-23 15:03 ` Tom Rini
0 siblings, 0 replies; 4+ messages in thread
From: Tom Rini @ 2002-12-23 15:03 UTC (permalink / raw)
To: Hollis Blanchard; +Cc: Todd Poynor, devel list
On Fri, Dec 20, 2002 at 05:31:14PM -0600, Hollis Blanchard wrote:
> On Thu, 2002-12-19 at 15:36, Todd Poynor wrote:
>
> > + jiffies += rtc_secs_elapsed * HZ;
> >
> > If jiffies is jumped forward then can kernel events (such as those
> > waiting on a kernel timer) be missed?
>
> I certainly *hope* the check is >= rather than == ... :)
They all should in fact be using time_after(...) or so, to deal
correctly with a jiffies wrap. But from what I recall of doing a
massive kick of the jiffies (to test some jiffies wrap thing) in early
2.4 I believe, things can become somewhat unhappy. Think of a device
which happens to be 'sleeping' while the user is on vacation or so.
--
Tom Rini (TR1265)
http://gate.crashing.org/~trini/
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2002-12-23 15:03 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-12-19 20:41 RFC: 405LP sleep Hollis Blanchard
2002-12-19 21:36 ` Todd Poynor
2002-12-20 23:31 ` Hollis Blanchard
2002-12-23 15:03 ` Tom Rini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).