diff options
author | Shen Yong <b00984@freescale.com> | 2010-06-28 13:14:22 +0800 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2010-12-17 12:10:50 -0500 |
commit | 529cc4441f785e43baa72e41634e6f3e21ac1c1d (patch) | |
tree | f42b91d3f7139dc605ab794bf771a8a1227f0488 | |
parent | 3879e4dc9d7034c37ea17331f74fc14d94da0a08 (diff) |
ENGR00124132 MX53: busfreq driver support
1. adjust lp_clk, ddr_clk MX53 and MX51 uses different one
2. adjust cpu rate in cpu_wp_table
3. enable clock divider handshaking when ddr clock changing
4. add AHB_MED_SET_POINT to ldb_di_clk
5. adjust the bit define about CCDR register
Signed-off-by: Shen Yong <b00984@freescale.com>
-rw-r--r-- | arch/arm/mach-mx5/bus_freq.c | 75 | ||||
-rw-r--r-- | arch/arm/mach-mx5/clock.c | 16 | ||||
-rw-r--r-- | arch/arm/mach-mx5/mx53_evk.c | 3 |
3 files changed, 69 insertions, 25 deletions
diff --git a/arch/arm/mach-mx5/bus_freq.c b/arch/arm/mach-mx5/bus_freq.c index ce5faad029e2..4fcaf95e3019 100644 --- a/arch/arm/mach-mx5/bus_freq.c +++ b/arch/arm/mach-mx5/bus_freq.c @@ -33,12 +33,8 @@ #include <mach/sdram_autogating.h> #include "crm_regs.h" -#define LP_NORMAL_CLK 133000000 -#define LP_MED_CLK 83125000 #define LP_APM_CLK 24000000 #define NAND_LP_APM_CLK 12000000 -#define DDR_LOW_FREQ_CLK 133000000 -#define DDR_NORMAL_CLK 200000000 #define AXI_A_NORMAL_CLK 166250000 #define AXI_A_CLK_NORMAL_DIV 4 #define AXI_B_CLK_NORMAL_DIV 5 @@ -46,7 +42,13 @@ #define EMI_SLOW_CLK_NORMAL_DIV AXI_B_CLK_NORMAL_DIV #define NFC_CLK_NORMAL_DIV 4 +static unsigned long lp_normal_rate; +static unsigned long lp_med_rate; +static unsigned long ddr_normal_rate; +static unsigned long ddr_low_rate; + static struct clk *ddr_clk; +static struct clk *pll1_sw_clk; static struct clk *pll2; static struct clk *pll3; static struct clk *main_bus_clk; @@ -93,7 +95,6 @@ struct dvfs_wp dvfs_core_setpoint[] = { {28, 8, 33, 20, 30, 0x08}, {29, 0, 33, 20, 10, 0x08},}; - int set_low_bus_freq(void) { u32 reg; @@ -102,15 +103,20 @@ int set_low_bus_freq(void) return 0; if (bus_freq_scaling_initialized) { + /* can not enter low bus freq, when cpu is in highest freq */ if (clk_get_rate(cpu_clk) != cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate) return 0; + /* currently not support on mx53 */ + if (cpu_is_mx53()) + return 0; + stop_dvfs_per(); stop_sdram_autogating(); /*Change the DDR freq to 133Mhz. */ clk_set_rate(ddr_hf_clk, - clk_round_rate(ddr_hf_clk, DDR_LOW_FREQ_CLK)); + clk_round_rate(ddr_hf_clk, ddr_low_rate)); /* Set PLL3 to 133Mhz if no-one is using it. */ if (clk_get_usecount(pll3) == 0) { @@ -163,6 +169,7 @@ int set_high_bus_freq(int high_bus_freq) u32 reg; if (bus_freq_scaling_initialized) { + stop_sdram_autogating(); if (low_bus_freq_mode) { @@ -207,7 +214,8 @@ int set_high_bus_freq(int high_bus_freq) /*Change the DDR freq to 200MHz*/ clk_set_rate(ddr_hf_clk, - clk_round_rate(ddr_hf_clk, DDR_NORMAL_CLK)); + clk_round_rate(ddr_hf_clk, ddr_normal_rate)); + start_dvfs_per(); } if (bus_freq_scaling_is_active) { @@ -219,24 +227,28 @@ int set_high_bus_freq(int high_bus_freq) cpu_wp_tbl[cpu_wp_nr - 1].cpu_rate) high_bus_freq = 1; - if (((clk_get_rate(ahb_clk) == LP_MED_CLK) + if (((clk_get_rate(ahb_clk) == lp_med_rate) && lp_high_freq) || high_bus_freq) { /* Set to the high setpoint. */ high_bus_freq_mode = 1; + clk_set_rate(ahb_clk, - clk_round_rate(ahb_clk, LP_NORMAL_CLK)); + clk_round_rate(ahb_clk, lp_normal_rate)); + clk_set_rate(ddr_hf_clk, - clk_round_rate(ddr_hf_clk, DDR_NORMAL_CLK)); + clk_round_rate(ddr_hf_clk, ddr_normal_rate)); } + if (!lp_high_freq && !high_bus_freq) { /* Set to the medium setpoint. */ high_bus_freq_mode = 0; low_bus_freq_mode = 0; + clk_set_rate(ddr_hf_clk, - clk_round_rate(ddr_hf_clk, - DDR_LOW_FREQ_CLK)); + clk_round_rate(ddr_hf_clk, ddr_low_rate)); + clk_set_rate(ahb_clk, - clk_round_rate(ahb_clk, LP_MED_CLK)); + clk_round_rate(ahb_clk, lp_med_rate)); } } start_sdram_autogating(); @@ -289,6 +301,7 @@ static ssize_t bus_freq_scaling_enable_store(struct device *dev, clk_set_parent(main_bus_clk, pll2); bus_freq_scaling_is_active = 1; + set_high_bus_freq(0); } else if (strstr(buf, "0") != NULL) { if (bus_freq_scaling_is_active) @@ -326,6 +339,7 @@ static DEVICE_ATTR(enable, 0644, bus_freq_scaling_enable_show, static int __devinit busfreq_probe(struct platform_device *pdev) { int err = 0; + unsigned long pll2_rate, pll1_rate; busfreq_dev = &pdev->dev; @@ -336,12 +350,41 @@ static int __devinit busfreq_probe(struct platform_device *pdev) return PTR_ERR(main_bus_clk); } + pll1_sw_clk = clk_get(NULL, "pll1_sw_clk"); + if (IS_ERR(pll1_sw_clk)) { + printk(KERN_DEBUG "%s: failed to get pll1_sw_clk\n", __func__); + return PTR_ERR(pll1_sw_clk); + } + pll2 = clk_get(NULL, "pll2"); if (IS_ERR(pll2)) { printk(KERN_DEBUG "%s: failed to get pll2\n", __func__); return PTR_ERR(pll2); } + pll1_rate = clk_get_rate(pll1_sw_clk); + pll2_rate = clk_get_rate(pll2); + + if (pll2_rate == 665000000) { + /* for mx51 */ + lp_normal_rate = pll2_rate / 5; + lp_med_rate = pll2_rate / 8; + ddr_normal_rate = pll1_rate / 4; /* 200M */ + ddr_low_rate = pll1_rate / 6; /* 133M */ + } else if (pll2_rate == 600000000) { + /* for mx53 evk rev.A */ + lp_normal_rate = pll2_rate / 5; + lp_med_rate = pll2_rate / 8; + 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; + ddr_normal_rate = pll2_rate / 1; + ddr_low_rate = pll2_rate / 3; + } + pll3 = clk_get(NULL, "pll3"); if (IS_ERR(pll3)) { printk(KERN_DEBUG "%s: failed to get pll3\n", __func__); @@ -362,7 +405,11 @@ static int __devinit busfreq_probe(struct platform_device *pdev) return PTR_ERR(axi_b_clk); } - ddr_hf_clk = clk_get(NULL, "ddr_hf_clk"); + if (cpu_is_mx51()) + ddr_hf_clk = clk_get(NULL, "ddr_hf_clk"); + else + ddr_hf_clk = clk_get(NULL, "axi_a_clk"); + if (IS_ERR(ddr_hf_clk)) { printk(KERN_DEBUG "%s: failed to get ddr_hf_clk\n", __func__); diff --git a/arch/arm/mach-mx5/clock.c b/arch/arm/mach-mx5/clock.c index b1b2d5818f0a..bded58677bed 100644 --- a/arch/arm/mach-mx5/clock.c +++ b/arch/arm/mach-mx5/clock.c @@ -1411,7 +1411,10 @@ static int _clk_ipu_enable(struct clk *clk) _clk_enable(clk); /* Handshake with IPU when certain clock rates are changed. */ reg = __raw_readl(MXC_CCM_CCDR); - reg &= ~MXC_CCM_CCDR_IPU_HS_MASK; + if (cpu_is_mx51()) + reg &= ~MXC_CCM_CCDR_IPU_HS_MASK; + else + reg &= ~MXC_CCM_CCDR_IPU_HS_MX53_MASK; __raw_writel(reg, MXC_CCM_CCDR); /* Handshake with IPU when LPM is entered as its enabled. */ @@ -1717,7 +1720,7 @@ static struct clk ldb_di_clk[] = { .set_rate = _clk_ldb_di_set_rate, .enable = _clk_ldb_di_enable, .disable = _clk_ldb_di_disable, - .flags = RATE_PROPAGATES, + .flags = RATE_PROPAGATES | AHB_MED_SET_POINT, }, { .name = "ldb_di1_clk", @@ -1731,7 +1734,7 @@ static struct clk ldb_di_clk[] = { .set_rate = _clk_ldb_di_set_rate, .enable = _clk_ldb_di_enable, .disable = _clk_ldb_di_disable, - .flags = RATE_PROPAGATES, + .flags = RATE_PROPAGATES | AHB_MED_SET_POINT, }, }; @@ -4829,13 +4832,6 @@ int __init mx53_clocks_init(unsigned long ckil, unsigned long osc, unsigned long __raw_writel(reg, MXC_CCM_CLPCR); #endif - /* Disable the handshake with HSC block as its not - * initialised right now. - */ - reg = __raw_readl(MXC_CCM_CCDR); - reg |= MXC_CCM_CCDR_EMI_HS_MASK; - __raw_writel(reg, MXC_CCM_CCDR); - /* This will propagate to all children and init all the clock rates */ propagate_rate(&osc_clk); propagate_rate(&ckih_clk); diff --git a/arch/arm/mach-mx5/mx53_evk.c b/arch/arm/mach-mx5/mx53_evk.c index cb0de8cfbbfc..e7bf88805d5f 100644 --- a/arch/arm/mach-mx5/mx53_evk.c +++ b/arch/arm/mach-mx5/mx53_evk.c @@ -98,7 +98,7 @@ static struct cpu_wp cpu_wp_auto[] = { .cpu_voltage = 1050000,}, { .pll_rate = 800000000, - .cpu_rate = 166250000, + .cpu_rate = 160000000, .pdf = 4, .mfi = 8, .mfd = 2, @@ -974,6 +974,7 @@ static void __init mxc_board_init(void) mxc_register_device(&sdram_autogating_device, NULL); */ mxc_register_device(&mxc_dvfs_core_device, &dvfs_core_data); + mxc_register_device(&busfreq_device, NULL); /* mxc_register_device(&mxc_dvfs_per_device, &dvfs_per_data); |