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
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQEcBAABAgAGBQJSZI9RAAoJEFBXWFqHsHzOhgkH/RpZ6cvXFFaRdTWQu/SZCXTN
 m3Ul0VpuaUp9gsbDNbu//OmqCAsayXaKI7PuJhs885zDKw6R3yMH7hbwXY7z0Qrq
 jl9hP1Wzj7oU4CHTQbSDdcO3glUk+jl58a2MrsMsUaXPJTF8iMb8RkatwnReYhiZ
 uCBXPwaet7SJTuVQOL1uJmq35LmiROwyAkGsDKnDmphg3ZDUiI9mhqlyOyrS522w
 TjmCXrzZQiHkTp12Xo42fIEvE6BF5wCLDlJbq9HRDAlT82CnV62uQC/9os45Hott
 H1pJbwdbcdv3+6gUdnWbraukrbhCxT8Yk0As4ljP6YBCxC7Sau+oMh3ii4pvuI0=
 =VUrE
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Olof Johansson 2013-10-28 10:37:52 -07:00
commit b6fb5474af
30 changed files with 592 additions and 346 deletions

View File

@ -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:

View File

@ -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"

View File

@ -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>;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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; unsigned int revision;
u32 digprog;
if (digprog) u16 offset = ANADIG_DIGPROG;
return 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);
return digprog; 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;
}
mxc_set_cpu_type(digprog >> 16 & 0xff);
imx_set_soc_revision(revision);
} }
void __init imx_anatop_init(void) void __init imx_anatop_init(void)

View File

@ -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);

View File

@ -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 */ /* All existing boards with PCIe use LVDS1 */
imx6q_set_lpm(WAIT_CLOCKED); 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);

View File

@ -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));

View File

