From: Ranjani Vaidyanathan Date: Wed, 7 Mar 2012 18:48:21 +0000 (-0600) Subject: ENGR00176366: MX6-Switch ARM_CLK to PLL2_400MHz when ARM freq is below 400MHz. X-Git-Tag: v3.0.35-fsl_4.1.0~1413 X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=de7c481845a80c730d46cb8791df2eeb1b836e46;p=karo-tx-linux.git ENGR00176366: MX6-Switch ARM_CLK to PLL2_400MHz when ARM freq is below 400MHz. PLL1 can be disabled whenever ARM_CLK is below 400MHz since ARM_CLK can be sourced from PLL2_PFD_400MHz. Signed-off-by: Ranjani Vaidyanathan --- diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index d48856be60cf..fa99bb6015e0 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "crm_regs.h" #include "cpu_op-mx6.h" #include "regs-anadig.h" @@ -51,6 +53,9 @@ void __iomem *apll_base; static struct clk pll1_sys_main_clk; static struct clk pll2_528_bus_main_clk; static struct clk pll2_pfd_400M; +static struct clk pll2_pfd_352M; +static struct clk pll3_pfd_540M; +static struct clk pll2_pfd_594M; static struct clk pll3_usb_otg_main_clk; static struct clk pll4_audio_main_clk; static struct clk pll5_video_main_clk; @@ -64,11 +69,14 @@ static struct clk usdhc3_clk; static struct cpu_op *cpu_op_tbl; static int cpu_op_nr; +static bool pll1_enabled; +static bool arm_needs_pll2_400; #define SPIN_DELAY 1200000 /* in nanoseconds */ #define AUDIO_VIDEO_MIN_CLK_FREQ 650000000 #define AUDIO_VIDEO_MAX_CLK_FREQ 1300000000 +DEFINE_SPINLOCK(clk_lock); /* We need to check the exp status again after timer expiration, * as there might be interrupt coming between the first time exp @@ -192,6 +200,7 @@ static void _clk_disable_inwait(struct clk *clk) __raw_writel(reg, clk->enable_reg); } + /* * For the 4-to-1 muxed input clock */ @@ -512,13 +521,25 @@ static int _clk_pll1_main_set_rate(struct clk *clk, unsigned long rate) return 0; } +static void _clk_pll1_disable(struct clk *clk) +{ + pll1_enabled = false; + _clk_pll_disable(clk); +} + +static int _clk_pll1_enable(struct clk *clk) +{ + _clk_pll_enable(clk); + pll1_enabled = true; +} + static struct clk pll1_sys_main_clk = { __INIT_CLK_DEBUG(pll1_sys_main_clk) .parent = &osc_clk, .get_rate = _clk_pll1_main_get_rate, .set_rate = _clk_pll1_main_set_rate, - .enable = _clk_pll_enable, - .disable = _clk_pll_disable, + .enable = _clk_pll1_enable, + .disable = _clk_pll1_disable, }; static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent) @@ -545,7 +566,6 @@ static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent) reg = __raw_readl(MXC_CCM_CCSR); reg |= MXC_CCM_CCSR_STEP_SEL; __raw_writel(reg, MXC_CCM_CCSR); - } reg = __raw_readl(MXC_CCM_CCSR); reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL; @@ -610,13 +630,19 @@ static struct clk pll2_528_bus_main_clk = { .disable = _clk_pll_disable, }; +static void _clk_pll2_pfd_400M_disable(struct clk *clk) +{ + if (!arm_needs_pll2_400) + _clk_pfd_disable(clk); +} + static struct clk pll2_pfd_400M = { __INIT_CLK_DEBUG(pll2_pfd_400M) .parent = &pll2_528_bus_main_clk, .enable_reg = (void *)PFD_528_BASE_ADDR, .enable_shift = ANADIG_PFD2_FRAC_OFFSET, .enable = _clk_pfd_enable, - .disable = _clk_pfd_disable, + .disable = _clk_pll2_pfd_400M_disable, .get_rate = pfd_get_rate, .set_rate = pfd_set_rate, .get_rate = pfd_get_rate, @@ -1152,8 +1178,8 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) { int i; u32 div; - u32 parent_rate; - + unsigned long parent_rate; + unsigned long flags; for (i = 0; i < cpu_op_nr; i++) { if (rate == cpu_op_tbl[i].cpu_rate) @@ -1162,30 +1188,67 @@ static int _clk_arm_set_rate(struct clk *clk, unsigned long rate) if (i >= cpu_op_nr) return -EINVAL; - if (cpu_op_tbl[i].pll_rate != clk_get_rate(&pll1_sys_main_clk)) { - /* Change the PLL1 rate. */ - if (pll2_pfd_400M.usecount != 0) + spin_lock_irqsave(&clk_lock, flags); + + if (rate <= clk_get_rate(&pll2_pfd_400M)) { + /* Source pll1_sw_clk from step_clk which is sourced from + * PLL2_PFD_400M. + */ + if (pll1_sw_clk.parent != &pll2_pfd_400M) { + pll2_pfd_400M.enable(&pll2_pfd_400M); + arm_needs_pll2_400 = true; pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd_400M); - else - pll1_sw_clk.set_parent(&pll1_sw_clk, &osc_clk); - pll1_sys_main_clk.set_rate(&pll1_sys_main_clk, cpu_op_tbl[i].pll_rate); - pll1_sw_clk.set_parent(&pll1_sw_clk, &pll1_sys_main_clk); + pll1_sw_clk.parent = &pll2_pfd_400M; + } + } else { + if (pll1_sw_clk.parent != &pll1_sys_main_clk) { + /* pll1_sw_clk was being sourced from pll2_400M. */ + /* Enable PLL1 and set pll1_sw_clk parent as PLL1 */ + if (!pll1_enabled) + pll1_sys_main_clk.enable(&pll1_sys_main_clk); + pll1_sw_clk.set_parent(&pll1_sw_clk, &pll1_sys_main_clk); + pll1_sw_clk.parent = &pll1_sys_main_clk; + arm_needs_pll2_400 = false; + if (pll2_pfd_400M.usecount == 0) + pll2_pfd_400M.disable(&pll2_pfd_400M); + } + if (cpu_op_tbl[i].pll_rate != clk_get_rate(&pll1_sys_main_clk)) { + /* Change the PLL1 rate. */ + if (pll2_pfd_400M.usecount != 0) + pll1_sw_clk.set_parent(&pll1_sw_clk, &pll2_pfd_400M); + else + pll1_sw_clk.set_parent(&pll1_sw_clk, &osc_clk); + pll1_sys_main_clk.set_rate(&pll1_sys_main_clk, cpu_op_tbl[i].pll_rate); + pll1_sw_clk.set_parent(&pll1_sw_clk, &pll1_sys_main_clk); + } } - parent_rate = clk_get_rate(clk->parent); div = parent_rate / rate; - if (div == 0) div = 1; if ((parent_rate / div) > rate) div++; - if (div > 8) + if (div > 8) { + spin_unlock_irqrestore(&clk_lock, flags); return -1; + } + + /* Need PLL1-MAIN to be ON to write to ARM-PODF bit. */ + if (!pll1_enabled) + pll1_sys_main_clk.enable(&pll1_sys_main_clk); __raw_writel(div - 1, MXC_CCM_CACRR); + while (__raw_readl(MXC_CCM_CDHIPR)) + ; + + if (pll1_sys_main_clk.usecount == 1 && arm_needs_pll2_400) + pll1_sys_main_clk.disable(&pll1_sys_main_clk); + + spin_unlock_irqrestore(&clk_lock, flags); + return 0; } @@ -1871,7 +1934,6 @@ static struct clk gpt_clk[] = { .enable = _clk_enable, .disable = _clk_disable, .get_rate = _clk_gpt_get_rate, - .secondary = &gpt_clk[1], }, { __INIT_CLK_DEBUG(gpt_serial_clk) @@ -2007,6 +2069,7 @@ static struct clk vpu_clk[] = { .set_rate = _clk_vpu_axi_set_rate, .get_rate = _clk_vpu_axi_get_rate, .secondary = &vpu_clk[1], + .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, }, { .parent = &mmdc_ch0_axi_clk[0], @@ -2016,7 +2079,6 @@ static struct clk vpu_clk[] = { .parent = &mx6fast1_clk, .secondary = &ocram_clk, }, - }; static int _clk_ipu1_set_parent(struct clk *clk, struct clk *parent) @@ -2097,7 +2159,7 @@ static struct clk ipu1_clk = { .round_rate = _clk_ipu_round_rate, .set_rate = _clk_ipu1_set_rate, .get_rate = _clk_ipu1_get_rate, - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static int _clk_ipu2_set_parent(struct clk *clk, struct clk *parent) @@ -2158,7 +2220,7 @@ static struct clk ipu2_clk = { .round_rate = _clk_ipu_round_rate, .set_rate = _clk_ipu2_set_rate, .get_rate = _clk_ipu2_get_rate, - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static struct clk usdhc_dep_clk = { @@ -2729,7 +2791,7 @@ static struct clk ldb_di0_clk = { .set_rate = _clk_ldb_di0_set_rate, .round_rate = _clk_ldb_di_round_rate, .get_rate = _clk_ldb_di0_get_rate, - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; static unsigned long _clk_ldb_di1_get_rate(struct clk *clk) @@ -2796,7 +2858,7 @@ static struct clk ldb_di1_clk = { .set_rate = _clk_ldb_di1_set_rate, .round_rate = _clk_ldb_di_round_rate, .get_rate = _clk_ldb_di1_get_rate, - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, }; @@ -2989,7 +3051,7 @@ static struct clk ipu1_di_clk[] = { .set_rate = _clk_ipu1_di0_set_rate, .round_rate = _clk_ipu_di_round_rate, .get_rate = _clk_ipu1_di0_get_rate, - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, }, { __INIT_CLK_DEBUG(ipu1_di_clk_1) @@ -3003,7 +3065,7 @@ static struct clk ipu1_di_clk[] = { .set_rate = _clk_ipu1_di1_set_rate, .round_rate = _clk_ipu_di_round_rate, .get_rate = _clk_ipu1_di1_get_rate, - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, }, }; @@ -3166,7 +3228,7 @@ static struct clk ipu2_di_clk[] = { .set_rate = _clk_ipu2_di0_set_rate, .round_rate = _clk_ipu_di_round_rate, .get_rate = _clk_ipu2_di0_get_rate, - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, }, { __INIT_CLK_DEBUG(ipu2_di_clk_1) @@ -3180,7 +3242,7 @@ static struct clk ipu2_di_clk[] = { .set_rate = _clk_ipu2_di1_set_rate, .round_rate = _clk_ipu_di_round_rate, .get_rate = _clk_ipu2_di1_get_rate, - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, }, }; @@ -4254,9 +4316,9 @@ static struct clk gpu3d_core_clk[] = { __INIT_CLK_DEBUG(gpu3d_core_clk) .parent = &pll2_pfd_594M, .enable = _clk_enable, + .disable = _clk_disable, .enable_reg = MXC_CCM_CCGR1, .enable_shift = MXC_CCM_CCGRx_CG13_OFFSET, - .disable = _clk_disable, .set_parent = _clk_gpu3d_core_set_parent, .set_rate = _clk_gpu3d_core_set_rate, .get_rate = _clk_gpu3d_core_get_rate, @@ -4656,7 +4718,7 @@ static struct clk usboh3_clk[] = { .enable_shift = MXC_CCM_CCGRx_CG0_OFFSET, .disable = _clk_disable, .secondary = &usboh3_clk[1], - .flags = AHB_HIGH_SET_POINT | CPU_FREQ_TRIG_UPDATE, + .flags = AHB_MED_SET_POINT | CPU_FREQ_TRIG_UPDATE, }, { .parent = &mmdc_ch0_axi_clk[0], @@ -5084,6 +5146,7 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, unsigned long ckih1, unsigned long ckih2) { __iomem void *base; + unsigned int reg; int i; external_low_reference = ckil; @@ -5201,9 +5264,9 @@ int __init mx6_clocks_init(unsigned long ckil, unsigned long osc, 3 << MXC_CCM_CCGRx_CG9_OFFSET | 3 << MXC_CCM_CCGRx_CG8_OFFSET, MXC_CCM_CCGR2); __raw_writel(1 << MXC_CCM_CCGRx_CG14_OFFSET | - 3 << MXC_CCM_CCGRx_CG13_OFFSET | + 1 << MXC_CCM_CCGRx_CG13_OFFSET | 3 << MXC_CCM_CCGRx_CG12_OFFSET | - 3 << MXC_CCM_CCGRx_CG11_OFFSET | + 1 << MXC_CCM_CCGRx_CG11_OFFSET | 3 << MXC_CCM_CCGRx_CG10_OFFSET, MXC_CCM_CCGR3); __raw_writel(3 << MXC_CCM_CCGRx_CG7_OFFSET | 1 << MXC_CCM_CCGRx_CG6_OFFSET | diff --git a/arch/arm/mach-mx6/cpu_op-mx6.c b/arch/arm/mach-mx6/cpu_op-mx6.c index 4fe3086dd7cc..80b5e055d089 100644 --- a/arch/arm/mach-mx6/cpu_op-mx6.c +++ b/arch/arm/mach-mx6/cpu_op-mx6.c @@ -40,14 +40,14 @@ static struct cpu_op mx6_cpu_op_1_2G[] = { .cpu_rate = 672000000, .cpu_voltage = 1100000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 396000000, - .cpu_podf = 1, + .cpu_podf = 0, .cpu_voltage = 950000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 198000000, - .cpu_podf = 3, + .cpu_podf = 1, .cpu_voltage = 850000,}, }; @@ -68,14 +68,14 @@ static struct cpu_op mx6_cpu_op_1G[] = { .cpu_rate = 672000000, .cpu_voltage = 1100000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 396000000, - .cpu_podf = 1, + .cpu_podf = 0, .cpu_voltage = 950000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 198000000, - .cpu_podf = 3, + .cpu_podf = 1, .cpu_voltage = 850000,}, }; @@ -86,14 +86,14 @@ static struct cpu_op mx6_cpu_op[] = { .cpu_podf = 0, .cpu_voltage = 1100000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 396000000, - .cpu_podf = 1, + .cpu_podf = 0, .cpu_voltage = 950000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 198000000, - .cpu_podf = 3, + .cpu_podf = 1, .cpu_voltage = 850000,}, }; @@ -110,14 +110,14 @@ static struct cpu_op mx6dl_cpu_op_1_2G[] = { .cpu_podf = 0, .cpu_voltage = 1100000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 396000000, - .cpu_podf = 1, + .cpu_podf = 0, .cpu_voltage = 1000000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 198000000, - .cpu_podf = 3, + .cpu_podf = 1, .cpu_voltage = 1000000,}, }; /* working point(wp): 0 - 1GHz; 1 - 800MHz, 2 - 400MHz, 3 - 200MHz */ @@ -133,14 +133,14 @@ static struct cpu_op mx6dl_cpu_op_1G[] = { .cpu_podf = 0, .cpu_voltage = 1100000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 396000000, - .cpu_podf = 1, + .cpu_podf = 0, .cpu_voltage = 1000000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 198000000, - .cpu_podf = 3, + .cpu_podf = 1, .cpu_voltage = 1000000,}, }; @@ -151,35 +151,35 @@ static struct cpu_op mx6dl_cpu_op[] = { .cpu_podf = 0, .cpu_voltage = 1100000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 396000000, - .cpu_podf = 1, + .cpu_podf = 0, .cpu_voltage = 1000000,}, { - .pll_rate = 792000000, + .pll_rate = 396000000, .cpu_rate = 198000000, - .cpu_podf = 3, + .cpu_podf = 1, .cpu_voltage = 1000000,}, }; static struct dvfs_op dvfs_core_setpoint_1_2G[] = { {33, 14, 33, 10, 128, 0x10}, /* 1.2GHz*/ {30, 12, 33, 100, 200, 0x10}, /* 800MHz */ - {28, 12, 33, 100, 200, 0x10}, /* 624MHz */ + {28, 12, 33, 100, 200, 0x10}, /* 672MHz */ {26, 8, 33, 100, 200, 0x10}, /* 400MHz */ {20, 0, 33, 20, 10, 0x10} }; /* 200MHz*/ static struct dvfs_op dvfs_core_setpoint_1G[] = { {33, 14, 33, 10, 128, 0x10}, /* 1GHz*/ {30, 12, 33, 100, 200, 0x10}, /* 800MHz */ - {28, 12, 33, 100, 200, 0x10}, /* 624MHz */ + {28, 12, 33, 100, 200, 0x10}, /* 672MHz */ {26, 8, 33, 100, 200, 0x10}, /* 400MHz */ {20, 0, 33, 20, 10, 0x10} }; /* 200MHz*/ static struct dvfs_op dvfs_core_setpoint[] = { {33, 14, 33, 10, 128, 0x08}, /* 800MHz */ {26, 8, 33, 100, 200, 0x08}, /* 400MHz */ - {20, 0, 33, 20, 10, 0x08} }; /* 200MHz*/ + {20, 0, 33, 100, 10, 0x08} }; /* 200MHz*/ static struct dvfs_op *mx6_get_dvfs_core_table(int *wp) {