diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 18:27:22 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-21 18:27:22 -0500 |
commit | bab588fcfb6335c767d811a8955979f5440328e0 (patch) | |
tree | 2a862ddf47a82be885a8e7945a17cc3ff7a658b9 /arch/arm/mach-imx | |
parent | 3298a3511f1e73255a8dc023efd909e569eea037 (diff) | |
parent | 9cb0d1babfcb1b4ac248c09425f7d5de1e771133 (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/Makefile | 6 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-imx27.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-imx31.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-imx35.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-imx/clk-imx6q.c | 12 | ||||
-rw-r--r-- | arch/arm/mach-imx/common.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-imx/cpuidle-imx6q.c | 95 | ||||
-rw-r--r-- | arch/arm/mach-imx/cpuidle.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-imx/gpc.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-imx/headsmp.S | 47 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx31-dt.c | 17 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6q.c | 17 | ||||
-rw-r--r-- | arch/arm/mach-imx/platsmp.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-imx/time.c | 3 |
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 | |||
28 | obj-$(CONFIG_MXC_USE_EPIT) += epit.o | 28 | obj-$(CONFIG_MXC_USE_EPIT) += epit.o |
29 | obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o | 29 | obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o |
30 | obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o | 30 | obj-$(CONFIG_CPU_FREQ_IMX) += cpufreq.o |
31 | obj-$(CONFIG_CPU_IDLE) += cpuidle.o | 31 | |
32 | ifeq ($(CONFIG_CPU_IDLE),y) | ||
33 | obj-y += cpuidle.o | ||
34 | obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o | ||
35 | endif | ||
32 | 36 | ||
33 | ifdef CONFIG_SND_IMX_SOC | 37 | ifdef CONFIG_SND_IMX_SOC |
34 | obj-y += ssi-fiq.o | 38 | obj-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 | ||
65 | static const char *ssi_sel_clks[] = { "spll", "mpll", }; | 65 | static const char *ssi_sel_clks[] = { "spll_gate", "mpll", }; |
66 | 66 | ||
67 | enum mx27_clks { | 67 | enum 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 | ||
88 | static struct clk *clk[clk_max]; | 88 | static 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", }; | |||
34 | static const char *fir_sel[] = { "mcu_main", "upll", "spll" }; | 34 | static const char *fir_sel[] = { "mcu_main", "upll", "spll" }; |
35 | 35 | ||
36 | enum mx31_clks { | 36 | enum 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 | ||
48 | static struct clk *clk[clk_max]; | 48 | static struct clk *clk[clk_max]; |
49 | static struct clk_onecell_data clk_data; | ||
49 | 50 | ||
50 | int __init mx31_clocks_init(unsigned long fref) | 51 | int __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 | ||
68 | static struct clk *clk[clk_max]; | 68 | static struct clk *clk[clk_max]; |
69 | 69 | ||
70 | int __init mx35_clocks_init() | 70 | int __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 | |||
57 | static void __iomem *ccm_base; | 60 | static void __iomem *ccm_base; |
58 | 61 | ||
62 | void 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 | |||
59 | int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) | 70 | int 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); | |||
116 | extern void v7_secondary_startup(void); | 116 | extern void v7_secondary_startup(void); |
117 | extern void imx_scu_map_io(void); | 117 | extern void imx_scu_map_io(void); |
118 | extern void imx_smp_prepare(void); | 118 | extern void imx_smp_prepare(void); |
119 | extern void imx_scu_standby_enable(void); | ||
119 | #else | 120 | #else |
120 | static inline void imx_scu_map_io(void) {} | 121 | static inline void imx_scu_map_io(void) {} |
121 | static inline void imx_smp_prepare(void) {} | 122 | static inline void imx_smp_prepare(void) {} |
123 | static inline void imx_scu_standby_enable(void) {} | ||
122 | #endif | 124 | #endif |
123 | extern void imx_enable_cpu(int cpu, bool enable); | 125 | extern void imx_enable_cpu(int cpu, bool enable); |
124 | extern void imx_set_cpu_jump(int cpu, void *jump_addr); | 126 | extern void imx_set_cpu_jump(int cpu, void *jump_addr); |
@@ -128,6 +130,7 @@ extern void imx_gpc_init(void); | |||
128 | extern void imx_gpc_pre_suspend(void); | 130 | extern void imx_gpc_pre_suspend(void); |
129 | extern void imx_gpc_post_resume(void); | 131 | extern void imx_gpc_post_resume(void); |
130 | extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); | 132 | extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); |
133 | extern void imx6q_set_chicken_bit(void); | ||
131 | 134 | ||
132 | extern void imx_cpu_die(unsigned int cpu); | 135 | extern void imx_cpu_die(unsigned int cpu); |
133 | extern int imx_cpu_kill(unsigned int cpu); | 136 | extern 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 | |||
18 | static atomic_t master = ATOMIC_INIT(0); | ||
19 | static DEFINE_SPINLOCK(master_lock); | ||
20 | |||
21 | static 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 | |||
42 | idle: | ||
43 | cpu_do_idle(); | ||
44 | done: | ||
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 | */ | ||
55 | static 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 | |||
62 | static 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 | |||
83 | int __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 |
16 | extern int imx_cpuidle_init(struct cpuidle_driver *drv); | 16 | extern int imx_cpuidle_init(struct cpuidle_driver *drv); |
17 | extern int imx6q_cpuidle_init(void); | ||
17 | #else | 18 | #else |
18 | static inline int imx_cpuidle_init(struct cpuidle_driver *drv) | 19 | static inline int imx_cpuidle_init(struct cpuidle_driver *drv) |
19 | { | 20 | { |
20 | return -ENODEV; | 21 | return -ENODEV; |
21 | } | 22 | } |
23 | static 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) | |||
101 | void __init imx_gpc_init(void) | 101 | void __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 | */ | ||
33 | ENTRY(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 | ||
52 | 1: sub r2, r2, #1 @ NumSets-- | ||
53 | mov r3, r4 @ Temp = NumWays | ||
54 | 2: 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 | ||
65 | ENDPROC(v7_invalidate_l1) | ||
66 | |||
67 | #ifdef CONFIG_SMP | 20 | #ifdef CONFIG_SMP |
68 | ENTRY(v7_secondary_startup) | 21 | ENTRY(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 | ||
21 | static 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 | |||
35 | static void __init imx31_dt_init(void) | 21 | static 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 | ||
41 | static const char *imx31_dt_board_compat[] __initdata = { | 26 | static 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 | ||
205 | static 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 | |||
213 | static void __init imx6q_init_late(void) | 203 | static 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 | ||
218 | static void __init imx6q_map_io(void) | 213 | static 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 | |||
23 | static void __iomem *scu_base; | 25 | static void __iomem *scu_base; |
24 | 26 | ||
25 | static struct map_desc scu_io_desc __initdata = { | 27 | static 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 | ||
47 | void 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 | |||
45 | static void __cpuinit imx_secondary_init(unsigned int cpu) | 55 | static 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 | ||