aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 14:02:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-07 14:02:18 -0400
commitfcba914542082b272f31c8e4c40000b88ed3208d (patch)
treefb28069bf571d93420daafd501b4e97f221d526c /arch/arm/mach-imx
parenta8c4b90e670be3b01e9395c7310639c8109fc77e (diff)
parent5c5f0421a8eea5bdaba9b9313c5bb4833aeb39cd (diff)
Merge tag 'soc-for-linus-3' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform updates (part 3) from Arnd Bergmann: "This is the third and smallest of the SoC specific updates. Changes include: - SMP support for the Xilinx zynq platform - Smaller imx changes - LPAE support for mvebu - Moving the orion5x, kirkwood, dove and mvebu platforms to a common "mbus" driver for their internal devices. It would be good to get feedback on the location of the "mbus" driver. Since this is used on multiple platforms may potentially get shared with other architectures (powerpc and arm64), it was moved to drivers/bus/. We expect other similar drivers to get moved to the same place in order to avoid creating more top-level directories under drivers/ or cluttering up the messy drivers/misc/ even more." * tag 'soc-for-linus-3' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (50 commits) ARM: imx: reset_controller may be disabled ARM: mvebu: Align the internal registers virtual base to support LPAE ARM: mvebu: Limit the DMA zone when LPAE is selected arm: plat-orion: remove addr-map code arm: mach-mv78xx0: convert to use the mvebu-mbus driver arm: mach-orion5x: convert to use mvebu-mbus driver arm: mach-dove: convert to use mvebu-mbus driver arm: mach-kirkwood: convert to use mvebu-mbus driver arm: mach-mvebu: convert to use mvebu-mbus driver ARM i.MX53: set CLK_SET_RATE_PARENT flag on the tve_ext_sel clock ARM i.MX53: tve_di clock is not part of the CCM, but of TVE ARM i.MX53: make tve_ext_sel propagate rate change to PLL ARM i.MX53: Remove unused tve_gate clkdev entry ARM i.MX5: Remove tve_sel clock from i.MX53 clock tree ARM: i.MX5: Add PATA and SRTC clocks ARM: imx: do not bring up unavailable cores ARM: imx: add initial imx6dl support ARM: imx1: mm: add call to mxc_device_init ARM: imx_v4_v5_defconfig: Add CONFIG_GPIO_SYSFS ARM: imx_v6_v7_defconfig: Select CONFIG_PERF_EVENTS ...
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/Kconfig10
-rw-r--r--arch/arm/mach-imx/Makefile1
-rw-r--r--arch/arm/mach-imx/anatop.c103
-rw-r--r--arch/arm/mach-imx/clk-imx51-imx53.c75
-rw-r--r--arch/arm/mach-imx/clk-imx6q.c126
-rw-r--r--arch/arm/mach-imx/clk.h17
-rw-r--r--arch/arm/mach-imx/common.h10
-rw-r--r--arch/arm/mach-imx/gpc.c23
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c74
-rw-r--r--arch/arm/mach-imx/mm-imx1.c2
-rw-r--r--arch/arm/mach-imx/mxc.h11
-rw-r--r--arch/arm/mach-imx/platsmp.c4
-rw-r--r--arch/arm/mach-imx/pm-imx6q.c4
-rw-r--r--arch/arm/mach-imx/src.c66
14 files changed, 444 insertions, 82 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 2ebc97e16b91..78f795d73cb6 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -65,6 +65,9 @@ config IRAM_ALLOC
65 bool 65 bool
66 select GENERIC_ALLOCATOR 66 select GENERIC_ALLOCATOR
67 67
68config HAVE_IMX_ANATOP
69 bool
70
68config HAVE_IMX_GPC 71config HAVE_IMX_GPC
69 bool 72 bool
70 73
@@ -73,6 +76,7 @@ config HAVE_IMX_MMDC
73 76
74config HAVE_IMX_SRC 77config HAVE_IMX_SRC
75 def_bool y if SMP 78 def_bool y if SMP
79 select ARCH_HAS_RESET_CONTROLLER
76 80
77config IMX_HAVE_IOMUX_V1 81config IMX_HAVE_IOMUX_V1
78 bool 82 bool
@@ -115,6 +119,8 @@ config SOC_IMX25
115 119
116config SOC_IMX27 120config SOC_IMX27
117 bool 121 bool
122 select ARCH_HAS_CPUFREQ
123 select ARCH_HAS_OPP
118 select COMMON_CLK 124 select COMMON_CLK
119 select CPU_ARM926T 125 select CPU_ARM926T
120 select IMX_HAVE_IOMUX_V1 126 select IMX_HAVE_IOMUX_V1
@@ -142,6 +148,7 @@ config SOC_IMX35
142config SOC_IMX5 148config SOC_IMX5
143 bool 149 bool
144 select ARCH_HAS_CPUFREQ 150 select ARCH_HAS_CPUFREQ
151 select ARCH_HAS_OPP
145 select ARCH_MXC_IOMUX_V3 152 select ARCH_MXC_IOMUX_V3
146 select COMMON_CLK 153 select COMMON_CLK
147 select CPU_V7 154 select CPU_V7
@@ -783,7 +790,7 @@ config SOC_IMX53
783 This enables support for Freescale i.MX53 processor. 790 This enables support for Freescale i.MX53 processor.
784 791
785config SOC_IMX6Q 792config SOC_IMX6Q
786 bool "i.MX6 Quad support" 793 bool "i.MX6 Quad/DualLite support"
787 select ARCH_HAS_CPUFREQ 794 select ARCH_HAS_CPUFREQ
788 select ARCH_HAS_OPP 795 select ARCH_HAS_OPP
789 select ARM_CPU_SUSPEND if PM 796 select ARM_CPU_SUSPEND if PM
@@ -796,6 +803,7 @@ config SOC_IMX6Q
796 select HAVE_ARM_SCU if SMP 803 select HAVE_ARM_SCU if SMP
797 select HAVE_ARM_TWD if LOCAL_TIMERS 804 select HAVE_ARM_TWD if LOCAL_TIMERS
798 select HAVE_CAN_FLEXCAN if CAN 805 select HAVE_CAN_FLEXCAN if CAN
806 select HAVE_IMX_ANATOP
799 select HAVE_IMX_GPC 807 select HAVE_IMX_GPC
800 select HAVE_IMX_MMDC 808 select HAVE_IMX_MMDC
801 select HAVE_IMX_SRC 809 select HAVE_IMX_SRC
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index fbe60a145344..930958973f81 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -91,6 +91,7 @@ obj-$(CONFIG_MACH_EUKREA_CPUIMX35SD) += mach-cpuimx35.o
91obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o 91obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o
92obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o 92obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
93 93
94obj-$(CONFIG_HAVE_IMX_ANATOP) += anatop.o
94obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o 95obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
95obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o 96obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
96obj-$(CONFIG_HAVE_IMX_SRC) += src.o 97obj-$(CONFIG_HAVE_IMX_SRC) += src.o
diff --git a/arch/arm/mach-imx/anatop.c b/arch/arm/mach-imx/anatop.c
new file mode 100644
index 000000000000..0cfa07dd9aa4
--- /dev/null
+++ b/arch/arm/mach-imx/anatop.c
@@ -0,0 +1,103 @@
1/*
2 * Copyright (C) 2013 Freescale Semiconductor, Inc.
3 *
4 * The code contained herein is licensed under the GNU General Public
5 * License. You may obtain a copy of the GNU General Public License
6 * Version 2 or later at the following locations:
7 *
8 * http://www.opensource.org/licenses/gpl-license.html
9 * http://www.gnu.org/copyleft/gpl.html
10 */
11
12#include <linux/err.h>
13#include <linux/io.h>
14#include <linux/of.h>
15#include <linux/of_address.h>
16#include <linux/mfd/syscon.h>
17#include <linux/regmap.h>
18#include "common.h"
19
20#define REG_SET 0x4
21#define REG_CLR 0x8
22
23#define ANADIG_REG_2P5 0x130
24#define ANADIG_REG_CORE 0x140
25#define ANADIG_ANA_MISC0 0x150
26#define ANADIG_USB1_CHRG_DETECT 0x1b0
27#define ANADIG_USB2_CHRG_DETECT 0x210
28#define ANADIG_DIGPROG 0x260
29
30#define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG 0x40000
31#define BM_ANADIG_REG_CORE_FET_ODRIVE 0x20000000
32#define BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG 0x1000
33#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x80000
34#define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x100000
35
36static struct regmap *anatop;
37
38static void imx_anatop_enable_weak2p5(bool enable)
39{
40 u32 reg, val;
41
42 regmap_read(anatop, ANADIG_ANA_MISC0, &val);
43
44 /* can only be enabled when stop_mode_config is clear. */
45 reg = ANADIG_REG_2P5;
46 reg += (enable && (val & BM_ANADIG_ANA_MISC0_STOP_MODE_CONFIG) == 0) ?
47 REG_SET : REG_CLR;
48 regmap_write(anatop, reg, BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG);
49}
50
51static void imx_anatop_enable_fet_odrive(bool enable)
52{
53 regmap_write(anatop, ANADIG_REG_CORE + (enable ? REG_SET : REG_CLR),
54 BM_ANADIG_REG_CORE_FET_ODRIVE);
55}
56
57void imx_anatop_pre_suspend(void)
58{
59 imx_anatop_enable_weak2p5(true);
60 imx_anatop_enable_fet_odrive(true);
61}
62
63void imx_anatop_post_resume(void)
64{
65 imx_anatop_enable_fet_odrive(false);
66 imx_anatop_enable_weak2p5(false);
67}
68
69void imx_anatop_usb_chrg_detect_disable(void)
70{
71 regmap_write(anatop, ANADIG_USB1_CHRG_DETECT,
72 BM_ANADIG_USB_CHRG_DETECT_EN_B
73 | BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
74 regmap_write(anatop, ANADIG_USB2_CHRG_DETECT,
75 BM_ANADIG_USB_CHRG_DETECT_EN_B |
76 BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
77}
78
79u32 imx_anatop_get_digprog(void)
80{
81 struct device_node *np;
82 void __iomem *anatop_base;
83 static u32 digprog;
84
85 if (digprog)
86 return digprog;
87
88 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
89 anatop_base = of_iomap(np, 0);
90 WARN_ON(!anatop_base);
91 digprog = readl_relaxed(anatop_base + ANADIG_DIGPROG);
92
93 return digprog;
94}
95
96void __init imx_anatop_init(void)
97{
98 anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop");
99 if (IS_ERR(anatop)) {
100 pr_err("%s: failed to find imx6q-anatop regmap!\n", __func__);
101 return;
102 }
103}
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index 2bc623b414c1..6fc486b6a3c6 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -45,16 +45,40 @@ static const char *mx53_ipu_di1_sel[] = { "di_pred", "osc", "ckih1", "tve_di", "
45static const char *mx53_ldb_di1_sel[] = { "pll3_sw", "pll4_sw", }; 45static const char *mx53_ldb_di1_sel[] = { "pll3_sw", "pll4_sw", };
46static const char *mx51_tve_ext_sel[] = { "osc", "ckih1", }; 46static const char *mx51_tve_ext_sel[] = { "osc", "ckih1", };
47static const char *mx53_tve_ext_sel[] = { "pll4_sw", "ckih1", }; 47static const char *mx53_tve_ext_sel[] = { "pll4_sw", "ckih1", };
48static const char *tve_sel[] = { "tve_pred", "tve_ext_sel", }; 48static const char *mx51_tve_sel[] = { "tve_pred", "tve_ext_sel", };
49static const char *ipu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", }; 49static const char *ipu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
50static const char *gpu3d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" };
51static const char *gpu2d_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb" };
50static const char *vpu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", }; 52static const char *vpu_sel[] = { "axi_a", "axi_b", "emi_slow_gate", "ahb", };
51static const char *mx53_can_sel[] = { "ipg", "ckih1", "ckih2", "lp_apm", }; 53static const char *mx53_can_sel[] = { "ipg", "ckih1", "ckih2", "lp_apm", };
54static const char *mx53_cko1_sel[] = {
55 "cpu_podf", "pll1_sw", "pll2_sw", "pll3_sw",
56 "emi_slow_podf", "pll4_sw", "nfc_podf", "dummy",
57 "di_pred", "dummy", "dummy", "ahb",
58 "ipg", "per_root", "ckil", "dummy",};
59static const char *mx53_cko2_sel[] = {
60 "dummy"/* dptc_core */, "dummy"/* dptc_perich */,
61 "dummy", "esdhc_a_podf",
62 "usboh3_podf", "dummy"/* wrck_clk_root */,
63 "ecspi_podf", "dummy"/* pll1_ref_clk */,
64 "esdhc_b_podf", "dummy"/* ddr_clk_root */,
65 "dummy"/* arm_axi_clk_root */, "dummy"/* usb_phy_out */,
66 "vpu_sel", "ipu_sel",
67 "osc", "ckih1",
68 "dummy", "esdhc_c_sel",
69 "ssi1_root_podf", "ssi2_root_podf",
70 "dummy", "dummy",
71 "dummy"/* lpsr_clk_root */, "dummy"/* pgc_clk_root */,
72 "dummy"/* tve_out */, "usb_phy_sel",
73 "tve_sel", "lp_apm",
74 "uart_root", "dummy"/* spdif0_clk_root */,
75 "dummy", "dummy", };
52 76
53enum imx5_clks { 77enum imx5_clks {
54 dummy, ckil, osc, ckih1, ckih2, ahb, ipg, axi_a, axi_b, uart_pred, 78 dummy, ckil, osc, ckih1, ckih2, ahb, ipg, axi_a, axi_b, uart_pred,
55 uart_root, esdhc_a_pred, esdhc_b_pred, esdhc_c_s, esdhc_d_s, 79 uart_root, esdhc_a_pred, esdhc_b_pred, esdhc_c_s, esdhc_d_s,
56 emi_sel, emi_slow_podf, nfc_podf, ecspi_pred, ecspi_podf, usboh3_pred, 80 emi_sel, emi_slow_podf, nfc_podf, ecspi_pred, ecspi_podf, usboh3_pred,
57 usboh3_podf, usb_phy_pred, usb_phy_podf, cpu_podf, di_pred, tve_di, 81 usboh3_podf, usb_phy_pred, usb_phy_podf, cpu_podf, di_pred, tve_di_unused,
58 tve_s, uart1_ipg_gate, uart1_per_gate, uart2_ipg_gate, 82 tve_s, uart1_ipg_gate, uart1_per_gate, uart2_ipg_gate,
59 uart2_per_gate, uart3_ipg_gate, uart3_per_gate, i2c1_gate, i2c2_gate, 83 uart2_per_gate, uart3_ipg_gate, uart3_per_gate, i2c1_gate, i2c2_gate,
60 gpt_ipg_gate, pwm1_ipg_gate, pwm1_hf_gate, pwm2_ipg_gate, pwm2_hf_gate, 84 gpt_ipg_gate, pwm1_ipg_gate, pwm1_hf_gate, pwm2_ipg_gate, pwm2_hf_gate,
@@ -83,7 +107,10 @@ enum imx5_clks {
83 ssi2_root_gate, ssi3_root_gate, ssi_ext1_gate, ssi_ext2_gate, 107 ssi2_root_gate, ssi3_root_gate, ssi_ext1_gate, ssi_ext2_gate,
84 epit1_ipg_gate, epit1_hf_gate, epit2_ipg_gate, epit2_hf_gate, 108 epit1_ipg_gate, epit1_hf_gate, epit2_ipg_gate, epit2_hf_gate,
85 can_sel, can1_serial_gate, can1_ipg_gate, 109 can_sel, can1_serial_gate, can1_ipg_gate,
86 owire_gate, 110 owire_gate, gpu3d_s, gpu2d_s, gpu3d_gate, gpu2d_gate, garb_gate,
111 cko1_sel, cko1_podf, cko1,
112 cko2_sel, cko2_podf, cko2,
113 srtc_gate, pata_gate,
87 clk_max 114 clk_max
88}; 115};
89 116
@@ -160,8 +187,6 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
160 usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str)); 187 usb_phy_sel_str, ARRAY_SIZE(usb_phy_sel_str));
161 clk[cpu_podf] = imx_clk_divider("cpu_podf", "pll1_sw", MXC_CCM_CACRR, 0, 3); 188 clk[cpu_podf] = imx_clk_divider("cpu_podf", "pll1_sw", MXC_CCM_CACRR, 0, 3);
162 clk[di_pred] = imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3); 189 clk[di_pred] = imx_clk_divider("di_pred", "pll3_sw", MXC_CCM_CDCDR, 6, 3);
163 clk[tve_di] = imx_clk_fixed("tve_di", 65000000); /* FIXME */
164 clk[tve_s] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1, tve_sel, ARRAY_SIZE(tve_sel));
165 clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30); 190 clk[iim_gate] = imx_clk_gate2("iim_gate", "ipg", MXC_CCM_CCGR0, 30);
166 clk[uart1_ipg_gate] = imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6); 191 clk[uart1_ipg_gate] = imx_clk_gate2("uart1_ipg_gate", "ipg", MXC_CCM_CCGR1, 6);
167 clk[uart1_per_gate] = imx_clk_gate2("uart1_per_gate", "uart_root", MXC_CCM_CCGR1, 8); 192 clk[uart1_per_gate] = imx_clk_gate2("uart1_per_gate", "uart_root", MXC_CCM_CCGR1, 8);
@@ -200,6 +225,11 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
200 clk[nfc_gate] = imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20); 225 clk[nfc_gate] = imx_clk_gate2("nfc_gate", "nfc_podf", MXC_CCM_CCGR5, 20);
201 clk[ipu_di0_gate] = imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10); 226 clk[ipu_di0_gate] = imx_clk_gate2("ipu_di0_gate", "ipu_di0_sel", MXC_CCM_CCGR6, 10);
202 clk[ipu_di1_gate] = imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12); 227 clk[ipu_di1_gate] = imx_clk_gate2("ipu_di1_gate", "ipu_di1_sel", MXC_CCM_CCGR6, 12);
228 clk[gpu3d_s] = imx_clk_mux("gpu3d_sel", MXC_CCM_CBCMR, 4, 2, gpu3d_sel, ARRAY_SIZE(gpu3d_sel));
229 clk[gpu2d_s] = imx_clk_mux("gpu2d_sel", MXC_CCM_CBCMR, 16, 2, gpu2d_sel, ARRAY_SIZE(gpu2d_sel));
230 clk[gpu3d_gate] = imx_clk_gate2("gpu3d_gate", "gpu3d_sel", MXC_CCM_CCGR5, 2);
231 clk[garb_gate] = imx_clk_gate2("garb_gate", "axi_a", MXC_CCM_CCGR5, 4);
232 clk[gpu2d_gate] = imx_clk_gate2("gpu2d_gate", "gpu2d_sel", MXC_CCM_CCGR6, 14);
203 clk[vpu_s] = imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel)); 233 clk[vpu_s] = imx_clk_mux("vpu_sel", MXC_CCM_CBCMR, 14, 2, vpu_sel, ARRAY_SIZE(vpu_sel));
204 clk[vpu_gate] = imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6); 234 clk[vpu_gate] = imx_clk_gate2("vpu_gate", "vpu_sel", MXC_CCM_CCGR5, 6);
205 clk[vpu_reference_gate] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8); 235 clk[vpu_reference_gate] = imx_clk_gate2("vpu_reference_gate", "osc", MXC_CCM_CCGR5, 8);
@@ -235,6 +265,8 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
235 clk[epit2_ipg_gate] = imx_clk_gate2("epit2_ipg_gate", "ipg", MXC_CCM_CCGR2, 6); 265 clk[epit2_ipg_gate] = imx_clk_gate2("epit2_ipg_gate", "ipg", MXC_CCM_CCGR2, 6);
236 clk[epit2_hf_gate] = imx_clk_gate2("epit2_hf_gate", "per_root", MXC_CCM_CCGR2, 8); 266 clk[epit2_hf_gate] = imx_clk_gate2("epit2_hf_gate", "per_root", MXC_CCM_CCGR2, 8);
237 clk[owire_gate] = imx_clk_gate2("owire_gate", "per_root", MXC_CCM_CCGR2, 22); 267 clk[owire_gate] = imx_clk_gate2("owire_gate", "per_root", MXC_CCM_CCGR2, 22);
268 clk[srtc_gate] = imx_clk_gate2("srtc_gate", "per_root", MXC_CCM_CCGR4, 28);
269 clk[pata_gate] = imx_clk_gate2("pata_gate", "ipg", MXC_CCM_CCGR4, 0);
238 270
239 for (i = 0; i < ARRAY_SIZE(clk); i++) 271 for (i = 0; i < ARRAY_SIZE(clk); i++)
240 if (IS_ERR(clk[i])) 272 if (IS_ERR(clk[i]))
@@ -286,7 +318,6 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
286 clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.0"); 318 clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.0");
287 clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.1"); 319 clk_register_clkdev(clk[dummy], NULL, "imx2-wdt.1");
288 clk_register_clkdev(clk[dummy], NULL, "imx-keypad"); 320 clk_register_clkdev(clk[dummy], NULL, "imx-keypad");
289 clk_register_clkdev(clk[tve_gate], NULL, "imx-tve.0");
290 clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx-tve.0"); 321 clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx-tve.0");
291 clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL); 322 clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL);
292 clk_register_clkdev(clk[epit1_ipg_gate], "ipg", "imx-epit.0"); 323 clk_register_clkdev(clk[epit1_ipg_gate], "ipg", "imx-epit.0");
@@ -331,8 +362,10 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
331 mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel)); 362 mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel));
332 clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, 363 clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
333 mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel)); 364 mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel));
334 clk[tve_ext_sel] = imx_clk_mux("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, 365 clk[tve_ext_sel] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
335 mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel)); 366 mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel), CLK_SET_RATE_PARENT);
367 clk[tve_s] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1,
368 mx51_tve_sel, ARRAY_SIZE(mx51_tve_sel));
336 clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30); 369 clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_sel", MXC_CCM_CCGR2, 30);
337 clk[tve_pred] = imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3); 370 clk[tve_pred] = imx_clk_divider("tve_pred", "pll3_sw", MXC_CCM_CDCDR, 28, 3);
338 clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); 371 clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
@@ -420,23 +453,23 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
420 clk[pll3_sw] = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE); 453 clk[pll3_sw] = imx_clk_pllv2("pll3_sw", "osc", MX53_DPLL3_BASE);
421 clk[pll4_sw] = imx_clk_pllv2("pll4_sw", "osc", MX53_DPLL4_BASE); 454 clk[pll4_sw] = imx_clk_pllv2("pll4_sw", "osc", MX53_DPLL4_BASE);
422 455
423 clk[ldb_di1_sel] = imx_clk_mux("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1,
424 mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel));
425 clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); 456 clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
426 clk[ldb_di1_div] = imx_clk_divider("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1); 457 clk[ldb_di1_div] = imx_clk_divider_flags("ldb_di1_div", "ldb_di1_div_3_5", MXC_CCM_CSCMR2, 11, 1, 0);
458 clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", MXC_CCM_CSCMR2, 9, 1,
459 mx53_ldb_di1_sel, ARRAY_SIZE(mx53_ldb_di1_sel), CLK_SET_RATE_PARENT);
427 clk[di_pll4_podf] = imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3); 460 clk[di_pll4_podf] = imx_clk_divider("di_pll4_podf", "pll4_sw", MXC_CCM_CDCDR, 16, 3);
428 clk[ldb_di0_sel] = imx_clk_mux("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1,
429 mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel));
430 clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); 461 clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
431 clk[ldb_di0_div] = imx_clk_divider("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1); 462 clk[ldb_di0_div] = imx_clk_divider_flags("ldb_di0_div", "ldb_di0_div_3_5", MXC_CCM_CSCMR2, 10, 1, 0);
463 clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", MXC_CCM_CSCMR2, 8, 1,
464 mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT);
432 clk[ldb_di0_gate] = imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28); 465 clk[ldb_di0_gate] = imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28);
433 clk[ldb_di1_gate] = imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30); 466 clk[ldb_di1_gate] = imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30);
434 clk[ipu_di0_sel] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, 467 clk[ipu_di0_sel] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
435 mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel)); 468 mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel));
436 clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, 469 clk[ipu_di1_sel] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
437 mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel)); 470 mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel));
438 clk[tve_ext_sel] = imx_clk_mux("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, 471 clk[tve_ext_sel] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
439 mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel)); 472 mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT);
440 clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30); 473 clk[tve_gate] = imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30);
441 clk[tve_pred] = imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3); 474 clk[tve_pred] = imx_clk_divider("tve_pred", "tve_ext_sel", MXC_CCM_CDCDR, 28, 3);
442 clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2); 475 clk[esdhc1_per_gate] = imx_clk_gate2("esdhc1_per_gate", "esdhc_a_podf", MXC_CCM_CCGR3, 2);
@@ -453,6 +486,16 @@ int __init mx53_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
453 clk[can2_ipg_gate] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6); 486 clk[can2_ipg_gate] = imx_clk_gate2("can2_ipg_gate", "ipg", MXC_CCM_CCGR4, 6);
454 clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22); 487 clk[i2c3_gate] = imx_clk_gate2("i2c3_gate", "per_root", MXC_CCM_CCGR1, 22);
455 488
489 clk[cko1_sel] = imx_clk_mux("cko1_sel", MXC_CCM_CCOSR, 0, 4,
490 mx53_cko1_sel, ARRAY_SIZE(mx53_cko1_sel));
491 clk[cko1_podf] = imx_clk_divider("cko1_podf", "cko1_sel", MXC_CCM_CCOSR, 4, 3);
492 clk[cko1] = imx_clk_gate2("cko1", "cko1_podf", MXC_CCM_CCOSR, 7);
493
494 clk[cko2_sel] = imx_clk_mux("cko2_sel", MXC_CCM_CCOSR, 16, 5,
495 mx53_cko2_sel, ARRAY_SIZE(mx53_cko2_sel));
496 clk[cko2_podf] = imx_clk_divider("cko2_podf", "cko2_sel", MXC_CCM_CCOSR, 21, 3);
497 clk[cko2] = imx_clk_gate2("cko2", "cko2_podf", MXC_CCM_CCOSR, 24);
498
456 for (i = 0; i < ARRAY_SIZE(clk); i++) 499 for (i = 0; i < ARRAY_SIZE(clk); i++)
457 if (IS_ERR(clk[i])) 500 if (IS_ERR(clk[i]))
458 pr_err("i.MX53 clk %d: register failed with %ld\n", 501 pr_err("i.MX53 clk %d: register failed with %ld\n",
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index d38e54f5b6d7..151259003086 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 2011 Freescale Semiconductor, Inc. 2 * Copyright 2011-2013 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd. 3 * Copyright 2011 Linaro Ltd.
4 * 4 *
5 * The code contained herein is licensed under the GNU General Public 5 * The code contained herein is licensed under the GNU General Public
@@ -14,6 +14,7 @@
14#include <linux/types.h> 14#include <linux/types.h>
15#include <linux/clk.h> 15#include <linux/clk.h>
16#include <linux/clkdev.h> 16#include <linux/clkdev.h>
17#include <linux/delay.h>
17#include <linux/err.h> 18#include <linux/err.h>
18#include <linux/io.h> 19#include <linux/io.h>
19#include <linux/of.h> 20#include <linux/of.h>
@@ -22,6 +23,12 @@
22 23
23#include "clk.h" 24#include "clk.h"
24#include "common.h" 25#include "common.h"
26#include "hardware.h"
27
28#define CCR 0x0
29#define BM_CCR_WB_COUNT (0x7 << 16)
30#define BM_CCR_RBC_BYPASS_COUNT (0x3f << 21)
31#define BM_CCR_RBC_EN (0x1 << 27)
25 32
26#define CCGR0 0x68 33#define CCGR0 0x68
27#define CCGR1 0x6c 34#define CCGR1 0x6c
@@ -67,6 +74,67 @@ void imx6q_set_chicken_bit(void)
67 writel_relaxed(val, ccm_base + CGPR); 74 writel_relaxed(val, ccm_base + CGPR);
68} 75}
69 76
77static void imx6q_enable_rbc(bool enable)
78{
79 u32 val;
80 static bool last_rbc_mode;
81
82 if (last_rbc_mode == enable)
83 return;
84 /*
85 * need to mask all interrupts in GPC before
86 * operating RBC configurations
87 */
88 imx_gpc_mask_all();
89
90 /* configure RBC enable bit */
91 val = readl_relaxed(ccm_base + CCR);
92 val &= ~BM_CCR_RBC_EN;
93 val |= enable ? BM_CCR_RBC_EN : 0;
94 writel_relaxed(val, ccm_base + CCR);
95
96 /* configure RBC count */
97 val = readl_relaxed(ccm_base + CCR);
98 val &= ~BM_CCR_RBC_BYPASS_COUNT;
99 val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
100 writel(val, ccm_base + CCR);
101
102 /*
103 * need to delay at least 2 cycles of CKIL(32K)
104 * due to hardware design requirement, which is
105 * ~61us, here we use 65us for safe
106 */
107 udelay(65);
108
109 /* restore GPC interrupt mask settings */
110 imx_gpc_restore_all();
111
112 last_rbc_mode = enable;
113}
114
115static void imx6q_enable_wb(bool enable)
116{
117 u32 val;
118 static bool last_wb_mode;
119
120 if (last_wb_mode == enable)
121 return;
122
123 /* configure well bias enable bit */
124 val = readl_relaxed(ccm_base + CLPCR);
125 val &= ~BM_CLPCR_WB_PER_AT_LPM;
126 val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
127 writel_relaxed(val, ccm_base + CLPCR);
128
129 /* configure well bias count */
130 val = readl_relaxed(ccm_base + CCR);
131 val &= ~BM_CCR_WB_COUNT;
132 val |= enable ? BM_CCR_WB_COUNT : 0;
133 writel_relaxed(val, ccm_base + CCR);
134
135 last_wb_mode = enable;
136}
137
70int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode) 138int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
71{ 139{
72 u32 val = readl_relaxed(ccm_base + CLPCR); 140 u32 val = readl_relaxed(ccm_base + CLPCR);
@@ -74,6 +142,8 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
74 val &= ~BM_CLPCR_LPM; 142 val &= ~BM_CLPCR_LPM;
75 switch (mode) { 143 switch (mode) {
76 case WAIT_CLOCKED: 144 case WAIT_CLOCKED:
145 imx6q_enable_wb(false);
146 imx6q_enable_rbc(false);
77 break; 147 break;
78 case WAIT_UNCLOCKED: 148 case WAIT_UNCLOCKED:
79 val |= 0x1 << BP_CLPCR_LPM; 149 val |= 0x1 << BP_CLPCR_LPM;
@@ -92,6 +162,8 @@ int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
92 val |= 0x3 << BP_CLPCR_STBY_COUNT; 162 val |= 0x3 << BP_CLPCR_STBY_COUNT;
93 val |= BM_CLPCR_VSTBY; 163 val |= BM_CLPCR_VSTBY;
94 val |= BM_CLPCR_SBYOS; 164 val |= BM_CLPCR_SBYOS;
165 imx6q_enable_wb(true);
166 imx6q_enable_rbc(true);
95 break; 167 break;
96 default: 168 default:
97 return -EINVAL; 169 return -EINVAL;
@@ -109,29 +181,29 @@ static const char *periph_clk2_sels[] = { "pll3_usb_otg", "osc", };
109static const char *periph_sels[] = { "periph_pre", "periph_clk2", }; 181static const char *periph_sels[] = { "periph_pre", "periph_clk2", };
110static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", }; 182static const char *periph2_sels[] = { "periph2_pre", "periph2_clk2", };
111static const char *axi_sels[] = { "periph", "pll2_pfd2_396m", "pll3_pfd1_540m", }; 183static const char *axi_sels[] = { "periph", "pll2_pfd2_396m", "pll3_pfd1_540m", };
112static const char *audio_sels[] = { "pll4_audio", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", }; 184static const char *audio_sels[] = { "pll4_post_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
113static const char *gpu_axi_sels[] = { "axi", "ahb", }; 185static const char *gpu_axi_sels[] = { "axi", "ahb", };
114static const char *gpu2d_core_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", }; 186static const char *gpu2d_core_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", };
115static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", }; 187static const char *gpu3d_core_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
116static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", }; 188static const char *gpu3d_shader_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd9_720m", };
117static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", }; 189static const char *ipu_sels[] = { "mmdc_ch0_axi", "pll2_pfd2_396m", "pll3_120m", "pll3_pfd1_540m", };
118static const char *ldb_di_sels[] = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", }; 190static const char *ldb_di_sels[] = { "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "mmdc_ch1_axi", "pll3_usb_otg", };
119static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", }; 191static const char *ipu_di_pre_sels[] = { "mmdc_ch0_axi", "pll3_usb_otg", "pll5_video_div", "pll2_pfd0_352m", "pll2_pfd2_396m", "pll3_pfd1_540m", };
120static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; 192static const char *ipu1_di0_sels[] = { "ipu1_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
121static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; 193static const char *ipu1_di1_sels[] = { "ipu1_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
122static const char *ipu2_di0_sels[] = { "ipu2_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; 194static const char *ipu2_di0_sels[] = { "ipu2_di0_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
123static const char *ipu2_di1_sels[] = { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", }; 195static const char *ipu2_di1_sels[] = { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
124static const char *hsi_tx_sels[] = { "pll3_120m", "pll2_pfd2_396m", }; 196static const char *hsi_tx_sels[] = { "pll3_120m", "pll2_pfd2_396m", };
125static const char *pcie_axi_sels[] = { "axi", "ahb", }; 197static const char *pcie_axi_sels[] = { "axi", "ahb", };
126static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio", }; 198static const char *ssi_sels[] = { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_post_div", };
127static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", }; 199static const char *usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
128static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", }; 200static const char *enfc_sels[] = { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", };
129static const char *emi_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", }; 201static const char *emi_sels[] = { "axi", "pll3_usb_otg", "pll2_pfd2_396m", "pll2_pfd0_352m", };
130static const char *vdo_axi_sels[] = { "axi", "ahb", }; 202static const char *vdo_axi_sels[] = { "axi", "ahb", };
131static const char *vpu_axi_sels[] = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", }; 203static const char *vpu_axi_sels[] = { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", };
132static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video", 204static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
133 "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0", 205 "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
134 "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio", }; 206 "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_post_div", };
135 207
136enum mx6q_clks { 208enum mx6q_clks {
137 dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m, 209 dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
@@ -165,7 +237,7 @@ enum mx6q_clks {
165 pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg, 237 pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg,
166 ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5, 238 ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
167 sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate, 239 sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
168 usbphy2_gate, clk_max 240 usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, clk_max
169}; 241};
170 242
171static struct clk *clk[clk_max]; 243static struct clk *clk[clk_max];
@@ -182,6 +254,21 @@ static struct clk_div_table clk_enet_ref_table[] = {
182 { .val = 3, .div = 4, }, 254 { .val = 3, .div = 4, },
183}; 255};
184 256
257static struct clk_div_table post_div_table[] = {
258 { .val = 2, .div = 1, },
259 { .val = 1, .div = 2, },
260 { .val = 0, .div = 4, },
261 { }
262};
263
264static struct clk_div_table video_div_table[] = {
265 { .val = 0, .div = 1, },
266 { .val = 1, .div = 2, },
267 { .val = 2, .div = 1, },
268 { .val = 3, .div = 4, },
269 { }
270};
271
185int __init mx6q_clocks_init(void) 272int __init mx6q_clocks_init(void)
186{ 273{
187 struct device_node *np; 274 struct device_node *np;
@@ -208,6 +295,14 @@ int __init mx6q_clocks_init(void)
208 base = of_iomap(np, 0); 295 base = of_iomap(np, 0);
209 WARN_ON(!base); 296 WARN_ON(!base);
210 297
298 /* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
299 if (cpu_is_imx6q() && imx6q_revision() == IMX_CHIP_REVISION_1_0) {
300 post_div_table[1].div = 1;
301 post_div_table[2].div = 1;
302 video_div_table[1].div = 1;
303 video_div_table[2].div = 1;
304 };
305
211 /* type name parent_name base div_mask */ 306 /* type name parent_name base div_mask */
212 clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f); 307 clk[pll1_sys] = imx_clk_pllv3(IMX_PLLV3_SYS, "pll1_sys", "osc", base, 0x7f);
213 clk[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1); 308 clk[pll2_bus] = imx_clk_pllv3(IMX_PLLV3_GENERIC, "pll2_bus", "osc", base + 0x30, 0x1);
@@ -260,6 +355,10 @@ int __init mx6q_clocks_init(void)
260 clk[pll3_60m] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8); 355 clk[pll3_60m] = imx_clk_fixed_factor("pll3_60m", "pll3_usb_otg", 1, 8);
261 clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2); 356 clk[twd] = imx_clk_fixed_factor("twd", "arm", 1, 2);
262 357
358 clk[pll4_post_div] = clk_register_divider_table(NULL, "pll4_post_div", "pll4_audio", CLK_SET_RATE_PARENT, base + 0x70, 19, 2, 0, post_div_table, &imx_ccm_lock);
359 clk[pll5_post_div] = clk_register_divider_table(NULL, "pll5_post_div", "pll5_video", CLK_SET_RATE_PARENT, base + 0xa0, 19, 2, 0, post_div_table, &imx_ccm_lock);
360 clk[pll5_video_div] = clk_register_divider_table(NULL, "pll5_video_div", "pll5_post_div", CLK_SET_RATE_PARENT, base + 0x170, 30, 2, 0, video_div_table, &imx_ccm_lock);
361
263 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm"); 362 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ccm");
264 base = of_iomap(np, 0); 363 base = of_iomap(np, 0);
265 WARN_ON(!base); 364 WARN_ON(!base);
@@ -283,8 +382,8 @@ int __init mx6q_clocks_init(void)
283 clk[gpu3d_shader_sel] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels)); 382 clk[gpu3d_shader_sel] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
284 clk[ipu1_sel] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); 383 clk[ipu1_sel] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
285 clk[ipu2_sel] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels)); 384 clk[ipu2_sel] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
286 clk[ldb_di0_sel] = imx_clk_mux("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels)); 385 clk[ldb_di0_sel] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
287 clk[ldb_di1_sel] = imx_clk_mux("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels)); 386 clk[ldb_di1_sel] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
288 clk[ipu1_di0_pre_sel] = imx_clk_mux("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); 387 clk[ipu1_di0_pre_sel] = imx_clk_mux("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
289 clk[ipu1_di1_pre_sel] = imx_clk_mux("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); 388 clk[ipu1_di1_pre_sel] = imx_clk_mux("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
290 clk[ipu2_di0_pre_sel] = imx_clk_mux("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels)); 389 clk[ipu2_di0_pre_sel] = imx_clk_mux("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
@@ -332,9 +431,9 @@ int __init mx6q_clocks_init(void)
332 clk[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3); 431 clk[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", base + 0x3c, 11, 3);
333 clk[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3); 432 clk[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", base + 0x3c, 16, 3);
334 clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7); 433 clk[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
335 clk[ldb_di0_podf] = imx_clk_divider("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1); 434 clk[ldb_di0_podf] = imx_clk_divider_flags("ldb_di0_podf", "ldb_di0_div_3_5", base + 0x20, 10, 1, 0);
336 clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7); 435 clk[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
337 clk[ldb_di1_podf] = imx_clk_divider("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1); 436 clk[ldb_di1_podf] = imx_clk_divider_flags("ldb_di1_podf", "ldb_di1_div_3_5", base + 0x20, 11, 1, 0);
338 clk[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3); 437 clk[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", base + 0x34, 3, 3);
339 clk[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3); 438 clk[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", base + 0x34, 12, 3);
340 clk[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3); 439 clk[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", base + 0x38, 3, 3);
@@ -448,6 +547,11 @@ int __init mx6q_clocks_init(void)
448 clk_register_clkdev(clk[cko1], "cko1", NULL); 547 clk_register_clkdev(clk[cko1], "cko1", NULL);
449 clk_register_clkdev(clk[arm], NULL, "cpu0"); 548 clk_register_clkdev(clk[arm], NULL, "cpu0");
450 549
550 if (imx6q_revision() != IMX_CHIP_REVISION_1_0) {
551 clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]);
552 clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
553 }
554
451 /* 555 /*
452 * The gpmi needs 100MHz frequency in the EDO/Sync mode, 556 * The gpmi needs 100MHz frequency in the EDO/Sync mode,
453 * We can not get the 100MHz from the pll2_pfd0_352m. 557 * We can not get the 100MHz from the pll2_pfd0_352m.
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 9d1f3b99d1d3..d9d9d9c66dff 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -59,6 +59,14 @@ static inline struct clk *imx_clk_divider(const char *name, const char *parent,
59 reg, shift, width, 0, &imx_ccm_lock); 59 reg, shift, width, 0, &imx_ccm_lock);
60} 60}
61 61
62static inline struct clk *imx_clk_divider_flags(const char *name,
63 const char *parent, void __iomem *reg, u8 shift, u8 width,
64 unsigned long flags)
65{
66 return clk_register_divider(NULL, name, parent, flags,
67 reg, shift, width, 0, &imx_ccm_lock);
68}
69
62static inline struct clk *imx_clk_gate(const char *name, const char *parent, 70static inline struct clk *imx_clk_gate(const char *name, const char *parent,
63 void __iomem *reg, u8 shift) 71 void __iomem *reg, u8 shift)
64{ 72{
@@ -73,6 +81,15 @@ static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
73 width, 0, &imx_ccm_lock); 81 width, 0, &imx_ccm_lock);
74} 82}
75 83
84static inline struct clk *imx_clk_mux_flags(const char *name,
85 void __iomem *reg, u8 shift, u8 width, const char **parents,
86 int num_parents, unsigned long flags)
87{
88 return clk_register_mux(NULL, name, parents, num_parents,
89 flags, reg, shift, width, 0,
90 &imx_ccm_lock);
91}
92
76static inline struct clk *imx_clk_fixed_factor(const char *name, 93static inline struct clk *imx_clk_fixed_factor(const char *name,
77 const char *parent, unsigned int mult, unsigned int div) 94 const char *parent, unsigned int mult, unsigned int div)
78{ 95{
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 9fea2522d7a3..4cba7dbb079f 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. 2 * Copyright 2004-2013 Freescale Semiconductor, Inc. All Rights Reserved.
3 */ 3 */
4 4
5/* 5/*
@@ -74,6 +74,7 @@ extern void mxc_set_cpu_type(unsigned int type);
74extern void mxc_restart(char, const char *); 74extern void mxc_restart(char, const char *);
75extern void mxc_arch_reset_init(void __iomem *); 75extern void mxc_arch_reset_init(void __iomem *);
76extern int mx53_revision(void); 76extern int mx53_revision(void);
77extern int imx6q_revision(void);
77extern int mx53_display_revision(void); 78extern int mx53_display_revision(void);
78extern void imx_set_aips(void __iomem *); 79extern void imx_set_aips(void __iomem *);
79extern int mxc_device_init(void); 80extern int mxc_device_init(void);
@@ -128,6 +129,13 @@ extern void imx_src_prepare_restart(void);
128extern void imx_gpc_init(void); 129extern void imx_gpc_init(void);
129extern void imx_gpc_pre_suspend(void); 130extern void imx_gpc_pre_suspend(void);
130extern void imx_gpc_post_resume(void); 131extern void imx_gpc_post_resume(void);
132extern void imx_gpc_mask_all(void);
133extern void imx_gpc_restore_all(void);
134extern void imx_anatop_init(void);
135extern void imx_anatop_pre_suspend(void);
136extern void imx_anatop_post_resume(void);
137extern void imx_anatop_usb_chrg_detect_disable(void);
138extern u32 imx_anatop_get_digprog(void);
131extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); 139extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
132extern void imx6q_set_chicken_bit(void); 140extern void imx6q_set_chicken_bit(void);
133 141
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 02b61cdf39b9..44a65e9ff1fc 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 2011 Freescale Semiconductor, Inc. 2 * Copyright 2011-2013 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd. 3 * Copyright 2011 Linaro Ltd.
4 * 4 *
5 * The code contained herein is licensed under the GNU General Public 5 * The code contained herein is licensed under the GNU General Public
@@ -69,6 +69,27 @@ static int imx_gpc_irq_set_wake(struct irq_data *d, unsigned int on)
69 return 0; 69 return 0;
70} 70}
71 71
72void imx_gpc_mask_all(void)
73{
74 void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
75 int i;
76
77 for (i = 0; i < IMR_NUM; i++) {
78 gpc_saved_imrs[i] = readl_relaxed(reg_imr1 + i * 4);
79 writel_relaxed(~0, reg_imr1 + i * 4);
80 }
81
82}
83
84void imx_gpc_restore_all(void)
85{
86 void __iomem *reg_imr1 = gpc_base + GPC_IMR1;
87 int i;
88
89 for (i = 0; i < IMR_NUM; i++)
90 writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
91}
92
72static void imx_gpc_irq_unmask(struct irq_data *d) 93static void imx_gpc_irq_unmask(struct irq_data *d)
73{ 94{
74 void __iomem *reg; 95 void __iomem *reg;
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 99502eeefdf7..5536fd81379a 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 2011 Freescale Semiconductor, Inc. 2 * Copyright 2011-2013 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd. 3 * Copyright 2011 Linaro Ltd.
4 * 4 *
5 * The code contained herein is licensed under the GNU General Public 5 * The code contained herein is licensed under the GNU General Public
@@ -38,38 +38,32 @@
38#include "cpuidle.h" 38#include "cpuidle.h"
39#include "hardware.h" 39#include "hardware.h"
40 40
41#define IMX6Q_ANALOG_DIGPROG 0x260 41static u32 chip_revision;
42 42
43static int imx6q_revision(void) 43int imx6q_revision(void)
44{ 44{
45 struct device_node *np; 45 return chip_revision;
46 void __iomem *base; 46}
47 static u32 rev; 47
48 48static void __init imx6q_init_revision(void)
49 if (!rev) { 49{
50 np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop"); 50 u32 rev = imx_anatop_get_digprog();
51 if (!np)
52 return IMX_CHIP_REVISION_UNKNOWN;
53 base = of_iomap(np, 0);
54 if (!base) {
55 of_node_put(np);
56 return IMX_CHIP_REVISION_UNKNOWN;
57 }
58 rev = readl_relaxed(base + IMX6Q_ANALOG_DIGPROG);
59 iounmap(base);
60 of_node_put(np);
61 }
62 51
63 switch (rev & 0xff) { 52 switch (rev & 0xff) {
64 case 0: 53 case 0:
65 return IMX_CHIP_REVISION_1_0; 54 chip_revision = IMX_CHIP_REVISION_1_0;
55 break;
66 case 1: 56 case 1:
67 return IMX_CHIP_REVISION_1_1; 57 chip_revision = IMX_CHIP_REVISION_1_1;
58 break;
68 case 2: 59 case 2:
69 return IMX_CHIP_REVISION_1_2; 60 chip_revision = IMX_CHIP_REVISION_1_2;
61 break;
70 default: 62 default:
71 return IMX_CHIP_REVISION_UNKNOWN; 63 chip_revision = IMX_CHIP_REVISION_UNKNOWN;
72 } 64 }
65
66 mxc_set_cpu_type(rev >> 16 & 0xff);
73} 67}
74 68
75static void imx6q_restart(char mode, const char *cmd) 69static void imx6q_restart(char mode, const char *cmd)
@@ -164,29 +158,7 @@ static void __init imx6q_1588_init(void)
164} 158}
165static void __init imx6q_usb_init(void) 159static void __init imx6q_usb_init(void)
166{ 160{
167 struct regmap *anatop; 161 imx_anatop_usb_chrg_detect_disable();
168
169#define HW_ANADIG_USB1_CHRG_DETECT 0x000001b0
170#define HW_ANADIG_USB2_CHRG_DETECT 0x00000210
171
172#define BM_ANADIG_USB_CHRG_DETECT_EN_B 0x00100000
173#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B 0x00080000
174
175 anatop = syscon_regmap_lookup_by_compatible("fsl,imx6q-anatop");
176 if (!IS_ERR(anatop)) {
177 /*
178 * The external charger detector needs to be disabled,
179 * or the signal at DP will be poor
180 */
181 regmap_write(anatop, HW_ANADIG_USB1_CHRG_DETECT,
182 BM_ANADIG_USB_CHRG_DETECT_EN_B
183 | BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
184 regmap_write(anatop, HW_ANADIG_USB2_CHRG_DETECT,
185 BM_ANADIG_USB_CHRG_DETECT_EN_B |
186 BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
187 } else {
188 pr_warn("failed to find fsl,imx6q-anatop regmap\n");
189 }
190} 162}
191 163
192static void __init imx6q_init_machine(void) 164static void __init imx6q_init_machine(void)
@@ -196,6 +168,7 @@ static void __init imx6q_init_machine(void)
196 168
197 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); 169 of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
198 170
171 imx_anatop_init();
199 imx6q_pm_init(); 172 imx6q_pm_init();
200 imx6q_usb_init(); 173 imx6q_usb_init();
201 imx6q_1588_init(); 174 imx6q_1588_init();
@@ -282,6 +255,7 @@ static void __init imx6q_map_io(void)
282 255
283static void __init imx6q_init_irq(void) 256static void __init imx6q_init_irq(void)
284{ 257{
258 imx6q_init_revision();
285 l2x0_of_init(0, ~0UL); 259 l2x0_of_init(0, ~0UL);
286 imx_src_init(); 260 imx_src_init();
287 imx_gpc_init(); 261 imx_gpc_init();
@@ -292,15 +266,17 @@ static void __init imx6q_timer_init(void)
292{ 266{
293 mx6q_clocks_init(); 267 mx6q_clocks_init();
294 clocksource_of_init(); 268 clocksource_of_init();
295 imx_print_silicon_rev("i.MX6Q", imx6q_revision()); 269 imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
270 imx6q_revision());
296} 271}
297 272
298static const char *imx6q_dt_compat[] __initdata = { 273static const char *imx6q_dt_compat[] __initdata = {
274 "fsl,imx6dl",
299 "fsl,imx6q", 275 "fsl,imx6q",
300 NULL, 276 NULL,
301}; 277};
302 278
303DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)") 279DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
304 .smp = smp_ops(imx_smp_ops), 280 .smp = smp_ops(imx_smp_ops),
305 .map_io = imx6q_map_io, 281 .map_io = imx6q_map_io,
306 .init_irq = imx6q_init_irq, 282 .init_irq = imx6q_init_irq,
diff --git a/arch/arm/mach-imx/mm-imx1.c b/arch/arm/mach-imx/mm-imx1.c
index 7a146671e65a..3c609c52d3eb 100644
--- a/arch/arm/mach-imx/mm-imx1.c
+++ b/arch/arm/mach-imx/mm-imx1.c
@@ -51,6 +51,8 @@ void __init mx1_init_irq(void)
51 51
52void __init imx1_soc_init(void) 52void __init imx1_soc_init(void)
53{ 53{
54 mxc_device_init();
55
54 mxc_register_gpio("imx1-gpio", 0, MX1_GPIO1_BASE_ADDR, SZ_256, 56 mxc_register_gpio("imx1-gpio", 0, MX1_GPIO1_BASE_ADDR, SZ_256,
55 MX1_GPIO_INT_PORTA, 0); 57 MX1_GPIO_INT_PORTA, 0);
56 mxc_register_gpio("imx1-gpio", 1, MX1_GPIO2_BASE_ADDR, SZ_256, 58 mxc_register_gpio("imx1-gpio", 1, MX1_GPIO2_BASE_ADDR, SZ_256,
diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h
index 7dce17a9fe6c..8629e5be7ecd 100644
--- a/arch/arm/mach-imx/mxc.h
+++ b/arch/arm/mach-imx/mxc.h
@@ -34,6 +34,8 @@
34#define MXC_CPU_MX35 35 34#define MXC_CPU_MX35 35
35#define MXC_CPU_MX51 51 35#define MXC_CPU_MX51 51
36#define MXC_CPU_MX53 53 36#define MXC_CPU_MX53 53
37#define MXC_CPU_IMX6DL 0x61
38#define MXC_CPU_IMX6Q 0x63
37 39
38#define IMX_CHIP_REVISION_1_0 0x10 40#define IMX_CHIP_REVISION_1_0 0x10
39#define IMX_CHIP_REVISION_1_1 0x11 41#define IMX_CHIP_REVISION_1_1 0x11
@@ -150,6 +152,15 @@ extern unsigned int __mxc_cpu_type;
150#endif 152#endif
151 153
152#ifndef __ASSEMBLY__ 154#ifndef __ASSEMBLY__
155static inline bool cpu_is_imx6dl(void)
156{
157 return __mxc_cpu_type == MXC_CPU_IMX6DL;
158}
159
160static inline bool cpu_is_imx6q(void)
161{
162 return __mxc_cpu_type == MXC_CPU_IMX6Q;
163}
153 164
154struct cpu_op { 165struct cpu_op {
155 u32 cpu_rate; 166 u32 cpu_rate;
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 77e9a25ed0f6..4a69305db65e 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -68,8 +68,8 @@ static void __init imx_smp_init_cpus(void)
68 68
69 ncores = scu_get_core_count(scu_base); 69 ncores = scu_get_core_count(scu_base);
70 70
71 for (i = 0; i < ncores; i++) 71 for (i = ncores; i < NR_CPUS; i++)
72 set_cpu_possible(i, true); 72 set_cpu_possible(i, false);
73} 73}
74 74
75void imx_smp_prepare(void) 75void imx_smp_prepare(void)
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
index 5faba7a3c95f..204942749e21 100644
--- a/arch/arm/mach-imx/pm-imx6q.c
+++ b/arch/arm/mach-imx/pm-imx6q.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright 2011 Freescale Semiconductor, Inc. 2 * Copyright 2011-2013 Freescale Semiconductor, Inc.
3 * Copyright 2011 Linaro Ltd. 3 * Copyright 2011 Linaro Ltd.
4 * 4 *
5 * The code contained herein is licensed under the GNU General Public 5 * The code contained herein is licensed under the GNU General Public
@@ -34,10 +34,12 @@ static int imx6q_pm_enter(suspend_state_t state)
34 case PM_SUSPEND_MEM: 34 case PM_SUSPEND_MEM:
35 imx6q_set_lpm(STOP_POWER_OFF); 35 imx6q_set_lpm(STOP_POWER_OFF);
36 imx_gpc_pre_suspend(); 36 imx_gpc_pre_suspend();
37 imx_anatop_pre_suspend();
37 imx_set_cpu_jump(0, v7_cpu_resume); 38 imx_set_cpu_jump(0, v7_cpu_resume);
38 /* Zzz ... */ 39 /* Zzz ... */
39 cpu_suspend(0, imx6q_suspend_finish); 40 cpu_suspend(0, imx6q_suspend_finish);
40 imx_smp_prepare(); 41 imx_smp_prepare();
42 imx_anatop_post_resume();
41 imx_gpc_post_resume(); 43 imx_gpc_post_resume();
42 imx6q_set_lpm(WAIT_CLOCKED); 44 imx6q_set_lpm(WAIT_CLOCKED);
43 break; 45 break;
diff --git a/arch/arm/mach-imx/src.c b/arch/arm/mach-imx/src.c
index 97d086889481..10a6b1a8c5ac 100644
--- a/arch/arm/mach-imx/src.c
+++ b/arch/arm/mach-imx/src.c
@@ -14,6 +14,7 @@
14#include <linux/io.h> 14#include <linux/io.h>
15#include <linux/of.h> 15#include <linux/of.h>
16#include <linux/of_address.h> 16#include <linux/of_address.h>
17#include <linux/reset-controller.h>
17#include <linux/smp.h> 18#include <linux/smp.h>
18#include <asm/smp_plat.h> 19#include <asm/smp_plat.h>
19#include "common.h" 20#include "common.h"
@@ -21,10 +22,65 @@
21#define SRC_SCR 0x000 22#define SRC_SCR 0x000
22#define SRC_GPR1 0x020 23#define SRC_GPR1 0x020
23#define BP_SRC_SCR_WARM_RESET_ENABLE 0 24#define BP_SRC_SCR_WARM_RESET_ENABLE 0
25#define BP_SRC_SCR_SW_GPU_RST 1
26#define BP_SRC_SCR_SW_VPU_RST 2
27#define BP_SRC_SCR_SW_IPU1_RST 3
28#define BP_SRC_SCR_SW_OPEN_VG_RST 4
29#define BP_SRC_SCR_SW_IPU2_RST 12
24#define BP_SRC_SCR_CORE1_RST 14 30#define BP_SRC_SCR_CORE1_RST 14
25#define BP_SRC_SCR_CORE1_ENABLE 22 31#define BP_SRC_SCR_CORE1_ENABLE 22
26 32
27static void __iomem *src_base; 33static void __iomem *src_base;
34static DEFINE_SPINLOCK(scr_lock);
35
36static const int sw_reset_bits[5] = {
37 BP_SRC_SCR_SW_GPU_RST,
38 BP_SRC_SCR_SW_VPU_RST,
39 BP_SRC_SCR_SW_IPU1_RST,
40 BP_SRC_SCR_SW_OPEN_VG_RST,
41 BP_SRC_SCR_SW_IPU2_RST
42};
43
44static int imx_src_reset_module(struct reset_controller_dev *rcdev,
45 unsigned long sw_reset_idx)
46{
47 unsigned long timeout;
48 unsigned long flags;
49 int bit;
50 u32 val;
51
52 if (!src_base)
53 return -ENODEV;
54
55 if (sw_reset_idx >= ARRAY_SIZE(sw_reset_bits))
56 return -EINVAL;
57
58 bit = 1 << sw_reset_bits[sw_reset_idx];
59
60 spin_lock_irqsave(&scr_lock, flags);
61 val = readl_relaxed(src_base + SRC_SCR);
62 val |= bit;
63 writel_relaxed(val, src_base + SRC_SCR);
64 spin_unlock_irqrestore(&scr_lock, flags);
65
66 timeout = jiffies + msecs_to_jiffies(1000);
67 while (readl(src_base + SRC_SCR) & bit) {
68 if (time_after(jiffies, timeout))
69 return -ETIME;
70 cpu_relax();
71 }
72
73 return 0;
74}
75
76static struct reset_control_ops imx_src_ops = {
77 .reset = imx_src_reset_module,
78};
79
80static struct reset_controller_dev imx_reset_controller = {
81 .ops = &imx_src_ops,
82 .nr_resets = ARRAY_SIZE(sw_reset_bits),
83};
28 84
29void imx_enable_cpu(int cpu, bool enable) 85void imx_enable_cpu(int cpu, bool enable)
30{ 86{
@@ -32,9 +88,11 @@ void imx_enable_cpu(int cpu, bool enable)
32 88
33 cpu = cpu_logical_map(cpu); 89 cpu = cpu_logical_map(cpu);
34 mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1); 90 mask = 1 << (BP_SRC_SCR_CORE1_ENABLE + cpu - 1);
91 spin_lock(&scr_lock);
35 val = readl_relaxed(src_base + SRC_SCR); 92 val = readl_relaxed(src_base + SRC_SCR);
36 val = enable ? val | mask : val & ~mask; 93 val = enable ? val | mask : val & ~mask;
37 writel_relaxed(val, src_base + SRC_SCR); 94 writel_relaxed(val, src_base + SRC_SCR);
95 spin_unlock(&scr_lock);
38} 96}
39 97
40void imx_set_cpu_jump(int cpu, void *jump_addr) 98void imx_set_cpu_jump(int cpu, void *jump_addr)
@@ -61,9 +119,11 @@ void imx_src_prepare_restart(void)
61 u32 val; 119 u32 val;
62 120
63 /* clear enable bits of secondary cores */ 121 /* clear enable bits of secondary cores */
122 spin_lock(&scr_lock);
64 val = readl_relaxed(src_base + SRC_SCR); 123 val = readl_relaxed(src_base + SRC_SCR);
65 val &= ~(0x7 << BP_SRC_SCR_CORE1_ENABLE); 124 val &= ~(0x7 << BP_SRC_SCR_CORE1_ENABLE);
66 writel_relaxed(val, src_base + SRC_SCR); 125 writel_relaxed(val, src_base + SRC_SCR);
126 spin_unlock(&scr_lock);
67 127
68 /* clear persistent entry register of primary core */ 128 /* clear persistent entry register of primary core */
69 writel_relaxed(0, src_base + SRC_GPR1); 129 writel_relaxed(0, src_base + SRC_GPR1);
@@ -80,11 +140,17 @@ void __init imx_src_init(void)
80 src_base = of_iomap(np, 0); 140 src_base = of_iomap(np, 0);
81 WARN_ON(!src_base); 141 WARN_ON(!src_base);
82 142
143 imx_reset_controller.of_node = np;
144 if (IS_ENABLED(CONFIG_RESET_CONTROLLER))
145 reset_controller_register(&imx_reset_controller);
146
83 /* 147 /*
84 * force warm reset sources to generate cold reset 148 * force warm reset sources to generate cold reset
85 * for a more reliable restart 149 * for a more reliable restart
86 */ 150 */
151 spin_lock(&scr_lock);
87 val = readl_relaxed(src_base + SRC_SCR); 152 val = readl_relaxed(src_base + SRC_SCR);
88 val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE); 153 val &= ~(1 << BP_SRC_SCR_WARM_RESET_ENABLE);
89 writel_relaxed(val, src_base + SRC_SCR); 154 writel_relaxed(val, src_base + SRC_SCR);
155 spin_unlock(&scr_lock);
90} 156}