Re: [linux-pm] PowerOP Take 2 1/3: ARM OMAP1 platform support

2005-09-01 Thread David Brownell
> Date: Wed, 31 Aug 2005 20:05:02 -0700
> From: Todd Poynor <[EMAIL PROTECTED]>
>
> David Brownell wrote:
> > Interesting.  I start to like this shape better; it moves more of the
> > logic to operating point code, where it can make the sysfs interface
> > talk in terms of meaningful abstractions, not cryptic numeric offsets.
> > But it was odd to see the first patch be platform-specific support,
> > rather than be a neutral framework into which platform-aware code plugs
> > different kinds of things...
>
> Since it is at a low layer below a number of possible interfaces, and 
> since there is no generic processing performed at this low layer (it's 
> pretty much set or get an opaque structure), there isn't any 
> higher-layer framework to plug into at the moment.

You're presenting PowerOP as a multi-platform thing in its own right.
I think that's my missing "higher level framework".  Although given the
other two patches in this group, maybe it was the sysfs API?  :)


>   If something like 
> these abstractions of power parameters and operating points are felt to 
> be a good foundation for a runtime power management stack then turning 
> our attentions to the next layer up (perhaps cpufreq or a new 
> embedded-oriented stack) would create that generic structure.

Something like -- certainly.  I suspect what I'm thinking about as the
API-visible structure is what you might want to call a range of operating
points, not just a single one ... example, "any CPU rate, low voltage, with
audio and display off".

In that example, suppose there are five choices for the CPU clock setting.
One way defines a different point for each choice, leading to five times
as many states as the one that just says "doesn't matter".

Come to think of it, I'm not clear how you think device drivers (a common
generic structure!) would interact with changes to power constraints.
Would you see the display driver being responsible for turning its power on
and off?  Or would code that switches operating points handle that too?
Should drivers get "here's the next operating point" calls?


> > One part I don't like is that the platform would be limited to tweaking
> > a predefined set of fields in registers.  That seems insufficient for
> > subsystems that may not be present on all boards.  
>
> Yes, the code currently assumes it would be tweaked for different 
> variants of platforms, partly due to the difficulty of implementing a 
> lean and mean way of integrating the different pieces.

Surely at least drawing a line between the on-chip hardware and
the drivers for external stuff is simple enough, though.  This
current construction would make it hard to draw that line, since
there's no distinction between the SOC logic (potentially very
reusable) and the board specific details (often less so) including
discrete devices and their drivers.


>   It sounds like 
> registering multiple handlers for multiple sets of power parameters may 
> be in order, although a single opaque structure shared between upper 
> layers and the handlers probably won't be sufficient any more.

I'm not sure why you say either of those things.  Surely the point
of the "echo pointname >file" operation is to change several
power constraints at once?  And I don't think you've talked much
about the layers on either side of PowerOP ... except maybe to say
they should exist.  :)


>  > Plus, to borrow some
> > terms from cpufreq, it only facilitates "usermode" governor models, never
> > "ondemand" or any other efficient quick-response adaptive algorithms.
>
> The sysfs interface does not itself handle such schemes, but the PowerOP 
> layer is fine with inserting beneath in-kernel algorithms.  Low-latency, 
> very frequent adjustments to power parameters are very much in mind for 
> what I'm trying to do, assuming embedded hardware will increasingly be 
> able to take advantage of aggressive runtime power management for 
> battery savings.

So you see why I want the "thing" seen by userspace to cover a range
of power states:  otherwise those "very frequent" adjustments would
always involve userspace transition and scheduling delays.


> ...
> > Alternatively, the "thing" could implement some adaptive algorithm
> > using local measurements, predictions, and feedback to adjust any
> > platform power parameters dynamically.  Maybe it'd delegate management
> > of the ARM clock to "cpufreq", and focus on managing power for other
> > board components that might never get really reusable code.  Switching
> > between operating points wouldn't require userspace instruction;
> > call it a "dynamic operating point" selection model.
>
> Interesting, although such close coordination of changing various clocks 
> and voltages is required on some platforms that it would be hard to 
> distribute it much among kernel components.

Much less "usermode" ones.  ;)

There will certainly be globs of functionality on a given platform
that don't factor nicely, and demand more 

Re: [linux-pm] PowerOP Take 2 1/3: ARM OMAP1 platform support

