]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00214810 [MX6]Fix bus freq 50M->528M change issue
authorAnson Huang <b20788@freescale.com>
Mon, 25 Jun 2012 18:18:47 +0000 (02:18 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:34:52 +0000 (08:34 +0200)
50M -> 528M bus freq change will cause system hang, root
cause is that we didn't set 50M as DLL off mode, it should
be DLL off mode.

And make sure bus, axi, ahb, ipg and ipg_perclk are at right
freq during all setpoints.

Can't disable PU LDO again if it is not enabled.

Signed-off-by: Anson Huang <b20788@freescale.com>
arch/arm/mach-mx6/bus_freq.c
arch/arm/mach-mx6/mx6_ddr_freq.S
arch/arm/mach-mx6/mx6_mmdc.c

index 85f23c75d2865a26f2c47c9deff2963d92fa00ca..cd53fde1a3834bc5d451f54a68c1bb75b8555e87 100644 (file)
@@ -175,40 +175,43 @@ static void reduce_bus_freq_handler(struct work_struct *work)
        high_bus_freq_mode = 0;
        med_bus_freq_mode = 0;
 
-       /* Disable the brown out detection since we are going to be
-         * disabling the LDO.
-         */
-       reg = __raw_readl(ANA_MISC2_BASE_ADDR);
-       reg &= ~ANADIG_ANA_MISC2_REG1_BO_EN;
-       __raw_writel(reg, ANA_MISC2_BASE_ADDR);
-
-       /* Power gate the PU LDO. */
-       /* Power gate the PU domain first. */
-       /* enable power down request */
-       reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
-       __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
-       /* power down request */
-       reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
-       __raw_writel(reg | 0x1, gpc_base + GPC_CNTR_OFFSET);
-       /* Wait for power down to complete. */
-       while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x1)
-               ;
-
-       /* Mask the ANATOP brown out interrupt in the GPC. */
-       reg = __raw_readl(gpc_base + 0x14);
-       reg |= 0x80000000;
-       __raw_writel(reg, gpc_base + 0x14);
-
-       /* PU power gating. */
-       org_ldo = reg = __raw_readl(ANADIG_REG_CORE);
-       reg &= ~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
-       __raw_writel(reg, ANADIG_REG_CORE);
-
-       /* Clear the BO interrupt in the ANATOP. */
-       reg = __raw_readl(ANADIG_MISC1_REG);
-       reg |= 0x80000000;
-       __raw_writel(reg, ANADIG_MISC1_REG);
+       /* Do not disable PU LDO if it is not enabled */
+       reg = __raw_readl(ANADIG_REG_CORE) & (ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
+       if ((low_bus_freq_mode || audio_bus_freq_mode) && reg != 0) {
+               /* Disable the brown out detection since we are going to be
+                 * disabling the LDO.
+                 */
+               reg = __raw_readl(ANA_MISC2_BASE_ADDR);
+               reg &= ~ANADIG_ANA_MISC2_REG1_BO_EN;
+               __raw_writel(reg, ANA_MISC2_BASE_ADDR);
 
+               /* Power gate the PU LDO. */
+               /* Power gate the PU domain first. */
+               /* enable power down request */
+               reg = __raw_readl(gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+               __raw_writel(reg | 0x1, gpc_base + GPC_PGC_GPU_PGCR_OFFSET);
+               /* power down request */
+               reg = __raw_readl(gpc_base + GPC_CNTR_OFFSET);
+               __raw_writel(reg | 0x1, gpc_base + GPC_CNTR_OFFSET);
+               /* Wait for power down to complete. */
+               while (__raw_readl(gpc_base + GPC_CNTR_OFFSET) & 0x1)
+                       ;
+
+               /* Mask the ANATOP brown out interrupt in the GPC. */
+               reg = __raw_readl(gpc_base + 0x14);
+               reg |= 0x80000000;
+               __raw_writel(reg, gpc_base + 0x14);
+
+               /* PU power gating. */
+               org_ldo = reg = __raw_readl(ANADIG_REG_CORE);
+               reg &= ~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET);
+               __raw_writel(reg, ANADIG_REG_CORE);
+
+               /* Clear the BO interrupt in the ANATOP. */
+               reg = __raw_readl(ANADIG_MISC1_REG);
+               reg |= 0x80000000;
+               __raw_writel(reg, ANADIG_MISC1_REG);
+       }
        mutex_unlock(&bus_freq_mutex);
 }
 
@@ -261,7 +264,7 @@ int set_high_bus_freq(int high_bus_freq)
        }
 
        /* Enable the PU LDO */