@ -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); void mx1_map_io(void);
extern void mx21_map_io(void); void mx21_map_io(void);
extern void mx25_map_io(void); void mx25_map_io(void);
extern void mx27_map_io(void); void mx27_map_io(void);
extern void mx31_map_io(void); void mx31_map_io(void);
extern void mx35_map_io(void); void mx35_map_io(void);
extern void mx51_map_io(void); void mx51_map_io(void);
extern void mx53_map_io(void); void mx53_map_io(void);
extern void imx1_init_early(void); void imx1_init_early(void);
extern void imx21_init_early(void); void imx21_init_early(void);
extern void imx25_init_early(void); void imx25_init_early(void);
extern void imx27_init_early(void); void imx27_init_early(void);
extern void imx31_init_early(void); void imx31_init_early(void);
extern void imx35_init_early(void); void imx35_init_early(void);
extern void imx51_init_early(void); void imx51_init_early(void);
extern void imx53_init_early(void); void imx53_init_early(void);
extern void mxc_init_irq(void __iomem *); void mxc_init_irq(void __iomem *);
extern void tzic_init_irq(void __iomem *); void tzic_init_irq(void __iomem *);
extern void mx1_init_irq(void); void mx1_init_irq(void);
extern void mx21_init_irq(void); void mx21_init_irq(void);
extern void mx25_init_irq(void); void mx25_init_irq(void);
extern void mx27_init_irq(void); void mx27_init_irq(void);
extern void mx31_init_irq(void); void mx31_init_irq(void);
extern void mx35_init_irq(void); void mx35_init_irq(void);
extern void mx51_init_irq(void); void mx51_init_irq(void);
extern void mx53_init_irq(void); void mx53_init_irq(void);
extern void imx1_soc_init(void); void imx1_soc_init(void);
extern void imx21_soc_init(void); void imx21_soc_init(void);
extern void imx25_soc_init(void); void imx25_soc_init(void);
extern void imx27_soc_init(void); void imx27_soc_init(void);
extern void imx31_soc_init(void); void imx31_soc_init(void);
extern void imx35_soc_init(void); void imx35_soc_init(void);
extern void imx51_soc_init(void); void imx51_soc_init(void);
extern void imx51_init_late(void); void imx51_init_late(void);
extern void imx53_init_late(void); void imx53_init_late(void);
extern void epit_timer_init(void __iomem *base, int irq); void epit_timer_init(void __iomem *base, int irq);
extern void mxc_timer_init(void __iomem *, int); void mxc_timer_init(void __iomem *, int);
extern int mx1_clocks_init(unsigned long fref); int mx1_clocks_init(unsigned long fref);
extern int mx21_clocks_init(unsigned long lref, unsigned long fref); int mx21_clocks_init(unsigned long lref, unsigned long fref);
extern int mx25_clocks_init(void); int mx25_clocks_init(void);
extern int mx27_clocks_init(unsigned long fref); int mx27_clocks_init(unsigned long fref);
extern int mx31_clocks_init(unsigned long fref); int mx31_clocks_init(unsigned long fref);
extern int mx35_clocks_init(void); int mx35_clocks_init(void);
extern int mx51_clocks_init(unsigned long ckil, unsigned long osc, 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); int mx25_clocks_init_dt(void);
extern int mx27_clocks_init_dt(void); int mx27_clocks_init_dt(void);
extern int mx31_clocks_init_dt(void); int mx31_clocks_init_dt(void);
extern struct platform_device *mxc_register_gpio(char *name, int id, 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); void mxc_set_cpu_type(unsigned int type);
extern void mxc_restart(enum reboot_mode, const char *); void mxc_restart(enum reboot_mode, const char *);
extern void mxc_arch_reset_init(void __iomem *); void mxc_arch_reset_init(void __iomem *);
extern void mxc_arch_reset_init_dt(void); void mxc_arch_reset_init_dt(void);
extern int mx53_revision(void); int mx53_revision(void);
extern int imx6q_revision(void); void imx_set_aips(void __iomem *);
extern int mx53_display_revision(void); int mxc_device_init(void);
extern void imx_set_aips(void __iomem *); void imx_set_soc_revision(unsigned int rev);
extern int mxc_device_init(void); 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); void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode);
extern void imx_print_silicon_rev(const char *cpu, int srev); 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); void imx_enable_cpu(int cpu, bool enable);
extern void imx_set_cpu_jump(int cpu, void *jump_addr); void imx_set_cpu_jump(int cpu, void *jump_addr);
extern u32 imx_get_cpu_arg(int cpu); u32 imx_get_cpu_arg(int cpu);
extern void imx_set_cpu_arg(int cpu, u32 arg); void imx_set_cpu_arg(int cpu, u32 arg);
extern void v7_cpu_resume(void); void v7_cpu_resume(void);
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
extern void v7_secondary_startup(void); void v7_secondary_startup(void);
extern void imx_scu_map_io(void); void imx_scu_map_io(void);
extern void imx_smp_prepare(void); void imx_smp_prepare(void);
extern void imx_scu_standby_enable(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); void imx_src_init(void);
extern void imx_src_prepare_restart(void); #ifdef CONFIG_HAVE_IMX_SRC
extern void imx_gpc_init(void); void imx_src_prepare_restart(void);
extern void imx_gpc_pre_suspend(void); #else
extern void imx_gpc_post_resume(void); static inline void imx_src_prepare_restart(void) {}
extern void imx_gpc_mask_all(void); #endif
extern void imx_gpc_restore_all(void); void imx_gpc_init(void);
extern void imx_anatop_init(void); void imx_gpc_pre_suspend(void);
extern void imx_anatop_pre_suspend(void); void imx_gpc_post_resume(void);
extern void imx_anatop_post_resume(void); void imx_gpc_mask_all(void);
extern u32 imx_anatop_get_digprog(void); void imx_gpc_restore_all(void);
extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode); void imx_gpc_irq_mask(struct irq_data *d);
extern void imx6q_set_chicken_bit(void); 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);
extern void imx_cpu_die(unsigned int cpu); void imx_cpu_die(unsigned int cpu);
extern int imx_cpu_kill(unsigned int cpu); int imx_cpu_kill(unsigned int cpu);
#ifdef CONFIG_PM #ifdef CONFIG_PM
extern void imx6q_pm_init(void); void imx6q_pm_init(void);
extern void imx5_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

View File

@ -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;
}

View File

@ -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,
}; };

View File

@ -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;

View File

@ -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)

View File

@ -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, detect_irq, IRQF_TRIGGER_FALLING,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
"sdhc-detect", data); "sdhc-detect", data);
if (ret) if (ret)

View File

@ -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

View File

@ -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();

View File

@ -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) {

View File

@ -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, IRQF_TRIGGER_FALLING, "sdhc-detect", data);
"sdhc-detect", data);
if (ret) if (ret)
goto err_gpio_free_2; goto err_gpio_free_2;

View File

@ -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 = {

View File

@ -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, detect_irq, IRQF_TRIGGER_FALLING,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
"MMC detect", data); "MMC detect", data);
if (ret) if (ret)
goto exit_free_wp; goto exit_free_wp;

View File

@ -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;

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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);

View File

@ -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,
}; };

View File

@ -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 */