2005-09-01 Thread David Brownell
 Date: Wed, 31 Aug 2005 20:05:02 -0700
 From: Todd Poynor [EMAIL PROTECTED]

 David Brownell wrote:
  Interesting.  I start to like this shape better; it moves more of the
  logic to operating point code, where it can make the sysfs interface
  talk in terms of meaningful abstractions, not cryptic numeric offsets.
  But it was odd to see the first patch be platform-specific support,
  rather than be a neutral framework into which platform-aware code plugs
  different kinds of things...

 Since it is at a low layer below a number of possible interfaces, and 
 since there is no generic processing performed at this low layer (it's 
 pretty much set or get an opaque structure), there isn't any 
 higher-layer framework to plug into at the moment.

You're presenting PowerOP as a multi-platform thing in its own right.
I think that's my missing higher level framework.  Although given the
other two patches in this group, maybe it was the sysfs API?  :)


   If something like 
 these abstractions of power parameters and operating points are felt to 
 be a good foundation for a runtime power management stack then turning 
 our attentions to the next layer up (perhaps cpufreq or a new 
 embedded-oriented stack) would create that generic structure.

Something like -- certainly.  I suspect what I'm thinking about as the
API-visible structure is what you might want to call a range of operating
points, not just a single one ... example, any CPU rate, low voltage, with
audio and display off.

In that example, suppose there are five choices for the CPU clock setting.
One way defines a different point for each choice, leading to five times
as many states as the one that just says doesn't matter.

Come to think of it, I'm not clear how you think device drivers (a common
generic structure!) would interact with changes to power constraints.
Would you see the display driver being responsible for turning its power on
and off?  Or would code that switches operating points handle that too?
Should drivers get here's the next operating point calls?


  One part I don't like is that the platform would be limited to tweaking
  a predefined set of fields in registers.  That seems insufficient for
  subsystems that may not be present on all boards.  

 Yes, the code currently assumes it would be tweaked for different 
 variants of platforms, partly due to the difficulty of implementing a 
 lean and mean way of integrating the different pieces.

Surely at least drawing a line between the on-chip hardware and
the drivers for external stuff is simple enough, though.  This
current construction would make it hard to draw that line, since
there's no distinction between the SOC logic (potentially very
reusable) and the board specific details (often less so) including
discrete devices and their drivers.


   It sounds like 
 registering multiple handlers for multiple sets of power parameters may 
 be in order, although a single opaque structure shared between upper 
 layers and the handlers probably won't be sufficient any more.

I'm not sure why you say either of those things.  Surely the point
of the echo pointname file operation is to change several
power constraints at once?  And I don't think you've talked much
about the layers on either side of PowerOP ... except maybe to say
they should exist.  :)


   Plus, to borrow some
  terms from cpufreq, it only facilitates usermode governor models, never
  ondemand or any other efficient quick-response adaptive algorithms.

 The sysfs interface does not itself handle such schemes, but the PowerOP 
 layer is fine with inserting beneath in-kernel algorithms.  Low-latency, 
 very frequent adjustments to power parameters are very much in mind for 
 what I'm trying to do, assuming embedded hardware will increasingly be 
 able to take advantage of aggressive runtime power management for 
 battery savings.

So you see why I want the thing seen by userspace to cover a range
of power states:  otherwise those very frequent adjustments would
always involve userspace transition and scheduling delays.


 ...
  Alternatively, the thing could implement some adaptive algorithm
  using local measurements, predictions, and feedback to adjust any
  platform power parameters dynamically.  Maybe it'd delegate management
  of the ARM clock to cpufreq, and focus on managing power for other
  board components that might never get really reusable code.  Switching
  between operating points wouldn't require userspace instruction;
  call it a dynamic operating point selection model.

 Interesting, although such close coordination of changing various clocks 
 and voltages is required on some platforms that it would be hard to 
 distribute it much among kernel components.

Much less usermode ones.  ;)

There will certainly be globs of functionality on a given platform
that don't factor nicely, and demand more monolithic approaches.
Groups of interrelated clocks seem to give good examples.

Then there will be other 

Re: [linux-pm] PowerOP Take 2 1/3: ARM OMAP1 platform support

2005-08-31 Thread Todd Poynor

David Brownell wrote:

Interesting.  I start to like this shape better; it moves more of the
logic to operating point code, where it can make the sysfs interface
talk in terms of meaningful abstractions, not cryptic numeric offsets.
But it was odd to see the first patch be platform-specific support,
rather than be a neutral framework into which platform-aware code plugs
different kinds of things...


Since it is at a low layer below a number of possible interfaces, and 
since there is no generic processing performed at this low layer (it's 
pretty much set or get an opaque structure), there isn't any 
higher-layer framework to plug into at the moment.  If something like 
these abstractions of power parameters and operating points are felt to 
be a good foundation for a runtime power management stack then turning 
our attentions to the next layer up (perhaps cpufreq or a new 
embedded-oriented stack) would create that generic structure.


