瀏覽代碼

Merge tag 'imx-soc-3.13' of git://git.linaro.org/people/shawnguo/linux-2.6 into next/soc

From Shawn Guo:
The imx/mxs soc changes for 3.13:

* Low-level debug support for Vybrid
* Support soc bus/device for imx6
* Suspend support for imx6dl and imx6sl
* The imx6q clock updates for PCIe and audio PLL support
* IOMUXC GPR update for fec support
* Some random cleanup
* A few defconfig updates

* tag 'imx-soc-3.13' of git://git.linaro.org/people/shawnguo/linux-2.6: (31 commits)
  ARM: imx: enable suspend for imx6sl
  ARM: imx: ensure dsm_request signal is not asserted when setting LPM
  ARM: imx6q: call WB and RBC configuration from imx6q_pm_enter()
  ARM: imx6q: move low-power code out of clock driver
  ARM: imx: drop extern with function prototypes in common.h
  ARM: imx: reset core along with enable/disable operation
  ARM: imx: do not return from imx_cpu_die() call
  ARM: imx_v6_v7_defconfig: Select CONFIG_PROVE_LOCKING
  ARM: imx_v6_v7_defconfig: Enable LEDS_GPIO related options
  ARM: mxs_defconfig: Turn off CONFIG_DEBUG_GPIO
  ARM: imx: replace imx6q_restart() with mxc_restart()
  ARM: mach-imx: mm-imx5: Retrieve iomuxc base address from dt
  ARM: mach-imx: mm-imx5: Retrieve tzic base address from dt
  ARM: mach-imx: clk-imx51-imx53: Retrieve base address and irq from dt
  ARM: mxs_defconfig: Add CHIPIDEA_UDC support
  ARM: imx: Include linux/err.h
  ARM: imx_v6_v7_defconfig: Add CHIPIDEA_UDC support
  ARM: imx_v6_v7_defconfig: Add SPDIF support
  ARM: imx6q: clock and Kconfig update for PCIe support
  ARM: imx: Add LVDS general-purpose clocks to i.MX6Q
  ...

Signed-off-by: Olof Johansson <olof@lixom.net>
Olof Johansson 12 年之前
父節點
當前提交
b6fb5474af

+ 5 - 0
Documentation/devicetree/bindings/clock/imx6q-clock.txt

@@ -215,6 +215,11 @@ clocks and IDs.
 	cko2      		200
 	cko2      		200
 	cko      		201
 	cko      		201
 	vdoa      		202
 	vdoa      		202
+	pll4_audio_div		203
+	lvds1_sel		204
+	lvds2_sel		205
+	lvds1_gate		206
+	lvds2_gate		207
 
 
 Examples:
 Examples:
 
 

+ 8 - 0
arch/arm/Kconfig.debug

@@ -386,6 +386,13 @@ choice
 		  when u-boot hands over to the kernel, the system
 		  when u-boot hands over to the kernel, the system
 		  silently crashes, with no serial output at all.
 		  silently crashes, with no serial output at all.
 
 
+	config DEBUG_VF_UART
+		bool "Vybrid UART"
+		depends on SOC_VF610
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on Vybrid based platforms.
+
 	config DEBUG_NOMADIK_UART
 	config DEBUG_NOMADIK_UART
 		bool "Kernel low-level debugging messages via NOMADIK UART"
 		bool "Kernel low-level debugging messages via NOMADIK UART"
 		depends on ARCH_NOMADIK
 		depends on ARCH_NOMADIK
@@ -906,6 +913,7 @@ config DEBUG_LL_INCLUDE
 	default "debug/tegra.S" if DEBUG_TEGRA_UART
 	default "debug/tegra.S" if DEBUG_TEGRA_UART
 	default "debug/ux500.S" if DEBUG_UX500_UART
 	default "debug/ux500.S" if DEBUG_UX500_UART
 	default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT
 	default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT
+	default "debug/vf.S" if DEBUG_VF_UART
 	default "debug/vt8500.S" if DEBUG_VT8500_UART0
 	default "debug/vt8500.S" if DEBUG_VT8500_UART0
 	default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
 	default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
 	default "mach/debug-macro.S"
 	default "mach/debug-macro.S"

+ 3 - 1
arch/arm/boot/dts/imx6sl.dtsi

