diff options
-rw-r--r-- | arch/arm/mach-mx6/bus_freq.c | 22 | ||||
-rw-r--r-- | arch/arm/mach-mx6/mx6_ddr_freq.S | 73 | ||||
-rw-r--r-- | arch/arm/mach-mx6/mx6_mmdc.c | 84 |
3 files changed, 129 insertions, 50 deletions
diff --git a/arch/arm/mach-mx6/bus_freq.c b/arch/arm/mach-mx6/bus_freq.c index 75b9ebdcc7e3..b721bc0479f0 100644 --- a/arch/arm/mach-mx6/bus_freq.c +++ b/arch/arm/mach-mx6/bus_freq.c @@ -111,6 +111,7 @@ static void reduce_bus_freq_handler(struct work_struct *work) mutex_unlock(&bus_freq_mutex); return; } + if (audio_bus_freq_mode && lp_audio_freq) { mutex_unlock(&bus_freq_mutex); return; @@ -131,20 +132,21 @@ static void reduce_bus_freq_handler(struct work_struct *work) low_bus_freq_mode = 1; audio_bus_freq_mode = 0; } + if (med_bus_freq_mode) clk_disable(pll2_400); high_bus_freq_mode = 0; med_bus_freq_mode = 0; - /* Power gate the PU LDO. */ - org_ldo = reg = __raw_readl(ANADIG_REG_CORE); - reg &= ~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET); - __raw_writel(reg, ANADIG_REG_CORE); - - mutex_unlock(&bus_freq_mutex); + if (cpu_is_mx6q()) { + /* Power gate the PU LDO. */ + org_ldo = reg = __raw_readl(ANADIG_REG_CORE); + reg &= ~(ANADIG_REG_TARGET_MASK << ANADIG_REG1_PU_TARGET_OFFSET); + __raw_writel(reg, ANADIG_REG_CORE); + } clk_disable(pll3); - + mutex_unlock(&bus_freq_mutex); } @@ -195,7 +197,7 @@ int set_high_bus_freq(int high_bus_freq) clk_enable(pll3); /* Enable the PU LDO */ - if (low_bus_freq_mode) + if (cpu_is_mx6q() && low_bus_freq_mode) __raw_writel(org_ldo, ANADIG_REG_CORE); if (high_bus_freq) { @@ -215,8 +217,10 @@ int set_high_bus_freq(int high_bus_freq) low_bus_freq_mode = 0; audio_bus_freq_mode = 0; - mutex_unlock(&bus_freq_mutex); + low_bus_freq_mode = 0; + clk_disable(pll3); + mutex_unlock(&bus_freq_mutex); return 0; } diff --git a/arch/arm/mach-mx6/mx6_ddr_freq.S b/arch/arm/mach-mx6/mx6_ddr_freq.S index d73394dd3dc2..85af2a402e68 100644 --- a/arch/arm/mach-mx6/mx6_ddr_freq.S +++ b/arch/arm/mach-mx6/mx6_ddr_freq.S @@ -348,7 +348,7 @@ ddr_freq_change: /* set CON_REG */ ldr r0, =0x8000 - str r0, [r5, #0x1C] + str r0, [r5, #0x1C] poll_conreq_set_1: ldr r0, [r5, #0x1C] and r0, r0, #0x4000 @@ -587,7 +587,7 @@ poll_conreq_clear_1: dll_on_mode: /* assert DVFS - enter self refresh mode */ ldr r0, [r5, #0x404] - orr r0, r0, #0x200000 + orr r0, r0, #0x200000 str r0, [r5, #0x404] /* de-assert CON_REQ */ @@ -632,7 +632,7 @@ poll_dvfs_clear_2: /* if DLL is currently off, turn it back on */ cmp r9, #0 - beq update_calibration + beq update_calibration_only ldr r0, =0xa5390003 str r0, [r5, #0x800] @@ -697,16 +697,17 @@ update_iomux1: @//setmem /32 0x021b0014 = 0x01ff00db @// MMDC0_MDCFG2 - tRRD - 4ck; tWTR - 4ck; tRTP - 4ck; tDLLK - 512ck @//setmem /32 0x021b0018 = 0x00081740 @// MMDC0_MDMISC, RALAT=0x5 (original value) */ + ldr r9, [r8] @size of array + add r8, r8, #8 @skip first eight bytes in array + ldr r0, [r8, #0x0] @ offset + ldr r3, [r8, #0x4] @ value + str r3, [r5, r0] + add r8, r8, #8 - ldr r0, [r5, #0x0C] - bic r0, r0, #0xf - orr r0, r0, #0x5 - str r0, [r5, #0x0C] - - ldr r0, [r5, #0x10] - bic r0, r0, #0x7 - orr r0, r0, #0x4 - str r0, [r5, #0x10] + ldr r0, [r8, #0x0] @ offset + ldr r3, [r8, #0x4] @ value + str r3, [r5, r0] + add r8, r8, #8 /* update MISC register: WALAT, RALAT */ ldr r0, =0x00081740 @@ -762,11 +763,17 @@ cont8: @//setmem /32 0x021b001c = 0x04088032 @//setmem /32 0x021b001c = 0x0408803a */ - ldr r0, =0x04088032 - str r0, [r5, #0x1C] + /* MR2 - CS0 */ + ldr r0, [r8, #0x0] @ offset + ldr r3, [r8, #0x4] @ value + str r3, [r5, r0] + add r8, r8, #8 - ldr r0, =0x0408803a - str r0, [r5, #0x1C] + /*MR2 - CS1 */ + ldr r0, [r8, #0x0] @ offset + ldr r3, [r8, #0x4] @ value + str r3, [r5, r0] + add r8, r8, #8 ldr r0, =0x00428031 str r0, [r5, #0x1C] @@ -778,11 +785,17 @@ cont8: @// setmem /32 0x021b001c = 0x08408030 @// setmem /32 0x021b001c = 0x08408038 */ - ldr r0, =0x08408030 - str r0, [r5, #0x1C] + /* MR1 - CS0 */ + ldr r0, [r8, #0x0] @ offset + ldr r3, [r8, #0x4] @ value + str r3, [r5, r0] + add r8, r8, #8 - ldr r0, =0x08408038 - str r0, [r5, #0x1C] + /*MR1 - CS1 */ + ldr r0, [r8, #0x0] @ offset + ldr r3, [r8, #0x4] @ value + str r3, [r5, r0] + add r8, r8, #8 /* issue a zq command @// setmem /32 0x021b001c = 0x04000040 @@ -798,8 +811,11 @@ cont8: @//setmem /32 0x021b0818 = 0x00022225 @// DDR_PHY_P0_MPODTCTRL @//setmem /32 0x021b4818 = 0x00022225 @// DDR_PHY_P1_MPODTCTRL */ - ldr r0, =0x00022225 - str r0, [r5, #0x818] + ldr r0, [r8, #0x0] @ offset + ldr r3, [r8, #0x4] @ value + str r3, [r5, r0] + add r8, r8, #8 + ldr r2, =0x4818 str r0, [r5, r2] @@ -827,10 +843,19 @@ cont15: orr r0, r0, #0x5500 str r0, [r5, #0x4] + b update_calibration + +update_calibration_only: + ldr r1, [r8] @ size of array + sub r1, r1, #7 @ first 7 entries are not related to calibration + add r8, r8, #64 @ Skip the first 7 entries that are needed only when DLL was OFF + count entry. + b update_calib + update_calibration: /* Write the new calibration values. */ - ldr r1, [r8] @size of array - add r8, r8, #8 @skip first eight bytes in array + mov r1, r9 @ size of array + sub r1, r1, #7 @ first 7 entries are not related to calibration + update_calib: ldr r0, [r8, #0x0] @ offset ldr r3, [r8, #0x4] @ value diff --git a/arch/arm/mach-mx6/mx6_mmdc.c b/arch/arm/mach-mx6/mx6_mmdc.c index 2b5ce842489e..2498f01e0889 100644 --- a/arch/arm/mach-mx6/mx6_mmdc.c +++ b/arch/arm/mach-mx6/mx6_mmdc.c @@ -64,12 +64,22 @@ static int ddr_settings_size; static int iomux_settings_size; static volatile unsigned int cpus_in_wfe; static volatile bool wait_for_ddr_freq_update; - +static int curr_ddr_rate; #define MIN_DLL_ON_FREQ 333000000 #define MAX_DLL_OFF_FREQ 125000000 -unsigned long ddr3_mmdc_regs_offsets[][2] = { +unsigned long ddr3_dll_mx6q[][2] = { + {0x0c, 0x0}, + {0x10, 0x0}, + {0x1C, 0x04088032}, + {0x1C, 0x0408803a}, + {0x1C, 0x08408030}, + {0x1C, 0x08408038}, + {0x818, 0x0}, +}; + +unsigned long ddr3_calibration[][2] = { {0x83c, 0x0}, {0x840, 0x0}, {0x483c, 0x0}, @@ -80,6 +90,16 @@ unsigned long ddr3_mmdc_regs_offsets[][2] = { {0x4850, 0x0}, }; +unsigned long ddr3_dll_mx6dl[][2] = { + {0x0c, 0x0}, + {0x10, 0x0}, + {0x1C, 0x04008032}, + {0x1C, 0x0400803a}, + {0x1C, 0x07208030}, + {0x1C, 0x07208038}, + {0x818, 0x0}, +}; + unsigned long iomux_offsets_mx6q[][2] = { {0x5A8, 0x0}, {0x5B0, 0x0}, @@ -90,6 +110,7 @@ unsigned long iomux_offsets_mx6q[][2] = { {0x5B8, 0x0}, {0x5C0, 0x0}, }; + unsigned long iomux_offsets_mx6dl[][2] = { {0x4BC, 0x0}, {0x4C0, 0x0}, @@ -146,13 +167,14 @@ irqreturn_t wait_in_wfe_irq(int irq, void *dev_id) wfe(); *((char *)(&cpus_in_wfe) + (u8)me) = 0; + return IRQ_HANDLED; } /* Change the DDR frequency. */ int update_ddr_freq(int ddr_rate) { - int i; + int i, j; unsigned int reg; bool dll_off = false; unsigned int online_cpus = 0; @@ -162,17 +184,26 @@ int update_ddr_freq(int ddr_rate) if (!can_change_ddr_freq()) return -1; + if (ddr_rate == curr_ddr_rate) + return 0; + if (low_bus_freq_mode) dll_off = true; iram_ddr_settings[0][0] = ddr_settings_size; iram_iomux_settings[0][0] = iomux_settings_size; - if (ddr_rate == ddr_med_rate) { - for (i = 0; i < iram_ddr_settings[0][0]; i++) { + if (ddr_rate == ddr_med_rate && cpu_is_mx6q()) { + for (i = 0; i < ARRAY_SIZE(ddr3_dll_mx6q); i++) { iram_ddr_settings[i + 1][0] = - ddr3_400[i][0]; + normal_mmdc_settings[i][0]; iram_ddr_settings[i + 1][1] = - ddr3_400[i][1]; + normal_mmdc_settings[i][1]; + } + for (j = 0, i = ARRAY_SIZE(ddr3_dll_mx6q); i < iram_ddr_settings[0][0]; j++, i++) { + iram_ddr_settings[i + 1][0] = + ddr3_400[j][0]; + iram_ddr_settings[i + 1][1] = + ddr3_400[j][1]; } } else if (ddr_rate == ddr_normal_rate) { for (i = 0; i < iram_ddr_settings[0][0]; i++) { @@ -190,7 +221,6 @@ int update_ddr_freq(int ddr_rate) *((char *)(&cpus_in_wfe) + (u8)me) = 0xff; wait_for_ddr_freq_update = true; - for_each_online_cpu(cpu) { *((char *)(&online_cpus) + (u8)cpu) = 0xff; if (cpu != me) { @@ -206,6 +236,8 @@ int update_ddr_freq(int ddr_rate) /* Now we can change the DDR frequency. */ mx6_change_ddr_freq(ddr_rate, iram_ddr_settings, dll_off, iram_iomux_settings); + curr_ddr_rate = ddr_rate; + /* DDR frequency change is done . */ wait_for_ddr_freq_update = false; @@ -229,19 +261,37 @@ int init_mmdc_settings(void) gic_dist_base = ioremap(IC_DISTRIBUTOR_BASE_ADDR, SZ_16K); gic_cpu_base = ioremap(IC_INTERFACES_BASE_ADDR, SZ_16K); - normal_mmdc_settings = ddr3_mmdc_regs_offsets; - ddr_settings_size = ARRAY_SIZE(ddr3_mmdc_regs_offsets); + if (cpu_is_mx6q()) + ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6q) + ARRAY_SIZE(ddr3_calibration); + if (cpu_is_mx6dl()) + ddr_settings_size = ARRAY_SIZE(ddr3_dll_mx6dl) + ARRAY_SIZE(ddr3_calibration); + + normal_mmdc_settings = kmalloc((ddr_settings_size * 8), GFP_KERNEL); + if (cpu_is_mx6q()) { + memcpy(normal_mmdc_settings, ddr3_dll_mx6q, sizeof(ddr3_dll_mx6q)); + memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6q)), ddr3_calibration, sizeof(ddr3_calibration)); + } + if (cpu_is_mx6dl()) { + memcpy(normal_mmdc_settings, ddr3_dll_mx6dl, sizeof(ddr3_dll_mx6dl)); + memcpy(((char *)normal_mmdc_settings + sizeof(ddr3_dll_mx6dl)), ddr3_calibration, sizeof(ddr3_calibration)); + } /* Store the original DDR settings at boot. */ for (i = 0; i < ddr_settings_size; i++) { - normal_mmdc_settings[i][1] = - __raw_readl(mmdc_base - + normal_mmdc_settings[i][0]); + /*Writes via command mode register cannot be read back. + * Hence hardcode them in the initial static array. + * This may require modification on a per customer basis. + */ + if (normal_mmdc_settings[i][0] != 0x1C) + normal_mmdc_settings[i][1] = + __raw_readl(mmdc_base + + normal_mmdc_settings[i][0]); } + /* Store the size of the array in iRAM also, * increase the size by 8 bytes. */ - iram_ddr_settings = iram_alloc(ddr_settings_size + 8, &iram_paddr); + iram_ddr_settings = iram_alloc((ddr_settings_size * 8) + 8, &iram_paddr); if (iram_ddr_settings == NULL) { printk(KERN_DEBUG "%s: failed to allocate iRAM memory for ddr settings\n", @@ -249,10 +299,11 @@ int init_mmdc_settings(void) return ENOMEM; } + iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6q); /* Store the size of the iomux settings in iRAM also, * increase the size by 8 bytes. */ - iram_iomux_settings = iram_alloc(iomux_settings_size + 8, &iram_paddr); + iram_iomux_settings = iram_alloc((iomux_settings_size * 8) + 8, &iram_paddr); if (iram_iomux_settings == NULL) { printk(KERN_DEBUG "%s: failed to allocate iRAM memory for iomuxr settings\n", @@ -262,7 +313,6 @@ int init_mmdc_settings(void) /* Store the IOMUX settings at boot. */ if (cpu_is_mx6q()) { - iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6q); for (i = 0; i < iomux_settings_size; i++) { iomux_offsets_mx6q[i][1] = __raw_readl(iomux_base @@ -272,8 +322,8 @@ int init_mmdc_settings(void) } irq_used = irqs_used_mx6q; } + if (cpu_is_mx6dl()) { - iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6dl); for (i = 0; i < iomux_settings_size; i++) { iomux_offsets_mx6dl[i][1] = __raw_readl(iomux_base |