Its worth noting that newer embedded SOCs are coming up with such 
complicated clocking structures and rules for setting and switching 
operating points that some silicon vendors are starting to provide code 
at approximately the PowerOP level for their platforms, to plug into 
different upper-layer power management stacks (and possibly different 
open source OSes).  So there may be some value to settling on common 
interfaces for this.



One part I don't like is that the platform would be limited to tweaking
a predefined set of fields in registers.  That seems insufficient for
subsystems that may not be present on all boards.  


Yes, the code currently assumes it would be tweaked for different 
variants of platforms, partly due to the difficulty of implementing a 
lean and mean way of integrating the different pieces.  It sounds like 
registering multiple handlers for multiple sets of power parameters may 
be in order, although a single opaque structure shared between upper 
layers and the handlers probably won't be sufficient any more.  If the 
operating point data structure basically goes away and sysfs becomes the 
preferred interface then it should be fairly straightforward to discover 
what PM capabilities are registered and to get/set the associated power 
param attributes.  Otherwise in-kernel interfaces might need some 
further thought to specify something that routes to the proper handler.


> Plus, to borrow some

terms from cpufreq, it only facilitates "usermode" governor models, never
"ondemand" or any other efficient quick-response adaptive algorithms.


The sysfs interface does not itself handle such schemes, but the PowerOP 
layer is fine with inserting beneath in-kernel algorithms.  Low-latency, 
very frequent adjustments to power parameters are very much in mind for 
what I'm trying to do, assuming embedded hardware will increasingly be 
able to take advantage of aggressive runtime power management for 
battery savings.  (Much of this is driven by how embedded hardware can 
most aggressively but usefully be power managed, and it would be nice to 
get those folks more involved.)  What DPM does with approximately the 
same type of interface is setup some operating points and policies for 
which operating point is appropriate in which situations, and then kick 
off a kernel state machine that handles the transitions.


...

Alternatively, the "thing" could implement some adaptive algorithm
using local measurements, predictions, and feedback to adjust any
platform power parameters dynamically.  Maybe it'd delegate management
of the ARM clock to "cpufreq", and focus on managing power for other
board components that might never get really reusable code.  Switching
between operating points wouldn't require userspace instruction;
call it a "dynamic operating point" selection model.


Interesting, although such close coordination of changing various clocks 
and voltages is required on some platforms that it would be hard to 
distribute it much among kernel components.  To some degree the above is 
how DPM functions: some policy instructions are sent to the kernel and 
the kernel switches operating points accordingly.  Something more 
flexible than operating points could be specified in the policy info, 
possibly even something as abstract as "battery low", pushing the 
interpretation of high-level power policy into kernel components instead 
of a userspace app giving the kernel low-level instructions.



The DSP clock might benefit from some support though.  I've never
much looked at this, beyond noting that SPUs on CELL should have
similar issues.  Wouldn't it be nice to have "ondemand" style
governors for DSPs or SPUs?  That's got to be easy. ;)


So far as I understand, Linux-coordinated power management of the DSP 
side of dual-core general-purpose + DSP platforms is often handled by a 
Linux driver that knows how to talk to whatever it is that runs on the 
DSP (such as via shared memory message libs from the silicon vendor). 
Soon the other core will be 

Re: [linux-pm] PowerOP Take 2 1/3: ARM OMAP1 platform support

2005-08-31 Thread Todd Poynor

David Brownell wrote:

Interesting.  I start to like this shape better; it moves more of the
logic to operating point code, where it can make the sysfs interface
talk in terms of meaningful abstractions, not cryptic numeric offsets.
But it was odd to see the first patch be platform-specific support,
rather than be a neutral framework into which platform-aware code plugs
different kinds of things...


Since it is at a low layer below a number of possible interfaces, and 
since there is no generic processing performed at this low layer (it's 
pretty much set or get an opaque structure), there isn't any 
higher-layer framework to plug into at the moment.  If something like 
these abstractions of power parameters and operating points are felt to 
be a good foundation for a runtime power management stack then turning 
our attentions to the next layer up (perhaps cpufreq or a new 
embedded-oriented stack) would create that generic structure.


Its worth noting that newer embedded SOCs are coming up with such 
complicated clocking structures and rules for setting and switching 
operating points that some silicon vendors are starting to provide code 
at approximately the PowerOP level for their platforms, to plug into 
different upper-layer power management stacks (and possibly different 
open source OSes).  So there may be some value to settling on common 
interfaces for this.



One part I don't like is that the platform would be limited to tweaking
a predefined set of fields in registers.  That seems insufficient for
subsystems that may not be present on all boards.  