@@ -380,7 +380,9 @@
 			};
 			};
 
 
 			anatop: anatop@020c8000 {
 			anatop: anatop@020c8000 {
-				compatible = "fsl,imx6sl-anatop", "syscon", "simple-bus";
+				compatible = "fsl,imx6sl-anatop",
+					     "fsl,imx6q-anatop",
+					     "syscon", "simple-bus";
 				reg = <0x020c8000 0x1000>;
 				reg = <0x020c8000 0x1000>;
 				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
 				interrupts = <0 49 0x04 0 54 0x04 0 127 0x04>;
 
 

+ 13 - 3
arch/arm/configs/imx_v6_v7_defconfig

@@ -132,7 +132,6 @@ CONFIG_TOUCHSCREEN_MC13783=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MMA8450=y
 CONFIG_INPUT_MMA8450=y
 CONFIG_SERIO_SERPORT=m
 CONFIG_SERIO_SERPORT=m
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX=y
@@ -188,22 +187,33 @@ CONFIG_SND_SOC_PHYCORE_AC97=y
 CONFIG_SND_SOC_EUKREA_TLV320=y
 CONFIG_SND_SOC_EUKREA_TLV320=y
 CONFIG_SND_SOC_IMX_WM8962=y
 CONFIG_SND_SOC_IMX_WM8962=y
 CONFIG_SND_SOC_IMX_SGTL5000=y
 CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_SPDIF=y
 CONFIG_SND_SOC_IMX_MC13783=y
 CONFIG_SND_SOC_IMX_MC13783=y
 CONFIG_USB=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
 CONFIG_USB_EHCI_MXC=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
 CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_USB_CHIPIDEA_HOST=y
-CONFIG_USB_PHY=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_NOP_USB_XCEIV=y
 CONFIG_USB_MXS_PHY=y
 CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_ESDHC_IMX=y
 CONFIG_MMC_SDHCI_ESDHC_IMX=y
 CONFIG_NEW_LEDS=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_ONESHOT=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_BACKLIGHT=y
+CONFIG_LEDS_TRIGGER_GPIO=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
 CONFIG_RTC_DRV_MC13XXX=y
 CONFIG_RTC_DRV_MC13XXX=y
@@ -246,7 +256,6 @@ CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS=y
-CONFIG_CONFIGFS_FS=m
 CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS=y
 CONFIG_UBIFS_FS=y
 CONFIG_UBIFS_FS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_FS=y
@@ -261,6 +270,7 @@ CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_UTF8=y
 CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHED_DEBUG is not set
+CONFIG_PROVE_LOCKING=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FTRACE is not set
 # CONFIG_FTRACE is not set
 # CONFIG_ARM_UNWIND is not set
 # CONFIG_ARM_UNWIND is not set

+ 4 - 3
arch/arm/configs/mxs_defconfig

@@ -76,7 +76,6 @@ CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_TSC2007=m
 CONFIG_TOUCHSCREEN_TSC2007=m
 # CONFIG_SERIO is not set
 # CONFIG_SERIO is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
 CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_DEVKMEM is not set
 # CONFIG_DEVKMEM is not set
@@ -91,7 +90,6 @@ CONFIG_I2C_MXS=y
 CONFIG_SPI=y
 CONFIG_SPI=y
 CONFIG_SPI_GPIO=m
 CONFIG_SPI_GPIO=m
 CONFIG_SPI_MXS=y
 CONFIG_SPI_MXS=y
-CONFIG_DEBUG_GPIO=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG=y
@@ -115,9 +113,12 @@ CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
 CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_USB_CHIPIDEA_HOST=y
-CONFIG_USB_PHY=y
 CONFIG_USB_MXS_PHY=y
 CONFIG_USB_MXS_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_ETH=m
+CONFIG_USB_MASS_STORAGE=m
 CONFIG_MMC=y
 CONFIG_MMC=y
 CONFIG_MMC_UNSAFE_RESUME=y
 CONFIG_MMC_UNSAFE_RESUME=y
 CONFIG_MMC_MXS=y
 CONFIG_MMC_MXS=y

+ 26 - 0
arch/arm/include/debug/vf.S

@@ -0,0 +1,26 @@
+/*
+ * Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+	.macro	addruart, rp, rv, tmp
+	ldr	\rp, =0x40028000	@ physical
+	ldr	\rv, =0xfe028000	@ virtual
+	.endm
+
+	.macro	senduart, rd, rx
+	strb	\rd, [\rx, #0x7]	@ Data Register
+	.endm
+
+	.macro	busyuart, rd, rx
+1001:	ldrb	\rd, [\rx, #0x4]	@ Status Register 1
+	tst	\rd, #1 << 6		@ TC
+	beq	1001b			@ wait until transmit done
+	.endm
+
+	.macro	waituart,rd,rx
+	.endm

+ 4 - 1
arch/arm/mach-imx/Kconfig

@@ -11,6 +11,7 @@ config ARCH_MXC
 	select GENERIC_IRQ_CHIP
 	select GENERIC_IRQ_CHIP
 	select MIGHT_HAVE_CACHE_L2X0 if ARCH_MULTI_V6_V7
 	select MIGHT_HAVE_CACHE_L2X0 if ARCH_MULTI_V6_V7
 	select MULTI_IRQ_HANDLER
 	select MULTI_IRQ_HANDLER
+	select SOC_BUS
 	select SPARSE_IRQ
 	select SPARSE_IRQ
 	select USE_OF
 	select USE_OF
 	help
 	help
@@ -24,7 +25,7 @@ config MXC_IRQ_PRIOR
 	help
 	help
 	  Select this if you want to use prioritized IRQ handling.
 	  Select this if you want to use prioritized IRQ handling.
 	  This feature prevents higher priority ISR to be interrupted
 	  This feature prevents higher priority ISR to be interrupted
-	  by lower priority IRQ even IRQF_DISABLED flag is not set.
+	  by lower priority IRQ.
 	  This may be useful in embedded applications, where are strong
 	  This may be useful in embedded applications, where are strong
 	  requirements for timing.
 	  requirements for timing.
 	  Say N here, unless you have a specialized requirement.
 	  Say N here, unless you have a specialized requirement.
@@ -801,6 +802,8 @@ config SOC_IMX6Q
 	select HAVE_IMX_SRC
 	select HAVE_IMX_SRC
 	select HAVE_SMP
 	select HAVE_SMP
 	select MFD_SYSCON
 	select MFD_SYSCON
+	select MIGHT_HAVE_PCI
+	select PCI_DOMAINS if PCI
 	select PINCTRL
 	select PINCTRL
 	select PINCTRL_IMX6Q
 	select PINCTRL_IMX6Q
 	select PL310_ERRATA_588369 if CACHE_PL310
 	select PL310_ERRATA_588369 if CACHE_PL310

+ 2 - 0
arch/arm/mach-imx/Makefile

@@ -102,6 +102,8 @@ obj-$(CONFIG_SOC_IMX6SL) += clk-imx6sl.o mach-imx6sl.o
 
 
 ifeq ($(CONFIG_PM),y)
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
 obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
+# i.MX6SL reuses pm-imx6q.c
+obj-$(CONFIG_SOC_IMX6SL) += pm-imx6q.o
 endif
 endif
 
 
 # i.MX5 based machines
 # i.MX5 based machines

+ 26 - 7
arch/arm/mach-imx/anatop.c

@@ -16,6 +16,7 @@
 #include <linux/mfd/syscon.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
 #include <linux/regmap.h>
 #include "common.h"
 #include "common.h"
+#include "hardware.h"
 
 
 #define REG_SET		0x4
 #define REG_SET		0x4
 #define REG_CLR		0x8
 #define REG_CLR		0x8
@@ -26,6 +27,7 @@
 #define ANADIG_USB1_CHRG_DETECT	0x1b0
 #define ANADIG_USB1_CHRG_DETECT	0x1b0
 #define ANADIG_USB2_CHRG_DETECT	0x210
 #define ANADIG_USB2_CHRG_DETECT	0x210
 #define ANADIG_DIGPROG		0x260
 #define ANADIG_DIGPROG		0x260
+#define ANADIG_DIGPROG_IMX6SL	0x280
 
 
 #define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG	0x40000
 #define BM_ANADIG_REG_2P5_ENABLE_WEAK_LINREG	0x40000
 #define BM_ANADIG_REG_CORE_FET_ODRIVE		0x20000000
 #define BM_ANADIG_REG_CORE_FET_ODRIVE		0x20000000
@@ -76,21 +78,38 @@ static void imx_anatop_usb_chrg_detect_disable(void)
 		BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
 		BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B);
 }
 }
 
 
-u32 imx_anatop_get_digprog(void)
+void __init imx_init_revision_from_anatop(void)
 {
 {
 	struct device_node *np;
 	struct device_node *np;
 	void __iomem *anatop_base;
 	void __iomem *anatop_base;
-	static u32 digprog;
-
-	if (digprog)
-		return digprog;
+	unsigned int revision;
+	u32 digprog;
+	u16 offset = ANADIG_DIGPROG;
 
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
 	anatop_base = of_iomap(np, 0);
 	anatop_base = of_iomap(np, 0);
 	WARN_ON(!anatop_base);
 	WARN_ON(!anatop_base);
-	digprog = readl_relaxed(anatop_base + ANADIG_DIGPROG);
+	if (of_device_is_compatible(np, "fsl,imx6sl-anatop"))
+		offset = ANADIG_DIGPROG_IMX6SL;
+	digprog = readl_relaxed(anatop_base + offset);
+	iounmap(anatop_base);
+
+	switch (digprog & 0xff) {
+	case 0:
+		revision = IMX_CHIP_REVISION_1_0;
+		break;
+	case 1:
+		revision = IMX_CHIP_REVISION_1_1;
+		break;
+	case 2:
+		revision = IMX_CHIP_REVISION_1_2;
+		break;
+	default:
+		revision = IMX_CHIP_REVISION_UNKNOWN;
+	}
 
 
-	return digprog;
+	mxc_set_cpu_type(digprog >> 16 & 0xff);
+	imx_set_soc_revision(revision);
 }
 }
 
 
 void __init imx_anatop_init(void)
 void __init imx_anatop_init(void)

+ 11 - 4
arch/arm/mach-imx/clk-imx51-imx53.c

@@ -14,6 +14,9 @@
 #include <linux/clk-provider.h>
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/err.h>
 #include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 
 #include "crm-regs-imx5.h"
 #include "crm-regs-imx5.h"
 #include "clk.h"
 #include "clk.h"
@@ -472,8 +475,9 @@ CLK_OF_DECLARE(imx51_ccm, "fsl,imx51-ccm", mx51_clocks_init_dt);
 
 
 static void __init mx53_clocks_init(struct device_node *np)
 static void __init mx53_clocks_init(struct device_node *np)
 {
 {
-	int i;
+	int i, irq;
 	unsigned long r;
 	unsigned long r;
+	void __iomem *base;
 
 
 	clk[pll1_sw] = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
 	clk[pll1_sw] = imx_clk_pllv2("pll1_sw", "osc", MX53_DPLL1_BASE);
 	clk[pll2_sw] = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
 	clk[pll2_sw] = imx_clk_pllv2("pll2_sw", "osc", MX53_DPLL2_BASE);
@@ -559,14 +563,17 @@ static void __init mx53_clocks_init(struct device_node *np)
 	clk_set_rate(clk[esdhc_a_podf], 200000000);
 	clk_set_rate(clk[esdhc_a_podf], 200000000);
 	clk_set_rate(clk[esdhc_b_podf], 200000000);
 	clk_set_rate(clk[esdhc_b_podf], 200000000);
 
 
-	/* System timer */
-	mxc_timer_init(MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR), MX53_INT_GPT);
-
 	clk_prepare_enable(clk[iim_gate]);
 	clk_prepare_enable(clk[iim_gate]);
 	imx_print_silicon_rev("i.MX53", mx53_revision());
 	imx_print_silicon_rev("i.MX53", mx53_revision());
 	clk_disable_unprepare(clk[iim_gate]);
 	clk_disable_unprepare(clk[iim_gate]);
 
 
 	r = clk_round_rate(clk[usboh3_per_gate], 54000000);
 	r = clk_round_rate(clk[usboh3_per_gate], 54000000);
 	clk_set_rate(clk[usboh3_per_gate], r);
 	clk_set_rate(clk[usboh3_per_gate], r);
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx53-gpt");
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+	irq = irq_of_parse_and_map(np, 0);
+	mxc_timer_init(base, irq);
 }
 }
 CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);
 CLK_OF_DECLARE(imx53_ccm, "fsl,imx53-ccm", mx53_clocks_init);

+ 31 - 159
arch/arm/mach-imx/clk-imx6q.c

@@ -14,7 +14,6 @@
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clkdev.h>
-#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of.h>
@@ -25,155 +24,6 @@
 #include "common.h"
 #include "common.h"
 #include "hardware.h"
 #include "hardware.h"
 
 
