summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorZhou Jingyu <b02241@freescale.com>2011-01-25 16:08:45 +0800
committerZhou Jingyu <b02241@freescale.com>2011-01-25 18:20:43 +0800
commit26cc5e46e6523c2a162b3a2714f25b75fa4b7833 (patch)
tree729558cc0843448c19134f5fedd5a506f9fc6e79 /arch
parentd12139288f0480eb1672083d652853b33630470e (diff)
ENGR00138479 Restructure MX53 bus frequecy driver
Restructure MX53 bus frequecy driver, Add handlers for DDR3 boards, MX53 DDR2 handlers not implemented in this patch Signed-off-by: Zhou Jingyu <Jingyu.Zhou@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-mx5/bus_freq.c289
-rw-r--r--arch/arm/plat-mxc/dvfs_core.c3
2 files changed, 165 insertions, 127 deletions
diff --git a/arch/arm/mach-mx5/bus_freq.c b/arch/arm/mach-mx5/bus_freq.c
index a41bcfcb4a98..5e3c5de2e476 100644
--- a/arch/arm/mach-mx5/bus_freq.c
+++ b/arch/arm/mach-mx5/bus_freq.c
@@ -35,6 +35,7 @@
#include <mach/mxc_dvfs.h>
#include <mach/sdram_autogating.h>
#include <asm/mach/map.h>
+#include <asm/mach-types.h>
#include <asm/cacheflush.h>
#include <asm/tlb.h>
#include "crm_regs.h"
@@ -53,6 +54,8 @@
#define HW_QOS_DISABLE 0x70
#define HW_QOS_DISABLE_SET 0x74
#define HW_QOS_DISABLE_CLR 0x78
+#define DDR_TYPE_DDR3 0x0
+#define DDR_TYPE_DDR2 0x1
DEFINE_SPINLOCK(ddr_freq_lock);
@@ -62,6 +65,7 @@ static unsigned long ddr_normal_rate;
static unsigned long ddr_med_rate;
static unsigned long ddr_low_rate;
static int cur_ddr_rate;
+static unsigned char mx53_ddr_type;
static struct clk *ddr_clk;
static struct clk *pll1_sw_clk;
@@ -116,8 +120,10 @@ struct completion voltage_change_cmpl;
void enter_lpapm_mode_mx50(void);
void enter_lpapm_mode_mx51(void);
+void enter_lpapm_mode_mx53(void);
void exit_lpapm_mode_mx50(int high_bus_freq);
void exit_lpapm_mode_mx51(void);
+void exit_lpapm_mode_mx53(void);
int low_freq_bus_used(void);
void set_ddr_freq(int ddr_freq);
void *ddr_freq_change_iram_base;
@@ -159,13 +165,8 @@ static void voltage_work_handler(struct work_struct *work)
int set_low_bus_freq(void)
{
- u32 reg;
- struct timespec nstimeofday;
- struct timespec curtime;
-
if (busfreq_suspended)
return 0;
-
if (bus_freq_scaling_initialized) {
/* can not enter low bus freq, when cpu is in higher freq
* or only have one working point */
@@ -180,66 +181,14 @@ int set_low_bus_freq(void)
stop_dvfs_per();
stop_sdram_autogating();
- if (!cpu_is_mx53()) {
- if (cpu_is_mx50()) {
- enter_lpapm_mode_mx50();
- }
- else
- enter_lpapm_mode_mx51();
-
- } else {
- /*Change the DDR freq to 133Mhz. */
- clk_set_rate(ddr_hf_clk,
- clk_round_rate(ddr_hf_clk, ddr_low_rate));
-
- /* move cpu clk to pll2, 400 / 3 = 133Mhz for cpu */
- clk_set_parent(pll1_sw_clk, pll2);
- cpu_podf = __raw_readl(MXC_CCM_CACRR);
- reg = __raw_readl(MXC_CCM_CDHIPR);
- if ((reg & MXC_CCM_CDHIPR_ARM_PODF_BUSY) == 0)
- __raw_writel(0x2, MXC_CCM_CACRR);
- else
- printk(KERN_DEBUG "ARM_PODF still in busy!!!!\n");
-
- /* ahb = 400/8, axi_b = 400/8, axi_a = 133*/
- reg = __raw_readl(MXC_CCM_CBCDR);
- reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
- | MXC_CCM_CBCDR_AXI_B_PODF_MASK
- | MXC_CCM_CBCDR_AHB_PODF_MASK);
- reg |= (2 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
- | 7 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
- | 7 << MXC_CCM_CBCDR_AHB_PODF_OFFSET);
- __raw_writel(reg, MXC_CCM_CBCDR);
-
- getnstimeofday(&nstimeofday);
- while (__raw_readl(MXC_CCM_CDHIPR) &
- (MXC_CCM_CDHIPR_AXI_A_PODF_BUSY |
- MXC_CCM_CDHIPR_AXI_B_PODF_BUSY |
- MXC_CCM_CDHIPR_AHB_PODF_BUSY)) {
- getnstimeofday(&curtime);
- if (curtime.tv_nsec - nstimeofday.tv_nsec
- > SPIN_DELAY)
- panic("low bus freq set rate error\n");
- }
-
- /* keep this infront of propagating */
- low_bus_freq_mode = 1;
- high_bus_freq_mode = 0;
- med_bus_freq_mode = 0;
-
- if (clk_get_usecount(pll1) == 0) {
- reg = __raw_readl(pll1_base + MXC_PLL_DP_CTL);
- reg &= ~MXC_PLL_DP_CTL_UPEN;
- __raw_writel(reg, pll1_base + MXC_PLL_DP_CTL);
- }
- if (clk_get_usecount(pll4) == 0) {
- reg = __raw_readl(pll4_base + MXC_PLL_DP_CTL);
- reg &= ~MXC_PLL_DP_CTL_UPEN;
- __raw_writel(reg, pll4_base + MXC_PLL_DP_CTL);
- }
- }
- mutex_unlock(&bus_freq_mutex);
+ if (cpu_is_mx50())
+ enter_lpapm_mode_mx50();
+ else if (cpu_is_mx51())
+ enter_lpapm_mode_mx51();
+ else
+ enter_lpapm_mode_mx53();
+ mutex_unlock(&bus_freq_mutex);
}
return 0;
}
@@ -321,7 +270,6 @@ void enter_lpapm_mode_mx50()
void enter_lpapm_mode_mx51()
{
u32 reg;
-
/* Set PLL3 to 133Mhz if no-one is using it. */
if (clk_get_usecount(pll3) == 0) {
u32 pll3_rate = clk_get_rate(pll3);
@@ -364,16 +312,74 @@ void enter_lpapm_mode_mx51()
/* Set PLL3 back to original rate. */
clk_set_rate(pll3, clk_round_rate(pll3, pll3_rate));
clk_disable(pll3);
-
}
}
-int set_high_bus_freq(int high_bus_freq)
+void enter_lpapm_mode_mx53()
{
u32 reg;
struct timespec nstimeofday;
struct timespec curtime;
+ /* TBD: Reduce DDR frequency for DDR2 */
+ /* if (mx53_ddr_type == DDR_TYPE_DDR2) {
+ } */
+
+ /* move cpu clk to pll2, 400 / 3 = 133Mhz for cpu */
+ /* Change the source of pll1_sw_clk to be the step_clk */
+ reg = __raw_readl(MXC_CCM_CCSR);
+ reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;
+ __raw_writel(reg, MXC_CCM_CCSR);
+
+ cpu_podf = __raw_readl(MXC_CCM_CACRR);
+ reg = __raw_readl(MXC_CCM_CDHIPR);
+ if ((reg & MXC_CCM_CDHIPR_ARM_PODF_BUSY) == 0)
+ __raw_writel(0x2, MXC_CCM_CACRR);
+ else
+ printk(KERN_DEBUG "ARM_PODF still in busy!!!!\n");
+ clk_set_parent(pll1_sw_clk, pll2);
+
+ /* ahb = pll2/8, axi_b = pll2/8, axi_a = pll2/1*/
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK);
+ reg |= (0 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ | 7 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ | 7 << MXC_CCM_CBCDR_AHB_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) &
+ (MXC_CCM_CDHIPR_AXI_A_PODF_BUSY |
+ MXC_CCM_CDHIPR_AXI_B_PODF_BUSY |
+ MXC_CCM_CDHIPR_AHB_PODF_BUSY)) {
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec - nstimeofday.tv_nsec
+ > SPIN_DELAY)
+ panic("low bus freq set rate error\n");
+ }
+
+ /* keep this infront of propagating */
+ low_bus_freq_mode = 1;
+ high_bus_freq_mode = 0;
+ med_bus_freq_mode = 0;
+
+ if (clk_get_usecount(pll1) == 0) {
+ reg = __raw_readl(pll1_base + MXC_PLL_DP_CTL);
+ reg &= ~MXC_PLL_DP_CTL_UPEN;
+ __raw_writel(reg, pll1_base + MXC_PLL_DP_CTL);
+ }
+ if (clk_get_usecount(pll4) == 0) {
+ reg = __raw_readl(pll4_base + MXC_PLL_DP_CTL);
+ reg &= ~MXC_PLL_DP_CTL_UPEN;
+ __raw_writel(reg, pll4_base + MXC_PLL_DP_CTL);
+ }
+}
+
+int set_high_bus_freq(int high_bus_freq)
+{
+ u32 reg;
if (bus_freq_scaling_initialized) {
mutex_lock(&bus_freq_mutex);
/*
@@ -389,54 +395,12 @@ int set_high_bus_freq(int high_bus_freq)
if (low_bus_freq_mode) {
/* Relock PLL3 to 133MHz */
- if (!cpu_is_mx53()) {
- if (cpu_is_mx50())
- exit_lpapm_mode_mx50(high_bus_freq);
- else
- exit_lpapm_mode_mx51();
- } else {
- /* move cpu clk to pll1 */
- reg = __raw_readl(MXC_CCM_CDHIPR);
- if ((reg & MXC_CCM_CDHIPR_ARM_PODF_BUSY) == 0)
- __raw_writel(cpu_podf & 0x7,
- MXC_CCM_CACRR);
- else
- printk(KERN_DEBUG
- "ARM_PODF still in busy!!!!\n");
-
- clk_set_parent(pll1_sw_clk, pll1);
-
- /* ahb = 400/3, axi_b = 400/3, axi_a = 400*/
- reg = __raw_readl(MXC_CCM_CBCDR);
- reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
- | MXC_CCM_CBCDR_AXI_B_PODF_MASK
- | MXC_CCM_CBCDR_AHB_PODF_MASK);
- reg |= (0 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
- | 2 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
- | 2 << MXC_CCM_CBCDR_AHB_PODF_OFFSET);
- __raw_writel(reg, MXC_CCM_CBCDR);
-
- getnstimeofday(&nstimeofday);
- while (__raw_readl(MXC_CCM_CDHIPR) &
- (MXC_CCM_CDHIPR_AXI_A_PODF_BUSY |
- MXC_CCM_CDHIPR_AXI_B_PODF_BUSY |
- MXC_CCM_CDHIPR_AHB_PODF_BUSY)) {
- getnstimeofday(&curtime);
- if (curtime.tv_nsec
- - nstimeofday.tv_nsec
- > SPIN_DELAY)
- panic("bus freq error\n");
- }
-
- /* keep this infront of propagating */
- low_bus_freq_mode = 0;
- high_bus_freq_mode = 1;
- med_bus_freq_mode = 0;
-
- /*Change the DDR freq to mormal_rate*/
- clk_set_rate(ddr_hf_clk,
- clk_round_rate(ddr_hf_clk, ddr_normal_rate));
- }
+ if (cpu_is_mx50())
+ exit_lpapm_mode_mx50(high_bus_freq);
+ else if (cpu_is_mx51())
+ exit_lpapm_mode_mx51();
+ else
+ exit_lpapm_mode_mx53();
start_dvfs_per();
}
if (bus_freq_scaling_is_active) {
@@ -498,11 +462,14 @@ int set_high_bus_freq(int high_bus_freq)
reg |= 8 << MXC_CCM_CLK_SYS_DIV_PLL_OFFSET;
__raw_writel(reg, MXC_CCM_CLK_SYS);
} else {
- clk_set_rate(ddr_hf_clk,
- clk_round_rate(ddr_hf_clk,
- ddr_low_rate));
+ if (cpu_is_mx51())
+ clk_set_rate(ddr_hf_clk,
+ clk_round_rate(
+ ddr_hf_clk,
+ ddr_low_rate));
clk_set_rate(ahb_clk,
- clk_round_rate(ahb_clk, lp_med_rate));
+ clk_round_rate(
+ ahb_clk, lp_med_rate));
}
/* Set to the medium setpoint. */
high_bus_freq_mode = 0;
@@ -694,7 +661,58 @@ void exit_lpapm_mode_mx51()
clk_round_rate(ddr_hf_clk, ddr_normal_rate));
}
-int can_change_ddr_freq()
+void exit_lpapm_mode_mx53()
+{
+ u32 reg;
+ struct timespec nstimeofday;
+ struct timespec curtime;
+
+
+ /* move cpu clk to pll1 */
+ reg = __raw_readl(MXC_CCM_CDHIPR);
+ if ((reg & MXC_CCM_CDHIPR_ARM_PODF_BUSY) != 0)
+ __raw_writel(cpu_podf & 0x7,
+ MXC_CCM_CACRR);
+ else
+ printk(KERN_DEBUG
+ "ARM_PODF still in busy!!!!\n");
+
+ clk_set_parent(pll1_sw_clk, pll1);
+
+
+ /* ahb = 400/3, axi_b = 400/2, axi_a = 400*/
+ reg = __raw_readl(MXC_CCM_CBCDR);
+ reg &= ~(MXC_CCM_CBCDR_AXI_A_PODF_MASK
+ | MXC_CCM_CBCDR_AXI_B_PODF_MASK
+ | MXC_CCM_CBCDR_AHB_PODF_MASK);
+ reg |= (0 << MXC_CCM_CBCDR_AXI_A_PODF_OFFSET
+ | 1 << MXC_CCM_CBCDR_AXI_B_PODF_OFFSET
+ | 2 << MXC_CCM_CBCDR_AHB_PODF_OFFSET);
+ __raw_writel(reg, MXC_CCM_CBCDR);
+
+ getnstimeofday(&nstimeofday);
+ while (__raw_readl(MXC_CCM_CDHIPR) &
+ (MXC_CCM_CDHIPR_AXI_A_PODF_BUSY |
+ MXC_CCM_CDHIPR_AXI_B_PODF_BUSY |
+ MXC_CCM_CDHIPR_AHB_PODF_BUSY)) {
+ getnstimeofday(&curtime);
+ if (curtime.tv_nsec
+ - nstimeofday.tv_nsec
+ > SPIN_DELAY)
+ panic("bus freq error\n");
+ }
+
+ /* keep this infront of propagating */
+ low_bus_freq_mode = 0;
+ high_bus_freq_mode = 1;
+ med_bus_freq_mode = 0;
+
+ /* TBD: Restore DDR frequency for DDR2 */
+ /* if (mx53_ddr_type == DDR_TYPE_DDR2) {
+ } */
+}
+
+int can_change_ddr_freq(void)
{
if (clk_get_usecount(epdc_clk) == 0)
return 1;
@@ -964,13 +982,8 @@ static int __devinit busfreq_probe(struct platform_device *pdev)
ddr_normal_rate = pll2_rate / 2;
ddr_low_rate = pll2_rate / 2;
} else if (pll2_rate == 400000000) {
- /* for mx53 evk rev.B */
- lp_normal_rate = pll2_rate / 3;
- lp_med_rate = pll2_rate / 5;
- if (cpu_is_mx53()) {
- ddr_normal_rate = pll2_rate / 1;
- ddr_low_rate = pll2_rate / 3;
- } else if (cpu_is_mx50()) {
+ if (cpu_is_mx50()) {
+ lp_normal_rate = pll2_rate / 3;
ddr_normal_rate = clk_get_rate(ddr_clk);
lp_med_rate = pll2_rate / 6;
ddr_low_rate = LP_APM_CLK;
@@ -978,6 +991,28 @@ static int __devinit busfreq_probe(struct platform_device *pdev)
}
}
+ /* for mx53 */
+ if (cpu_is_mx53()) {
+ /* set DDR type */
+ if (machine_is_mx53_evk() || machine_is_mx53_ard())
+ mx53_ddr_type = DDR_TYPE_DDR2;
+ else
+ mx53_ddr_type = DDR_TYPE_DDR3;
+ if (mx53_ddr_type == DDR_TYPE_DDR2) {
+ /* DDR2 */
+ lp_normal_rate = pll2_rate / 3;
+ lp_med_rate = pll2_rate / 5;
+ ddr_normal_rate = pll2_rate / 1;
+ ddr_low_rate = pll2_rate / 3;
+ } else {
+ /* DDR3: DDR3 frequency can not be lower than 300MHZ */
+ lp_normal_rate = pll2_rate / 3;
+ lp_med_rate = pll2_rate / 5;
+ ddr_normal_rate = pll2_rate / 1;
+ ddr_low_rate = pll2_rate / 1;
+ }
+ }
+
if (cpu_is_mx50()) {
u32 reg;
diff --git a/arch/arm/plat-mxc/dvfs_core.c b/arch/arm/plat-mxc/dvfs_core.c
index 060db87fe656..807fa63141ad 100644
--- a/arch/arm/plat-mxc/dvfs_core.c
+++ b/arch/arm/plat-mxc/dvfs_core.c
@@ -373,6 +373,9 @@ static int start_dvfs(void)
for (curr_wp = 0; curr_wp < cpu_wp_nr; curr_wp++)
if (cpu_rate == cpu_wp_tbl[curr_wp].cpu_rate)
break;
+ /* if doesn't find it, set it as the lowest point */
+ if (curr_wp == cpu_wp_nr)
+ curr_wp--;
old_wp = curr_wp;
/* config reg GPC_CNTR */
reg = __raw_readl(gpc_base + dvfs_data->gpc_cntr_offset);