summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/Kconfig6
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c23
-rw-r--r--arch/arm/mach-imx/mach-imx6sx.c27
-rw-r--r--arch/arm/mach-imx/system.c62
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);