-#define CCR				0x0
-#define BM_CCR_WB_COUNT			(0x7 << 16)
-#define BM_CCR_RBC_BYPASS_COUNT		(0x3f << 21)
-#define BM_CCR_RBC_EN			(0x1 << 27)
-
-#define CCGR0				0x68
-#define CCGR1				0x6c
-#define CCGR2				0x70
-#define CCGR3				0x74
-#define CCGR4				0x78
-#define CCGR5				0x7c
-#define CCGR6				0x80
-#define CCGR7				0x84
-
-#define CLPCR				0x54
-#define BP_CLPCR_LPM			0
-#define BM_CLPCR_LPM			(0x3 << 0)
-#define BM_CLPCR_BYPASS_PMIC_READY	(0x1 << 2)
-#define BM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
-#define BM_CLPCR_SBYOS			(0x1 << 6)
-#define BM_CLPCR_DIS_REF_OSC		(0x1 << 7)
-#define BM_CLPCR_VSTBY			(0x1 << 8)
-#define BP_CLPCR_STBY_COUNT		9
-#define BM_CLPCR_STBY_COUNT		(0x3 << 9)
-#define BM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
-#define BM_CLPCR_WB_PER_AT_LPM		(0x1 << 16)
-#define BM_CLPCR_WB_CORE_AT_LPM		(0x1 << 17)
-#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS	(0x1 << 19)
-#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS	(0x1 << 21)
-#define BM_CLPCR_MASK_CORE0_WFI		(0x1 << 22)
-#define BM_CLPCR_MASK_CORE1_WFI		(0x1 << 23)
-#define BM_CLPCR_MASK_CORE2_WFI		(0x1 << 24)
-#define BM_CLPCR_MASK_CORE3_WFI		(0x1 << 25)
-#define BM_CLPCR_MASK_SCU_IDLE		(0x1 << 26)
-#define BM_CLPCR_MASK_L2CC_IDLE		(0x1 << 27)
-
-#define CGPR				0x64
-#define BM_CGPR_CHICKEN_BIT		(0x1 << 17)
-
-static void __iomem *ccm_base;
-
-void imx6q_set_chicken_bit(void)
-{
-	u32 val = readl_relaxed(ccm_base + CGPR);
-
-	val |= BM_CGPR_CHICKEN_BIT;
-	writel_relaxed(val, ccm_base + CGPR);
-}
-
-static void imx6q_enable_rbc(bool enable)
-{
-	u32 val;
-	static bool last_rbc_mode;
-
-	if (last_rbc_mode == enable)
-		return;
-	/*
-	 * need to mask all interrupts in GPC before
-	 * operating RBC configurations
-	 */
-	imx_gpc_mask_all();
-
-	/* configure RBC enable bit */
-	val = readl_relaxed(ccm_base + CCR);
-	val &= ~BM_CCR_RBC_EN;
-	val |= enable ? BM_CCR_RBC_EN : 0;
-	writel_relaxed(val, ccm_base + CCR);
-
-	/* configure RBC count */
-	val = readl_relaxed(ccm_base + CCR);
-	val &= ~BM_CCR_RBC_BYPASS_COUNT;
-	val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
-	writel(val, ccm_base + CCR);
-
-	/*
-	 * need to delay at least 2 cycles of CKIL(32K)
-	 * due to hardware design requirement, which is
-	 * ~61us, here we use 65us for safe
-	 */
-	udelay(65);
-
-	/* restore GPC interrupt mask settings */
-	imx_gpc_restore_all();
-
-	last_rbc_mode = enable;
-}
-
-static void imx6q_enable_wb(bool enable)
-{
-	u32 val;
-	static bool last_wb_mode;
-
-	if (last_wb_mode == enable)
-		return;
-
-	/* configure well bias enable bit */
-	val = readl_relaxed(ccm_base + CLPCR);
-	val &= ~BM_CLPCR_WB_PER_AT_LPM;
-	val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
-	writel_relaxed(val, ccm_base + CLPCR);
-
-	/* configure well bias count */
-	val = readl_relaxed(ccm_base + CCR);
-	val &= ~BM_CCR_WB_COUNT;
-	val |= enable ? BM_CCR_WB_COUNT : 0;
-	writel_relaxed(val, ccm_base + CCR);
-
-	last_wb_mode = enable;
-}
-
-int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
-{
-	u32 val = readl_relaxed(ccm_base + CLPCR);
-
-	val &= ~BM_CLPCR_LPM;
-	switch (mode) {
-	case WAIT_CLOCKED:
-		imx6q_enable_wb(false);
-		imx6q_enable_rbc(false);
-		break;
-	case WAIT_UNCLOCKED:
-		val |= 0x1 << BP_CLPCR_LPM;
-		val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
-		break;
-	case STOP_POWER_ON:
-		val |= 0x2 << BP_CLPCR_LPM;
-		break;
-	case WAIT_UNCLOCKED_POWER_OFF:
-		val |= 0x1 << BP_CLPCR_LPM;
-		val &= ~BM_CLPCR_VSTBY;
-		val &= ~BM_CLPCR_SBYOS;
-		break;
-	case STOP_POWER_OFF:
-		val |= 0x2 << BP_CLPCR_LPM;
-		val |= 0x3 << BP_CLPCR_STBY_COUNT;
-		val |= BM_CLPCR_VSTBY;
-		val |= BM_CLPCR_SBYOS;
-		imx6q_enable_wb(true);
-		imx6q_enable_rbc(true);
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	writel_relaxed(val, ccm_base + CLPCR);
-
-	return 0;
-}
-
 static const char *step_sels[]	= { "osc", "pll2_pfd2_396m", };
 static const char *step_sels[]	= { "osc", "pll2_pfd2_396m", };
 static const char *pll1_sw_sels[]	= { "pll1_sys", "step", };
 static const char *pll1_sw_sels[]	= { "pll1_sys", "step", };
 static const char *periph_pre_sels[]	= { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
 static const char *periph_pre_sels[]	= { "pll2_bus", "pll2_pfd2_396m", "pll2_pfd0_352m", "pll2_198m", };
@@ -182,7 +32,7 @@ static const char *periph2_clk2_sels[]	= { "pll3_usb_otg", "pll2_bus", };
 static const char *periph_sels[]	= { "periph_pre", "periph_clk2", };
 static const char *periph_sels[]	= { "periph_pre", "periph_clk2", };
 static const char *periph2_sels[]	= { "periph2_pre", "periph2_clk2", };
 static const char *periph2_sels[]	= { "periph2_pre", "periph2_clk2", };
 static const char *axi_sels[]		= { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", };
 static const char *axi_sels[]		= { "periph", "pll2_pfd2_396m", "periph", "pll3_pfd1_540m", };
-static const char *audio_sels[]	= { "pll4_post_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
+static const char *audio_sels[]	= { "pll4_audio_div", "pll3_pfd2_508m", "pll3_pfd3_454m", "pll3_usb_otg", };
 static const char *gpu_axi_sels[]	= { "axi", "ahb", };
 static const char *gpu_axi_sels[]	= { "axi", "ahb", };
 static const char *gpu2d_core_sels[]	= { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", };
 static const char *gpu2d_core_sels[]	= { "axi", "pll3_usb_otg", "pll2_pfd0_352m", "pll2_pfd2_396m", };
 static const char *gpu3d_core_sels[]	= { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
 static const char *gpu3d_core_sels[]	= { "mmdc_ch0_axi", "pll3_usb_otg", "pll2_pfd1_594m", "pll2_pfd2_396m", };
@@ -196,7 +46,7 @@ static const char *ipu2_di0_sels[]	= { "ipu2_di0_pre", "dummy", "dummy", "ldb_di
 static const char *ipu2_di1_sels[]	= { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
 static const char *ipu2_di1_sels[]	= { "ipu2_di1_pre", "dummy", "dummy", "ldb_di0", "ldb_di1", };
 static const char *hsi_tx_sels[]	= { "pll3_120m", "pll2_pfd2_396m", };
 static const char *hsi_tx_sels[]	= { "pll3_120m", "pll2_pfd2_396m", };
 static const char *pcie_axi_sels[]	= { "axi", "ahb", };
 static const char *pcie_axi_sels[]	= { "axi", "ahb", };
-static const char *ssi_sels[]		= { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_post_div", };
+static const char *ssi_sels[]		= { "pll3_pfd2_508m", "pll3_pfd3_454m", "pll4_audio_div", };
 static const char *usdhc_sels[]	= { "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *usdhc_sels[]	= { "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *enfc_sels[]	= { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", };
 static const char *enfc_sels[]	= { "pll2_pfd0_352m", "pll2_bus", "pll3_usb_otg", "pll2_pfd2_396m", };
 static const char *emi_sels[]		= { "pll2_pfd2_396m", "pll3_usb_otg", "axi", "pll2_pfd0_352m", };
 static const char *emi_sels[]		= { "pll2_pfd2_396m", "pll3_usb_otg", "axi", "pll2_pfd0_352m", };
@@ -205,7 +55,7 @@ static const char *vdo_axi_sels[]	= { "axi", "ahb", };
 static const char *vpu_axi_sels[]	= { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *vpu_axi_sels[]	= { "axi", "pll2_pfd2_396m", "pll2_pfd0_352m", };
 static const char *cko1_sels[]	= { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
 static const char *cko1_sels[]	= { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
 				    "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
 				    "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
-				    "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_post_div", };
+				    "ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio_div", };
 static const char *cko2_sels[] = {
 static const char *cko2_sels[] = {
 	"mmdc_ch0_axi", "mmdc_ch1_axi", "usdhc4", "usdhc1",
 	"mmdc_ch0_axi", "mmdc_ch1_axi", "usdhc4", "usdhc1",
 	"gpu2d_axi", "dummy", "ecspi_root", "gpu3d_axi",
 	"gpu2d_axi", "dummy", "ecspi_root", "gpu3d_axi",
@@ -217,6 +67,11 @@ static const char *cko2_sels[] = {
 	"uart_serial", "spdif", "asrc", "hsi_tx",
 	"uart_serial", "spdif", "asrc", "hsi_tx",
 };
 };
 static const char *cko_sels[] = { "cko1", "cko2", };
 static const char *cko_sels[] = { "cko1", "cko2", };
+static const char *lvds_sels[] = {
+	"dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
+	"pll4_audio", "pll5_video", "pll8_mlb", "enet_ref",
+	"pcie_ref", "sata_ref",
+};
 
 
 enum mx6q_clks {
 enum mx6q_clks {
 	dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
 	dummy, ckil, ckih, osc, pll2_pfd0_352m, pll2_pfd1_594m, pll2_pfd2_396m,
@@ -251,7 +106,8 @@ enum mx6q_clks {
 	ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
 	ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
 	sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
 	sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
 	usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow,
 	usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow,
-	spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, clk_max
+	spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, pll4_audio_div,
+	lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, clk_max
 };
 };
 
 
 static struct clk *clk[clk_max];
 static struct clk *clk[clk_max];
@@ -300,7 +156,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	WARN_ON(!base);
 	WARN_ON(!base);
 
 
 	/* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
 	/* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
-	if (cpu_is_imx6q() && imx6q_revision() == IMX_CHIP_REVISION_1_0) {
+	if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) {
 		post_div_table[1].div = 1;
 		post_div_table[1].div = 1;
 		post_div_table[2].div = 1;
 		post_div_table[2].div = 1;
 		video_div_table[1].div = 1;
 		video_div_table[1].div = 1;
@@ -342,6 +198,18 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 			base + 0xe0, 0, 2, 0, clk_enet_ref_table,
 			base + 0xe0, 0, 2, 0, clk_enet_ref_table,
 			&imx_ccm_lock);
 			&imx_ccm_lock);
 
 
+	clk[lvds1_sel] = imx_clk_mux("lvds1_sel", base + 0x160, 0, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+	clk[lvds2_sel] = imx_clk_mux("lvds2_sel", base + 0x160, 5, 5, lvds_sels, ARRAY_SIZE(lvds_sels));
+
+	/*
+	 * lvds1_gate and lvds2_gate are pseudo-gates.  Both can be
+	 * independently configured as clock inputs or outputs.  We treat
+	 * the "output_enable" bit as a gate, even though it's really just
+	 * enabling clock output.
+	 */
+	clk[lvds1_gate] = imx_clk_gate("lvds1_gate", "dummy", base + 0x160, 10);
+	clk[lvds2_gate] = imx_clk_gate("lvds2_gate", "dummy", base + 0x160, 11);
+
 	/*                                name              parent_name        reg       idx */
 	/*                                name              parent_name        reg       idx */
 	clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
 	clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
 	clk[pll2_pfd1_594m] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
 	clk[pll2_pfd1_594m] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
@@ -359,13 +227,15 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	clk[twd]       = imx_clk_fixed_factor("twd",       "arm",            1, 2);
 	clk[twd]       = imx_clk_fixed_factor("twd",       "arm",            1, 2);
 
 
 	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);
 	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);
+	clk[pll4_audio_div] = clk_register_divider(NULL, "pll4_audio_div", "pll4_post_div", CLK_SET_RATE_PARENT, base + 0x170, 15, 1, 0, &imx_ccm_lock);
 	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);
 	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);
 	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);
 	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);
 
 
 	np = ccm_node;
 	np = ccm_node;
 	base = of_iomap(np, 0);
 	base = of_iomap(np, 0);
 	WARN_ON(!base);
 	WARN_ON(!base);
-	ccm_base = base;
+
+	imx6q_pm_set_ccm_base(base);
 
 
 	/*                                  name                reg       shift width parent_names     num_parents */
 	/*                                  name                reg       shift width parent_names     num_parents */
 	clk[step]             = imx_clk_mux("step",	        base + 0xc,  8,  1, step_sels,	       ARRAY_SIZE(step_sels));
 	clk[step]             = imx_clk_mux("step",	        base + 0xc,  8,  1, step_sels,	       ARRAY_SIZE(step_sels));
@@ -573,7 +443,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	clk_register_clkdev(clk[pll4_post_div], "pll4_post_div", NULL);
 	clk_register_clkdev(clk[pll4_post_div], "pll4_post_div", NULL);
 	clk_register_clkdev(clk[pll4_audio], "pll4_audio", NULL);
 	clk_register_clkdev(clk[pll4_audio], "pll4_audio", NULL);
 
 
-	if ((imx6q_revision() != IMX_CHIP_REVISION_1_0) || cpu_is_imx6dl()) {
+	if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
+	    cpu_is_imx6dl()) {
 		clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]);
 		clk_set_parent(clk[ldb_di0_sel], clk[pll5_video_div]);
 		clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
 		clk_set_parent(clk[ldb_di1_sel], clk[pll5_video_div]);
 	}
 	}
@@ -603,8 +474,9 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
 	if (ret)
 	if (ret)
 		pr_warn("failed to set up CLKO: %d\n", ret);
 		pr_warn("failed to set up CLKO: %d\n", ret);
 
 
-	/* Set initial power mode */
-	imx6q_set_lpm(WAIT_CLOCKED);
+	/* All existing boards with PCIe use LVDS1 */
+	if (IS_ENABLED(CONFIG_PCI_IMX6))
+		clk_set_parent(clk[lvds1_sel], clk[sata_ref]);
 
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
 	base = of_iomap(np, 0);
 	base = of_iomap(np, 0);

+ 3 - 0
arch/arm/mach-imx/clk-imx6sl.c

@@ -127,6 +127,9 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
 	base = of_iomap(np, 0);
 	base = of_iomap(np, 0);
 	WARN_ON(!base);
 	WARN_ON(!base);
 
 
+	/* Reuse imx6q pm code */
+	imx6q_pm_set_ccm_base(base);
+
 	/*                                              name                reg       shift width parent_names     num_parents */
 	/*                                              name                reg       shift width parent_names     num_parents */
 	clks[IMX6SL_CLK_STEP]             = imx_clk_mux("step",             base + 0xc,  8,  1, step_sels,         ARRAY_SIZE(step_sels));
 	clks[IMX6SL_CLK_STEP]             = imx_clk_mux("step",             base + 0xc,  8,  1, step_sels,         ARRAY_SIZE(step_sels));
 	clks[IMX6SL_CLK_PLL1_SW]          = imx_clk_mux("pll1_sw",          base + 0xc,  2,  1, pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));
 	clks[IMX6SL_CLK_PLL1_SW]          = imx_clk_mux("pll1_sw",          base + 0xc,  2,  1, pll1_sw_sels,      ARRAY_SIZE(pll1_sw_sels));

+ 98 - 88
arch/arm/mach-imx/common.h

@@ -13,70 +13,73 @@
 
 
 #include <linux/reboot.h>
 #include <linux/reboot.h>
 
 
+struct irq_data;
 struct platform_device;
 struct platform_device;
 struct pt_regs;
 struct pt_regs;
 struct clk;
 struct clk;
 enum mxc_cpu_pwr_mode;
 enum mxc_cpu_pwr_mode;
 
 
-extern void mx1_map_io(void);
-extern void mx21_map_io(void);
-extern void mx25_map_io(void);
-extern void mx27_map_io(void);
-extern void mx31_map_io(void);
-extern void mx35_map_io(void);
-extern void mx51_map_io(void);
-extern void mx53_map_io(void);
-extern void imx1_init_early(void);
-extern void imx21_init_early(void);
-extern void imx25_init_early(void);
-extern void imx27_init_early(void);
-extern void imx31_init_early(void);
-extern void imx35_init_early(void);
-extern void imx51_init_early(void);
-extern void imx53_init_early(void);
-extern void mxc_init_irq(void __iomem *);
-extern void tzic_init_irq(void __iomem *);
-extern void mx1_init_irq(void);
-extern void mx21_init_irq(void);
-extern void mx25_init_irq(void);
-extern void mx27_init_irq(void);
-extern void mx31_init_irq(void);
-extern void mx35_init_irq(void);
-extern void mx51_init_irq(void);
-extern void mx53_init_irq(void);
-extern void imx1_soc_init(void);
-extern void imx21_soc_init(void);
-extern void imx25_soc_init(void);
-extern void imx27_soc_init(void);
-extern void imx31_soc_init(void);
-extern void imx35_soc_init(void);
-extern void imx51_soc_init(void);
-extern void imx51_init_late(void);
-extern void imx53_init_late(void);
-extern void epit_timer_init(void __iomem *base, int irq);
-extern void mxc_timer_init(void __iomem *, int);
-extern int mx1_clocks_init(unsigned long fref);
-extern int mx21_clocks_init(unsigned long lref, unsigned long fref);
-extern int mx25_clocks_init(void);
-extern int mx27_clocks_init(unsigned long fref);
-extern int mx31_clocks_init(unsigned long fref);
-extern int mx35_clocks_init(void);
-extern int mx51_clocks_init(unsigned long ckil, unsigned long osc,
+void mx1_map_io(void);
+void mx21_map_io(void);
+void mx25_map_io(void);
+void mx27_map_io(void);
+void mx31_map_io(void);
+void mx35_map_io(void);
+void mx51_map_io(void);
+void mx53_map_io(void);
+void imx1_init_early(void);
+void imx21_init_early(void);
+void imx25_init_early(void);
+void imx27_init_early(void);
+void imx31_init_early(void);
+void imx35_init_early(void);
+void imx51_init_early(void);
+void imx53_init_early(void);
+void mxc_init_irq(void __iomem *);
+void tzic_init_irq(void __iomem *);
+void mx1_init_irq(void);
+void mx21_init_irq(void);
+void mx25_init_irq(void);
+void mx27_init_irq(void);
+void mx31_init_irq(void);
+void mx35_init_irq(void);
+void mx51_init_irq(void);
+void mx53_init_irq(void);
+void imx1_soc_init(void);
+void imx21_soc_init(void);
+void imx25_soc_init(void);
+void imx27_soc_init(void);
+void imx31_soc_init(void);
+void imx35_soc_init(void);
+void imx51_soc_init(void);
+void imx51_init_late(void);
+void imx53_init_late(void);
+void epit_timer_init(void __iomem *base, int irq);
+void mxc_timer_init(void __iomem *, int);
+int mx1_clocks_init(unsigned long fref);
+int mx21_clocks_init(unsigned long lref, unsigned long fref);
+int mx25_clocks_init(void);
+int mx27_clocks_init(unsigned long fref);
+int mx31_clocks_init(unsigned long fref);
+int mx35_clocks_init(void);
+int mx51_clocks_init(unsigned long ckil, unsigned long osc,
 			unsigned long ckih1, unsigned long ckih2);
 			unsigned long ckih1, unsigned long ckih2);
-extern int mx25_clocks_init_dt(void);
-extern int mx27_clocks_init_dt(void);
-extern int mx31_clocks_init_dt(void);
-extern struct platform_device *mxc_register_gpio(char *name, int id,
+int mx25_clocks_init_dt(void);
+int mx27_clocks_init_dt(void);
+int mx31_clocks_init_dt(void);
+struct platform_device *mxc_register_gpio(char *name, int id,
 	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
 	resource_size_t iobase, resource_size_t iosize, int irq, int irq_high);
-extern void mxc_set_cpu_type(unsigned int type);
-extern void mxc_restart(enum reboot_mode, const char *);
-extern void mxc_arch_reset_init(void __iomem *);
-extern void mxc_arch_reset_init_dt(void);
-extern int mx53_revision(void);
-extern int imx6q_revision(void);
-extern int mx53_display_revision(void);
-extern void imx_set_aips(void __iomem *);
-extern int mxc_device_init(void);
+void mxc_set_cpu_type(unsigned int type);
+void mxc_restart(enum reboot_mode, const char *);
+void mxc_arch_reset_init(void __iomem *);
+void mxc_arch_reset_init_dt(void);
+int mx53_revision(void);
+void imx_set_aips(void __iomem *);
+int mxc_device_init(void);
+void imx_set_soc_revision(unsigned int rev);
+unsigned int imx_get_soc_revision(void);
+void imx_init_revision_from_anatop(void);
+struct device *imx_soc_device_init(void);
 
 
 enum mxc_cpu_pwr_mode {
 enum mxc_cpu_pwr_mode {
 	WAIT_CLOCKED,		/* wfi only */
 	WAIT_CLOCKED,		/* wfi only */
@@ -93,8 +96,8 @@ enum mx3_cpu_pwr_mode {
 	MX3_SLEEP,
 	MX3_SLEEP,
 };
 };
 
 
-extern void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode);
-extern void imx_print_silicon_rev(const char *cpu, int srev);
+void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode);
+void imx_print_silicon_rev(const char *cpu, int srev);
 
 
 void avic_handle_irq(struct pt_regs *);
 void avic_handle_irq(struct pt_regs *);
 void tzic_handle_irq(struct pt_regs *);
 void tzic_handle_irq(struct pt_regs *);
@@ -108,54 +111,61 @@ void tzic_handle_irq(struct pt_regs *);
 #define imx51_handle_irq tzic_handle_irq
 #define imx51_handle_irq tzic_handle_irq
 #define imx53_handle_irq tzic_handle_irq
 #define imx53_handle_irq tzic_handle_irq
 
 
-extern void imx_enable_cpu(int cpu, bool enable);
-extern void imx_set_cpu_jump(int cpu, void *jump_addr);
-extern u32 imx_get_cpu_arg(int cpu);
-extern void imx_set_cpu_arg(int cpu, u32 arg);
-extern void v7_cpu_resume(void);
+void imx_enable_cpu(int cpu, bool enable);
+void imx_set_cpu_jump(int cpu, void *jump_addr);
+u32 imx_get_cpu_arg(int cpu);
+void imx_set_cpu_arg(int cpu, u32 arg);
+void v7_cpu_resume(void);
 #ifdef CONFIG_SMP
 #ifdef CONFIG_SMP
-extern void v7_secondary_startup(void);
-extern void imx_scu_map_io(void);
-extern void imx_smp_prepare(void);
-extern void imx_scu_standby_enable(void);
+void v7_secondary_startup(void);
+void imx_scu_map_io(void);
+void imx_smp_prepare(void);
+void imx_scu_standby_enable(void);
 #else
 #else
 static inline void imx_scu_map_io(void) {}
 static inline void imx_scu_map_io(void) {}
 static inline void imx_smp_prepare(void) {}
 static inline void imx_smp_prepare(void) {}
 static inline void imx_scu_standby_enable(void) {}
 static inline void imx_scu_standby_enable(void) {}
 #endif
 #endif
-extern void imx_src_init(void);
-extern void imx_src_prepare_restart(void);
-extern void imx_gpc_init(void);
-extern void imx_gpc_pre_suspend(void);
-extern void imx_gpc_post_resume(void);
-extern void imx_gpc_mask_all(void);
-extern void imx_gpc_restore_all(void);
-extern void imx_anatop_init(void);
-extern void imx_anatop_pre_suspend(void);
-extern void imx_anatop_post_resume(void);
-extern u32 imx_anatop_get_digprog(void);
-extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
-extern void imx6q_set_chicken_bit(void);
-
-extern void imx_cpu_die(unsigned int cpu);
-extern int imx_cpu_kill(unsigned int cpu);
+void imx_src_init(void);
+#ifdef CONFIG_HAVE_IMX_SRC
+void imx_src_prepare_restart(void);
+#else
+static inline void imx_src_prepare_restart(void) {}
+#endif
+void imx_gpc_init(void);
+void imx_gpc_pre_suspend(void);
+void imx_gpc_post_resume(void);
+void imx_gpc_mask_all(void);
+void imx_gpc_restore_all(void);
+void imx_gpc_irq_mask(struct irq_data *d);
+void imx_gpc_irq_unmask(struct irq_data *d);
+void imx_anatop_init(void);
+void imx_anatop_pre_suspend(void);
+void imx_anatop_post_resume(void);
+int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
+void imx6q_set_chicken_bit(void);
+
+void imx_cpu_die(unsigned int cpu);
+int imx_cpu_kill(unsigned int cpu);
 
 
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
-extern void imx6q_pm_init(void);
-extern void imx5_pm_init(void);
+void imx6q_pm_init(void);
+void imx6q_pm_set_ccm_base(void __iomem *base);
+void imx5_pm_init(void);
 #else
 #else
 static inline void imx6q_pm_init(void) {}
 static inline void imx6q_pm_init(void) {}
+static inline void imx6q_pm_set_ccm_base(void __iomem *base) {}
 static inline void imx5_pm_init(void) {}
 static inline void imx5_pm_init(void) {}
 #endif
 #endif
 
 
 #ifdef CONFIG_NEON
 #ifdef CONFIG_NEON
-extern int mx51_neon_fixup(void);
+int mx51_neon_fixup(void);
 #else
 #else
 static inline int mx51_neon_fixup(void) { return 0; }
 static inline int mx51_neon_fixup(void) { return 0; }
 #endif
 #endif
 
 
 #ifdef CONFIG_CACHE_L2X0
 #ifdef CONFIG_CACHE_L2X0
-extern void imx_init_l2cache(void);
+void imx_init_l2cache(void);
 #else
 #else
 static inline void imx_init_l2cache(void) {}
 static inline void imx_init_l2cache(void) {}
 #endif
 #endif

+ 94 - 1
arch/arm/mach-imx/cpu.c

@@ -1,6 +1,9 @@
-
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/io.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
 
 
 #include "hardware.h"
 #include "hardware.h"
 #include "common.h"
 #include "common.h"
@@ -8,11 +11,23 @@
 unsigned int __mxc_cpu_type;
 unsigned int __mxc_cpu_type;
 EXPORT_SYMBOL(__mxc_cpu_type);
 EXPORT_SYMBOL(__mxc_cpu_type);
 
 
+static unsigned int imx_soc_revision;
+
 void mxc_set_cpu_type(unsigned int type)
 void mxc_set_cpu_type(unsigned int type)
 {
 {
 	__mxc_cpu_type = type;
 	__mxc_cpu_type = type;
 }
 }
 
 
+void imx_set_soc_revision(unsigned int rev)
+{
+	imx_soc_revision = rev;
+}
+
+unsigned int imx_get_soc_revision(void)
+{
+	return imx_soc_revision;
+}
+
 void imx_print_silicon_rev(const char *cpu, int srev)
 void imx_print_silicon_rev(const char *cpu, int srev)
 {
 {
 	if (srev == IMX_CHIP_REVISION_UNKNOWN)
 	if (srev == IMX_CHIP_REVISION_UNKNOWN)
@@ -44,3 +59,81 @@ void __init imx_set_aips(void __iomem *base)
 	reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
 	reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
 	__raw_writel(reg, base + 0x50);
 	__raw_writel(reg, base + 0x50);
 }
 }
+
+struct device * __init imx_soc_device_init(void)
+{
+	struct soc_device_attribute *soc_dev_attr;
+	struct soc_device *soc_dev;
+	struct device_node *root;
+	const char *soc_id;
+	int ret;
+
+	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+	if (!soc_dev_attr)
+		return NULL;
+
+	soc_dev_attr->family = "Freescale i.MX";
+
+	root = of_find_node_by_path("/");
+	ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
+	of_node_put(root);
+	if (ret)
+		goto free_soc;
+
+	switch (__mxc_cpu_type) {
+	case MXC_CPU_MX1:
+		soc_id = "i.MX1";
+		break;
+	case MXC_CPU_MX21:
+		soc_id = "i.MX21";
+		break;
+	case MXC_CPU_MX25:
+		soc_id = "i.MX25";
+		break;
+	case MXC_CPU_MX27:
+		soc_id = "i.MX27";
+		break;
+	case MXC_CPU_MX31:
+		soc_id = "i.MX31";
+		break;
+	case MXC_CPU_MX35:
+		soc_id = "i.MX35";
+		break;
+	case MXC_CPU_MX51:
+		soc_id = "i.MX51";
+		break;
+	case MXC_CPU_MX53:
+		soc_id = "i.MX53";
+		break;
+	case MXC_CPU_IMX6SL:
+		soc_id = "i.MX6SL";
+		break;
+	case MXC_CPU_IMX6DL:
+		soc_id = "i.MX6DL";
+		break;
+	case MXC_CPU_IMX6Q:
+		soc_id = "i.MX6Q";
+		break;
+	default:
+		soc_id = "Unknown";
+	}
+	soc_dev_attr->soc_id = soc_id;
+
+	soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d.%d",
+					   (imx_soc_revision >> 4) & 0xf,
+					   imx_soc_revision & 0xf);
+	if (!soc_dev_attr->revision)
+		goto free_soc;
+
+	soc_dev = soc_device_register(soc_dev_attr);
+	if (IS_ERR(soc_dev))
+		goto free_rev;
+
+	return soc_device_to_device(soc_dev);
+
+free_rev:
+	kfree(soc_dev_attr->revision);
+free_soc:
+	kfree(soc_dev_attr);
+	return NULL;
+}

+ 1 - 1
arch/arm/mach-imx/epit.c

@@ -171,7 +171,7 @@ static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
 
 
 static struct irqaction epit_timer_irq = {
 static struct irqaction epit_timer_irq = {
 	.name		= "i.MX EPIT Timer Tick",
 	.name		= "i.MX EPIT Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
 	.handler	= epit_timer_interrupt,
 	.handler	= epit_timer_interrupt,
 };
 };
 
 

+ 2 - 2
arch/arm/mach-imx/gpc.c

@@ -90,7 +90,7 @@ void imx_gpc_restore_all(void)
 		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
 		writel_relaxed(gpc_saved_imrs[i], reg_imr1 + i * 4);
 }
 }
 
 
-static void imx_gpc_irq_unmask(struct irq_data *d)
+void imx_gpc_irq_unmask(struct irq_data *d)
 {
 {
 	void __iomem *reg;
 	void __iomem *reg;
 	u32 val;
 	u32 val;
@@ -105,7 +105,7 @@ static void imx_gpc_irq_unmask(struct irq_data *d)
 	writel_relaxed(val, reg);
 	writel_relaxed(val, reg);
 }
 }
 
 
-static void imx_gpc_irq_mask(struct irq_data *d)
+void imx_gpc_irq_mask(struct irq_data *d)
 {
 {
 	void __iomem *reg;
 	void __iomem *reg;
 	u32 val;
 	u32 val;

+ 3 - 1
arch/arm/mach-imx/hotplug.c

@@ -52,7 +52,9 @@ void imx_cpu_die(unsigned int cpu)
 	 * the register being cleared to kill the cpu.
 	 * the register being cleared to kill the cpu.
 	 */
 	 */
 	imx_set_cpu_arg(cpu, ~0);
 	imx_set_cpu_arg(cpu, ~0);
-	cpu_do_idle();
+
+	while (1)
+		cpu_do_idle();
 }
 }
 
 
 int imx_cpu_kill(unsigned int cpu)
 int imx_cpu_kill(unsigned int cpu)

+ 1 - 2
arch/arm/mach-imx/mach-armadillo5x0.c

@@ -404,8 +404,7 @@ static int armadillo5x0_sdhc1_init(struct device *dev,
 
 
 	/* When supported the trigger type have to be BOTH */
 	/* When supported the trigger type have to be BOTH */
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)),
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)),
-			  detect_irq,
-			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			  detect_irq, IRQF_TRIGGER_FALLING,
 			  "sdhc-detect", data);
 			  "sdhc-detect", data);
 
 
 	if (ret)
 	if (ret)