Yes, the code currently assumes it would be tweaked for different 
variants of platforms, partly due to the difficulty of implementing a 
lean and mean way of integrating the different pieces.  It sounds like 
registering multiple handlers for multiple sets of power parameters may 
be in order, although a single opaque structure shared between upper 
layers and the handlers probably won't be sufficient any more.  If the 
operating point data structure basically goes away and sysfs becomes the 
preferred interface then it should be fairly straightforward to discover 
what PM capabilities are registered and to get/set the associated power 
param attributes.  Otherwise in-kernel interfaces might need some 
further thought to specify something that routes to the proper handler.


 Plus, to borrow some

terms from cpufreq, it only facilitates usermode governor models, never
ondemand or any other efficient quick-response adaptive algorithms.


The sysfs interface does not itself handle such schemes, but the PowerOP 
layer is fine with inserting beneath in-kernel algorithms.  Low-latency, 
very frequent adjustments to power parameters are very much in mind for 
what I'm trying to do, assuming embedded hardware will increasingly be 
able to take advantage of aggressive runtime power management for 
battery savings.  (Much of this is driven by how embedded hardware can 
most aggressively but usefully be power managed, and it would be nice to 
get those folks more involved.)  What DPM does with approximately the 
same type of interface is setup some operating points and policies for 
which operating point is appropriate in which situations, and then kick 
off a kernel state machine that handles the transitions.


...

Alternatively, the thing could implement some adaptive algorithm
using local measurements, predictions, and feedback to adjust any
platform power parameters dynamically.  Maybe it'd delegate management
of the ARM clock to cpufreq, and focus on managing power for other
board components that might never get really reusable code.  Switching
between operating points wouldn't require userspace instruction;
call it a dynamic operating point selection model.


Interesting, although such close coordination of changing various clocks 
and voltages is required on some platforms that it would be hard to 
distribute it much among kernel components.  To some degree the above is 
how DPM functions: some policy instructions are sent to the kernel and 
the kernel switches operating points accordingly.  Something more 
flexible than operating points could be specified in the policy info, 
possibly even something as abstract as battery low, pushing the 
interpretation of high-level power policy into kernel components instead 
of a userspace app giving the kernel low-level instructions.



The DSP clock might benefit from some support though.  I've never
much looked at this, beyond noting that SPUs on CELL should have
similar issues.  Wouldn't it be nice to have ondemand style
governors for DSPs or SPUs?  That's got to be easy. ;)


So far as I understand, Linux-coordinated power management of the DSP 
side of dual-core general-purpose + DSP platforms is often handled by a 
Linux driver that knows how to talk to whatever it is that runs on the 
DSP (such as via shared memory message libs from the silicon vendor). 
Soon the other core will be running Linux as 

Re: [linux-pm] PowerOP Take 2 1/3: ARM OMAP1 platform support

2005-08-30 Thread David Brownell
Interesting.  I start to like this shape better; it moves more of the
logic to operating point code, where it can make the sysfs interface
talk in terms of meaningful abstractions, not cryptic numeric offsets.
But it was odd to see the first patch be platform-specific support,
rather than be a neutral framework into which platform-aware code plugs
different kinds of things...

One part I don't like is that the platform would be limited to tweaking
a predefined set of fields in registers.  That seems insufficient for
subsystems that may not be present on all boards.  Plus, to borrow some
terms from cpufreq, it only facilitates "usermode" governor models, never
"ondemand" or any other efficient quick-response adaptive algorithms.

The PM modules I imagine loading would define things that look more like:

struct thing {
char thing[THING_NAME_LEN];

/* there'd be sysfs hooks here
 *  - the thing's directory node (kobject)
 *  - array of attributes and matching get/set code
 *  - ... memory management fun too ...
 */

/* these wrap all relevant platform-specific knowledge: */
int (*set_thing)(struct thing *);
void*data;
};

That "data" could maybe be values directly matching your predefined
list of registers on the SOC ... or it could start with them, then add
stuff specific to a given board.  (Of course it would provide its own
sysfs API.)   Let's call that the "static operating point" model.

Alternatively, the "thing" could implement some adaptive algorithm
using local measurements, predictions, and feedback to adjust any
platform power parameters dynamically.  Maybe it'd delegate management
of the ARM clock to "cpufreq", and focus on managing power for other
board components that might never get really reusable code.  Switching
between operating points wouldn't require userspace instruction;
call it a "dynamic operating point" selection model.



