diff options
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r-- | arch/arm/mach-imx/Kconfig | 6 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6q.c | 23 | ||||
-rw-r--r-- | arch/arm/mach-imx/mach-imx6sx.c | 27 | ||||
-rw-r--r-- | arch/arm/mach-imx/system.c | 62 |
4 files changed, 117 insertions, 1 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 65d5476679c6..bb8454ba609b 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -889,6 +889,12 @@ config SOC_VF610 help This enable support for Freescale Vybrid VF610 processor. +config MXC_REBOOT_MFGMODE + bool "MFG mode setting" + +config MXC_REBOOT_ANDROID_CMD + bool "Android reboot setting" + endif source "arch/arm/mach-imx/devices/Kconfig" diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index aafec45babab..6da2da5ed2f5 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -231,6 +231,28 @@ static void __init imx6q_csi_mux_init(void) } } +/* + * Init GPIO PCIE_PWR_EN to keep power supply to miniPCIE 3G modem + * +*/ +static void __init imx6q_mini_pcie_init(void) +{ + struct device_node *np = NULL; + int ret, power_on_gpio; + np = of_find_node_by_name(NULL, "minipcie_ctrl"); + if (!np) + return; + + power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0); + if (gpio_is_valid(power_on_gpio)) { + ret = gpio_request_one(power_on_gpio, GPIOF_OUT_INIT_HIGH, + "miniPCIE Power On"); + pr_warn("!!request miniPCIE Power On gpio\n"); + if (ret) + pr_warn("failed to request miniPCIE Power On gpio\n"); + } +} + #define OCOTP_MACn(n) (0x00000620 + (n) * 0x10) void __init imx6_enet_mac_init(const char *compatible) { @@ -339,6 +361,7 @@ static void __init imx6q_init_machine(void) imx_anatop_init(); imx6_pm_init(); imx6q_csi_mux_init(); + imx6q_mini_pcie_init(); } #define OCOTP_CFG3 0x440 diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c index 96c79a0bb4f5..c92decf51a21 100644 --- a/arch/arm/mach-imx/mach-imx6sx.c +++ b/arch/arm/mach-imx/mach-imx6sx.c @@ -29,6 +29,9 @@ #include "cpuidle.h" #include "hardware.h" +static struct platform_device imx6slx_cpufreq_pdev = { + .name = "imx6-cpufreq", +}; static struct flexcan_platform_data flexcan_pdata[2]; static int flexcan_en_gpio; static int flexcan_stby_gpio; @@ -190,6 +193,25 @@ static void __init imx6sx_init_machine(void) imx6sx_qos_init(); } +static void __init imx6slx_opp_init(struct device *cpu_dev) +{ + struct device_node *np; + + np = of_find_node_by_path("/cpus/cpu@0"); + if (!np) { + pr_warn("failed to find cpu0 node\n"); + return; + } + + cpu_dev->of_node = np; + if (of_init_opp_table(cpu_dev)) { + pr_warn("failed to init OPP table\n"); + goto put_node; + } + +put_node: + of_node_put(np); +} static void __init imx6sx_init_late(void) { struct regmap *gpr; @@ -209,6 +231,11 @@ static void __init imx6sx_init_late(void) if (of_machine_is_compatible("fsl,imx6sx-17x17-arm2") || of_machine_is_compatible("fsl,imx6sx-sdb")) imx6sx_arm2_flexcan_fixup(); + + if (IS_ENABLED(CONFIG_ARM_IMX6_CPUFREQ)) { + imx6slx_opp_init(&imx6slx_cpufreq_pdev.dev); + platform_device_register(&imx6slx_cpufreq_pdev); + } } static void __init imx6sx_map_io(void) diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c index df3d1ff0c288..b3f48f032a26 100644 --- a/arch/arm/mach-imx/system.c +++ b/arch/arm/mach-imx/system.c @@ -1,7 +1,7 @@ /* * Copyright (C) 1999 ARM Limited * Copyright (C) 2000 Deep Blue Solutions Ltd - * Copyright (C) 2006-2013 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2006-2014 Freescale Semiconductor, Inc. All Rights Reserved. * Copyright 2008 Juergen Beisert, kernel@pengutronix.de * Copyright 2009 Ilya Yanok, Emcraft Systems Ltd, yanok@emcraft.com * @@ -31,11 +31,69 @@ #include "common.h" #include "hardware.h" +#include "mx6.h" static void __iomem *wdog_base; static struct clk *wdog_clk; static u32 wdog_source = 1; /* use WDOG1 default */ +#ifdef CONFIG_MXC_REBOOT_ANDROID_CMD +/* This function will set a bit on SNVS_LPGPR[7-8] bits to enter + * special boot mode. These bits will not clear by watchdog reset, so + * it can be checked by bootloader to choose enter different mode.*/ + +#define ANDROID_RECOVERY_BOOT (1 << 7) +#define ANDROID_FASTBOOT_BOOT (1 << 8) + +#define AIPS1_ARB_BASE_ADDR 0x02000000 +#define ATZ1_BASE_ADDR AIPS1_ARB_BASE_ADDR +#define AIPS1_OFF_BASE_ADDR (ATZ1_BASE_ADDR + 0x80000) +#define MX6_SNVS_BASE_ADDR (AIPS1_OFF_BASE_ADDR + 0x4C000) +#define SNVS_LPGPR 0x68 +#define SNVS_SIZE (1024*16) +void do_switch_recovery(void) +{ + u32 reg; + u32 addr; + addr = ioremap(MX6_SNVS_BASE_ADDR, SNVS_SIZE); + if (!addr) { + pr_warn("SNVS ioremap failed!\n"); + return; + } + reg = __raw_readl(addr + SNVS_LPGPR); + reg |= ANDROID_RECOVERY_BOOT; + __raw_writel(reg, (addr + SNVS_LPGPR)); + + iounmap(addr); +} + +void do_switch_fastboot(void) +{ + u32 reg; + u32 addr; + + addr = ioremap(MX6_SNVS_BASE_ADDR, SNVS_SIZE); + if (!addr) { + pr_warn("SNVS ioremap failed!\n"); + return; + } + + reg = __raw_readl(addr + SNVS_LPGPR); + reg |= ANDROID_FASTBOOT_BOOT; + __raw_writel(reg, addr + SNVS_LPGPR); + + iounmap(addr); +} +#endif +static void arch_reset_special_mode(char mode, const char *cmd) +{ +#ifdef CONFIG_MXC_REBOOT_ANDROID_CMD + if (strcmp(cmd, "recovery") == 0) + do_switch_recovery(); + else if (strcmp(cmd, "fastboot") == 0) + do_switch_fastboot(); +#endif +} /* * Reset the system. It is called by machine_restart(). */ @@ -43,6 +101,8 @@ void mxc_restart(char mode, const char *cmd) { unsigned int wcr_enable; + arch_reset_special_mode(mode, cmd); + if (wdog_clk) clk_enable(wdog_clk); |