+ 13 - 64
arch/arm/mach-imx/mach-imx6q.c

@@ -13,7 +13,6 @@
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
 #include <linux/clkdev.h>
 #include <linux/cpu.h>
 #include <linux/cpu.h>
-#include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/io.h>
@@ -38,64 +37,6 @@
 #include "cpuidle.h"
 #include "cpuidle.h"
 #include "hardware.h"
 #include "hardware.h"
 
 
-static u32 chip_revision;
-
-int imx6q_revision(void)
-{
-	return chip_revision;
-}
-
-static void __init imx6q_init_revision(void)
-{
-	u32 rev = imx_anatop_get_digprog();
-
-	switch (rev & 0xff) {
-	case 0:
-		chip_revision = IMX_CHIP_REVISION_1_0;
-		break;
-	case 1:
-		chip_revision = IMX_CHIP_REVISION_1_1;
-		break;
-	case 2:
-		chip_revision = IMX_CHIP_REVISION_1_2;
-		break;
-	default:
-		chip_revision = IMX_CHIP_REVISION_UNKNOWN;
-	}
-
-	mxc_set_cpu_type(rev >> 16 & 0xff);
-}
-
-static void imx6q_restart(enum reboot_mode mode, const char *cmd)
-{
-	struct device_node *np;
-	void __iomem *wdog_base;
-
-	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-wdt");
-	wdog_base = of_iomap(np, 0);
-	if (!wdog_base)
-		goto soft;
-
-	imx_src_prepare_restart();
-
-	/* enable wdog */
-	writew_relaxed(1 << 2, wdog_base);
-	/* write twice to ensure the request will not get ignored */
-	writew_relaxed(1 << 2, wdog_base);
-
-	/* wait for reset to assert ... */
-	mdelay(500);
-
-	pr_err("Watchdog reset failed to assert reset\n");
-
-	/* delay to allow the serial port to show the message */
-	mdelay(50);
-
-soft:
-	/* we'll take a jump through zero as a poor second */
-	soft_restart(0);
-}
-
 /* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
 /* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
 static int ksz9021rn_phy_fixup(struct phy_device *phydev)
 static int ksz9021rn_phy_fixup(struct phy_device *phydev)
 {
 {
@@ -190,12 +131,20 @@ static void __init imx6q_1588_init(void)
 
 
 static void __init imx6q_init_machine(void)
 static void __init imx6q_init_machine(void)
 {
 {
+	struct device *parent;
+
 	imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
 	imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
-			      imx6q_revision());
+			      imx_get_soc_revision());
+
+	mxc_arch_reset_init_dt();
+
+	parent = imx_soc_device_init();
+	if (parent == NULL)
+		pr_warn("failed to initialize soc device\n");
 
 
 	imx6q_enet_phy_init();
 	imx6q_enet_phy_init();
 
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
 
 
 	imx_anatop_init();
 	imx_anatop_init();
 	imx6q_pm_init();
 	imx6q_pm_init();
@@ -270,7 +219,7 @@ static void __init imx6q_init_late(void)
 	 * WAIT mode is broken on TO 1.0 and 1.1, so there is no point
 	 * WAIT mode is broken on TO 1.0 and 1.1, so there is no point
 	 * to run cpuidle on them.
 	 * to run cpuidle on them.
 	 */
 	 */