> Date: Wed, 24 Aug 2005 19:53:57 -0700
> From: Todd Poynor <[EMAIL PROTECTED]>
>
> PowerOP support for OMAP1 platforms.  Currently handles these power
> parameters:
>
>dpllmult   DPLL_CTL reg PLL MULT bits
>dplldivDPLL_CTL reg PLL DIV bits
>armdiv ARM_CKCTL reg ARMDIV bits
>dspdiv ARM_CKCTL reg DSPDIV bits

The ARM clock is already managed by arch/arm/plat-omap/clocks.c,
which is used by cpufreq through whatever governor is active.
This would just be another kind of "usermode" governor.

The DSP clock might benefit from some support though.  I've never
much looked at this, beyond noting that SPUs on CELL should have
similar issues.  Wouldn't it be nice to have "ondemand" style
governors for DSPs or SPUs?  That's got to be easy. ;)


>tcdiv  ARM_CKCTL reg TCDIV bits

Affecting bandwidth on one of the main I/O busses ... does the
PC world usually change things like that outside of maybe in
BIOS/ACPI PM code?


>lowpwr 1 = assert ULPD LOW_PWR, voltage scale low

Could you describe the policy effect of this bit?  I suspect
a good "PCs don't work like that!" example is lurking here.
That interacts with some other bits, and code ... when would
setting this be good, or bad?


> Other parameters such as DSPMMUDIV, LCDDIV, and ARM_PERDIV might also be
> useful.

Again, PERDIV changes would need to involve clock.c to cascade
the changes through the clock tree.  Change PERDIV and you'll
need to recalculate the peripheral clocks that derive from it...
better not do it while an I/O operation is actively using it!

As with TCDIV, that makes a useful example of something that is
clearly not within the "cpufreq" domain.  

- Dave


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [linux-pm] PowerOP Take 2 1/3: ARM OMAP1 platform support

2005-08-30 Thread David Brownell
Interesting.  I start to like this shape better; it moves more of the
logic to operating point code, where it can make the sysfs interface
talk in terms of meaningful abstractions, not cryptic numeric offsets.
But it was odd to see the first patch be platform-specific support,
rather than be a neutral framework into which platform-aware code plugs
different kinds of things...

One part I don't like is that the platform would be limited to tweaking
a predefined set of fields in registers.  That seems insufficient for
subsystems that may not be present on all boards.  Plus, to borrow some
terms from cpufreq, it only facilitates usermode governor models, never
ondemand or any other efficient quick-response adaptive algorithms.

The PM modules I imagine loading would define things that look more like:

struct thing {
char thing[THING_NAME_LEN];

/* there'd be sysfs hooks here
 *  - the thing's directory node (kobject)
 *  - array of attributes and matching get/set code
 *  - ... memory management fun too ...
 */

/* these wrap all relevant platform-specific knowledge: */
int (*set_thing)(struct thing *);
void*data;
};

That data could maybe be values directly matching your predefined
list of registers on the SOC ... or it could start with them, then add
stuff specific to a given board.  (Of course it would provide its own
sysfs API.)   Let's call that the static operating point model.

Alternatively, the thing could implement some adaptive algorithm
using local measurements, predictions, and feedback to adjust any
platform power parameters dynamically.  Maybe it'd delegate management
of the ARM clock to cpufreq, and focus on managing power for other
board components that might never get really reusable code.  Switching
between operating points wouldn't require userspace instruction;
call it a dynamic operating point selection model.



 Date: Wed, 24 Aug 2005 19:53:57 -0700
 From: Todd Poynor [EMAIL PROTECTED]

 PowerOP support for OMAP1 platforms.  Currently handles these power
 parameters:

dpllmult   DPLL_CTL reg PLL MULT bits
dplldivDPLL_CTL reg PLL DIV bits
armdiv ARM_CKCTL reg ARMDIV bits
dspdiv ARM_CKCTL reg DSPDIV bits

The ARM clock is already managed by arch/arm/plat-omap/clocks.c,
which is used by cpufreq through whatever governor is active.
This would just be another kind of usermode governor.

The DSP clock might benefit from some support though.  I've never
much looked at this, beyond noting that SPUs on CELL should have
similar issues.  Wouldn't it be nice to have ondemand style
governors for DSPs or SPUs?  That's got to be easy. ;)


tcdiv  ARM_CKCTL reg TCDIV bits

Affecting bandwidth on one of the main I/O busses ... does the
PC world usually change things like that outside of maybe in
BIOS/ACPI PM code?


lowpwr 1 = assert ULPD LOW_PWR, voltage scale low

