summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-mx6/bus_freq.c22
-rw-r--r--arch/arm/mach-mx6/mx6_ddr_freq.S73
-rw-r--r--arch/arm/mach-mx6/mx6_mmdc.c84
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