aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-imx/busfreq-imx6.c68
-rw-r--r--arch/arm/mach-imx/busfreq_ddr3.c67
-rw-r--r--arch/arm/mach-imx/busfreq_lpddr2.c16
-rw-r--r--arch/arm/mach-imx/common.h1
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6sl.c12
-rw-r--r--arch/arm/mach-imx/ddr3_freq_imx6.S30
-rw-r--r--arch/arm/mach-imx/ddr3_freq_imx6sx.S33
-rw-r--r--arch/arm/mach-imx/imx6sl_wfi.S34
-rw-r--r--arch/arm/mach-imx/lpddr2_freq_imx6.S32
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c1
-rw-r--r--arch/arm/mach-imx/mach-imx6sl.c3
-rw-r--r--arch/arm/mach-imx/mach-imx6sx.c1
-rw-r--r--arch/arm/mach-imx/mx6.h14
-rw-r--r--arch/arm/mach-imx/pm-imx6.c13
-rw-r--r--arch/arm/mach-imx/suspend-imx6.S33
15 files changed, 261 insertions, 97 deletions
diff --git a/arch/arm/mach-imx/busfreq-imx6.c b/arch/arm/mach-imx/busfreq-imx6.c
index 8e640d39013e..fdd0c40d6b66 100644
--- a/arch/arm/mach-imx/busfreq-imx6.c
+++ b/arch/arm/mach-imx/busfreq-imx6.c
@@ -39,6 +39,7 @@
39#include <linux/module.h> 39#include <linux/module.h>
40#include <linux/mutex.h> 40#include <linux/mutex.h>
41#include <linux/of.h> 41#include <linux/of.h>
42#include <linux/of_fdt.h>
42#include <linux/platform_device.h> 43#include <linux/platform_device.h>
43#include <linux/proc_fs.h> 44#include <linux/proc_fs.h>
44#include <linux/reboot.h> 45#include <linux/reboot.h>
@@ -63,6 +64,9 @@ int low_bus_freq_mode;
63int ultra_low_bus_freq_mode; 64int ultra_low_bus_freq_mode;
64unsigned int ddr_med_rate; 65unsigned int ddr_med_rate;
65unsigned int ddr_normal_rate; 66unsigned int ddr_normal_rate;
67unsigned long ddr_freq_change_total_size;
68unsigned long ddr_freq_change_iram_base;
69unsigned long ddr_freq_change_iram_phys;
66 70
67static int bus_freq_scaling_initialized; 71static int bus_freq_scaling_initialized;
68static struct device *busfreq_dev; 72static struct device *busfreq_dev;
@@ -72,6 +76,9 @@ static int bus_freq_scaling_is_active;
72static int high_bus_count, med_bus_count, audio_bus_count, low_bus_count; 76static int high_bus_count, med_bus_count, audio_bus_count, low_bus_count;
73static unsigned int ddr_low_rate; 77static unsigned int ddr_low_rate;
74 78
79extern unsigned long iram_tlb_phys_addr;
80extern int unsigned long iram_tlb_base_addr;
81
75extern int init_mmdc_lpddr2_settings(struct platform_device *dev); 82extern int init_mmdc_lpddr2_settings(struct platform_device *dev);
76extern int init_mmdc_ddr3_settings_imx6q(struct platform_device *dev); 83extern int init_mmdc_ddr3_settings_imx6q(struct platform_device *dev);
77extern int init_mmdc_ddr3_settings_imx6sx(struct platform_device *dev); 84extern int init_mmdc_ddr3_settings_imx6sx(struct platform_device *dev);
@@ -684,6 +691,63 @@ void release_bus_freq(enum bus_freq_mode mode)
684} 691}
685EXPORT_SYMBOL(release_bus_freq); 692EXPORT_SYMBOL(release_bus_freq);
686 693
694static struct map_desc ddr_iram_io_desc __initdata = {
695 /* .virtual and .pfn are run-time assigned */
696 .length = SZ_1M,
697 .type = MT_MEMORY_NONCACHED,
698};
699
700const static char *ddr_freq_iram_match[] __initconst = {
701 "fsl,ddr-lpm-sram",
702 NULL
703};
704
705static int __init imx6_dt_find_ddr_sram(unsigned long node,
706 const char *uname, int depth, void *data)
707{
708 unsigned long ddr_iram_addr;
709 __be32 *prop;
710
711 if (of_flat_dt_match(node, ddr_freq_iram_match)) {
712 unsigned long len;
713 prop = of_get_flat_dt_prop(node, "reg", &len);
714 if (prop == NULL || len != (sizeof(unsigned long) * 2))
715 return EINVAL;
716 ddr_iram_addr = be32_to_cpu(prop[0]);
717 ddr_freq_change_total_size = be32_to_cpu(prop[1]);
718
719 if ((iram_tlb_phys_addr & 0xFFF00000) != (ddr_iram_addr & 0xFFF00000)) {
720 unsigned long i;
721
722 /* We need to create a 1M page table entry. */
723 ddr_iram_io_desc.virtual = IMX_IO_P2V(ddr_iram_addr & 0xFFF00000);
724 ddr_iram_io_desc.pfn = __phys_to_pfn(ddr_iram_addr & 0xFFF00000);
725 iotable_init(&ddr_iram_io_desc, 1);
726
727 /*
728 * Make sure the ddr_iram virtual address has a mapping
729 * in the IRAM page table.
730 */
731 i = ((IMX_IO_P2V(ddr_iram_addr) >> 20) << 2) / 4;
732 *((unsigned long *)iram_tlb_base_addr + i) =
733 (ddr_iram_addr & 0xFFF00000) | TT_ATTRIB_NON_CACHEABLE_1M;
734
735 }
736 ddr_freq_change_iram_phys = (void *)ddr_iram_addr;
737 ddr_freq_change_iram_base = IMX_IO_P2V(ddr_iram_addr);
738 }
739 return 0;
740}
741
742void __init imx6_busfreq_map_io(void)
743{
744 /*
745 * Get the address of IRAM to be used by the ddr frequency
746 * change code from the device tree.
747 */
748 WARN_ON(of_scan_flat_dt(imx6_dt_find_ddr_sram, NULL));
749}
750
687static void bus_freq_daemon_handler(struct work_struct *work) 751static void bus_freq_daemon_handler(struct work_struct *work)
688{ 752{
689 mutex_lock(&bus_freq_mutex); 753 mutex_lock(&bus_freq_mutex);
@@ -782,6 +846,10 @@ static int busfreq_probe(struct platform_device *pdev)
782 846
783 busfreq_dev = &pdev->dev; 847 busfreq_dev = &pdev->dev;
784 848
849 /* Return if no IRAM space is allocated for ddr freq change code. */
850 if (!ddr_freq_change_iram_base)
851 return ENOMEM;
852
785 pll2_400 = devm_clk_get(&pdev->dev, "pll2_pfd2_396m"); 853 pll2_400 = devm_clk_get(&pdev->dev, "pll2_pfd2_396m");
786 if (IS_ERR(pll2_400)) { 854 if (IS_ERR(pll2_400)) {
787 dev_err(busfreq_dev, "%s: failed to get pll2_pfd2_396m\n", 855 dev_err(busfreq_dev, "%s: failed to get pll2_pfd2_396m\n",
diff --git a/arch/arm/mach-imx/busfreq_ddr3.c b/arch/arm/mach-imx/busfreq_ddr3.c
index e19249dd2265..f2719205097b 100644
--- a/arch/arm/mach-imx/busfreq_ddr3.c
+++ b/arch/arm/mach-imx/busfreq_ddr3.c
@@ -70,7 +70,6 @@ static void __iomem *iomux_base;
70static void __iomem *gic_dist_base; 70static void __iomem *gic_dist_base;
71static u32 *irqs_used; 71static u32 *irqs_used;
72 72
73static void *ddr_freq_change_iram_base;
74static int ddr_settings_size; 73static int ddr_settings_size;
75static int iomux_settings_size; 74static int iomux_settings_size;
76static volatile unsigned int cpus_in_wfe; 75static volatile unsigned int cpus_in_wfe;
@@ -91,7 +90,12 @@ extern void mx6_ddr3_freq_change(u32 freq, void *ddr_settings,
91 bool dll_mode, void *iomux_offsets); 90 bool dll_mode, void *iomux_offsets);
92extern unsigned long save_ttbr1(void); 91extern unsigned long save_ttbr1(void);
93extern void restore_ttbr1(unsigned long ttbr1); 92extern void restore_ttbr1(unsigned long ttbr1);
94extern unsigned long iram_tlb_phys_addr; 93extern unsigned long ddr_freq_change_iram_base;
94extern unsigned long ddr_freq_change_total_size;
95extern unsigned long mx6_ddr3_freq_change_start asm("mx6_ddr3_freq_change_start");
96extern unsigned long mx6_ddr3_freq_change_end asm("mx6_ddr3_freq_change_end");
97extern unsigned long imx6sx_ddr3_freq_change_start asm("imx6sx_ddr3_freq_change_start");
98extern unsigned long imx6sx_ddr3_freq_change_end asm("imx6sx_ddr3_freq_change_end");
95 99
96#define MIN_DLL_ON_FREQ 333000000 100#define MIN_DLL_ON_FREQ 333000000
97#define MAX_DLL_OFF_FREQ 125000000 101#define MAX_DLL_OFF_FREQ 125000000
@@ -343,6 +347,7 @@ int init_mmdc_ddr3_settings_imx6sx(struct platform_device *busfreq_pdev)
343{ 347{
344 int i; 348 int i;
345 struct device_node *node; 349 struct device_node *node;
350 unsigned long ddr_code_size;
346 351
347 node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc"); 352 node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc");
348 if (!node) { 353 if (!node) {
@@ -384,10 +389,27 @@ int init_mmdc_ddr3_settings_imx6sx(struct platform_device *busfreq_pdev)
384 389
385 iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6sx); 390 iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6sx);
386 391
387 iram_iomux_settings = (void *)IMX_IO_P2V(iram_tlb_phys_addr) + 392 ddr_code_size = (&imx6sx_ddr3_freq_change_end -&imx6sx_ddr3_freq_change_start) *4 +
388 DDR3_IOMUX_SETTINGS_ADDR_OFFSET; 393 sizeof(*imx6sx_busfreq_info);
389 394
395 imx6sx_busfreq_info = (struct imx6_busfreq_info *)ddr_freq_change_iram_base;
396
397 imx6sx_change_ddr_freq = (void *)fncpy((void *)ddr_freq_change_iram_base + sizeof(*imx6sx_busfreq_info),
398 &imx6sx_ddr3_freq_change, ddr_code_size - sizeof(*imx6sx_busfreq_info));
399
400 /*
401 * Store the size of the array in iRAM also,
402 * increase the size by 8 bytes.
403 */
404 iram_iomux_settings = ddr_freq_change_iram_base + ddr_code_size;
390 iram_ddr_settings = iram_iomux_settings + (iomux_settings_size * 8) + 8; 405 iram_ddr_settings = iram_iomux_settings + (iomux_settings_size * 8) + 8;
406
407 if ((ddr_code_size + (iomux_settings_size + ddr_settings_size) * 8 + 16)
408 > ddr_freq_change_total_size) {
409 printk(KERN_ERR "Not enough memory allocated for DDR Frequency change code.\n");
410 return EINVAL;
411 }
412
391 for (i = 0; i < iomux_settings_size; i++) { 413 for (i = 0; i < iomux_settings_size; i++) {
392 iomux_offsets_mx6sx[i][1] = 414 iomux_offsets_mx6sx[i][1] =
393 readl_relaxed(iomux_base + 415 readl_relaxed(iomux_base +
@@ -398,18 +420,6 @@ int init_mmdc_ddr3_settings_imx6sx(struct platform_device *busfreq_pdev)
398 iomux_offsets_mx6sx[i][1]; 420 iomux_offsets_mx6sx[i][1];
399 } 421 }
400 422
401 /* Calculate the virtual address of the code */
402 ddr_freq_change_iram_base =
403 (void *)IMX_IO_P2V(iram_tlb_phys_addr) +
404 DDR3_FREQ_CODE_ADDR_OFFSET;
405
406 imx6sx_busfreq_info = (struct imx6_busfreq_info *)ddr_freq_change_iram_base;
407
408 imx6sx_change_ddr_freq = (void *)fncpy(ddr_freq_change_iram_base +
409 sizeof(*imx6sx_busfreq_info),
410 &imx6sx_ddr3_freq_change,
411 DDR3_FREQ_CODE_SIZE - sizeof(*imx6sx_busfreq_info));
412
413 curr_ddr_rate = ddr_normal_rate; 423 curr_ddr_rate = ddr_normal_rate;
414 424
415 return 0; 425 return 0;
@@ -421,6 +431,7 @@ int init_mmdc_ddr3_settings_imx6q(struct platform_device *busfreq_pdev)
421 int i, err; 431 int i, err;
422 u32 cpu; 432 u32 cpu;
423 struct device_node *node; 433 struct device_node *node;
434 unsigned long ddr_code_size;
424 435
425 node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc-combine"); 436 node = of_find_compatible_node(NULL, NULL, "fsl,imx6q-mmdc-combine");
426 if (!node) { 437 if (!node) {
@@ -516,12 +527,24 @@ int init_mmdc_ddr3_settings_imx6q(struct platform_device *busfreq_pdev)
516 } 527 }
517 iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6q); 528 iomux_settings_size = ARRAY_SIZE(iomux_offsets_mx6q);
518 529
530 ddr_code_size = (&mx6_ddr3_freq_change_end -&mx6_ddr3_freq_change_start) *4;
519 531
520 iram_iomux_settings = (void *)IMX_IO_P2V(iram_tlb_phys_addr) + 532 mx6_change_ddr_freq = (void *)fncpy((void *)ddr_freq_change_iram_base,
521 DDR3_IOMUX_SETTINGS_ADDR_OFFSET; 533 &mx6_ddr3_freq_change, ddr_code_size);
522 534
535 /*
536 * Store the size of the array in iRAM also,
537 * increase the size by 8 bytes.
538 */
539 iram_iomux_settings = ddr_freq_change_iram_base + ddr_code_size;
523 iram_ddr_settings = iram_iomux_settings + (iomux_settings_size * 8) + 8; 540 iram_ddr_settings = iram_iomux_settings + (iomux_settings_size * 8) + 8;
524 541
542 if ((ddr_code_size + (iomux_settings_size + ddr_settings_size) * 8 + 16)
543 > ddr_freq_change_total_size) {
544 printk(KERN_ERR "Not enough memory allocated for DDR Frequency change code.\n");
545 return EINVAL;
546 }
547
525 if (cpu_is_imx6q()) { 548 if (cpu_is_imx6q()) {
526 /* store the IOMUX settings at boot. */ 549 /* store the IOMUX settings at boot. */
527 for (i = 0; i < iomux_settings_size; i++) { 550 for (i = 0; i < iomux_settings_size; i++) {
@@ -543,14 +566,6 @@ int init_mmdc_ddr3_settings_imx6q(struct platform_device *busfreq_pdev)
543 } 566 }
544 } 567 }
545 568
546 /* Calculate the virtual address of the code */
547 ddr_freq_change_iram_base =
548 (void *)IMX_IO_P2V(iram_tlb_phys_addr) +
549 DDR3_FREQ_CODE_ADDR_OFFSET;
550
551 mx6_change_ddr_freq = (void *)fncpy(ddr_freq_change_iram_base,
552 &mx6_ddr3_freq_change, DDR3_FREQ_CODE_SIZE);
553
554 curr_ddr_rate = ddr_normal_rate; 569 curr_ddr_rate = ddr_normal_rate;
555 570
556 return 0; 571 return 0;
diff --git a/arch/arm/mach-imx/busfreq_lpddr2.c b/arch/arm/mach-imx/busfreq_lpddr2.c
index 1e332bf66cbf..5c96885f9fc5 100644
--- a/arch/arm/mach-imx/busfreq_lpddr2.c
+++ b/arch/arm/mach-imx/busfreq_lpddr2.c
@@ -44,7 +44,6 @@
44 44
45 45
46static struct device *busfreq_dev; 46static struct device *busfreq_dev;
47static void *ddr_freq_change_iram_base;
48static int curr_ddr_rate; 47static int curr_ddr_rate;
49static DEFINE_SPINLOCK(freq_lock); 48static DEFINE_SPINLOCK(freq_lock);
50 49
@@ -55,10 +54,11 @@ extern int low_bus_freq_mode;
55extern int ultra_low_bus_freq_mode; 54extern int ultra_low_bus_freq_mode;
56extern void mx6_lpddr2_freq_change(u32 freq, int bus_freq_mode); 55extern void mx6_lpddr2_freq_change(u32 freq, int bus_freq_mode);
57extern void imx6sx_lpddr2_freq_change(u32 freq, int bus_freq_mode); 56extern void imx6sx_lpddr2_freq_change(u32 freq, int bus_freq_mode);
58
59extern unsigned long save_ttbr1(void); 57extern unsigned long save_ttbr1(void);
60extern void restore_ttbr1(unsigned long ttbr1); 58extern void restore_ttbr1(unsigned long ttbr1);
61extern unsigned long iram_tlb_phys_addr; 59extern unsigned long ddr_freq_change_iram_base;
60extern unsigned long imx6_lpddr2_freq_change_start asm("imx6_lpddr2_freq_change_start");
61extern unsigned long imx6_lpddr2_freq_change_end asm("imx6_lpddr2_freq_change_end");
62 62
63/* change the DDR frequency. */ 63/* change the DDR frequency. */
64int update_lpddr2_freq(int ddr_rate) 64int update_lpddr2_freq(int ddr_rate)
@@ -93,20 +93,18 @@ int update_lpddr2_freq(int ddr_rate)
93int init_mmdc_lpddr2_settings(struct platform_device *busfreq_pdev) 93int init_mmdc_lpddr2_settings(struct platform_device *busfreq_pdev)
94{ 94{
95 busfreq_dev = &busfreq_pdev->dev; 95 busfreq_dev = &busfreq_pdev->dev;
96 unsigned long ddr_code_size;
96 97
97 /* Calculate the virtual address of the code */ 98 ddr_code_size = (&imx6_lpddr2_freq_change_end -&imx6_lpddr2_freq_change_start) *4;
98 ddr_freq_change_iram_base =
99 (void *)IMX_IO_P2V(iram_tlb_phys_addr) +
100 MX6SL_LPDDR2_FREQ_ADDR_OFFSET;
101 99
102 if (cpu_is_imx6sl()) 100 if (cpu_is_imx6sl())
103 mx6_change_lpddr2_freq = (void *)fncpy( 101 mx6_change_lpddr2_freq = (void *)fncpy(
104 ddr_freq_change_iram_base, 102 ddr_freq_change_iram_base,
105 &mx6_lpddr2_freq_change, LPDDR2_FREQ_CODE_SIZE); 103 &mx6_lpddr2_freq_change, ddr_code_size);
106 else if (cpu_is_imx6sx()) 104 else if (cpu_is_imx6sx())
107 mx6_change_lpddr2_freq = (void *)fncpy( 105 mx6_change_lpddr2_freq = (void *)fncpy(
108 ddr_freq_change_iram_base, 106 ddr_freq_change_iram_base,
109 &imx6sx_lpddr2_freq_change, LPDDR2_FREQ_CODE_SIZE); 107 &imx6sx_lpddr2_freq_change, ddr_code_size);
110 108
111 curr_ddr_rate = ddr_normal_rate; 109 curr_ddr_rate = ddr_normal_rate;
112 110
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index b0872d986b7a..6f8bac300ca6 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -131,6 +131,7 @@ static inline void imx_smp_prepare(void) {}
131static inline void imx_scu_standby_enable(void) {} 131static inline void imx_scu_standby_enable(void) {}
132#endif 132#endif
133extern void imx6_pm_map_io(void); 133extern void imx6_pm_map_io(void);
134extern void imx6_busfreq_map_io(void);
134extern void imx6_suspend(void); 135extern void imx6_suspend(void);
135extern void imx_src_init(void); 136extern void imx_src_init(void);
136#ifdef CONFIG_HAVE_IMX_SRC 137#ifdef CONFIG_HAVE_IMX_SRC
diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c
index cd4e1fda4e35..412b86aacb86 100644
--- a/arch/arm/mach-imx/cpuidle-imx6sl.c
+++ b/arch/arm/mach-imx/cpuidle-imx6sl.c
@@ -33,6 +33,9 @@ extern void imx6sl_low_power_wfi(void);
33extern unsigned long save_ttbr1(void); 33extern unsigned long save_ttbr1(void);
34extern void restore_ttbr1(unsigned long ttbr1); 34extern void restore_ttbr1(unsigned long ttbr1);
35extern unsigned long iram_tlb_phys_addr; 35extern unsigned long iram_tlb_phys_addr;
36extern unsigned long total_suspend_size;
37extern unsigned long mx6sl_lpm_wfi_start asm("mx6sl_lpm_wfi_start");
38extern unsigned long mx6sl_lpm_wfi_end asm("mx6sl_lpm_wfi_end");
36 39
37static void __iomem *iomux_base; 40static void __iomem *iomux_base;
38static void *wfi_iram_base; 41static void *wfi_iram_base;
@@ -99,6 +102,7 @@ static struct cpuidle_driver imx6sl_cpuidle_driver = {
99int __init imx6sl_cpuidle_init(void) 102int __init imx6sl_cpuidle_init(void)
100{ 103{
101 struct device_node *node; 104 struct device_node *node;
105 u32 wfi_code_size;
102 106
103 node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-iomuxc"); 107 node = of_find_compatible_node(NULL, NULL, "fsl,imx6sl-iomuxc");
104 if (!node) { 108 if (!node) {
@@ -112,12 +116,14 @@ int __init imx6sl_cpuidle_init(void)
112 if (IS_ERR(vbus_ldo)) 116 if (IS_ERR(vbus_ldo))
113 vbus_ldo = NULL; 117 vbus_ldo = NULL;
114 118
115 /* Calculate the virtual address of the code */ 119 wfi_code_size = (&mx6sl_lpm_wfi_end -&mx6sl_lpm_wfi_start) *4;
120
121 /* Get the virtual address of the wfi iram code. */
116 wfi_iram_base = (void *)IMX_IO_P2V(iram_tlb_phys_addr) + 122 wfi_iram_base = (void *)IMX_IO_P2V(iram_tlb_phys_addr) +
117 MX6SL_WFI_IRAM_ADDR_OFFSET; 123 total_suspend_size;
118 124
119 imx6sl_wfi_in_iram_fn = (void *)fncpy(wfi_iram_base, 125 imx6sl_wfi_in_iram_fn = (void *)fncpy(wfi_iram_base,
120 &imx6sl_low_power_wfi, MX6SL_WFI_IRAM_CODE_SIZE); 126 &imx6sl_low_power_wfi, wfi_code_size);
121 127
122 return cpuidle_register(&imx6sl_cpuidle_driver, NULL); 128 return cpuidle_register(&imx6sl_cpuidle_driver, NULL);
123} 129}
diff --git a/arch/arm/mach-imx/ddr3_freq_imx6.S b/arch/arm/mach-imx/ddr3_freq_imx6.S
index 26a601805b8a..25406d45ccb8 100644
--- a/arch/arm/mach-imx/ddr3_freq_imx6.S
+++ b/arch/arm/mach-imx/ddr3_freq_imx6.S
@@ -43,6 +43,8 @@
43#define L2_CACHE_SYNC 0x730 43#define L2_CACHE_SYNC 0x730
44 44
45.extern iram_tlb_phys_addr 45.extern iram_tlb_phys_addr
46.globl mx6_ddr3_freq_change_start
47.globl mx6_ddr3_freq_change_end
46 48
47 .align 3 49 .align 3
48 50
@@ -331,6 +333,7 @@ wait_div_update:
331 */ 333 */
332ENTRY(mx6_ddr3_freq_change) 334ENTRY(mx6_ddr3_freq_change)
333 335
336mx6_ddr3_freq_change_start:
334 stmfd sp!, {r4-r12} 337 stmfd sp!, {r4-r12}
335 338
336 /* 339 /*
@@ -344,7 +347,6 @@ ENTRY(mx6_ddr3_freq_change)
344 mov r9, r2 347 mov r9, r2
345 mov r11, r3 348 mov r11, r3
346 349
347ddr_freq_change:
348 /* 350 /*
349 * To ensure no page table walks occur in DDR, we 351 * To ensure no page table walks occur in DDR, we
350 * have a another page table stored in IRAM that only 352 * have a another page table stored in IRAM that only
@@ -361,15 +363,15 @@ ddr_freq_change:
361 ldr r6, =iram_tlb_phys_addr 363 ldr r6, =iram_tlb_phys_addr
362 ldr r7, [r6] 364 ldr r7, [r6]
363 365
364 /* Flush the Branch Target Address Cache (BTAC) */
365 ldr r6, =0x0
366 mcr p15, 0, r6, c7, c1, 6
367
368 /* Disable Branch Prediction, Z bit in SCTLR. */ 366 /* Disable Branch Prediction, Z bit in SCTLR. */
369 mrc p15, 0, r6, c1, c0, 0 367 mrc p15, 0, r6, c1, c0, 0
370 bic r6, r6, #0x800 368 bic r6, r6, #0x800
371 mcr p15, 0, r6, c1, c0, 0 369 mcr p15, 0, r6, c1, c0, 0
372 370
371 /* Flush the Branch Target Address Cache (BTAC) */
372 ldr r6, =0x0
373 mcr p15, 0, r6, c7, c1, 6
374
373 dsb 375 dsb
374 isb 376 isb
375 377
@@ -402,6 +404,13 @@ ddr_freq_change:
402 * Sync operation on L2 drains the buffers. 404 * Sync operation on L2 drains the buffers.
403 */ 405 */
404 ldr r12, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR) 406 ldr r12, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
407
408 /* Wait for background operations to complete. */
409wait_for_l2_to_idle:
410 ldr r1, [r12, #L2_CACHE_SYNC]
411 cmp r1, #0x0
412 bne wait_for_l2_to_idle
413
405 mov r1, #0x0 414 mov r1, #0x0
406 str r1, [r12, #L2_CACHE_SYNC] 415 str r1, [r12, #L2_CACHE_SYNC]
407 416
@@ -955,7 +964,10 @@ done:
955 ldmfd sp!, {r4-r12} 964 ldmfd sp!, {r4-r12}
956 mov pc, lr 965 mov pc, lr
957 966
958 .type mx6_do_ddr3_freq_change, #object 967 /*
959ENTRY(mx6_do_ddr_freq_change) 968 * Add ltorg here to ensure that all
960 .word mx6_ddr3_freq_change 969 * literals are stored here and are
961 .size mx6_ddr3_freq_change, . - mx6_ddr3_freq_change 970 * within the text space.
971 */
972 .ltorg
973mx6_ddr3_freq_change_end:
diff --git a/arch/arm/mach-imx/ddr3_freq_imx6sx.S b/arch/arm/mach-imx/ddr3_freq_imx6sx.S
index 152740fd3ffd..c63bf570100d 100644
--- a/arch/arm/mach-imx/ddr3_freq_imx6sx.S
+++ b/arch/arm/mach-imx/ddr3_freq_imx6sx.S
@@ -19,6 +19,9 @@
19#include <linux/linkage.h> 19#include <linux/linkage.h>
20#include "hardware.h" 20#include "hardware.h"
21 21
22.globl imx6sx_ddr3_freq_change_start
23.globl imx6sx_ddr3_freq_change_end
24
22#define MMDC0_MDPDC 0x4 25#define MMDC0_MDPDC 0x4
23#define MMDC0_MDCF0 0xc 26#define MMDC0_MDCF0 0xc
24#define MMDC0_MDCF1 0x10 27#define MMDC0_MDCF1 0x10
@@ -204,13 +207,13 @@ skip_periph2_clk2_switch_50m:
204 */ 207 */
205ENTRY(imx6sx_ddr3_freq_change) 208ENTRY(imx6sx_ddr3_freq_change)
206 209
210imx6sx_ddr3_freq_change_start:
207 stmfd sp!, {r4 - r11} 211 stmfd sp!, {r4 - r11}
208 212
209 ldr r1, [r0, #BUSFREQ_INFO_DDR_SETTINGS_OFFSET] 213 ldr r1, [r0, #BUSFREQ_INFO_DDR_SETTINGS_OFFSET]
210 ldr r2, [r0, #BUSFREQ_INFO_DLL_OFF_OFFSET] 214 ldr r2, [r0, #BUSFREQ_INFO_DLL_OFF_OFFSET]
211 ldr r3, [r0, #BUSFREQ_INFO_IOMUX_OFFSETS_OFFSET] 215 ldr r3, [r0, #BUSFREQ_INFO_IOMUX_OFFSETS_OFFSET]
212 216
213ddr_freq_change:
214 /* 217 /*
215 * To ensure no page table walks occur in DDR, we 218 * To ensure no page table walks occur in DDR, we
216 * have a another page table stored in IRAM that only 219 * have a another page table stored in IRAM that only
@@ -224,17 +227,17 @@ ddr_freq_change:
224 * and 2-4G is translated by TTBR1. 227 * and 2-4G is translated by TTBR1.
225 */ 228 */
226 229
230 /* Disable Branch Prediction, Z bit in SCTLR. */
231 mrc p15, 0, r7, c1, c0, 0
232 bic r7, r7, #0x800
233 mcr p15, 0, r7, c1, c0, 0
234
227 /* Flush the Branch Target Address Cache (BTAC) */ 235 /* Flush the Branch Target Address Cache (BTAC) */
228 ldr r6, =0x0 236 ldr r6, =0x0
229 mcr p15, 0, r6, c7, c1, 6 237 mcr p15, 0, r6, c7, c1, 6
230 ldr r6, =iram_tlb_phys_addr 238 ldr r6, =iram_tlb_phys_addr
231 ldr r6, [r6] 239 ldr r6, [r6]
232 240
233 /* Disable Branch Prediction, Z bit in SCTLR. */
234 mrc p15, 0, r7, c1, c0, 0
235 bic r7, r7, #0x800
236 mcr p15, 0, r7, c1, c0, 0
237
238 dsb 241 dsb
239 isb 242 isb
240 243
@@ -270,12 +273,15 @@ ddr_freq_change:
270 * sync operation on L2 drains the buffers. 273 * sync operation on L2 drains the buffers.
271 */ 274 */
272 ldr r8, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR) 275 ldr r8, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
276
277 /* Wait for background operations to complete. */
278wait_for_l2_to_idle:
279 ldr r7, [r8, #0x730]
280 cmp r7, #0x0
281 bne wait_for_l2_to_idle
282
273 mov r7, #0x0 283 mov r7, #0x0
274 str r7, [r8, #L2_CACHE_SYNC] 284 str r7, [r8, #L2_CACHE_SYNC]
275l2:
276 ldr r7, [r8, #L2_CACHE_SYNC]
277 ands r7, r7, #0x1
278 bne l2
279 285
280 /* Disable L2. */ 286 /* Disable L2. */
281 mov r7, #0x0 287 mov r7, #0x0
@@ -719,4 +725,11 @@ done:
719 ldmfd sp!, {r4 - r11} 725 ldmfd sp!, {r4 - r11}
720 mov pc, lr 726 mov pc, lr
721 727
728 /*
729 * Add ltorg here to ensure that all
730 * literals are stored here and are
731 * within the text space.
732 */
733 .ltorg
734imx6sx_ddr3_freq_change_end:
722ENDPROC(imx6sx_ddr3_freq_change) 735ENDPROC(imx6sx_ddr3_freq_change)
diff --git a/arch/arm/mach-imx/imx6sl_wfi.S b/arch/arm/mach-imx/imx6sl_wfi.S
index e4ce82faaa8e..4bd0a86f11b4 100644
--- a/arch/arm/mach-imx/imx6sl_wfi.S
+++ b/arch/arm/mach-imx/imx6sl_wfi.S
@@ -20,6 +20,8 @@
20#include "hardware.h" 20#include "hardware.h"
21 21
22.extern iram_tlb_phys_addr 22.extern iram_tlb_phys_addr
23.globl mx6sl_lpm_wfi_start
24.globl mx6sl_lpm_wfi_end
23 25
24 .macro sl_ddr_io_save 26 .macro sl_ddr_io_save
25 27
@@ -161,9 +163,10 @@ fifo_reset2_wait:
161 .align 3 163 .align 3
162ENTRY(imx6sl_low_power_wfi) 164ENTRY(imx6sl_low_power_wfi)
163 165
166mx6sl_lpm_wfi_start:
167
164 push {r4-r12} 168 push {r4-r12}
165 169
166mx6sl_lpm_wfi:
167 /* Can LDO2p5 be disabled */ 170 /* Can LDO2p5 be disabled */
168 mov r12, r1 171 mov r12, r1
169 /* Store audio_bus_freq_mode */ 172 /* Store audio_bus_freq_mode */
@@ -172,7 +175,8 @@ mx6sl_lpm_wfi:
172 /* Get the IRAM data storage address. */ 175 /* Get the IRAM data storage address. */
173 mov r10, r0 176 mov r10, r0
174 mov r9, r0 /* get wfi_iram_base */ 177 mov r9, r0 /* get wfi_iram_base */
175 add r9, r9, #MX6SL_WFI_IRAM_CODE_SIZE 178 adrl r4, mx6sl_lpm_wfi_end
179 add r9, r4, #MX6SL_WFI_IRAM_DATA_SIZE
176 180
177 /* 181 /*
178 * To ensure no page table walks occur in DDR, we 182 * To ensure no page table walks occur in DDR, we
@@ -190,15 +194,15 @@ mx6sl_lpm_wfi:
190 ldr r6, =iram_tlb_phys_addr 194 ldr r6, =iram_tlb_phys_addr
191 ldr r7, [r6] 195 ldr r7, [r6]
192 196
193 /* Flush the BTAC. */
194 ldr r6, =0x0
195 mcr p15, 0, r6, c7, c1, 6
196
197 /* Disable Branch Prediction, Z bit in SCTLR. */ 197 /* Disable Branch Prediction, Z bit in SCTLR. */
198 mrc p15, 0, r6, c1, c0, 0 198 mrc p15, 0, r6, c1, c0, 0
199 bic r6, r6, #0x800 199 bic r6, r6, #0x800
200 mcr p15, 0, r6, c1, c0, 0 200 mcr p15, 0, r6, c1, c0, 0
201 201
202 /* Flush the BTAC. */
203 ldr r6, =0x0
204 mcr p15, 0, r6, c7, c1, 6
205
202 dsb 206 dsb
203 isb 207 isb
204 208
@@ -231,6 +235,13 @@ mx6sl_lpm_wfi:
231 * Performing a sync operation does this. 235 * Performing a sync operation does this.
232 */ 236 */
233 ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR) 237 ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
238
239 /* Wait for background operations to complete. */
240wait_for_l2_to_idle:
241 ldr r6, [r7, #0x730]
242 cmp r6, #0x0
243 bne wait_for_l2_to_idle
244
234 mov r6, #0x0 245 mov r6, #0x0
235 str r6, [r7, #0x730] 246 str r6, [r7, #0x730]
236 247
@@ -609,8 +620,8 @@ audio_arm_clk_restore:
609 620
610wfi_restore: 621wfi_restore:
611 /* get wfi_iram_base */ 622 /* get wfi_iram_base */
612 mov r9, r10 623 adrl r9, mx6sl_lpm_wfi_end
613 add r9, r9, #MX6SL_WFI_IRAM_CODE_SIZE 624 add r9, r9, #MX6SL_WFI_IRAM_DATA_SIZE
614 625
615 /* Restore the DDR IO before exiting self-refresh. */ 626 /* Restore the DDR IO before exiting self-refresh. */
616 sl_ddr_io_restore 627 sl_ddr_io_restore
@@ -732,3 +743,10 @@ poll_dvfs_clear_1:
732 743
733 /* Restore registers */ 744 /* Restore registers */
734 mov pc, lr 745 mov pc, lr
746 /*
747 * Add ltorg here to ensure that all
748 * literals are stored here and are
749 * within the text space.
750 */
751 .ltorg
752mx6sl_lpm_wfi_end:
diff --git a/arch/arm/mach-imx/lpddr2_freq_imx6.S b/arch/arm/mach-imx/lpddr2_freq_imx6.S
index 121a88bb62e8..8ed95fe57c1d 100644
--- a/arch/arm/mach-imx/lpddr2_freq_imx6.S
+++ b/arch/arm/mach-imx/lpddr2_freq_imx6.S
@@ -19,6 +19,9 @@
19#include <linux/linkage.h> 19#include <linux/linkage.h>
20#include "hardware.h" 20#include "hardware.h"
21 21
22.globl imx6_lpddr2_freq_change_start
23.globl imx6_lpddr2_freq_change_end
24
22 .macro mx6sl_switch_to_24MHz 25 .macro mx6sl_switch_to_24MHz
23 26
24 /* 27 /*
@@ -343,7 +346,7 @@ force_measure1:
343 */ 346 */
344 .align 3 347 .align 3
345ENTRY(mx6_lpddr2_freq_change) 348ENTRY(mx6_lpddr2_freq_change)
346 349imx6_lpddr2_freq_change_start:
347 push {r4-r10} 350 push {r4-r10}
348 351
349 /* 352 /*
@@ -362,16 +365,15 @@ ENTRY(mx6_lpddr2_freq_change)
362 ldr r6, =iram_tlb_phys_addr 365 ldr r6, =iram_tlb_phys_addr
363 ldr r7, [r6] 366 ldr r7, [r6]
364 367
365
366 /* Flush the Branch Target Address Cache (BTAC) */
367 ldr r6, =0x0
368 mcr p15, 0, r6, c7, c1, 6
369
370 /* Disable Branch Prediction, Z bit in SCTLR. */ 368 /* Disable Branch Prediction, Z bit in SCTLR. */
371 mrc p15, 0, r6, c1, c0, 0 369 mrc p15, 0, r6, c1, c0, 0
372 bic r6, r6, #0x800 370 bic r6, r6, #0x800
373 mcr p15, 0, r6, c1, c0, 0 371 mcr p15, 0, r6, c1, c0, 0
374 372
373 /* Flush the Branch Target Address Cache (BTAC) */
374 ldr r6, =0x0
375 mcr p15, 0, r6, c7, c1, 6
376
375 dsb 377 dsb
376 isb 378 isb
377 /* Store the IRAM table in TTBR1 */ 379 /* Store the IRAM table in TTBR1 */
@@ -404,6 +406,13 @@ ENTRY(mx6_lpddr2_freq_change)
404 * Performing a sync operation does this. 406 * Performing a sync operation does this.
405 */ 407 */
406 ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR) 408 ldr r7, =IMX_IO_P2V(MX6Q_L2_BASE_ADDR)
409
410 /* Wait for background operations to complete. */
411wait_for_l2_to_idle:
412 ldr r6, [r7, #0x730]
413 cmp r6, #0x0
414 bne wait_for_l2_to_idle
415
407 mov r6, #0x0 416 mov r6, #0x0
408 str r6, [r7, #0x730] 417 str r6, [r7, #0x730]
409 418
@@ -589,7 +598,10 @@ skip_power_down:
589 /* Restore registers */ 598 /* Restore registers */
590 mov pc, lr 599 mov pc, lr
591 600
592 .type mx6_lpddr2_do_iram, #object 601 /*
593ENTRY(mx6_lpddr2_do_iram) 602 * Add ltorg here to ensure that all
594 .word mx6_lpddr2_freq_change 603 * literals are stored here and are
595 .size mx6_lpddr2_freq_change, . - mx6_lpddr2_freq_change 604 * within the text space.
605 */
606 .ltorg
607imx6_lpddr2_freq_change_end:
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 4808ebbff9ac..05366ad2e9e8 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -489,6 +489,7 @@ static void __init imx6q_map_io(void)
489 debug_ll_io_init(); 489 debug_ll_io_init();
490 imx_scu_map_io(); 490 imx_scu_map_io();
491 imx6_pm_map_io(); 491 imx6_pm_map_io();
492 imx6_busfreq_map_io();
492} 493}
493 494
494static void __init imx6q_init_irq(void) 495static void __init imx6q_init_irq(void)
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index 78090b430dd7..283031d28aa8 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2013 Freescale Semiconductor, Inc. 2 * Copyright (C) 2013-2014 Freescale Semiconductor, Inc.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as 5 * it under the terms of the GNU General Public License version 2 as
@@ -117,6 +117,7 @@ static void __init imx6sl_map_io(void)
117{ 117{
118 debug_ll_io_init(); 118 debug_ll_io_init();
119 imx6_pm_map_io(); 119 imx6_pm_map_io();
120 imx6_busfreq_map_io();
120} 121}
121 122
122static void __init imx6sl_init_irq(void) 123static void __init imx6sl_init_irq(void)
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 5d6e50d28b2a..1c9b005cc56f 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -310,6 +310,7 @@ static void __init imx6sx_map_io(void)
310{ 310{
311 debug_ll_io_init(); 311 debug_ll_io_init();
312 imx6_pm_map_io(); 312 imx6_pm_map_io();
313 imx6_busfreq_map_io();
313} 314}
314 315
315#define MX6SX_SRC_SMBR_L2_AS_OCRAM_MASK 0x100 316#define MX6SX_SRC_SMBR_L2_AS_OCRAM_MASK 0x100
diff --git a/arch/arm/mach-imx/mx6.h b/arch/arm/mach-imx/mx6.h
index 477c523745a2..54aa28e47151 100644
--- a/arch/arm/mach-imx/mx6.h
+++ b/arch/arm/mach-imx/mx6.h
@@ -37,19 +37,11 @@
37 37
38#define MX6SX_IRAM_TLB_BASE_ADDR 0x008f8000 38#define MX6SX_IRAM_TLB_BASE_ADDR 0x008f8000
39#define MX6Q_IRAM_TLB_BASE_ADDR 0x00900000 39#define MX6Q_IRAM_TLB_BASE_ADDR 0x00900000
40#define MX6Q_IRAM_TLB_SIZE 0x100000 40#define MX6Q_IRAM_TLB_SIZE 0x4000
41#define TT_ATTRIB_NON_CACHEABLE_1M 0x802 41#define TT_ATTRIB_NON_CACHEABLE_1M 0x802
42 42
43#define MX6_SUSPEND_IRAM_SIZE 0x1000 43#define MX6_SUSPEND_IRAM_DATA_SIZE 256
44#define LPDDR2_FREQ_CODE_SIZE 0x600 44#define MX6SL_WFI_IRAM_DATA_SIZE 100
45#define DDR3_FREQ_CODE_SIZE 0xC00
46#define DDR3_IOMUX_SETTINGS_SIZE 0x400
47#define MX6SL_WFI_IRAM_CODE_SIZE 0x700
48 45
49#define MX6_SUSPEND_IRAM_ADDR_OFFSET 0 46#define MX6_SUSPEND_IRAM_ADDR_OFFSET 0
50#define DDR3_FREQ_CODE_ADDR_OFFSET (MX6_SUSPEND_IRAM_ADDR_OFFSET + MX6_SUSPEND_IRAM_SIZE)
51#define DDR3_IOMUX_SETTINGS_ADDR_OFFSET (DDR3_FREQ_CODE_ADDR_OFFSET + DDR3_FREQ_CODE_SIZE)
52#define MX6SL_LPDDR2_FREQ_ADDR_OFFSET (MX6_SUSPEND_IRAM_ADDR_OFFSET + MX6_SUSPEND_IRAM_SIZE)
53#define MX6SL_WFI_IRAM_ADDR_OFFSET (MX6SL_LPDDR2_FREQ_ADDR_OFFSET + LPDDR2_FREQ_CODE_SIZE)
54
55#endif 47#endif
diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c
index 674a1537fae4..b03defb21473 100644
--- a/arch/arm/mach-imx/pm-imx6.c
+++ b/arch/arm/mach-imx/pm-imx6.c
@@ -85,6 +85,10 @@ static unsigned int cpu_type;
85static void __iomem *ccm_base; 85static void __iomem *ccm_base;
86struct regmap *romcp; 86struct regmap *romcp;
87 87
88unsigned long total_suspend_size;
89extern unsigned long imx6_suspend_start asm("imx6_suspend_start");
90extern unsigned long imx6_suspend_end asm("imx6_suspend_end");
91
88unsigned long save_ttbr1(void) 92unsigned long save_ttbr1(void)
89{ 93{
90 unsigned long lttbr1; 94 unsigned long lttbr1;
@@ -415,7 +419,7 @@ void __init imx6_pm_map_io(void)
415 return; 419 return;
416 420
417 /* Set all entries to 0. */ 421 /* Set all entries to 0. */
418 memset((void *)iram_tlb_base_addr, 0, SZ_16K); 422 memset((void *)iram_tlb_base_addr, 0, MX6Q_IRAM_TLB_SIZE);
419 423
420 /* 424 /*
421 * Make sure the IRAM virtual address has a mapping 425 * Make sure the IRAM virtual address has a mapping
@@ -470,6 +474,8 @@ void imx6_pm_set_ccm_base(void __iomem *base)
470 474
471void __init imx6_pm_init(void) 475void __init imx6_pm_init(void)
472{ 476{
477 unsigned long suspend_code_size;
478
473 if (!iram_tlb_base_addr) { 479 if (!iram_tlb_base_addr) {
474 pr_warn("No IRAM/OCRAM memory allocated for suspend/resume code. \ 480 pr_warn("No IRAM/OCRAM memory allocated for suspend/resume code. \
475Please ensure device tree has an entry fsl,lpm-sram\n"); 481Please ensure device tree has an entry fsl,lpm-sram\n");
@@ -481,8 +487,11 @@ Please ensure device tree has an entry fsl,lpm-sram\n");
481 suspend_iram_base = (void *)IMX_IO_P2V(iram_tlb_phys_addr) + 487 suspend_iram_base = (void *)IMX_IO_P2V(iram_tlb_phys_addr) +
482 MX6_SUSPEND_IRAM_ADDR_OFFSET; 488 MX6_SUSPEND_IRAM_ADDR_OFFSET;
483 489
490 suspend_code_size = (&imx6_suspend_end -&imx6_suspend_start) *4;
484 suspend_in_iram_fn = (void *)fncpy(suspend_iram_base, 491 suspend_in_iram_fn = (void *)fncpy(suspend_iram_base,
485 &imx6_suspend, MX6_SUSPEND_IRAM_SIZE); 492 &imx6_suspend, suspend_code_size);
493 /* Now add the space used for storing various registers and IO in suspend. */
494 total_suspend_size = suspend_code_size + MX6_SUSPEND_IRAM_DATA_SIZE;
486 495
487 suspend_set_ops(&imx6_pm_ops); 496 suspend_set_ops(&imx6_pm_ops);
488 497
diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S
index 620181a4886b..da9bd589f5ea 100644
--- a/arch/arm/mach-imx/suspend-imx6.S
+++ b/arch/arm/mach-imx/suspend-imx6.S
@@ -31,6 +31,9 @@
31#define MX6Q_CCM_CCR 0x0 31#define MX6Q_CCM_CCR 0x0
32#define MX6Q_ANATOP_CORE 0x140 32#define MX6Q_ANATOP_CORE 0x140
33 33
34.globl imx6_suspend_start
35.globl imx6_suspend_end
36
34 .align 3 37 .align 3
35 38
36 .macro imx6sx_ddr_io_save 39 .macro imx6sx_ddr_io_save
@@ -557,7 +560,7 @@
557 .endm 560 .endm
558 561
559ENTRY(imx6_suspend) 562ENTRY(imx6_suspend)
560 563imx6_suspend_start:
561 push {r4-r12} 564 push {r4-r12}
562 565
563 /* 566 /*
@@ -590,15 +593,19 @@ ENTRY(imx6_suspend)
590 * is for the jump when we finish DDR IO 593 * is for the jump when we finish DDR IO
591 * restore. 594 * restore.
592 */ 595 */
596 ldr r7,=total_suspend_size
597 ldr r7, [r7]
598 add r10, r0, r7
599
593 ldr r5, [r8, #MX6Q_SRC_GPR1] 600 ldr r5, [r8, #MX6Q_SRC_GPR1]
594 add r10, r0, #MX6_SUSPEND_IRAM_SIZE
595 stmfd r10!, {r5} 601 stmfd r10!, {r5}
596 602
597 /* save cpu type */ 603 /* save cpu type */
598 stmfd r10!, {r2} 604 stmfd r10!, {r2}
599 605
600 str r9, [r8, #MX6Q_SRC_GPR1] 606 str r9, [r8, #MX6Q_SRC_GPR1]
601 add r3, r1, #MX6_SUSPEND_IRAM_SIZE 607 add r3, r1, r7
608
602 str r3, [r8, #MX6Q_SRC_GPR2] 609 str r3, [r8, #MX6Q_SRC_GPR2]
603 610
604 ldr r8, =IMX_IO_P2V(MX6Q_IOMUXC_BASE_ADDR) 611 ldr r8, =IMX_IO_P2V(MX6Q_IOMUXC_BASE_ADDR)
@@ -636,15 +643,16 @@ ddr_io_save_dsm_done:
636 * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0 643 * 4. Set TTBR0.N=1, implying 0-2G is translated by TTBR0
637 * and 2-4G is translated by TTBR1. 644 * and 2-4G is translated by TTBR1.
638 */ 645 */
639 /* Flush the BTAC. */
640 ldr r6, =0x0
641 mcr p15, 0, r6, c7, c1, 6
642
643 /* Disable Branch Prediction, Z bit in SCTLR. */ 646 /* Disable Branch Prediction, Z bit in SCTLR. */
644 mrc p15, 0, r6, c1, c0, 0 647 mrc p15, 0, r6, c1, c0, 0
645 bic r6, r6, #0x800 648 bic r6, r6, #0x800
646 mcr p15, 0, r6, c1, c0, 0 649 mcr p15, 0, r6, c1, c0, 0
647 650
651 /* Flush the BTAC. */
652 ldr r6, =0x0
653 mcr p15, 0, r6, c7, c1, 6
654
655
648 ldr r6, =iram_tlb_phys_addr 656 ldr r6, =iram_tlb_phys_addr
649 ldr r6, [r6] 657 ldr r6, [r6]
650 dsb 658 dsb
@@ -820,8 +828,9 @@ ldo_bypass_restore:
820 orr r7, r7, #0x1f 828 orr r7, r7, #0x1f
821 str r7, [r8, #MX6Q_ANATOP_CORE] 829 str r7, [r8, #MX6Q_ANATOP_CORE]
822ldo_check_done2: 830ldo_check_done2:
831 adrl r7, imx6_suspend_end
832 add r10, r7, #MX6_SUSPEND_IRAM_DATA_SIZE
823 833
824 add r10, r0, #MX6_SUSPEND_IRAM_SIZE
825 /* skip the lr saved in iram */ 834 /* skip the lr saved in iram */
826 sub r10, r10, #0x4 835 sub r10, r10, #0x4
827 /* skip the cpu type saved in iram */ 836 /* skip the cpu type saved in iram */
@@ -1014,3 +1023,11 @@ poll_dvfs_clear_1:
1014 bic r7, r7, #0x1 1023 bic r7, r7, #0x1
1015 str r7, [r8, #MX6Q_MMDC_MAPSR] 1024 str r7, [r8, #MX6Q_MMDC_MAPSR]
1016 mov pc, lr 1025 mov pc, lr
1026
1027 /*
1028 * Add ltorg here to ensure that all
1029 * literals are stored here and are
1030 * within the text space.
1031 */
1032 .ltorg
1033imx6_suspend_end: