summaryrefslogtreecommitdiff
path: root/packages/linux/linux-omap2-git
diff options
context:
space:
mode:
authorKoen Kooi <koen@openembedded.org>2008-08-11 14:39:50 +0000
committerKoen Kooi <koen@openembedded.org>2008-08-11 14:39:50 +0000
commit5cf49c96a744508ff2dcbb49c86f709096a8f39e (patch)
tree850f3df66d7d20d364dc556fcb80460063bedc23 /packages/linux/linux-omap2-git
parent37ccaf6d05e4f962d4d7eab0e7b00179b409e64c (diff)
linux-omap2 git: check in WIP cpufreq patches for beagleboard
Diffstat (limited to 'packages/linux/linux-omap2-git')
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/01-beagle-cpufreq.diff178
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/01-omap3-cpufreq.eml319
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/01-omappm-srf.eml513
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/01-postrate-notifier.eml392
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/02-beagle_use_gptimer1238
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/02-omappm-mpu-latency-modeling.eml245
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/02-postrate-notifier.eml186
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/03-omappm-omap3srf.eml167
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/04-omappm-srf-noop.eml497
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/05-omappm-virtualclocks.eml456
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/06-omappm-opp-resource-modeling.eml228
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/07-omappm-srf-updates.eml173
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/08-omappm-voltagescaling.eml96
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/09-omappm-vdd2-scaling.eml102
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/10-omappm-off-mode.eml35
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/defconfig18
-rw-r--r--packages/linux/linux-omap2-git/beagleboard/omap23-pm-noop.eml894
17 files changed, 4530 insertions, 7 deletions
diff --git a/packages/linux/linux-omap2-git/beagleboard/01-beagle-cpufreq.diff b/packages/linux/linux-omap2-git/beagleboard/01-beagle-cpufreq.diff
new file mode 100644
index 0000000000..5343f3276b
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/01-beagle-cpufreq.diff
@@ -0,0 +1,178 @@
+--- /tmp/board-omap3beagle.h 2008-08-11 15:40:17.000000000 +0200
++++ git/include/asm-arm/arch-omap/board-omap3beagle.h 2008-08-11 15:41:32.433198000 +0200
+@@ -29,5 +29,41 @@
+ #ifndef __ASM_ARCH_OMAP3_BEAGLE_H
+ #define __ASM_ARCH_OMAP3_BEAGLE_H
+
++/* MPU speeds */
++#define S600M 600000000
++#define S550M 550000000
++#define S500M 500000000
++#define S250M 250000000
++#define S125M 125000000
++
++/* IVA speeds */
++#define S430M 430000000
++#define S400M 400000000
++#define S360M 360000000
++#define S180M 180000000
++#define S90M 90000000
++
++/* L3 speeds */
++#define S83M 83000000
++#define S166M 166000000
++
++/* VDD1 OPPS */
++#define VDD1_OPP1 0x1
++#define VDD1_OPP2 0x2
++#define VDD1_OPP3 0x3
++#define VDD1_OPP4 0x4
++#define VDD1_OPP5 0x5
++
++/* VDD2 OPPS */
++#define VDD2_OPP1 0x1
++#define VDD2_OPP2 0x2
++#define VDD2_OPP3 0x3
++
++#define MIN_VDD1_OPP VDD1_OPP1
++#define MAX_VDD1_OPP VDD1_OPP5
++#define MIN_VDD2_OPP VDD2_OPP1
++#define MAX_VDD2_OPP VDD2_OPP3
++
++
+ #endif /* __ASM_ARCH_OMAP3_BEAGLE_H */
+
+--- /tmp/resource34xx.c 2008-08-11 16:11:28.000000000 +0200
++++ git/arch/arm/mach-omap2/resource34xx.c 2008-08-11 16:20:18.803198000 +0200
+@@ -173,7 +173,7 @@
+
+ int set_opp(struct shared_resource *resp, u32 target_level)
+ {
+-#ifdef CONFIG_MACH_OMAP_3430SDP
++#if defined(CONFIG_MACH_OMAP_3430SDP) || defined(CONFIG_MACH_OMAP3_BEAGLE)
+ unsigned long mpu_freq, l3_freq, tput;
+ int ind;
+ struct bus_throughput_db *tput_db;
+@@ -248,7 +248,7 @@
+ */
+ void init_freq(struct shared_resource *resp)
+ {
+-#ifdef CONFIG_MACH_OMAP_3430SDP
++#if defined(CONFIG_MACH_OMAP_3430SDP) || defined(CONFIG_MACH_OMAP3_BEAGLE)
+ char *linked_res_name;
+ resp->no_of_users = 0;
+
+@@ -269,7 +269,7 @@
+
+ int set_freq(struct shared_resource *resp, u32 target_level)
+ {
+-#ifdef CONFIG_MACH_OMAP_3430SDP
++#if defined(CONFIG_MACH_OMAP_3430SDP) || defined(CONFIG_MACH_OMAP3_BEAGLE)
+ unsigned int vdd1_opp;
+
+ if (strcmp(resp->name, "mpu_freq") == 0)
+--- /tmp/clock34xx.c 2008-08-11 15:57:48.000000000 +0200
++++ git/arch/arm/mach-omap2/clock34xx.c 2008-08-11 16:22:43.093198000 +0200
+@@ -773,7 +773,7 @@
+ dpll2_clk = clk_get(NULL, "dpll2_ck");
+ dpll3_clk = clk_get(NULL, "dpll3_ck");
+
+-#ifdef CONFIG_MACH_OMAP_3430SDP
++#if defined(CONFIG_MACH_OMAP_3430SDP) || defined(CONFIG_MACH_OMAP3_BEAGLE)
+ mpu_speed = dpll1_clk->rate;
+ prcm_vdd = vdd1_rate_table + MAX_VDD1_OPP;
+ for (; prcm_vdd->speed; prcm_vdd--) {
+@@ -836,7 +836,7 @@
+ return (prcm_config+1)->opp;
+ }
+
+-#ifdef CONFIG_MACH_OMAP_3430SDP
++#if defined(CONFIG_MACH_OMAP_3430SDP) || defined(CONFIG_MACH_OMAP3_BEAGLE)
+ static void omap3_table_recalc(struct clk *clk)
+ {
+ if ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set))
+--- /tmp/board-omap3beagle.c 2008-08-11 15:54:04.000000000 +0200
++++ git/arch/arm/mach-omap2/board-omap3beagle.c 2008-08-11 16:25:11.333198000 +0200
+@@ -39,9 +39,62 @@
+ #include <asm/arch/gpmc.h>
+ #include <asm/arch/nand.h>
+
++#include <asm/arch/clock.h>
++
+ #define GPMC_CS0_BASE 0x60
+ #define GPMC_CS_SIZE 0x30
+
++struct vdd_prcm_config vdd1_rate_table[] = {
++ {0, 0, 0},
++ /*OPP1*/
++ {S125M, VDD1_OPP1, 0},
++ /*OPP2*/
++ {S250M, VDD1_OPP2, 0},
++ /*OPP3*/
++ {S500M, VDD1_OPP3, 0},
++ /*OPP4*/
++ {S550M, VDD1_OPP4, 0},
++ /*OPP5*/
++ {S600M, VDD1_OPP5, 0},
++};
++
++struct vdd_prcm_config vdd2_rate_table[] = {
++ {0, 0, 0},
++ /*OPP1*/
++ {0, VDD2_OPP1, 0},
++ /*OPP2*/
++ {S83M, VDD2_OPP2, 0},
++ /*OPP3*/
++ {S166M, VDD2_OPP3, 0},
++};
++
++struct vdd_prcm_config iva2_rate_table[] = {
++ {0, 0, 0},
++ /*OPP1*/
++ {S90M, VDD1_OPP1, 0},
++ /*OPP2*/
++ {S180M, VDD1_OPP2, 0},
++ /*OPP3*/
++ {S360M, VDD1_OPP3, 0},
++ /*OPP4*/
++ {S400M, VDD1_OPP4, 0},
++ /*OPP5*/
++ {S430M, VDD1_OPP5, 0},
++};
++
++u8 vdd1_volts[MAX_VDD1_OPP] = {
++ /* Vsel corresponding to 0.9V (OPP1), 1.00V (OPP2),
++ * 1.20V (OPP3), 1.27V (OPP4), 1.35 (OPP5)
++ */
++ 0x18, 0x20, 0x30, 0x36, 0x3C
++};
++
++u8 vdd2_volts[MAX_VDD2_OPP] = {
++ /* Vsel corresponding to 0.9V (OPP1), 1.00V (OPP2), 1.15 (OPP3) */
++ 0x18, 0x20, 0x2C
++};
++
++
+ static struct mtd_partition omap3beagle_nand_partitions[] = {
+ /* All the partition sizes are listed in terms of NAND block size */
+ {
+--- /tmp/cpu-omap.c 2008-08-11 15:43:01.000000000 +0200
++++ git/arch/arm/plat-omap/cpu-omap.c 2008-08-11 16:31:24.943198000 +0200
+@@ -47,7 +47,7 @@
+
+ static struct clk *mpu_clk;
+
+-#ifdef CONFIG_MACH_OMAP_3430SDP
++#if defined(CONFIG_MACH_OMAP_3430SDP) || defined(CONFIG_MACH_OMAP3_BEAGLE)
+ extern struct vdd_prcm_config vdd1_rate_table[];
+ extern struct vdd_prcm_config vdd2_rate_table[];
+ extern struct vdd_prcm_config iva2_rate_table[];
+@@ -127,7 +127,7 @@
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ #elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)\
+- && defined(CONFIG_MACH_OMAP_3430SDP)
++ && (defined(CONFIG_MACH_OMAP_3430SDP) || defined(CONFIG_MACH_OMAP3_BEAGLE))
+ {
+ int ind;
+ for (ind = 1; ind <= MAX_VDD1_OPP; ind++) {
diff --git a/packages/linux/linux-omap2-git/beagleboard/01-omap3-cpufreq.eml b/packages/linux/linux-omap2-git/beagleboard/01-omap3-cpufreq.eml
new file mode 100644
index 0000000000..b45a81edce
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/01-omap3-cpufreq.eml
@@ -0,0 +1,319 @@
+CPUFreq driver for OMAP3
+
+Signed-off-by: Rajendra Nayak <rnayak@ti.com>
+---
+ arch/arm/configs/omap_3430sdp_defconfig | 19 +++++++
+ arch/arm/mach-omap2/clock34xx.c | 42 ++++++++++++++++-
+ arch/arm/mach-omap2/resource34xx.c | 6 --
+ arch/arm/plat-omap/cpu-omap.c | 78 ++++++++++++++++++++++++++++++--
+ drivers/cpufreq/cpufreq.c | 2
+ 5 files changed, 136 insertions(+), 11 deletions(-)
+
+Index: linux-omap-2.6/arch/arm/mach-omap2/clock34xx.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/clock34xx.c 2008-08-11
+17:21:57.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/clock34xx.c 2008-08-11
+17:36:53.000000000 +0530
+@@ -31,6 +31,7 @@
+ #include <asm/arch/sram.h>
+ #include <asm/div64.h>
+ #include <asm/bitops.h>
++#include <linux/cpufreq.h>
+
+ #include <asm/arch/sdrc.h>
+ #include "clock.h"
+@@ -637,6 +638,35 @@ static void omap3_clkoutx2_recalc(struct
+ */
+ #if defined(CONFIG_ARCH_OMAP3)
+
++#ifdef CONFIG_CPU_FREQ
++static struct cpufreq_frequency_table freq_table[MAX_VDD1_OPP+1];
++
++void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
++{
++ struct vdd_prcm_config *prcm;
++ int i = 0;
++
++ prcm = vdd1_rate_table + MAX_VDD1_OPP;
++ for (; prcm->speed; prcm--) {
++ freq_table[i].index = i;
++ freq_table[i].frequency = prcm->speed / 1000;
++ i++;
++ }
++
++ if (i == 0) {
++ printk(KERN_WARNING "%s: failed to initialize frequency \
++ table\n",
++ __func__);
++ return;
++ }
++
++ freq_table[i].index = i;
++ freq_table[i].frequency = CPUFREQ_TABLE_END;
++
++ *table = &freq_table[0];
++}
++#endif
++
+ static struct clk_functions omap2_clk_functions = {
+ .clk_enable = omap2_clk_enable,
+ .clk_disable = omap2_clk_disable,
+@@ -644,6 +674,9 @@ static struct clk_functions omap2_clk_fu
+ .clk_set_rate = omap2_clk_set_rate,
+ .clk_set_parent = omap2_clk_set_parent,
+ .clk_disable_unused = omap2_clk_disable_unused,
++#ifdef CONFIG_CPU_FREQ
++ .clk_init_cpufreq_table = omap2_clk_init_cpufreq_table,
++#endif
+ };
+
+ /*
+@@ -793,12 +826,11 @@ inline unsigned int get_opp(struct vdd_p
+
+ if (prcm_config->speed <= freq)
+ return prcm_config->opp; /* Return the Highest OPP */
+- for (; prcm_config->speed; prcm_config--) {
++ for (; prcm_config->speed; prcm_config--)
+ if (prcm_config->speed < freq)
+ return (prcm_config+1)->opp;
+ else if (prcm_config->speed == freq)
+ return prcm_config->opp;
+- }
+ /* Return the least OPP */
+ return (prcm_config+1)->opp;
+ }
+@@ -878,6 +910,10 @@ static int omap3_select_table_rate(struc
+ clk_set_rate(dpll1_clk, prcm_vdd->speed);
+ clk_set_rate(dpll2_clk, iva2_rate_table[index].speed);
+ curr_vdd1_prcm_set = prcm_vdd;
++ omap2_clksel_recalc(&mpu_ck);
++ propagate_rate(&mpu_ck);
++ omap2_clksel_recalc(&iva2_ck);
++ propagate_rate(&iva2_ck);
+ #ifndef CONFIG_CPU_FREQ
+ /*Update loops_per_jiffy if processor speed is being changed*/
+ loops_per_jiffy = compute_lpj(loops_per_jiffy,
+@@ -886,6 +922,8 @@ static int omap3_select_table_rate(struc
+ } else {
+ clk_set_rate(dpll3_clk, prcm_vdd->speed);
+ curr_vdd2_prcm_set = prcm_vdd;
++ omap2_clksel_recalc(&core_ck);
++ propagate_rate(&core_ck);
+ }
+ return 0;
+ }
+Index: linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/resource34xx.c 2008-08-11
+17:36:52.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c 2008-08-11
+17:36:53.000000000 +0530
+@@ -278,11 +278,7 @@ int set_freq(struct shared_resource *res
+ else if (strcmp(resp->name, "dsp_freq") == 0)
+ vdd1_opp = get_opp(iva2_rate_table + MAX_VDD1_OPP,
+ target_level);
+-
+- if (vdd1_opp == MIN_VDD1_OPP)
+- resource_release("vdd1_opp", &dummy_srf_dev);
+- else
+- resource_request("vdd1_opp", &dummy_srf_dev, vdd1_opp);
++ resource_request("vdd1_opp", &dummy_srf_dev, vdd1_opp);
+
+ resp->curr_level = target_level;
+ #endif
+Index: linux-omap-2.6/arch/arm/plat-omap/cpu-omap.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/plat-omap/cpu-omap.c 2008-08-11
+17:21:57.000000000 +0530
++++ linux-omap-2.6/arch/arm/plat-omap/cpu-omap.c 2008-08-11 17:36:53.000000000
++0530
+@@ -8,6 +8,10 @@
+ *
+ * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
+ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Updated to support OMAP3
++ * Rajendra Nayak <rnayak@ti.com>
++ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+@@ -25,6 +29,9 @@
+ #include <asm/io.h>
+ #include <asm/system.h>
+ #include <asm/arch/clock.h>
++#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
++#include <asm/arch/omap-pm.h>
++#endif
+
+ #define VERY_HI_RATE 900000000
+
+@@ -32,12 +39,34 @@ static struct cpufreq_frequency_table *f
+
+ #ifdef CONFIG_ARCH_OMAP1
+ #define MPU_CLK "mpu"
++#elif CONFIG_ARCH_OMAP3
++#define MPU_CLK "virt_vdd1_prcm_set"
+ #else
+ #define MPU_CLK "virt_prcm_set"
+ #endif
+
+ static struct clk *mpu_clk;
+
++#ifdef CONFIG_MACH_OMAP_3430SDP
++extern struct vdd_prcm_config vdd1_rate_table[];
++extern struct vdd_prcm_config vdd2_rate_table[];
++extern struct vdd_prcm_config iva2_rate_table[];
++#endif
++
++#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
++int cpufreq_pre_func(struct notifier_block *n, unsigned long event, void *ptr);
++int cpufreq_post_func(struct notifier_block *n, unsigned long event, void *ptr);
++static struct notifier_block cpufreq_pre = {
++ cpufreq_pre_func,
++ NULL,
++};
++
++static struct notifier_block cpufreq_post = {
++ cpufreq_post_func,
++ NULL,
++};
++#endif
++
+ /* TODO: Add support for SDRAM timing changes */
+
+ int omap_verify_speed(struct cpufreq_policy *policy)
+@@ -89,7 +118,7 @@ static int omap_target(struct cpufreq_po
+
+ if (freqs.old == freqs.new)
+ return ret;
+-
++#ifdef CONFIG_ARCH_OMAP1
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ #ifdef CONFIG_CPU_FREQ_DEBUG
+ printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
+@@ -97,10 +126,50 @@ static int omap_target(struct cpufreq_po
+ #endif
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+-
++#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)\
++ && defined(CONFIG_MACH_OMAP_3430SDP)
++ {
++ int ind;
++ for (ind = 1; ind <= MAX_VDD1_OPP; ind++) {
++ if (vdd1_rate_table[ind].speed/1000 >= freqs.new) {
++ omap_pm_cpu_set_freq
++ (vdd1_rate_table[ind].speed);
++ break;
++ }
++ }
++ }
++#endif
+ return ret;
+ }
+
++#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
++static struct cpufreq_freqs freqs_notify;
++int cpufreq_pre_func(struct notifier_block *n, unsigned long event, void *ptr)
++{
++ struct clk_notifier_data *cnd;
++
++ cnd = (struct clk_notifier_data *)ptr;
++ freqs_notify.old = cnd->old_rate/1000;
++ freqs_notify.new = cnd->new_rate/1000;
++ /* HACK: The clk_notify_post_rate_chg currently
++ * returns a zero for old_rate at bootup
++ */
++ if (freqs_notify.old == 0)
++ freqs_notify.old = 500000;
++ cpufreq_notify_transition(&freqs_notify, CPUFREQ_PRECHANGE);
++ return 0;
++}
++
++int cpufreq_post_func(struct notifier_block *n, unsigned long event, void *ptr)
++{
++ struct clk_notifier_data *cnd;
++
++ cnd = (struct clk_notifier_data *)ptr;
++ cpufreq_notify_transition(&freqs_notify, CPUFREQ_POSTCHANGE);
++ return 0;
++}
++#endif
++
+ static int __init omap_cpu_init(struct cpufreq_policy *policy)
+ {
+ int result = 0;
+@@ -128,7 +197,10 @@ static int __init omap_cpu_init(struct c
+
+ /* FIXME: what's the actual transition time? */
+ policy->cpuinfo.transition_latency = 10 * 1000 * 1000;
+-
++#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
++ clk_notifier_register(mpu_clk, &cpufreq_pre);
++ clk_notifier_register(mpu_clk, &cpufreq_post);
++#endif
+ return 0;
+ }
+
+Index: linux-omap-2.6/drivers/cpufreq/cpufreq.c
+===================================================================
+--- linux-omap-2.6.orig/drivers/cpufreq/cpufreq.c 2008-08-11 17:21:57.000000000
++0530
++++ linux-omap-2.6/drivers/cpufreq/cpufreq.c 2008-08-11 17:36:53.000000000 +0530
+@@ -321,7 +321,9 @@ void cpufreq_notify_transition(struct cp
+ {
+ struct cpufreq_policy *policy;
+
++#if 0 /*This causes an issue if clk_notify_post_rate_chg is used*/
+ BUG_ON(irqs_disabled());
++#endif
+
+ freqs->flags = cpufreq_driver->flags;
+ dprintk("notification %u of frequency transition to %u kHz\n",
+Index: linux-omap-2.6/arch/arm/configs/omap_3430sdp_defconfig
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/configs/omap_3430sdp_defconfig 2008-08-11
+17:36:43.000000000 +0530
++++ linux-omap-2.6/arch/arm/configs/omap_3430sdp_defconfig 2008-08-11
+17:37:33.000000000 +0530
+@@ -193,6 +193,9 @@ CONFIG_OMAP_LL_DEBUG_UART1=y
+ # CONFIG_OMAP_LL_DEBUG_UART2 is not set
+ # CONFIG_OMAP_LL_DEBUG_UART3 is not set
+ CONFIG_OMAP_SERIAL_WAKE=y
++# CONFIG_OMAP_PM_NONE is not set
++# CONFIG_OMAP_PM_NOOP is not set
++CONFIG_OMAP_PM_SRF=y
+ CONFIG_ARCH_OMAP34XX=y
+ CONFIG_ARCH_OMAP3430=y
+
+@@ -288,7 +291,21 @@ CONFIG_CMDLINE="root=/dev/nfs nfsroot=19
+ #
+ # CPU Frequency scaling
+ #
+-# CONFIG_CPU_FREQ is not set
++CONFIG_CPU_FREQ=y
++CONFIG_CPU_FREQ_TABLE=y
++# CONFIG_CPU_FREQ_DEBUG is not set
++CONFIG_CPU_FREQ_STAT=y
++CONFIG_CPU_FREQ_STAT_DETAILS=y
++CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
++# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
++# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
++CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
++# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
++# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
++CONFIG_CPU_FREQ_GOV_ONDEMAND=y
++# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+
+ #
+ # Floating point emulation
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/packages/linux/linux-omap2-git/beagleboard/01-omappm-srf.eml b/packages/linux/linux-omap2-git/beagleboard/01-omappm-srf.eml
new file mode 100644
index 0000000000..8b8b183808
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/01-omappm-srf.eml
@@ -0,0 +1,513 @@
+Adds Generic Shared Resource Framework structures and API's
+
+Signed-off-by: Rajendra Nayak <rnayak@ti.com>
+---
+ arch/arm/plat-omap/resource.c | 389 +++++++++++++++++++++++++++++++++++
+ include/asm-arm/arch-omap/resource.h | 97 ++++++++
+ 2 files changed, 486 insertions(+)
+
+Index: linux-omap-2.6/arch/arm/plat-omap/resource.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-omap-2.6/arch/arm/plat-omap/resource.c 2008-08-07 15:06:58.000000000
++0530
+@@ -0,0 +1,389 @@
++/*
++ * linux/arch/arm/plat-omap/resource.c
++ * Shared Resource Framework API implementation
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Written by Rajendra Nayak <rnayak@ti.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ * History:
++ *
++ */
++
++#include <linux/errno.h>
++#include <linux/err.h>
++#include <asm/arch/resource.h>
++#include <linux/slab.h>
++
++/* res_list contains all registered struct shared_resource */
++static LIST_HEAD(res_list);
++
++/* res_mutex protects res_list add and del ops */
++static DEFINE_MUTEX(res_mutex);
++
++/* Static Pool of users for a resource */
++/* used till kmalloc becomes availabel */
++struct users_list usr_list[MAX_USERS];
++
++/* Private/Internal functions */
++
++/**
++ * resource_lookup - loop up a resource by its name, return a pointer
++ * @name: The name of the resource to lookup
++ *
++ * Looks for a registered resource by its name. Returns a pointer to
++ * the struct shared_resource if found, else returns NULL.
++ */
++static struct shared_resource *resource_lookup(const char *name)
++{
++ struct shared_resource *res, *tmp_res;
++
++ if (!name)
++ return NULL;
++
++ res = NULL;
++
++ srf_mutex_lock(&res_mutex);
++ list_for_each_entry(tmp_res, &res_list, node) {
++ if (!strcmp(name, tmp_res->name)) {
++ res = tmp_res;
++ break;
++ }
++ }
++ srf_mutex_unlock(&res_mutex);
++ return res;
++}
++
++/**
++ * update_resource_level - Regenerates and updates the curr_level of the res
++ * @resp: Pointer to the resource
++ *
++ * This function looks at all the users of the given resource and the levels
++ * requested by each of them, and recomputes a target level for the resource
++ * acceptable to all its current usres. It then calls platform specific
++ * change_level to change the level of the resource.
++ * Returns 0 on success, else a non-zero value returned by the platform
++ * specific change_level function.
++ **/
++static int update_resource_level(struct shared_resource *resp)
++{
++ struct users_list *user;
++ unsigned long target_level;
++ int ret;
++
++ /* Regenerate the target_value for the resource */
++ target_level = RES_DEFAULTLEVEL;
++ list_for_each_entry(user, &resp->users_list, node)
++ if (user->level > target_level)
++ target_level = user->level;
++
++ pr_debug("SRF: Changing Level for resource %s to %ld\n",
++ resp->name, target_level);
++ ret = resp->ops->change_level(resp, target_level);
++ if (ret) {
++ printk(KERN_ERR "Unable to Change"
++ "level for resource %s to %ld\n",
++ resp->name, target_level);
++ return ret;
++ }
++ return ret;
++}
++
++/**
++ * get_user - gets a new users_list struct from static pool or dynamically
++ *
++ * This function initally looks for availability in the static pool and
++ * tries to dynamcially allocate only once the static pool is empty.
++ * We hope that during bootup by the time we hit a case of dynamic allocation
++ * slab initialization would have happened.
++ * Returns a pointer users_list struct on success. On dynamic allocation failure
++ * returns a ERR_PTR(-ENOMEM).
++ */
++static struct users_list *get_user(void)
++{
++ int ind = 0;
++ struct users_list *user;
++
++ /* See if something available in the static pool */
++ while (ind < MAX_USERS) {
++ if (usr_list[ind].usage == UNUSED)
++ break;
++ else
++ ind++;
++ }
++ if (ind < MAX_USERS) {
++ /* Pick from the static pool */
++ user = &usr_list[ind];
++ user->usage = STATIC_ALLOC;
++ } else {
++ /* By this time we hope slab is initialized */
++ if (slab_is_available()) {
++ user = kmalloc(sizeof(struct users_list), GFP_KERNEL);
++ if (!user) {
++ printk(KERN_ERR "SRF:FATAL ERROR: kmalloc"
++ "failed\n");
++ return ERR_PTR(-ENOMEM);
++ }
++ user->usage = DYNAMIC_ALLOC;
++ } else {
++ /* Dynamic alloc not available yet */
++ printk(KERN_ERR "SRF: FATAL ERROR: users_list"
++ "initial POOL EMPTY before slab init\n");
++ return ERR_PTR(-ENOMEM);
++ }
++ }
++ return user;
++}
++
++/**
++ * free_user - frees the dynamic users_list and marks the static one unused
++ * @user: The struct users_list to be freed
++ *
++ * Looks at the usage flag and either frees the users_list if it was
++ * dynamically allocated, and if its from the static pool, marks it unused.
++ * No return value.
++ */
++void free_user(struct users_list *user)
++{
++ if (user->usage == DYNAMIC_ALLOC)
++ kfree(user);
++ else {
++ user->usage = UNUSED;
++ user->level = RES_DEFAULTLEVEL;
++ user->dev = NULL;
++ }
++}
++
++/**
++ * resource_init - Initializes the Shared resource framework.
++ * @resources: List of all the resources modelled
++ *
++ * Loops through the list of resources and registers all that
++ * are available for the current CPU.
++ * No return value
++ */
++void resource_init(struct shared_resource **resources)
++{
++ struct shared_resource **resp;
++ int ind;
++
++ pr_debug("Initializing Shared Resource Framework\n");
++
++ if (!cpu_is_omap343x()) {
++ /* This CPU is not supported */
++ printk(KERN_WARNING "Shared Resource Framework does not"
++ "support this CPU type.\n");
++ WARN_ON(1);
++ }
++
++ /* Init the users_list POOL */
++ for (ind = 0; ind < MAX_USERS; ind++) {
++ usr_list[ind].usage = UNUSED;
++ usr_list[ind].dev = NULL;
++ usr_list[ind].level = RES_DEFAULTLEVEL;
++ }
++
++ if (resources)
++ for (resp = resources; *resp; resp++)
++ resource_register(*resp);
++}
++
++/**
++ * resource_register - registers and initializes a resource
++ * @res: struct shared_resource * to register
++ *
++ * Initializes the given resource and adds it to the resource list
++ * for the current CPU.
++ * Returns 0 on success, -EINVAL if given a NULL pointer, -EEXIST if the
++ * resource is already registered.
++ */
++int resource_register(struct shared_resource *resp)
++{
++ if (!resp)
++ return -EINVAL;
++
++ if (!omap_chip_is(resp->omap_chip))
++ return -EINVAL;
++
++ /* Verify that the resource is not already registered */
++ if (resource_lookup(resp->name))
++ return -EEXIST;
++
++ INIT_LIST_HEAD(&resp->users_list);
++ mutex_init(&resp->res_mutex);
++
++ srf_mutex_lock(&res_mutex);
++ /* Add the resource to the resource list */
++ list_add(&resp->node, &res_list);
++ srf_mutex_unlock(&res_mutex);
++
++ /* Call the resource specific init*/
++ if (resp->ops->init)
++ resp->ops->init(resp);
++
++ pr_debug("resource: registered %s\n", resp->name);
++
++ return 0;
++}
++EXPORT_SYMBOL(resource_register);
++
++/**
++ * resource_unregister - unregister a resource
++ * @res: struct shared_resource * to unregister
++ *
++ * Removes a resource from the resource list.
++ * Returns 0 on success, -EINVAL if passed a NULL pointer.
++ */
++int resource_unregister(struct shared_resource *resp)
++{
++ if (!resp)
++ return -EINVAL;
++
++ srf_mutex_lock(&res_mutex);
++ /* delete the resource from the resource list */
++ list_del(&resp->node);
++ srf_mutex_unlock(&res_mutex);
++
++ pr_debug("resource: unregistered %s\n", resp->name);
++
++ return 0;
++}
++EXPORT_SYMBOL(resource_unregister);
++
++/**
++ * resource_request - Request for a required level of a resource
++ * @name: The name of the resource requested
++ * @dev: Uniquely identifes the caller
++ * @level: The requested level for the resource
++ *
++ * This function recomputes the target level of the resource based on
++ * the level requested by the user. The level of the resource is
++ * changed to the target level, if it is not the same as the existing level
++ * of the resource. Multiple calls to this function by the same device will
++ * replace the previous level requested
++ * Returns 0 on success, -EINVAL if the resource name passed in invalid.
++ * -ENOMEM if no static pool available or dynamic allocations fails.
++ * Else returns a non-zero error value returned by one of the failing
++ * shared_resource_ops.
++ */
++int resource_request(const char *name, struct device *dev,
++ unsigned long level)
++{
++ struct shared_resource *resp;
++ struct users_list *user;
++ int found = 0, ret = 0;
++
++ resp = resource_lookup(name);
++ if (!resp) {
++ printk(KERN_ERR "resource_request: Invalid resource name\n");
++ return -EINVAL;
++ }
++
++ /* Call the resource specific validate function */
++ if (resp->ops->validate_level)
++ ret = resp->ops->validate_level(resp, level);
++ if (ret)
++ return ret;
++
++ srf_mutex_lock(&resp->res_mutex);
++ list_for_each_entry(user, &(resp->users_list), node)
++ if (user->dev == dev) {
++ found = 1;
++ break;
++ }
++ if (!found) {
++ /* First time user */
++ user = get_user();
++ if (IS_ERR(user)) {
++ srf_mutex_unlock(&resp->res_mutex);
++ return -ENOMEM;
++ }
++ user->dev = dev;
++ list_add(&user->node, &resp->users_list);
++ resp->no_of_users++;
++ }
++ user->level = level;
++ srf_mutex_unlock(&resp->res_mutex);
++
++ /* Recompute and set the current level for the resource */
++ return update_resource_level(resp);
++}
++EXPORT_SYMBOL(resource_request);
++
++/**
++ * resource_release - Release a previously requested level of a resource
++ * @name: The name of the resource to be released
++ * @dev: Uniquely identifes the caller
++ *
++ * This function recomputes the target level of the resource after removing
++ * the level requested by the user. The level of the resource is
++ * changed to the target level, if it is not the same as the existing level
++ * of the resource.
++ * Returns 0 on success, -EINVAL if the resource name or dev structure
++ * is invalid.
++ */
++int resource_release(const char *name, struct device *dev)
++{
++ struct shared_resource *resp;
++ struct users_list *user;
++ int found = 0;
++
++ resp = resource_lookup(name);
++ if (!resp) {
++ printk(KERN_ERR "resource_release: Invalid resource name\n");
++ return -EINVAL;
++ }
++
++ srf_mutex_lock(&resp->res_mutex);
++ list_for_each_entry(user, &(resp->users_list), node)
++ if (user->dev == dev) {
++ found = 1;
++ break;
++ }
++
++ if (!found) {
++ srf_mutex_unlock(&resp->res_mutex);
++ /* No such user exists */
++ return -EINVAL;
++ }
++
++ resp->no_of_users--;
++ list_del(&user->node);
++ free_user(user);
++ srf_mutex_unlock(&resp->res_mutex);
++
++ /* Recompute and set the current level for the resource */
++ return update_resource_level(resp);
++}
++EXPORT_SYMBOL(resource_release);
++
++/**
++ * resource_get_level - Returns the current level of the resource
++ * @name: Name of the resource
++ *
++ * Returns the current level of the resource if found, else returns
++ * -EINVAL if the resource name is invalid.
++ */
++int resource_get_level(const char *name)
++{
++ struct shared_resource *resp;
++ u32 ret;
++
++ resp = resource_lookup(name);
++ if (!resp) {
++ printk(KERN_ERR "resource_release: Invalid resource name\n");
++ return -EINVAL;
++ }
++
++ srf_mutex_lock(&resp->res_mutex);
++ ret = resp->curr_level;
++ srf_mutex_unlock(&resp->res_mutex);
++ return ret;
++}
++EXPORT_SYMBOL(resource_get_level);
+Index: linux-omap-2.6/include/asm-arm/arch-omap/resource.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-omap-2.6/include/asm-arm/arch-omap/resource.h 2008-08-07
+15:06:58.000000000 +0530
+@@ -0,0 +1,97 @@
++/*
++ * linux/include/asm-arm/arch-omap/resource.h
++ * Structure definitions for Shared resource Framework
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Written by Rajendra Nayak <rnayak@ti.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ *
++ * History:
++ *
++ */
++
++#ifndef __ARCH_ARM_OMAP_RESOURCE_H
++#define __ARCH_ARM_OMAP_RESOURCE_H
++
++#include <linux/list.h>
++#include <linux/mutex.h>
++#include <linux/device.h>
++#include <asm/arch/cpu.h>
++
++#define srf_mutex_lock(x) { \
++ if (!(in_atomic() || irqs_disabled())) \
++ mutex_lock(x); \
++ }
++#define srf_mutex_unlock(x) { \
++ if (!(in_atomic() || irqs_disabled())) \
++ mutex_unlock(x); \
++ }
++
++#define RES_DEFAULTLEVEL 0x0
++
++struct shared_resource_ops; /* forward declaration */
++
++/* Used to model a Shared Multilevel Resource */
++struct shared_resource {
++ /* Resource name */
++ const char *name;
++ /* Used to represent the OMAP chip types containing this res */
++ const struct omap_chip_id omap_chip;
++ /* Total no of users at any point of this resource */
++ u8 no_of_users;
++ /* Current level of this resource */
++ u32 curr_level;
++ /* Used to store any resource specific data */
++ void *resource_data;
++ /* List of all the current users for this resource */
++ struct list_head users_list;
++ /* Used to guard the resource */
++ struct mutex res_mutex;
++ /* Shared resource operations */
++ struct shared_resource_ops *ops;
++ struct list_head node;
++};
++
++struct shared_resource_ops {
++ /* Init function for the resource */
++ void (*init)(struct shared_resource *res);
++ /* Function to change the level of the resource */
++ int (*change_level)(struct shared_resource *res, u32 target_level);
++ /* Function to validate the requested level of the resource */
++ int (*validate_level)(struct shared_resource *res, u32 target_level);
++};
++
++/* This is to statically defining the users pool */
++/* This static pool is used till kmalloc becomes available */
++#define MAX_USERS 10
++#define UNUSED 0x0
++#define DYNAMIC_ALLOC 0x1
++#define STATIC_ALLOC 0x2
++
++/* Used to represent a user of a shared resource */
++struct users_list {
++ /* Device pointer used to uniquely identify the user */
++ struct device *dev;
++ /* Current level as requested for the resource by the user */
++ u32 level;
++ struct list_head node;
++ u8 usage;
++};
++
++/* Shared resource Framework API's */
++void resource_init(struct shared_resource **resources);
++int resource_register(struct shared_resource *res);
++int resource_unregister(struct shared_resource *res);
++int resource_request(const char *name, struct device *dev,
++ unsigned long level);
++int resource_release(const char *name, struct device *dev);
++int resource_get_level(const char *name);
++
++#endif /* __ARCH_ARM_OMAP_RESOURCE_H */
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
+
diff --git a/packages/linux/linux-omap2-git/beagleboard/01-postrate-notifier.eml b/packages/linux/linux-omap2-git/beagleboard/01-postrate-notifier.eml
new file mode 100644
index 0000000000..8e72afeb3f
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/01-postrate-notifier.eml
@@ -0,0 +1,392 @@
+Add the infrastructure necessary to support clock post-rate-change notifiers
+in the OMAP clock framework. This includes:
+
+- adding the clk_notify_post_rate_chg() function, which will trigger a
+ notifier call chain when a clock rate is changed (but which currently
+ does nothing); and
+
+- adding calls to clk_notify_post_rate_chg() everywhere clk->rate is
+ assigned (mostly *_recalc() functions).
+
+This patch has no functional effect by itself; the actual notifier
+implementation follows in a separate patch.
+
+One item to note is that the post-rate-change notifier is called even
+if the new clock rate is identical to the old rate. This is because
+the process of changing the rate may have temporarily disabled or
+glitched the clock or one of its parents, and some devices may be
+sensitive to such changes.
+
+Signed-off-by: Paul Walmsley <paul@pwsan.com>
+---
+
+ arch/arm/mach-omap2/clock.c | 37 +++++++++++++++++++++++++++------
+ arch/arm/mach-omap2/clock24xx.c | 42 +++++++++++++++++++++++++++++++++++--
+ arch/arm/mach-omap2/clock34xx.c | 10 +++++++++
+ arch/arm/plat-omap/clock.c | 32 ++++++++++++++++++++++++++++
+ include/asm-arm/arch-omap/clock.h | 21 +++++++++++++++++++
+ 5 files changed, 134 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/clock.c b/arch/arm/mach-omap2/clock.c
+index ed15868..bd3c1f8 100644
+--- a/arch/arm/mach-omap2/clock.c
++++ b/arch/arm/mach-omap2/clock.c
+@@ -165,10 +165,15 @@ u32 omap2_get_dpll_rate(struct clk *clk)
+ */
+ void omap2_fixed_divisor_recalc(struct clk *clk)
+ {
++ unsigned long orig_rate;
++
+ WARN_ON(!clk->fixed_div);
+
++ orig_rate = clk->rate;
+ clk->rate = clk->parent->rate / clk->fixed_div;
+
++ clk_notify_post_rate_chg(clk, orig_rate, clk->rate);
++
+ if (clk->flags & RATE_PROPAGATES)
+ propagate_rate(clk);
+ }
+@@ -376,6 +381,7 @@ int omap2_clk_enable(struct clk *clk)
+ void omap2_clksel_recalc(struct clk *clk)
+ {
+ u32 div = 0;
++ unsigned long orig_rate;
+
+ pr_debug("clock: recalc'ing clksel clk %s\n", clk->name);
+
+@@ -385,10 +391,13 @@ void omap2_clksel_recalc(struct clk *clk)
+
+ if (clk->rate == (clk->parent->rate / div))
+ return;
++ orig_rate = clk->rate;
+ clk->rate = clk->parent->rate / div;
+
+ pr_debug("clock: new clock rate is %ld (div %d)\n", clk->rate, div);
+
++ clk_notify_post_rate_chg(clk, orig_rate, clk->rate);
++
+ if (clk->flags & RATE_PROPAGATES)
+ propagate_rate(clk);
+ }
+@@ -662,6 +671,8 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
+ wmb();
+ }
+
++ /* post-rate-change notifier will be called by omap2_clk_set_rate() */
++
+ return 0;
+ }
+
+@@ -670,20 +681,30 @@ int omap2_clksel_set_rate(struct clk *clk, unsigned long rate)
+ int omap2_clk_set_rate(struct clk *clk, unsigned long rate)
+ {
+ int ret = -EINVAL;
+-
+- pr_debug("clock: set_rate for clock %s to rate %ld\n", clk->name, rate);
++ unsigned long orig_rate;
+
+ /* CONFIG_PARTICIPANT clocks are changed only in sets via the
+ rate table mechanism, driven by mpu_speed */
+ if (clk->flags & CONFIG_PARTICIPANT)
+ return -EINVAL;
+
++ if (!clk->set_rate)
++ return -EINVAL;
++
++ orig_rate = clk->rate;
++
++ pr_debug("clock: set_rate for clock %s from %ld Hz to %ld Hz\n",
++ clk->name, orig_rate, rate);
++
+ /* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */
+- if (clk->set_rate)
+- ret = clk->set_rate(clk, rate);
++ ret = clk->set_rate(clk, rate);
+
+- if (ret == 0 && (clk->flags & RATE_PROPAGATES))
+- propagate_rate(clk);
++ if (ret == 0) {
++ clk_notify_post_rate_chg(clk, orig_rate, rate);
++
++ if (clk->flags & RATE_PROPAGATES)
++ propagate_rate(clk);
++ }
+
+ return ret;
+ }
+@@ -732,6 +753,7 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
+ {
+ void __iomem *src_addr;
+ u32 field_val, field_mask, reg_val, parent_div;
++ unsigned long orig_rate;
+
+ if (clk->flags & CONFIG_PARTICIPANT)
+ return -EINVAL;
+@@ -765,11 +787,14 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
+ clk->parent = new_parent;
+
+ /* CLKSEL clocks follow their parents' rates, divided by a divisor */
++ orig_rate = clk->rate;
+ clk->rate = new_parent->rate;
+
+ if (parent_div > 0)
+ clk->rate /= parent_div;
+
++ clk_notify_post_rate_chg(clk, orig_rate, clk->rate);
++
+ pr_debug("clock: set parent of %s to %s (new rate %ld)\n",
+ clk->name, clk->parent->name, clk->rate);
+
+diff --git a/arch/arm/mach-omap2/clock24xx.c b/arch/arm/mach-omap2/clock24xx.c
+index 54cc6e1..e001549 100644
+--- a/arch/arm/mach-omap2/clock24xx.c
++++ b/arch/arm/mach-omap2/clock24xx.c
+@@ -172,11 +172,22 @@ static long omap2_dpllcore_round_rate(unsigned long target_rate)
+
+ static void omap2_dpllcore_recalc(struct clk *clk)
+ {
++ unsigned long orig_rate;
++
++ orig_rate = clk->rate;
+ clk->rate = omap2_get_dpll_rate_24xx(clk);
+
++ clk_notify_post_rate_chg(clk, orig_rate, clk->rate);
++
+ propagate_rate(clk);
+ }
+
++/*
++ * XXX REVISIT: This code needs to keep track of the underlying struct
++ * clocks that it is changing, so it can call post-rate-change notifiers
++ * on them. This function probably should be rewritten to use the clock
++ * fw.
++ */
+ static int omap2_reprogram_dpllcore(struct clk *clk, unsigned long rate)
+ {
+ u32 cur_rate, low, mult, div, valid_rate, done_rate;
+@@ -259,7 +270,14 @@ dpll_exit:
+ */
+ static void omap2_table_mpu_recalc(struct clk *clk)
+ {
++ unsigned long orig_rate;
++
++ orig_rate = clk->rate;
+ clk->rate = curr_prcm_set->mpu_speed;
++
++ clk_notify_post_rate_chg(clk, orig_rate, clk->rate);
++
++ /* No rate propagation since table clocks have no children */
+ }
+
+ /*
+@@ -294,7 +312,14 @@ static long omap2_round_to_table_rate(struct clk *clk, unsigned long rate)
+ return highest_rate;
+ }
+
+-/* Sets basic clocks based on the specified rate */
++/*
++ * Sets basic clocks based on the specified rate
++ *
++ * XXX REVISIT: This code needs to keep track of the underlying struct
++ * clocks that it is changing, so it can call post-rate-change notifiers
++ * on them. This function probably should be rewritten to use the clock
++ * fw.
++ */
+ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
+ {
+ u32 cur_rate, done_rate, bypass = 0, tmp;
+@@ -353,7 +378,8 @@ static int omap2_select_table_rate(struct clk *clk, unsigned long rate)
+ cm_write_mod_reg(prcm->cm_clksel_gfx, GFX_MOD, CM_CLKSEL);
+
+ /* Major subsystem dividers */
+- tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) & OMAP24XX_CLKSEL_DSS2_MASK;
++ tmp = cm_read_mod_reg(CORE_MOD, CM_CLKSEL1) &
++ OMAP24XX_CLKSEL_DSS2_MASK;
+ cm_write_mod_reg(prcm->cm_clksel1_core | tmp, CORE_MOD,
+ CM_CLKSEL1);
+
+@@ -460,13 +486,25 @@ static u32 omap2_get_sysclkdiv(void)
+
+ static void omap2_osc_clk_recalc(struct clk *clk)
+ {
++ unsigned long orig_rate;
++
++ orig_rate = clk->rate;
+ clk->rate = omap2_get_apll_clkin() * omap2_get_sysclkdiv();
++
++ clk_notify_post_rate_chg(clk, orig_rate, clk->rate);
++
+ propagate_rate(clk);
+ }
+
+ static void omap2_sys_clk_recalc(struct clk *clk)
+ {
++ unsigned long orig_rate;
++
++ orig_rate = clk->rate;
+ clk->rate = clk->parent->rate / omap2_get_sysclkdiv();
++
++ clk_notify_post_rate_chg(clk, orig_rate, clk->rate);
++
+ propagate_rate(clk);
+ }
+
+diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
+index 408b51a..7b89b61 100644
+--- a/arch/arm/mach-omap2/clock34xx.c
++++ b/arch/arm/mach-omap2/clock34xx.c
+@@ -53,8 +53,13 @@
+ */
+ static void omap3_dpll_recalc(struct clk *clk)
+ {
++ unsigned long orig_rate;
++
++ orig_rate = clk->rate;
+ clk->rate = omap2_get_dpll_rate(clk);
+
++ clk_notify_post_rate_chg(clk, orig_rate, clk->rate);
++
+ propagate_rate(clk);
+ }
+
+@@ -500,6 +505,7 @@ static void omap3_clkoutx2_recalc(struct clk *clk)
+ const struct dpll_data *dd;
+ u32 v;
+ struct clk *pclk;
++ unsigned long orig_rate;
+
+ /* Walk up the parents of clk, looking for a DPLL */
+ pclk = clk->parent;
+@@ -513,6 +519,8 @@ static void omap3_clkoutx2_recalc(struct clk *clk)
+
+ WARN_ON(!dd->control_reg || !dd->enable_mask);
+
++ orig_rate = clk->rate;
++
+ v = __raw_readl(dd->control_reg) & dd->enable_mask;
+ v >>= __ffs(dd->enable_mask);
+ if (v != DPLL_LOCKED)
+@@ -520,6 +528,8 @@ static void omap3_clkoutx2_recalc(struct clk *clk)
+ else
+ clk->rate = clk->parent->rate * 2;
+
++ clk_notify_post_rate_chg(clk, orig_rate, clk->rate);
++
+ if (clk->flags & RATE_PROPAGATES)
+ propagate_rate(clk);
+ }
+diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
+index c2e741d..421d076 100644
+--- a/arch/arm/plat-omap/clock.c
++++ b/arch/arm/plat-omap/clock.c
+@@ -254,10 +254,16 @@ __setup("mpurate=", omap_clk_setup);
+ /* Used for clocks that always have same value as the parent clock */
+ void followparent_recalc(struct clk *clk)
+ {
++ unsigned long orig_rate;
++
+ if (clk == NULL || IS_ERR(clk))
+ return;
+
++ orig_rate = clk->rate;
+ clk->rate = clk->parent->rate;
++
++ clk_notify_post_rate_chg(clk, orig_rate, clk->rate);
++
+ if (unlikely(clk->flags & RATE_PROPAGATES))
+ propagate_rate(clk);
+ }
+@@ -373,6 +379,32 @@ void clk_init_cpufreq_table(struct cpufreq_frequency_table **table)
+ EXPORT_SYMBOL(clk_init_cpufreq_table);
+ #endif
+
++/**
++ * clk_notify_post_rate_chg - call post-clk-rate-change notifier chain
++ * @clk: struct clk * that is changing rate
++ * @old_rate: old rate
++ * @new_rate: new rate
++ *
++ * Triggers a notifier call chain on the post-clk-rate-change notifier
++ * for clock 'clk'. Passes a pointer to the struct clk and the
++ * previous and current rates to the notifier callback. Intended to be
++ * called by internal clock code only. No return value.
++ */
++void clk_notify_post_rate_chg(struct clk *clk, unsigned long old_rate,
++ unsigned long new_rate)
++{
++ struct clk_notifier *cn;
++ struct clk_notifier_data cnd;
++
++ cnd.clk = clk;
++ cnd.old_rate = old_rate;
++ cnd.new_rate = new_rate;
++
++ /* XXX Call notifier here */
++
++}
++
++
+ /*-------------------------------------------------------------------------*/
+
+ #ifdef CONFIG_OMAP_RESET_CLOCKS
+diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
+index bfaf7b6..e3c9aeb 100644
+--- a/include/asm-arm/arch-omap/clock.h
++++ b/include/asm-arm/arch-omap/clock.h
+@@ -10,6 +10,8 @@
+ * published by the Free Software Foundation.
+ */
+
++#include <linux/notifier.h>
++
+ #ifndef __ARCH_ARM_OMAP_CLOCK_H
+ #define __ARCH_ARM_OMAP_CLOCK_H
+
+@@ -58,6 +60,19 @@ struct dpll_data {
+
+ #endif
+
++struct clk_notifier {
++ struct clk *clk;
++ struct atomic_notifier_head notifier_head;
++ struct list_head node;
++};
++
++struct clk_notifier_data {
++ struct clk *clk;
++ unsigned long old_rate;
++ unsigned long new_rate;
++};
++
++
+ struct clk {
+ struct list_head node;
+ struct module *owner;
+@@ -121,6 +136,10 @@ extern void clk_allow_idle(struct clk *clk);
+ extern void clk_deny_idle(struct clk *clk);
+ extern int clk_get_usecount(struct clk *clk);
+ extern void clk_enable_init_clocks(void);
++extern int clk_notifier_register(struct clk *clk, struct notifier_block *nb);
++extern int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);
++extern void clk_notify_post_rate_chg(struct clk *clk, unsigned long old_rate,
++ unsigned long new_rate);
+ #ifdef CONFIG_CPU_FREQ
+ extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
+ #endif
+@@ -161,6 +180,8 @@ extern void clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
+
+ #define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X)
+
++/* Clk rate change notifier callback type */
++#define CLK_POST_RATE_CHANGE 1
+
+ /* CM_CLKSEL2_PLL.CORE_CLK_SRC options (24XX) */
+ #define CORE_CLK_SRC_32K 0
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
+
diff --git a/packages/linux/linux-omap2-git/beagleboard/02-beagle_use_gptimer12 b/packages/linux/linux-omap2-git/beagleboard/02-beagle_use_gptimer12
new file mode 100644
index 0000000000..51d2c8cff0
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/02-beagle_use_gptimer12
@@ -0,0 +1,38 @@
+BeagleBoard: make Beagle use GPTIMER12 for system ticks
+
+From: Paul Walmsley <paul@pwsan.com>
+
+There is suspicion that the 32kHz input clock to the OMAP may be noisy
+on BeagleBoards. On OMAP2/3 GPTIMER1, this can cause the timer
+counter register to warp to unknown values or miss interrupt
+conditions. So, use GPTIMER12 instead, which apparently has its own
+secure 32kHz oscillator and will hopefully not be prone to the 32kHz
+glitches.
+---
+
+ arch/arm/configs/omap3_beagle_defconfig | 5 +++--
+ 1 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/arm/configs/omap3_beagle_defconfig b/arch/arm/configs/omap3_beagle_defconfig
+index e1b16d0..7805995 100644
+--- a/arch/arm/configs/omap3_beagle_defconfig
++++ defconfig
+@@ -182,8 +182,8 @@ CONFIG_OMAP_BOOT_REASON=y
+ # CONFIG_OMAP_MCBSP is not set
+ # CONFIG_OMAP_MMU_FWK is not set
+ # CONFIG_OMAP_MBOX_FWK is not set
+-CONFIG_OMAP_MPU_TIMER=y
+-# CONFIG_OMAP_32K_TIMER is not set
++# CONFIG_OMAP_MPU_TIMER is not set
++CONFIG_OMAP_32K_TIMER=y
+ CONFIG_OMAP_DM_TIMER=y
+ # CONFIG_OMAP_LL_DEBUG_UART1 is not set
+ # CONFIG_OMAP_LL_DEBUG_UART2 is not set
+@@ -198,6 +198,7 @@ CONFIG_ARCH_OMAP3430=y
+ # CONFIG_MACH_OMAP_3430SDP is not set
+ # CONFIG_MACH_OMAP3EVM is not set
+ CONFIG_MACH_OMAP3_BEAGLE=y
++CONFIG_OMAP_TICK_GPTIMER=12
+
+ #
+ # Boot options
diff --git a/packages/linux/linux-omap2-git/beagleboard/02-omappm-mpu-latency-modeling.eml b/packages/linux/linux-omap2-git/beagleboard/02-omappm-mpu-latency-modeling.eml
new file mode 100644
index 0000000000..35ef87bdf0
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/02-omappm-mpu-latency-modeling.eml
@@ -0,0 +1,245 @@
+Adds resource def's for mpu/core/powerdomain latencies for OMAP3
+
+Signed-off-by: Rajendra Nayak <rnayak@ti.com>
+---
+ arch/arm/mach-omap2/resource34xx.h | 226 +++++++++++++++++++++++++++++++++++++
+ 1 files changed, 226 insertions(+)
+
+Index: linux-omap-2.6/arch/arm/mach-omap2/resource34xx.h
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-omap-2.6/arch/arm/mach-omap2/resource34xx.h 2008-08-07
+15:07:02.000000000 +0530
+@@ -0,0 +1,226 @@
++/*
++ * linux/arch/arm/mach-omap2/resource34xx.h
++ *
++ * OMAP3 resource definitions
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Written by Rajendra Nayak <rnayak@ti.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ *
++ * History:
++ *
++ */
++
++#ifndef __ARCH_ARM_MACH_OMAP2_RESOURCE_H
++#define __ARCH_ARM_MACH_OMAP2_RESOURCE_H
++
++#include <asm/arch/resource.h>
++#include <asm/arch/powerdomain.h>
++
++/**
++ * mpu_latency/core_latency are used to control the cpuidle C state.
++ */
++void init_latency(struct shared_resource *resp);
++int set_latency(struct shared_resource *resp, u32 target_level);
++
++static u8 mpu_qos_req_added;
++static u8 core_qos_req_added;
++
++static struct shared_resource_ops lat_res_ops = {
++ .init = init_latency,
++ .change_level = set_latency,
++};
++
++static struct shared_resource mpu_latency = {
++ .name = "mpu_latency",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .resource_data = &mpu_qos_req_added,
++ .ops = &lat_res_ops,
++};
++
++static struct shared_resource core_latency = {
++ .name = "core_latency",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .resource_data = &core_qos_req_added,
++ .ops = &lat_res_ops,
++};
++
++/**
++ * Power domain Latencies are used to control the target Power
++ * domain state once all clocks for the power domain
++ * are released.
++ */
++void init_pd_latency(struct shared_resource *resp);
++int set_pd_latency(struct shared_resource *resp, u32 target_level);
++
++/* Power Domain Latency levels */
++#define PD_LATENCY_OFF 0x0
++#define PD_LATENCY_RET 0x1
++#define PD_LATENCY_INACT 0x2
++#define PD_LATENCY_ON 0x3
++
++#define PD_LATENCY_MAXLEVEL 0x4
++
++struct pd_latency_db {
++ char *pwrdm_name;
++ struct powerdomain *pd;
++ /* Latencies for each state transition, stored in us */
++ unsigned long latency[PD_LATENCY_MAXLEVEL];
++};
++
++static struct shared_resource_ops pd_lat_res_ops = {
++ .init = init_pd_latency,
++ .change_level = set_pd_latency,
++};
++
++static struct pd_latency_db iva2_pwrdm_lat_db = {
++ .pwrdm_name = "iva2_pwrdm",
++ .latency[PD_LATENCY_OFF] = 1000,
++ .latency[PD_LATENCY_RET] = 100,
++ .latency[PD_LATENCY_INACT] = 0,
++ .latency[PD_LATENCY_ON] = 0
++};
++
++static struct shared_resource iva2_pwrdm_latency = {
++ .name = "iva2_pwrdm_latency",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .resource_data = &iva2_pwrdm_lat_db,
++ .ops = &pd_lat_res_ops,
++};
++
++static struct pd_latency_db gfx_pwrdm_lat_db = {
++ .pwrdm_name = "gfx_pwrdm",
++ .latency[PD_LATENCY_OFF] = 1000,
++ .latency[PD_LATENCY_RET] = 100,
++ .latency[PD_LATENCY_INACT] = 0,
++ .latency[PD_LATENCY_ON] = 0
++};
++
++static struct shared_resource gfx_pwrdm_latency = {
++ .name = "gfx_pwrdm_latency",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
++ .resource_data = &gfx_pwrdm_lat_db,
++ .ops = &pd_lat_res_ops,
++};
++
++static struct shared_resource sgx_pwrdm_latency = {
++ .name = "sgx_pwrdm_latency",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
++ .resource_data = &gfx_pwrdm_lat_db,
++ .ops = &pd_lat_res_ops,
++};
++
++static struct pd_latency_db dss_pwrdm_lat_db = {
++ .pwrdm_name = "dss_pwrdm",
++ .latency[PD_LATENCY_OFF] = 70,
++ .latency[PD_LATENCY_RET] = 20,
++ .latency[PD_LATENCY_INACT] = 0,
++ .latency[PD_LATENCY_ON] = 0
++};
++
++static struct shared_resource dss_pwrdm_latency = {
++ .name = "dss_pwrdm_latency",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .resource_data = &dss_pwrdm_lat_db,
++ .ops = &pd_lat_res_ops,
++};
++
++static struct pd_latency_db cam_pwrdm_lat_db = {
++ .pwrdm_name = "cam_pwrdm",
++ .latency[PD_LATENCY_OFF] = 850,
++ .latency[PD_LATENCY_RET] = 35,
++ .latency[PD_LATENCY_INACT] = 0,
++ .latency[PD_LATENCY_ON] = 0
++};
++
++static struct shared_resource cam_pwrdm_latency = {
++ .name = "cam_pwrdm_latency",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .resource_data = &cam_pwrdm_lat_db,
++ .ops = &pd_lat_res_ops,
++};
++
++static struct pd_latency_db per_pwrdm_lat_db = {
++ .pwrdm_name = "per_pwrdm",
++ .latency[PD_LATENCY_OFF] = 200,
++ .latency[PD_LATENCY_RET] = 110,
++ .latency[PD_LATENCY_INACT] = 0,
++ .latency[PD_LATENCY_ON] = 0
++};
++
++static struct shared_resource per_pwrdm_latency = {
++ .name = "per_pwrdm_latency",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .resource_data = &per_pwrdm_lat_db,
++ .ops = &pd_lat_res_ops,
++};
++
++static struct pd_latency_db neon_pwrdm_lat_db = {
++ .pwrdm_name = "neon_pwrdm",
++ .latency[PD_LATENCY_OFF] = 1000,
++ .latency[PD_LATENCY_RET] = 100,
++ .latency[PD_LATENCY_INACT] = 0,
++ .latency[PD_LATENCY_ON] = 0
++};
++
++static struct shared_resource neon_pwrdm_latency = {
++ .name = "neon_pwrdm_latency",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .resource_data = &neon_pwrdm_lat_db,
++ .ops = &pd_lat_res_ops,
++};
++
++static struct pd_latency_db usbhost_pwrdm_lat_db = {
++ .pwrdm_name = "usbhost_pwrdm",
++ .latency[PD_LATENCY_OFF] = 1000,
++ .latency[PD_LATENCY_RET] = 100,
++ .latency[PD_LATENCY_INACT] = 0,
++ .latency[PD_LATENCY_ON] = 0
++};
++
++static struct shared_resource usbhost_pwrdm_latency = {
++ .name = "usbhost_pwrdm_latency",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES2),
++ .resource_data = &usbhost_pwrdm_lat_db,
++ .ops = &pd_lat_res_ops,
++};
++
++static struct pd_latency_db emu_pwrdm_lat_db = {
++ .pwrdm_name = "emu_pwrdm",
++ .latency[PD_LATENCY_OFF] = 1000,
++ .latency[PD_LATENCY_RET] = 100,
++ .latency[PD_LATENCY_INACT] = 0,
++ .latency[PD_LATENCY_ON] = 0
++};
++
++static struct shared_resource emu_pwrdm_latency = {
++ .name = "emu_pwrdm",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .resource_data = &emu_pwrdm_lat_db,
++ .ops = &pd_lat_res_ops,
++};
++
++struct shared_resource *resources_omap[] __initdata = {
++ &mpu_latency,
++ &core_latency,
++ /* Power Domain Latency resources */
++ &iva2_pwrdm_latency,
++ &gfx_pwrdm_latency,
++ &sgx_pwrdm_latency,
++ &dss_pwrdm_latency,
++ &cam_pwrdm_latency,
++ &per_pwrdm_latency,
++ &neon_pwrdm_latency,
++ &usbhost_pwrdm_latency,
++ &emu_pwrdm_latency,
++ NULL
++};
++
++#endif /* __ARCH_ARM_MACH_OMAP2_RESOURCE_H */
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/packages/linux/linux-omap2-git/beagleboard/02-postrate-notifier.eml b/packages/linux/linux-omap2-git/beagleboard/02-postrate-notifier.eml
new file mode 100644
index 0000000000..97058f99e1
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/02-postrate-notifier.eml
@@ -0,0 +1,186 @@
+This patch implements the remaining code for notification of clock
+rate changes via the clock framework:
+
+- a notifier registration function, clk_notifier_register()
+
+- a notifier unregistration function, clk_notifier_unregister()
+
+- the clk_notify_post_rate_chg() call-chain function, has been fleshed out
+
+The implementation is via an atomic notifier, called with the clockfw
+spinlock held. Callback functions must not sleep and must not re-enter
+the clock framework, and should execute quickly.
+
+In the medium-term future, there are likely to be few users of these
+notifiers. So, rather than storing one notifier per struct clk,
+notifiers are stored in a separate, dynamically allocated list,
+effectively trading execution speed (in terms of a sequential scan of
+the notifier list) for memory savings. The implementation is
+completely hidden from the callbacks and is easily changed if
+necessary.
+
+Signed-off-by: Paul Walmsley <paul@pwsan.com>
+---
+
+ arch/arm/plat-omap/clock.c | 118 +++++++++++++++++++++++++++++++++++++++++++-
+ 1 files changed, 115 insertions(+), 3 deletions(-)
+
+diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
+index 421d076..354f45f 100644
+--- a/arch/arm/plat-omap/clock.c
++++ b/arch/arm/plat-omap/clock.c
+@@ -22,6 +22,7 @@
+ #include <linux/mutex.h>
+ #include <linux/platform_device.h>
+ #include <linux/cpufreq.h>
++#include <linux/notifier.h>
+ #include <linux/debugfs.h>
+
+ #include <asm/io.h>
+@@ -34,6 +35,8 @@ static DEFINE_SPINLOCK(clockfw_lock);
+
+ static struct clk_functions *arch_clock;
+
++static LIST_HEAD(clk_notifier_list);
++
+ /*-------------------------------------------------------------------------
+ * Standard clock functions defined in include/linux/clk.h
+ *-------------------------------------------------------------------------*/
+@@ -380,6 +383,110 @@ EXPORT_SYMBOL(clk_init_cpufreq_table);
+ #endif
+
+ /**
++<<<<<<< current:arch/arm/plat-omap/clock.c
++=======
++ * clk_notifier_register - add a clock rate change notifier
++ * @clk: struct clk * to watch for rate echanges
++ * @nb: struct notifier_block * with callback info
++ *
++ * Request notification after a frequency change on clock 'clk'. This
++ * uses an atomic notifier. The callback will be called with
++ * interrupts disabled; therefore callback code should be very
++ * lightweight. Callback code must not call back into the clock
++ * framework. Callback code will be passed the previous and new rate
++ * of the clock.
++ *
++ * clk_notifier_register() must be called from process
++ * context. Returns -EINVAL if called with null arguments, -ENOMEM
++ * upon allocation failure; otherwise, passes along the return value
++ * of atomic_notifier_chain_register().
++ */
++int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
++{
++ struct clk_notifier *cn = NULL, *cn_new = NULL;
++ int r;
++ unsigned long flags;
++
++ if (!clk || !nb)
++ return -EINVAL;
++
++ /* Allocate this here speculatively so we can avoid GFP_ATOMIC */
++ cn_new = kzalloc(sizeof(struct clk_notifier), GFP_KERNEL);
++ if (!cn_new)
++ return -ENOMEM;
++
++ spin_lock_irqsave(&clockfw_lock, flags);
++
++ list_for_each_entry(cn, &clk_notifier_list, node) {
++ if (cn->clk == clk)
++ break;
++ }
++
++ if (cn->clk != clk) {
++ cn_new->clk = clk;
++ ATOMIC_INIT_NOTIFIER_HEAD(&cn_new->notifier_head);
++
++ list_add(&cn_new->node, &clk_notifier_list);
++ cn = cn_new;
++ } else {
++ kfree(cn_new); /* didn't need it after all */
++ }
++
++ r = atomic_notifier_chain_register(&cn->notifier_head, nb);
++
++ spin_unlock_irqrestore(&clockfw_lock, flags);
++
++ return r;
++}
++
++/**
++ * clk_notifier_unregister - remove a clock rate change notifier
++ * @clk: struct clk *
++ * @nb: struct notifier_block * with callback info
++ *
++ * Request no further notification for frequency changes on clock
++ * 'clk'. This function presently does not release memory allocated
++ * by its corresponding _register function; see inline comments for
++ * more informations. Returns -EINVAL if called with null arguments;
++ * otherwise, passes along the return value of
++ * atomic_notifier_chain_unregister().
++ */
++int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
++{
++ struct clk_notifier *cn = NULL;
++ int r = -EINVAL;
++ unsigned long flags;
++
++ if (!clk || !nb)
++ return -EINVAL;
++
++ spin_lock_irqsave(&clockfw_lock, flags);
++
++ list_for_each_entry(cn, &clk_notifier_list, node) {
++ if (cn->clk == clk)
++ break;
++ }
++
++ if (cn->clk == clk) {
++ r = atomic_notifier_chain_unregister(&cn->notifier_head, nb);
++
++ /*
++ * XXX unfortunately it seems that there is no polite
++ * way to test if a notifier has zero users. So once
++ * a post-notifier has been registered on a clock,
++ * that struct clk_notifier will not be freed, even if
++ * all of its users unregister.
++ */
++ } else {
++ r = -ENOENT;
++ }
++
++ spin_unlock_irqrestore(&clockfw_lock, flags);
++
++ return r;
++}
++
++/**
+ * clk_notify_post_rate_chg - call post-clk-rate-change notifier chain
+ * @clk: struct clk * that is changing rate
+ * @old_rate: old rate
+@@ -400,11 +507,16 @@ void clk_notify_post_rate_chg(struct clk *clk, unsigned long old_rate,
+ cnd.old_rate = old_rate;
+ cnd.new_rate = new_rate;
+
+- /* XXX Call notifier here */
+-
++ list_for_each_entry(cn, &clk_notifier_list, node) {
++ if (cn->clk == clk) {
++ atomic_notifier_call_chain(&cn->notifier_head,
++ CLK_POST_RATE_CHANGE,
++ &cnd);
++ break;
++ }
++ }
+ }
+
+-
+ /*-------------------------------------------------------------------------*/
+
+ #ifdef CONFIG_OMAP_RESET_CLOCKS
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
+
diff --git a/packages/linux/linux-omap2-git/beagleboard/03-omappm-omap3srf.eml b/packages/linux/linux-omap2-git/beagleboard/03-omappm-omap3srf.eml
new file mode 100644
index 0000000000..d052023f12
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/03-omappm-omap3srf.eml
@@ -0,0 +1,167 @@
+Adds init/change_level/validate_level calls for OMAP3 resources
+
+Signed-off-by: Rajendra Nayak <rnayak@ti.com>
+---
+ arch/arm/mach-omap2/resource34xx.c | 148 +++++++++++++++++++++++++++++++++++++
+ 1 files changed, 148 insertions(+)
+
+Index: linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c 2008-08-07
+15:07:04.000000000 +0530
+@@ -0,0 +1,148 @@
++/*
++ * linux/arch/arm/mach-omap2/resource34xx.c
++ * OMAP3 resource init/change_level/validate_level functions
++ *
++ * Copyright (C) 2007-2008 Texas Instruments, Inc.
++ * Written by Rajendra Nayak <rnayak@ti.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
++ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
++ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
++ * History:
++ *
++ */
++
++#include <linux/pm_qos_params.h>
++#include <asm/arch/powerdomain.h>
++#include <asm/arch/clockdomain.h>
++#include "resource34xx.h"
++
++/**
++ * init_latency - Initializes the mpu/core latency resource.
++ * @resp: Latency resource to be initalized
++ *
++ * No return value.
++ */
++void init_latency(struct shared_resource *resp)
++{
++ resp->no_of_users = 0;
++ resp->curr_level = RES_DEFAULTLEVEL;
++ *((u8 *)resp->resource_data) = 0;
++ return;
++}
++
++/**
++ * set_latency - Adds/Updates and removes the CPU_DMA_LATENCY in *pm_qos_params.
++ * @resp: resource pointer
++ * @latency: target latency to be set
++ *
++ * Returns 0 on success, or error values as returned by
++ * pm_qos_update_requirement/pm_qos_add_requirement.
++ */
++int set_latency(struct shared_resource *resp, u32 latency)
++{
++ u8 *pm_qos_req_added;
++
++ if (resp->curr_level == latency)
++ return 0;
++ else
++ /* Update the resources current level */
++ resp->curr_level = latency;
++
++ pm_qos_req_added = resp->resource_data;
++ if (latency == RES_DEFAULTLEVEL)
++ /* No more users left, remove the pm_qos_req if present */
++ if (*pm_qos_req_added) {
++ pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY,
++ resp->name);
++ *pm_qos_req_added = 0;
++ return 0;
++ }
++
++ if (*pm_qos_req_added) {
++ return pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY,
++ resp->name, latency);
++ } else {
++ *pm_qos_req_added = 1;
++ return pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY,
++ resp->name, latency);
++ }
++}
++
++/**
++ * init_pd_latency - Initializes the power domain latency resource.
++ * @resp: Power Domain Latency resource to be initialized.
++ *
++ * No return value.
++ */
++void init_pd_latency(struct shared_resource *resp)
++{
++ struct pd_latency_db *pd_lat_db;
++
++ resp->no_of_users = 0;
++ resp->curr_level = PD_LATENCY_OFF;
++ pd_lat_db = resp->resource_data;
++ /* Populate the power domain associated with the latency resource */
++ pd_lat_db->pd = pwrdm_lookup(pd_lat_db->pwrdm_name);
++ return;
++}
++
++/**
++ * set_pd_latency - Updates the curr_level of the power domain resource.
++ * @resp: Power domain latency resource.
++ * @latency: New latency value acceptable.
++ *
++ * This function maps the latency in microsecs to the acceptable
++ * Power domain state using the latency DB.
++ * It then programs the power domain to enter the target state.
++ * Always returns 0.
++ */
++int set_pd_latency(struct shared_resource *resp, u32 latency)
++{
++ u32 pd_lat_level, ind, i;
++ struct pd_latency_db *pd_lat_db;
++ struct powerdomain *pwrdm;
++
++ pd_lat_db = resp->resource_data;
++ pwrdm = pd_lat_db->pd;
++ pd_lat_level = PD_LATENCY_OFF;
++ /* using the latency db map to the appropriate PD state */
++ for (ind = 0; ind < PD_LATENCY_MAXLEVEL; ind++)
++ if (pd_lat_db->latency[ind] < latency)
++ pd_lat_level = ind;
++
++ resp->curr_level = pd_lat_level;
++ switch (pd_lat_level) {
++ case PWRDM_POWER_OFF:
++ case PWRDM_POWER_RET:
++ /* Errata 1.29: No transitions from INACTIVE to RET/OFF
++ * possible.
++ * Need to be taken care of here.
++ */
++ if (pwrdm_read_pwrst(pwrdm) != PWRDM_POWER_ON) {
++ /* Force the clock domains to ON */
++ for (i = 0; pwrdm->pwrdm_clkdms[i]; i++) {
++ omap2_clkdm_deny_idle(pwrdm->pwrdm_clkdms[i]);
++ omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[i]);
++ }
++ pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_ON);
++ pwrdm_set_next_pwrst(pwrdm, pd_lat_level);
++ for (i = 0; pwrdm->pwrdm_clkdms[i]; i++) {
++ omap2_clkdm_sleep(pwrdm->pwrdm_clkdms[i]);
++ omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[i]);
++ }
++ } else
++ pwrdm_set_next_pwrst(pwrdm, pd_lat_level);
++ break;
++ case PWRDM_POWER_ON:
++ pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_ON);
++ break;
++ default:
++ break;
++ }
++ return 0;
++}
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/packages/linux/linux-omap2-git/beagleboard/04-omappm-srf-noop.eml b/packages/linux/linux-omap2-git/beagleboard/04-omappm-srf-noop.eml
new file mode 100644
index 0000000000..32d767a342
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/04-omappm-srf-noop.eml
@@ -0,0 +1,497 @@
+Adds SRF calls into OMAP PM skeleton layer developed by Paul W.
+
+Signed-off-by: Rajendra Nayak <rnayak@ti.com>
+---
+ arch/arm/mach-omap2/Makefile | 1
+ arch/arm/mach-omap2/clockdomain.c | 7
+ arch/arm/plat-omap/Kconfig | 3
+ arch/arm/plat-omap/Makefile | 4
+ arch/arm/plat-omap/omap-pm-srf.c | 367 ++++++++++++++++++++++++++++++++
+ include/asm-arm/arch-omap/powerdomain.h | 1
+ include/asm-arm/arch-omap/resource.h | 1
+ 7 files changed, 383 insertions(+), 1 deletion(-)
+
+Index: linux-omap-2.6/arch/arm/plat-omap/omap-pm-srf.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-omap-2.6/arch/arm/plat-omap/omap-pm-srf.c 2008-08-11
+17:38:37.000000000 +0530
+@@ -0,0 +1,367 @@
++/*
++ * omap-pm-srf.c - OMAP power management interface implemented
++ * using Shared resource framework
++ *
++ * This code implements the OMAP power management interface to
++ * drivers, CPUIdle, CPUFreq, and DSP Bridge. It is strictly for
++ * debug/demonstration use, as it does nothing but printk() whenever a
++ * function is called (when DEBUG is defined, below)
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ * Copyright (C) 2008 Nokia Corporation
++ * Paul Walmsley
++ *
++ * Interface developed by (in alphabetical order):
++ * Karthik Dasu, Amish Lakhani, Tony Lindgren, Rajendra Nayak, Sakari
++ * Poussa, Veeramanikandan Raju, Igor Stoppa, Paul Walmsley, Richard
++ * Woodruff
++ *
++ * Interfaces defined by Paul Walmsley
++ * Updated with SRF calls by Rajendra Nayak
++ */
++
++#undef DEBUG
++
++#include <linux/init.h>
++#include <linux/cpufreq.h>
++#include <linux/device.h>
++
++/* Interface documentation is in asm/arch/omap-pm.h */
++#include <asm/arch/omap-pm.h>
++
++#include <asm/arch/powerdomain.h>
++#include <asm/arch/resource.h>
++/*
++#include <asm/arch/tiocp.h>
++*/
++
++#define LAT_RES_POSTAMBLE "_latency"
++char latency_res_name[30];
++/* lat_name_mutex protects latency_res_name*/
++static DEFINE_MUTEX(lat_name_mutex);
++
++
++/**
++ * get_lat_res_name - gets the latency resource name given a power domain name
++ * @pwrdm_name: Name of the power domain.
++ *
++ * Returns a pointer to the latency resource name.
++ */
++static char *get_lat_res_name(const char *pwrdm_name)
++{
++ strcpy(latency_res_name, "");
++ if (!(in_atomic() || irqs_disabled()))
++ mutex_lock(&lat_name_mutex);
++ WARN_ON(strlen(pwrdm_name) + strlen(LAT_RES_POSTAMBLE) >
++ sizeof(latency_res_name));
++ strcpy(latency_res_name, pwrdm_name);
++ strcat(latency_res_name, LAT_RES_POSTAMBLE);
++ if (!(in_atomic() || irqs_disabled()))
++ mutex_unlock(&lat_name_mutex);
++ return latency_res_name;
++}
++
++static struct omap_opp *dsp_opps;
++static struct omap_opp *mpu_opps;
++
++/*
++ * Device-driver-originated constraints (via board-*.c files)
++ */
++
++void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
++{
++ if (!dev || t < -1) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (t == -1) {
++ pr_debug("OMAP PM: remove max MPU wakeup latency constraint: "
++ "dev %s\n", dev_name(dev));
++ resource_release("mpu_latency", dev);
++ } else {
++ pr_debug("OMAP PM: add max MPU wakeup latency constraint: "
++ "dev %s, t = %ld usec\n", dev_name(dev), t);
++ resource_request("mpu_latency", dev, t);
++ }
++}
++
++void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
++{
++ if (!dev || agent_id != OCP_INITIATOR_AGENT ||
++ agent_id != OCP_TARGET_AGENT) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (r == 0)
++ pr_debug("OMAP PM: remove min bus tput constraint: "
++ "dev %s for agent_id %d\n", dev_name(dev), agent_id);
++ else
++ pr_debug("OMAP PM: add min bus tput constraint: "
++ "dev %s for agent_id %d: rate %ld KiB\n",
++ dev_name(dev), agent_id, r);
++
++ /*
++ * This code should model the interconnect and compute the
++ * required clock frequency, convert that to a VDD2 OPP ID, then
++ * set the VDD2 OPP appropriately.
++ *
++ * TI CDP code can call constraint_set here on the VDD2 OPP.
++ */
++}
++
++void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t)
++{
++ /* struct tiocp *tiocp_dev; */
++ struct powerdomain *pwrdm_dev;
++ char *res_name;
++
++ if (!dev || t < -1) {
++ WARN_ON(1);
++ return;
++ };
++ /* Look for the devices Power Domain */
++ /* TODO: Put this back in once tiocp layer is available
++ tiocp_dev = container_of(dev, struct tiocp, dev);
++ pwrdm_dev = tiocp_dev->pwrdm;
++ */
++
++ if (t == -1) {
++ pr_debug("OMAP PM: remove max device latency constraint: "
++ "dev %s\n", dev_name(dev));
++ res_name = get_lat_res_name(pwrdm_dev->name);
++ resource_release(res_name, dev);
++ } else {
++ pr_debug("OMAP PM: add max device latency constraint: "
++ "dev %s, t = %ld usec\n", dev_name(dev), t);
++ res_name = get_lat_res_name(pwrdm_dev->name);
++ resource_request(res_name, dev, t);
++ }
++
++ /*
++ * For current Linux, this needs to map the device to a
++ * powerdomain, then go through the list of current max lat
++ * constraints on that powerdomain and find the smallest. If
++ * the latency constraint has changed, the code should
++ * recompute the state to enter for the next powerdomain
++ * state. Conceivably, this code should also determine
++ * whether to actually disable the device clocks or not,
++ * depending on how long it takes to re-enable the clocks.
++ *
++ * TI CDP code can call constraint_set here.
++ */
++}
++
++void omap_pm_set_max_sdma_lat(struct device *dev, long t)
++{
++ if (!dev || t < -1) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (t == -1) {
++ pr_debug("OMAP PM: remove max DMA latency constraint: "
++ "dev %s\n", dev_name(dev));
++ resource_release("core_latency", dev);
++ } else {
++ pr_debug("OMAP PM: add max DMA latency constraint: "
++ "dev %s, t = %ld usec\n", dev_name(dev), t);
++ resource_request("core_latency", dev, t);
++ }
++
++ /*
++ * For current Linux PM QOS params, this code should scan the
++ * list of maximum CPU and DMA latencies and select the
++ * smallest, then set cpu_dma_latency pm_qos_param
++ * accordingly.
++ *
++ * For future Linux PM QOS params, with separate CPU and DMA
++ * latency params, this code should just set the dma_latency param.
++ *
++ * TI CDP code can call constraint_set here.
++ */
++
++}
++
++
++/*
++ * DSP Bridge-specific constraints
++ */
++
++const struct omap_opp *omap_pm_dsp_get_opp_table(void)
++{
++ pr_debug("OMAP PM: DSP request for OPP table\n");
++
++ /*
++ * Return DSP frequency table here: The final item in the
++ * array should have .rate = .opp_id = 0.
++ */
++
++ return NULL;
++}
++
++void omap_pm_dsp_set_min_opp(u8 opp_id)
++{
++ if (opp_id == 0) {
++ WARN_ON(1);
++ return;
++ }
++
++ pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id);
++
++ /*
++ *
++ * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we
++ * can just test to see which is higher, the CPU's desired OPP
++ * ID or the DSP's desired OPP ID, and use whichever is
++ * highest.
++ *
++ * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP
++ * rate is keyed on MPU speed, not the OPP ID. So we need to
++ * map the OPP ID to the MPU speed for use with clk_set_rate()
++ * if it is higher than the current OPP clock rate.
++ *
++ */
++}
++
++
++u8 omap_pm_dsp_get_opp(void)
++{
++ pr_debug("OMAP PM: DSP requests current DSP OPP ID\n");
++
++ /*
++ * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock
++ *
++ * CDP12.14+:
++ * Call clk_get_rate() on the OPP custom clock, map that to an
++ * OPP ID using the tables defined in board-*.c/chip-*.c files.
++ */
++
++ return 0;
++}
++
++/*
++ * CPUFreq-originated constraint
++ *
++ * In the future, this should be handled by custom OPP clocktype
++ * functions.
++ */
++
++struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void)
++{
++ pr_debug("OMAP PM: CPUFreq request for frequency table\n");
++
++ /*
++ * Return CPUFreq frequency table here: loop over
++ * all VDD1 clkrates, pull out the mpu_ck frequencies, build
++ * table
++ */
++
++ return NULL;
++}
++
++void omap_pm_cpu_set_freq(unsigned long f)
++{
++ if (f == 0) {
++ WARN_ON(1);
++ return;
++ }
++
++ pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n",
++ f);
++
++ /*
++ * For l-o dev tree, determine whether MPU freq or DSP OPP id
++ * freq is higher. Find the OPP ID corresponding to the
++ * higher frequency. Call clk_round_rate() and clk_set_rate()
++ * on the OPP custom clock.
++ *
++ * CDP should just be able to set the VDD1 OPP clock rate here.
++ */
++}
++
++unsigned long omap_pm_cpu_get_freq(void)
++{
++ pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n");
++
++ /*
++ * Call clk_get_rate() on the mpu_ck.
++ */
++
++ return 0;
++}
++
++struct device omap_pm_dev;
++
++/*
++ * Powerdomain usecounting hooks
++ */
++
++void omap_pm_pwrdm_active(struct powerdomain *pwrdm)
++{
++ char *res_name;
++
++ if (!pwrdm) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (!strcmp(pwrdm->name, "wkup_pwrdm") ||
++ !strcmp(pwrdm->name, "core_pwrdm"))
++ return;
++
++ pr_debug("OMAP PM: powerdomain %s is becoming active\n", pwrdm->name);
++
++ res_name = get_lat_res_name(pwrdm->name);
++ /* Request for a zero latency which puts the Power Domain in ON state*/
++ resource_request(res_name, &omap_pm_dev, 0);
++ return;
++}
++
++void omap_pm_pwrdm_inactive(struct powerdomain *pwrdm)
++{
++ char *res_name;
++
++ if (!pwrdm) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (!strcmp(pwrdm->name, "wkup_pwrdm") ||
++ !strcmp(pwrdm->name, "core_pwrdm"))
++ return;
++
++ pr_debug("OMAP PM: powerdomain %s is becoming inactive\n",
++ pwrdm->name);
++
++ res_name = get_lat_res_name(pwrdm->name);
++ /* Release the latency requested */
++ resource_release(res_name, &omap_pm_dev);
++ return;
++}
++
++/*
++ * Should be called before clk framework since clk fw will call
++ * omap_pm_pwrdm_{in,}active()
++ */
++int __init omap_pm_if_early_init(void)
++{
++ return 0;
++}
++
++/* Must be called after clock framework is initialized */
++int __init omap_pm_if_init(struct omap_opp *mpu_opp_table,
++ struct omap_opp *dsp_opp_table)
++{
++ mpu_opps = mpu_opp_table;
++ dsp_opps = dsp_opp_table;
++ resource_init(resources_omap);
++ return 0;
++}
++
++void omap_pm_if_exit(void)
++{
++ /* Deallocate CPUFreq frequency table here */
++}
++
+Index: linux-omap-2.6/arch/arm/mach-omap2/clockdomain.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/clockdomain.c 2008-08-11
+17:12:19.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/clockdomain.c 2008-08-11
+17:14:31.000000000 +0530
+@@ -35,6 +35,7 @@
+
+ #include <asm/arch/powerdomain.h>
+ #include <asm/arch/clockdomain.h>
++#include <asm/arch/omap-pm.h>
+
+ /* clkdm_list contains all registered struct clockdomains */
+ static LIST_HEAD(clkdm_list);
+@@ -561,6 +562,9 @@ int omap2_clkdm_clk_enable(struct clockd
+ else
+ omap2_clkdm_wakeup(clkdm);
+
++ /*Hook to inform the OMAP PM layer that the pwrdm has become active */
++ omap_pm_pwrdm_active(clkdm->pwrdm.ptr);
++
+ return 0;
+ }
+
+@@ -612,6 +616,9 @@ int omap2_clkdm_clk_disable(struct clock
+ else
+ omap2_clkdm_sleep(clkdm);
+
++ /*Hook to inform the OMAP PM layer that the pwrdm has become inactive */
++ omap_pm_pwrdm_inactive(clkdm->pwrdm.ptr);
++
+ return 0;
+ }
+
+Index: linux-omap-2.6/include/asm-arm/arch-omap/powerdomain.h
+===================================================================
+--- linux-omap-2.6.orig/include/asm-arm/arch-omap/powerdomain.h 2008-08-11
+17:12:19.000000000 +0530
++++ linux-omap-2.6/include/asm-arm/arch-omap/powerdomain.h 2008-08-11
+17:14:31.000000000 +0530
+@@ -148,6 +148,7 @@ int pwrdm_read_next_pwrst(struct powerdo
+ int pwrdm_read_pwrst(struct powerdomain *pwrdm);
+ int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm);
+ int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm);
++int pwrdm_read_pwrst(struct powerdomain *pwrdm);
+
+ int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst);
+ int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst);
+Index: linux-omap-2.6/arch/arm/mach-omap2/Makefile
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/Makefile 2008-08-11
+17:12:19.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/Makefile 2008-08-11 17:14:31.000000000
++0530
+@@ -34,6 +34,7 @@ obj-$(CONFIG_OMAP_SMARTREFLEX) += smart
+ # Clock framework
+ obj-$(CONFIG_ARCH_OMAP2) += clock24xx.o
+ obj-$(CONFIG_ARCH_OMAP3) += clock34xx.o
++obj-$(CONFIG_OMAP_PM_SRF) += resource34xx.o
+
+ # DSP
+ obj-$(CONFIG_OMAP_MMU_FWK) += mmu_mach.o
+Index: linux-omap-2.6/arch/arm/plat-omap/Kconfig
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/plat-omap/Kconfig 2008-08-11
+17:12:25.000000000 +0530
++++ linux-omap-2.6/arch/arm/plat-omap/Kconfig 2008-08-11 17:14:31.000000000 +0530
+@@ -258,6 +258,9 @@ config OMAP_PM_NONE
+ config OMAP_PM_NOOP
+ bool "No-op/debug PM layer"
+
++config OMAP_PM_SRF
++ bool "PM layer implemented using SRF"
++
+ endchoice
+
+ endif
+Index: linux-omap-2.6/arch/arm/plat-omap/Makefile
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/plat-omap/Makefile 2008-08-11
+17:12:25.000000000 +0530
++++ linux-omap-2.6/arch/arm/plat-omap/Makefile 2008-08-11 17:14:31.000000000 +0530
+@@ -29,4 +29,6 @@ obj-$(CONFIG_OMAP_MMU_FWK) += mmu.o
+ # OMAP mailbox framework
+ obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
+
+-obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
+\ No newline at end of file
++obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
++obj-$(CONFIG_OMAP_PM_SRF) += omap-pm-srf.o \
++ resource.o
+Index: linux-omap-2.6/include/asm-arm/arch-omap/resource.h
+===================================================================
+--- linux-omap-2.6.orig/include/asm-arm/arch-omap/resource.h 2008-08-11
+17:12:30.000000000 +0530
++++ linux-omap-2.6/include/asm-arm/arch-omap/resource.h 2008-08-11
+17:14:31.000000000 +0530
+@@ -85,6 +85,7 @@ struct users_list {
+ u8 usage;
+ };
+
++extern struct shared_resource *resources_omap[];
+ /* Shared resource Framework API's */
+ void resource_init(struct shared_resource **resources);
+ int resource_register(struct shared_resource *res);
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/packages/linux/linux-omap2-git/beagleboard/05-omappm-virtualclocks.eml b/packages/linux/linux-omap2-git/beagleboard/05-omappm-virtualclocks.eml
new file mode 100644
index 0000000000..0aaed7b91c
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/05-omappm-virtualclocks.eml
@@ -0,0 +1,456 @@
+The patch defines virtual nodes for VDD1 and VDD2
+
+Signed-off-by: Rajendra Nayak <rnayak@ti.com>
+---
+ arch/arm/mach-omap2/board-3430sdp.c | 38 +++++
+ arch/arm/mach-omap2/clock34xx.c | 206 +++++++++++++++++++++++++-----
+ arch/arm/mach-omap2/clock34xx.h | 29 ++++
+ include/asm-arm/arch-omap/board-3430sdp.h | 35 +++++
+ include/asm-arm/arch-omap/clock.h | 8 +
+ 5 files changed, 287 insertions(+), 29 deletions(-)
+
+Index: linux-omap-2.6/arch/arm/mach-omap2/clock34xx.h
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/clock34xx.h 2008-08-06
+14:55:12.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/clock34xx.h 2008-08-07
+15:07:19.000000000 +0530
+@@ -36,6 +36,14 @@ static int omap3_noncore_dpll_enable(str
+ static void omap3_noncore_dpll_disable(struct clk *clk);
+ static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
+ static int omap3_core_dpll_m2_set_rate(struct clk *clk, unsigned long rate);
++static void omap3_table_recalc(struct clk *clk);
++static long omap3_round_to_table_rate(struct clk *clk, unsigned long rate);
++static int omap3_select_table_rate(struct clk *clk, unsigned long rate);
++
++extern struct vdd_prcm_config vdd1_rate_table[];
++extern struct vdd_prcm_config vdd2_rate_table[];
++extern struct vdd_prcm_config iva2_rate_table[];
++
+
+ /* Maximum DPLL multiplier, divider values for OMAP3 */
+ #define OMAP3_MAX_DPLL_MULT 2048
+@@ -3064,6 +3072,24 @@ static struct clk wdt1_fck = {
+ .recalc = &followparent_recalc,
+ };
+
++static struct clk virt_vdd1_prcm_set = {
++ .name = "virt_vdd1_prcm_set",
++ .flags = CLOCK_IN_OMAP343X | VIRTUAL_CLOCK | ALWAYS_ENABLED,
++ .parent = &mpu_ck, /* Indexed by mpu speed, no parent */
++ .recalc = &omap3_table_recalc, /*sets are keyed on mpu rate */
++ .set_rate = &omap3_select_table_rate,
++ .round_rate = &omap3_round_to_table_rate,
++};
++
++static struct clk virt_vdd2_prcm_set = {
++ .name = "virt_vdd2_prcm_set",
++ .flags = CLOCK_IN_OMAP343X | VIRTUAL_CLOCK | ALWAYS_ENABLED,
++ .parent = &core_ck,
++ .recalc = &omap3_table_recalc,
++ .set_rate = &omap3_select_table_rate,
++ .round_rate = &omap3_round_to_table_rate,
++};
++
+ static struct clk *onchip_34xx_clks[] __initdata = {
+ &omap_32k_fck,
+ &virt_12m_ck,
+@@ -3276,6 +3302,9 @@ static struct clk *onchip_34xx_clks[] __
+ &secure_32k_fck,
+ &gpt12_fck,
+ &wdt1_fck,
++ /* virtual group clock */
++ &virt_vdd1_prcm_set,
++ &virt_vdd2_prcm_set,
+ };
+
+ #endif
+Index: linux-omap-2.6/arch/arm/mach-omap2/clock34xx.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/clock34xx.c 2008-08-07
+14:34:23.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/clock34xx.c 2008-08-07
+15:07:19.000000000 +0530
+@@ -25,6 +25,7 @@
+ #include <linux/clk.h>
+ #include <linux/io.h>
+ #include <linux/limits.h>
++#include <linux/err.h>
+
+ #include <asm/arch/clock.h>
+ #include <asm/arch/sram.h>
+@@ -45,6 +46,32 @@
+
+ #define MAX_DPLL_WAIT_TRIES 1000000
+
++struct vdd_prcm_config *curr_vdd1_prcm_set;
++struct vdd_prcm_config *curr_vdd2_prcm_set;
++static struct clk *dpll1_clk, *dpll2_clk, *dpll3_clk;
++
++#ifndef CONFIG_CPU_FREQ
++static unsigned long compute_lpj(unsigned long ref, u_int div, u_int mult)
++{
++ unsigned long new_jiffy_l, new_jiffy_h;
++
++ /*
++ * Recalculate loops_per_jiffy. We do it this way to
++ * avoid math overflow on 32-bit machines. Maybe we
++ * should make this architecture dependent? If you have
++ * a better way of doing this, please replace!
++ *
++ * new = old * mult / div
++ */
++ new_jiffy_h = ref / div;
++ new_jiffy_l = (ref % div) / 100;
++ new_jiffy_h *= mult;
++ new_jiffy_l = new_jiffy_l * mult / div;
++
++ return new_jiffy_h + new_jiffy_l * 100;
++}
++#endif
++
+ /**
+ * omap3_dpll_recalc - recalculate DPLL rate
+ * @clk: DPLL struct clk
+@@ -644,15 +671,6 @@ void omap2_clk_prepare_for_reboot(void)
+ */
+ static int __init omap2_clk_arch_init(void)
+ {
+- if (!mpurate)
+- return -EINVAL;
+-
+- /* REVISIT: not yet ready for 343x */
+-#if 0
+- if (omap2_select_table_rate(&virt_prcm_set, mpurate))
+- printk(KERN_ERR "Could not find matching MPU rate\n");
+-#endif
+-
+ recalculate_root_clocks();
+
+ printk(KERN_INFO "Switched to new clocking rate (Crystal/DPLL3/MPU): "
+@@ -670,6 +688,9 @@ int __init omap2_clk_init(void)
+ struct clk **clkp;
+ /* u32 clkrate; */
+ u32 cpu_clkflg;
++ unsigned long mpu_speed, core_speed;
++ struct vdd_prcm_config *prcm_vdd;
++
+
+ /* REVISIT: Ultimately this will be used for multiboot */
+ #if 0
+@@ -712,22 +733,31 @@ int __init omap2_clk_init(void)
+ }
+ }
+
+- /* REVISIT: Not yet ready for OMAP3 */
+-#if 0
+- /* Check the MPU rate set by bootloader */
+- clkrate = omap2_get_dpll_rate_24xx(&dpll_ck);
+- for (prcm = rate_table; prcm->mpu_speed; prcm++) {
+- if (!(prcm->flags & cpu_mask))
+- continue;
+- if (prcm->xtal_speed != sys_ck.rate)
+- continue;
+- if (prcm->dpll_speed <= clkrate)
+- break;
++ recalculate_root_clocks();
++
++ dpll1_clk = clk_get(NULL, "dpll1_ck");
++ dpll2_clk = clk_get(NULL, "dpll2_ck");
++ dpll3_clk = clk_get(NULL, "dpll3_ck");
++
++#ifdef CONFIG_MACH_OMAP_3430SDP
++ mpu_speed = dpll1_clk->rate;
++ prcm_vdd = vdd1_rate_table + MAX_VDD1_OPP;
++ for (; prcm_vdd->speed; prcm_vdd--) {
++ if (prcm_vdd->speed <= mpu_speed) {
++ curr_vdd1_prcm_set = prcm_vdd;
++ break;
++ }
+ }
+- curr_prcm_set = prcm;
+-#endif
+
+- recalculate_root_clocks();
++ core_speed = dpll3_clk->rate;
++ prcm_vdd = vdd2_rate_table + MAX_VDD2_OPP;
++ for (; prcm_vdd->speed; prcm_vdd--) {
++ if (prcm_vdd->speed <= core_speed) {
++ curr_vdd2_prcm_set = prcm_vdd;
++ break;
++ }
++ }
++#endif
+
+ printk(KERN_INFO "Clocking rate (Crystal/DPLL/ARM core): "
+ "%ld.%01ld/%ld/%ld MHz\n",
+@@ -740,13 +770,131 @@ int __init omap2_clk_init(void)
+ */
+ clk_enable_init_clocks();
+
+- /* Avoid sleeping during omap2_clk_prepare_for_reboot() */
+- /* REVISIT: not yet ready for 343x */
+-#if 0
+- vclk = clk_get(NULL, "virt_prcm_set");
+- sclk = clk_get(NULL, "sys_ck");
+-#endif
+ return 0;
+ }
+
++inline unsigned int get_freq(struct vdd_prcm_config *opp_freq_table,
++ unsigned long opp)
++{
++ struct vdd_prcm_config *prcm_config;
++ prcm_config = opp_freq_table;
++
++ for (; prcm_config->opp; prcm_config--)
++ if (prcm_config->opp == opp)
++ return prcm_config->speed;
++ return 0;
++}
++
++inline unsigned int get_opp(struct vdd_prcm_config *opp_freq_table,
++ unsigned long freq)
++{
++ struct vdd_prcm_config *prcm_config;
++ prcm_config = opp_freq_table;
++
++ if (prcm_config->speed <= freq)
++ return prcm_config->opp; /* Return the Highest OPP */
++ for (; prcm_config->speed; prcm_config--) {
++ if (prcm_config->speed < freq)
++ return (prcm_config+1)->opp;
++ else if (prcm_config->speed == freq)
++ return prcm_config->opp;
++ }
++ /* Return the least OPP */
++ return (prcm_config+1)->opp;
++}
++
++#ifdef CONFIG_MACH_OMAP_3430SDP
++static void omap3_table_recalc(struct clk *clk)
++{
++ if ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set))
++ return;
++
++ if ((curr_vdd1_prcm_set) && (clk == &virt_vdd1_prcm_set))
++ clk->rate = curr_vdd1_prcm_set->speed;
++ else if ((curr_vdd2_prcm_set) && (clk == &virt_vdd2_prcm_set))
++ clk->rate = curr_vdd2_prcm_set->speed;
++ pr_debug("CLK RATE:%lu\n", clk->rate);
++}
++
++static long omap3_round_to_table_rate(struct clk *clk, unsigned long rate)
++{
++ struct vdd_prcm_config *ptr;
++ long highest_rate;
++
++ if ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set))
++ return -EINVAL;
++
++ highest_rate = -EINVAL;
++
++ if (clk == &virt_vdd1_prcm_set)
++ ptr = vdd1_rate_table + MAX_VDD1_OPP;
++ else
++ ptr = vdd2_rate_table + MAX_VDD2_OPP;
++
++ for (; ptr->speed; ptr--) {
++ highest_rate = ptr->speed;
++ pr_debug("Highest speed : %lu, rate: %lu\n", highest_rate,
++ rate);
++ if (ptr->speed <= rate)
++ break;
++ }
++ return highest_rate;
++}
++
++static int omap3_select_table_rate(struct clk *clk, unsigned long rate)
++{
++ struct vdd_prcm_config *prcm_vdd;
++ unsigned long found_speed = 0, curr_mpu_speed;
++ int index;
++
++ if ((clk != &virt_vdd1_prcm_set) && (clk != &virt_vdd2_prcm_set))
++ return -EINVAL;
++
++ if (clk == &virt_vdd1_prcm_set) {
++ prcm_vdd = vdd1_rate_table + MAX_VDD1_OPP;
++ index = MAX_VDD1_OPP;
++ } else if (clk == &virt_vdd2_prcm_set) {
++ prcm_vdd = vdd2_rate_table + MAX_VDD2_OPP;
++ index = MAX_VDD2_OPP;
++ }
++
++ for (; prcm_vdd->speed; prcm_vdd--, index--) {
++ if (prcm_vdd->speed <= rate) {
++ found_speed = prcm_vdd->speed;
++ pr_debug("Found speed = %lu\n", found_speed);
++ break;
++ }
++ }
++
++ if (!found_speed) {
++ printk(KERN_INFO "Could not set table rate to %luMHz\n",
++ rate / 1000000);
++ return -EINVAL;
++ }
++
++
++ if (clk == &virt_vdd1_prcm_set) {
++ curr_mpu_speed = curr_vdd1_prcm_set->speed;
++ clk_set_rate(dpll1_clk, prcm_vdd->speed);
++ clk_set_rate(dpll2_clk, iva2_rate_table[index].speed);
++ curr_vdd1_prcm_set = prcm_vdd;
++#ifndef CONFIG_CPU_FREQ
++ /*Update loops_per_jiffy if processor speed is being changed*/
++ loops_per_jiffy = compute_lpj(loops_per_jiffy,
++ curr_mpu_speed/1000, found_speed/1000);
+ #endif
++ } else {
++ clk_set_rate(dpll3_clk, prcm_vdd->speed);
++ curr_vdd2_prcm_set = prcm_vdd;
++ }
++ return 0;
++}
++#else /* CONFIG_MACH_OMAP_3430SDP */
++static void omap3_table_recalc(struct clk *clk) {}
++static long omap3_round_to_table_rate(struct clk *clk, unsigned long rate)
++{ return 0; }
++static int omap3_select_table_rate(struct clk *clk, unsigned long rate)
++{ return 0; }
++#endif /* CONFIG_MACH_OMAP_3430SDP */
++
++#endif /* CONFIG_ARCH_OMAP3 */
+Index: linux-omap-2.6/include/asm-arm/arch-omap/clock.h
+===================================================================
+--- linux-omap-2.6.orig/include/asm-arm/arch-omap/clock.h 2008-08-07
+14:34:23.000000000 +0530
++++ linux-omap-2.6/include/asm-arm/arch-omap/clock.h 2008-08-07
+15:07:19.000000000 +0530
+@@ -126,6 +126,14 @@ struct clk_functions {
+ #endif
+ };
+
++#ifdef CONFIG_ARCH_OMAP3
++struct vdd_prcm_config {
++ unsigned long speed;
++ unsigned long opp;
++ unsigned long flags;
++};
++#endif
++
+ extern unsigned int mpurate;
+
+ extern int clk_init(struct clk_functions *custom_clocks);
+Index: linux-omap-2.6/arch/arm/mach-omap2/board-3430sdp.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/board-3430sdp.c 2008-08-06
+14:55:12.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/board-3430sdp.c 2008-08-07
+15:07:50.000000000 +0530
+@@ -40,6 +40,7 @@
+ #include <asm/arch/keypad.h>
+ #include <asm/arch/dma.h>
+ #include <asm/arch/gpmc.h>
++#include <asm/arch/clock.h>
+ #include <linux/i2c/twl4030-rtc.h>
+
+ #include <asm/io.h>
+@@ -53,6 +54,43 @@
+ #define ENABLE_VAUX3_DEDICATED 0x03
+ #define ENABLE_VAUX3_DEV_GRP 0x20
+
++struct vdd_prcm_config vdd1_rate_table[] = {
++ {0, 0, 0},
++ /*OPP1*/
++ {S125M, VDD1_OPP1, 0},
++ /*OPP2*/
++ {S250M, VDD1_OPP2, 0},
++ /*OPP3*/
++ {S500M, VDD1_OPP3, 0},
++ /*OPP4*/
++ {S550M, VDD1_OPP4, 0},
++ /*OPP5*/
++ {S600M, VDD1_OPP5, 0},
++};
++
++struct vdd_prcm_config vdd2_rate_table[] = {
++ {0, 0, 0},
++ /*OPP1*/
++ {0, VDD2_OPP1, 0},
++ /*OPP2*/
++ {S83M, VDD2_OPP2, 0},
++ /*OPP3*/
++ {S166M, VDD2_OPP3, 0},
++};
++
++struct vdd_prcm_config iva2_rate_table[] = {
++ {0, 0, 0},
++ /*OPP1*/
++ {S90M, VDD1_OPP1, 0},
++ /*OPP2*/
++ {S180M, VDD1_OPP2, 0},
++ /*OPP3*/
++ {S360M, VDD1_OPP3, 0},
++ /*OPP4*/
++ {S400M, VDD1_OPP4, 0},
++ /*OPP5*/
++ {S430M, VDD1_OPP5, 0},
++};
+
+ #define TWL4030_MSECURE_GPIO 22
+
+Index: linux-omap-2.6/include/asm-arm/arch-omap/board-3430sdp.h
+===================================================================
+--- linux-omap-2.6.orig/include/asm-arm/arch-omap/board-3430sdp.h 2008-08-06
+14:55:22.000000000 +0530
++++ linux-omap-2.6/include/asm-arm/arch-omap/board-3430sdp.h 2008-08-07
+15:07:19.000000000 +0530
+@@ -68,5 +68,40 @@ extern void twl4030_bci_battery_init(voi
+ #define FLASH_SIZE_SDPV1 SZ_64M
+ #define FLASH_SIZE_SDPV2 SZ_128M
+
++/* MPU speeds */
++#define S600M 600000000
++#define S550M 550000000
++#define S500M 500000000
++#define S250M 250000000
++#define S125M 125000000
++
++/* IVA speeds */
++#define S430M 430000000
++#define S400M 400000000
++#define S360M 360000000
++#define S180M 180000000
++#define S90M 90000000
++
++/* L3 speeds */
++#define S83M 83000000
++#define S166M 166000000
++
++/* VDD1 OPPS */
++#define VDD1_OPP1 0x1
++#define VDD1_OPP2 0x2
++#define VDD1_OPP3 0x3
++#define VDD1_OPP4 0x4
++#define VDD1_OPP5 0x5
++
++/* VDD2 OPPS */
++#define VDD2_OPP1 0x1
++#define VDD2_OPP2 0x2
++#define VDD2_OPP3 0x3
++
++#define MIN_VDD1_OPP VDD1_OPP1
++#define MAX_VDD1_OPP VDD1_OPP5
++#define MIN_VDD2_OPP VDD2_OPP1
++#define MAX_VDD2_OPP VDD2_OPP3
++
+ #endif /* __ASM_ARCH_OMAP_3430SDP_H */
+
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/packages/linux/linux-omap2-git/beagleboard/06-omappm-opp-resource-modeling.eml b/packages/linux/linux-omap2-git/beagleboard/06-omappm-opp-resource-modeling.eml
new file mode 100644
index 0000000000..69ed0f748c
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/06-omappm-opp-resource-modeling.eml
@@ -0,0 +1,228 @@
+Adds OPP/Frequency resources to SRF
+
+Signed-off-by: Rajendra Nayak <rnayak@ti.com>
+---
+ arch/arm/mach-omap2/resource34xx.c | 101 +++++++++++++++++++++++++++++++++++++
+ arch/arm/mach-omap2/resource34xx.h | 74 +++++++++++++++++++++++++++
+ 2 files changed, 175 insertions(+)
+
+Index: linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/resource34xx.c 2008-08-07
+15:07:08.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c 2008-08-07
+15:09:01.000000000 +0530
+@@ -146,3 +146,104 @@ int set_pd_latency(struct shared_resourc
+ }
+ return 0;
+ }
++
++static struct clk *vdd1_clk;
++static struct clk *vdd2_clk;
++static struct device dummy_srf_dev;
++
++/**
++ * init_opp - Initialize the OPP resource
++ */
++void init_opp(struct shared_resource *resp)
++{
++ resp->no_of_users = 0;
++ /* Initialize the current level of the OPP resource
++ * to the opp set by u-boot.
++ */
++ if (strcmp(resp->name, "vdd1_opp") == 0) {
++ resp->curr_level = curr_vdd1_prcm_set->opp;
++ vdd1_clk = clk_get(NULL, "virt_vdd1_prcm_set");
++ } else if (strcmp(resp->name, "vdd2_opp") == 0) {
++ resp->curr_level = curr_vdd2_prcm_set->opp;
++ vdd2_clk = clk_get(NULL, "virt_vdd2_prcm_set");
++ }
++ return;
++}
++
++int set_opp(struct shared_resource *resp, u32 target_level)
++{
++#ifdef CONFIG_MACH_OMAP_3430SDP
++ unsigned long mpu_freq;
++ if (strcmp(resp->name, "vdd1_opp") == 0) {
++ mpu_freq = get_freq(vdd1_rate_table + MAX_VDD1_OPP,
++ target_level);
++ clk_set_rate(vdd1_clk, mpu_freq);
++ resp->curr_level = curr_vdd1_prcm_set->opp;
++ } else if (strcmp(resp->name, "vdd2_opp") == 0) {
++ /* Not supported yet */
++ }
++#endif
++ return 0;
++}
++
++/**
++ * validate_opp - Validates if valid VDD1 OPP's are passed as the
++ * target_level.
++ * VDD2 OPP levels are passed as L3 throughput, which are then mapped
++ * to an appropriate OPP.
++ */
++int validate_opp(struct shared_resource *resp, u32 target_level)
++{
++ return 0;
++}
++
++/**
++ * init_freq - Initialize the frequency resource.
++ */
++void init_freq(struct shared_resource *resp)
++{
++#ifdef CONFIG_MACH_OMAP_3430SDP
++ char *linked_res_name;
++ resp->no_of_users = 0;
++
++ linked_res_name = (char *)resp->resource_data;
++ /* Initialize the current level of the Freq resource
++ * to the frequency set by u-boot.
++ */
++ if (strcmp(resp->name, "mpu_freq") == 0)
++ /* MPU freq in Mhz */
++ resp->curr_level = curr_vdd1_prcm_set->speed;
++ else if (strcmp(resp->name, "dsp_freq") == 0)
++ /* DSP freq in Mhz */
++ resp->curr_level = get_freq(iva2_rate_table + MAX_VDD2_OPP,
++ curr_vdd1_prcm_set->opp);
++#endif
++ return;
++}
++
++int set_freq(struct shared_resource *resp, u32 target_level)
++{
++#ifdef CONFIG_MACH_OMAP_3430SDP
++ unsigned int vdd1_opp;
++
++ if (strcmp(resp->name, "mpu_freq") == 0)
++ vdd1_opp = get_opp(vdd1_rate_table + MAX_VDD1_OPP,
++ target_level);
++ else if (strcmp(resp->name, "dsp_freq") == 0)
++ vdd1_opp = get_opp(iva2_rate_table + MAX_VDD1_OPP,
++ target_level);
++
++ if (vdd1_opp == MIN_VDD1_OPP)
++ resource_release("vdd1_opp", &dummy_srf_dev);
++ else
++ resource_request("vdd1_opp", &dummy_srf_dev, vdd1_opp);
++
++ resp->curr_level = target_level;
++#endif
++ return 0;
++}
++
++int validate_freq(struct shared_resource *resp, u32 target_level)
++{
++ return 0;
++}
+Index: linux-omap-2.6/arch/arm/mach-omap2/resource34xx.h
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/resource34xx.h 2008-08-07
+15:07:02.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/resource34xx.h 2008-08-07
+15:31:42.000000000 +0530
+@@ -22,8 +22,17 @@
+ #define __ARCH_ARM_MACH_OMAP2_RESOURCE_H
+
+ #include <asm/arch/resource.h>
++#include <linux/clk.h>
++#include <asm/arch/clock.h>
+ #include <asm/arch/powerdomain.h>
+
++extern struct vdd_prcm_config *curr_vdd1_prcm_set;
++extern struct vdd_prcm_config *curr_vdd2_prcm_set;
++extern unsigned int get_freq(struct vdd_prcm_config *, unsigned long);
++extern unsigned int get_opp(struct vdd_prcm_config *, unsigned long);
++extern struct vdd_prcm_config vdd1_rate_table[];
++extern struct vdd_prcm_config vdd2_rate_table[];
++extern struct vdd_prcm_config iva2_rate_table[];
+ /**
+ * mpu_latency/core_latency are used to control the cpuidle C state.
+ */
+@@ -207,6 +216,66 @@ static struct shared_resource emu_pwrdm_
+ .ops = &pd_lat_res_ops,
+ };
+
++void init_opp(struct shared_resource *resp);
++int set_opp(struct shared_resource *resp, u32 target_level);
++int validate_opp(struct shared_resource *resp, u32 target_level);
++void init_freq(struct shared_resource *resp);
++int set_freq(struct shared_resource *resp, u32 target_level);
++int validate_freq(struct shared_resource *resp, u32 target_level);
++
++struct bus_throughput_db {
++ /* Throughput for each OPP/Freq of the bus */
++ unsigned long throughput[3];
++};
++
++static struct shared_resource_ops opp_res_ops = {
++ .init = init_opp,
++ .change_level = set_opp,
++ .validate_level = validate_opp,
++};
++
++static struct shared_resource vdd1_opp = {
++ .name = "vdd1_opp",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .ops = &opp_res_ops,
++};
++
++/* Throughput in KiB/s */
++static struct bus_throughput_db l3_throughput_db = {
++ .throughput[0] = 0,
++ .throughput[1] = 100,
++ .throughput[2] = 250,
++};
++
++static struct shared_resource vdd2_opp = {
++ .name = "vdd2_opp",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .resource_data = &l3_throughput_db,
++ .ops = &opp_res_ops,
++};
++
++static char linked_res[] = "vdd1_opp";
++
++static struct shared_resource_ops freq_res_ops = {
++ .init = init_freq,
++ .change_level = set_freq,
++ .validate_level = validate_freq,
++};
++
++static struct shared_resource mpu_freq = {
++ .name = "mpu_freq",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .resource_data = &linked_res,
++ .ops = &freq_res_ops,
++};
++
++static struct shared_resource dsp_freq = {
++ .name = "dsp_freq",
++ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
++ .resource_data = &linked_res,
++ .ops = &freq_res_ops,
++};
++
+ struct shared_resource *resources_omap[] __initdata = {
+ &mpu_latency,
+ &core_latency,
+@@ -220,6 +289,11 @@ struct shared_resource *resources_omap[]
+ &neon_pwrdm_latency,
+ &usbhost_pwrdm_latency,
+ &emu_pwrdm_latency,
++ /* OPP/frequency resources */
++ &vdd1_opp,
++ &vdd2_opp,
++ &mpu_freq,
++ &dsp_freq,
+ NULL
+ };
+
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/packages/linux/linux-omap2-git/beagleboard/07-omappm-srf-updates.eml b/packages/linux/linux-omap2-git/beagleboard/07-omappm-srf-updates.eml
new file mode 100644
index 0000000000..735e991298
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/07-omappm-srf-updates.eml
@@ -0,0 +1,173 @@
+Updates the omap-pm apis with calls to SRF implementation
+
+Signed-off-by: Rajendra Nayak <rnayak@ti.com>
+---
+ arch/arm/plat-omap/omap-pm-srf.c | 84 +++++++++------------------------------
+ 1 files changed, 20 insertions(+), 64 deletions(-)
+
+Index: linux-omap-2.6/arch/arm/plat-omap/omap-pm-srf.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/plat-omap/omap-pm-srf.c 2008-07-21
+12:10:19.824596984 +0530
++++ linux-omap-2.6/arch/arm/plat-omap/omap-pm-srf.c 2008-07-21
+12:10:21.626540178 +0530
+@@ -25,6 +25,7 @@
+ #include <linux/init.h>
+ #include <linux/cpufreq.h>
+ #include <linux/device.h>
++#include <linux/module.h>
+
+ /* Interface documentation is in asm/arch/omap-pm.h */
+ #include <asm/arch/omap-pm.h>
+@@ -121,6 +122,7 @@ void omap_pm_set_max_dev_wakeup_lat(stru
+ WARN_ON(1);
+ return;
+ };
++
+ /* Look for the devices Power Domain */
+ /* TODO: Put this back in once tiocp layer is available
+ tiocp_dev = container_of(dev, struct tiocp, dev);
+@@ -138,19 +140,6 @@ void omap_pm_set_max_dev_wakeup_lat(stru
+ res_name = get_lat_res_name(pwrdm_dev->name);
+ resource_request(res_name, dev, t);
+ }
+-
+- /*
+- * For current Linux, this needs to map the device to a
+- * powerdomain, then go through the list of current max lat
+- * constraints on that powerdomain and find the smallest. If
+- * the latency constraint has changed, the code should
+- * recompute the state to enter for the next powerdomain
+- * state. Conceivably, this code should also determine
+- * whether to actually disable the device clocks or not,
+- * depending on how long it takes to re-enable the clocks.
+- *
+- * TI CDP code can call constraint_set here.
+- */
+ }
+
+ void omap_pm_set_max_sdma_lat(struct device *dev, long t)
+@@ -169,21 +158,9 @@ void omap_pm_set_max_sdma_lat(struct dev
+ "dev %s, t = %ld usec\n", dev_name(dev), t);
+ resource_request("core_latency", dev, t);
+ }
+-
+- /*
+- * For current Linux PM QOS params, this code should scan the
+- * list of maximum CPU and DMA latencies and select the
+- * smallest, then set cpu_dma_latency pm_qos_param
+- * accordingly.
+- *
+- * For future Linux PM QOS params, with separate CPU and DMA
+- * latency params, this code should just set the dma_latency param.
+- *
+- * TI CDP code can call constraint_set here.
+- */
+-
+ }
+
++static struct device dummy_dsp_dev;
+
+ /*
+ * DSP Bridge-specific constraints
+@@ -200,6 +177,7 @@ const struct omap_opp *omap_pm_dsp_get_o
+
+ return NULL;
+ }
++EXPORT_SYMBOL(omap_pm_dsp_get_opp_table);
+
+ void omap_pm_dsp_set_min_opp(u8 opp_id)
+ {
+@@ -210,36 +188,21 @@ void omap_pm_dsp_set_min_opp(u8 opp_id)
+
+ pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id);
+
+- /*
+- *
+- * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we
+- * can just test to see which is higher, the CPU's desired OPP
+- * ID or the DSP's desired OPP ID, and use whichever is
+- * highest.
+- *
+- * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP
+- * rate is keyed on MPU speed, not the OPP ID. So we need to
+- * map the OPP ID to the MPU speed for use with clk_set_rate()
+- * if it is higher than the current OPP clock rate.
+- *
+- */
+-}
++ /* For now pass a dummy_dev struct for SRF to identify the caller.
++ * Maybe its good to have DSP pass this as an argument
++ */
++ resource_request("vdd1_opp", &dummy_dsp_dev, opp_id);
++ return;
+
++}
++EXPORT_SYMBOL(omap_pm_dsp_set_min_opp);
+
+ u8 omap_pm_dsp_get_opp(void)
+ {
+ pr_debug("OMAP PM: DSP requests current DSP OPP ID\n");
+-
+- /*
+- * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock
+- *
+- * CDP12.14+:
+- * Call clk_get_rate() on the OPP custom clock, map that to an
+- * OPP ID using the tables defined in board-*.c/chip-*.c files.
+- */
+-
+- return 0;
++ return resource_get_level("vdd1_opp");
+ }
++EXPORT_SYMBOL(omap_pm_dsp_get_opp);
+
+ /*
+ * CPUFreq-originated constraint
+@@ -261,6 +224,8 @@ struct cpufreq_frequency_table **omap_pm
+ return NULL;
+ }
+
++static struct device dummy_cpufreq_dev;
++
+ void omap_pm_cpu_set_freq(unsigned long f)
+ {
+ if (f == 0) {
+@@ -271,26 +236,17 @@ void omap_pm_cpu_set_freq(unsigned long
+ pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n",
+ f);
+
+- /*
+- * For l-o dev tree, determine whether MPU freq or DSP OPP id
+- * freq is higher. Find the OPP ID corresponding to the
+- * higher frequency. Call clk_round_rate() and clk_set_rate()
+- * on the OPP custom clock.
+- *
+- * CDP should just be able to set the VDD1 OPP clock rate here.
+- */
++ resource_request("mpu_freq", &dummy_cpufreq_dev, f);
++ return;
+ }
++EXPORT_SYMBOL(omap_pm_cpu_set_freq);
+
+ unsigned long omap_pm_cpu_get_freq(void)
+ {
+ pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n");
+-
+- /*
+- * Call clk_get_rate() on the mpu_ck.
+- */
+-
+- return 0;
++ return resource_get_level("mpu_freq");
+ }
++EXPORT_SYMBOL(omap_pm_cpu_get_freq);
+
+ struct device omap_pm_dev;
+
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/packages/linux/linux-omap2-git/beagleboard/08-omappm-voltagescaling.eml b/packages/linux/linux-omap2-git/beagleboard/08-omappm-voltagescaling.eml
new file mode 100644
index 0000000000..a7885774f4
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/08-omappm-voltagescaling.eml
@@ -0,0 +1,96 @@
+Adds Voltage scaling support
+
+Signed-off-by: Rajendra Nayak <rnayak@ti.com>
+---
+ arch/arm/mach-omap2/board-3430sdp.c | 12 ++++++++++++
+ arch/arm/mach-omap2/resource34xx.c | 17 ++++++++++++++++-
+ arch/arm/mach-omap2/resource34xx.h | 3 +++
+ 3 files changed, 31 insertions(+), 1 deletion(-)
+
+Index: linux-omap-2.6/arch/arm/mach-omap2/board-3430sdp.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/board-3430sdp.c 2008-08-11
+17:16:07.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/board-3430sdp.c 2008-08-11
+17:17:58.000000000 +0530
+@@ -94,6 +94,18 @@ struct vdd_prcm_config iva2_rate_table[]
+
+ #define TWL4030_MSECURE_GPIO 22
+
++u8 vdd1_volts[MAX_VDD1_OPP] = {
++ /* Vsel corresponding to 0.9V (OPP1), 1.00V (OPP2),
++ * 1.20V (OPP3), 1.27V (OPP4), 1.35 (OPP5)
++ */
++ 0x18, 0x20, 0x30, 0x36, 0x3C
++};
++
++u8 vdd2_volts[MAX_VDD2_OPP] = {
++ /* Vsel corresponding to 0.9V (OPP1), 1.00V (OPP2), 1.15 (OPP3) */
++ 0x18, 0x20, 0x2C
++};
++
+ static struct resource sdp3430_smc91x_resources[] = {
+ [0] = {
+ .start = OMAP34XX_ETHR_START,
+Index: linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/resource34xx.c 2008-08-11
+17:17:23.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c 2008-08-11
+17:22:02.000000000 +0530
+@@ -19,6 +19,7 @@
+ #include <linux/pm_qos_params.h>
+ #include <asm/arch/powerdomain.h>
+ #include <asm/arch/clockdomain.h>
++#include "smartreflex.h"
+ #include "resource34xx.h"
+
+ /**
+@@ -174,10 +175,24 @@ int set_opp(struct shared_resource *resp
+ {
+ #ifdef CONFIG_MACH_OMAP_3430SDP
+ unsigned long mpu_freq;
++
++ if (resp->curr_level == target_level)
++ return 0;
++
+ if (strcmp(resp->name, "vdd1_opp") == 0) {
+ mpu_freq = get_freq(vdd1_rate_table + MAX_VDD1_OPP,
+ target_level);
+- clk_set_rate(vdd1_clk, mpu_freq);
++ if (resp->curr_level > target_level) {
++ /* Scale Frequency and then voltage */
++ clk_set_rate(vdd1_clk, mpu_freq);
++ sr_voltagescale_vcbypass(PRCM_VDD1,
++ vdd1_volts[target_level-1]);
++ } else {
++ /* Scale Voltage and then frequency */
++ sr_voltagescale_vcbypass(PRCM_VDD1,
++ vdd1_volts[target_level-1]);
++ clk_set_rate(vdd1_clk, mpu_freq);
++ }
+ resp->curr_level = curr_vdd1_prcm_set->opp;
+ } else if (strcmp(resp->name, "vdd2_opp") == 0) {
+ /* Not supported yet */
+Index: linux-omap-2.6/arch/arm/mach-omap2/resource34xx.h
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/resource34xx.h 2008-08-11
+17:17:23.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/resource34xx.h 2008-08-11
+17:17:58.000000000 +0530
+@@ -33,6 +33,9 @@ extern unsigned int get_opp(struct vdd_p
+ extern struct vdd_prcm_config vdd1_rate_table[];
+ extern struct vdd_prcm_config vdd2_rate_table[];
+ extern struct vdd_prcm_config iva2_rate_table[];
++extern u8 vdd1_volts[];
++extern u8 vdd2_volts[];
++extern int sr_voltagescale_vcbypass(u32 target_opp, u8 vsel);
+ /**
+ * mpu_latency/core_latency are used to control the cpuidle C state.
+ */
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/packages/linux/linux-omap2-git/beagleboard/09-omappm-vdd2-scaling.eml b/packages/linux/linux-omap2-git/beagleboard/09-omappm-vdd2-scaling.eml
new file mode 100644
index 0000000000..532a9f7975
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/09-omappm-vdd2-scaling.eml
@@ -0,0 +1,102 @@
+Adds VDD2 scaling support
+
+Signed-off-by: Rajendra Nayak <rnayak@ti.com>
+---
+ arch/arm/mach-omap2/resource34xx.c | 35 +++++++++++++++++++++++++++++++++--
+ arch/arm/plat-omap/omap-pm-srf.c | 15 +++++----------
+ 2 files changed, 38 insertions(+), 12 deletions(-)
+
+Index: linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/resource34xx.c 2008-07-21
+12:10:22.032527379 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c 2008-07-21
+12:10:22.479513287 +0530
+@@ -174,7 +174,9 @@ void init_opp(struct shared_resource *re
+ int set_opp(struct shared_resource *resp, u32 target_level)
+ {
+ #ifdef CONFIG_MACH_OMAP_3430SDP
+- unsigned long mpu_freq;
++ unsigned long mpu_freq, l3_freq, tput;
++ int ind;
++ struct bus_throughput_db *tput_db;
+
+ if (resp->curr_level == target_level)
+ return 0;
+@@ -195,7 +197,36 @@ int set_opp(struct shared_resource *resp
+ }
+ resp->curr_level = curr_vdd1_prcm_set->opp;
+ } else if (strcmp(resp->name, "vdd2_opp") == 0) {
+- /* Not supported yet */
++ tput_db = resp->resource_data;
++ tput = target_level;
++ /* using the throughput db map to the appropriate L3 Freq */
++ for (ind = 1; ind < MAX_VDD2_OPP; ind++)
++ if (tput_db->throughput[ind] > tput)
++ target_level = ind;
++
++ /* Set the highest OPP possible */
++ if (ind == MAX_VDD2_OPP)
++ target_level = ind-1;
++
++ if (resp->curr_level == target_level)
++ return 0;
++
++ resp->curr_level = target_level;
++
++ l3_freq = get_freq(vdd2_rate_table + MAX_VDD2_OPP,
++ target_level);
++ if (resp->curr_level > target_level) {
++ /* Scale Frequency and then voltage */
++ clk_set_rate(vdd2_clk, l3_freq);
++ sr_voltagescale_vcbypass(PRCM_VDD2,
++ vdd2_volts[target_level-1]);
++ } else {
++ /* Scale Voltage and then frequency */
++ sr_voltagescale_vcbypass(PRCM_VDD2,
++ vdd2_volts[target_level-1]);
++ clk_set_rate(vdd1_clk, l3_freq);
++ }
++ resp->curr_level = curr_vdd2_prcm_set->opp;
+ }
+ #endif
+ return 0;
+Index: linux-omap-2.6/arch/arm/plat-omap/omap-pm-srf.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/plat-omap/omap-pm-srf.c 2008-07-21
+12:10:21.626540178 +0530
++++ linux-omap-2.6/arch/arm/plat-omap/omap-pm-srf.c 2008-07-21
+12:10:22.479513287 +0530
+@@ -95,21 +95,16 @@ void omap_pm_set_min_bus_tput(struct dev
+ return;
+ };
+
+- if (r == 0)
++ if (r == 0) {
+ pr_debug("OMAP PM: remove min bus tput constraint: "
+ "dev %s for agent_id %d\n", dev_name(dev), agent_id);
+- else
++ resource_release("vdd2_opp", r);
++ } else {
+ pr_debug("OMAP PM: add min bus tput constraint: "
+ "dev %s for agent_id %d: rate %ld KiB\n",
+ dev_name(dev), agent_id, r);
+-
+- /*
+- * This code should model the interconnect and compute the
+- * required clock frequency, convert that to a VDD2 OPP ID, then
+- * set the VDD2 OPP appropriately.
+- *
+- * TI CDP code can call constraint_set here on the VDD2 OPP.
+- */
++ resource_request("vdd2_opp", dev, r);
++ }
+ }
+
+ void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t)
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/packages/linux/linux-omap2-git/beagleboard/10-omappm-off-mode.eml b/packages/linux/linux-omap2-git/beagleboard/10-omappm-off-mode.eml
new file mode 100644
index 0000000000..3728440159
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/10-omappm-off-mode.eml
@@ -0,0 +1,35 @@
+A Temp patch needed only till OFF mode is implemented.
+
+Signed-off-by: Rajendra Nayak <rnayak@ti.com>
+---
+ arch/arm/mach-omap2/resource34xx.c | 4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+Index: linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c
+===================================================================
+--- linux-omap-2.6.orig/arch/arm/mach-omap2/resource34xx.c 2008-08-11
+17:39:00.000000000 +0530
++++ linux-omap-2.6/arch/arm/mach-omap2/resource34xx.c 2008-08-11
+17:39:00.000000000 +0530
+@@ -131,13 +131,13 @@ int set_pd_latency(struct shared_resourc
+ omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[i]);
+ }
+ pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_ON);
+- pwrdm_set_next_pwrst(pwrdm, pd_lat_level);
++ pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_RET);
+ for (i = 0; pwrdm->pwrdm_clkdms[i]; i++) {
+ omap2_clkdm_sleep(pwrdm->pwrdm_clkdms[i]);
+ omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[i]);
+ }
+ } else
+- pwrdm_set_next_pwrst(pwrdm, pd_lat_level);
++ pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_RET);
+ break;
+ case PWRDM_POWER_ON:
+ pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_ON);
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/packages/linux/linux-omap2-git/beagleboard/defconfig b/packages/linux/linux-omap2-git/beagleboard/defconfig
index c07d0ab5e2..b3ea5f9557 100644
--- a/packages/linux/linux-omap2-git/beagleboard/defconfig
+++ b/packages/linux/linux-omap2-git/beagleboard/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.26-omap1
-# Tue Aug 5 20:34:54 2008
+# Mon Aug 11 16:37:34 2008
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -189,10 +189,14 @@ CONFIG_OMAP_MCBSP=y
# CONFIG_OMAP_MBOX_FWK is not set
# CONFIG_OMAP_MPU_TIMER is not set
CONFIG_OMAP_32K_TIMER=y
+CONFIG_OMAP_32K_TIMER_HZ=128
CONFIG_OMAP_DM_TIMER=y
# CONFIG_OMAP_LL_DEBUG_UART1 is not set
# CONFIG_OMAP_LL_DEBUG_UART2 is not set
CONFIG_OMAP_LL_DEBUG_UART3=y
+# CONFIG_OMAP_PM_NONE is not set
+# CONFIG_OMAP_PM_NOOP is not set
+CONFIG_OMAP_PM_SRF=y
CONFIG_ARCH_OMAP34XX=y
CONFIG_ARCH_OMAP3430=y
@@ -256,7 +260,7 @@ CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_PREEMPT is not set
-CONFIG_HZ=100
+CONFIG_HZ=128
CONFIG_AEABI=y
# CONFIG_OABI_COMPAT is not set
# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
@@ -307,19 +311,19 @@ CONFIG_CPU_IDLE_GOV_MENU=y
#
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TABLE=y
-# CONFIG_CPU_FREQ_DEBUG is not set
+CONFIG_CPU_FREQ_DEBUG=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_STAT_DETAILS=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
-# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
#
# Floating point emulation
diff --git a/packages/linux/linux-omap2-git/beagleboard/omap23-pm-noop.eml b/packages/linux/linux-omap2-git/beagleboard/omap23-pm-noop.eml
new file mode 100644
index 0000000000..48ff5da822
--- /dev/null
+++ b/packages/linux/linux-omap2-git/beagleboard/omap23-pm-noop.eml
@@ -0,0 +1,894 @@
+The interface provides device drivers, CPUFreq, and DSP Bridge with a
+means of controlling OMAP power management parameters that are not yet
+supported by the Linux PM PMQOS interface. Copious documentation and
+rationale is in the patch in Documentation/arm/OMAP/omap_pm and the
+interface header file, include/asm-arm/arch-omap/omap-pm.h.
+
+Signed-off-by: Paul Walmsley <paul@pwsan.com>
+---
+
+ Documentation/arm/OMAP/omap_pm | 185 +++++++++++++++++++++
+ arch/arm/mach-omap2/io.c | 4
+ arch/arm/plat-omap/Kconfig | 13 +
+ arch/arm/plat-omap/Makefile | 1
+ arch/arm/plat-omap/omap-pm-noop.c | 309 +++++++++++++++++++++++++++++++++++
+ include/asm-arm/arch-omap/omap-pm.h | 300 ++++++++++++++++++++++++++++++++++
+ 6 files changed, 812 insertions(+), 0 deletions(-)
+ create mode 100644 Documentation/arm/OMAP/omap_pm
+ create mode 100644 arch/arm/plat-omap/omap-pm-noop.c
+ create mode 100644 include/asm-arm/arch-omap/omap-pm.h
+
+diff --git a/Documentation/arm/OMAP/omap_pm b/Documentation/arm/OMAP/omap_pm
+new file mode 100644
+index 0000000..2ec2034
+--- /dev/null
++++ b/Documentation/arm/OMAP/omap_pm
+@@ -0,0 +1,185 @@
++
++Rationale: the OMAP PM interface
++================================
++
++
++Existing PM interfaces are currently not ideal for OMAP
++-------------------------------------------------------
++
++There are two PM interfaces in use with publicly-distributed OMAP
++Linux code: the TI Shared Resource Framework (SRF) and the Linux PM
++QoS parameters code. Neither interface is ideal for Linux OMAP code.
++
++TI Shared Resource Framework:
++
++The TI CDP 12.14 tree drivers currently use the TI Shared Resource
++Framework (SRF) to control chip power management. Use of the SRF
++allowed TI to get the drivers up and running quickly with considerable
++power savings; and the SRF provided debugging support. However, many
++of the SRF parameters are specified in OMAP-specific terms, such as
++target OPPs, rather than in terms of actual latency or throughput
++requirements. OPPs change depending on OMAP silicon revisions or OMAP
++types, and are meaningless for other architectures, so drivers shared
++between OMAP and other architectures would also have to #ifdef out the
++SRF constraints.
++
++Linux PM QoS parameters:
++
++In February 2008, the mainline Linux kernel added code that is
++somewhat similar to the SRF: the Linux PM QoS parameters code, located
++in kernel/pm_qos_params.c. (This code replaced the latency management
++code that was present in earlier kernels.) Ideally, OMAP drivers
++would be able to use this Linux PM QoS code directly, but the PM QoS
++code has some drawbacks:
++
++- It combines some power management parameters that should be kept
++ separate for maximum power savings on OMAP3. For example, in the PM
++ QoS code, CPU and system DMA wakeup latency are combined into one
++ parameter; but on OMAP3, these are distinct parameters. The Linux
++ PM QoS code also combines all network power management knobs into
++ two non-device-specific parameters. OMAP2/3 systems can have
++ different network devices with different power management
++ requirements - for example, a wired Ethernet interface may have
++ different latency and throughput constraints than a WiFi interface.
++
++- It does not yet cover all of the power management capabilities of
++ the OMAP3 architecture. It does not express latency constraints on
++ a per-device or per-powerdomain basis; it only covers
++ cpu_dma_latency and network throughput and latency, which would not
++ cover most of the OMAP3 devices.
++
++The result is that drivers using the current Linux PM QoS layer
++directly are unlikely to reach the same level of power efficiency as
++driver code using the Shared Resource Framework.
++
++To summarize, the SRF provides significant power savings, but
++expresses power constraints in an OMAP- and silicon-revision-specific
++way; and the PM QoS layer expresses PM constraints in a cross-platform
++manner (in terms of fundamental physical units), but does not support
++per-powerdomain constraints and does not cover many of the OMAP power
++management features.
++
++
++A medium-term alternative: the OMAP PM interface
++------------------------------------------------
++
++We need a way for driver code to express PM parameters which:
++
++- supports the range of power management parameters present in the TI SRF;
++
++- separates the drivers from the underlying PM parameter
++ implementation, whether it is the TI SRF or Linux PM QoS or Linux
++ latency framework or something else;
++
++- specifies PM parameters in terms of fundamental units, such as
++ latency and throughput, rather than units which are specific to OMAP
++ or to particular OMAP variants;
++
++- allows drivers which are shared with other architectures (e.g.,
++ DaVinci) to add these constraints in a way which won't affect non-OMAP
++ systems,
++
++- can be implemented immediately with minimal disruption of other
++ architectures.
++
++
++We therefore propose the OMAP PM interface, including the following
++four power management functions for driver code:
++
++1. Set the maximum MPU wakeup latency:
++ (*pdata->set_max_mpu_wakeup_lat)(struct device *dev, unsigned long t)
++
++2. Set the maximum device wakeup latency:
++ (*pdata->set_max_dev_wakeup_lat)(struct device *dev, unsigned long t)
++
++3. Set the maximum system DMA transfer start latency (CORE pwrdm):
++ (*pdata->set_max_sdma_lat)(struct device *dev, long t)
++
++4. Set the minimum bus throughput needed by a device:
++ (*pdata->set_min_bus_tput)(struct device *dev, u8 agent_id, unsigned long r)
++
++
++These functions are extensively documented in the OMAP PM interface header
++file, included in the patch.
++
++
++The OMAP PM layer is intended to be temporary
++---------------------------------------------
++
++The intention is that, in time, the Linux PM QoS layer should support
++the range of power management features present in OMAP3. As this
++happens, existing drivers using the OMAP PM interface can be modified
++to use the Linux PM QoS code; and the OMAP PM interface can disappear.
++
++
++Driver usage of the OMAP PM functions
++-------------------------------------
++
++As the 'pdata' in the above examples indicates, these functions are
++exposed to drivers through function pointers in driver .platform_data
++structures. The function pointers are initialized by the board-*.c
++files to point to the corresponding OMAP PM functions:
++.set_max_dev_wakeup_lat will point to
++omap_pm_set_max_dev_wakeup_lat(), etc. Other architectures which do
++not support these functions should leave these function pointers set
++to NULL. Drivers should use the following idiom:
++
++ if (pdata->set_max_dev_wakeup_lat)
++ (*pdata->set_max_dev_wakeup_lat)(dev, t);
++
++The most common usage of these functions will probably be to specify
++the maximum time from when an interrupt occurs, to when the device
++becomes accessible. To accomplish this, driver writers should use the
++set_max_mpu_wakeup_lat() function to to constrain the MPU wakeup
++latency, and the set_max_dev_wakeup_lat() function to constrain the
++device wakeup latency (from clk_enable() to accessibility). For
++example,
++
++ /* Limit MPU wakeup latency */
++ if (pdata->set_max_mpu_wakeup_lat)
++ (*pdata->set_max_mpu_wakeup_lat)(dev, tc);
++
++ /* Limit device powerdomain wakeup latency */
++ if (pdata->set_max_dev_wakeup_lat)
++ (*pdata->set_max_dev_wakeup_lat)(dev, td);
++
++ /* total wakeup latency in this example: (tc + td) */
++
++
++The PM parameters can be overwritten by calling the function again
++with the new value. The settings can be removed by calling the
++function with a t argument of -1 (except in the case of
++set_max_bus_tput(), which should be called with an r argument of 0).
++
++
++Other specialized interface functions
++-------------------------------------
++
++The four functions listed above are intended to be usable by any
++device driver. However, DSPBridge and CPUFreq have special
++requirements. DSPBridge expresses target DSP performance levels in
++terms of OPP IDs. CPUFreq expresses target MPU performance levels in
++terms of MPU frequency. The OMAP PM interface contains functions for
++these specialized cases to convert that input information (OPPs/MPU
++frequency) into the form that the underlying power management
++implementation needs:
++
++5. (*pdata->omap_pm_dsp_get_opp_table)(void)
++
++6. (*pdata->omap_pm_dsp_set_min_opp)(u8 opp_id)
++
++7. (*pdata->omap_pm_dsp_get_opp)(void)
++
++8. (*pdata->omap_pm_cpu_get_freq_table)(void)
++
++9. (*pdata->omap_pm_cpu_set_freq)(unsigned long f)
++
++10. (*pdata->omap_pm_cpu_get_freq)(void)
++
++
++There are also functions for use by the clockdomain layer to indicate
++that a powerdomain should wake up or be put to sleep:
++
++11. (*pdata->omap_pm_pwrdm_active)(struct powerdomain *pwrdm)
++
++12. (*pdata->omap_pm_pwrdm_inactive)(struct powerdomain *pwrdm)
+diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
+index 960c13f..ca790ac 100644
+--- a/arch/arm/plat-omap/Kconfig
++++ b/arch/arm/plat-omap/Kconfig
+@@ -247,4 +247,17 @@ config OMAP_SERIAL_WAKE
+
+ endmenu
+
++choice
++ prompt "OMAP PM layer selection"
++ depends on ARCH_OMAP
++ default OMAP_PM_NOOP
++
++config OMAP_PM_NONE
++ bool "No PM layer"
++
++config OMAP_PM_NOOP
++ bool "No-op/debug PM layer"
++
++endchoice
++
+ endif
+diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
+index 93bbb64..d5453d5 100644
+--- a/arch/arm/plat-omap/Makefile
++++ b/arch/arm/plat-omap/Makefile
+@@ -29,3 +29,4 @@ obj-$(CONFIG_OMAP_MMU_FWK) += mmu.o
+ # OMAP mailbox framework
+ obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox.o
+
++obj-$(CONFIG_OMAP_PM_NOOP) += omap-pm-noop.o
+\ No newline at end of file
+diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c
+new file mode 100644
+index 0000000..5ff7962
+--- /dev/null
++++ b/arch/arm/plat-omap/omap-pm-noop.c
+@@ -0,0 +1,309 @@
++/*
++ * omap-pm-noop.c - OMAP power management interface - dummy version
++ *
++ * This code implements the OMAP power management interface to
++ * drivers, CPUIdle, CPUFreq, and DSP Bridge. It is strictly for
++ * debug/demonstration use, as it does nothing but printk() whenever a
++ * function is called (when DEBUG is defined, below)
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ * Copyright (C) 2008 Nokia Corporation
++ * Paul Walmsley
++ *
++ * Interface developed by (in alphabetical order):
++ * Karthik Dasu, Amish Lakhani, Tony Lindgren, Rajendra Nayak, Sakari
++ * Poussa, Veeramanikandan Raju, Igor Stoppa, Paul Walmsley, Richard
++ * Woodruff
++ */
++
++#undef DEBUG
++
++#include <linux/init.h>
++#include <linux/cpufreq.h>
++#include <linux/device.h>
++
++/* Interface documentation is in asm/arch/omap-pm.h */
++#include <asm/arch/omap-pm.h>
++
++#include <asm/arch/powerdomain.h>
++
++static struct omap_opp *dsp_opps;
++static struct omap_opp *mpu_opps;
++
++/*
++ * Device-driver-originated constraints (via board-*.c files)
++ */
++
++void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t)
++{
++ if (!dev || t < -1) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (t == -1)
++ pr_debug("OMAP PM: remove max MPU wakeup latency constraint: "
++ "dev %s\n", dev_name(dev));
++ else
++ pr_debug("OMAP PM: add max MPU wakeup latency constraint: "
++ "dev %s, t = %ld usec\n", dev_name(dev), t);
++
++ /*
++ * For current Linux, this needs to map the MPU to a
++ * powerdomain, then go through the list of current max lat
++ * constraints on the MPU and find the smallest. If
++ * the latency constraint has changed, the code should
++ * recompute the state to enter for the next powerdomain
++ * state.
++ *
++ * TI CDP code can call constraint_set here.
++ */
++}
++
++void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r)
++{
++ if (!dev || agent_id != OCP_INITIATOR_AGENT ||
++ agent_id != OCP_TARGET_AGENT) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (r == 0)
++ pr_debug("OMAP PM: remove min bus tput constraint: "
++ "dev %s for agent_id %d\n", dev_name(dev), agent_id);
++ else
++ pr_debug("OMAP PM: add min bus tput constraint: "
++ "dev %s for agent_id %d: rate %ld KiB\n",
++ dev_name(dev), agent_id, r);
++
++ /*
++ * This code should model the interconnect and compute the
++ * required clock frequency, convert that to a VDD2 OPP ID, then
++ * set the VDD2 OPP appropriately.
++ *
++ * TI CDP code can call constraint_set here on the VDD2 OPP.
++ */
++}
++
++void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t)
++{
++ if (!dev || t < -1) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (t == -1)
++ pr_debug("OMAP PM: remove max device latency constraint: "
++ "dev %s\n", dev_name(dev));
++ else
++ pr_debug("OMAP PM: add max device latency constraint: "
++ "dev %s, t = %ld usec\n", dev_name(dev), t);
++
++ /*
++ * For current Linux, this needs to map the device to a
++ * powerdomain, then go through the list of current max lat
++ * constraints on that powerdomain and find the smallest. If
++ * the latency constraint has changed, the code should
++ * recompute the state to enter for the next powerdomain
++ * state. Conceivably, this code should also determine
++ * whether to actually disable the device clocks or not,
++ * depending on how long it takes to re-enable the clocks.
++ *
++ * TI CDP code can call constraint_set here.
++ */
++}
++
++void omap_pm_set_max_sdma_lat(struct device *dev, long t)
++{
++ if (!dev || t < -1) {
++ WARN_ON(1);
++ return;
++ };
++
++ if (t == -1)
++ pr_debug("OMAP PM: remove max DMA latency constraint: "
++ "dev %s\n", dev_name(dev));
++ else
++ pr_debug("OMAP PM: add max DMA latency constraint: "
++ "dev %s, t = %ld usec\n", dev_name(dev), t);
++
++ /*
++ * For current Linux PM QOS params, this code should scan the
++ * list of maximum CPU and DMA latencies and select the
++ * smallest, then set cpu_dma_latency pm_qos_param
++ * accordingly.
++ *
++ * For future Linux PM QOS params, with separate CPU and DMA
++ * latency params, this code should just set the dma_latency param.
++ *
++ * TI CDP code can call constraint_set here.
++ */
++
++}
++
++
++/*
++ * DSP Bridge-specific constraints
++ */
++
++const struct omap_opp *omap_pm_dsp_get_opp_table(void)
++{
++ pr_debug("OMAP PM: DSP request for OPP table\n");
++
++ /*
++ * Return DSP frequency table here: The final item in the
++ * array should have .rate = .opp_id = 0.
++ */
++
++ return NULL;
++}
++
++void omap_pm_dsp_set_min_opp(u8 opp_id)
++{
++ if (opp_id == 0) {
++ WARN_ON(1);
++ return;
++ }
++
++ pr_debug("OMAP PM: DSP requests minimum VDD1 OPP to be %d\n", opp_id);
++
++ /*
++ *
++ * For l-o dev tree, our VDD1 clk is keyed on OPP ID, so we
++ * can just test to see which is higher, the CPU's desired OPP
++ * ID or the DSP's desired OPP ID, and use whichever is
++ * highest.
++ *
++ * In CDP12.14+, the VDD1 OPP custom clock that controls the DSP
++ * rate is keyed on MPU speed, not the OPP ID. So we need to
++ * map the OPP ID to the MPU speed for use with clk_set_rate()
++ * if it is higher than the current OPP clock rate.
++ *
++ */
++}
++
++
++u8 omap_pm_dsp_get_opp(void)
++{
++ pr_debug("OMAP PM: DSP requests current DSP OPP ID\n");
++
++ /*
++ * For l-o dev tree, call clk_get_rate() on VDD1 OPP clock
++ *
++ * CDP12.14+:
++ * Call clk_get_rate() on the OPP custom clock, map that to an
++ * OPP ID using the tables defined in board-*.c/chip-*.c files.
++ */
++
++ return 0;
++}
++
++/*
++ * CPUFreq-originated constraint
++ *
++ * In the future, this should be handled by custom OPP clocktype
++ * functions.
++ */
++
++struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void)
++{
++ pr_debug("OMAP PM: CPUFreq request for frequency table\n");
++
++ /*
++ * Return CPUFreq frequency table here: loop over
++ * all VDD1 clkrates, pull out the mpu_ck frequencies, build
++ * table
++ */
++
++ return NULL;
++}
++
++void omap_pm_cpu_set_freq(unsigned long f)
++{
++ if (f == 0) {
++ WARN_ON(1);
++ return;
++ }
++
++ pr_debug("OMAP PM: CPUFreq requests CPU frequency to be set to %lu\n",
++ f);
++
++ /*
++ * For l-o dev tree, determine whether MPU freq or DSP OPP id
++ * freq is higher. Find the OPP ID corresponding to the
++ * higher frequency. Call clk_round_rate() and clk_set_rate()
++ * on the OPP custom clock.
++ *
++ * CDP should just be able to set the VDD1 OPP clock rate here.
++ */
++}
++
++unsigned long omap_pm_cpu_get_freq(void)
++{
++ pr_debug("OMAP PM: CPUFreq requests current CPU frequency\n");
++
++ /*
++ * Call clk_get_rate() on the mpu_ck.
++ */
++
++ return 0;
++}
++
++/*
++ * Powerdomain usecounting hooks
++ */
++
++void omap_pm_pwrdm_active(struct powerdomain *pwrdm)
++{
++ if (!pwrdm) {
++ WARN_ON(1);
++ return;
++ };
++
++ pr_debug("OMAP PM: powerdomain %s is becoming active\n", pwrdm->name);
++
++ /*
++ * CDP code apparently will need these for the enable_power_domain()
++ * and disable_power_domain() functions.
++ */
++}
++
++void omap_pm_pwrdm_inactive(struct powerdomain *pwrdm)
++{
++ if (!pwrdm) {
++ WARN_ON(1);
++ return;
++ };
++
++ pr_debug("OMAP PM: powerdomain %s is becoming inactive\n",
++ pwrdm->name);
++
++ /*
++ * CDP code apparently will need these for the enable_power_domain()
++ * and disable_power_domain() functions.
++ */
++}
++
++/*
++ * Should be called before clk framework since clk fw will call
++ * omap_pm_pwrdm_{in,}active()
++ */
++int __init omap_pm_if_early_init(void)
++{
++ return 0;
++}
++
++/* Must be called after clock framework is initialized */
++int __init omap_pm_if_init(struct omap_opp *mpu_opp_table,
++ struct omap_opp *dsp_opp_table)
++{
++ mpu_opps = mpu_opp_table;
++ dsp_opps = dsp_opp_table;
++ return 0;
++}
++
++void omap_pm_if_exit(void)
++{
++ /* Deallocate CPUFreq frequency table here */
++}
++
+diff --git a/include/asm-arm/arch-omap/omap-pm.h b/include/asm-arm/arch-omap/omap-pm.h
+new file mode 100644
+index 0000000..d272dba
+--- /dev/null
++++ b/include/asm-arm/arch-omap/omap-pm.h
+@@ -0,0 +1,300 @@
++/*
++ * omap-pm.h - OMAP power management interface
++ *
++ * Copyright (C) 2008 Texas Instruments, Inc.
++ * Copyright (C) 2008 Nokia Corporation
++ * Paul Walmsley
++ *
++ * Interface developed by (in alphabetical order): Karthik Dasu, Jouni
++ * Högander, Tony Lindgren, Rajendra Nayak, Sakari Poussa,
++ * Veeramanikandan Raju, Anand Sawant, Igor Stoppa, Paul Walmsley,
++ * Richard Woodruff
++ */
++
++#ifndef ASM_ARM_ARCH_OMAP_OMAP_PM_H
++#define ASM_ARM_ARCH_OMAP_OMAP_PM_H
++
++#include <linux/device.h>
++#include <linux/cpufreq.h>
++
++#include "powerdomain.h"
++
++/**
++ * struct omap_opp - clock frequency-to-OPP ID table for DSP, MPU
++ * @rate: target clock rate
++ * @opp_id: OPP ID
++ * @min_vdd: minimum VDD1 voltage (in millivolts) for this OPP
++ *
++ * Operating performance point data. Can vary by OMAP chip and board.
++ */
++struct omap_opp {
++ unsigned long rate;
++ u8 opp_id;
++ u16 min_vdd;
++};
++
++/*
++ * agent_id values for use with omap_pm_set_min_bus_tput():
++ *
++ * OCP_INITIATOR_AGENT is only valid for devices that can act as
++ * initiators -- it represents the device's L3 interconnect
++ * connection. OCP_TARGET_AGENT represents the device's L4
++ * interconnect connection.
++ */
++#define OCP_TARGET_AGENT 1
++#define OCP_INITIATOR_AGENT 2
++
++/**
++ * omap_pm_if_early_init - OMAP PM init code called before clock fw init
++ *
++ * Initialize anything that must be configured before the clock
++ * framework starts. The "_if_" is to avoid name collisions with the
++ * PM idle-loop code.
++ */
++int __init omap_pm_if_early_init(void);
++
++/**
++ * omap_pm_if_init - OMAP PM init code called after clock fw init
++ * @mpu_opp_table: array ptr to struct omap_opp for MPU
++ * @dsp_opp_table: array ptr to struct omap_opp for DSP
++ *
++ * The main initialization code. OPP tables are passed in here. The
++ * "_if_" is to avoid name collisions with the PM idle-loop code.
++ */
++int __init omap_pm_if_init(struct omap_opp *mpu_opp_table,
++ struct omap_opp *dsp_opp_table);
++
++/**
++ * omap_pm_if_exit - OMAP PM exit code
++ *
++ * Exit code; currently unused. The "_if_" is to avoid name
++ * collisions with the PM idle-loop code.
++ */
++void omap_pm_if_exit(void);
++
++/*
++ * Device-driver-originated constraints (via board-*.c files, platform_data)
++ */
++
++
++/**
++ * omap_pm_set_max_mpu_wakeup_lat - set the maximum MPU wakeup latency
++ * @dev: struct device * requesting the constraint
++ * @t: maximum MPU wakeup latency in microseconds
++ *
++ * Request that the maximum interrupt latency for the MPU to be no
++ * greater than 't' microseconds. "Interrupt latency" in this case is
++ * defined as the elapsed time from the occurrence of a hardware or
++ * timer interrupt to the time when the device driver's interrupt
++ * service routine has been entered by the MPU.
++ *
++ * It is intended that underlying PM code will use this information to
++ * determine what power state to put the MPU powerdomain into, and
++ * possibly the CORE powerdomain as well, since interrupt handling
++ * code currently runs from SDRAM. Advanced PM or board*.c code may
++ * also configure interrupt controller priorities, OCP bus priorities,
++ * CPU speed(s), etc.
++ *
++ * This function will not affect device wakeup latency, e.g., time
++ * elapsed from when a device driver enables a hardware device with
++ * clk_enable(), to when the device is ready for register access or
++ * other use. To control this device wakeup latency, use
++ * set_max_dev_wakeup_lat()
++ *
++ * Multiple calls to set_max_mpu_wakeup_lat() will replace the
++ * previous t value. To remove the latency target for the MPU, call
++ * with t = -1.
++ *
++ * No return value.
++ */
++void omap_pm_set_max_mpu_wakeup_lat(struct device *dev, long t);
++
++
++/**
++ * omap_pm_set_min_bus_tput - set minimum bus throughput needed by device
++ * @dev: struct device * requesting the constraint
++ * @tbus_id: interconnect to operate on (OCP_{INITIATOR,TARGET}_AGENT)
++ * @r: minimum throughput (in KiB/s)
++ *
++ * Request that the minimum data throughput on the OCP interconnect
++ * attached to device 'dev' interconnect agent 'tbus_id' be no less
++ * than 'r' KiB/s.
++ *
++ * It is expected that the OMAP PM or bus code will use this
++ * information to set the interconnect clock to run at the lowest
++ * possible speed that satisfies all current system users. The PM or
++ * bus code will adjust the estimate based on its model of the bus, so
++ * device driver authors should attempt to specify an accurate
++ * quantity for their device use case, and let the PM or bus code
++ * overestimate the numbers as necessary to handle request/response
++ * latency, other competing users on the system, etc. On OMAP2/3, if
++ * a driver requests a minimum L4 interconnect speed constraint, the
++ * code will also need to add an minimum L3 interconnect speed
++ * constraint,
++ *
++ * Multiple calls to set_min_bus_tput() will replace the previous rate
++ * value for this device. To remove the interconnect throughput
++ * restriction for this device, call with r = 0.
++ *
++ * No return value.
++ */
++void omap_pm_set_min_bus_tput(struct device *dev, u8 agent_id, unsigned long r);
++
++
++/**
++ * omap_pm_set_max_dev_wakeup_lat - set the maximum device enable latency
++ * @dev: struct device *
++ * @t: maximum device wakeup latency in microseconds
++ *
++ * Request that the maximum amount of time necessary for a device to
++ * become accessible after its clocks are enabled should be no greater
++ * than 't' microseconds. Specifically, this represents the time from
++ * when a device driver enables device clocks with clk_enable(), to
++ * when the register reads and writes on the device will succeed.
++ * This function should be called before clk_disable() is called,
++ * since the power state transition decision may be made during
++ * clk_disable().
++ *
++ * It is intended that underlying PM code will use this information to
++ * determine what power state to put the powerdomain enclosing this
++ * device into.
++ *
++ * Multiple calls to set_max_dev_wakeup_lat() will replace the
++ * previous wakeup latency values for this device. To remove the wakeup
++ * latency restriction for this device, call with t = -1.
++ *
++ * No return value.
++ */
++void omap_pm_set_max_dev_wakeup_lat(struct device *dev, long t);
++
++
++/**
++ * omap_pm_set_max_sdma_lat - set the maximum system DMA transfer start latency
++ * @dev: struct device *
++ * @t: maximum DMA transfer start latency in microseconds
++ *
++ * Request that the maximum system DMA transfer start latency for this
++ * device 'dev' should be no greater than 't' microseconds. "DMA
++ * transfer start latency" here is defined as the elapsed time from
++ * when a device (e.g., McBSP) requests that a system DMA transfer
++ * start or continue, to the time at which data starts to flow into
++ * that device from the system DMA controller.
++ *
++ * It is intended that underlying PM code will use this information to
++ * determine what power state to put the CORE powerdomain into.
++ *
++ * Since system DMA transfers may not involve the MPU, this function
++ * will not affect MPU wakeup latency. Use set_max_cpu_lat() to do
++ * so. Similarly, this function will not affect device wakeup latency
++ * -- use set_max_dev_wakeup_lat() to affect that.
++ *
++ * Multiple calls to set_max_sdma_lat() will replace the previous t
++ * value for this device. To remove the maximum DMA latency for this
++ * device, call with t = -1.
++ *
++ * No return value.
++ */
++void omap_pm_set_max_sdma_lat(struct device *dev, long t);
++
++
++/*
++ * DSP Bridge-specific constraints
++ */
++
++/**
++ * omap_pm_dsp_get_opp_table - get OPP->DSP clock frequency table
++ *
++ * Intended for use by DSPBridge. Returns an array of OPP->DSP clock
++ * frequency entries. The final item in the array should have .rate =
++ * .opp_id = 0.
++ */
++const struct omap_opp *omap_pm_dsp_get_opp_table(void);
++
++/**
++ * omap_pm_dsp_set_min_opp - receive desired OPP target ID from DSP Bridge
++ * @opp_id: target DSP OPP ID
++ *
++ * Set a minimum OPP ID for the DSP. This is intended to be called
++ * only from the DSP Bridge MPU-side driver. Unfortunately, the only
++ * information that code receives from the DSP/BIOS load estimator is the
++ * target OPP ID; hence, this interface. No return value.
++ */
++void omap_pm_dsp_set_min_opp(u8 opp_id);
++
++/**
++ * omap_pm_dsp_get_opp - report the current DSP OPP ID
++ *
++ * Report the current OPP for the DSP. Since on OMAP3, the DSP and
++ * MPU share a single voltage domain, the OPP ID returned back may
++ * represent a higher DSP speed than the OPP requested via
++ * omap_pm_dsp_set_min_opp().
++ *
++ * Returns the current VDD1 OPP ID, or 0 upon error.
++ */
++u8 omap_pm_dsp_get_opp(void);
++
++
++/*
++ * CPUFreq-originated constraint
++ *
++ * In the future, this should be handled by custom OPP clocktype
++ * functions.
++ */
++
++/**
++ * omap_pm_cpu_get_freq_table - return a cpufreq_frequency_table array ptr
++ *
++ * Provide a frequency table usable by CPUFreq for the current chip/board.
++ * Returns a pointer to a struct cpufreq_frequency_table array or NULL
++ * upon error.
++ */
++struct cpufreq_frequency_table **omap_pm_cpu_get_freq_table(void);
++
++/**
++ * omap_pm_cpu_set_freq - set the current minimum MPU frequency
++ * @f: MPU frequency in Hz
++ *
++ * Set the current minimum CPU frequency. The actual CPU frequency
++ * used could end up higher if the DSP requested a higher OPP.
++ * Intended to be called by plat-omap/cpu_omap.c:omap_target(). No
++ * return value.
++ */
++void omap_pm_cpu_set_freq(unsigned long f);
++
++/**
++ * omap_pm_cpu_get_freq - report the current CPU frequency
++ *
++ * Returns the current MPU frequency, or 0 upon error.
++ */
++unsigned long omap_pm_cpu_get_freq(void);
++
++
++/*
++ * Powerdomain usecounting hooks
++ */
++
++/**
++ * omap_pm_pwrdm_active - indicate that a power domain has become active
++ * @pwrdm: struct powerdomain *
++ *
++ * Notify the OMAP PM layer that the power domain 'pwrdm' has become active,
++ * presumably due to a device driver enabling an underlying clock. This
++ * function is intended to be called by a clockdomain node in the clock
++ * framework. No return value.
++ */
++void omap_pm_pwrdm_active(struct powerdomain *pwrdm);
++
++
++/**
++ * omap_pm_pwrdm_inactive - indicate that a power domain has become inactive
++ * @pwrdm: struct powerdomain *
++ *
++ * Notify the OMAP PM layer that the power domain 'pwrdm' has become
++ * inactive, presumably due to a device driver disabling an underlying
++ * clock. This function is intended to be called by a clockdomain
++ * node in the clock framework. No return value.
++ */
++void omap_pm_pwrdm_inactive(struct powerdomain *pwrdm);
++
++
++#endif
+
+
+--
+To unsubscribe from this list: send the line "unsubscribe linux-omap" in
+the body of a message to majordomo@vger.kernel.org
+More majordomo info at http://vger.kernel.org/majordomo-info.html
+
+--- /tmp/io.c 2008-08-11 15:29:32.000000000 +0200
++++ git/arch/arm/mach-omap2/io.c 2008-08-11 15:30:20.083198000 +0200
+@@ -38,6 +38,8 @@
+ #include <asm/arch/clockdomain.h>
+ #include "clockdomains.h"
+
++#include <asm/arch/omap-pm.h>
++
+ /*
+ * The machine specific code may provide the extra mapping besides the
+ * default mapping provided here.
+@@ -197,9 +199,11 @@
+ void __init omap2_init_common_hw(struct omap_sdrc_params *sp)
+ {
+ omap2_mux_init();
++ omap_pm_if_early_init();
+ pwrdm_init(powerdomains_omap);
+ clkdm_init(clockdomains_omap, clkdm_pwrdm_autodeps);
+ omap2_clk_init();
++ omap_pm_if_init(NULL, NULL);
+ omap2_sdrc_init(sp);
+ gpmc_init();
+ }