Could you describe the policy effect of this bit?  I suspect
a good PCs don't work like that! example is lurking here.
That interacts with some other bits, and code ... when would
setting this be good, or bad?


 Other parameters such as DSPMMUDIV, LCDDIV, and ARM_PERDIV might also be
 useful.

Again, PERDIV changes would need to involve clock.c to cascade
the changes through the clock tree.  Change PERDIV and you'll
need to recalculate the peripheral clocks that derive from it...
better not do it while an I/O operation is actively using it!

As with TCDIV, that makes a useful example of something that is
clearly not within the cpufreq domain.  

- Dave


-
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


PowerOP Take 2 1/3: ARM OMAP1 platform support

2005-08-24 Thread Todd Poynor
PowerOP support for OMAP1 platforms.  Currently handles these power
parameters:

   dpllmult DPLL_CTL reg PLL MULT bits
   dplldiv  DPLL_CTL reg PLL DIV bits
   armdiv   ARM_CKCTL reg ARMDIV bits
   dspdiv   ARM_CKCTL reg DSPDIV bits
   tcdivARM_CKCTL reg TCDIV bits
   lowpwr   1 = assert ULPD LOW_PWR, voltage scale low

Other parameters such as DSPMMUDIV, LCDDIV, and ARM_PERDIV might also be
useful.

Example usage will be shown with a follow-on sysfs UI patch.

Index: linux-2.6.13-rc4/arch/arm/mach-omap1/powerop.c
===
--- /dev/null
+++ linux-2.6.13-rc4/arch/arm/mach-omap1/powerop.c
@@ -0,0 +1,157 @@
+/*
+ * PowerOP support for OMAP1
+ *
+ * Based on DPM OMAP code by Matthew Locke, Dmitry Chigirev, Vladimir
+ * Barinov, and Todd Poynor.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+
+/* ARM_CKCTL bit shifts */
+#define CKCTL_PERDIV_OFFSET0
+#define CKCTL_LCDDIV_OFFSET2
+#define CKCTL_ARMDIV_OFFSET4
+#define CKCTL_DSPDIV_OFFSET6
+#define CKCTL_TCDIV_OFFSET 8
+#define CKCTL_DSPMMUDIV_OFFSET 10
+
+#define DPLL_CTL_MASK  0xfe0
+
+#define ULPD_MIN_MAX_REG (1 << 11)
+#define ULPD_DVS_ENABLE  (1 << 10)
+#define ULPD_LOW_PWR_REQ (1 << 1)
+#define LOW_POWER (ULPD_MIN_MAX_REG | ULPD_DVS_ENABLE | ULPD_LOW_PWR_REQ | \
+  ULPD_LOW_PWR_EN)
+
+int
+powerop_get_point(struct powerop_point *point)
+{
+   unsigned long flags;
+   int dpll_ctl, arm_cktl;
+
+   local_irq_save(flags);
+   dpll_ctl = omap_readw(DPLL_CTL);
+   arm_cktl = omap_readw(ARM_CKCTL);
+
+   point->dpllmult = dpll_ctl >> 7 & 0x1f;
+   point->dplldiv = dpll_ctl >> 5 & 0x3;
+   point->armdiv = arm_cktl >> CKCTL_ARMDIV_OFFSET & 0x3;
+   point->dspdiv = arm_cktl >> CKCTL_DSPDIV_OFFSET & 0x3;
+   point->tcdiv = arm_cktl >> CKCTL_TCDIV_OFFSET & 0x3;
+   point->lowpwr = (omap_readw(ULPD_POWER_CTRL) & (ULPD_LOW_PWR_REQ)) ?
+   1 : 0;
+   local_irq_restore(flags);
+   return 0;
+}
+
+static void scale_dpll(int dpll_ctl)
+{
+   int i;
+
+   omap_writew((omap_readw(DPLL_CTL) & ~DPLL_CTL_MASK) | dpll_ctl,
+   DPLL_CTL);
+
+   for (i = 0; i < 0x1FF; i++)
+   nop();
+
+   /*
+* Wait for PLL relock.
+*/
+
+   while ((omap_readw(DPLL_CTL) & 0x1) == 0);
+}
+
+static void set_low_pwr(int lowpwr)
+{
+   int cur_lowpwr;
+
+   if (lowpwr == -1)
+   return;
+
+   cur_lowpwr = (omap_readw(ULPD_POWER_CTRL) & (ULPD_LOW_PWR_REQ)) ?
+   1 : 0;
+
+   if (cur_lowpwr != lowpwr) {
+   if (lowpwr)
+   omap_writew(omap_readw(ULPD_POWER_CTRL) | LOW_POWER,
+   ULPD_POWER_CTRL);
+   else
+   omap_writew(omap_readw(ULPD_POWER_CTRL) & ~LOW_POWER,
+   ULPD_POWER_CTRL);
+   }
+}
+
+int
+powerop_set_point(struct powerop_point *point)
+{
+   int dpll_ctl = 0;
+   int dpll_mod = 0;
+   int arm_ctl = 0;
+   int arm_msk = 0;
+   int cur_dpll_ctl;
+   unsigned long flags;
+
+   if ((point->dpllmult != -1) && (point->dplldiv != -1)) {
+   dpll_ctl = (point->dpllmult << 7) |
+   (point->dplldiv << 5);
+   dpll_mod = 1;
+   }
+
+   if (point->armdiv != -1) {
+   arm_ctl |= (point->armdiv << CKCTL_ARMDIV_OFFSET);
+   arm_msk |= (3 << CKCTL_ARMDIV_OFFSET);
+   }
+
+   if (point->dspdiv != -1) {
+   arm_ctl |= (point->dspdiv << CKCTL_DSPDIV_OFFSET);
+   arm_msk |= (3 << CKCTL_DSPDIV_OFFSET);
+   }
+
+   if (point->tcdiv != -1) {
+   arm_ctl |= (point->tcdiv << CKCTL_TCDIV_OFFSET);
+   arm_msk |= (3 << CKCTL_TCDIV_OFFSET);
+   }
+
+   local_irq_save(flags);
+   cur_dpll_ctl = omap_readw(DPLL_CTL) & DPLL_CTL_MASK;
+
+   if (dpll_mod && (dpll_ctl < cur_dpll_ctl))
+   scale_dpll(dpll_ctl);
+
+   if (arm_msk != 0)
+   omap_writew((omap_readw(ARM_CKCTL) & ~arm_msk) | arm_ctl,
+   ARM_CKCTL);
+
+   if (dpll_mod && (dpll_ctl > cur_dpll_ctl))
+   scale_dpll(dpll_ctl);
+
+   set_low_pwr(point->lowpwr);
+   local_irq_restore(flags);
+   return 0;
+}
+
+EXPORT_SYMBOL_GPL(powerop_get_point);
+EXPORT_SYMBOL_GPL(powerop_set_point);
+
+static int __init powerop_init(void)
+{
+   return 0;
+}
+
+static void __exit powerop_exit(void)
+{
+}
+
+module_init(powerop_init);
+module_exit(powerop_exit);
Index: linux-2.6.13-rc4/include/asm-arm/arch-omap/powerop.h