-	if (imx6q_revision() > IMX_CHIP_REVISION_1_1)
+	if (imx_get_soc_revision() > IMX_CHIP_REVISION_1_1)
 		imx6q_cpuidle_init();
 		imx6q_cpuidle_init();
 
 
 	if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
 	if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
@@ -287,7 +236,7 @@ static void __init imx6q_map_io(void)
 
 
 static void __init imx6q_init_irq(void)
 static void __init imx6q_init_irq(void)
 {
 {
-	imx6q_init_revision();
+	imx_init_revision_from_anatop();
 	imx_init_l2cache();
 	imx_init_l2cache();
 	imx_src_init();
 	imx_src_init();
 	imx_gpc_init();
 	imx_gpc_init();
@@ -307,5 +256,5 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
 	.init_machine	= imx6q_init_machine,
 	.init_machine	= imx6q_init_machine,
 	.init_late      = imx6q_init_late,
 	.init_late      = imx6q_init_late,
 	.dt_compat	= imx6q_dt_compat,
 	.dt_compat	= imx6q_dt_compat,
-	.restart	= imx6q_restart,
+	.restart	= mxc_restart,
 MACHINE_END
 MACHINE_END

+ 32 - 1
arch/arm/mach-imx/mach-imx6sl.c

@@ -10,20 +10,51 @@
 #include <linux/irqchip.h>
 #include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
 #include <linux/of_platform.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/regmap.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/map.h>
 
 
 #include "common.h"
 #include "common.h"
 
 
+static void __init imx6sl_fec_init(void)
+{
+	struct regmap *gpr;
+
+	/* set FEC clock from internal PLL clock source */
+	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sl-iomuxc-gpr");
+	if (!IS_ERR(gpr)) {
+		regmap_update_bits(gpr, IOMUXC_GPR1,
+			IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK, 0);
+		regmap_update_bits(gpr, IOMUXC_GPR1,
+			IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK, 0);
+	} else {
+		pr_err("failed to find fsl,imx6sl-iomux-gpr regmap\n");
+	}
+}
+
 static void __init imx6sl_init_machine(void)
 static void __init imx6sl_init_machine(void)
 {
 {
+	struct device *parent;
+
 	mxc_arch_reset_init_dt();
 	mxc_arch_reset_init_dt();
 
 
-	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+	parent = imx_soc_device_init();
+	if (parent == NULL)
+		pr_warn("failed to initialize soc device\n");
+
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
+
+	imx6sl_fec_init();
+	imx_anatop_init();
+	/* Reuse imx6q pm code */
+	imx6q_pm_init();
 }
 }
 
 
 static void __init imx6sl_init_irq(void)
 static void __init imx6sl_init_irq(void)
 {
 {
+	imx_init_revision_from_anatop();
 	imx_init_l2cache();
 	imx_init_l2cache();
 	imx_src_init();
 	imx_src_init();
 	imx_gpc_init();
 	imx_gpc_init();

+ 1 - 1
arch/arm/mach-imx/mach-mx31_3ds.c

@@ -311,7 +311,7 @@ static int mx31_3ds_sdhc1_init(struct device *dev,
 	}
 	}
 
 
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)),
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)),
-			  detect_irq, IRQF_DISABLED |
+			  detect_irq,
 			  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
 			  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
 			  "sdhc1-detect", data);
 			  "sdhc1-detect", data);
 	if (ret) {
 	if (ret) {

+ 1 - 2
arch/arm/mach-imx/mach-pcm037.c

@@ -371,8 +371,7 @@ static int pcm970_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
 #endif
 #endif
 
 
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SCK6)), detect_irq,
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SCK6)), detect_irq,
-			IRQF_DISABLED | IRQF_TRIGGER_FALLING,
-				"sdhc-detect", data);
+			IRQF_TRIGGER_FALLING, "sdhc-detect", data);
 	if (ret)
 	if (ret)
 		goto err_gpio_free_2;
 		goto err_gpio_free_2;
 
 

