diff options
-rw-r--r-- | arch/arm/mach-imx/busfreq-imx6.c | 68 | ||||
-rw-r--r-- | arch/arm/mach-imx/busfreq_ddr3.c | 67 | ||||
-rw-r--r-- | arch/arm/mach-imx/busfreq_lpddr2.c | 16 | ||||
-rw-r--r-- | arch/arm/mach-imx/common.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/cpuidle-imx6sl.c | 12 | ||||
-rw-r--r-- | arch/arm/mach-imx/ddr3_freq_imx6.S | 30 | ||||
-rw-r--r-- | arch/arm/mach-imx/ddr3_freq_imx6sx.S | 33 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx6sl_wfi.S | 34 | ||||
-rw-r--r-- | arch/arm/mach-imx/lpddr2_freq_imx6.S | 32 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6q.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6sl.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6sx.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/mx6.h | 14 | ||||
-rw-r--r-- | arch/arm/mach-imx/pm-imx6.c | 13 | ||||
-rw-r--r-- | arch/arm/mach-imx/suspend-imx6.S | 33 |
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; | |||
63 | int ultra_low_bus_freq_mode; | 64 | int ultra_low_bus_freq_mode; |
64 | unsigned int ddr_med_rate; | 65 | unsigned int ddr_med_rate; |
65 | unsigned int ddr_normal_rate; | 66 | unsigned int ddr_normal_rate; |
67 | unsigned long ddr_freq_change_total_size; | ||
68 | unsigned long ddr_freq_change_iram_base; | ||
69 | unsigned long ddr_freq_change_iram_phys; | ||
66 | 70 | ||
67 | static int bus_freq_scaling_initialized; | 71 | static int bus_freq_scaling_initialized; |
68 | static struct device *busfreq_dev; | 72 | static struct device *busfreq_dev; |
@@ -72,6 +76,9 @@ static int bus_freq_scaling_is_active; | |||
72 | static int high_bus_count, med_bus_count, audio_bus_count, low_bus_count; | 76 | static int high_bus_count, med_bus_count, audio_bus_count, low_bus_count; |
73 | static unsigned int ddr_low_rate; | 77 | static unsigned int ddr_low_rate; |
74 | 78 | ||
79 | extern unsigned long iram_tlb_phys_addr; | ||
80 | extern int unsigned long iram_tlb_base_addr; | ||
81 | |||
75 | extern int init_mmdc_lpddr2_settings(struct platform_device *dev); | 82 | extern int init_mmdc_lpddr2_settings(struct platform_device *dev); |
76 | extern int init_mmdc_ddr3_settings_imx6q(struct platform_device *dev); | 83 | extern int init_mmdc_ddr3_settings_imx6q(struct platform_device *dev); |
77 | extern int init_mmdc_ddr3_settings_imx6sx(struct platform_device *dev); | 84 | extern 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 | } |
685 | EXPORT_SYMBOL(release_bus_freq); | 692 | EXPORT_SYMBOL(release_bus_freq); |
686 | 693 | ||
694 | static 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 | |||
700 | const static char *ddr_freq_iram_match[] __initconst = { | ||
701 | "fsl,ddr-lpm-sram", | ||
702 | NULL | ||
703 | }; | ||
704 | |||
705 | static 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 | |||
742 | void __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 | |||
687 | static void bus_freq_daemon_handler(struct work_struct *work) | 751 | static 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; | |||
70 | static void __iomem *gic_dist_base; | 70 | static void __iomem *gic_dist_base; |
71 | static u32 *irqs_used; | 71 | static u32 *irqs_used; |
72 | 72 | ||
73 | static void *ddr_freq_change_iram_base; | ||
74 | static int ddr_settings_size; | 73 | static int ddr_settings_size; |
75 | static int iomux_settings_size; | 74 | static int iomux_settings_size; |
76 | static volatile unsigned int cpus_in_wfe; | 75 | static 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); |
92 | extern unsigned long save_ttbr1(void); | 91 | extern unsigned long save_ttbr1(void); |
93 | extern void restore_ttbr1(unsigned long ttbr1); | 92 | extern void restore_ttbr1(unsigned long ttbr1); |
94 | extern unsigned long iram_tlb_phys_addr; | 93 | extern unsigned long ddr_freq_change_iram_base; |
94 | extern unsigned long ddr_freq_change_total_size; | ||
95 | extern unsigned long mx6_ddr3_freq_change_start asm("mx6_ddr3_freq_change_start"); | ||
96 | extern unsigned long mx6_ddr3_freq_change_end asm("mx6_ddr3_freq_change_end"); | ||
97 | extern unsigned long imx6sx_ddr3_freq_change_start asm("imx6sx_ddr3_freq_change_start"); | ||
98 | extern 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 | ||
46 | static struct device *busfreq_dev; | 46 | static struct device *busfreq_dev; |
47 | static void *ddr_freq_change_iram_base; | ||
48 | static int curr_ddr_rate; | 47 | static int curr_ddr_rate; |
49 | static DEFINE_SPINLOCK(freq_lock); | 48 | static DEFINE_SPINLOCK(freq_lock); |
50 | 49 | ||
@@ -55,10 +54,11 @@ extern int low_bus_freq_mode; | |||
55 | extern int ultra_low_bus_freq_mode; | 54 | extern int ultra_low_bus_freq_mode; |
56 | extern void mx6_lpddr2_freq_change(u32 freq, int bus_freq_mode); | 55 | extern void mx6_lpddr2_freq_change(u32 freq, int bus_freq_mode); |
57 | extern void imx6sx_lpddr2_freq_change(u32 freq, int bus_freq_mode); | 56 | extern void imx6sx_lpddr2_freq_change(u32 freq, int bus_freq_mode); |
58 | |||
59 | extern unsigned long save_ttbr1(void); | 57 | extern unsigned long save_ttbr1(void); |
60 | extern void restore_ttbr1(unsigned long ttbr1); | 58 | extern void restore_ttbr1(unsigned long ttbr1); |
61 | extern unsigned long iram_tlb_phys_addr; | 59 | extern unsigned long ddr_freq_change_iram_base; |
60 | extern unsigned long imx6_lpddr2_freq_change_start asm("imx6_lpddr2_freq_change_start"); | ||
61 | extern 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. */ |
64 | int update_lpddr2_freq(int ddr_rate) | 64 | int update_lpddr2_freq(int ddr_rate) |
@@ -93,20 +93,18 @@ int update_lpddr2_freq(int ddr_rate) | |||
93 | int init_mmdc_lpddr2_settings(struct platform_device *busfreq_pdev) | 93 | int 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) {} | |||
131 | static inline void imx_scu_standby_enable(void) {} | 131 | static inline void imx_scu_standby_enable(void) {} |
132 | #endif | 132 | #endif |
133 | extern void imx6_pm_map_io(void); | 133 | extern void imx6_pm_map_io(void); |
134 | extern void imx6_busfreq_map_io(void); | ||
134 | extern void imx6_suspend(void); | 135 | extern void imx6_suspend(void); |
135 | extern void imx_src_init(void); | 136 | extern 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); | |||
33 | extern unsigned long save_ttbr1(void); | 33 | extern unsigned long save_ttbr1(void); |
34 | extern void restore_ttbr1(unsigned long ttbr1); | 34 | extern void restore_ttbr1(unsigned long ttbr1); |
35 | extern unsigned long iram_tlb_phys_addr; | 35 | extern unsigned long iram_tlb_phys_addr; |
36 | extern unsigned long total_suspend_size; | ||
37 | extern unsigned long mx6sl_lpm_wfi_start asm("mx6sl_lpm_wfi_start"); | ||
38 | extern unsigned long mx6sl_lpm_wfi_end asm("mx6sl_lpm_wfi_end"); | ||
36 | 39 | ||
37 | static void __iomem *iomux_base; | 40 | static void __iomem *iomux_base; |
38 | static void *wfi_iram_base; | 41 | static void *wfi_iram_base; |
@@ -99,6 +102,7 @@ static struct cpuidle_driver imx6sl_cpuidle_driver = { | |||
99 | int __init imx6sl_cpuidle_init(void) | 102 | int __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 | */ |
332 | ENTRY(mx6_ddr3_freq_change) | 334 | ENTRY(mx6_ddr3_freq_change) |
333 | 335 | ||
336 | mx6_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 | ||
347 | ddr_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. */ | ||
409 | wait_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 | /* |
959 | ENTRY(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 | ||
973 | mx6_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 | */ |
205 | ENTRY(imx6sx_ddr3_freq_change) | 208 | ENTRY(imx6sx_ddr3_freq_change) |
206 | 209 | ||
210 | imx6sx_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 | ||
213 | ddr_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. */ | ||
278 | wait_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] |
275 | l2: | ||
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 | ||
734 | imx6sx_ddr3_freq_change_end: | ||
722 | ENDPROC(imx6sx_ddr3_freq_change) | 735 | ENDPROC(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 |
162 | ENTRY(imx6sl_low_power_wfi) | 164 | ENTRY(imx6sl_low_power_wfi) |
163 | 165 | ||
166 | mx6sl_lpm_wfi_start: | ||
167 | |||
164 | push {r4-r12} | 168 | push {r4-r12} |
165 | 169 | ||
166 | mx6sl_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. */ | ||
240 | wait_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 | ||
610 | wfi_restore: | 621 | wfi_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 | ||
752 | mx6sl_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 |
345 | ENTRY(mx6_lpddr2_freq_change) | 348 | ENTRY(mx6_lpddr2_freq_change) |
346 | 349 | imx6_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. */ | ||
411 | wait_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 | /* |
593 | ENTRY(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 | ||
607 | imx6_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 | ||
494 | static void __init imx6q_init_irq(void) | 495 | static 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 | ||
122 | static void __init imx6sl_init_irq(void) | 123 | static 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; | |||
85 | static void __iomem *ccm_base; | 85 | static void __iomem *ccm_base; |
86 | struct regmap *romcp; | 86 | struct regmap *romcp; |
87 | 87 | ||
88 | unsigned long total_suspend_size; | ||
89 | extern unsigned long imx6_suspend_start asm("imx6_suspend_start"); | ||
90 | extern unsigned long imx6_suspend_end asm("imx6_suspend_end"); | ||
91 | |||
88 | unsigned long save_ttbr1(void) | 92 | unsigned 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 | ||
471 | void __init imx6_pm_init(void) | 475 | void __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. \ |
475 | Please ensure device tree has an entry fsl,lpm-sram\n"); | 481 | Please 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 | ||
559 | ENTRY(imx6_suspend) | 562 | ENTRY(imx6_suspend) |
560 | 563 | imx6_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] |
822 | ldo_check_done2: | 830 | ldo_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 | ||
1033 | imx6_suspend_end: | ||