]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - doc/html/ref/power-controller.html
RedBoot TX53 Release 2012-02-15
[karo-tx-redboot.git] / doc / html / ref / power-controller.html
1 <!-- Copyright (C) 2003 Red Hat, Inc.                                -->
2 <!-- This material may be distributed only subject to the terms      -->
3 <!-- and conditions set forth in the Open Publication License, v1.0  -->
4 <!-- or later (the latest version is presently available at          -->
5 <!-- http://www.opencontent.org/openpub/).                           -->
6 <!-- Distribution of the work or derivative of the work in any       -->
7 <!-- standard (paper) book form is prohibited unless prior           -->
8 <!-- permission is obtained from the copyright holder.               -->
9 <HTML
10 ><HEAD
11 ><TITLE
12 >Implementing a Power Controller</TITLE
13 ><meta name="MSSmartTagsPreventParsing" content="TRUE">
14 <META
15 NAME="GENERATOR"
16 CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
17 "><LINK
18 REL="HOME"
19 TITLE="eCos Reference Manual"
20 HREF="ecos-ref.html"><LINK
21 REL="UP"
22 TITLE="eCos Power Management Support"
23 HREF="services-power.html"><LINK
24 REL="PREVIOUS"
25 TITLE="Attached and Detached Controllers"
26 HREF="power-attached.html"><LINK
27 REL="NEXT"
28 TITLE="eCos USB Slave Support"
29 HREF="io-usb-slave.html"></HEAD
30 ><BODY
31 CLASS="REFENTRY"
32 BGCOLOR="#FFFFFF"
33 TEXT="#000000"
34 LINK="#0000FF"
35 VLINK="#840084"
36 ALINK="#0000FF"
37 ><DIV
38 CLASS="NAVHEADER"
39 ><TABLE
40 SUMMARY="Header navigation table"
41 WIDTH="100%"
42 BORDER="0"
43 CELLPADDING="0"
44 CELLSPACING="0"
45 ><TR
46 ><TH
47 COLSPAN="3"
48 ALIGN="center"
49 >eCos Reference Manual</TH
50 ></TR
51 ><TR
52 ><TD
53 WIDTH="10%"
54 ALIGN="left"
55 VALIGN="bottom"
56 ><A
57 HREF="power-attached.html"
58 ACCESSKEY="P"
59 >Prev</A
60 ></TD
61 ><TD
62 WIDTH="80%"
63 ALIGN="center"
64 VALIGN="bottom"
65 ></TD
66 ><TD
67 WIDTH="10%"
68 ALIGN="right"
69 VALIGN="bottom"
70 ><A
71 HREF="io-usb-slave.html"
72 ACCESSKEY="N"
73 >Next</A
74 ></TD
75 ></TR
76 ></TABLE
77 ><HR
78 ALIGN="LEFT"
79 WIDTH="100%"></DIV
80 ><H1
81 ><A
82 NAME="POWER-CONTROLLER">Implementing a Power Controller</H1
83 ><DIV
84 CLASS="REFNAMEDIV"
85 ><A
86 NAME="AEN15936"
87 ></A
88 ><H2
89 >Name</H2
90 >Implementing a Power Controller&nbsp;--&nbsp;adding power management support to device drivers and
91 other packages</DIV
92 ><DIV
93 CLASS="REFSECT1"
94 ><A
95 NAME="AEN15939"
96 ></A
97 ><H2
98 >Implementing a Power Controller</H2
99 ><P
100 >A system will have some number of power controllers. Usually there
101 will be one power controller for the cpu,
102 <TT
103 CLASS="VARNAME"
104 >power_controller_cpu</TT
105 >, typically provided by one of
106 the HAL packages and responsible for managing the processor itself and
107 associated critical components such as memory. Some or all of the
108 device drivers will provide power controllers, allowing the power
109 consumption of the associated devices to be controlled. There may be
110 some arbitrary number of other controllers present in the system. The
111 power management package does not impose any restrictions on the
112 number or nature of the power controllers in the system, other than
113 insisting that at most one <TT
114 CLASS="VARNAME"
115 >power_controller_cpu</TT
116 > be
117 provided.</P
118 ><P
119 >Each power controller involves a single data structure of type
120 <SPAN
121 CLASS="STRUCTNAME"
122 >PowerController</SPAN
123 >, defined in the header file
124 <TT
125 CLASS="FILENAME"
126 >cyg/power/power.h</TT
127 >. These data
128 structures should all be placed in the table
129 <TT
130 CLASS="LITERAL"
131 >__POWER__</TT
132 >, so that the power management package and
133 other code can easily locate all the controllers in the system. This
134 table is constructed at link-time, avoiding code-size or run-time
135 overheads. To facilitate this the package provides two macros which
136 should be used to define a power controller,
137 <TT
138 CLASS="LITERAL"
139 >POWER_CONTROLLER()</TT
140 > and
141 <TT
142 CLASS="LITERAL"
143 >POWER_CONTROLLER_CPU()</TT
144 >.</P
145 ><P
146 >The macro <TT
147 CLASS="LITERAL"
148 >POWER_CONTROLLER</TT
149 > takes four arguments:</P
150 ><P
151 ></P
152 ><OL
153 TYPE="1"
154 ><LI
155 ><P
156 >A variable name. This can be used to access the power controller
157 directly, as well as via the table.</P
158 ></LI
159 ><LI
160 ><P
161 >A priority. The table of power controllers is sorted, such that power
162 controllers with a numerically lower priority come earlier in the
163 table. The special controller <TT
164 CLASS="VARNAME"
165 >power_controller_cpu</TT
166 >
167 always comes at the end of the table. When moving from a high-power
168 mode to a lower-powered mode, the power management package iterates
169 through the table from front to back. When moving to a higher-powered
170 mode the reverse direction is used. The intention is that the power
171 controller for a software-only package such as a TCP/IP stack should
172 appear near the start of the table, whereas the controllers for the
173 ethernet and similar devices would be near the end of the table. Hence
174 when the policy module initiates a mode change to a lower-powered mode
175 the TCP/IP stack gets a chance to cancel this mode change, before the
176 devices it depends on are powered down. Similarly when moving to a
177 higher-powered mode the devices will be re-activated before any
178 software that depends on those devices.</P
179 ><P
180 >The header file <TT
181 CLASS="FILENAME"
182 >cyg/power/power.h</TT
183 > defines three
184 priorities <TT
185 CLASS="LITERAL"
186 >PowerPri_Early</TT
187 >,
188 <TT
189 CLASS="LITERAL"
190 >PowerPri_Typical</TT
191 > and
192 <TT
193 CLASS="LITERAL"
194 >PowerPri_Late</TT
195 >. For most controllers one of these
196 priorities, possibly with a small number added or subtracted, will
197 give sufficient control. If an application developer is uncertain
198 about the relative priorities of the various controllers, a simple
199 <A
200 HREF="power-info.html#POWER-INFO-IDS"
201 >test program</A
202 > that iterates over
203 the table will quickly eliminate any confusion.</P
204 ></LI
205 ><LI
206 ><P
207 >A constant string identifier. If the system has been configured
208 without support for such identifiers
209 (<TT
210 CLASS="VARNAME"
211 >CYGIMP_POWER_PROVIDE_STRINGS</TT
212 >) then this identifer
213 will be discarded at compile-time. Otherwise it will be made available
214 to higher-level code using the function
215 <TT
216 CLASS="FUNCTION"
217 >power_get_controller_id</TT
218 >. </P
219 ></LI
220 ><LI
221 ><P
222 >A function pointer. This will be invoked to perform actual mode
223 changes, as described below.</P
224 ></LI
225 ></OL
226 ><P
227 >A typical example of the use of the
228 <TT
229 CLASS="LITERAL"
230 >POWER_CONTROLLER</TT
231 > macro would be as follows:</P
232 ><TABLE
233 BORDER="5"
234 BGCOLOR="#E0E0F0"
235 WIDTH="70%"
236 ><TR
237 ><TD
238 ><PRE
239 CLASS="PROGRAMLISTING"
240 >#include &lt;pkgconf/system.h&gt;
241
242 #ifdef CYGPKG_POWER
243 # include &lt;cyg/power/power.h&gt;
244
245 static void
246 xyzzy_device_power_mode_change(
247     PowerController* controller,
248     PowerMode        desired_mode,
249     PowerModeChange  change)
250 {
251    // Do the work
252 }
253
254 static POWER_CONTROLLER(xyzzy_power_controller, \
255                         PowerPri_Late,          \
256                         "xyzzy device",         \
257                         &amp;xyzzy_device_power_mode_change);
258 #endif</PRE
259 ></TD
260 ></TR
261 ></TABLE
262 ><P
263 >This creates a variable <TT
264 CLASS="VARNAME"
265 >xyzzy_power_controller</TT
266 >,
267 which is a power controller data structure that will end up near the
268 end of the table of power controllers. Higher-level code can
269 iterate through this table and report the string <TT
270 CLASS="LITERAL"
271 >"xyzzy
272 device"</TT
273 > to the user. Whenever there is a mode change
274 operation that affects this controller, the function
275 <TT
276 CLASS="FUNCTION"
277 >xyzzy_device_power_mode_change</TT
278 > will be invoked.
279 The variable is declared static so this controller cannot be
280 manipulated by name in any other code. Alternatively, if the variable
281 had not been declared static other code could manipulate this
282 controller by name as well as through the table, especially if the
283 package for the xyzzy device driver explicitly declared this
284 variable in an exported header file. Obviously exporting the variable
285 involves a slight risk of a name clash at link time.</P
286 ><P
287 >The above code explicitly checks for the presence of the power
288 management package before including that package's header file or
289 providing any related functionality. Since power management
290 functionality is optional, such checks are recommended.</P
291 ><P
292 >The macro <TT
293 CLASS="LITERAL"
294 >POWER_CONTROLLER_CPU</TT
295 > only takes two
296 arguments, a string identifier and a mode change function pointer.
297 This macro always instantiates a variable
298 <TT
299 CLASS="VARNAME"
300 >power_controller_cpu</TT
301 > so there is no need to provide
302 a variable name. The resulting power controller structure always
303 appears at the end of the table, so there is no need to specify a
304 priority. Typical usage of the <TT
305 CLASS="LITERAL"
306 >POWER_CONTROLLER_CPU</TT
307 >
308 macro would be:</P
309 ><TABLE
310 BORDER="5"
311 BGCOLOR="#E0E0F0"
312 WIDTH="70%"
313 ><TR
314 ><TD
315 ><PRE
316 CLASS="PROGRAMLISTING"
317 >static void
318 wumpus_processor_power_mode_change(
319     PowerController* controller,
320     PowerMode        desired_mode,
321     PowerModeChange  change)
322 {
323    // Do the work
324 }
325
326 POWER_CONTROLLER_CPU("wumpus processor", \
327                      &amp;wumpus_processor_power_mode_change);</PRE
328 ></TD
329 ></TR
330 ></TABLE
331 ><P
332 >This defines a power controller structure
333 <TT
334 CLASS="VARNAME"
335 >power_controller_cpu</TT
336 >. It should not be declared
337 static since higher-level code may well want to manipulate the cpu's
338 power mode directly, and the variable is declared by the power
339 management package's header file.</P
340 ><P
341 >Some care has to be taken to ensure that the power controllers
342 actually end up in the final executable. If a power controller
343 variable ends up in an ordinary library and is never referenced
344 directly then typically the linker will believe that the variable is
345 not needed and it will not end up in the executable. For eCos packages
346 this can be achieved in the CDL, by specifying that the containing
347 source file should end up in <TT
348 CLASS="FILENAME"
349 >libextras.a</TT
350 > rather
351 than the default <TT
352 CLASS="FILENAME"
353 >libtarget.a</TT
354 >:</P
355 ><TABLE
356 BORDER="5"
357 BGCOLOR="#E0E0F0"
358 WIDTH="70%"
359 ><TR
360 ><TD
361 ><PRE
362 CLASS="PROGRAMLISTING"
363 >cdl_package CYGPKG_HAL_WUMPUS_ARCH {
364     &#8230;
365     compile -library=libextras.a data.c
366 }</PRE
367 ></TD
368 ></TR
369 ></TABLE
370 ><P
371 >If the file <TT
372 CLASS="FILENAME"
373 >data.c</TT
374 > instantiates a power
375 controller this is now guaranteed to end up in the final executable,
376 as intended. Typically HAL and device driver packages will already
377 have some data that must not be eliminated by the linker, so they will
378 already contain a file that gets built into
379 <TT
380 CLASS="FILENAME"
381 >libextras.a</TT
382 >. For power controllers defined inside
383 application code it is important that the power controllers end up in
384 <TT
385 CLASS="FILENAME"
386 >.o</TT
387 > object files rather than in
388 <TT
389 CLASS="FILENAME"
390 >.a</TT
391 > library archive files.</P
392 ><P
393 >All the real work of a power controller is done by the mode change
394 function. If the power management package has been configured to use a
395 separate thread then this mode change function will be invoked by that
396 thread (except for the special case of <A
397 HREF="power-change.html#POWER-CHANGE-CONTROLLER-NOW"
398 ><TT
399 CLASS="FUNCTION"
400 >power_set_controller_mode_now</TT
401 ></A
402 >). 
403 If no separate thread is used then the mode change function will be
404 invoked directly by <TT
405 CLASS="FUNCTION"
406 >power_set_mode</TT
407 > or
408 <TT
409 CLASS="FUNCTION"
410 >power_set_controller_mode</TT
411 >.</P
412 ><P
413 >The mode change function will be invoked with three arguments. The
414 first argument identifies the power controller. Usually this argument
415 is not actually required since a given mode change function will only
416 ever be invoked for a single power controller. For example,
417 <TT
418 CLASS="FUNCTION"
419 >xyzzy_device_power_mode_change</TT
420 > will only ever be
421 used in conjunction with <TT
422 CLASS="VARNAME"
423 >xyzzy_power_controller</TT
424 >.
425 However there may be some packages which contain multiple controllers,
426 all of which can share a single mode change function, and in that case
427 it is essential to identify the specific controller. The second
428 argument specifies the mode the controller should switch to, if
429 possible: it will be one of <TT
430 CLASS="LITERAL"
431 >PowerMode_Active</TT
432 >,
433 <TT
434 CLASS="LITERAL"
435 >PowerMode_Idle</TT
436 >, <TT
437 CLASS="LITERAL"
438 >PowerMode_Sleep</TT
439 >
440 or <TT
441 CLASS="LITERAL"
442 >PowerMode_Off</TT
443 >. The final argument will be one of
444 <TT
445 CLASS="LITERAL"
446 >PowerModeChange_Controller</TT
447 >,
448 PowerModeChange_ControllerNow, or
449 <TT
450 CLASS="LITERAL"
451 >PowerModeChange_Global</TT
452 >, and identifies the call
453 that caused this invocation. For example, if the mode change function
454 was invoked because of a call to <TT
455 CLASS="FUNCTION"
456 >power_set_mode</TT
457 >
458 then this argument will be <TT
459 CLASS="LITERAL"
460 >PowerModeChange_Global</TT
461 >.
462 It is up to each controller to decide how to interpret this final
463 argument. A typical controller might reject a global request to switch
464 to <SPAN
465 CLASS="TYPE"
466 >off</SPAN
467 > mode if the associated device is still busy, but
468 if the request was aimed specifically at this controller then it could
469 instead abort any current I/O operations and switch off the device.</P
470 ><P
471 >The <SPAN
472 CLASS="STRUCTNAME"
473 >PowerController</SPAN
474 > data structure contains
475 one field, <TT
476 CLASS="STRUCTFIELD"
477 ><I
478 >mode</I
479 ></TT
480 >, that needs to be updated
481 by the power mode change function. At all times it should indicate the
482 current mode for this controller. When a mode change is requested the
483 desired mode is passed as the second argument. The exact operation of
484 the power mode change function depends very much on what is being
485 controlled and the current circumstances, but some guidelines are
486 possible:</P
487 ><P
488 ></P
489 ><OL
490 TYPE="1"
491 ><LI
492 ><P
493 >If the request can be satisfied without obvious detriment, do so and
494 update the <TT
495 CLASS="STRUCTFIELD"
496 ><I
497 >mode</I
498 ></TT
499 > field. Reducing the power
500 consumption of a device that is not currently being used is generally
501 harmless.</P
502 ></LI
503 ><LI
504 ><P
505 >If a request is a no-op, for example if the system is switching
506 from <SPAN
507 CLASS="TYPE"
508 >idle</SPAN
509 > to <SPAN
510 CLASS="TYPE"
511 >sleep</SPAN
512 > mode and the controller
513 does not distinguish between these modes, simply act as if the request
514 was satisfied.</P
515 ></LI
516 ><LI
517 ><P
518 >If a request is felt to be unsafe, for example shutting down a
519 device that is still in use, then the controller may decide
520 to reject this request. This is especially true if the request was a
521 global mode change as opposed to one intended specifically for this
522 controller: in the latter case the policy module should be given due
523 deference. There are a number of ways in which a request can be
524 rejected:</P
525 ><P
526 ></P
527 ><OL
528 TYPE="a"
529 ><LI
530 ><P
531 >If the request cannot be satisfied immediately but may be feasible in
532 a short while, leave the <TT
533 CLASS="STRUCTFIELD"
534 ><I
535 >mode</I
536 ></TT
537 > field
538 unchanged. Higher-level code in the policy module can interpret this
539 as a hint to retry the operation a little bit later. This approach is
540 also useful if the mode change can be started but will take some time
541 to complete, for example shutting down a socket connection, and
542 additional processing will be needed later on.</P
543 ></LI
544 ><LI
545 ><P
546 >If the request is felt to be inappropriate, for example switching off
547 a device that is still in use, the mode change function can
548 call <TT
549 CLASS="FUNCTION"
550 >power_set_controller_mode</TT
551 > to reset the
552 desired mode for this controller back to the current mode.
553 Higher-level code can then interpret this as a hint that there is more
554 activity in the system than had been apparent.</P
555 ></LI
556 ><LI
557 ><P
558 >For a global mode change, if the new mode is felt to be inappropriate
559 then the power controller can call <TT
560 CLASS="FUNCTION"
561 >power_set_mode</TT
562 >
563 to indicate this. An example of this would be the policy module
564 deciding to switch off the whole unit while there is still I/O
565 activity.</P
566 ></LI
567 ></OL
568 ></LI
569 ></OL
570 ><P
571 >Mode change functions should not directly manipulate any other fields
572 in the <SPAN
573 CLASS="STRUCTNAME"
574 >PowerController</SPAN
575 > data structure. If it
576 is necessary to keep track of additional data then static variables
577 can be used.</P
578 ><P
579 >It should be noted that the above are only guidelines. Their
580 application in any given situation may be unclear. In addition the
581 detailed requirements of specific systems will vary, so even if the
582 power controller for a given device driver follows the above
583 guidelines exactly it may turn out that slightly different behaviour
584 would be more appropriate for the actual system that is being
585 developed. Fortunately the open source nature of
586 <SPAN
587 CLASS="PRODUCTNAME"
588 >eCos</SPAN
589 > allows system developers to fine-tune
590 power controllers to meet their exact requirements.</P
591 ></DIV
592 ><DIV
593 CLASS="NAVFOOTER"
594 ><HR
595 ALIGN="LEFT"
596 WIDTH="100%"><TABLE
597 SUMMARY="Footer navigation table"
598 WIDTH="100%"
599 BORDER="0"
600 CELLPADDING="0"
601 CELLSPACING="0"
602 ><TR
603 ><TD
604 WIDTH="33%"
605 ALIGN="left"
606 VALIGN="top"
607 ><A
608 HREF="power-attached.html"
609 ACCESSKEY="P"
610 >Prev</A
611 ></TD
612 ><TD
613 WIDTH="34%"
614 ALIGN="center"
615 VALIGN="top"
616 ><A
617 HREF="ecos-ref.html"
618 ACCESSKEY="H"
619 >Home</A
620 ></TD
621 ><TD
622 WIDTH="33%"
623 ALIGN="right"
624 VALIGN="top"
625 ><A
626 HREF="io-usb-slave.html"
627 ACCESSKEY="N"
628 >Next</A
629 ></TD
630 ></TR
631 ><TR
632 ><TD
633 WIDTH="33%"
634 ALIGN="left"
635 VALIGN="top"
636 >Attached and Detached Controllers</TD
637 ><TD
638 WIDTH="34%"
639 ALIGN="center"
640 VALIGN="top"
641 ><A
642 HREF="services-power.html"
643 ACCESSKEY="U"
644 >Up</A
645 ></TD
646 ><TD
647 WIDTH="33%"
648 ALIGN="right"
649 VALIGN="top"
650 >eCos USB Slave Support</TD
651 ></TR
652 ></TABLE
653 ></DIV
654 ></BODY
655 ></HTML
656 >