+ 17 - 2
arch/arm/mach-imx/mm-imx5.c

@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/clk.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/pinctrl/machine.h>
+#include <linux/of_address.h>
 
 
 #include <asm/mach/map.h>
 #include <asm/mach/map.h>
 
 
@@ -88,8 +89,15 @@ void __init imx51_init_early(void)
 
 
 void __init imx53_init_early(void)
 void __init imx53_init_early(void)
 {
 {
+	struct device_node *np;
+	void __iomem *base;
+
 	mxc_set_cpu_type(MXC_CPU_MX53);
 	mxc_set_cpu_type(MXC_CPU_MX53);
-	mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx53-iomuxc");
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+	mxc_iomux_v3_init(base);
 	imx_src_init();
 	imx_src_init();
 }
 }
 
 
@@ -100,7 +108,14 @@ void __init mx51_init_irq(void)
 
 
 void __init mx53_init_irq(void)
 void __init mx53_init_irq(void)
 {
 {
-	tzic_init_irq(MX53_IO_ADDRESS(MX53_TZIC_BASE_ADDR));
+	struct device_node *np;
+	void __iomem *base;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx53-tzic");
+	base = of_iomap(np, 0);
+	WARN_ON(!base);
+
+	tzic_init_irq(base);
 }
 }
 
 
 static struct sdma_platform_data imx51_sdma_pdata __initdata = {
 static struct sdma_platform_data imx51_sdma_pdata __initdata = {

+ 1 - 2
arch/arm/mach-imx/mx31lilly-db.c

@@ -130,8 +130,7 @@ static int mxc_mmc1_init(struct device *dev,
 	gpio_direction_input(gpio_wp);
 	gpio_direction_input(gpio_wp);
 
 
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)),
 	ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)),
