aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 18:27:22 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 18:27:22 -0500
commitbab588fcfb6335c767d811a8955979f5440328e0 (patch)
tree2a862ddf47a82be885a8e7945a17cc3ff7a658b9 /arch/arm/mach-imx
parent3298a3511f1e73255a8dc023efd909e569eea037 (diff)
parent9cb0d1babfcb1b4ac248c09425f7d5de1e771133 (diff)
Merge tag 'soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC-specific updates from Arnd Bergmann: "This is a larger set of new functionality for the existing SoC families, including: - vt8500 gains support for new CPU cores, notably the Cortex-A9 based wm8850 - prima2 gains support for the "marco" SoC family, its SMP based cousin - tegra gains support for the new Tegra4 (Tegra114) family - socfpga now supports a newer version of the hardware including SMP - i.mx31 and bcm2835 are now using DT probing for their clocks - lots of updates for sh-mobile - OMAP updates for clocks, power management and USB - i.mx6q and tegra now support cpuidle - kirkwood now supports PCIe hot plugging - tegra clock support is updated - tegra USB PHY probing gets implemented diffently" * tag 'soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (148 commits) ARM: prima2: remove duplicate v7_invalidate_l1 ARM: shmobile: r8a7779: Correct TMU clock support again ARM: prima2: fix __init section for cpu hotplug ARM: OMAP: Consolidate OMAP USB-HS platform data (part 3/3) ARM: OMAP: Consolidate OMAP USB-HS platform data (part 1/3) arm: socfpga: Add SMP support for actual socfpga harware arm: Add v7_invalidate_l1 to cache-v7.S arm: socfpga: Add entries to enable make dtbs socfpga arm: socfpga: Add new device tree source for actual socfpga HW ARM: tegra: sort Kconfig selects for Tegra114 ARM: tegra: enable ARCH_REQUIRE_GPIOLIB for Tegra114 ARM: tegra: Fix build error w/ ARCH_TEGRA_114_SOC w/o ARCH_TEGRA_3x_SOC ARM: tegra: Fix build error for gic update ARM: tegra: remove empty tegra_smp_init_cpus() ARM: shmobile: Register ARM architected timer ARM: MARCO: fix the build issue due to gic-vic-to-irqchip move ARM: shmobile: r8a7779: Correct TMU clock support ARM: mxs_defconfig: Select CONFIG_DEVTMPFS_MOUNT ARM: mxs: decrease mxs_clockevent_device.min_delta_ns to 2 clock cycles ARM: mxs: use apbx bus clock to drive the timers on timrotv2 ...
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/Makefile6
-rw-r--r--arch/arm/mach-imx/clk-imx27.c7
-rw-r--r--arch/arm/mach-imx/clk-imx31.c15
-rw-r--r--arch/arm/mach-imx/clk-imx35.c4
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c12
-rw-r--r--arch/arm/mach-imx/common.h3
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6q.c95
-rw-r--r--arch/arm/mach-imx/cpuidle.h5
-rw-r--r--arch/arm/mach-imx/gpc.c5
-rw-r--r--arch/arm/mach-imx/headsmp.S47
-rw-r--r--arch/arm/mach-imx/imx31-dt.c17
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c17
-rw-r--r--arch/arm/mach-imx/platsmp.c10
-rw-r--r--arch/arm/mach-imx/time.c3
14 files changed, 163 insertions, 83 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 240e0294c372..c4ce0906d76a 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -28,7 +28,11 @@ obj-$(CONFIG_MXC_ULPI) += ulpi.o
28obj-$(CONFIG_MXC_USE_EPIT) += epit.o 28obj-$(CONFIG_MXC_USE_EPIT) += epit.o
29obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o 29obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
30obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o 30obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o
31obj-$(CONFIG_CPU_IDLE) += cpuidle.o 31
32ifeq ($(CONFIG_CPU_IDLE),y)
33obj-y += cpuidle.o
34obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
35endif
32 36
33ifdef CONFIG_SND_IMX_SOC 37ifdef CONFIG_SND_IMX_SOC
34obj-y += ssi-fiq.o 38obj-y += ssi-fiq.o
diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
index e30369a58e4e..30b3242a7d49 100644
--- a/arch/arm/mach-imx/clk-imx27.c
+++ b/arch/arm/mach-imx/clk-imx27.c
@@ -62,7 +62,7 @@ static const char *clko_sel_clks[] = {
62 "32k", "usb_div", "dptc", 62 "32k", "usb_div", "dptc",
63}; 63};
64 64
65static const char *ssi_sel_clks[] = { "spll", "mpll", }; 65static const char *ssi_sel_clks[] = { "spll_gate", "mpll", };
66 66
67enum mx27_clks { 67enum mx27_clks {
68 dummy, ckih, ckil, mpll, spll, mpll_main2, ahb, ipg, nfc_div, per1_div, 68 dummy, ckih, ckil, mpll, spll, mpll_main2, ahb, ipg, nfc_div, per1_div,
@@ -82,7 +82,7 @@ enum mx27_clks {
82 csi_ahb_gate, brom_ahb_gate, ata_ahb_gate, wdog_ipg_gate, usb_ipg_gate, 82 csi_ahb_gate, brom_ahb_gate, ata_ahb_gate, wdog_ipg_gate, usb_ipg_gate,
83 uart6_ipg_gate, uart5_ipg_gate, uart4_ipg_gate, uart3_ipg_gate, 83 uart6_ipg_gate, uart5_ipg_gate, uart4_ipg_gate, uart3_ipg_gate,
84 uart2_ipg_gate, uart1_ipg_gate, ckih_div1p5, fpm, mpll_osc_sel, 84 uart2_ipg_gate, uart1_ipg_gate, ckih_div1p5, fpm, mpll_osc_sel,
85 mpll_sel, clk_max 85 mpll_sel, spll_gate, clk_max
86}; 86};
87 87
88static struct clk *clk[clk_max]; 88static struct clk *clk[clk_max];
@@ -104,6 +104,7 @@ int __init mx27_clocks_init(unsigned long fref)
104 ARRAY_SIZE(mpll_sel_clks)); 104 ARRAY_SIZE(mpll_sel_clks));
105 clk[mpll] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0); 105 clk[mpll] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
106 clk[spll] = imx_clk_pllv1("spll", "ckih", CCM_SPCTL0); 106 clk[spll] = imx_clk_pllv1("spll", "ckih", CCM_SPCTL0);
107 clk[spll_gate] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
107 clk[mpll_main2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3); 108 clk[mpll_main2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
108 109
109 if (mx27_revision() >= IMX_CHIP_REVISION_2_0) { 110 if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
@@ -121,7 +122,7 @@ int __init mx27_clocks_init(unsigned long fref)
121 clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6); 122 clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
122 clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks)); 123 clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
123 clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6); 124 clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);
124 clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3); 125 clk[usb_div] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 28, 3);
125 clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks)); 126 clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
126 clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks)); 127 clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
127 if (mx27_revision() >= IMX_CHIP_REVISION_2_0) 128 if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
diff --git a/arch/arm/mach-imx/clk-imx31.c b/arch/arm/mach-imx/clk-imx31.c
index 16ccbd41dea9..b5b65f3efaf1 100644
--- a/arch/arm/mach-imx/clk-imx31.c
+++ b/arch/arm/mach-imx/clk-imx31.c
@@ -34,8 +34,8 @@ static const char *csi_sel[] = { "upll", "spll", };
34static const char *fir_sel[] = { "mcu_main", "upll", "spll" }; 34static const char *fir_sel[] = { "mcu_main", "upll", "spll" };
35 35
36enum mx31_clks { 36enum mx31_clks {
37 ckih, ckil, mpll, spll, upll, mcu_main, hsp, ahb, nfc, ipg, per_div, 37 dummy, ckih, ckil, mpll, spll, upll, mcu_main, hsp, ahb, nfc, ipg,
38 per, csi, fir, csi_div, usb_div_pre, usb_div_post, fir_div_pre, 38 per_div, per, csi, fir, csi_div, usb_div_pre, usb_div_post, fir_div_pre,
39 fir_div_post, sdhc1_gate, sdhc2_gate, gpt_gate, epit1_gate, epit2_gate, 39 fir_div_post, sdhc1_gate, sdhc2_gate, gpt_gate, epit1_gate, epit2_gate,
40 iim_gate, ata_gate, sdma_gate, cspi3_gate, rng_gate, uart1_gate, 40 iim_gate, ata_gate, sdma_gate, cspi3_gate, rng_gate, uart1_gate,
41 uart2_gate, ssi1_gate, i2c1_gate, i2c2_gate, i2c3_gate, hantro_gate, 41 uart2_gate, ssi1_gate, i2c1_gate, i2c2_gate, i2c3_gate, hantro_gate,
@@ -46,12 +46,15 @@ enum mx31_clks {
46}; 46};
47 47
48static struct clk *clk[clk_max]; 48static struct clk *clk[clk_max];
49static struct clk_onecell_data clk_data;
49 50
50int __init mx31_clocks_init(unsigned long fref) 51int __init mx31_clocks_init(unsigned long fref)
51{ 52{
52 void __iomem *base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR); 53 void __iomem *base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR);
53 int i; 54 int i;
55 struct device_node *np;
54 56
57 clk[dummy] = imx_clk_fixed("dummy", 0);
55 clk[ckih] = imx_clk_fixed("ckih", fref); 58 clk[ckih] = imx_clk_fixed("ckih", fref);
56 clk[ckil] = imx_clk_fixed("ckil", 32768); 59 clk[ckil] = imx_clk_fixed("ckil", 32768);
57 clk[mpll] = imx_clk_pllv1("mpll", "ckih", base + MXC_CCM_MPCTL); 60 clk[mpll] = imx_clk_pllv1("mpll", "ckih", base + MXC_CCM_MPCTL);
@@ -116,6 +119,14 @@ int __init mx31_clocks_init(unsigned long fref)
116 pr_err("imx31 clk %d: register failed with %ld\n", 119 pr_err("imx31 clk %d: register failed with %ld\n",
117 i, PTR_ERR(clk[i])); 120 i, PTR_ERR(clk[i]));
118 121
122 np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm");
123
124 if (np) {
125 clk_data.clks = clk;
126 clk_data.clk_num = ARRAY_SIZE(clk);
127 of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
128 }
129
119 clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0"); 130 clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
120 clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0"); 131 clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
121 clk_register_clkdev(clk[cspi1_gate], NULL, "imx31-cspi.0"); 132 clk_register_clkdev(clk[cspi1_gate], NULL, "imx31-cspi.0");
diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c
index f0727e80815d..74e3a34d78b8 100644
--- a/arch/arm/mach-imx/clk-imx35.c
+++ b/arch/arm/mach-imx/clk-imx35.c
@@ -67,13 +67,13 @@ enum mx35_clks {
67 67
68static struct clk *clk[clk_max]; 68static struct clk *clk[clk_max];
69 69
70int __init mx35_clocks_init() 70int __init mx35_clocks_init(void)
71{ 71{
72 void __iomem *base = MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR); 72 void __iomem *base = MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR);
73 u32 pdr0, consumer_sel, hsp_sel; 73 u32 pdr0, consumer_sel, hsp_sel;
74 struct arm_ahb_div *aad; 74 struct arm_ahb_div *aad;
75 unsigned char *hsp_div; 75 unsigned char *hsp_div;
76 int i; 76 u32 i;
77 77
78 pdr0 = __raw_readl(base + MXC_CCM_PDR0); 78 pdr0 = __raw_readl(base + MXC_CCM_PDR0);
79 consumer_sel = (pdr0 >> 16) & 0xf; 79 consumer_sel = (pdr0 >> 16) & 0xf;
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 19644f6524dc..540138c4606c 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -54,8 +54,19 @@
54#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26) 54#define BM_CLPCR_MASK_SCU_IDLE (0x1 << 26)
55#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27) 55#define BM_CLPCR_MASK_L2CC_IDLE (0x1 << 27)
56 56
57#define CGPR 0x64
58#define BM_CGPR_CHICKEN_BIT (0x1 << 17)
59
57static void __iomem *ccm_base; 60static void __iomem *ccm_base;
58 61
62void imx6q_set_chicken_bit(void)
63{
64 u32 val = readl_relaxed(ccm_base + CGPR);
65
66 val |= BM_CGPR_CHICKEN_BIT;
67 writel_relaxed(val, ccm_base + CGPR);
68}
69
59int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) 70int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
60{ 71{
61 u32 val = readl_relaxed(ccm_base + CLPCR); 72 u32 val = readl_relaxed(ccm_base + CLPCR);
@@ -66,6 +77,7 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
66 break; 77 break;
67 case WAIT_UNCLOCKED: 78 case WAIT_UNCLOCKED:
68 val |= 0x1 << BP_CLPCR_LPM; 79 val |= 0x1 << BP_CLPCR_LPM;
80 val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
69 break; 81 break;
70 case STOP_POWER_ON: 82 case STOP_POWER_ON:
71 val |= 0x2 << BP_CLPCR_LPM; 83 val |= 0x2 << BP_CLPCR_LPM;
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 76c420043289..5a800bfcec5b 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -116,9 +116,11 @@ extern u32 *pl310_get_save_ptr(void);
116extern void v7_secondary_startup(void); 116extern void v7_secondary_startup(void);
117extern void imx_scu_map_io(void); 117extern void imx_scu_map_io(void);
118extern void imx_smp_prepare(void); 118extern void imx_smp_prepare(void);
119extern void imx_scu_standby_enable(void);
119#else 120#else
120static inline void imx_scu_map_io(void) {} 121static inline void imx_scu_map_io(void) {}
121static inline void imx_smp_prepare(void) {} 122static inline void imx_smp_prepare(void) {}
123static inline void imx_scu_standby_enable(void) {}
122#endif 124#endif
123extern void imx_enable_cpu(int cpu, bool enable); 125extern void imx_enable_cpu(int cpu, bool enable);
124extern void imx_set_cpu_jump(int cpu, void *jump_addr); 126extern void imx_set_cpu_jump(int cpu, void *jump_addr);
@@ -128,6 +130,7 @@ extern void imx_gpc_init(void);
128extern void imx_gpc_pre_suspend(void); 130extern void imx_gpc_pre_suspend(void);
129extern void imx_gpc_post_resume(void); 131extern void imx_gpc_post_resume(void);
130extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); 132extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
133extern void imx6q_set_chicken_bit(void);
131 134
132extern void imx_cpu_die(unsigned int cpu); 135extern void imx_cpu_die(unsigned int cpu);
133extern int imx_cpu_kill(unsigned int cpu); 136extern int imx_cpu_kill(unsigned int cpu);
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
new file mode 100644
index 000000000000..d533e2695f0e
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -0,0 +1,95 @@
1/*
2 * Copyright (C) 2012 Freescale Semiconductor, Inc.
3 *
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
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/clockchips.h>
10#include <linux/cpuidle.h>
11#include <linux/module.h>
12#include <asm/cpuidle.h>
13#include <asm/proc-fns.h>
14
15#include "common.h"
16#include "cpuidle.h"
17
18static atomic_t master = ATOMIC_INIT(0);
19static DEFINE_SPINLOCK(master_lock);
20
21static int imx6q_enter_wait(struct cpuidle_device *dev,
22 struct cpuidle_driver *drv, int index)
23{
24 int cpu = dev->cpu;
25
26 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
27
28 if (atomic_inc_return(&master) == num_online_cpus()) {
29 /*
30 * With this lock, we prevent other cpu to exit and enter
31 * this function again and become the master.
32 */
33 if (!spin_trylock(&master_lock))
34 goto idle;
35 imx6q_set_lpm(WAIT_UNCLOCKED);
36 cpu_do_idle();
37 imx6q_set_lpm(WAIT_CLOCKED);
38 spin_unlock(&master_lock);
39 goto done;
40 }
41
42idle:
43 cpu_do_idle();
44done:
45 atomic_dec(&master);
46 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
47
48 return index;
49}
50
51/*
52 * For each cpu, setup the broadcast timer because local timer
53 * stops for the states other than WFI.
54 */
55static void imx6q_setup_broadcast_timer(void *arg)
56{
57 int cpu = smp_processor_id();
58
59 clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
60}
61
62static struct cpuidle_driver imx6q_cpuidle_driver = {
63 .name = "imx6q_cpuidle",
64 .owner = THIS_MODULE,
65 .en_core_tk_irqen = 1,
66 .states = {
67 /* WFI */
68 ARM_CPUIDLE_WFI_STATE,
69 /* WAIT */
70 {
71 .exit_latency = 50,
72 .target_residency = 75,
73 .flags = CPUIDLE_FLAG_TIME_VALID,
74 .enter = imx6q_enter_wait,
75 .name = "WAIT",
76 .desc = "Clock off",
77 },
78 },
79 .state_count = 2,
80 .safe_state_index = 0,
81};
82
83int __init imx6q_cpuidle_init(void)
84{
85 /* Need to enable SCU standby for entering WAIT modes */
86 imx_scu_standby_enable();
87
88 /* Set chicken bit to get a reliable WAIT mode support */
89 imx6q_set_chicken_bit();
90
91 /* Configure the broadcast timer on each cpu */
92 on_each_cpu(imx6q_setup_broadcast_timer, NULL, 1);
93
94 return imx_cpuidle_init(&imx6q_cpuidle_driver);
95}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index bc932d1af372..e092d1359d94 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -14,9 +14,14 @@
14 14
15#ifdef CONFIG_CPU_IDLE 15#ifdef CONFIG_CPU_IDLE
16extern int imx_cpuidle_init(struct cpuidle_driver *drv); 16extern int imx_cpuidle_init(struct cpuidle_driver *drv);
17extern int imx6q_cpuidle_init(void);
17#else 18#else
18static inline int imx_cpuidle_init(struct cpuidle_driver *drv) 19static inline int imx_cpuidle_init(struct cpuidle_driver *drv)
19{ 20{
20 return -ENODEV; 21 return -ENODEV;
21} 22}
23static inline int imx6q_cpuidle_init(void)
24{
25 return -ENODEV;
26}
22#endif 27#endif
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index ff24920699e4..a96ccc7f5012 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -101,11 +101,16 @@ static void imx_gpc_irq_mask(struct irq_data *d)
101void __init imx_gpc_init(void) 101void __init imx_gpc_init(void)
102{ 102{
103 struct device_node *np; 103 struct device_node *np;
104 int i;
104 105
105 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc"); 106 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
106 gpc_base = of_iomap(np, 0); 107 gpc_base = of_iomap(np, 0);
107 WARN_ON(!gpc_base); 108 WARN_ON(!gpc_base);
108 109
110 /* Initially mask all interrupts */
111 for (i = 0; i < IMR_NUM; i++)
112 writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4);
113
109 /* Register GPC as the secondary interrupt controller behind GIC */ 114 /* Register GPC as the secondary interrupt controller behind GIC */
110 gic_arch_extn.irq_mask = imx_gpc_irq_mask; 115 gic_arch_extn.irq_mask = imx_gpc_irq_mask;
111 gic_arch_extn.irq_unmask = imx_gpc_irq_unmask; 116 gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
diff --git a/arch/arm/mach-imx/headsmp.S b/arch/arm/mach-imx/headsmp.S
index 7e49deb128a4..921fc1555854 100644
--- a/arch/arm/mach-imx/headsmp.S
+++ b/arch/arm/mach-imx/headsmp.S
@@ -17,53 +17,6 @@
17 17
18 .section ".text.head", "ax" 18 .section ".text.head", "ax"
19 19
20/*
21 * The secondary kernel init calls v7_flush_dcache_all before it enables
22 * the L1; however, the L1 comes out of reset in an undefined state, so
23 * the clean + invalidate performed by v7_flush_dcache_all causes a bunch
24 * of cache lines with uninitialized data and uninitialized tags to get
25 * written out to memory, which does really unpleasant things to the main
26 * processor. We fix this by performing an invalidate, rather than a
27 * clean + invalidate, before jumping into the kernel.
28 *
29 * This funciton is cloned from arch/arm/mach-tegra/headsmp.S, and needs
30 * to be called for both secondary cores startup and primary core resume
31 * procedures. Ideally, it should be moved into arch/arm/mm/cache-v7.S.
32 */
33ENTRY(v7_invalidate_l1)
34 mov r0, #0
35 mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
36 mcr p15, 2, r0, c0, c0, 0
37 mrc p15, 1, r0, c0, c0, 0
38
39 ldr r1, =0x7fff
40 and r2, r1, r0, lsr #13
41
42 ldr r1, =0x3ff
43
44 and r3, r1, r0, lsr #3 @ NumWays - 1
45 add r2, r2, #1 @ NumSets
46
47 and r0, r0, #0x7
48 add r0, r0, #4 @ SetShift
49
50 clz r1, r3 @ WayShift
51 add r4, r3, #1 @ NumWays
521: sub r2, r2, #1 @ NumSets--
53 mov r3, r4 @ Temp = NumWays
542: subs r3, r3, #1 @ Temp--
55 mov r5, r3, lsl r1
56 mov r6, r2, lsl r0
57 orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
58 mcr p15, 0, r5, c7, c6, 2
59 bgt 2b
60 cmp r2, #0
61 bgt 1b
62 dsb
63 isb
64 mov pc, lr
65ENDPROC(v7_invalidate_l1)
66
67#ifdef CONFIG_SMP 20#ifdef CONFIG_SMP
68ENTRY(v7_secondary_startup) 21ENTRY(v7_secondary_startup)
69 bl v7_invalidate_l1 22 bl v7_invalidate_l1
diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c
index b5c04eece780..67de611e29ab 100644
--- a/arch/arm/mach-imx/imx31-dt.c
+++ b/arch/arm/mach-imx/imx31-dt.c
@@ -18,24 +18,9 @@
18#include "common.h" 18#include "common.h"
19#include "mx31.h" 19#include "mx31.h"
20 20
21static const struct of_dev_auxdata imx31_auxdata_lookup[] __initconst = {
22 OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART1_BASE_ADDR,
23 "imx21-uart.0", NULL),
24 OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART2_BASE_ADDR,
25 "imx21-uart.1", NULL),
26 OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART3_BASE_ADDR,
27 "imx21-uart.2", NULL),
28 OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART4_BASE_ADDR,
29 "imx21-uart.3", NULL),
30 OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART5_BASE_ADDR,
31 "imx21-uart.4", NULL),
32 { /* sentinel */ }
33};
34
35static void __init imx31_dt_init(void) 21static void __init imx31_dt_init(void)
36{ 22{
37 of_platform_populate(NULL, of_default_bus_match_table, 23 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
38 imx31_auxdata_lookup, NULL);
39} 24}
40 25
41static const char *imx31_dt_board_compat[] __initdata = { 26static const char *imx31_dt_board_compat[] __initdata = {
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 5a18e7e5c564..1786b2d1257e 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -12,7 +12,6 @@
12 12
13#include <linux/clk.h> 13#include <linux/clk.h>
14#include <linux/clkdev.h> 14#include <linux/clkdev.h>
15#include <linux/cpuidle.h>
16#include <linux/delay.h> 15#include <linux/delay.h>
17#include <linux/export.h> 16#include <linux/export.h>
18#include <linux/init.h> 17#include <linux/init.h>
@@ -27,7 +26,6 @@
27#include <linux/regmap.h> 26#include <linux/regmap.h>
28#include <linux/micrel_phy.h> 27#include <linux/micrel_phy.h>
29#include <linux/mfd/syscon.h> 28#include <linux/mfd/syscon.h>
30#include <asm/cpuidle.h>
31#include <asm/smp_twd.h> 29#include <asm/smp_twd.h>
32#include <asm/hardware/cache-l2x0.h> 30#include <asm/hardware/cache-l2x0.h>
33#include <asm/mach/arch.h> 31#include <asm/mach/arch.h>
@@ -202,17 +200,14 @@ static void __init imx6q_init_machine(void)
202 imx6q_1588_init(); 200 imx6q_1588_init();
203} 201}
204 202
205static struct cpuidle_driver imx6q_cpuidle_driver = {
206 .name = "imx6q_cpuidle",
207 .owner = THIS_MODULE,
208 .en_core_tk_irqen = 1,
209 .states[0] = ARM_CPUIDLE_WFI_STATE,
210 .state_count = 1,
211};
212
213static void __init imx6q_init_late(void) 203static void __init imx6q_init_late(void)
214{ 204{
215 imx_cpuidle_init(&imx6q_cpuidle_driver); 205 /*
206 * WAIT mode is broken on TO 1.0 and 1.1, so there is no point
207 * to run cpuidle on them.
208 */
209 if (imx6q_revision() > IMX_CHIP_REVISION_1_1)
210 imx6q_cpuidle_init();
216} 211}
217 212
218static void __init imx6q_map_io(void) 213static void __init imx6q_map_io(void)
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index b2872ec614a4..7c0b03f67b05 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -20,6 +20,8 @@
20#include "common.h" 20#include "common.h"
21#include "hardware.h" 21#include "hardware.h"
22 22
23#define SCU_STANDBY_ENABLE (1 << 5)
24
23static void __iomem *scu_base; 25static void __iomem *scu_base;
24 26
25static struct map_desc scu_io_desc __initdata = { 27static struct map_desc scu_io_desc __initdata = {
@@ -42,6 +44,14 @@ void __init imx_scu_map_io(void)
42 scu_base = IMX_IO_ADDRESS(base); 44 scu_base = IMX_IO_ADDRESS(base);
43} 45}
44 46
47void imx_scu_standby_enable(void)
48{
49 u32 val = readl_relaxed(scu_base);
50
51 val |= SCU_STANDBY_ENABLE;
52 writel_relaxed(val, scu_base);
53}
54
45static void __cpuinit imx_secondary_init(unsigned int cpu) 55static void __cpuinit imx_secondary_init(unsigned int cpu)
46{ 56{
47 /* 57 /*
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 62769df36db1..fea91313678b 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -152,7 +152,8 @@ static int v2_set_next_event(unsigned long evt,
152 152
153 __raw_writel(tcmp, timer_base + V2_TCMP); 153 __raw_writel(tcmp, timer_base + V2_TCMP);
154 154
155 return (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ? 155 return evt < 0x7fffffff &&
156 (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ?
156 -ETIME : 0; 157 -ETIME : 0;
157} 158}
158 159