summaryrefslogtreecommitdiff
path: root/arch/arm/mach-imx
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-03-06 09:33:05 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-06 09:33:05 -0800
commitaebbfafc74b8d4eac573aab47aaa2e7965295096 (patch)
tree42d34e293b4142957da56877c6479afa8cbb347c /arch/arm/mach-imx
parentfa29f5ba42404b44aceb1a63ff4757efe5cd1789 (diff)
parent49b35cd5e7ddad04ae2fac614cd26f29c4851957 (diff)
Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
Pull ARM SoC platform updates from Arnd Bergmann: "The APM X-Gene platform is now maintained by folks from Ampere computing that took over the product line a while ago, this gets reflected in the MAINTAINERS file. Cleanups continue on the older mach-davinci and mach-pxa platform, to get them to be more like the modern ones. For pxa, we now remove the Raumfeld platform code as it now works with device tree based booting. i.MX adds a couple new features for the i.MX7ULP SoC Mediatek gains support for a new SoC: MT7629 is a new wireless router platform, following MT7623. Aside from those, there are the usual minor cleanups and bugfixes across several platforms" * tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (49 commits) MAINTAINERS: Update Ampere email address usb: ohci-da8xx: remove unused callbacks from platform data ARM: davinci: da830-evm: remove legacy usb helpers ARM: davinci: omapl138-hawk: remove legacy usb helpers usb: ohci-da8xx: add vbus and overcurrent gpios ARM: davinci: da830-evm: use gpio lookup entries for usb gpios ARM: davinci: omapl138-hawk: use gpio lookup entries for usb gpios usb: ohci-da8xx: add a helper pointer to &pdev->dev usb: ohci-da8xx: add a new line after local variables arm64: meson: enable g12a clock controller MAINTAINERS: Add entry for uDPU board ARM: davinci: da850-evm: use GPIO hogs instead of the legacy API arm: mediatek: add MT7629 smp bring up code Revert "ARM: mediatek: add MT7623a smp bringup code" dt-bindings: soc: fix typo of MT8173 power dt-bindings ARM: meson: remove COMMON_CLK_AMLOGIC selection arm64: meson: remove COMMON_CLK_AMLOGIC selection ARM: lpc32xx: remove platform data of ARM PL111 LCD controller ARM: lpc32xx: remove platform data of ARM PL180 SD/MMC controller ARM: lpc32xx: Use kmemdup to replace duplicating its implementation ...
Diffstat (limited to 'arch/arm/mach-imx')
-rw-r--r--arch/arm/mach-imx/Makefile3
-rw-r--r--arch/arm/mach-imx/common.h10
-rw-r--r--arch/arm/mach-imx/cpuidle-imx7ulp.c60
-rw-r--r--arch/arm/mach-imx/cpuidle.h5
-rw-r--r--arch/arm/mach-imx/mach-imx7ulp.c46
-rw-r--r--arch/arm/mach-imx/pm-imx7ulp.c49
6 files changed, 167 insertions, 6 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 8af2f7e91d13..35ff620537e6 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -29,9 +29,10 @@ obj-$(CONFIG_SOC_IMX6SL) += cpuidle-imx6sl.o
obj-$(CONFIG_SOC_IMX6SLL) += cpuidle-imx6sx.o
obj-$(CONFIG_SOC_IMX6SX) += cpuidle-imx6sx.o
obj-$(CONFIG_SOC_IMX6UL) += cpuidle-imx6sx.o
+obj-$(CONFIG_SOC_IMX7ULP) += cpuidle-imx7ulp.o
endif
-ifdef CONFIG_SND_IMX_SOC
+ifdef CONFIG_SND_SOC_IMX_PCM_FIQ
obj-y += ssi-fiq.o
obj-y += ssi-fiq-ksym.o
endif
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index bc915e5b4d56..c51764a85fd7 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -72,6 +72,15 @@ enum mxc_cpu_pwr_mode {
STOP_POWER_OFF, /* STOP + SRPG */
};
+enum ulp_cpu_pwr_mode {
+ ULP_PM_HSRUN, /* High speed run mode */
+ ULP_PM_RUN, /* Run mode */
+ ULP_PM_WAIT, /* Wait mode */
+ ULP_PM_STOP, /* Stop mode */
+ ULP_PM_VLPS, /* Very low power stop mode */
+ ULP_PM_VLLS, /* very low leakage stop mode */
+};
+
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);
@@ -98,6 +107,7 @@ int imx6_set_lpm(enum mxc_cpu_pwr_mode mode);
void imx6_set_int_mem_clk_lpm(bool enable);
void imx6sl_set_wait_clk(bool enter);
int imx_mmdc_get_ddr_type(void);
+int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode);
void imx_cpu_die(unsigned int cpu);
int imx_cpu_kill(unsigned int cpu);
diff --git a/arch/arm/mach-imx/cpuidle-imx7ulp.c b/arch/arm/mach-imx/cpuidle-imx7ulp.c
new file mode 100644
index 000000000000..ca86c967d19e
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx7ulp.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017-2018 NXP
+ * Anson Huang <Anson.Huang@nxp.com>
+ */
+
+#include <linux/cpuidle.h>
+#include <linux/module.h>
+#include <asm/cpuidle.h>
+
+#include "common.h"
+#include "cpuidle.h"
+
+static int imx7ulp_enter_wait(struct cpuidle_device *dev,
+ struct cpuidle_driver *drv, int index)
+{
+ if (index == 1)
+ imx7ulp_set_lpm(ULP_PM_WAIT);
+ else
+ imx7ulp_set_lpm(ULP_PM_STOP);
+
+ cpu_do_idle();
+
+ imx7ulp_set_lpm(ULP_PM_RUN);
+
+ return index;
+}
+
+static struct cpuidle_driver imx7ulp_cpuidle_driver = {
+ .name = "imx7ulp_cpuidle",
+ .owner = THIS_MODULE,
+ .states = {
+ /* WFI */
+ ARM_CPUIDLE_WFI_STATE,
+ /* WAIT */
+ {
+ .exit_latency = 50,
+ .target_residency = 75,
+ .enter = imx7ulp_enter_wait,
+ .name = "WAIT",
+ .desc = "PSTOP2",
+ },
+ /* STOP */
+ {
+ .exit_latency = 100,
+ .target_residency = 150,
+ .enter = imx7ulp_enter_wait,
+ .name = "STOP",
+ .desc = "PSTOP1",
+ },
+ },
+ .state_count = 3,
+ .safe_state_index = 0,
+};
+
+int __init imx7ulp_cpuidle_init(void)
+{
+ return cpuidle_register(&imx7ulp_cpuidle_driver, NULL);
+}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index f9140128ba05..7694c8f810a4 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -15,6 +15,7 @@ extern int imx5_cpuidle_init(void);
extern int imx6q_cpuidle_init(void);
extern int imx6sl_cpuidle_init(void);
extern int imx6sx_cpuidle_init(void);
+extern int imx7ulp_cpuidle_init(void);
#else
static inline int imx5_cpuidle_init(void)
{
@@ -32,4 +33,8 @@ static inline int imx6sx_cpuidle_init(void)
{
return 0;
}
+static inline int imx7ulp_cpuidle_init(void)
+{
+ return 0;
+}
#endif
diff --git a/arch/arm/mach-imx/mach-imx7ulp.c b/arch/arm/mach-imx/mach-imx7ulp.c
index 33937ebf66b5..11ac71aaf965 100644
--- a/arch/arm/mach-imx/mach-imx7ulp.c
+++ b/arch/arm/mach-imx/mach-imx7ulp.c
@@ -6,17 +6,57 @@
*/
#include <linux/irqchip.h>
+#include <linux/mfd/syscon.h>
#include <linux/of_platform.h>
+#include <linux/regmap.h>
#include <asm/mach/arch.h>
#include "common.h"
+#include "cpuidle.h"
#include "hardware.h"
+#define SIM_JTAG_ID_REG 0x8c
+
+static void __init imx7ulp_set_revision(void)
+{
+ struct regmap *sim;
+ u32 revision;
+
+ sim = syscon_regmap_lookup_by_compatible("fsl,imx7ulp-sim");
+ if (IS_ERR(sim)) {
+ pr_warn("failed to find fsl,imx7ulp-sim regmap!\n");
+ return;
+ }
+
+ if (regmap_read(sim, SIM_JTAG_ID_REG, &revision)) {
+ pr_warn("failed to read sim regmap!\n");
+ return;
+ }
+
+ /*
+ * bit[31:28] of JTAG_ID register defines revision as below from B0:
+ * 0001 B0
+ * 0010 B1
+ */
+ switch (revision >> 28) {
+ case 1:
+ imx_set_soc_revision(IMX_CHIP_REVISION_2_0);
+ break;
+ case 2:
+ imx_set_soc_revision(IMX_CHIP_REVISION_2_1);
+ break;
+ default:
+ imx_set_soc_revision(IMX_CHIP_REVISION_1_0);
+ break;
+ }
+}
+
static void __init imx7ulp_init_machine(void)
{
imx7ulp_pm_init();
mxc_set_cpu_type(MXC_CPU_IMX7ULP);
+ imx7ulp_set_revision();
of_platform_default_populate(NULL, NULL, imx_soc_device_init());
}
@@ -25,7 +65,13 @@ static const char *const imx7ulp_dt_compat[] __initconst = {
NULL,
};
+static void __init imx7ulp_init_late(void)
+{
+ imx7ulp_cpuidle_init();
+}
+
DT_MACHINE_START(IMX7ulp, "Freescale i.MX7ULP (Device Tree)")
.init_machine = imx7ulp_init_machine,
.dt_compat = imx7ulp_dt_compat,
+ .init_late = imx7ulp_init_late,
MACHINE_END
diff --git a/arch/arm/mach-imx/pm-imx7ulp.c b/arch/arm/mach-imx/pm-imx7ulp.c
index cf6a380c2b8d..7b2f7387e662 100644
--- a/arch/arm/mach-imx/pm-imx7ulp.c
+++ b/arch/arm/mach-imx/pm-imx7ulp.c
@@ -9,21 +9,60 @@
#include <linux/of.h>
#include <linux/of_address.h>
+#include "common.h"
+
#define SMC_PMCTRL 0x10
#define BP_PMCTRL_PSTOPO 16
#define PSTOPO_PSTOP3 0x3
+#define PSTOPO_PSTOP2 0x2
+#define PSTOPO_PSTOP1 0x1
+#define BP_PMCTRL_RUNM 8
+#define RUNM_RUN 0
+#define BP_PMCTRL_STOPM 0
+#define STOPM_STOP 0
+
+#define BM_PMCTRL_PSTOPO (3 << BP_PMCTRL_PSTOPO)
+#define BM_PMCTRL_RUNM (3 << BP_PMCTRL_RUNM)
+#define BM_PMCTRL_STOPM (7 << BP_PMCTRL_STOPM)
+
+static void __iomem *smc1_base;
+
+int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode)
+{
+ u32 val = readl_relaxed(smc1_base + SMC_PMCTRL);
+
+ /* clear all */
+ val &= ~(BM_PMCTRL_RUNM | BM_PMCTRL_STOPM | BM_PMCTRL_PSTOPO);
+
+ switch (mode) {
+ case ULP_PM_RUN:
+ /* system/bus clock enabled */
+ val |= PSTOPO_PSTOP3 << BP_PMCTRL_PSTOPO;
+ break;
+ case ULP_PM_WAIT:
+ /* system clock disabled, bus clock enabled */
+ val |= PSTOPO_PSTOP2 << BP_PMCTRL_PSTOPO;
+ break;
+ case ULP_PM_STOP:
+ /* system/bus clock disabled */
+ val |= PSTOPO_PSTOP1 << BP_PMCTRL_PSTOPO;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ writel_relaxed(val, smc1_base + SMC_PMCTRL);
+
+ return 0;
+}
void __init imx7ulp_pm_init(void)
{
struct device_node *np;
- void __iomem *smc1_base;
np = of_find_compatible_node(NULL, NULL, "fsl,imx7ulp-smc1");
smc1_base = of_iomap(np, 0);
WARN_ON(!smc1_base);
- /* Partial Stop mode 3 with system/bus clock enabled */
- writel_relaxed(PSTOPO_PSTOP3 << BP_PMCTRL_PSTOPO,
- smc1_base + SMC_PMCTRL);
- iounmap(smc1_base);
+ imx7ulp_set_lpm(ULP_PM_RUN);
}