diff options
Diffstat (limited to 'packages')
18 files changed, 4546 insertions, 8 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 ++ ++#i |