-			  detect_irq,
-			  IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+			  detect_irq, IRQF_TRIGGER_FALLING,
 			  "MMC detect", data);
 			  "MMC detect", data);
 	if (ret)
 	if (ret)
 		goto exit_free_wp;
 		goto exit_free_wp;

+ 6 - 0
arch/arm/mach-imx/mxc.h

@@ -34,6 +34,7 @@
 #define MXC_CPU_MX35		35
 #define MXC_CPU_MX35		35
 #define MXC_CPU_MX51		51
 #define MXC_CPU_MX51		51
 #define MXC_CPU_MX53		53
 #define MXC_CPU_MX53		53
+#define MXC_CPU_IMX6SL		0x60
 #define MXC_CPU_IMX6DL		0x61
 #define MXC_CPU_IMX6DL		0x61
 #define MXC_CPU_IMX6Q		0x63
 #define MXC_CPU_IMX6Q		0x63
 
 
@@ -152,6 +153,11 @@ extern unsigned int __mxc_cpu_type;
 #endif
 #endif
 
 
 #ifndef __ASSEMBLY__
 #ifndef __ASSEMBLY__
+static inline bool cpu_is_imx6sl(void)
+{
+	return __mxc_cpu_type == MXC_CPU_IMX6SL;
+}
+
 static inline bool cpu_is_imx6dl(void)
 static inline bool cpu_is_imx6dl(void)
 {
 {
 	return __mxc_cpu_type == MXC_CPU_IMX6DL;
 	return __mxc_cpu_type == MXC_CPU_IMX6DL;

+ 175 - 1
arch/arm/mach-imx/pm-imx6q.c

@@ -10,9 +10,15 @@
  * http://www.gnu.org/copyleft/gpl.html
  * http://www.gnu.org/copyleft/gpl.html
  */
  */
 
 
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
 #include <linux/of.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/regmap.h>
 #include <linux/suspend.h>
 #include <linux/suspend.h>
 #include <asm/cacheflush.h>
 #include <asm/cacheflush.h>
 #include <asm/proc-fns.h>
 #include <asm/proc-fns.h>
@@ -22,6 +28,147 @@
 #include "common.h"
 #include "common.h"
 #include "hardware.h"
 #include "hardware.h"
 
 
+#define CCR				0x0
+#define BM_CCR_WB_COUNT			(0x7 << 16)
+#define BM_CCR_RBC_BYPASS_COUNT		(0x3f << 21)
+#define BM_CCR_RBC_EN			(0x1 << 27)
+
+#define CLPCR				0x54
+#define BP_CLPCR_LPM			0
+#define BM_CLPCR_LPM			(0x3 << 0)
+#define BM_CLPCR_BYPASS_PMIC_READY	(0x1 << 2)
+#define BM_CLPCR_ARM_CLK_DIS_ON_LPM	(0x1 << 5)
+#define BM_CLPCR_SBYOS			(0x1 << 6)
+#define BM_CLPCR_DIS_REF_OSC		(0x1 << 7)
+#define BM_CLPCR_VSTBY			(0x1 << 8)
+#define BP_CLPCR_STBY_COUNT		9
+#define BM_CLPCR_STBY_COUNT		(0x3 << 9)
+#define BM_CLPCR_COSC_PWRDOWN		(0x1 << 11)
+#define BM_CLPCR_WB_PER_AT_LPM		(0x1 << 16)
+#define BM_CLPCR_WB_CORE_AT_LPM		(0x1 << 17)
+#define BM_CLPCR_BYP_MMDC_CH0_LPM_HS	(0x1 << 19)
+#define BM_CLPCR_BYP_MMDC_CH1_LPM_HS	(0x1 << 21)
+#define BM_CLPCR_MASK_CORE0_WFI		(0x1 << 22)
+#define BM_CLPCR_MASK_CORE1_WFI		(0x1 << 23)
+#define BM_CLPCR_MASK_CORE2_WFI		(0x1 << 24)
+#define BM_CLPCR_MASK_CORE3_WFI		(0x1 << 25)
+#define BM_CLPCR_MASK_SCU_IDLE		(0x1 << 26)
+#define BM_CLPCR_MASK_L2CC_IDLE		(0x1 << 27)
+
+#define CGPR				0x64
+#define BM_CGPR_CHICKEN_BIT		(0x1 << 17)
+
+static void __iomem *ccm_base;
+
+void imx6q_set_chicken_bit(void)
+{
+	u32 val = readl_relaxed(ccm_base + CGPR);
+
+	val |= BM_CGPR_CHICKEN_BIT;
+	writel_relaxed(val, ccm_base + CGPR);
+}
+
+static void imx6q_enable_rbc(bool enable)
+{
+	u32 val;
+
+	/*
+	 * need to mask all interrupts in GPC before
+	 * operating RBC configurations
+	 */
+	imx_gpc_mask_all();
+
+	/* configure RBC enable bit */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_RBC_EN;
+	val |= enable ? BM_CCR_RBC_EN : 0;
+	writel_relaxed(val, ccm_base + CCR);
+
+	/* configure RBC count */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_RBC_BYPASS_COUNT;
+	val |= enable ? BM_CCR_RBC_BYPASS_COUNT : 0;
+	writel(val, ccm_base + CCR);
+
+	/*
+	 * need to delay at least 2 cycles of CKIL(32K)
+	 * due to hardware design requirement, which is
+	 * ~61us, here we use 65us for safe
+	 */
+	udelay(65);
+
+	/* restore GPC interrupt mask settings */
+	imx_gpc_restore_all();
+}
+
+static void imx6q_enable_wb(bool enable)
+{
+	u32 val;
+
+	/* configure well bias enable bit */
+	val = readl_relaxed(ccm_base + CLPCR);
+	val &= ~BM_CLPCR_WB_PER_AT_LPM;
+	val |= enable ? BM_CLPCR_WB_PER_AT_LPM : 0;
+	writel_relaxed(val, ccm_base + CLPCR);
+
+	/* configure well bias count */
+	val = readl_relaxed(ccm_base + CCR);
+	val &= ~BM_CCR_WB_COUNT;
+	val |= enable ? BM_CCR_WB_COUNT : 0;
+	writel_relaxed(val, ccm_base + CCR);
+}
+
+int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
+{
+	struct irq_desc *iomuxc_irq_desc;
+	u32 val = readl_relaxed(ccm_base + CLPCR);
+
+	val &= ~BM_CLPCR_LPM;
+	switch (mode) {
+	case WAIT_CLOCKED:
+		break;
+	case WAIT_UNCLOCKED:
+		val |= 0x1 << BP_CLPCR_LPM;
+		val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
+		break;
+	case STOP_POWER_ON:
+		val |= 0x2 << BP_CLPCR_LPM;
+		break;
+	case WAIT_UNCLOCKED_POWER_OFF:
+		val |= 0x1 << BP_CLPCR_LPM;
+		val &= ~BM_CLPCR_VSTBY;
+		val &= ~BM_CLPCR_SBYOS;
+		break;
+	case STOP_POWER_OFF:
+		val |= 0x2 << BP_CLPCR_LPM;
+		val |= 0x3 << BP_CLPCR_STBY_COUNT;
+		val |= BM_CLPCR_VSTBY;
+		val |= BM_CLPCR_SBYOS;
+		if (cpu_is_imx6sl()) {
+			val |= BM_CLPCR_BYPASS_PMIC_READY;
+			val |= BM_CLPCR_BYP_MMDC_CH0_LPM_HS;
+		} else {
+			val |= BM_CLPCR_BYP_MMDC_CH1_LPM_HS;
+		}
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/*
+	 * Unmask the always pending IOMUXC interrupt #32 as wakeup source to
+	 * deassert dsm_request signal, so that we can ensure dsm_request
+	 * is not asserted when we're going to write CLPCR register to set LPM.
+	 * After setting up LPM bits, we need to mask this wakeup source.
+	 */
+	iomuxc_irq_desc = irq_to_desc(32);
+	imx_gpc_irq_unmask(&iomuxc_irq_desc->irq_data);
+	writel_relaxed(val, ccm_base + CLPCR);
+	imx_gpc_irq_mask(&iomuxc_irq_desc->irq_data);
+
+	return 0;
+}
+
 static int imx6q_suspend_finish(unsigned long val)
 static int imx6q_suspend_finish(unsigned long val)
 {
 {
 	cpu_do_idle();
 	cpu_do_idle();
@@ -33,14 +180,19 @@ static int imx6q_pm_enter(suspend_state_t state)
 	switch (state) {
 	switch (state) {
 	case PM_SUSPEND_MEM:
 	case PM_SUSPEND_MEM:
 		imx6q_set_lpm(STOP_POWER_OFF);
 		imx6q_set_lpm(STOP_POWER_OFF);
+		imx6q_enable_wb(true);
+		imx6q_enable_rbc(true);
 		imx_gpc_pre_suspend();
 		imx_gpc_pre_suspend();
 		imx_anatop_pre_suspend();
 		imx_anatop_pre_suspend();
 		imx_set_cpu_jump(0, v7_cpu_resume);
 		imx_set_cpu_jump(0, v7_cpu_resume);
 		/* Zzz ... */
 		/* Zzz ... */
 		cpu_suspend(0, imx6q_suspend_finish);
 		cpu_suspend(0, imx6q_suspend_finish);
-		imx_smp_prepare();
+		if (cpu_is_imx6q() || cpu_is_imx6dl())
+			imx_smp_prepare();
 		imx_anatop_post_resume();
 		imx_anatop_post_resume();
 		imx_gpc_post_resume();
 		imx_gpc_post_resume();
+		imx6q_enable_rbc(false);
+		imx6q_enable_wb(false);
 		imx6q_set_lpm(WAIT_CLOCKED);
 		imx6q_set_lpm(WAIT_CLOCKED);
 		break;
 		break;
 	default:
 	default:
@@ -55,7 +207,29 @@ static const struct platform_suspend_ops imx6q_pm_ops = {
 	.valid = suspend_valid_only_mem,
 	.valid = suspend_valid_only_mem,
 };
 };
 
 
+void __init imx6q_pm_set_ccm_base(void __iomem *base)
+{
+	ccm_base = base;
+}
+
 void __init imx6q_pm_init(void)
 void __init imx6q_pm_init(void)
 {
 {
+	struct regmap *gpr;
+
+	WARN_ON(!ccm_base);
+
+	/*
+	 * Force IOMUXC irq pending, so that the interrupt to GPC can be
+	 * used to deassert dsm_request signal when the signal gets
+	 * asserted unexpectedly.
+	 */
+	gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+	if (!IS_ERR(gpr))
+		regmap_update_bits(gpr, IOMUXC_GPR1, IMX6Q_GPR1_GINT,
+				   IMX6Q_GPR1_GINT);
+
+	/* Set initial power mode */
+	imx6q_set_lpm(WAIT_CLOCKED);
+
 	suspend_set_ops(&imx6q_pm_ops);
 	suspend_set_ops(&imx6q_pm_ops);
 }
 }

+ 1 - 0
arch/arm/mach-imx/src.c

@@ -91,6 +91,7 @@ void imx_enable_cpu(int cpu, bool enable)
 	spin_lock(&scr_lock);
 	spin_lock(&scr_lock);
 	val = readl_relaxed(src_base + SRC_SCR);
 	val = readl_relaxed(src_base + SRC_SCR);
 	val = enable ? val | mask : val & ~mask;
 	val = enable ? val | mask : val & ~mask;
+	val |= 1 << (BP_SRC_SCR_CORE1_RST + cpu - 1);
 	writel_relaxed(val, src_base + SRC_SCR);
 	writel_relaxed(val, src_base + SRC_SCR);
 	spin_unlock(&scr_lock);
 	spin_unlock(&scr_lock);
 }
 }

+ 5 - 0
arch/arm/mach-imx/system.c

@@ -42,6 +42,9 @@ void mxc_restart(enum reboot_mode mode, const char *cmd)
 {
 {
 	unsigned int wcr_enable;
 	unsigned int wcr_enable;
 
 
+	if (cpu_is_imx6q() || cpu_is_imx6dl())
+		imx_src_prepare_restart();
+
 	if (wdog_clk)
 	if (wdog_clk)
 		clk_enable(wdog_clk);
 		clk_enable(wdog_clk);
 
 
@@ -52,6 +55,8 @@ void mxc_restart(enum reboot_mode mode, const char *cmd)
 
 
 	/* Assert SRS signal */
 	/* Assert SRS signal */
 	__raw_writew(wcr_enable, wdog_base);
 	__raw_writew(wcr_enable, wdog_base);
+	/* write twice to ensure the request will not get ignored */
+	__raw_writew(wcr_enable, wdog_base);
 
 
 	/* wait for reset to assert... */
 	/* wait for reset to assert... */
 	mdelay(500);
 	mdelay(500);

+ 1 - 1
arch/arm/mach-imx/time.c

@@ -250,7 +250,7 @@ static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id)
 
 
 static struct irqaction mxc_timer_irq = {
 static struct irqaction mxc_timer_irq = {
 	.name		= "i.MX Timer Tick",
 	.name		= "i.MX Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
 	.handler	= mxc_timer_interrupt,
 	.handler	= mxc_timer_interrupt,
 };
 };
 
 

+ 5 - 0
include/linux/mfd/syscon/imx6q-iomuxc-gpr.h

@@ -363,4 +363,9 @@
 #define IMX6Q_GPR13_SATA_TX_LVL_1_240_V		(0x1f << 2)
 #define IMX6Q_GPR13_SATA_TX_LVL_1_240_V		(0x1f << 2)
 #define IMX6Q_GPR13_SATA_MPLL_CLK_EN		BIT(1)
 #define IMX6Q_GPR13_SATA_MPLL_CLK_EN		BIT(1)
 #define IMX6Q_GPR13_SATA_TX_EDGE_RATE		BIT(0)
 #define IMX6Q_GPR13_SATA_TX_EDGE_RATE		BIT(0)
+
+/* For imx6sl iomux gpr register field define */
+#define IMX6SL_GPR1_FEC_CLOCK_MUX1_SEL_MASK    (0x3 << 17)
+#define IMX6SL_GPR1_FEC_CLOCK_MUX2_SEL_MASK    (0x1 << 14)
+
 #endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */
 #endif /* __LINUX_IMX6Q_IOMUXC_GPR_H */