PowerOP Take 2 1/3: ARM OMAP1 platform support

2005-08-24 Thread Todd Poynor
PowerOP support for OMAP1 platforms.  Currently handles these power
parameters:

   dpllmult DPLL_CTL reg PLL MULT bits
   dplldiv  DPLL_CTL reg PLL DIV bits
   armdiv   ARM_CKCTL reg ARMDIV bits
   dspdiv   ARM_CKCTL reg DSPDIV bits
   tcdivARM_CKCTL reg TCDIV bits
   lowpwr   1 = assert ULPD LOW_PWR, voltage scale low

Other parameters such as DSPMMUDIV, LCDDIV, and ARM_PERDIV might also be
useful.

Example usage will be shown with a follow-on sysfs UI patch.

Index: linux-2.6.13-rc4/arch/arm/mach-omap1/powerop.c
===
--- /dev/null
+++ linux-2.6.13-rc4/arch/arm/mach-omap1/powerop.c
@@ -0,0 +1,157 @@
+/*
+ * PowerOP support for OMAP1
+ *
+ * Based on DPM OMAP code by Matthew Locke, Dmitry Chigirev, Vladimir
+ * Barinov, and Todd Poynor.
+ *
+ * 2005 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed as is without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include linux/module.h
+#include linux/errno.h
+#include linux/init.h
+
+#include asm/arch/powerop.h
+#include asm/hardware.h
+#include asm/arch/pm.h
+
+/* ARM_CKCTL bit shifts */
+#define CKCTL_PERDIV_OFFSET0
+#define CKCTL_LCDDIV_OFFSET2
+#define CKCTL_ARMDIV_OFFSET4
+#define CKCTL_DSPDIV_OFFSET6
+#define CKCTL_TCDIV_OFFSET 8
+#define CKCTL_DSPMMUDIV_OFFSET 10
+
+#define DPLL_CTL_MASK  0xfe0
+
+#define ULPD_MIN_MAX_REG (1  11)
+#define ULPD_DVS_ENABLE  (1  10)
+#define ULPD_LOW_PWR_REQ (1  1)
+#define LOW_POWER (ULPD_MIN_MAX_REG | ULPD_DVS_ENABLE | ULPD_LOW_PWR_REQ | \
+  ULPD_LOW_PWR_EN)
+
+int
+powerop_get_point(struct powerop_point *point)
+{
+   unsigned long flags;
+   int dpll_ctl, arm_cktl;
+
+   local_irq_save(flags);
+   dpll_ctl = omap_readw(DPLL_CTL);
+   arm_cktl = omap_readw(ARM_CKCTL);
+
+   point-dpllmult = dpll_ctl  7  0x1f;
+   point-dplldiv = dpll_ctl  5  0x3;
+   point-armdiv = arm_cktl  CKCTL_ARMDIV_OFFSET  0x3;
+   point-dspdiv = arm_cktl  CKCTL_DSPDIV_OFFSET  0x3;
+   point-tcdiv = arm_cktl  CKCTL_TCDIV_OFFSET  0x3;
+   point-lowpwr = (omap_readw(ULPD_POWER_CTRL)  (ULPD_LOW_PWR_REQ)) ?
+   1 : 0;
+   local_irq_restore(flags);
+   return 0;
+}
+
+static void scale_dpll(int dpll_ctl)
+{
+   int i;
+
+   omap_writew((omap_readw(DPLL_CTL)  ~DPLL_CTL_MASK) | dpll_ctl,
+   DPLL_CTL);
+
+   for (i = 0; i  0x1FF; i++)
+   nop();
+
+   /*
+* Wait for PLL relock.
+*/
+
+   while ((omap_readw(DPLL_CTL)  0x1) == 0);
+}
+
+static void set_low_pwr(int lowpwr)
+{
+   int cur_lowpwr;
+
+   if (lowpwr == -1)
+   return;
+
+   cur_lowpwr = (omap_readw(ULPD_POWER_CTRL)  (ULPD_LOW_PWR_REQ)) ?
+   1 : 0;
+
+   if (cur_lowpwr != lowpwr) {
+   if (lowpwr)
+   omap_writew(omap_readw(ULPD_POWER_CTRL) | LOW_POWER,
+   ULPD_POWER_CTRL);
+   else
+   omap_writew(omap_readw(ULPD_POWER_CTRL)  ~LOW_POWER,
+   ULPD_POWER_CTRL);
+   }
+}
+
+int
+powerop_set_point(struct powerop_point *point)
+{
+   int dpll_ctl = 0;
+   int dpll_mod = 0;
+   int arm_ctl = 0;
+   int arm_msk = 0;
+   int cur_dpll_ctl;
+   unsigned long flags;
+
+   if ((point-dpllmult != -1)  (point-dplldiv != -1)) {
+   dpll_ctl = (point-dpllmult  7) |
+   (point-dplldiv  5);
+   dpll_mod = 1;
+   }
+
+   if (point-armdiv != -1) {
+   arm_ctl |= (point-armdiv  CKCTL_ARMDIV_OFFSET);
+   arm_msk |= (3  CKCTL_ARMDIV_OFFSET);
+   }
+
+   if (point-dspdiv != -1) {
+   arm_ctl |= (point-dspdiv  CKCTL_DSPDIV_OFFSET);
+   arm_msk |= (3  CKCTL_DSPDIV_OFFSET);
+   }
+
+   if (point-tcdiv != -1) {
+   arm_ctl |= (point-tcdiv  CKCTL_TCDIV_OFFSET);
+   arm_msk |= (3  CKCTL_TCDIV_OFFSET);
+   }
+
+   local_irq_save(flags);
+   cur_dpll_ctl = omap_readw(DPLL_CTL)  DPLL_CTL_MASK;
+
+   if (dpll_mod  (dpll_ctl  cur_dpll_ctl))
+   scale_dpll(dpll_ctl);
+
+   if (arm_msk != 0)
+   omap_writew((omap_readw(ARM_CKCTL)  ~arm_msk) | arm_ctl,
+   ARM_CKCTL);
+
+   if (dpll_mod  (dpll_ctl  cur_dpll_ctl))
+   scale_dpll(dpll_ctl);
+
+   set_low_pwr(point-lowpwr);
+   local_irq_restore(flags);
+   return 0;
+}
+
+EXPORT_SYMBOL_GPL(powerop_get_point);
+EXPORT_SYMBOL_GPL(powerop_set_point);
+
+static int __init powerop_init(void)
+{
+   return 0;
+}
+
+static void __exit powerop_exit(void)
+{
+}
+
+module_init(powerop_init);
+module_exit(powerop_exit);
Index: linux-2.6.13-rc4/include/asm-arm/arch-omap/powerop.h