summaryrefslogtreecommitdiff
path: root/packages/linux/linux-ezx/dpm-pxa27x-2.6.16.patch
diff options
context:
space:
mode:
authorMichael Lauer <mickey@vanille-media.de>2006-05-20 18:31:50 +0000
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>2006-05-20 18:31:50 +0000
commit61a3368e962e14767ccbd4f24456b362bedbfdd2 (patch)
tree365738e7b61ac4c5ed95e64876acc334490c54f7 /packages/linux/linux-ezx/dpm-pxa27x-2.6.16.patch
parentf89ded6650e53252ce92bb12072a47f63badc918 (diff)
parent5dc648ea9c4ff5e7976f17459dc2fb685fcebc26 (diff)
merge of 17b5ed09da5a4cdb493874b746d2586d5ba53c86
and 8d5e1a3025b2da6e7d30136891450c13c77eacfe
Diffstat (limited to 'packages/linux/linux-ezx/dpm-pxa27x-2.6.16.patch')
-rw-r--r--packages/linux/linux-ezx/dpm-pxa27x-2.6.16.patch2469
1 files changed, 0 insertions, 2469 deletions
diff --git a/packages/linux/linux-ezx/dpm-pxa27x-2.6.16.patch b/packages/linux/linux-ezx/dpm-pxa27x-2.6.16.patch
deleted file mode 100644
index e429a7b754..0000000000
--- a/packages/linux/linux-ezx/dpm-pxa27x-2.6.16.patch
+++ /dev/null
@@ -1,2469 +0,0 @@
-Source: MontaVista Software, Inc.
-MR: 9340
-Type: Enhancment
-Disposition: submitted to
-Keywords: DPM, PXA27x
-Description:
- Platform core support for DPM functions (NOT including drivers)
-
-
-Index: linux-2.6.16/arch/arm/mach-pxa/Makefile
-===================================================================
---- linux-2.6.16.orig/arch/arm/mach-pxa/Makefile
-+++ linux-2.6.16/arch/arm/mach-pxa/Makefile
-@@ -31,4 +31,5 @@ obj-$(CONFIG_PXA_SSP) += ssp.o
-
- ifeq ($(CONFIG_PXA27x),y)
- obj-$(CONFIG_PM) += standby.o
-+obj-$(CONFIG_DPM) += dpm-pxa27x.o
- endif
-Index: linux-2.6.16/include/asm-arm/arch-pxa/dpm.h
-===================================================================
---- /dev/null
-+++ linux-2.6.16/include/asm-arm/arch-pxa/dpm.h
-@@ -0,0 +1,157 @@
-+/*
-+ * include/asm-arm/arch-pxa/dpm.h
-+ *
-+ * Bulverde-specific definitions for DPM. If further PXA boards are
-+ * supported in the future, will split into board-specific files.
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * Copyright (C) 2002 MontaVista Software <source@mvista.com>
-+ *
-+ * Based on arch/ppc/platforms/ibm405lp_dpm.h by Bishop Brock.
-+ */
-+
-+#ifndef __ASM_ARM_PXA_DPM_H__
-+#define __ASM_ARM_PXA_DPM_H__
-+
-+/*
-+ * machine dependent operating state
-+ *
-+ * An operating state is a cpu execution state that has implications for power
-+ * management. The DPM will select operating points based largely on the
-+ * current operating state.
-+ *
-+ * DPM_STATES is the number of supported operating states. Valid operating
-+ * states are from 0 to DPM_STATES-1 but when setting an operating state the
-+ * kernel should only specify a state from the set of "base states" and should
-+ * do so by name. During the context switch the new operating state is simply
-+ * extracted from current->dpm_state.
-+ *
-+ * task states:
-+ *
-+ * APIs that reference task states use the range -(DPM_TASK_STATE_LIMIT + 1)
-+ * through +DPM_TASK_STATE_LIMIT. This value is added to DPM_TASK_STATE to
-+ * obtain the downward or upward adjusted task state value. The
-+ * -(DPM_TASK_STATE_LIMIT + 1) value is interpreted specially, and equates to
-+ * DPM_NO_STATE.
-+ *
-+ * Tasks inherit their task operating states across calls to
-+ * fork(). DPM_TASK_STATE is the default operating state for all tasks, and is
-+ * inherited from init. Tasks can change (or have changed) their tasks states
-+ * using the DPM_SET_TASK_STATE variant of the sys_dpm() system call. */
-+
-+#define DPM_NO_STATE -1
-+
-+#define DPM_IDLE_TASK_STATE 0
-+#define DPM_IDLE_STATE 1
-+#define DPM_SLEEP_STATE 2
-+#define DPM_BASE_STATES 3
-+
-+#define DPM_TASK_STATE_LIMIT 4
-+#define DPM_TASK_STATE (DPM_BASE_STATES + DPM_TASK_STATE_LIMIT)
-+#define DPM_STATES (DPM_TASK_STATE + DPM_TASK_STATE_LIMIT + 1)
-+#define DPM_TASK_STATES (DPM_STATES - DPM_BASE_STATES)
-+
-+/*
-+ *length of DPM_STATE_NAMES is DPM_STATES,
-+ */
-+#define DPM_STATE_NAMES \
-+{ "idle-task", "idle", "sleep",\
-+ "task-4", "task-3", "task-2", "task-1",\
-+ "task", \
-+ "task+1", "task+2", "task+3", "task+4" \
-+}
-+
-+/* Operating point parameters */
-+#define DPM_MD_V 0 /* Voltage */
-+#define DPM_MD_PLL_L 1 /* L */
-+#define DPM_MD_PLL_N 2 /* N */
-+#define DPM_MD_PLL_B 3 /* B */
-+#define DPM_MD_HALF_TURBO 4 /* Cuts turbo mode in half */
-+#define DPM_MD_CCCRA 5 /* The A bit in the CCCR is
-+ for MEMC clocks */
-+#define DPM_MD_CPLL_ON 6 /* Core PLL on/off */
-+#define DPM_MD_PPLL_ON 7 /* Peripheral PLL on/off */
-+#define DPM_MD_SLEEP_MODE 8 /* Sleep mode, from pm.h */
-+#define DPM_MD_PLL_LCD 9 /* calculated value */
-+
-+
-+enum
-+{
-+ CPUMODE_RUN,
-+ CPUMODE_IDLE,
-+ CPUMODE_STANDBY,
-+ CPUMODE_SLEEP,
-+ CPUMODE_RESERVED,
-+ CPUMODE_SENSE,
-+ CPUMODE_RESERVED2,
-+ CPUMODE_DEEPSLEEP,
-+};
-+
-+/* this is the number of specifiable operating point parameters,
-+ * used by arch-independent DPM-core driver
-+ */
-+#define DPM_PP_NBR 10
-+#define DPM_PARAM_NAMES {"v","l","n","b","ht","a","cpll", "ppll","sleep", "lcd"};
-+
-+#ifndef __ASSEMBLER__
-+
-+#include <linux/types.h>
-+#include <linux/proc_fs.h>
-+#include <asm/hardware.h>
-+#include <asm/arch/pxa-regs.h>
-+
-+#define dpm_time() (OSCR)
-+#define DPM_NSEC_PER_TICK 308 /* nanoseconds per tick */
-+#define dpm_time_to_usec(ticks) ({ \
-+ unsigned long long quot = \
-+ ((ticks) * DPM_NSEC_PER_TICK * 2 + 1); \
-+ do_div(quot, (unsigned long) 1000*2); \
-+ quot; })
-+
-+struct dpm_regs {
-+ unsigned int cccr;
-+ unsigned int clkcfg;
-+ unsigned int voltage; /*This is not a register.*/
-+};
-+
-+/* Instances of this structure define valid Bulverde operating points for DPM.
-+ Voltages are represented in mV, and frequencies are represented in KHz. */
-+
-+struct dpm_md_opt {
-+ /* Specified values */
-+ int v; /* Target voltage in mV*/
-+ int l; /* Run Mode to Oscillator ratio */
-+ int n; /* Turbo-Mode to Run-Mode ratio */
-+ int b; /* Fast Bus Mode */
-+ int half_turbo;/* Half Turbo bit */
-+ int cccra; /* the 'A' bit of the CCCR register,
-+ alternate MEMC clock */
-+ int cpll_enabled; /* core PLL is ON? (Bulverde >="C0" feature)*/
-+ int ppll_enabled; /* peripherial PLL is ON? (Bulverde >="C0" feature)*/
-+
-+ int sleep_mode;
-+ /*Calculated values*/
-+ unsigned int lcd; /*in KHz */
-+ unsigned int lpj; /*New value for loops_per_jiffy */
-+ unsigned int cpu; /*CPU frequency in KHz */
-+ unsigned int turbo; /* Turbo bit in clkcfg */
-+
-+ struct dpm_regs regs; /* Register values */
-+};
-+
-+#endif /* __ASSEMBLER__ */
-+#endif /* __ASM_BULVERDE_DPM_H__ */
-+
-Index: linux-2.6.16/arch/arm/mach-pxa/dpm-pxa27x.c
-===================================================================
---- /dev/null
-+++ linux-2.6.16/arch/arm/mach-pxa/dpm-pxa27x.c
-@@ -0,0 +1,2110 @@
-+/*
-+ * arch/arm/mach-pxa/dpm-pxa27x.c DPM support for Intel PXA27x
-+ *
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-+ *
-+ * Copyright (C) 2002, 2005 MontaVista Software <source@mvista.com>.
-+ *
-+ * Includes code from David Burrage, Alexandre Rusev, and Todd Poynor,
-+ * based on DPM code by Matthew Locke, Dmitry Chigirev and Bishop Brock.
-+ *
-+ * Includes cpufreq/ipm code by Chao Xie and Cain Yuan
-+ * Copyright (C) 2003-2004 Intel Corporation.
-+ */
-+
-+#include <linux/config.h>
-+
-+#include <linux/dpm.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/kernel.h>
-+
-+#include <linux/delay.h>
-+
-+#include <asm/uaccess.h>
-+#include <asm/pgtable.h>
-+#include <asm/pgalloc.h>
-+#include <asm/hardware.h>
-+#include <asm/system.h>
-+#include <asm/io.h>
-+#include <asm/arch/pxa-regs.h>
-+#include <asm/arch/system.h>
-+#include <asm/arch/dpm.h>
-+#include <asm/mach/time.h>
-+
-+static int saved_loops_per_jiffy = 0;
-+static int saved_cpu_freq = 0;
-+
-+#define CCCR_CPDIS_BIT_ON (1 << 31)
-+#define CCCR_PPDIS_BIT_ON (1 << 30)
-+#define CCCR_CPDIS_BIT_OFF (0 << 31)
-+#define CCCR_PPDIS_BIT_OFF (0 << 30)
-+#define CCCR_PLL_EARLY_EN_BIT_ON (1 << 26)
-+#define CCSR_CPLL_LOCKED (1 << 29)
-+#define CCSR_PPLL_LOCKED (1 << 28)
-+
-+/* CLKCFG
-+ | 31------------------------------------------- | 3 | 2 | 1 | 0 |
-+ | --------------------------------------------- | B | HT | F | T |
-+*/
-+#define CLKCFG_B_BIT (1 << 3)
-+#define CLKCFG_HT_BIT (1 << 2)
-+#define CLKCFG_F_BIT (1 << 1)
-+#define CLKCFG_T_BIT 1
-+
-+#define PLL_L_MAX 31
-+#define PLL_N_MAX 8
-+
-+/* The MIN for L is 2 in the Yellow Book tables, but L=1 really means
-+ 13M mode, so L min includes 1 */
-+#define PLL_L_MIN 1
-+#define PLL_N_MIN 2
-+
-+#define CCLKCFG_TURBO 0x1
-+#define CCLKCFG_FCS 0x2
-+
-+#define L_NUM 31 /* 30 different L numbers. */
-+#define N_NUM 7 /* 7 N numbers. */
-+
-+#define BLVD_MIN_FREQ 13000
-+/* latest PowerPoint documentation indicates 624000*/
-+#define BLVD_MAX_FREQ 520000
-+
-+#define MAX_VOL 1400 /* in mV. */
-+#define MIN_VOL 850 /* in Mv. */
-+
-+#define MDREFR_DRI 0xFFF
-+#define MSC0_RDF (0xF << 20)
-+#define MSC0_RDN (0xF << 24)
-+#define MSC0_RRR (0x7 << 12)
-+#define MDREFR_RFU 0xC0200000
-+#define MDCNFG_DTC0 (0x3 << 8)
-+#define MDCNFG_DTC2 (0x3 << 24)
-+
-+/* memory timing (MSC0,DTC,DRI) constants (see Blob and Intel BBU sources) */
-+#define XLLI_MSC0_13 0x11101110
-+#define XLLI_MSC0_19 0x11101110
-+#define XLLI_MSC0_26 0x11201120 /* 26 MHz setting */
-+#define XLLI_MSC0_32 0x11201120
-+#define XLLI_MSC0_39 0x11301130 /* 39 MHz setting */
-+#define XLLI_MSC0_45 0x11301130
-+#define XLLI_MSC0_52 0x11401140 /* @ 52 MHz setting */
-+#define XLLI_MSC0_58 0x11401140
-+#define XLLI_MSC0_65 0x11501150 /* @ 65 MHz setting */
-+#define XLLI_MSC0_68 0x11501150
-+#define XLLI_MSC0_71 0x11501150 /* @ 71.5 MHz setting */
-+#define XLLI_MSC0_74 0x11601160
-+#define XLLI_MSC0_78 0x12601260 /* @ 78 MHz setting */
-+#define XLLI_MSC0_81 0x12601260
-+#define XLLI_MSC0_84 0x12601260 /* @ 84.5 MHz setting */
-+#define XLLI_MSC0_87 0x12701270
-+#define XLLI_MSC0_91 0x12701270 /* 91 MHz setting */
-+#define XLLI_MSC0_94 0x12701270 /* 94.2 MHz setting */
-+#define XLLI_MSC0_97 0x12701270 /* 97.5 MHz setting */
-+#define XLLI_MSC0_100 0x12801280 /* 100.7 MHz setting */
-+#define XLLI_MSC0_104 0x12801280 /* 104 MHz setting */
-+#define XLLI_MSC0_110 0x12901290
-+#define XLLI_MSC0_117 0x13901390 /* 117 MHz setting */
-+#define XLLI_MSC0_124 0x13A013A0
-+#define XLLI_MSC0_130 0x13A013A0 /* 130 MHz setting */
-+#define XLLI_MSC0_136 0x13B013B0
-+#define XLLI_MSC0_143 0x13B013B0
-+#define XLLI_MSC0_149 0x13C013C0
-+#define XLLI_MSC0_156 0x14C014C0
-+#define XLLI_MSC0_162 0x14C014C0
-+#define XLLI_MSC0_169 0x14C014C0
-+#define XLLI_MSC0_175 0x14C014C0
-+#define XLLI_MSC0_182 0x14C014C0
-+#define XLLI_MSC0_188 0x14C014C0
-+#define XLLI_MSC0_195 0x15C015C0
-+#define XLLI_MSC0_201 0x15D015D0
-+#define XLLI_MSC0_208 0x15D015D0
-+
-+/* DTC settings depend on 16/32 bit SDRAM we have (32 is chosen) */
-+#define XLLI_DTC_13 0x00000000
-+#define XLLI_DTC_19 0x00000000
-+#define XLLI_DTC_26 0x00000000
-+#define XLLI_DTC_32 0x00000000
-+#define XLLI_DTC_39 0x00000000
-+#define XLLI_DTC_45 0x00000000
-+#define XLLI_DTC_52 0x00000000
-+#define XLLI_DTC_58 0x01000100
-+#define XLLI_DTC_65 0x01000100
-+#define XLLI_DTC_68 0x01000100
-+#define XLLI_DTC_71 0x01000100
-+#define XLLI_DTC_74 0x01000100
-+#define XLLI_DTC_78 0x01000100
-+#define XLLI_DTC_81 0x01000100
-+#define XLLI_DTC_84 0x01000100
-+#define XLLI_DTC_87 0x01000100
-+#define XLLI_DTC_91 0x02000200
-+#define XLLI_DTC_94 0x02000200
-+#define XLLI_DTC_97 0x02000200
-+#define XLLI_DTC_100 0x02000200
-+#define XLLI_DTC_104 0x02000200
-+/* 110-208 MHz setting - SDCLK Halved*/
-+#define XLLI_DTC_110 0x01000100
-+#define XLLI_DTC_117 0x01000100
-+#define XLLI_DTC_124 0x01000100
-+#define XLLI_DTC_130 0x01000100
-+#define XLLI_DTC_136 0x01000100
-+#define XLLI_DTC_143 0x01000100
-+#define XLLI_DTC_149 0x01000100
-+#define XLLI_DTC_156 0x01000100
-+#define XLLI_DTC_162 0x01000100
-+#define XLLI_DTC_169 0x01000100
-+#define XLLI_DTC_175 0x01000100
-+/* 182-208 MHz setting - SDCLK Halved - Close to edge, so bump up */
-+#define XLLI_DTC_182 0x02000200
-+#define XLLI_DTC_188 0x02000200
-+#define XLLI_DTC_195 0x02000200
-+#define XLLI_DTC_201 0x02000200
-+#define XLLI_DTC_208 0x02000200
-+
-+/* Optimal values for DRI (refreash interval) settings for
-+ * various MemClk settings (MDREFR)
-+ */
-+#define XLLI_DRI_13 0x002
-+#define XLLI_DRI_19 0x003
-+#define XLLI_DRI_26 0x005
-+#define XLLI_DRI_32 0x006
-+#define XLLI_DRI_39 0x008
-+#define XLLI_DRI_45 0x00A
-+#define XLLI_DRI_52 0x00B
-+#define XLLI_DRI_58 0x00D
-+#define XLLI_DRI_65 0x00E
-+#define XLLI_DRI_68 0x00F
-+#define XLLI_DRI_71 0x010
-+#define XLLI_DRI_74 0x011
-+#define XLLI_DRI_78 0x012
-+#define XLLI_DRI_81 0x012
-+#define XLLI_DRI_84 0x013
-+#define XLLI_DRI_87 0x014
-+#define XLLI_DRI_91 0x015
-+#define XLLI_DRI_94 0x016
-+#define XLLI_DRI_97 0x016
-+#define XLLI_DRI_100 0x017
-+#define XLLI_DRI_104 0x018
-+#define XLLI_DRI_110 0x01A
-+#define XLLI_DRI_117 0x01B
-+#define XLLI_DRI_124 0x01D
-+#define XLLI_DRI_130 0x01E
-+#define XLLI_DRI_136 0x020
-+#define XLLI_DRI_143 0x021
-+#define XLLI_DRI_149 0x023
-+#define XLLI_DRI_156 0x025
-+#define XLLI_DRI_162 0x026
-+#define XLLI_DRI_169 0x028
-+#define XLLI_DRI_175 0x029
-+#define XLLI_DRI_182 0x02B
-+#define XLLI_DRI_188 0x02D
-+#define XLLI_DRI_195 0x02E
-+#define XLLI_DRI_201 0x030
-+#define XLLI_DRI_208 0x031
-+
-+
-+
-+/* timings for memory controller set up (masked values) */
-+struct mem_timings{
-+ unsigned int msc0; /* for MSC0 */
-+ unsigned int dtc; /* for MDCNFG */
-+ unsigned int dri; /* for MDREFR */
-+};
-+
-+static unsigned int cpufreq_matrix[N_NUM][L_NUM + 1];
-+static volatile int *ramstart;
-+
-+#define CP15R0_REV_MASK 0x0000000f
-+#define PXA270_C5 0x7
-+
-+static u32 chiprev;
-+static int mvdt_size;
-+
-+struct MvDAC {
-+ unsigned int mv;
-+ unsigned int DACIn;
-+} *mvDACtable;
-+
-+/*
-+ * Transfer desired mv to required DAC value.
-+ * Vcore = 1.3v - ( 712uv * DACIn )
-+ */
-+static struct MvDAC table_c0[] = {
-+ {1425, 0},
-+ {1400, 69},
-+ {1300, 248},
-+ {1200, 428},
-+ {1100, 601},
-+ {1000, 777},
-+ {950, 872},
-+ {868, 1010},
-+ {861, 0xFFFFFFFF},
-+};
-+
-+/*
-+ * Transfer desired mv to required DAC value, update for new boards,
-+ * according to "Intel PXA27x Processor Developer's Kit User's Guide,
-+ * April 2004, Revision 4.001"
-+ * Vcore = 1.5V - (587uV * DAC(input)).
-+ */
-+static struct MvDAC table_c5[] = {
-+ {1500, 0},
-+ {1484,25},
-+ {1471,50},
-+ {1456,75},
-+ {1441,100},
-+ {1427,125},
-+ {1412,150},
-+ {1397,175},
-+ {1383,200},
-+ {1368,225},
-+ {1353,250},
-+ {1339,275},
-+ {1323,300},
-+ {1309,325},
-+ {1294,350},
-+ {1280,375},
-+ {1265,400},
-+ {1251,425},
-+ {1236,450},
-+ {1221,475},
-+ {1207,500},
-+ {1192,525},
-+ {1177,550},
-+ {1162,575},
-+ {1148,600},
-+ {1133,625},
-+ {1118,650},
-+ {1104,675},
-+ {1089,700},
-+ {1074,725},
-+ {1060,750},
-+ {1045,775},
-+ {1030,800},
-+ {1016,825},
-+ {1001,850},
-+ {986,875},
-+ {972,900},
-+ {957,925},
-+ {942,950},
-+ {928,975},
-+ {913,1000},
-+ {899, 1023},
-+};
-+
-+static unsigned int mv2DAC(unsigned int mv)
-+{
-+ int i, num = mvdt_size;
-+
-+ if (mvDACtable[0].mv <= mv) { /* Max or bigger */
-+ /* Return the first one */
-+ return mvDACtable[0].DACIn;
-+ }
-+
-+ if (mvDACtable[num - 1].mv >= mv) { /* Min or smaller */
-+ /* Return the last one */
-+ return mvDACtable[num - 1].DACIn;
-+ }
-+
-+ /* The biggest and smallest value cases are covered, now the
-+ loop may skip those */
-+ for (i = 1; i <= (num - 1); i++) {
-+ if ((mvDACtable[i].mv >= mv) && (mvDACtable[i + 1].mv < mv)) {
-+ return mvDACtable[i].DACIn;
-+ }
-+ }
-+
-+ /* Should never get here */
-+ return 0;
-+}
-+
-+static void clr_all_sqc(void)
-+{
-+ int i = 0;
-+ for (i = 0; i < 32; i++)
-+ PCMD(i) &= ~PCMD_SQC;
-+}
-+
-+static void clr_all_mbc(void)
-+{
-+ int i = 0;
-+ for (i = 0; i < 32; i++)
-+ PCMD(i) &= ~PCMD_MBC;
-+}
-+
-+static void clr_all_dce(void)
-+{
-+ int i = 0;
-+ for (i = 0; i < 32; i++)
-+ PCMD(i) &= ~PCMD_DCE;
-+}
-+
-+static void set_mbc_bit(int ReadPointer, int NumOfBytes)
-+{
-+ PCMD0 |= PCMD_MBC;
-+ PCMD1 |= PCMD_MBC;
-+}
-+
-+static void set_lc_bit(int ReadPointer, int NumOfBytes)
-+{
-+ PCMD0 |= PCMD_LC;
-+ PCMD1 |= PCMD_LC;
-+ PCMD2 |= PCMD_LC;
-+}
-+
-+static void set_cmd_data(unsigned char *DataArray, int StartPoint, int size)
-+{
-+ PCMD0 &= 0xFFFFFF00;
-+ PCMD0 |= DataArray[0];
-+ PCMD1 &= 0xFFFFFF00;
-+ PCMD1 |= DataArray[1];
-+ PCMD2 &= 0xFFFFFF00;
-+ PCMD2 |= DataArray[2];
-+}
-+
-+/* coupled indicates that this VCS is to be coupled with a FCS */
-+static void power_change_cmd(unsigned int DACValue, int coupled)
-+{
-+ unsigned char dataArray[3];
-+
-+ dataArray[0] = 0; /* Command 0 */
-+ dataArray[1] = (DACValue & 0x000000FF); /* data LSB */
-+ dataArray[2] = (DACValue & 0x0000FF00) >> 8; /* data MSB */
-+
-+ PVCR = 0;
-+
-+ PCFR &= ~PCFR_FVC;
-+ PVCR &= 0xFFFFF07F; /* no delay is necessary */
-+ PVCR &= 0xFFFFFF80; /* clear slave address */
-+ PVCR |= 0x20; /* set slave address */
-+
-+ PVCR &= 0xFE0FFFFF; /* clear read pointer 0 */
-+ PVCR |= 0;
-+
-+ /* DCE and SQC are not necessary for single command */
-+ clr_all_sqc();
-+ clr_all_dce();
-+
-+ clr_all_mbc();
-+ set_mbc_bit(0, 2);
-+
-+ /* indicate the last byte of this command is holded in this register */
-+ PCMD2 &= ~PCMD_MBC;
-+
-+ /* indicate this is the first command and last command also */
-+ set_lc_bit(0, 3);
-+
-+ /* programming the command data bit */
-+ set_cmd_data(dataArray, 0, 2);
-+
-+ if (coupled) {
-+ /* Enable Power I2C and FVC */
-+ PCFR |= (PCFR_PI2CEN | PCFR_FVC);
-+ } else {
-+ /* Enable Power I2C */
-+ PCFR |= PCFR_PI2CEN;
-+ }
-+}
-+
-+static void change_voltage(void)
-+{
-+ unsigned long flags;
-+ unsigned int unused;
-+
-+
-+ local_irq_save(flags);
-+
-+ __asm__ __volatile__("\n\
-+ @ WOKAROUND - Core hangs on voltage change at different\n\
-+ @ alignments and at different core clock frequencies\n\
-+ @ To ensure that no external fetches occur, we want to store the next\n\
-+ @ several instructions that occur after the voltage change inside\n\
-+ @ the cache. The load dependency stall near the retry label ensures \n\
-+ @ that any outstanding instruction cacheline loads are complete before \n\
-+ @ the mcr instruction is executed on the 2nd pass. This procedure \n\
-+ @ ensures us that the internal bus will not be busy. \n\
-+ \n\
-+ b 2f \n\
-+ nop \n\
-+ .align 5 \n\
-+2: \n\
-+ ldr r0, [%1] @ APB register read and compare \n\
-+ cmp r0, #0 @ fence for pending slow apb reads \n\
-+ \n\
-+ mov r0, #8 @ VC bit for PWRMODE \n\
-+ movs r1, #1 @ don't execute mcr on 1st pass \n\
-+ \n\
-+ @ %1 points to uncacheable memory to force memory read \n\
-+ \n\
-+retry: \n\
-+ ldreq r3, [%2] @ only stall on the 2nd pass\n\
-+ cmpeq r3, #0 @ cmp causes fence on mem transfers\n\
-+ cmp r1, #0 @ is this the 2nd pass? \n\
-+ mcreq p14, 0, r0, c7, c0, 0 @ write to PWRMODE on 2nd pass only \n\
-+ \n\
-+ @ Read VC bit until it is 0, indicates that the VoltageChange is done.\n\
-+ @ On first pass, we never set the VC bit, so it will be clear already.\n\
-+ \n\
-+VoltageChange_loop: \n\
-+ mrc p14, 0, r3, c7, c0, 0 \n\
-+ tst r3, #0x8 \n\
-+ bne VoltageChange_loop \n\
-+ \n\
-+ subs r1, r1, #1 @ update conditional execution counter\n\
-+ beq retry":"=&r"(unused)
-+ :"r"(&CCCR), "r"(ramstart)
-+ :"r0", "r1", "r3");
-+
-+ local_irq_restore(flags);
-+}
-+
-+void vm_setvoltage(unsigned int DACValue)
-+{
-+ power_change_cmd(DACValue, 0 /* not-coupled */ );
-+ /* Execute voltage change sequence */
-+ change_voltage(); /* set VC on the PWRMODE on CP14 */
-+}
-+
-+static void set_voltage(unsigned int mv)
-+{
-+ vm_setvoltage(mv2DAC(mv));
-+}
-+
-+static int vcs_init(void)
-+{
-+ /* we distinguish new and old boards by proc chip
-+ * revision, we assume new boards have C5 proc
-+ * revision and we use the new table (table_c5) for them,
-+ * for all other boards we use the old table (table_c0).
-+ * Note, the logics won't work and inaccurate voltage
-+ * will be set if C5 proc installed to old board
-+ * and vice versa.
-+ */
-+
-+ asm("mrc%? p15, 0, %0, c0, c0" : "=r" (chiprev));
-+
-+ chiprev &= CP15R0_REV_MASK;
-+
-+ if (chiprev == PXA270_C5) {
-+ mvDACtable = table_c5;
-+ mvdt_size = sizeof(table_c5) / sizeof(struct MvDAC);
-+ } else {
-+ mvDACtable = table_c0;
-+ mvdt_size = sizeof(table_c0) / sizeof(struct MvDAC);
-+ }
-+
-+ CKEN |= 0x1 << 15;
-+ CKEN |= 0x1 << 14;
-+ PCFR = PCFR_PI2CEN;
-+ return 0;
-+}
-+
-+static void initialize_freq_matrix(void)
-+{
-+ int n, l;
-+
-+ memset(&cpufreq_matrix, 0, sizeof(cpufreq_matrix));
-+
-+ for (n = 2; n < N_NUM + 2; n++) {
-+ for (l = 2; l <= L_NUM; l++) {
-+ cpufreq_matrix[n - 2][l - 2] = (13 * n * l / 2) * 1000;
-+ if (cpufreq_matrix[n - 2][l - 2] > BLVD_MAX_FREQ)
-+ cpufreq_matrix[n - 2][l - 2] = 0;
-+ }
-+ }
-+}
-+
-+/*
-+ This should be called with a valid freq point that was
-+ obtained via validate_speed
-+*/
-+static void set_freq(unsigned int CLKCFGValue)
-+{
-+ unsigned long flags;
-+ unsigned int unused;
-+ unsigned int fcsbits = 0xe3dfeff;
-+ volatile int v;
-+
-+ local_irq_save(flags);
-+
-+ /*
-+ force a tlb fault to get the mapping into the tlb
-+ (otherwise this will occur below when the sdram is turned off and
-+ something-bad(tm) will happen)
-+ */
-+
-+ v = *(volatile unsigned long *)ramstart;
-+ *(volatile unsigned long *)ramstart = v;
-+
-+ __asm__ __volatile__(" \n\
-+ ldr r4, [%1] @load MDREFR \n\
-+ mcr p14, 0, %2, c6, c0, 0 @ set CCLKCFG[FCS] \n\
-+ ldr r5, [%3] \n\
-+ and r4, r4, r5 \n\
-+ str r4, [%1] @restore \n\
-+ ":"=&r"(unused)
-+ :"r"(&MDREFR), "r"(CLKCFGValue), "r"(&fcsbits)
-+ :"r4", "r5");
-+
-+ local_irq_restore(flags);
-+}
-+
-+static int get_freq(void)
-+{
-+ unsigned int freq, n, l, ccsr;
-+
-+ ccsr = CCSR;
-+
-+ l = ccsr & CCCR_L_MASK; /* Get L */
-+ n = (ccsr & CCCR_N_MASK) >> 7; /* Get 2N */
-+
-+ if (n < 2)
-+ n = 2;
-+
-+ /* Shift to divide by 2 because N is really 2N */
-+ freq = (13000 * l * n) >> 1; /* in kHz */
-+
-+ return freq;
-+}
-+
-+static unsigned int read_clkcfg(void)
-+{
-+ unsigned int value = 0;
-+ unsigned int un_used;
-+
-+ __asm__ __volatile__("mrc p14, 0, %1, c6, c0, 0": "=&r"(un_used):"r"(value));
-+
-+ return value;
-+}
-+
-+static int init_freqs(void)
-+{
-+ int cpu_ver;
-+
-+ asm volatile ("mrc%? p15, 0, %0, c0, c0":"=r" (cpu_ver));
-+
-+ /*
-+ Bulverde A0: 0x69054110,
-+ A1: 0x69054111
-+ */
-+ if ((cpu_ver & 0x0000f000) >> 12 == 4 &&
-+ (cpu_ver & 0xffff0000) >> 16 == 0x6905) {
-+ /* It is a PXA27x chip. */
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
-+static int freq_init(void)
-+{
-+ unsigned int freq;
-+
-+ /*
-+ * In order to turn the sdram back on (see below) we need to
-+ * r/w the sdram. We need to do this without the cache and
-+ * write buffer in the way. So, we temporarily ioremap the
-+ * first page of sdram as uncached i/o memory and use the
-+ * aliased address
-+ */
-+
-+ /* map the first page of sdram to an uncached virtual page */
-+ ramstart = (int *)ioremap(PHYS_OFFSET, 4096);
-+
-+ if (! ramstart) {
-+ printk(KERN_ERR "PXA27x DPM: ioremap of first page failed.");
-+ return -1;
-+ }
-+
-+ initialize_freq_matrix();
-+
-+ if (init_freqs()) {
-+ freq = get_freq(); /* in kHz */
-+ printk(KERN_INFO "PXA27x DPM: Initial frequency is %dkHz.\n", freq);
-+ return 0;
-+ }
-+
-+ return -1;
-+}
-+
-+void freq_cleanup(void)
-+{
-+ /* unmap the page we used*/
-+ iounmap((void *)ramstart);
-+}
-+
-+static unsigned long
-+calculate_memclk(unsigned long cccr, unsigned long clkcfg)
-+{
-+ unsigned long M, memclk;
-+ u32 L;
-+
-+ L = cccr & 0x1f;
-+ if (cccr & (1 << 25)) {
-+ if (clkcfg & CLKCFG_B_BIT)
-+ memclk = (L*13);
-+ else
-+ memclk = (L*13)/2;
-+ }
-+ else {
-+ if (L <= 10) M = 1;
-+ else if (L <= 20) M = 2;
-+ else M = 4;
-+
-+ memclk = (L*13)/M;
-+ }
-+
-+ return memclk;
-+}
-+
-+static unsigned long
-+calculate_new_memclk(struct dpm_regs *regs)
-+{
-+ return calculate_memclk(regs->cccr, regs->clkcfg);
-+}
-+
-+static unsigned long
-+calculate_cur_memclk(void)
-+{
-+ unsigned long cccr = CCCR;
-+ return calculate_memclk(cccr, read_clkcfg());
-+}
-+
-+/* Returns optimal timings for memory controller
-+ * a - [A]
-+ * b - [B]
-+ * l - value of L
-+ */
-+static struct mem_timings get_optimal_mem_timings(int a, int b, int l){
-+ struct mem_timings ret = {
-+ .msc0 = 0,
-+ .dtc = 0,
-+ .dri = 0,
-+ };
-+
-+ if(a!=0 && b==0){
-+ switch(l){
-+ case 2:
-+ ret.msc0 = XLLI_MSC0_13;
-+ ret.dtc = XLLI_DTC_13;
-+ ret.dri = XLLI_DRI_13;
-+ break;
-+ case 3:
-+ ret.msc0 = XLLI_MSC0_19;
-+ ret.dtc = XLLI_DTC_19;
-+ ret.dri = XLLI_DRI_19;
-+ break;
-+ case 4:
-+ ret.msc0 = XLLI_MSC0_26;
-+ ret.dtc = XLLI_DTC_26;
-+ ret.dri = XLLI_DRI_26;
-+ break;
-+ case 5:
-+ ret.msc0 = XLLI_MSC0_32;
-+ ret.dtc = XLLI_DTC_32;
-+ ret.dri = XLLI_DRI_32;
-+ break;
-+ case 6:
-+ ret.msc0 = XLLI_MSC0_39;
-+ ret.dtc = XLLI_DTC_39;
-+ ret.dri = XLLI_DRI_39;
-+ break;
-+ case 7:
-+ ret.msc0 = XLLI_MSC0_45;
-+ ret.dtc = XLLI_DTC_45;
-+ ret.dri = XLLI_DRI_45;
-+ break;
-+ case 8:
-+ ret.msc0 = XLLI_MSC0_52;
-+ ret.dtc = XLLI_DTC_52;
-+ ret.dri = XLLI_DRI_52;
-+ break;
-+ case 9:
-+ ret.msc0 = XLLI_MSC0_58;
-+ ret.dtc = XLLI_DTC_58;
-+ ret.dri = XLLI_DRI_58;
-+ break;
-+ case 10:
-+ ret.msc0 = XLLI_MSC0_65;
-+ ret.dtc = XLLI_DTC_65;
-+ ret.dri = XLLI_DRI_65;
-+ break;
-+ /*
-+ * L11 - L20 ARE THE SAME for A0Bx
-+ */
-+ case 11:
-+ ret.msc0 = XLLI_MSC0_71;
-+ ret.dtc = XLLI_DTC_71;
-+ ret.dri = XLLI_DRI_71;
-+ break;
-+ case 12:
-+ ret.msc0 = XLLI_MSC0_78;
-+ ret.dtc = XLLI_DTC_78;
-+ ret.dri = XLLI_DRI_78;
-+ break;
-+ case 13:
-+ ret.msc0 = XLLI_MSC0_84;
-+ ret.dtc = XLLI_DTC_84;
-+ ret.dri = XLLI_DRI_84;
-+ break;
-+ case 14:
-+ ret.msc0 = XLLI_MSC0_91;
-+ ret.dtc = XLLI_DTC_91;
-+ ret.dri = XLLI_DRI_91;
-+ break;
-+ case 15:
-+ ret.msc0 = XLLI_MSC0_97;
-+ ret.dtc = XLLI_DTC_97;
-+ ret.dri = XLLI_DRI_97;
-+ break;
-+ case 16:
-+ ret.msc0 = XLLI_MSC0_104;
-+ ret.dtc = XLLI_DTC_104;
-+ ret.dri = XLLI_DRI_104;
-+ break;
-+ case 17:
-+ ret.msc0 = XLLI_MSC0_110;
-+ ret.dtc = XLLI_DTC_110;
-+ ret.dri = XLLI_DRI_110;
-+ break;
-+ case 18:
-+ ret.msc0 = XLLI_MSC0_117;
-+ ret.dtc = XLLI_DTC_117;
-+ ret.dri = XLLI_DRI_117;
-+ break;
-+ case 19:
-+ ret.msc0 = XLLI_MSC0_124;
-+ ret.dtc = XLLI_DTC_124;
-+ ret.dri = XLLI_DRI_124;
-+ break;
-+ case 20:
-+ ret.msc0 = XLLI_MSC0_130;
-+ ret.dtc = XLLI_DTC_130;
-+ ret.dri = XLLI_DRI_130;
-+ break;
-+ case 21:
-+ ret.msc0 = XLLI_MSC0_136;
-+ ret.dtc = XLLI_DTC_136;
-+ ret.dri = XLLI_DRI_136;
-+ break;
-+ case 22:
-+ ret.msc0 = XLLI_MSC0_143;
-+ ret.dtc = XLLI_DTC_143;
-+ ret.dri = XLLI_DRI_143;
-+ break;
-+ case 23:
-+ ret.msc0 = XLLI_MSC0_149;
-+ ret.dtc = XLLI_DTC_149;
-+ ret.dri = XLLI_DRI_149;
-+ break;
-+ case 24:
-+ ret.msc0 = XLLI_MSC0_156;
-+ ret.dtc = XLLI_DTC_156;
-+ ret.dri = XLLI_DRI_156;
-+ break;
-+ case 25:
-+ ret.msc0 = XLLI_MSC0_162;
-+ ret.dtc = XLLI_DTC_162;
-+ ret.dri = XLLI_DRI_162;
-+ break;
-+ case 26:
-+ ret.msc0 = XLLI_MSC0_169;
-+ ret.dtc = XLLI_DTC_169;
-+ ret.dri = XLLI_DRI_169;
-+ break;
-+ case 27:
-+ ret.msc0 = XLLI_MSC0_175;
-+ ret.dtc = XLLI_DTC_175;
-+ ret.dri = XLLI_DRI_175;
-+ break;
-+ case 28:
-+ ret.msc0 = XLLI_MSC0_182;
-+ ret.dtc = XLLI_DTC_182;
-+ ret.dri = XLLI_DRI_182;
-+ break;
-+ case 29:
-+ ret.msc0 = XLLI_MSC0_188;
-+ ret.dtc = XLLI_DTC_188;
-+ ret.dri = XLLI_DRI_188;
-+ break;
-+ case 30:
-+ ret.msc0 = XLLI_MSC0_195;
-+ ret.dtc = XLLI_DTC_195;
-+ ret.dri = XLLI_DRI_195;
-+ break;
-+ case 31:
-+ ret.msc0 = XLLI_MSC0_201;
-+ ret.dtc = XLLI_DTC_201;
-+ ret.dri = XLLI_DRI_201;
-+ }
-+
-+ }else if(a!=0 && b!=0){
-+ switch(l){
-+ case 2:
-+ ret.msc0 = XLLI_MSC0_26;
-+ ret.dtc = XLLI_DTC_26;
-+ ret.dri = XLLI_DRI_26;
-+ break;
-+ case 3:
-+ ret.msc0 = XLLI_MSC0_39;
-+ ret.dtc = XLLI_DTC_39;
-+ ret.dri = XLLI_DRI_39;
-+ break;
-+ case 4:
-+ ret.msc0 = XLLI_MSC0_52;
-+ ret.dtc = XLLI_DTC_52;
-+ ret.dri = XLLI_DRI_52;
-+ break;
-+ case 5:
-+ ret.msc0 = XLLI_MSC0_65;
-+ ret.dtc = XLLI_DTC_65;
-+ ret.dri = XLLI_DRI_65;
-+ break;
-+ case 6:
-+ ret.msc0 = XLLI_MSC0_78;
-+ ret.dtc = XLLI_DTC_78;
-+ ret.dri = XLLI_DRI_78;
-+ break;
-+ case 7:
-+ ret.msc0 = XLLI_MSC0_91;
-+ ret.dtc = XLLI_DTC_91;
-+ ret.dri = XLLI_DRI_91;
-+ break;
-+ case 8:
-+ ret.msc0 = XLLI_MSC0_104;
-+ ret.dtc = XLLI_DTC_104;
-+ ret.dri = XLLI_DRI_104;
-+ break;
-+ case 9:
-+ ret.msc0 = XLLI_MSC0_117;
-+ ret.dtc = XLLI_DTC_117;
-+ ret.dri = XLLI_DRI_117;
-+ break;
-+ case 10:
-+ ret.msc0 = XLLI_MSC0_130;
-+ ret.dtc = XLLI_DTC_130;
-+ ret.dri = XLLI_DRI_130;
-+ break;
-+ case 11:
-+ ret.msc0 = XLLI_MSC0_143;
-+ ret.dtc = XLLI_DTC_143;
-+ ret.dri = XLLI_DRI_143;
-+ break;
-+ case 12:
-+ ret.msc0 = XLLI_MSC0_156;
-+ ret.dtc = XLLI_DTC_156;
-+ ret.dri = XLLI_DRI_156;
-+ break;
-+ case 13:
-+ ret.msc0 = XLLI_MSC0_169;
-+ ret.dtc = XLLI_DTC_169;
-+ ret.dri = XLLI_DRI_169;
-+ break;
-+ case 14:
-+ ret.msc0 = XLLI_MSC0_182;
-+ ret.dtc = XLLI_DTC_182;
-+ ret.dri = XLLI_DRI_182;
-+ break;
-+ case 15:
-+ ret.msc0 = XLLI_MSC0_195;
-+ ret.dtc = XLLI_DTC_195;
-+ ret.dri = XLLI_DRI_195;
-+ break;
-+ case 16:
-+ ret.msc0 = XLLI_MSC0_208;
-+ ret.dtc = XLLI_DTC_208;
-+ ret.dri = XLLI_DRI_208;
-+ }
-+ }else{
-+ /* A0Bx */
-+ switch(l){
-+ case 2:
-+ ret.msc0 = XLLI_MSC0_26;
-+ ret.dtc = XLLI_DTC_26;
-+ ret.dri = XLLI_DRI_26;
-+ break;
-+ case 3:
-+ ret.msc0 = XLLI_MSC0_39;
-+ ret.dtc = XLLI_DTC_39;
-+ ret.dri = XLLI_DRI_39;
-+ break;
-+ case 4:
-+ ret.msc0 = XLLI_MSC0_52;
-+ ret.dtc = XLLI_DTC_52;
-+ ret.dri = XLLI_DRI_52;
-+ break;
-+ case 5:
-+ ret.msc0 = XLLI_MSC0_65;
-+ ret.dtc = XLLI_DTC_65;
-+ ret.dri = XLLI_DRI_65;
-+ break;
-+ case 6:
-+ ret.msc0 = XLLI_MSC0_78;
-+ ret.dtc = XLLI_DTC_78;
-+ ret.dri = XLLI_DRI_78;
-+ break;
-+ case 7:
-+ ret.msc0 = XLLI_MSC0_91;
-+ ret.dtc = XLLI_DTC_91;
-+ ret.dri = XLLI_DRI_91;
-+ break;
-+ case 8:
-+ ret.msc0 = XLLI_MSC0_104;
-+ ret.dtc = XLLI_DTC_104;
-+ ret.dri = XLLI_DRI_104;
-+ break;
-+ case 9:
-+ ret.msc0 = XLLI_MSC0_117;
-+ ret.dtc = XLLI_DTC_117;
-+ ret.dri = XLLI_DRI_117;
-+ break;
-+ case 10:
-+ ret.msc0 = XLLI_MSC0_130;
-+ ret.dtc = XLLI_DTC_130;
-+ ret.dri = XLLI_DRI_130;
-+ break;
-+ case 11:
-+ ret.msc0 = XLLI_MSC0_71;
-+ ret.dtc = XLLI_DTC_71;
-+ ret.dri = XLLI_DRI_71;
-+ break;
-+ case 12:
-+ ret.msc0 = XLLI_MSC0_78;
-+ ret.dtc = XLLI_DTC_78;
-+ ret.dri = XLLI_DRI_78;
-+ break;
-+ case 13:
-+ ret.msc0 = XLLI_MSC0_84;
-+ ret.dtc = XLLI_DTC_84;
-+ ret.dri = XLLI_DRI_84;
-+ break;
-+ case 14:
-+ ret.msc0 = XLLI_MSC0_91;
-+ ret.dtc = XLLI_DTC_91;
-+ ret.dri = XLLI_DRI_91;
-+ break;
-+ case 15:
-+ ret.msc0 = XLLI_MSC0_97;
-+ ret.dtc = XLLI_DTC_97;
-+ ret.dri = XLLI_DRI_97;
-+ break;
-+ case 16:
-+ ret.msc0 = XLLI_MSC0_104;
-+ ret.dtc = XLLI_DTC_104;
-+ ret.dri = XLLI_DRI_104;
-+ break;
-+ case 17:
-+ ret.msc0 = XLLI_MSC0_110;
-+ ret.dtc = XLLI_DTC_110;
-+ ret.dri = XLLI_DRI_110;
-+ break;
-+ case 18:
-+ ret.msc0 = XLLI_MSC0_117;
-+ ret.dtc = XLLI_DTC_117;
-+ ret.dri = XLLI_DRI_117;
-+ break;
-+ case 19:
-+ ret.msc0 = XLLI_MSC0_124;
-+ ret.dtc = XLLI_DTC_124;
-+ ret.dri = XLLI_DRI_124;
-+ break;
-+ case 20:
-+ ret.msc0 = XLLI_MSC0_130;
-+ ret.dtc = XLLI_DTC_130;
-+ ret.dri = XLLI_DRI_130;
-+ break;
-+ case 21:
-+ ret.msc0 = XLLI_MSC0_68;
-+ ret.dtc = XLLI_DTC_68;
-+ ret.dri = XLLI_DRI_68;
-+ break;
-+ case 22:
-+ ret.msc0 = XLLI_MSC0_71;
-+ ret.dtc = XLLI_DTC_71;
-+ ret.dri = XLLI_DRI_71;
-+ break;
-+ case 23:
-+ ret.msc0 = XLLI_MSC0_74;
-+ ret.dtc = XLLI_DTC_74;
-+ ret.dri = XLLI_DRI_74;
-+ break;
-+ case 24:
-+ ret.msc0 = XLLI_MSC0_78;
-+ ret.dtc = XLLI_DTC_78;
-+ ret.dri = XLLI_DRI_78;
-+ break;
-+ case 25:
-+ ret.msc0 = XLLI_MSC0_81;
-+ ret.dtc = XLLI_DTC_81;
-+ ret.dri = XLLI_DRI_81;
-+ break;
-+ case 26:
-+ ret.msc0 = XLLI_MSC0_84;
-+ ret.dtc = XLLI_DTC_84;
-+ ret.dri = XLLI_DRI_84;
-+ break;
-+ case 27:
-+ ret.msc0 = XLLI_MSC0_87;
-+ ret.dtc = XLLI_DTC_87;
-+ ret.dri = XLLI_DRI_87;
-+ break;
-+ case 28:
-+ ret.msc0 = XLLI_MSC0_91;
-+ ret.dtc = XLLI_DTC_91;
-+ ret.dri = XLLI_DRI_91;
-+ break;
-+ case 29:
-+ ret.msc0 = XLLI_MSC0_94;
-+ ret.dtc = XLLI_DTC_94;
-+ ret.dri = XLLI_DRI_94;
-+ break;
-+ case 30:
-+ ret.msc0 = XLLI_MSC0_97;
-+ ret.dtc = XLLI_DTC_97;
-+ ret.dri = XLLI_DRI_97;
-+ break;
-+ case 31:
-+ ret.msc0 = XLLI_MSC0_100;
-+ ret.dtc = XLLI_DTC_100;
-+ ret.dri = XLLI_DRI_100;
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+static void assign_optimal_mem_timings(
-+ unsigned int* msc0_reg,
-+ unsigned int* mdrefr_reg,
-+ unsigned int* mdcnfg_reg,
-+ int a, int b, int l
-+ )
-+{
-+ unsigned int msc0_reg_tmp = (*msc0_reg);
-+ unsigned int mdrefr_reg_tmp = (*mdrefr_reg);
-+ unsigned int mdcnfg_reg_tmp = (*mdcnfg_reg);
-+ struct mem_timings timings = get_optimal_mem_timings(a,b,l);
-+
-+ /* clear bits which are set by get_optimal_mem_timings*/
-+ msc0_reg_tmp &= ~(MSC0_RDF & MSC0_RDN & MSC0_RRR);
-+ mdrefr_reg_tmp &= ~(MDREFR_RFU & MDREFR_DRI);
-+ mdcnfg_reg_tmp &= ~(MDCNFG_DTC0 & MDCNFG_DTC2);
-+
-+ /* prepare appropriate timings */
-+ msc0_reg_tmp |= timings.msc0;
-+ mdrefr_reg_tmp |= timings.dri;
-+ mdcnfg_reg_tmp |= timings.dtc;
-+
-+ /* set timings (all bits one time) */
-+ (*msc0_reg) = msc0_reg_tmp;
-+ (*mdrefr_reg) = mdrefr_reg_tmp;
-+ (*mdcnfg_reg) = mdcnfg_reg_tmp;
-+}
-+
-+static void set_mdrefr_value(u32 new_mdrefr){
-+ unsigned long s, old_mdrefr, errata62;
-+ old_mdrefr = MDREFR;
-+ /* E62 (28007106.pdf): Memory controller may hang while clearing
-+ * MDREFR[K1DB2] or MDREFR[K2DB2]
-+ */
-+ errata62 =
-+ (((old_mdrefr & MDREFR_K1DB2) != 0) && ((new_mdrefr & MDREFR_K1DB2) == 0)) ||
-+ (((old_mdrefr & MDREFR_K2DB2) != 0) && ((new_mdrefr & MDREFR_K2DB2) == 0));
-+
-+ if(errata62){
-+ unsigned long oscr_0 = OSCR;
-+ unsigned long oscr_1 = oscr_0;
-+ /* Step 1 - disable interrupts */
-+ local_irq_save(s);
-+ /* Step 2 - leave KxDB2, but set MDREFR[DRI] (bits 0-11) to
-+ * 0xFFF
-+ */
-+ MDREFR = MDREFR | MDREFR_DRI;
-+ /* Step 3 - read MDREFR one time */
-+ MDREFR;
-+ /* Step 4 - wait 1.6167us
-+ * (3.25MHz clock increments OSCR0 7 times)
-+ */
-+ while(oscr_1-oscr_0 < 7){
-+ cpu_relax();
-+ oscr_1 = OSCR;
-+ }
-+
-+ }
-+
-+ /* Step 5 - clear K1DB1 and/or K2DB2, and set MDREFR[DRI] to
-+ * proper value at the same time
-+ */
-+
-+ /*Set MDREFR as if no errata workaround is needed*/
-+ MDREFR = new_mdrefr;
-+
-+ if(errata62){
-+ /* Step 6 - read MDREFR one time*/
-+ MDREFR;
-+ /* Step 7 - enable interrupts*/
-+ local_irq_restore(s);
-+ }
-+}
-+
-+static void scale_cpufreq(struct dpm_regs *regs)
-+{
-+ unsigned long new_memclk, cur_memclk;
-+ u32 new_mdrefr, cur_mdrefr, read_mdrefr;
-+ u32 new_msc0, new_mdcnfg;
-+ int set_mdrefr = 0, scaling_up = 0;
-+ int l, a, b;
-+
-+ l = regs->cccr & CCCR_L_MASK; /* Get L */
-+ b = (regs->clkcfg >> 3) & 0x1;
-+ a = (regs->cccr >> 25) & 0x1; /* cccr[A]: bit 25 */
-+ cur_memclk = calculate_cur_memclk();
-+ new_memclk = calculate_new_memclk(regs);
-+
-+ new_mdrefr = cur_mdrefr = MDREFR;
-+ new_msc0 = MSC0;
-+ new_mdcnfg = MDCNFG;
-+
-+ if (new_memclk != cur_memclk) {
-+ new_mdrefr &= ~( MDREFR_K0DB2 | MDREFR_K0DB4 |
-+ MDREFR_K1DB2 | MDREFR_K2DB2 );
-+
-+ if ((new_memclk > 52) && (new_memclk <= 104)) {
-+ /* SDCLK0 = MEMCLK/2, SDCLK1,SDCLK2 = MEMCLK */
-+ new_mdrefr |= MDREFR_K0DB2;
-+ }
-+ else if (new_memclk > 104){
-+ /* SDCLK0 = MEMCLK/4, SDCLK1 and SDCLK2 = MEMCLK/2 */
-+ new_mdrefr |= (MDREFR_K0DB4 | MDREFR_K1DB2 | MDREFR_K2DB2);
-+ }
-+
-+ /* clock increasing or decreasing? */
-+ if (new_memclk > cur_memclk) scaling_up = 1;
-+ }
-+
-+ /* set MDREFR if necessary */
-+ if (new_mdrefr != cur_mdrefr){
-+ set_mdrefr = 1;
-+ /* also adjust timings as long as we change MDREFR value */
-+ assign_optimal_mem_timings(
-+ &new_msc0,
-+ &new_mdrefr,
-+ &new_mdcnfg,
-+ a,b,l
-+ );
-+ }
-+
-+ /* if memclk is scaling up, set MDREFR before freq change
-+ * (2800002.pdf:6.5.1.4)
-+ */
-+ if (set_mdrefr && scaling_up) {
-+ MSC0 = new_msc0;
-+ set_mdrefr_value(new_mdrefr);
-+ MDCNFG = new_mdcnfg;
-+ read_mdrefr = MDREFR;
-+ }
-+
-+ CCCR = regs->cccr;
-+ set_freq(regs->clkcfg);
-+
-+ /* if memclk is scaling down, set MDREFR after freq change
-+ * (2800002.pdf:6.5.1.4)
-+ */
-+ if (set_mdrefr && !scaling_up) {
-+ MSC0 = new_msc0;
-+ set_mdrefr_value(new_mdrefr);
-+ MDCNFG = new_mdcnfg;
-+ read_mdrefr = MDREFR;
-+ }
-+}
-+
-+static void scale_voltage(struct dpm_regs *regs)
-+{
-+ set_voltage(regs->voltage);
-+}
-+
-+static void scale_voltage_coupled(struct dpm_regs *regs)
-+{
-+ power_change_cmd(mv2DAC(regs->voltage), 1 /* coupled */ );
-+}
-+
-+static void calculate_lcd_freq(struct dpm_md_opt *opt)
-+{
-+ int k = 1; /* lcd divisor */
-+
-+ /* L is verified to be between PLL_L_MAX and PLL_L_MIN in
-+ dpm_bulverde_init_opt().
-+ */
-+ if (opt->l == -1) {
-+ opt->lcd = -1;
-+ return;
-+ }
-+
-+ if (opt->l > 16) {
-+ /* When L=17-31, K=4 */
-+ k = 4;
-+ } else if (opt->l > 7) {
-+ /* When L=8-16, K=2 */
-+ k = 2;
-+ }
-+
-+ /* Else, when L=2-7, K=1 */
-+
-+ opt->lcd = 13000 * opt->l / k;
-+}
-+
-+static void calculate_reg_values(struct dpm_md_opt *opt)
-+{
-+ int f = 0; /* frequency change bit */
-+ int turbo = 0; /* turbo mode bit; depends on N value */
-+
-+ opt->regs.voltage = opt->v;
-+
-+/*
-+ CCCR:
-+
-+ A: Alternate setting for MEMC clock
-+ 0 = MEM clock frequency as specified in user guide table
-+ 1 = MEM clock frq = System Bus Frequency
-+
-+ CLKCFG:
-+
-+ B = Fast-Bus Mode 0: System Bus is half of run-mode
-+ 1: System Bus is equal to run-mode
-+ NOTE: only allowed when L <= 16
-+
-+ HT = Half-Turbo 0: core frequency = run or turbo, depending on T bit
-+ 1: core frequency = turbo frequency / 2
-+ NOTE: only allowed when 2N = 6 or 2N = 8
-+
-+ F = Frequency change
-+ 0: No frequency change is performed
-+ 1: Do frequency-change
-+
-+ T = Turbo Mode 0: CPU operates at run Frequency
-+ 1: CPU operates at Turbo Frequency (when n2 > 2)
-+*/
-+ /* Set the CLKCFG with B, T, and HT */
-+ if (opt->b != -1 && opt->n != -1) {
-+ f = 1;
-+
-+ /*When 2N=2, Turbo Mode equals Run Mode, so it
-+ does not really matter if this is >2 or >=2
-+ */
-+ if (opt->n > 2) {
-+ turbo = 0x1;
-+ }
-+ opt->regs.clkcfg = (opt->b << 3) + (f << 1) + turbo;
-+ } else {
-+ f = 0x1;
-+ opt->regs.clkcfg = (f << 1);
-+ }
-+
-+ /*
-+ What about when 2N=0 ... it is not defined by the yellow
-+ book
-+ */
-+ if (opt->n != -1) {
-+ /* 2N is 4 bits, L is 5 bits */
-+ opt->regs.cccr = ((opt->n & 0xF) << 7) + (opt->l & 0x1F);
-+ }
-+
-+ if (opt->cccra > 0) {
-+ /* Turn on the CCCR[A] bit */
-+ opt->regs.cccr |= (1 << 25);
-+ }
-+
-+ if(opt->cpll_enabled == 0) {
-+ opt->regs.cccr |= (CCCR_CPDIS_BIT_ON);
-+ }
-+ if(opt->ppll_enabled == 0) {
-+ opt->regs.cccr |= (CCCR_PPDIS_BIT_ON);
-+ }
-+
-+}
-+
-+static int init_opt(struct dpm_opt *opt)
-+{
-+ int v = -1;
-+ int l = -1;
-+ int n2 = -1;
-+ int b = -1;
-+ int half_turbo = -1;
-+ int cccra = -1;
-+ int cpll_enabled = -1;
-+ int ppll_enabled = -1;
-+ int sleep_mode = -1;
-+ struct dpm_md_opt *md_opt = NULL;
-+
-+ v = opt->pp[DPM_MD_V];
-+ l = opt->pp[DPM_MD_PLL_L];
-+ n2 = opt->pp[DPM_MD_PLL_N]; /* 2*N */
-+ b = opt->pp[DPM_MD_PLL_B]; /* Fast bus mode bit. */
-+ half_turbo = opt->pp[DPM_MD_HALF_TURBO];
-+ cccra = opt->pp[DPM_MD_CCCRA]; /* Alternate setting
-+ for the MEM clock */
-+ cpll_enabled = opt->pp[DPM_MD_CPLL_ON];
-+ ppll_enabled = opt->pp[DPM_MD_PPLL_ON];
-+ sleep_mode = opt->pp[DPM_MD_SLEEP_MODE];
-+
-+ md_opt = &opt->md_opt;
-+
-+ /* Up-front error checking. If we fail any of these, then the
-+ whole operating point is suspect and therefore invalid.
-+ */
-+
-+ /*PXA27x manual ("Yellow book") 3.5.5 (Table 3-7) states that CPLL-"On" and
-+ *PPLL-"Off"
-+ *configuration is forbidden (all others seam to be OK for "B0")
-+ *for "C0" boards we suppose that this configuration is also enabled.
-+ *PXA27x manual ("Yellow book") also states at 3.5.7.1 (page 3-25)
-+ *that "CCCR[PPDIS] and CCCR[CPDIS] must always be identical and
-+ *changed together". "If PLLs are to be turned off using xPDIS then
-+ *set xPDIS before frequency change and clear xPDIS after frequency
-+ *change"
-+ */
-+
-+ if( (l > PLL_L_MIN) && ( cpll_enabled == 0 ) ){
-+ printk(KERN_WARNING
-+ "DPM: when l>0 (NOT 13M mode) CPLL must be On \n");
-+ return -EINVAL;
-+ }
-+ if( (cpll_enabled>0) && (ppll_enabled==0) ){
-+ printk(KERN_WARNING
-+ "DPM: illegal combination CPLL=On PPLL=Off\n");
-+ return -EINVAL;
-+ }
-+
-+ /* Check if voltage is correct */
-+ if(v < -1){
-+ printk(KERN_WARNING
-+ "DPM: incorrect voltage %d\n",
-+ v);
-+ return -EINVAL;
-+ }
-+
-+ if ((l != -1) && (n2 != -1)) {
-+ if (((l && n2) == 0) && (l || n2) != 0) {
-+ /* If one of L or N2 is 0, but they are not both 0 */
-+ printk(KERN_WARNING
-+ "DPM: L/N (%d/%d) must both be 0 or both be non-zero\n",
-+ l, n2);
-+ return -EINVAL;
-+ }
-+
-+ /* Standard range checking */
-+ if (((l > 0) && (n2 > 0)) && /* Don't complain about 0, it means sleep */
-+ ((l > PLL_L_MAX) ||
-+ (n2 > PLL_N_MAX) || (l < PLL_L_MIN) || (n2 < PLL_N_MIN))) {
-+ /* Range checking */
-+ printk(KERN_WARNING
-+ "DPM: L/N (%d/%d) out of range, L=1-31, N=2-8 \n",
-+ l, n2);
-+ return -EINVAL;
-+ }
-+
-+ /* If this is for 13M mode, do some more checking */
-+ if (l == PLL_L_MIN) {
-+ /*
-+ NOTE: the Yellow Book does not require any
-+ particular setting for N, but we think it really
-+ should be 2
-+ */
-+ if (n2 != 2) {
-+ printk(KERN_WARNING
-+ "DPM: When L=1 (13M Mode), N must be 2 (%d)\n",
-+ n2);
-+ return -EINVAL;
-+ }
-+
-+ if ((cpll_enabled != 0) && (cpll_enabled != -1)) {
-+ printk(KERN_WARNING
-+ "DPM: When L=1 (13M Mode), CPLL must be OFF (%d)\n",
-+ cpll_enabled);
-+ return -EINVAL;
-+ }
-+
-+ /* Page 3-32, section 3.5.7.5.2 of the Yellow Book
-+ says, "Notes: Other bits in the CLKCFG can not be
-+ changed while entering or exiting the 13M
-+ mode. While in 13M mode, it is illegal to write to
-+ CLKCFG's B, HT, or T bits"
-+ */
-+ if ((b > 0) || (half_turbo > 0)) {
-+ printk(KERN_WARNING
-+ "DPM: When L=1 (13M Mode), B (%d) and "
-+ "Half-Turbo (%d) must be off\n", b, half_turbo);
-+ return -EINVAL;
-+ }
-+ }
-+ }
-+
-+ if (half_turbo > 1) {
-+ printk(KERN_WARNING "DPM: Half-Turbo must be 0 or 1 (%d)\n",
-+ half_turbo);
-+ return -EINVAL;
-+ }
-+
-+ if (b > 1) {
-+ printk(KERN_WARNING
-+ "DPM: Fast-Bus Mode (B) must be 0 or 1 (%d)\n", b);
-+ return -EINVAL;
-+ }
-+
-+ /* 2800002.pdf 3.5.7.1 It is illegal to set B if CCCR[CPDIS] is set. */
-+ if( cpll_enabled==0 && b == 1){
-+ printk(KERN_WARNING
-+ "DPM: fast bus (b=%d) must both be 0 if CPLL is Off\n",
-+ b);
-+ return -EINVAL;
-+ }
-+
-+ if (cccra > 1) {
-+ printk(KERN_WARNING
-+ "DPM: CCCR[A] (alternate MEMC clock) must be 0 or 1 (%d)\n",
-+ cccra);
-+ return -EINVAL;
-+ }
-+
-+ /* This (when CCCR[A] is on and FastBus is on, L must be <=16)
-+ is explicitly stated in text at the bottom of one of the
-+ CPU frequency tables--the one where CCCR[A] is on */
-+ if ((b == 1) && (cccra == 1) && (l > 16)) {
-+ printk(KERN_WARNING
-+ "DPM: when B=1 and CCCR[A]=1, L must be <= 16 (L is %d)\n",
-+ l);
-+ return -EINVAL;
-+ }
-+
-+ /* This one is not explicitly stated the Yellow Book as a bad
-+ thing (as the previous restriction is), but according to
-+ the CPU frequency tables, fast bus mode *cannot* be
-+ supported, even when CCCR[A] is not 1.
-+ */
-+ if ((b == 1) && (l > 16)) {
-+ printk(KERN_WARNING
-+ "DPM: when B=1, L must be <= 16 (L is %d)\n", l);
-+ return -EINVAL;
-+ }
-+
-+ if (n2 != -1) {
-+ if ((half_turbo == 1) && (n2 != 6) && (n2 != 8)) {
-+ printk(KERN_WARNING
-+ "DPM: Half Turbo only allowed when N2 is 6 or 8\n"
-+ "(N2 is %d)\n", n2);
-+ return -EINVAL;
-+ }
-+ }
-+
-+ /* Check Sleep Mode versus modes from pm.h
-+ NOTE: CPUMODE_SENSE is not implemented.
-+ */
-+ if ((l == 0) && (n2 == 0) && (sleep_mode != -1) &&
-+ (sleep_mode != CPUMODE_STANDBY) &&
-+ (sleep_mode != CPUMODE_SLEEP) &&
-+ (sleep_mode != CPUMODE_DEEPSLEEP)) {
-+ printk(KERN_WARNING
-+ "DPM: Sleep Mode value %d is not allowed"
-+ " (only %d, %d, or %d) l=%d n2=%d\n",
-+ sleep_mode,
-+ CPUMODE_STANDBY, CPUMODE_SLEEP, CPUMODE_DEEPSLEEP,
-+ l, n2);
-+ return -EINVAL;
-+ }
-+
-+ /* save the values for this operating point */
-+ md_opt->v = v;
-+ md_opt->l = l;
-+ md_opt->n = n2;
-+ md_opt->b = b;
-+ md_opt->cccra = cccra;
-+ md_opt->half_turbo = half_turbo;
-+ md_opt->cpll_enabled = cpll_enabled;
-+ md_opt->ppll_enabled = ppll_enabled;
-+ md_opt->sleep_mode = sleep_mode;
-+ calculate_lcd_freq(md_opt);
-+
-+ if ((md_opt->l == -1) || (md_opt->n == -1)) {
-+ md_opt->cpu = -1;
-+ } else {
-+ /* shift 1 to divide by 2 because opt->n is 2*N */
-+ md_opt->cpu = (13000 * md_opt->l * md_opt->n) >> 1;
-+ if (md_opt->half_turbo == 1) {
-+ /* divide by 2 */
-+ md_opt->cpu = md_opt->cpu >> 1;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static void fully_define_opt(struct dpm_md_opt *cur, struct dpm_md_opt *new)
-+{
-+ if (new->v == -1)
-+ new->v = cur->v;
-+ if (new->l == -1)
-+ new->l = cur->l;
-+ if (new->n == -1)
-+ new->n = cur->n;
-+ if (new->b == -1)
-+ new->b = cur->b;
-+ if (new->half_turbo == -1)
-+ new->half_turbo = cur->half_turbo;
-+ if (new->cccra == -1)
-+ new->cccra = cur->cccra;
-+ if (new->cpll_enabled == -1)
-+ new->cpll_enabled = cur->cpll_enabled;
-+ if (new->ppll_enabled == -1)
-+ new->ppll_enabled = cur->ppll_enabled;
-+ if (new->sleep_mode == -1)
-+ new->sleep_mode = cur->sleep_mode;
-+
-+ if (new->n > 2) {
-+ new->turbo = 1;
-+ /* turbo mode: 13K * L * (N/2)
-+ Shift at the end to divide N by 2 for Turbo mode or
-+ by 4 for Half-Turbo mode )
-+ */
-+ new->cpu = (13000 * new->l * new->n) >>
-+ ((new->half_turbo == 1) ? 2 : 1);
-+ } else {
-+ new->turbo = 0;
-+ /* run mode */
-+ new->cpu = 13000 * new->l;
-+ }
-+ /* lcd freq is derived from L */
-+ calculate_lcd_freq(new);
-+ calculate_reg_values(new);
-+ /* We want to keep a baseline loops_per_jiffy/cpu-freq ratio
-+ to work off of for future calculations, especially when
-+ emerging from sleep when there is no current cpu frequency
-+ to calculate from (because cpu-freq of 0 means sleep).
-+ */
-+ if (!saved_loops_per_jiffy) {
-+ saved_loops_per_jiffy = loops_per_jiffy;
-+ saved_cpu_freq = cur->cpu;
-+ }
-+
-+ if (new->cpu) {
-+ /* Normal change (not sleep), just compute. Always use
-+ the "baseline" lpj and freq */
-+ new->lpj =
-+ dpm_compute_lpj(saved_loops_per_jiffy, saved_cpu_freq,
-+ new->cpu);
-+ } else {
-+ /* If sleeping, keep the old LPJ */
-+ new->lpj = loops_per_jiffy;
-+ }
-+}
-+
-+static void xpll_on(struct dpm_regs *regs)
-+{
-+ int tmp_cccr, tmp_ccsr;
-+ int new_cpllon=0, new_ppllon=0, cur_cpllon=0;
-+ int cur_ppllon=0, start_cpll=0, start_ppll=0;
-+
-+ tmp_ccsr = CCSR;
-+
-+ if ((regs->cccr & CCCR_CPDIS_BIT_ON) == 0)
-+ new_cpllon = 1;
-+ if ((regs->cccr & CCCR_PPDIS_BIT_ON) == 0)
-+ new_ppllon = 1;
-+ if (((tmp_ccsr >> 31) & 0x1) == 0)
-+ cur_cpllon = 1;
-+ if (((tmp_ccsr >> 30) & 0x1) == 0)
-+ cur_ppllon = 1;
-+
-+ if ((new_cpllon == 1) && (cur_cpllon == 0))
-+ start_cpll=1;
-+
-+ if ((new_ppllon == 1) && (cur_ppllon == 0))
-+ start_ppll=1;
-+
-+ if ((start_cpll == 0) && (start_ppll == 0))
-+ return;
-+
-+ /* NOTE: the Yellow Book says that exiting 13M mode requires a
-+ PLL relock, which takes at least 120uS, so the book suggests
-+ the OS could use a timer to keep busy until it is time to
-+ check the CCSR bits which must happen before changing the
-+ frequency back.
-+
-+ For now, we'll just loop.
-+ */
-+
-+ /* From Yellow Book, page 3-31, section 3.5.7.5 13M Mode
-+
-+ Exiting 13M Mode:
-+
-+ 1. Remain in 13M mode, but early enable the PLL via
-+ CCCR[CPDIS, PPDIS]=11, and CCCR[PLL_EARLY_EN]=1. Doing
-+ so will allow the PLL to be started early.
-+
-+ 2. Read CCCR and compare to make sure that the data was
-+ correctly written.
-+
-+ 3. Check to see if CCS[CPLOCK] and CCSR[PPLOCK] bits are
-+ both set. Once these bits are both high, the PLLs are
-+ locked and you may move on.
-+
-+ 4. Note that the CPU is still in 13M mode, but the PLLs are
-+ started.
-+
-+ 5. Exit from 13M mode by writing CCCR[CPDIS, PPDIS]=00, but
-+ maintain CCCR[PLL_EARLY_EN]=1. This bit will be cleared
-+ by the imminent frequency change.
-+ */
-+
-+ /* Step 1 */
-+ tmp_cccr = CCCR;
-+
-+ if (start_cpll)
-+ tmp_cccr |= CCCR_CPDIS_BIT_ON;
-+
-+ if(start_ppll)
-+ tmp_cccr |= CCCR_PPDIS_BIT_ON;
-+
-+ tmp_cccr |= CCCR_PLL_EARLY_EN_BIT_ON;
-+ CCCR = tmp_cccr;
-+
-+ /* Step 2 */
-+ tmp_cccr = CCCR;
-+
-+#ifdef DEBUG
-+ if ((tmp_cccr & CCCR_PLL_EARLY_EN_BIT_ON) != CCCR_PLL_EARLY_EN_BIT_ON)
-+ printk(KERN_WARNING
-+ "DPM: Warning: PLL_EARLY_EN is NOT on\n");
-+
-+ if ((start_cpll==1) &&
-+ ((tmp_cccr & CCCR_CPDIS_BIT_ON) != CCCR_CPDIS_BIT_ON))
-+ printk(KERN_WARNING
-+ "DPM: Warning: CPDIS is NOT on\n");
-+
-+ if ((start_ppll==1) &&
-+ (tmp_cccr & CCCR_PPDIS_BIT_ON) != CCCR_PPDIS_BIT_ON)
-+ printk(KERN_WARNING
-+ "DPM: Warning: PPDIS is NOT on\n");
-+#endif
-+
-+ /* Step 3 */
-+ {
-+ /* Note: the point of this is to "wait" for the lock
-+ bits to be set; the Yellow Book says this may take
-+ a while, but observation indicates that it is
-+ instantaneous.
-+ */
-+
-+ long volatile int i = 0;
-+
-+ int cpll_complete=1;
-+ int ppll_complete=1;
-+
-+ if (start_cpll == 1)
-+ cpll_complete=0;
-+
-+ if (start_ppll == 1)
-+ ppll_complete=0;
-+
-+ /*loop arbitrary big value to prevent looping forever */
-+ for (i = 0; i < 999999; i++) {
-+ tmp_ccsr = CCSR;
-+
-+ if (tmp_ccsr & CCSR_CPLL_LOCKED)
-+ cpll_complete=1;
-+
-+ if (tmp_ccsr & CCSR_PPLL_LOCKED)
-+ ppll_complete=1;
-+
-+ if ((cpll_complete == 1) && (ppll_complete == 1))
-+ break;
-+ }
-+ }
-+
-+ /* Step 4: NOP */
-+
-+ /* Step 5
-+ Clear the PLL disable bits - do NOT do it here.
-+ */
-+
-+ /* But leave EARLY_EN on; it will be cleared by the frequency change */
-+ regs->cccr |= CCCR_PLL_EARLY_EN_BIT_ON;
-+
-+ /*
-+ Step 6: Now go continue on with frequency change
-+ We do this step later as if voltage is too low,
-+ we must ensure that it rised up before entereng to higher
-+ freq mode or simultaniously.
-+ */
-+}
-+
-+static int set_opt(struct dpm_opt *curop, struct dpm_opt *newop)
-+{
-+ struct dpm_md_opt *cur, *new;
-+ int current_n = (CCSR & CCCR_N_MASK) >> 7;
-+ int set_opt_flags = 0;
-+ unsigned int cccr, clkcfg = 0;
-+ unsigned long s;
-+
-+#define SET_OPT_CPUFREQ (1 << 0)
-+#define SET_OPT_VOLTAGE (1 << 1)
-+#define SET_OPT_TURBO_ON (1 << 2)
-+#define SET_OPT_TURBO_OFF (1 << 3)
-+#define SET_OPT_TURBO (SET_OPT_TURBO_ON | SET_OPT_TURBO_OFF)
-+
-+ pr_debug("set_opt: %s => %s\n", curop->name, newop->name);
-+
-+ cur = &curop->md_opt;
-+ new = &newop->md_opt;
-+ fully_define_opt(cur, new);
-+
-+ if (new->regs.voltage != cur->regs.voltage)
-+ set_opt_flags |= SET_OPT_VOLTAGE;
-+
-+ if (new->cpu) {
-+ if ((new->regs.cccr != cur->regs.cccr) ||
-+ (new->regs.clkcfg != cur->regs.clkcfg)) {
-+
-+ /* Find out if it is *just* a turbo bit change */
-+
-+ if ((cur->l == new->l) &&
-+ (cur->cccra == new->cccra) &&
-+ (cur->b == new->b) &&
-+ (cur->half_turbo == new->half_turbo)) {
-+ /* If the real, current N is a turbo freq and
-+ the new N is not a turbo freq, then set
-+ TURBO_OFF and do not change N.
-+ */
-+ if ((cur->n > 1) && (new->n == 2))
-+ set_opt_flags |= SET_OPT_TURBO_OFF;
-+
-+ /* Else if the current operating point's N is
-+ not-turbo and the new N is the desired
-+ destination N, then set TURBO_ON
-+ */
-+ else if ((cur->n == 2) && (new->n == current_n)) {
-+ /* Desired N must be what is current
-+ set in the CCCR/CCSR.
-+ */
-+ set_opt_flags |= SET_OPT_TURBO_ON;
-+ }
-+ /* Else, fall through to regular FCS */
-+ }
-+
-+ if (!(set_opt_flags & SET_OPT_TURBO)) {
-+ /* It this is not a Turbo bit only change, it
-+ must be a regular FCS.
-+ */
-+ set_opt_flags |= SET_OPT_CPUFREQ;
-+ }
-+ loops_per_jiffy = new->lpj;
-+ }
-+
-+ local_irq_save(s);
-+
-+ /* If exiting 13M mode (turn on PLL(s)), do some extra work
-+ before changing the CPU frequency or voltage.
-+ We may turn on a combination of PLLs supported by hardware
-+ only. Otherwise xpll_on(...) hang the system.
-+ */
-+
-+ if ((!cur->cpll_enabled && new->cpll_enabled) ||
-+ (!cur->ppll_enabled && new->ppll_enabled))
-+ xpll_on(&new->regs);
-+
-+ /* In accordance with Yellow Book section 3.7.6.3, "Coupling
-+ Voltage Change with Frequency Change", always set the
-+ voltage first (setting the FVC bit in the PCFR) and then do
-+ the frequency change
-+ */
-+
-+ if (set_opt_flags & SET_OPT_VOLTAGE) {
-+ if (set_opt_flags & SET_OPT_CPUFREQ)
-+ /* coupled voltage & freq change */
-+ scale_voltage_coupled(&new->regs);
-+ else
-+ /* Scale CPU voltage un-coupled with freq */
-+ scale_voltage(&new->regs);
-+ }
-+
-+ if (set_opt_flags & SET_OPT_CPUFREQ) /* Scale CPU freq */
-+ scale_cpufreq(&new->regs);
-+
-+ if ((set_opt_flags & SET_OPT_VOLTAGE) &&
-+ (set_opt_flags & SET_OPT_CPUFREQ))
-+ PCFR &= ~PCFR_FVC;
-+
-+ if (set_opt_flags & SET_OPT_TURBO) {
-+ clkcfg = read_clkcfg();
-+
-+ /* Section 3.5.7 of the Yellow Book says that the F
-+ bit will be left on after a FCS, so we need to
-+ explicitly clear it. But do not change the B bit.
-+ */
-+
-+ clkcfg &= ~(CLKCFG_F_BIT);
-+
-+ if (set_opt_flags & SET_OPT_TURBO_ON)
-+ clkcfg = clkcfg | (CLKCFG_T_BIT);
-+ else
-+ clkcfg = clkcfg & ~(CLKCFG_T_BIT);
-+
-+ /* enable */
-+ set_freq(clkcfg);
-+ }
-+
-+ if (new->half_turbo != cur->half_turbo) {
-+ if ((set_opt_flags & SET_OPT_CPUFREQ) ||
-+ (set_opt_flags & SET_OPT_VOLTAGE)) {
-+ /*
-+ From the Yellow Book, p 3-106:
-+
-+ "Any two writes to CLKCFG or PWRMODE
-+ registers must be separated by six 13-MHz
-+ cycles. This requirement is achieved by
-+ doing the write to the CLKCFG or POWERMODE
-+ register, performing a read of CCCR, and
-+ then comparing the value in the CLKCFG or
-+ POWERMODE register to the written value
-+ until it matches."
-+
-+ Since the setting of half turbo is a
-+ separate write to CLKCFG, we need to adhere
-+ to this requirement.
-+ */
-+
-+ cccr = CCCR;
-+ clkcfg = read_clkcfg();
-+ while (clkcfg != new->regs.clkcfg)
-+ clkcfg = read_clkcfg();
-+ }
-+
-+ if (clkcfg == 0)
-+ clkcfg = new->regs.clkcfg;
-+
-+ /* Turn off f-bit.
-+
-+ According to the Yellow Book, page 3-23, "If only
-+ HT is set, F is clear, and B is not altered, then
-+ the core PLL is not stopped." */
-+
-+ clkcfg = clkcfg & ~(CLKCFG_F_BIT);
-+
-+ /* set half turbo bit */
-+
-+ if (new->half_turbo)
-+ clkcfg = clkcfg | (CLKCFG_HT_BIT);
-+ else
-+ clkcfg = clkcfg & ~(CLKCFG_HT_BIT);
-+
-+ /* enable */
-+
-+ set_freq(clkcfg);
-+ loops_per_jiffy = new->lpj;
-+ }
-+
-+ local_irq_restore(s);
-+
-+ } else {
-+
-+ /*
-+ * A sleep operating point.
-+ */
-+
-+#ifdef CONFIG_PM
-+ /* NOTE: voltage needs i2c, so be sure to change
-+ voltage BEFORE* calling device_suspend
-+ */
-+
-+ if (set_opt_flags & SET_OPT_VOLTAGE)
-+ /* Scale CPU voltage un-coupled with freq */
-+ scale_voltage(&new->regs);
-+
-+ if (new->sleep_mode == CPUMODE_STANDBY)
-+ pm_suspend(PM_SUSPEND_STANDBY);
-+ else if (new->sleep_mode == CPUMODE_DEEPSLEEP)
-+ ; // not supported upstream yet
-+ else
-+ pm_suspend(PM_SUSPEND_MEM);
-+
-+ /* Here when we wake up. */
-+#endif /*CONFIG_PM*/
-+
-+ /* Recursive call to switch back to to task state. */
-+ dpm_set_os(DPM_TASK_STATE);
-+ }
-+
-+#ifdef CONFIG_DPM_STATS
-+ dpm_update_stats(&newop->stats, &dpm_active_opt->stats);
-+#endif
-+ dpm_active_opt = newop;
-+ mb();
-+
-+ /* Devices only need to scale on a core frequency
-+ change. Half-Turbo changes are separate from the regular
-+ frequency changes, so Half-Turbo changes do not need to
-+ trigger a device recalculation.
-+
-+ NOTE: turbo-mode-only changes could someday also be
-+ optimized like Half-Turbo (to not trigger a device
-+ recalc).
-+ */
-+
-+ if (new->cpu && (set_opt_flags & SET_OPT_CPUFREQ))
-+ /* Normal change (not sleep), just compute. Always use
-+ the "baseline" lpj and freq */
-+ dpm_driver_scale(SCALE_POSTCHANGE, newop);
-+
-+ return 0;
-+}
-+
-+/* Fully determine the current machine-dependent operating point, and fill in a
-+ structure presented by the caller. This should only be called when the
-+ dpm_sem is held. This call can return an error if the system is currently at
-+ an operating point that could not be constructed by dpm_md_init_opt(). */
-+
-+static int get_opt(struct dpm_opt *opt)
-+{
-+ unsigned int tmp_cccr;
-+ unsigned int cpdis;
-+ unsigned int ppdis;
-+ struct dpm_md_opt *md_opt = &opt->md_opt;
-+
-+ /* You should read CCSR to see what's up...but there is no A
-+ bit in the CCSR, so we'll grab it from the CCCR.
-+ */
-+ tmp_cccr = CCCR;
-+ md_opt->cccra = (tmp_cccr >> 25) & 0x1; /* cccr[A]: bit 25 */
-+
-+ /* NOTE: the current voltage is not obtained, but will be left
-+ as 0 in the opt which will mean no voltage change at all.
-+ */
-+
-+ md_opt->regs.cccr = CCSR;
-+
-+ md_opt->l = md_opt->regs.cccr & CCCR_L_MASK; /* Get L */
-+ md_opt->n = (md_opt->regs.cccr & CCCR_N_MASK) >> 7; /* Get 2N */
-+
-+ /* This should never really be less than 2 */
-+ if (md_opt->n < 2) {
-+ md_opt->n = 2;
-+ }
-+
-+ md_opt->regs.clkcfg = read_clkcfg();
-+ md_opt->b = (md_opt->regs.clkcfg >> 3) & 0x1; /* Fast Bus (b): bit 3 */
-+ md_opt->turbo = md_opt->regs.clkcfg & 0x1; /* Turbo is bit 1 */
-+ md_opt->half_turbo = (md_opt->regs.clkcfg >> 2) & 0x1; /* HalfTurbo: bit 2 */
-+
-+ calculate_lcd_freq(md_opt);
-+
-+ /* are any of the PLLs is on? */
-+ cpdis = ((md_opt->regs.cccr >> 31) & 0x1);
-+ ppdis = ((md_opt->regs.cccr >> 30) & 0x1);
-+ /* Newer revisions still require that if CPLL is On
-+ then PPLL must also be On.
-+ */
-+ if ((cpdis == 0) && (ppdis != 0)) {
-+ /* CPLL=On PPLL=Off is NOT supported with hardware.
-+ NOTE:"B0"-revision has even more restrictive requirments
-+ to PLLs
-+ */
-+ printk("DPM: cpdis and ppdis are not in sync!\n");
-+ }
-+
-+ md_opt->cpll_enabled = (cpdis == 0);
-+ md_opt->ppll_enabled = (ppdis == 0);
-+
-+ /* Shift 1 to divide by 2 (because opt->n is really 2*N */
-+ if (md_opt->turbo) {
-+ md_opt->cpu = (13000 * md_opt->l * md_opt->n) >> 1;
-+ } else {
-+ /* turbo bit is off, so skip N multiplier (no matter
-+ what N really is) and use Run frequency (13K * L)
-+ */
-+ md_opt->cpu = 13000 * md_opt->l;
-+ }
-+
-+ return 0;
-+}
-+
-+/****************************************************************************
-+ * DPM Idle Handler
-+ ****************************************************************************/
-+
-+static void (*orig_idle) (void);
-+
-+static void dpm_pxa27x_idle(void)
-+{
-+ extern void default_idle(void);
-+
-+ if (orig_idle)
-+ orig_idle();
-+ else {
-+ /*
-+ * arch/arm/kernel/process.c: default_idle()
-+ * do be sure to watch for updates :(
-+ */
-+
-+ local_irq_disable();
-+ if (!need_resched()) {
-+ timer_dyn_reprogram();
-+ arch_idle();
-+ }
-+ local_irq_enable();
-+ }
-+}
-+
-+/****************************************************************************
-+ * Initialization/Exit
-+ ****************************************************************************/
-+
-+extern void (*pm_idle) (void);
-+
-+static void startup(void)
-+{
-+ orig_idle = pm_idle;
-+ pm_idle = dpm_idle;
-+}
-+
-+static void cleanup(void)
-+{
-+ pm_idle = orig_idle;
-+}
-+
-+static int __init dpm_pxa27x_init(void)
-+{
-+ printk("PXA27x Dynamic Power Management\n");
-+
-+ if (freq_init()) {
-+ printk("PXA27x DPM init failed\n");
-+ return -1;
-+ }
-+
-+ vcs_init();
-+ dpm_md.init_opt = init_opt;
-+ dpm_md.set_opt = set_opt;
-+ dpm_md.get_opt = get_opt;
-+ dpm_md.check_constraint = dpm_default_check_constraint;
-+ dpm_md.idle = dpm_pxa27x_idle;
-+ dpm_md.startup = startup;
-+ dpm_md.cleanup = cleanup;
-+ return 0;
-+}
-+
-+static void __exit dpm_pxa27x_exit(void){
-+ freq_cleanup();
-+}
-+
-+__initcall(dpm_pxa27x_init);
-+__exitcall(dpm_pxa27x_exit);
-Index: linux-2.6.16/drivers/serial/pxa.c
-===================================================================
---- linux-2.6.16.orig/drivers/serial/pxa.c
-+++ linux-2.6.16/drivers/serial/pxa.c
-@@ -43,6 +43,8 @@
- #include <linux/tty.h>
- #include <linux/tty_flip.h>
- #include <linux/serial_core.h>
-+#include <linux/dpm.h>
-+#include <linux/notifier.h>
-
- #include <asm/io.h>
- #include <asm/hardware.h>
-@@ -57,6 +59,7 @@ struct uart_pxa_port {
- unsigned char mcr;
- unsigned int lsr_break_flag;
- unsigned int cken;
-+ unsigned int baud;
- char *name;
- };
-
-@@ -473,6 +476,7 @@ serial_pxa_set_termios(struct uart_port
- */
- baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
- quot = uart_get_divisor(port, baud);
-+ up->baud = baud; // save for DPM scale callback
-
- if ((up->port.uartclk / quot) < (2400 * 16))
- fcr = UART_FCR_ENABLE_FIFO | UART_FCR_PXAR1;
-@@ -817,6 +821,44 @@ static int serial_pxa_resume(struct plat
- return 0;
- }
-
-+static int serial_pxa_scale(struct notifier_block *self,
-+ unsigned long level, void *newop)
-+{
-+ int n=0;int i=0;
-+ int ccsr=CCSR;
-+ n=sizeof(serial_pxa_ports)/sizeof(struct uart_pxa_port);
-+
-+ for (i=0; i<n; ++i) {
-+ struct uart_pxa_port *up = (struct uart_pxa_port *) &serial_pxa_ports[i];
-+
-+ if(up->baud) {
-+ unsigned int quot;
-+
-+ if ((ccsr & (1<<30))){
-+ if (up->port.uartclk == 13000000)
-+ return 0;
-+
-+ /*if PPLL is Off (clocking with 13MHz now)*/
-+ up->port.uartclk = 13000000;
-+ } else {
-+ if (up->port.uartclk == 921600 * 16)
-+ return 0;
-+
-+ /*clocking with 14.7456 MHz*/
-+ up->port.uartclk = 921600 * 16;
-+ }
-+
-+ quot = uart_get_divisor(&up->port, up->baud);
-+ serial_out(up, UART_LCR, up->lcr | UART_LCR_DLAB);/* set DLAB */
-+ serial_out(up, UART_DLL, quot & 0xff); /* LS of divisor */
-+ serial_out(up, UART_DLM, quot >> 8); /* MS of divisor */
-+ serial_out(up, UART_LCR, up->lcr); /* reset DLAB */
-+ }
-+ }
-+
-+ return 0;
-+}
-+
- static int serial_pxa_probe(struct platform_device *dev)
- {
- serial_pxa_ports[dev->id].port.dev = &dev->dev;
-@@ -848,6 +890,10 @@ static struct platform_driver serial_pxa
- },
- };
-
-+static struct notifier_block serial_pxa_nb = {
-+ .notifier_call = serial_pxa_scale,
-+};
-+
- int __init serial_pxa_init(void)
- {
- int ret;
-@@ -860,6 +906,9 @@ int __init serial_pxa_init(void)
- if (ret != 0)
- uart_unregister_driver(&serial_pxa_reg);
-
-+ if (! ret)
-+ dpm_register_scale(&serial_pxa_nb, SCALE_POSTCHANGE);
-+
- return ret;
- }
-
-@@ -867,6 +916,7 @@ void __exit serial_pxa_exit(void)
- {
- platform_driver_unregister(&serial_pxa_driver);
- uart_unregister_driver(&serial_pxa_reg);
-+ dpm_unregister_scale(&serial_pxa_nb, SCALE_POSTCHANGE);
- }
-
- module_init(serial_pxa_init);
-Index: linux-2.6.16/drivers/video/pxafb.c
-===================================================================
---- linux-2.6.16.orig/drivers/video/pxafb.c
-+++ linux-2.6.16/drivers/video/pxafb.c
-@@ -1000,6 +1000,39 @@ static int pxafb_resume(struct platform_
- #define pxafb_resume NULL
- #endif
-
-+#ifdef CONFIG_DPM
-+#include <linux/dpm.h>
-+
-+#define WAIT_FOR_LCD_INTR(reg,intr,timeout) ({ \
-+ int __done =0; \
-+ int __t = timeout; \
-+ while (__t) { \
-+ __done = (reg) & (intr); \
-+ if (__done) break; \
-+ udelay(50); \
-+ __t--; \
-+ } \
-+ __done; \
-+})
-+
-+static int pxafb_scale(struct notifier_block *nb, unsigned long val, void *data)
-+{
-+#if 0 // Without disable.enable overlays, doesn't work well yet
-+ struct pxafb_info *fbi = TO_INF(nb, scale);
-+ u_int pcd;
-+
-+ LCSR = 0xffffffff; /* Clear LCD Status Register */
-+ LCCR0 &= ~LCCR0_LDM; /* Enable LCD Disable Done Interrupt */
-+ LCCR0 |= LCCR0_DIS; /* Disable LCD Controller */
-+ WAIT_FOR_LCD_INTR(LCSR,LCSR_LDD,20);
-+ pcd = get_pcd(fbi->fb.var.pixclock);
-+ fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
-+ pxafb_enable_controller(fbi);
-+#endif
-+ return 0;
-+}
-+#endif
-+
- /*
- * pxafb_map_video_memory():
- * Allocates the DRAM memory for the frame buffer. This buffer is
-@@ -1367,6 +1400,10 @@ int __init pxafb_probe(struct platform_d
- cpufreq_register_notifier(&fbi->freq_transition, CPUFREQ_TRANSITION_NOTIFIER);
- cpufreq_register_notifier(&fbi->freq_policy, CPUFREQ_POLICY_NOTIFIER);
- #endif
-+#ifdef CONFIG_DPM
-+ fbi->scale.notifier_call = pxafb_scale;
-+ dpm_register_scale(&fbi->scale, SCALE_POSTCHANGE);
-+#endif
-
- /*
- * Ok, now enable the LCD controller
-Index: linux-2.6.16/drivers/video/pxafb.h
-===================================================================
---- linux-2.6.16.orig/drivers/video/pxafb.h
-+++ linux-2.6.16/drivers/video/pxafb.h
-@@ -95,6 +95,10 @@ struct pxafb_info {
- struct notifier_block freq_transition;
- struct notifier_block freq_policy;
- #endif
-+
-+#ifdef CONFIG_DPM
-+ struct notifier_block scale;
-+#endif
- };
-
- #define TO_INF(ptr,member) container_of(ptr,struct pxafb_info,member)