-       if (low_bus_freq_mode) {
+       if (low_bus_freq_mode || audio_bus_freq_mode) {
                /* Set the voltage of VDDSOC as in normal mode. */
                __raw_writel(org_ldo, ANADIG_REG_CORE);
 
index 770b9cf1ba7280f397b5e52578dc2e6c570ab281..19fb49179cfdb12823f00c1f3a99f517053aec8a 100644 (file)
 
        /* Set the AHB dividers before the switch. */
        /* Don't change AXI clock divider. */
-       /* Set the MMDC_DIV=1, AHB_DIV=4 (need to maintain GPT divider). */
+       /* Set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4 (need to maintain GPT divider). */
        ldr     r0, [r6, #0x14]
-       ldr     r2, =0x381D00
+       ldr     r2, =0x3f1f00
        bic     r0, r0, r2
-       orr     r0, r0, #0xD00
+       orr     r0, r0, #0xd00
+       orr     r0, r0, #0x10000
        str     r0, [r6, #0x14]
 
 wait_div_update528:
@@ -72,13 +73,11 @@ set_ahb_podf_before_switch:
          * would be too fast when switching to PLL3.
          */
        /* Don't change AXI clock divider. */
-       /* Set the MMDC_DIV=1, AHB_DIV=4 (need to maintain GPT divider). */
+       /* Set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4 (need to maintain GPT divider). */
        ldr     r0, [r6, #0x14]
-       ldr     r2, =0x381D00
+       ldr     r2, =0x3f1f00
        bic     r0, r0, r2
-       orr     r0, r0, #0xD00
-       /* Make sure AXI clock divider is 1 */
-       bic     r0, r0, #0x70000
+       orr     r0, r0, #0xd00
        orr     r0, r0, #0x10000
        str     r0, [r6, #0x14]
 
@@ -148,11 +147,12 @@ set_ahb_podf_before_switch1:
          * would be too fast when switching to PLL3.
          */
        /* Don't change AXI clock divider. */
-       /* Set the MMDC_DIV=1, AHB_DIV=4 (need to maintain GPT divider). */
+       /* Set the MMDC_DIV=1, AXI_DIV = 2, AHB_DIV=4 (need to maintain GPT divider). */
        ldr     r0, [r6, #0x14]
-       ldr     r2, =0x381D00
+       ldr     r2, =0x3f1f00
        bic     r0, r0, r2
-       orr     r0, r0, #0xD00
+       orr     r0, r0, #0x900
+       orr     r0, r0, #0x10000
        str     r0, [r6, #0x14]
 
 wait_div_update400_1:
@@ -180,13 +180,11 @@ periph_clk_switch6:
 
        /* Change AHB divider so that we are at 400/3=133MHz. */
        /* Don't change AXI clock divider. */
-       /* Set the MMDC_DIV=1, AHB_DIV=3 (need to maintain GPT divider). */
+       /* Set the MMDC_DIV=1, AXI_DIV=2, AHB_DIV=3 (need to maintain GPT divider). */
        ldr     r0, [r6, #0x14]
-       ldr     r2, =0x381D00
+       ldr     r2, =0x3f1f00
        bic     r0, r0, r2
        orr     r0, r0, #0x900
-       /* Make sure AXI clock divider is 1 */
-       bic     r0, r0, #0x70000
        orr     r0, r0, #0x10000
        str     r0, [r6, #0x14]
 
@@ -242,15 +240,15 @@ switch_pre_periph_clk_50:
 
        /* Set the MMDC_DIV=4, AXI_DIV = 4, AHB_DIV=8 (need to maintain GPT divider). */
        ldr     r0, [r6, #0x14]
-       ldr     r2, =0x3F1C00
+       ldr     r2, =0x3f1f00
        bic     r0, r0, r2
 
        orr     r0, r0, #0x180000
        orr     r0, r0, #0x30000
 
        /* If changing AHB divider remember to change the IPGPER divider too below. */
-        orr     r0, r0, #0x1C00
-        str     r0, [r6, #0x14]
+       orr     r0, r0, #0x1d00
+       str     r0, [r6, #0x14]
 
 wait_div_update_50:
        ldr      r0, [r6, #0x48]
@@ -270,7 +268,7 @@ periph_clk_switch2:
        /* Change the GPT divider so that its at 6MHz. */
        ldr     r0, [r6, #0x1C]
        bic     r0, r0, #0x3F
-       orr     r0, r0, #0x3
+       orr     r0, r0, #0x1
        str     r0, [r6, #0x1C]
 
        .endm
@@ -302,8 +300,9 @@ periph_clk_switch1:
 
        /* Change all the dividers to 1. */
        ldr     r0, [r6, #0x14]
-       ldr     r2, =0x3F1C00
+       ldr     r2, =0x3f1f00
        bic     r0, r0, r2
+       orr     r0, r0, #0x100
        str     r0, [r6, #0x14]
 
        /* Wait for the divider to change. */
index c4f232f0e56d5f53107087bdc6f4e4d25d6c98c2..f0771b65209443beb3d8c05034e53bf14930cc0f 100644 (file)
@@ -55,6 +55,7 @@ extern unsigned int ddr_low_rate;
 extern unsigned int ddr_med_rate;
 extern unsigned int ddr_normal_rate;
 extern int low_bus_freq_mode;
+extern int audio_bus_freq_mode;
 extern int mmdc_med_rate;
 extern void __iomem *ccm_base;
 extern void mx6_ddr_freq_change(u32 freq, void *ddr_settings, bool dll_mode, void *iomux_offsets);
@@ -187,7 +188,7 @@ int update_ddr_freq(int ddr_rate)
        if (ddr_rate == curr_ddr_rate)
                return 0;
 
-       if (low_bus_freq_mode)
+       if (low_bus_freq_mode || audio_bus_freq_mode)
                dll_off = true;
 
        iram_ddr_settings[0][0] = ddr_settings_size;