diff options
| author | Klaus Kurzmann <mok@fluxnetz.de> | 2009-12-13 20:17:29 +0100 |
|---|---|---|
| committer | Klaus Kurzmann <mok@fluxnetz.de> | 2009-12-13 20:17:29 +0100 |
| commit | 5e133e2a50fd32187d16334efe7a5315633fd687 (patch) | |
| tree | 5885e39c6a8b0fc12f38ef192fd0fbacc6adaed9 | |
| parent | 91f546068cc31ad59cf9094da28cc3d3438c97b4 (diff) | |
| parent | 9f65815c37fff6c2ad9438b84f6ce866c5c44f73 (diff) | |
Merge branch 'org.openembedded.dev' of git+ssh://git.openembedded.net/openembedded into org.openembedded.dev
| -rw-r--r-- | conf/checksums.ini | 4 | ||||
| -rw-r--r-- | conf/distro/include/preferred-om-2008-versions.inc | 4 | ||||
| -rw-r--r-- | conf/machine/sgh-i900.conf | 1 | ||||
| -rw-r--r-- | recipes/libpcre/libpcre_7.6.bb | 7 | ||||
| -rw-r--r-- | recipes/linux/linux-sgh-i900/sgh-i900-support.patch | 13031 | ||||
| -rw-r--r-- | recipes/linux/linux-sgh-i900/sgh_i900_defconfig | 414 | ||||
| -rw-r--r-- | recipes/linux/linux-sgh-i900/wm97xx-ts-fix.patch | 130 | ||||
| -rw-r--r-- | recipes/linux/linux-sgh-i900_2.6.32.bb (renamed from recipes/linux/linux-sgh-i900_2.6.29.bb) | 10 |
8 files changed, 13296 insertions, 305 deletions
diff --git a/conf/checksums.ini b/conf/checksums.ini index 3bf98541fe..0fe5acb594 100644 --- a/conf/checksums.ini +++ b/conf/checksums.ini @@ -17378,6 +17378,10 @@ sha256=d7b9f19b92fd5c693c16cd62f441d051b699f28ec6a175d1b464e58bacd8c78f md5=84c077a37684e4cbfa67b18154390d8a sha256=0acd83f7b85db7ee18c2b0b7505e1ba6fd722c36f49a8870a831c851660e3512 +[http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.tar.bz2] +md5=260551284ac224c3a43c4adac7df4879 +sha256=5099786d80b8407d98a619df00209c2353517f22d804fdd9533b362adcb4504e + [http://kernel.org//pub/linux/kernel/v2.6/linux-2.6.9.tar.bz2] md5=e921200f074ca97184e150ef5a4af825 sha256=f5dba6366e87e91234d1b0069cfea655b0a4cb37ea97f899226f16998e6ab9f1 diff --git a/conf/distro/include/preferred-om-2008-versions.inc b/conf/distro/include/preferred-om-2008-versions.inc index 7cc923cc60..d881202b09 100644 --- a/conf/distro/include/preferred-om-2008-versions.inc +++ b/conf/distro/include/preferred-om-2008-versions.inc @@ -175,7 +175,7 @@ PREFERRED_VERSION_comprec ?= "0.02" PREFERRED_VERSION_confuse ?= "2.5" PREFERRED_VERSION_confuse-native ?= "2.5" PREFERRED_VERSION_connect ?= "0.1" -PREFERRED_VERSION_connman ?= "0.10" +PREFERRED_VERSION_connman ?= "0.15" PREFERRED_VERSION_conserver ?= "8.1.14" PREFERRED_VERSION_console-tools ?= "0.3.2" PREFERRED_VERSION_contacts ?= "0.7" @@ -1963,7 +1963,7 @@ PREFERRED_VERSION_wlan-ng-modules ?= "0.2.7" PREFERRED_VERSION_wlan-ng-utils ?= "0.2.7" PREFERRED_VERSION_wmctrl ?= "1.07" PREFERRED_VERSION_wpa-gui ?= "0.4.8" -PREFERRED_VERSION_wpa-supplicant ?= "0.6.3" +PREFERRED_VERSION_wpa-supplicant ?= "0.6.9" PREFERRED_VERSION_wpa-supplicant-nossl ?= "0.2.6" PREFERRED_VERSION_wpa-supplicant-ssl ?= "0.2.6" PREFERRED_VERSION_wrt-imagetools-native ?= "1.0" diff --git a/conf/machine/sgh-i900.conf b/conf/machine/sgh-i900.conf index 2080bf8e1a..4d3cd5fcee 100644 --- a/conf/machine/sgh-i900.conf +++ b/conf/machine/sgh-i900.conf @@ -11,6 +11,7 @@ TARGET_ARCH = "arm" require conf/machine/include/tune-xscale.inc MACHINE_FEATURES = "alsa apm bluetooth camera gps kernel26 phone screen touchscreen vfat wifi" +MACHINE_EXTRA_RRECOMMENDS = " kernel-modules" # Software/packages selection # diff --git a/recipes/libpcre/libpcre_7.6.bb b/recipes/libpcre/libpcre_7.6.bb index f9c9c06cd4..f89f83d631 100644 --- a/recipes/libpcre/libpcre_7.6.bb +++ b/recipes/libpcre/libpcre_7.6.bb @@ -5,7 +5,7 @@ provides a POSIX calling interface to PCRE; the regular expressions \ themselves still follow Perl syntax and semantics. The header file for \ the POSIX-style functions is called pcreposix.h." SECTION = "devel" -PR = "r5" +PR = "r6" LICENSE = "BSD" SRC_URI = "${SOURCEFORGE_MIRROR}/pcre/pcre-${PV}.tar.bz2 \ file://pcre-cross.patch;patch=1" @@ -38,6 +38,11 @@ do_compile () { oe_runmake CC_FOR_BUILD="${BUILD_CC}" CFLAGS_FOR_BUILD="-DLINK_SIZE=2 -I${S}/include" LINK_FOR_BUILD="${BUILD_CC} -L${S}/lib" } +do_stage () { + autotools_stage_all + install -d ${STAGING_BINDIR} + install -m 0755 ${D}${bindir}/pcre-config ${STAGING_BINDIR}/ +} python populate_packages_prepend () { pcre_libdir = bb.data.expand('${libdir}', d) pcre_libdir_dbg = bb.data.expand('${libdir}/.debug', d) diff --git a/recipes/linux/linux-sgh-i900/sgh-i900-support.patch b/recipes/linux/linux-sgh-i900/sgh-i900-support.patch new file mode 100644 index 0000000000..28d65938a1 --- /dev/null +++ b/recipes/linux/linux-sgh-i900/sgh-i900-support.patch @@ -0,0 +1,13031 @@ +diff -ur linux-2.6.32/arch/arm/Kconfig kernel/arch/arm/Kconfig +--- linux-2.6.32/arch/arm/Kconfig 2009-12-03 05:51:21.000000000 +0200 ++++ kernel/arch/arm/Kconfig 2009-12-12 16:09:25.656278659 +0200 +@@ -1502,6 +1502,112 @@ + config ARCH_SUSPEND_POSSIBLE + def_bool y + ++config PXA_DVFM ++ bool "PXA Processor High Level DVFM support" ++ depends on PM ++ default y ++ help ++ This enables the dynamical frequency and voltage changes framework ++ for PXA Processor series. ++ ++config PXA_MIPSRAM ++ bool "PXA MIPSRAM monitoring support" ++ default n ++ help ++ Enable MIPS RAM monitoring for process switching implemented in ++ the scheduler ++ ++config PXA3xx_DVFM ++ bool "PXA3xx Processor DVFM support" ++ depends on PM && PXA3xx && PXA_DVFM ++# select PXA3xx_ARAVA ++# select PXA3xx_MICCO ++ default y ++ help ++ This implements the dynamical frequency and voltage changes features ++ for PXA3xx Processor particularly. ++ ++config PXA3xx_DVFM_STATS ++ bool "PXA3xx/PXA930 Processor DVFM Statistics support" ++ depends on PXA3xx_DVFM ++ select RELAY ++ select DEBUG_FS ++ default y ++ help ++ This is used to collect statistics during the dynamic frequency ++ and voltage changes ++ ++config PXA3xx_PMU ++ bool "PXA3xx/PXA930 Processor PMU support" ++ default y ++ help ++ PXA3xx/PXA930 provide Performance Monitor Unit to report ++ CPU statistics info. ++ ++config PXA3xx_PRM ++ bool "PXA3xx Processor Profiler Resource Manager" ++ depends on PXA3xx_DVFM && PXA3xx_PMU ++ default y ++ help ++ This enables the PXA3xx Processor Profiler Resource Manager ++ ++config IPM ++ bool "Marvell(R) Scalable Power Management Profiler" ++ depends on PXA3xx_PRM ++ default y ++ help ++ Support Profiler of Marvell(R) Scalable Power Management ++ ++config IPMC ++ bool "Marvell(R) Scalable Power Management Userspace Daemon" ++ depends on PXA3xx_PRM ++ default n ++ help ++ Support Userspace Daemon of Marvell(R) Scalable Power Management ++ ++config BPMD ++ bool "Borqs Scalable Power Management Kernel Daemon" ++ depends on PXA3xx_PRM ++ default y ++ help ++ Kernel Daemon of Borqs Scalable Power Management ++ ++config TEST_BPMD ++ bool "Borqs Scalable Power Management Test Module" ++ depends on PXA3xx_PRM ++ default y ++ help ++ Test Module of Borqs Scalable Power Management ++ ++config IPM_DEEPIDLE ++ bool "PXA3xx/PXA930 Processor Deep Idle support" ++ depends on IPM ++ default y ++ help ++ This enables the kernel support for PXA3xx/PXA930 ++ Processor Deep Idle (D0CS Idle) ++ ++config IPM_D2IDLE ++ bool "Support PXA3xx/PXA930 Processor D2 Mode as Idle" ++ depends on IPM && PXA_32KTIMER ++ default y ++ help ++ This enables kernel support PXA3xx/PXA930 D2 idle ++ ++config PERIPHERAL_STATUS ++ bool "Support list peripheral status of pm" ++ depends on PM ++ default y ++ help ++ This enables kernel support peripheral status calculate ++ ++config IPM_CGIDLE ++ bool "Support PXA935 Processor Clock Gated Mode as Idle" ++ depends on IPM && PXA_32KTIMER ++ default y ++ help ++ This enables kernel support PXA935 D2 idle ++ + endmenu + + source "net/Kconfig" +diff -ur linux-2.6.32/arch/arm/mach-pxa/Kconfig kernel/arch/arm/mach-pxa/Kconfig +--- linux-2.6.32/arch/arm/mach-pxa/Kconfig 2009-12-03 05:51:21.000000000 +0200 ++++ kernel/arch/arm/mach-pxa/Kconfig 2009-12-12 16:09:26.426281936 +0200 +@@ -27,6 +27,12 @@ + bool "PXA950 (codename Tavor-PV2)" + select CPU_PXA930 + ++config PXA3xx_PMIC ++ bool "PXA3xx PMIC support" ++ default y ++ help ++ PMIC support ++ + endmenu + + endif +@@ -303,6 +309,18 @@ + select HAVE_PWM + select PXA_HAVE_BOARD_IRQS + ++config MACH_SGH_I900 ++ bool "Samsung SGH-i900 (Omnia) phone" ++ select PXA3xx ++ select CPU_PXA310 ++ select HAVE_PWM ++ ++config MACH_SGH_I780 ++ bool "Samsung SGH-i780 phone" ++ select PXA3xx ++ select CPU_PXA310 ++ select HAVE_PWM ++ + config MACH_LITTLETON + bool "PXA3xx Form Factor Platform (aka Littleton)" + select PXA3xx +diff -ur linux-2.6.32/arch/arm/mach-pxa/Makefile kernel/arch/arm/mach-pxa/Makefile +--- linux-2.6.32/arch/arm/mach-pxa/Makefile 2009-12-03 05:51:21.000000000 +0200 ++++ kernel/arch/arm/mach-pxa/Makefile 2009-12-12 16:09:26.426281936 +0200 +@@ -5,6 +5,15 @@ + # Common support (must be linked before board specific support) + obj-y += clock.o devices.o generic.o irq.o \ + time.o reset.o ++obj-$(CONFIG_PXA_DVFM) += dvfm.o ++ifeq ($(CONFIG_PXA3xx), y) ++ obj-$(CONFIG_PXA3xx_PMIC) += pxa3xx_pmic.o ++ obj-$(CONFIG_PXA3xx_DVFM) += pxa3xx_dvfm.o pxa3xx_dvfm_ll.o ++ obj-$(CONFIG_PXA3xx_PMU) += pmu.o pmu_ll.o ++ obj-$(CONFIG_PXA3xx_PRM) += prm.o ++ obj-$(CONFIG_BPMD) += bpm.o bpm_prof.o ++endif ++ + obj-$(CONFIG_PM) += pm.o sleep.o standby.o + + ifeq ($(CONFIG_CPU_FREQ),y) +@@ -66,6 +75,8 @@ + obj-$(CONFIG_MACH_PALMZ72) += palmz72.o + obj-$(CONFIG_MACH_TREO680) += treo680.o + obj-$(CONFIG_ARCH_VIPER) += viper.o ++obj-$(CONFIG_MACH_SGH_I900) += sgh_i780_i900.o sgh_smd.o sgh_rpc.o ++obj-$(CONFIG_MACH_SGH_I780) += sgh_i780_i900.o sgh_smd.o sgh_rpc.o + + ifeq ($(CONFIG_MACH_ZYLONITE),y) + obj-y += zylonite.o +diff -ur linux-2.6.32/arch/arm/mach-pxa/bpm.c kernel/arch/arm/mach-pxa/bpm.c +--- linux-2.6.32/arch/arm/mach-pxa/bpm.c 2009-12-13 12:57:59.831957275 +0200 ++++ kernel/arch/arm/mach-pxa/bpm.c 2009-12-12 16:09:26.429614458 +0200 +@@ -0,0 +1,1814 @@ ++/* ++ * linux/arch/arm/mach-pxa/bpm.c ++ * ++ * Provide bpm thread to scale system voltage & frequency dynamically. ++ * ++ * Copyright (C) 2008 Borqs Corporation. ++ * ++ * Author: Emichael Li <emichael.li@borqs.com> ++ * ++ * This software program is licensed subject to the GNU General Public License ++ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html ++ * ++ */ ++ ++#include <linux/kernel.h> ++#include <mach/prm.h> ++#include <mach/dvfm.h> ++#include <mach/mspm_prof.h> ++#include <linux/sysdev.h> ++#include <linux/delay.h> ++#include <mach/bpm.h> ++#include <mach/hardware.h> ++#include <mach/pxa3xx-regs.h> ++#include <linux/list.h> ++#include <asm/io.h> ++#include <asm/mach-types.h> ++#include <linux/freezer.h> ++#include <mach/regs-ost.h> ++#ifdef CONFIG_ANDROID_POWER ++#include <linux/android_power.h> ++#endif ++ ++#define DEBUG ++ ++#ifdef DEBUG ++#define PM_BUG_ON(condition) \ ++ do { \ ++ if (unlikely(condition)) { \ ++ printk(KERN_ERR "BUG: failure at %s:%d/%s()!\n", \ ++ __FILE__, __LINE__, __FUNCTION__); \ ++ WARN_ON(1); \ ++ } \ ++ } while(0) ++#define DPRINTK(fmt,args...) \ ++ do { \ ++ if (g_bpm_log_level) \ ++ printk(KERN_ERR "%s: " fmt, __FUNCTION__ , ## args); \ ++ } while (0) ++#else ++#define PM_BUG_ON(condition) \ ++ do { \ ++ if (unlikely(condition)) { \ ++ printk(KERN_ERR "BUG: failure at %s:%d/%s()!\n", \ ++ __FILE__, __LINE__, __FUNCTION__); \ ++ } \ ++ } while(0) ++#define DPRINTK(fmt,args...) \ ++ do {} while (0) ++#endif ++ ++/*****************************************************************************/ ++/* */ ++/* Policy variables */ ++/* */ ++/*****************************************************************************/ ++#define REDUCE_624M_DUTYCYCLE (1) ++ ++#define BPM_FREQ_POLICY_NUM (3) ++#define BPM_PROFILER_WINDOW (100) ++#define SYSTEM_BOOTUP_TIME (15000) ++#define BPM_MAX_OP_NUM (10) ++ ++struct bpm_freq_bonus_arg { ++ int mips; ++ int mem_stall; ++}; ++ ++struct bpm_freq_policy { ++ int lower[BPM_FREQ_POLICY_NUM]; ++ int higher[BPM_FREQ_POLICY_NUM]; ++}; ++ ++#define CONSTRAINT_ID_LEN (32) ++struct bpm_cons { ++ struct list_head list; ++ char sid[CONSTRAINT_ID_LEN]; ++ int count; ++ unsigned long ms; ++ unsigned long tmp_ms; ++ unsigned long tm; ++}; ++ ++struct bpm_cons_head { ++ struct list_head list; ++}; ++ ++/* manage all the ops which are supported by the hardware */ ++static struct dvfm_op g_dyn_ops[BPM_MAX_OP_NUM]; ++static spinlock_t g_dyn_ops_lock = SPIN_LOCK_UNLOCKED; ++ ++static struct bpm_cons_head g_bpm_cons[BPM_MAX_OP_NUM]; ++ ++/* map the op from active ops to g_dyn_ops[] */ ++static int g_active_ops_map[BPM_MAX_OP_NUM]; ++static int g_active_ops_num; ++static int g_active_cur_idx = -1; ++static int g_prefer_op_idx; ++static int g_active_bonus[BPM_MAX_OP_NUM][BPM_MAX_OP_NUM * 2 - 1]; ++struct bpm_freq_policy g_active_policy[BPM_MAX_OP_NUM]; ++ ++/*****************************************************************************/ ++/* */ ++/* Framework Supportted Variables */ ++/* */ ++/*****************************************************************************/ ++ ++int (*pipm_start_pmu) (void *) = NULL; ++EXPORT_SYMBOL(pipm_start_pmu); ++int (*pipm_stop_pmu)(void) = NULL; ++EXPORT_SYMBOL(pipm_stop_pmu); ++ ++static int g_bpm_thread_exit; ++int g_bpm_enabled; ++static wait_queue_head_t g_bpm_enabled_waitq; ++ ++static int g_profiler_window = BPM_PROFILER_WINDOW; ++static int g_bpm_log_level = 1; ++struct completion g_bpm_thread_over; ++ ++extern struct sysdev_class cpu_sysdev_class; ++ ++static struct bpm_event_queue g_bpm_event_queue; ++static spinlock_t g_bpm_event_queue_lock = SPIN_LOCK_UNLOCKED; ++ ++#ifdef CONFIG_TEST_BPMD ++static int g_cpuload_mode; ++#endif ++ ++static int dvfm_dev_idx; ++ ++extern int __dvfm_enable_op(int index, int dev_idx); ++extern int __dvfm_disable_op2(int index, int dev_idx); ++extern int cur_op; ++extern struct info_head dvfm_trace_list; ++ ++extern int g_dvfm_disabled; ++ ++#ifdef CONFIG_MTD_NAND_HSS_FIX ++extern atomic_t nand_in_cmd; ++#endif ++/*****************************************************************************/ ++/* */ ++/* Blink Variables */ ++/* */ ++/*****************************************************************************/ ++#define DVFM_BLINK_OWNER_LEN (16) ++ ++struct dvfm_blink_info { ++ int time; ++ char name[DVFM_BLINK_OWNER_LEN]; ++}; ++ ++static int g_dvfm_blink = 0; ++static struct timer_list g_dvfm_blink_timer; ++static struct dvfm_blink_info g_dvfm_binfo; ++static unsigned long g_dvfm_blink_timeout = 0; ++ ++/*****************************************************************************/ ++/* */ ++/* android power interface */ ++/* */ ++/*****************************************************************************/ ++static int g_android_suspended = 0; ++ ++#ifdef CONFIG_ANDROID_POWER ++void bpm_android_suspend_handler(android_early_suspend_t *h) ++{ ++ unsigned long flags; ++ local_irq_save(flags); ++ g_android_suspended = 1; ++ local_irq_restore(flags); ++} ++ ++void bpm_android_resume_handler(android_early_suspend_t *h) ++{ ++ unsigned long flags; ++ local_irq_save(flags); ++ g_android_suspended = 0; ++ local_irq_restore(flags); ++} ++ ++static android_early_suspend_t bpm_early_suspend = { ++ .level = 98, ++ .suspend = bpm_android_suspend_handler, ++ .resume = bpm_android_resume_handler, ++}; ++#endif ++ ++static inline int is_out_d0cs(void) ++{ ++#ifdef CONFIG_PXA3xx_DVFM ++ extern int out_d0cs; ++ return out_d0cs; ++#endif ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* */ ++/* BPMD Event Queue */ ++/* */ ++/*****************************************************************************/ ++ ++static int bpmq_init(void) ++{ ++ g_bpm_event_queue.head = g_bpm_event_queue.tail = 0; ++ g_bpm_event_queue.len = 0; ++ init_waitqueue_head(&g_bpm_event_queue.waitq); ++ return 0; ++} ++ ++static int bpmq_clear(void) ++{ ++ unsigned long flag; ++ ++ spin_lock_irqsave(&g_bpm_event_queue_lock, flag); ++ ++ g_bpm_event_queue.head = g_bpm_event_queue.tail = 0; ++ g_bpm_event_queue.len = 0; ++ ++ spin_unlock_irqrestore(&g_bpm_event_queue_lock, flag); ++ ++ return 0; ++} ++ ++static int bpmq_get(struct bpm_event *e) ++{ ++ unsigned long flag; ++ ++ spin_lock_irqsave(&g_bpm_event_queue_lock, flag); ++ ++ if (!g_bpm_event_queue.len) { ++ spin_unlock_irqrestore(&g_bpm_event_queue_lock, flag); ++ printk(KERN_ERR "Logic error, please check bpmq_empty()\n"); ++ return -1; ++ } ++ memcpy(e, g_bpm_event_queue.bpmes + g_bpm_event_queue.tail, ++ sizeof(struct bpm_event)); ++ g_bpm_event_queue.len--; ++ g_bpm_event_queue.tail = ++ (g_bpm_event_queue.tail + 1) % MAX_BPM_EVENT_NUM; ++ ++ spin_unlock_irqrestore(&g_bpm_event_queue_lock, flag); ++ ++ return 0; ++} ++ ++static int bpmq_put(struct bpm_event *e) ++{ ++ unsigned long flag; ++ static int err_cnt = 0; ++ ++ if (unlikely(0 == g_bpm_enabled)) ++ return 0; ++ ++ spin_lock_irqsave(&g_bpm_event_queue_lock, flag); ++ ++ if (g_bpm_event_queue.len == MAX_BPM_EVENT_NUM) { ++ if (++err_cnt > 0) { ++ printk(KERN_ERR "bpm queue over flow!\n"); ++ show_state(); ++ printk(KERN_ERR "send event many times instantly?"); ++ dump_stack(); ++ } ++ spin_unlock_irqrestore(&g_bpm_event_queue_lock, flag); ++ return -1; ++ } ++ memcpy(g_bpm_event_queue.bpmes + g_bpm_event_queue.head, e, ++ sizeof(struct bpm_event)); ++ g_bpm_event_queue.len++; ++ g_bpm_event_queue.head = ++ (g_bpm_event_queue.head + 1) % MAX_BPM_EVENT_NUM; ++ ++ spin_unlock_irqrestore(&g_bpm_event_queue_lock, flag); ++ ++ wake_up_interruptible(&g_bpm_event_queue.waitq); ++ ++ return 0; ++} ++ ++static __inline int bpmq_empty(void) ++{ ++ return (g_bpm_event_queue.len > 0) ? 0 : 1; ++} ++ ++int bpm_event_notify(int type, int kind, void *info, unsigned int info_len) ++{ ++ struct bpm_event event; ++ int len = 0; ++ ++ if (info_len > INFO_SIZE) ++ len = INFO_SIZE; ++ else if ((info_len < INFO_SIZE) && (info_len > 0)) ++ len = info_len; ++ memset(&event, 0, sizeof(struct bpm_event)); ++ event.type = type; ++ event.kind = kind; ++ if ((len > 0) && (info != NULL)) { ++ memcpy(event.info, info, len); ++ } ++ if (0 != bpmq_put(&event)) { ++ len = -1; ++ } ++ ++/* DPRINTK("type: %d kind: %d, len(ret): %d\n", type, kind, len); */ ++ return len; ++} ++ ++EXPORT_SYMBOL(bpm_event_notify); ++ ++/*****************************************************************************/ ++/* */ ++/* BPMD PMU Interface */ ++/* */ ++/*****************************************************************************/ ++ ++static int bpm_start_pmu(void) ++{ ++ int ret = -ENXIO; ++ struct ipm_profiler_arg pmu_arg; ++ ++ if (pipm_start_pmu != NULL) { ++ pmu_arg.size = sizeof(struct ipm_profiler_arg); ++/* pmu_arg.flags = IPM_IDLE_PROFILER | IPM_PMU_PROFILER; */ ++ pmu_arg.flags = IPM_IDLE_PROFILER; ++ pmu_arg.window_size = g_profiler_window; ++ ++ pmu_arg.pmn0 = PXA3xx_EVENT_EXMEM; ++ pmu_arg.pmn1 = PXA3xx_EVENT_DMC_NOT_EMPTY; ++ pmu_arg.pmn2 = PMU_EVENT_POWER_SAVING; ++ pmu_arg.pmn3 = PMU_EVENT_POWER_SAVING; ++ ++ ret = pipm_start_pmu(&pmu_arg); ++ } else { ++ printk(KERN_CRIT "No profiler\n"); ++ PM_BUG_ON(1); ++ } ++ ++ return ret; ++} ++ ++static int bpm_stop_pmu(void) ++{ ++ pipm_stop_pmu(); ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* */ ++/* BPMD POLICY */ ++/* */ ++/*****************************************************************************/ ++ ++static int bpm_dump_policy(void) ++{ ++#define TMP_BUF_SIZE (4096) ++ int i, j; ++ char *buf = kmalloc(TMP_BUF_SIZE, GFP_KERNEL); ++ char *s = NULL; ++ ++ if (NULL == buf) { ++ printk(KERN_ERR "Can not alloc memory\n"); ++ return 0; ++ } ++ ++ s = buf; ++ memset(s, 0, TMP_BUF_SIZE); ++ ++ s += sprintf(s, "--------------BPM DUMP POLICY BEGIN--------------\n"); ++ s += sprintf(s, "dyn_boot_op = %d\n", dvfm_get_defop()); ++ s += sprintf(s, "g_active_ops_maps:\n"); ++ ++ for (i = 0; i < BPM_MAX_OP_NUM; ++i) ++ s += sprintf(s, "%8d ", g_active_ops_map[i]); ++ s += sprintf(s, "\n"); ++ ++ s += sprintf(s, "g_active_ops_num: %d\n", g_active_ops_num); ++ s += sprintf(s, "g_active_cur_idx: %d\n", g_active_cur_idx); ++ ++ s += sprintf(s, "g_active_policy:\n"); ++ for (i = 0; i < BPM_MAX_OP_NUM; ++i) { ++ for (j = 0; j < BPM_FREQ_POLICY_NUM; ++j) { ++ s += sprintf(s, "%8d ", g_active_policy[i].lower[j]); ++ } ++ ++ for (j = 0; j < BPM_FREQ_POLICY_NUM; ++j) { ++ s += sprintf(s, "%8d ", g_active_policy[i].higher[j]); ++ } ++ s += sprintf(s, "\n"); ++ } ++ ++ DPRINTK("%s", buf); ++ ++ s = buf; ++ memset(s, 0, TMP_BUF_SIZE); ++ ++ s += sprintf(s, "g_active_bonus:\n"); ++ for (i = 0; i < BPM_MAX_OP_NUM; ++i) { ++ for (j = 0; j < BPM_MAX_OP_NUM * 2 - 1; ++j) { ++ s += sprintf(s, "%8d ", g_active_bonus[i][j]); ++ } ++ s += sprintf(s, "\n"); ++ } ++ ++ DPRINTK("%s", buf); ++ ++ s = buf; ++ memset(s, 0, TMP_BUF_SIZE); ++ ++ s += sprintf(s, "g_dyn_ops num: %d\n", ++ sizeof(g_dyn_ops) / sizeof(struct dvfm_op)); ++ ++ s += sprintf(s, "g_dyn_ops:\n"); ++ ++ for (i = 0; i < sizeof(g_dyn_ops) / sizeof(struct dvfm_op); ++i) { ++ s += sprintf(s, "%8d %8d %8d %s\n", ++ g_dyn_ops[i].index, ++ g_dyn_ops[i].count, ++ g_dyn_ops[i].cpu_freq, g_dyn_ops[i].name); ++ } ++ s += sprintf(s, "--------------BPM DUMP POLICY END----------------\n"); ++ ++ DPRINTK("%s", buf); ++ ++ kfree(buf); ++ return 0; ++} ++ ++static int build_active_ops(void) ++{ ++ int i, j; ++ int pre_idx; ++ int cur_idx; ++ int pre_freq, cur_freq, pre_ratio; ++ int m, n; ++ ++ memset(g_active_ops_map, -1, sizeof(g_active_ops_map)); ++ ++ for (i = 0, j = 0; i < BPM_MAX_OP_NUM; ++i) { ++ if (g_dyn_ops[i].count == 0 && g_dyn_ops[i].name != NULL ++ && !dvfm_check_active_op(g_dyn_ops[i].index)) ++ g_active_ops_map[j++] = i; ++ } ++ ++ g_active_ops_num = j; ++ g_active_cur_idx = -1; ++ ++ memset(g_active_bonus, -1, sizeof(g_active_bonus)); ++ memset(g_active_policy, -1, sizeof(g_active_policy)); ++ ++ for (i = 0; i < g_active_ops_num; ++i) { ++ g_active_policy[i].higher[0] = 80; ++ g_active_policy[i].higher[1] = 95; ++ g_active_policy[i].higher[2] = 100; ++ ++ if (i == 0) { ++ memset(g_active_policy[i].lower, 0, ++ sizeof(g_active_policy[i].lower)); ++ cur_idx = g_active_ops_map[i]; ++ cur_freq = g_dyn_ops[cur_idx].cpu_freq; ++ if (cur_freq == 60) { ++ g_active_policy[i].higher[0] = 90; ++ } ++ } else { ++ pre_idx = g_active_ops_map[i - 1]; ++ cur_idx = g_active_ops_map[i]; ++ pre_freq = g_dyn_ops[pre_idx].cpu_freq; ++ cur_freq = g_dyn_ops[cur_idx].cpu_freq; ++ pre_ratio = g_active_policy[i - 1].higher[0]; ++ ++ g_active_policy[i].lower[2] = pre_freq * pre_ratio / cur_freq; ++ ++ if (i > 1) { ++ pre_idx = g_active_ops_map[i - 2]; ++ pre_freq = g_dyn_ops[pre_idx].cpu_freq; ++ pre_ratio = g_active_policy[i - 2].higher[0]; ++ ++ g_active_policy[i].lower[1] = pre_freq * pre_ratio / cur_freq; ++ } else { ++ g_active_policy[i].lower[1] = 0; ++ } ++ ++ g_active_policy[i].lower[0] = 0; ++ } ++ ++ for (j = 0; j < g_active_ops_num - 1 - i; ++j) { ++ g_active_bonus[i][j] = 0; ++ } ++ ++ m = g_active_ops_num - 1; ++ n = 0; ++ for (j = m - i; j < 2 * g_active_ops_num - 1; ++j) { ++ g_active_bonus[i][j] = n < m ? n : m; ++ ++n; ++ } ++ ++ } ++ ++ g_active_policy[i - 1].higher[0] = 100; ++ g_active_policy[i - 1].higher[1] = 100; ++ g_active_policy[i - 1].higher[2] = 100; ++ ++#if REDUCE_624M_DUTYCYCLE ++ cur_idx = g_active_ops_map[i - 1]; ++ cur_freq = g_dyn_ops[cur_idx].cpu_freq; ++ if (cur_freq == 624) { ++ if (i > 1) { ++ g_active_policy[i - 2].higher[0] = 96; ++ g_active_policy[i - 2].higher[1] = 100; ++ ++ pre_idx = g_active_ops_map[i - 2]; ++ pre_freq = g_dyn_ops[pre_idx].cpu_freq; ++ pre_ratio = g_active_policy[i - 2].higher[0]; ++ ++ g_active_policy[i - 1].lower[2] = pre_freq * pre_ratio / cur_freq; ++ } ++ if (i > 2) { ++ g_active_policy[i - 3].higher[1] = 100; ++ ++ pre_idx = g_active_ops_map[i - 3]; ++ pre_freq = g_dyn_ops[pre_idx].cpu_freq; ++ pre_ratio = g_active_policy[i - 3].higher[0]; ++ ++ g_active_policy[i - 1].lower[1] = pre_freq * pre_ratio / cur_freq; ++ } ++ } ++#endif ++ return 0; ++} ++ ++/*****************************************************************************/ ++/* */ ++/* Platform Related */ ++/* */ ++/*****************************************************************************/ ++ ++int get_op_power_bonus(void) ++{ ++ if (0 == g_active_cur_idx) ++ return 1; ++ else ++ return 0; ++} ++ ++static int build_dyn_ops(void) ++{ ++ int i; ++ int ret; ++ int op_num = 0; ++ int count, x; ++ ++ struct op_info *info = NULL; ++ struct op_freq freq; ++ ++ op_num = dvfm_op_count(); ++ PM_BUG_ON(op_num > BPM_MAX_OP_NUM); ++ ++ memset(&g_dyn_ops, -1, sizeof(g_dyn_ops)); ++ ++ for (i = 0; i < op_num; ++i) { ++ ret = dvfm_get_opinfo(i, &info); ++ ++ PM_BUG_ON(ret); ++ ++ /* calculate how much bits is set in device word */ ++ x = info->device; ++ for (count = 0; x; x = x & (x - 1), count++); ++ ++ g_dyn_ops[i].index = i; ++ g_dyn_ops[i].count = count; ++ ++ ret = dvfm_get_op_freq(i, &freq); ++ PM_BUG_ON(ret); ++ ++ g_dyn_ops[i].cpu_freq = freq.cpu_freq; ++ ++ g_dyn_ops[i].name = dvfm_get_op_name(i); ++ ++ PM_BUG_ON(!g_dyn_ops[i].name); ++ ++ INIT_LIST_HEAD(&(g_bpm_cons[i].list)); ++ } ++ ++ for (i = op_num; i < BPM_MAX_OP_NUM; ++i) { ++ g_dyn_ops[i].index = -1; ++ g_dyn_ops[i].count = 0; ++ g_dyn_ops[i].cpu_freq = 0; ++ g_dyn_ops[i].name = NULL; ++ ++ INIT_LIST_HEAD(&(g_bpm_cons[i].list)); ++ } ++ ++ return 0; ++} ++ ++static int get_dyn_idx(int active_idx) ++{ ++ int t; ++ t = g_active_ops_map[active_idx]; ++ return g_dyn_ops[t].index; ++} ++ ++static int get_cur_freq(void) ++{ ++ PM_BUG_ON(g_active_cur_idx == -1); ++ return g_dyn_ops[get_dyn_idx(g_active_cur_idx)].cpu_freq; ++} ++ ++static int calc_new_idx(int bonus) ++{ ++ int new_idx; ++ ++ new_idx = ++ g_active_bonus[g_active_cur_idx][bonus + g_active_ops_num - 1]; ++ ++ return new_idx; ++} ++ ++static int calc_bonus(struct bpm_freq_bonus_arg *parg) ++{ ++ int i; ++ int bonus = 0; ++ int mem_stall = parg->mem_stall; ++ int mipsload = parg->mips * 100 / get_cur_freq(); ++ int cpuload = mipsload > 100 ? 100 : mipsload; ++ ++ PM_BUG_ON(cpuload > 100 || cpuload < 0); ++ ++ for (i = 0; i < BPM_FREQ_POLICY_NUM; ++i) { ++ if (cpuload > g_active_policy[g_active_cur_idx].higher[i]) { ++ bonus += 1; ++// break; /* FIX ME: change the freq one by one */ ++ } ++ } ++ ++ for (i = BPM_FREQ_POLICY_NUM - 1; i >= 0; --i) { ++ if (cpuload < g_active_policy[g_active_cur_idx].lower[i]) { ++ bonus -= 1; ++// break; /* FIX ME: change the freq one by one */ ++ } ++ } ++ ++ /* memory bound */ ++ if (bonus <= 0 && mem_stall > 17) ++ bonus = 1; ++ ++ /* change to user_sleep policy ... */ ++ if (g_android_suspended && (g_active_cur_idx <= 1)) ++ bonus -= 1; ++ ++ if (bonus > g_active_ops_num - 1) ++ bonus = g_active_ops_num - 1; ++ else if (bonus < 1 - g_active_ops_num) ++ bonus = 1 - g_active_ops_num; ++ ++ return bonus; ++} ++ ++/*****************************************************************************/ ++/* */ ++/* BPMD API */ ++/* */ ++/*****************************************************************************/ ++ ++static int bpm_change_op(int cur_idx, int new_idx) ++{ ++ int ret; ++ struct dvfm_freqs freqs; ++ unsigned int oscr; ++ ++ freqs.old = cur_idx; ++ freqs.new = new_idx; ++ oscr = OSCR; ++ ret = dvfm_set_op(&freqs, freqs.new, RELATION_STICK); ++ oscr = OSCR - oscr; ++ DPRINTK("old: %d cur: %d (tm: %d)\n", cur_idx, new_idx, oscr/325); ++/* ++ DPRINTK("ACCR: 0x%x ACSR: 0x%x AVCR: 0x%x SVCR: 0x%x CVCR: 0x%x\n", ++ ACCR, ACSR, AVCR, SVCR, CVCR); ++*/ ++ return ret; ++} ++ ++/* this function need to be refatored later? */ ++int bpm_disable_op(int dyn_idx, int dev_idx) ++{ ++ int i; ++ int ret = 0; ++ int cur_op_idx = -1, op_idx; ++ int next_op_idx = -1, next_active_idx = -1; ++ ++ op_idx = g_dyn_ops[dyn_idx].index; ++ ++ /* save current op information */ ++ if (g_active_cur_idx != -1) { ++ cur_op_idx = get_dyn_idx(g_active_cur_idx); ++ } ++ ++ if (!dvfm_check_active_op(op_idx) && g_active_ops_num == 1 && ++ cur_op_idx == op_idx) { ++ printk(KERN_ERR "Can't disable this op %d\n", op_idx); ++ bpm_dump_policy(); ++ return -1; ++ } ++ ++ /* ++ * it should be at least two enabled ops here, ++ * otherwise it cannot come here if there is one enabled op. ++ */ ++ if ((g_active_cur_idx != -1) && (g_active_ops_num > 1)) { ++ if (g_active_cur_idx == (g_active_ops_num - 1)) { ++ next_op_idx = get_dyn_idx(g_active_cur_idx - 1); ++ PM_BUG_ON((g_active_cur_idx - 1) < 0); ++ if ((g_active_cur_idx - 1) < 0) { ++ printk(KERN_ERR "err: %d %d\n", g_active_cur_idx, g_active_ops_num); ++ bpm_dump_policy(); ++ } ++ } else { ++ next_op_idx = get_dyn_idx(g_active_cur_idx + 1); ++ PM_BUG_ON((g_active_cur_idx + 1) > (g_active_ops_num - 1)); ++ if ((g_active_cur_idx + 1) > (g_active_ops_num - 1)) { ++ printk(KERN_ERR "err2: %d %d\n", g_active_cur_idx, g_active_ops_num); ++ bpm_dump_policy(); ++ } ++ } ++ } ++ ++ g_dyn_ops[dyn_idx].count++; ++ ++ __dvfm_disable_op2(op_idx, dev_idx); ++ ++ if (!dvfm_check_active_op(op_idx) && g_dyn_ops[dyn_idx].count == 1) { ++ build_active_ops(); ++ } ++ ++ if (cur_op_idx != -1) { ++ for (i = 0; i < g_active_ops_num; ++i) { ++ if (get_dyn_idx(i) == cur_op_idx) { ++ g_active_cur_idx = i; ++ break; ++ } ++ } ++ ++ /* the disabled op is previous op, change to another op */ ++ if (g_active_cur_idx == -1) { ++ ++ /* find next op */ ++ for (i = 0; i < g_active_ops_num; ++i) { ++ if (get_dyn_idx(i) == next_op_idx) { ++ next_active_idx = i; ++ break; ++ } ++ } ++ ++ PM_BUG_ON(cur_op_idx != op_idx); ++ PM_BUG_ON(next_op_idx != get_dyn_idx(next_active_idx)); ++ g_active_cur_idx = next_active_idx; ++ ret = bpm_change_op(cur_op_idx, next_op_idx); ++ PM_BUG_ON(ret); ++ |
