mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-29 01:59:02 +00:00
a83eae385a
This patch is to update linux 4.9 patches to LSDK-18.06 release and to adjust config-4.9 accordingly. Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
1031 lines
31 KiB
Diff
1031 lines
31 KiB
Diff
From d78d78ccbaded757e8bea0d13c4120518bdd4660 Mon Sep 17 00:00:00 2001
|
|
From: Yangbo Lu <yangbo.lu@nxp.com>
|
|
Date: Thu, 5 Jul 2018 17:21:38 +0800
|
|
Subject: [PATCH 15/32] cpufreq: support layerscape
|
|
|
|
This is an integrated patch for layerscape pm support.
|
|
|
|
Signed-off-by: Tang Yuantian <Yuantian.Tang@nxp.com>
|
|
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
|
|
---
|
|
.../devicetree/bindings/powerpc/fsl/pmc.txt | 59 ++--
|
|
drivers/cpufreq/Kconfig | 2 +-
|
|
drivers/cpufreq/qoriq-cpufreq.c | 176 +++++------
|
|
drivers/firmware/psci.c | 12 +-
|
|
drivers/soc/fsl/rcpm.c | 158 ++++++++++
|
|
drivers/soc/fsl/sleep_fsm.c | 279 ++++++++++++++++++
|
|
drivers/soc/fsl/sleep_fsm.h | 130 ++++++++
|
|
7 files changed, 678 insertions(+), 138 deletions(-)
|
|
create mode 100644 drivers/soc/fsl/rcpm.c
|
|
create mode 100644 drivers/soc/fsl/sleep_fsm.c
|
|
create mode 100644 drivers/soc/fsl/sleep_fsm.h
|
|
|
|
--- a/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
|
|
+++ b/Documentation/devicetree/bindings/powerpc/fsl/pmc.txt
|
|
@@ -9,15 +9,20 @@ Properties:
|
|
|
|
"fsl,mpc8548-pmc" should be listed for any chip whose PMC is
|
|
compatible. "fsl,mpc8536-pmc" should also be listed for any chip
|
|
- whose PMC is compatible, and implies deep-sleep capability.
|
|
+ whose PMC is compatible, and implies deep-sleep capability and
|
|
+ wake on user defined packet(wakeup on ARP).
|
|
+
|
|
+ "fsl,p1022-pmc" should be listed for any chip whose PMC is
|
|
+ compatible, and implies lossless Ethernet capability during sleep.
|
|
|
|
"fsl,mpc8641d-pmc" should be listed for any chip whose PMC is
|
|
compatible; all statements below that apply to "fsl,mpc8548-pmc" also
|
|
apply to "fsl,mpc8641d-pmc".
|
|
|
|
Compatibility does not include bit assignments in SCCR/PMCDR/DEVDISR; these
|
|
- bit assignments are indicated via the sleep specifier in each device's
|
|
- sleep property.
|
|
+ bit assignments are indicated via the clock nodes. Device which has a
|
|
+ controllable clock source should have a "fsl,pmc-handle" property pointing
|
|
+ to the clock node.
|
|
|
|
- reg: For devices compatible with "fsl,mpc8349-pmc", the first resource
|
|
is the PMC block, and the second resource is the Clock Configuration
|
|
@@ -33,31 +38,35 @@ Properties:
|
|
this is a phandle to an "fsl,gtm" node on which timer 4 can be used as
|
|
a wakeup source from deep sleep.
|
|
|
|
-Sleep specifiers:
|
|
-
|
|
- fsl,mpc8349-pmc: Sleep specifiers consist of one cell. For each bit
|
|
- that is set in the cell, the corresponding bit in SCCR will be saved
|
|
- and cleared on suspend, and restored on resume. This sleep controller
|
|
- supports disabling and resuming devices at any time.
|
|
-
|
|
- fsl,mpc8536-pmc: Sleep specifiers consist of three cells, the third of
|
|
- which will be ORed into PMCDR upon suspend, and cleared from PMCDR
|
|
- upon resume. The first two cells are as described for fsl,mpc8578-pmc.
|
|
- This sleep controller only supports disabling devices during system
|
|
- sleep, or permanently.
|
|
-
|
|
- fsl,mpc8548-pmc: Sleep specifiers consist of one or two cells, the
|
|
- first of which will be ORed into DEVDISR (and the second into
|
|
- DEVDISR2, if present -- this cell should be zero or absent if the
|
|
- hardware does not have DEVDISR2) upon a request for permanent device
|
|
- disabling. This sleep controller does not support configuring devices
|
|
- to disable during system sleep (unless supported by another compatible
|
|
- match), or dynamically.
|
|
+Clock nodes:
|
|
+The clock nodes are to describe the masks in PM controller registers for each
|
|
+soc clock.
|
|
+- fsl,pmcdr-mask: For "fsl,mpc8548-pmc"-compatible devices, the mask will be
|
|
+ ORed into PMCDR before suspend if the device using this clock is the wake-up
|
|
+ source and need to be running during low power mode; clear the mask if
|
|
+ otherwise.
|
|
+
|
|
+- fsl,sccr-mask: For "fsl,mpc8349-pmc"-compatible devices, the corresponding
|
|
+ bit specified by the mask in SCCR will be saved and cleared on suspend, and
|
|
+ restored on resume.
|
|
+
|
|
+- fsl,devdisr-mask: Contain one or two cells, depending on the availability of
|
|
+ DEVDISR2 register. For compatible devices, the mask will be ORed into DEVDISR
|
|
+ or DEVDISR2 when the clock should be permenently disabled.
|
|
|
|
Example:
|
|
|
|
- power@b00 {
|
|
- compatible = "fsl,mpc8313-pmc", "fsl,mpc8349-pmc";
|
|
- reg = <0xb00 0x100 0xa00 0x100>;
|
|
- interrupts = <80 8>;
|
|
+ power@e0070 {
|
|
+ compatible = "fsl,mpc8536-pmc", "fsl,mpc8548-pmc";
|
|
+ reg = <0xe0070 0x20>;
|
|
+
|
|
+ etsec1_clk: soc-clk@24 {
|
|
+ fsl,pmcdr-mask = <0x00000080>;
|
|
+ };
|
|
+ etsec2_clk: soc-clk@25 {
|
|
+ fsl,pmcdr-mask = <0x00000040>;
|
|
+ };
|
|
+ etsec3_clk: soc-clk@26 {
|
|
+ fsl,pmcdr-mask = <0x00000020>;
|
|
+ };
|
|
};
|
|
--- a/drivers/cpufreq/Kconfig
|
|
+++ b/drivers/cpufreq/Kconfig
|
|
@@ -334,7 +334,7 @@ endif
|
|
|
|
config QORIQ_CPUFREQ
|
|
tristate "CPU frequency scaling driver for Freescale QorIQ SoCs"
|
|
- depends on OF && COMMON_CLK && (PPC_E500MC || ARM)
|
|
+ depends on OF && COMMON_CLK && (PPC_E500MC || ARM || ARM64)
|
|
depends on !CPU_THERMAL || THERMAL
|
|
select CLK_QORIQ
|
|
help
|
|
--- a/drivers/cpufreq/qoriq-cpufreq.c
|
|
+++ b/drivers/cpufreq/qoriq-cpufreq.c
|
|
@@ -11,6 +11,7 @@
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
|
|
#include <linux/clk.h>
|
|
+#include <linux/clk-provider.h>
|
|
#include <linux/cpufreq.h>
|
|
#include <linux/cpu_cooling.h>
|
|
#include <linux/errno.h>
|
|
@@ -22,10 +23,6 @@
|
|
#include <linux/slab.h>
|
|
#include <linux/smp.h>
|
|
|
|
-#if !defined(CONFIG_ARM)
|
|
-#include <asm/smp.h> /* for get_hard_smp_processor_id() in UP configs */
|
|
-#endif
|
|
-
|
|
/**
|
|
* struct cpu_data
|
|
* @pclk: the parent clock of cpu
|
|
@@ -37,73 +34,51 @@ struct cpu_data {
|
|
struct thermal_cooling_device *cdev;
|
|
};
|
|
|
|
+/*
|
|
+ * Don't use cpufreq on this SoC -- used when the SoC would have otherwise
|
|
+ * matched a more generic compatible.
|
|
+ */
|
|
+#define SOC_BLACKLIST 1
|
|
+
|
|
/**
|
|
* struct soc_data - SoC specific data
|
|
- * @freq_mask: mask the disallowed frequencies
|
|
- * @flag: unique flags
|
|
+ * @flags: SOC_xxx
|
|
*/
|
|
struct soc_data {
|
|
- u32 freq_mask[4];
|
|
- u32 flag;
|
|
-};
|
|
-
|
|
-#define FREQ_MASK 1
|
|
-/* see hardware specification for the allowed frqeuencies */
|
|
-static const struct soc_data sdata[] = {
|
|
- { /* used by p2041 and p3041 */
|
|
- .freq_mask = {0x8, 0x8, 0x2, 0x2},
|
|
- .flag = FREQ_MASK,
|
|
- },
|
|
- { /* used by p5020 */
|
|
- .freq_mask = {0x8, 0x2},
|
|
- .flag = FREQ_MASK,
|
|
- },
|
|
- { /* used by p4080, p5040 */
|
|
- .freq_mask = {0},
|
|
- .flag = 0,
|
|
- },
|
|
+ u32 flags;
|
|
};
|
|
|
|
-/*
|
|
- * the minimum allowed core frequency, in Hz
|
|
- * for chassis v1.0, >= platform frequency
|
|
- * for chassis v2.0, >= platform frequency / 2
|
|
- */
|
|
-static u32 min_cpufreq;
|
|
-static const u32 *fmask;
|
|
-
|
|
-#if defined(CONFIG_ARM)
|
|
-static int get_cpu_physical_id(int cpu)
|
|
-{
|
|
- return topology_core_id(cpu);
|
|
-}
|
|
-#else
|
|
-static int get_cpu_physical_id(int cpu)
|
|
-{
|
|
- return get_hard_smp_processor_id(cpu);
|
|
-}
|
|
-#endif
|
|
-
|
|
static u32 get_bus_freq(void)
|
|
{
|
|
struct device_node *soc;
|
|
u32 sysfreq;
|
|
+ struct clk *pltclk;
|
|
+ int ret;
|
|
|
|
+ /* get platform freq by searching bus-frequency property */
|
|
soc = of_find_node_by_type(NULL, "soc");
|
|
- if (!soc)
|
|
- return 0;
|
|
-
|
|
- if (of_property_read_u32(soc, "bus-frequency", &sysfreq))
|
|
- sysfreq = 0;
|
|
+ if (soc) {
|
|
+ ret = of_property_read_u32(soc, "bus-frequency", &sysfreq);
|
|
+ of_node_put(soc);
|
|
+ if (!ret)
|
|
+ return sysfreq;
|
|
+ }
|
|
|
|
- of_node_put(soc);
|
|
+ /* get platform freq by its clock name */
|
|
+ pltclk = clk_get(NULL, "cg-pll0-div1");
|
|
+ if (IS_ERR(pltclk)) {
|
|
+ pr_err("%s: can't get bus frequency %ld\n",
|
|
+ __func__, PTR_ERR(pltclk));
|
|
+ return PTR_ERR(pltclk);
|
|
+ }
|
|
|
|
- return sysfreq;
|
|
+ return clk_get_rate(pltclk);
|
|
}
|
|
|
|
-static struct device_node *cpu_to_clk_node(int cpu)
|
|
+static struct clk *cpu_to_clk(int cpu)
|
|
{
|
|
- struct device_node *np, *clk_np;
|
|
+ struct device_node *np;
|
|
+ struct clk *clk;
|
|
|
|
if (!cpu_present(cpu))
|
|
return NULL;
|
|
@@ -112,37 +87,28 @@ static struct device_node *cpu_to_clk_no
|
|
if (!np)
|
|
return NULL;
|
|
|
|
- clk_np = of_parse_phandle(np, "clocks", 0);
|
|
- if (!clk_np)
|
|
- return NULL;
|
|
-
|
|
+ clk = of_clk_get(np, 0);
|
|
of_node_put(np);
|
|
-
|
|
- return clk_np;
|
|
+ return clk;
|
|
}
|
|
|
|
/* traverse cpu nodes to get cpu mask of sharing clock wire */
|
|
static void set_affected_cpus(struct cpufreq_policy *policy)
|
|
{
|
|
- struct device_node *np, *clk_np;
|
|
struct cpumask *dstp = policy->cpus;
|
|
+ struct clk *clk;
|
|
int i;
|
|
|
|
- np = cpu_to_clk_node(policy->cpu);
|
|
- if (!np)
|
|
- return;
|
|
-
|
|
for_each_present_cpu(i) {
|
|
- clk_np = cpu_to_clk_node(i);
|
|
- if (!clk_np)
|
|
+ clk = cpu_to_clk(i);
|
|
+ if (IS_ERR(clk)) {
|
|
+ pr_err("%s: no clock for cpu %d\n", __func__, i);
|
|
continue;
|
|
+ }
|
|
|
|
- if (clk_np == np)
|
|
+ if (clk_is_match(policy->clk, clk))
|
|
cpumask_set_cpu(i, dstp);
|
|
-
|
|
- of_node_put(clk_np);
|
|
}
|
|
- of_node_put(np);
|
|
}
|
|
|
|
/* reduce the duplicated frequencies in frequency table */
|
|
@@ -198,10 +164,11 @@ static void freq_table_sort(struct cpufr
|
|
|
|
static int qoriq_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
|
{
|
|
- struct device_node *np, *pnode;
|
|
+ struct device_node *np;
|
|
int i, count, ret;
|
|
- u32 freq, mask;
|
|
+ u32 freq;
|
|
struct clk *clk;
|
|
+ const struct clk_hw *hwclk;
|
|
struct cpufreq_frequency_table *table;
|
|
struct cpu_data *data;
|
|
unsigned int cpu = policy->cpu;
|
|
@@ -221,17 +188,13 @@ static int qoriq_cpufreq_cpu_init(struct
|
|
goto err_nomem2;
|
|
}
|
|
|
|
- pnode = of_parse_phandle(np, "clocks", 0);
|
|
- if (!pnode) {
|
|
- pr_err("%s: could not get clock information\n", __func__);
|
|
- goto err_nomem2;
|
|
- }
|
|
+ hwclk = __clk_get_hw(policy->clk);
|
|
+ count = clk_hw_get_num_parents(hwclk);
|
|
|
|
- count = of_property_count_strings(pnode, "clock-names");
|
|
data->pclk = kcalloc(count, sizeof(struct clk *), GFP_KERNEL);
|
|
if (!data->pclk) {
|
|
pr_err("%s: no memory\n", __func__);
|
|
- goto err_node;
|
|
+ goto err_nomem2;
|
|
}
|
|
|
|
table = kcalloc(count + 1, sizeof(*table), GFP_KERNEL);
|
|
@@ -240,23 +203,11 @@ static int qoriq_cpufreq_cpu_init(struct
|
|
goto err_pclk;
|
|
}
|
|
|
|
- if (fmask)
|
|
- mask = fmask[get_cpu_physical_id(cpu)];
|
|
- else
|
|
- mask = 0x0;
|
|
-
|
|
for (i = 0; i < count; i++) {
|
|
- clk = of_clk_get(pnode, i);
|
|
+ clk = clk_hw_get_parent_by_index(hwclk, i)->clk;
|
|
data->pclk[i] = clk;
|
|
freq = clk_get_rate(clk);
|
|
- /*
|
|
- * the clock is valid if its frequency is not masked
|
|
- * and large than minimum allowed frequency.
|
|
- */
|
|
- if (freq < min_cpufreq || (mask & (1 << i)))
|
|
- table[i].frequency = CPUFREQ_ENTRY_INVALID;
|
|
- else
|
|
- table[i].frequency = freq / 1000;
|
|
+ table[i].frequency = freq / 1000;
|
|
table[i].driver_data = i;
|
|
}
|
|
freq_table_redup(table, count);
|
|
@@ -282,7 +233,6 @@ static int qoriq_cpufreq_cpu_init(struct
|
|
policy->cpuinfo.transition_latency = u64temp + 1;
|
|
|
|
of_node_put(np);
|
|
- of_node_put(pnode);
|
|
|
|
return 0;
|
|
|
|
@@ -290,10 +240,7 @@ err_nomem1:
|
|
kfree(table);
|
|
err_pclk:
|
|
kfree(data->pclk);
|
|
-err_node:
|
|
- of_node_put(pnode);
|
|
err_nomem2:
|
|
- policy->driver_data = NULL;
|
|
kfree(data);
|
|
err_np:
|
|
of_node_put(np);
|
|
@@ -357,12 +304,25 @@ static struct cpufreq_driver qoriq_cpufr
|
|
.attr = cpufreq_generic_attr,
|
|
};
|
|
|
|
+static const struct soc_data blacklist = {
|
|
+ .flags = SOC_BLACKLIST,
|
|
+};
|
|
+
|
|
static const struct of_device_id node_matches[] __initconst = {
|
|
- { .compatible = "fsl,p2041-clockgen", .data = &sdata[0], },
|
|
- { .compatible = "fsl,p3041-clockgen", .data = &sdata[0], },
|
|
- { .compatible = "fsl,p5020-clockgen", .data = &sdata[1], },
|
|
- { .compatible = "fsl,p4080-clockgen", .data = &sdata[2], },
|
|
- { .compatible = "fsl,p5040-clockgen", .data = &sdata[2], },
|
|
+ /* e6500 cannot use cpufreq due to erratum A-008083 */
|
|
+ { .compatible = "fsl,b4420-clockgen", &blacklist },
|
|
+ { .compatible = "fsl,b4860-clockgen", &blacklist },
|
|
+ { .compatible = "fsl,t2080-clockgen", &blacklist },
|
|
+ { .compatible = "fsl,t4240-clockgen", &blacklist },
|
|
+
|
|
+ { .compatible = "fsl,ls1012a-clockgen", },
|
|
+ { .compatible = "fsl,ls1021a-clockgen", },
|
|
+ { .compatible = "fsl,ls1043a-clockgen", },
|
|
+ { .compatible = "fsl,ls1046a-clockgen", },
|
|
+ { .compatible = "fsl,ls1088a-clockgen", },
|
|
+ { .compatible = "fsl,ls2080a-clockgen", },
|
|
+ { .compatible = "fsl,p4080-clockgen", },
|
|
+ { .compatible = "fsl,qoriq-clockgen-1.0", },
|
|
{ .compatible = "fsl,qoriq-clockgen-2.0", },
|
|
{}
|
|
};
|
|
@@ -380,16 +340,12 @@ static int __init qoriq_cpufreq_init(voi
|
|
|
|
match = of_match_node(node_matches, np);
|
|
data = match->data;
|
|
- if (data) {
|
|
- if (data->flag)
|
|
- fmask = data->freq_mask;
|
|
- min_cpufreq = get_bus_freq();
|
|
- } else {
|
|
- min_cpufreq = get_bus_freq() / 2;
|
|
- }
|
|
|
|
of_node_put(np);
|
|
|
|
+ if (data && data->flags & SOC_BLACKLIST)
|
|
+ return -ENODEV;
|
|
+
|
|
ret = cpufreq_register_driver(&qoriq_cpufreq_driver);
|
|
if (!ret)
|
|
pr_info("Freescale QorIQ CPU frequency scaling driver\n");
|
|
--- a/drivers/firmware/psci.c
|
|
+++ b/drivers/firmware/psci.c
|
|
@@ -437,8 +437,12 @@ CPUIDLE_METHOD_OF_DECLARE(psci, "psci",
|
|
|
|
static int psci_system_suspend(unsigned long unused)
|
|
{
|
|
- return invoke_psci_fn(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND),
|
|
- virt_to_phys(cpu_resume), 0, 0);
|
|
+ u32 state;
|
|
+
|
|
+ state = ( 2 << PSCI_0_2_POWER_STATE_AFFL_SHIFT) |
|
|
+ (1 << PSCI_0_2_POWER_STATE_TYPE_SHIFT);
|
|
+
|
|
+ return psci_cpu_suspend(state, virt_to_phys(cpu_resume));
|
|
}
|
|
|
|
static int psci_system_suspend_enter(suspend_state_t state)
|
|
@@ -458,6 +462,8 @@ static void __init psci_init_system_susp
|
|
if (!IS_ENABLED(CONFIG_SUSPEND))
|
|
return;
|
|
|
|
+ suspend_set_ops(&psci_suspend_ops);
|
|
+
|
|
ret = psci_features(PSCI_FN_NATIVE(1_0, SYSTEM_SUSPEND));
|
|
|
|
if (ret != PSCI_RET_NOT_SUPPORTED)
|
|
@@ -562,6 +568,8 @@ static void __init psci_0_2_set_function
|
|
arm_pm_restart = psci_sys_reset;
|
|
|
|
pm_power_off = psci_sys_poweroff;
|
|
+ psci_init_system_suspend();
|
|
+ suspend_set_ops(&psci_suspend_ops);
|
|
}
|
|
|
|
/*
|
|
--- /dev/null
|
|
+++ b/drivers/soc/fsl/rcpm.c
|
|
@@ -0,0 +1,158 @@
|
|
+/*
|
|
+ * Run Control and Power Management (RCPM) driver
|
|
+ *
|
|
+ * Copyright 2016 NXP
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation; either version 2 of the License, or
|
|
+ * (at your option) any later version.
|
|
+ *
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ * GNU General Public License for more details.
|
|
+ *
|
|
+ */
|
|
+#define pr_fmt(fmt) "RCPM: %s: " fmt, __func__
|
|
+
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/io.h>
|
|
+#include <linux/of_platform.h>
|
|
+#include <linux/of_address.h>
|
|
+#include <linux/suspend.h>
|
|
+
|
|
+/* RCPM register offset */
|
|
+#define RCPM_IPPDEXPCR0 0x140
|
|
+
|
|
+#define RCPM_WAKEUP_CELL_SIZE 2
|
|
+
|
|
+struct rcpm_config {
|
|
+ int ipp_num;
|
|
+ int ippdexpcr_offset;
|
|
+ u32 ippdexpcr[2];
|
|
+ void *rcpm_reg_base;
|
|
+};
|
|
+
|
|
+static struct rcpm_config *rcpm;
|
|
+
|
|
+static inline void rcpm_reg_write(u32 offset, u32 value)
|
|
+{
|
|
+ iowrite32be(value, rcpm->rcpm_reg_base + offset);
|
|
+}
|
|
+
|
|
+static inline u32 rcpm_reg_read(u32 offset)
|
|
+{
|
|
+ return ioread32be(rcpm->rcpm_reg_base + offset);
|
|
+}
|
|
+
|
|
+static void rcpm_wakeup_fixup(struct device *dev, void *data)
|
|
+{
|
|
+ struct device_node *node = dev ? dev->of_node : NULL;
|
|
+ u32 value[RCPM_WAKEUP_CELL_SIZE];
|
|
+ int ret, i;
|
|
+
|
|
+ if (!dev || !node || !device_may_wakeup(dev))
|
|
+ return;
|
|
+
|
|
+ /*
|
|
+ * Get the values in the "rcpm-wakeup" property.
|
|
+ * Three values are:
|
|
+ * The first is a pointer to the RCPM node.
|
|
+ * The second is the value of the ippdexpcr0 register.
|
|
+ * The third is the value of the ippdexpcr1 register.
|
|
+ */
|
|
+ ret = of_property_read_u32_array(node, "fsl,rcpm-wakeup",
|
|
+ value, RCPM_WAKEUP_CELL_SIZE);
|
|
+ if (ret)
|
|
+ return;
|
|
+
|
|
+ pr_debug("wakeup source: the device %s\n", node->full_name);
|
|
+
|
|
+ for (i = 0; i < rcpm->ipp_num; i++)
|
|
+ rcpm->ippdexpcr[i] |= value[i + 1];
|
|
+}
|
|
+
|
|
+static int rcpm_suspend_prepare(void)
|
|
+{
|
|
+ int i;
|
|
+ u32 val;
|
|
+
|
|
+ BUG_ON(!rcpm);
|
|
+
|
|
+ for (i = 0; i < rcpm->ipp_num; i++)
|
|
+ rcpm->ippdexpcr[i] = 0;
|
|
+
|
|
+ dpm_for_each_dev(NULL, rcpm_wakeup_fixup);
|
|
+
|
|
+ for (i = 0; i < rcpm->ipp_num; i++) {
|
|
+ if (rcpm->ippdexpcr[i]) {
|
|
+ val = rcpm_reg_read(rcpm->ippdexpcr_offset + 4 * i);
|
|
+ rcpm_reg_write(rcpm->ippdexpcr_offset + 4 * i,
|
|
+ val | rcpm->ippdexpcr[i]);
|
|
+ pr_debug("ippdexpcr%d = 0x%x\n", i, rcpm->ippdexpcr[i]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int rcpm_suspend_notifier_call(struct notifier_block *bl,
|
|
+ unsigned long state,
|
|
+ void *unused)
|
|
+{
|
|
+ switch (state) {
|
|
+ case PM_SUSPEND_PREPARE:
|
|
+ rcpm_suspend_prepare();
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return NOTIFY_DONE;
|
|
+}
|
|
+
|
|
+static struct rcpm_config rcpm_default_config = {
|
|
+ .ipp_num = 1,
|
|
+ .ippdexpcr_offset = RCPM_IPPDEXPCR0,
|
|
+};
|
|
+
|
|
+static const struct of_device_id rcpm_matches[] = {
|
|
+ {
|
|
+ .compatible = "fsl,qoriq-rcpm-2.1",
|
|
+ .data = &rcpm_default_config,
|
|
+ },
|
|
+ {}
|
|
+};
|
|
+
|
|
+static struct notifier_block rcpm_suspend_notifier = {
|
|
+ .notifier_call = rcpm_suspend_notifier_call,
|
|
+};
|
|
+
|
|
+static int __init layerscape_rcpm_init(void)
|
|
+{
|
|
+ const struct of_device_id *match;
|
|
+ struct device_node *np;
|
|
+
|
|
+ np = of_find_matching_node_and_match(NULL, rcpm_matches, &match);
|
|
+ if (!np) {
|
|
+ pr_err("Can't find the RCPM node.\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ if (match->data)
|
|
+ rcpm = (struct rcpm_config *)match->data;
|
|
+ else
|
|
+ return -EINVAL;
|
|
+
|
|
+ rcpm->rcpm_reg_base = of_iomap(np, 0);
|
|
+ of_node_put(np);
|
|
+ if (!rcpm->rcpm_reg_base)
|
|
+ return -ENOMEM;
|
|
+
|
|
+ register_pm_notifier(&rcpm_suspend_notifier);
|
|
+
|
|
+ pr_info("The RCPM driver initialized.\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+subsys_initcall(layerscape_rcpm_init);
|
|
--- /dev/null
|
|
+++ b/drivers/soc/fsl/sleep_fsm.c
|
|
@@ -0,0 +1,279 @@
|
|
+/*
|
|
+ * deep sleep FSM (finite-state machine) configuration
|
|
+ *
|
|
+ * Copyright 2018 NXP
|
|
+ *
|
|
+ * Author: Hongbo Zhang <hongbo.zhang@freescale.com>
|
|
+ * Chenhui Zhao <chenhui.zhao@freescale.com>
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions are met:
|
|
+ * * Redistributions of source code must retain the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer.
|
|
+ * * Redistributions in binary form must reproduce the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer in the
|
|
+ * documentation and/or other materials provided with the distribution.
|
|
+ * * Neither the name of the above-listed copyright holders nor the
|
|
+ * names of any contributors may be used to endorse or promote products
|
|
+ * derived from this software without specific prior written permission.
|
|
+ *
|
|
+ * ALTERNATIVELY, this software may be distributed under the terms of the
|
|
+ * GNU General Public License ("GPL") as published by the Free Software
|
|
+ * Foundation, either version 2 of that License or (at your option) any
|
|
+ * later version.
|
|
+ *
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
|
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
+ * POSSIBILITY OF SUCH DAMAGE.
|
|
+ */
|
|
+
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/io.h>
|
|
+#include <linux/types.h>
|
|
+
|
|
+#include "sleep_fsm.h"
|
|
+/*
|
|
+ * These values are from chip's reference manual. For example,
|
|
+ * the values for T1040 can be found in "8.4.3.8 Programming
|
|
+ * supporting deep sleep mode" of Chapter 8 "Run Control and
|
|
+ * Power Management (RCPM)".
|
|
+ * The default value can be applied to T104x, LS1021.
|
|
+ */
|
|
+struct fsm_reg_vals epu_default_val[] = {
|
|
+ /* EPGCR (Event Processor Global Control Register) */
|
|
+ {EPGCR, 0},
|
|
+ /* EPECR (Event Processor Event Control Registers) */
|
|
+ {EPECR0 + EPECR_STRIDE * 0, 0},
|
|
+ {EPECR0 + EPECR_STRIDE * 1, 0},
|
|
+ {EPECR0 + EPECR_STRIDE * 2, 0xF0004004},
|
|
+ {EPECR0 + EPECR_STRIDE * 3, 0x80000084},
|
|
+ {EPECR0 + EPECR_STRIDE * 4, 0x20000084},
|
|
+ {EPECR0 + EPECR_STRIDE * 5, 0x08000004},
|
|
+ {EPECR0 + EPECR_STRIDE * 6, 0x80000084},
|
|
+ {EPECR0 + EPECR_STRIDE * 7, 0x80000084},
|
|
+ {EPECR0 + EPECR_STRIDE * 8, 0x60000084},
|
|
+ {EPECR0 + EPECR_STRIDE * 9, 0x08000084},
|
|
+ {EPECR0 + EPECR_STRIDE * 10, 0x42000084},
|
|
+ {EPECR0 + EPECR_STRIDE * 11, 0x90000084},
|
|
+ {EPECR0 + EPECR_STRIDE * 12, 0x80000084},
|
|
+ {EPECR0 + EPECR_STRIDE * 13, 0x08000084},
|
|
+ {EPECR0 + EPECR_STRIDE * 14, 0x02000084},
|
|
+ {EPECR0 + EPECR_STRIDE * 15, 0x00000004},
|
|
+ /*
|
|
+ * EPEVTCR (Event Processor EVT Pin Control Registers)
|
|
+ * SCU8 triger EVT2, and SCU11 triger EVT9
|
|
+ */
|
|
+ {EPEVTCR0 + EPEVTCR_STRIDE * 0, 0},
|
|
+ {EPEVTCR0 + EPEVTCR_STRIDE * 1, 0},
|
|
+ {EPEVTCR0 + EPEVTCR_STRIDE * 2, 0x80000001},
|
|
+ {EPEVTCR0 + EPEVTCR_STRIDE * 3, 0},
|
|
+ {EPEVTCR0 + EPEVTCR_STRIDE * 4, 0},
|
|
+ {EPEVTCR0 + EPEVTCR_STRIDE * 5, 0},
|
|
+ {EPEVTCR0 + EPEVTCR_STRIDE * 6, 0},
|
|
+ {EPEVTCR0 + EPEVTCR_STRIDE * 7, 0},
|
|
+ {EPEVTCR0 + EPEVTCR_STRIDE * 8, 0},
|
|
+ {EPEVTCR0 + EPEVTCR_STRIDE * 9, 0xB0000001},
|
|
+ /* EPCMPR (Event Processor Counter Compare Registers) */
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 0, 0},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 1, 0},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 2, 0x000000FF},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 3, 0},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 4, 0x000000FF},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 5, 0x00000020},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 6, 0},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 7, 0},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 8, 0x000000FF},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 9, 0x000000FF},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 10, 0x000000FF},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 11, 0x000000FF},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 12, 0x000000FF},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 13, 0},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 14, 0x000000FF},
|
|
+ {EPCMPR0 + EPCMPR_STRIDE * 15, 0x000000FF},
|
|
+ /* EPCCR (Event Processor Counter Control Registers) */
|
|
+ {EPCCR0 + EPCCR_STRIDE * 0, 0},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 1, 0},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 2, 0x92840000},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 3, 0},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 4, 0x92840000},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 5, 0x92840000},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 6, 0},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 7, 0},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 8, 0x92840000},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 9, 0x92840000},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 10, 0x92840000},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 11, 0x92840000},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 12, 0x92840000},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 13, 0},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 14, 0x92840000},
|
|
+ {EPCCR0 + EPCCR_STRIDE * 15, 0x92840000},
|
|
+ /* EPSMCR (Event Processor SCU Mux Control Registers) */
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 0, 0},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 1, 0},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 2, 0x6C700000},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 3, 0x2F000000},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 4, 0x002F0000},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 5, 0x00002E00},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 6, 0x7C000000},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 7, 0x30000000},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 8, 0x64300000},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 9, 0x00003000},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 10, 0x65000030},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 11, 0x31740000},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 12, 0x7F000000},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 13, 0x00003100},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 14, 0x00000031},
|
|
+ {EPSMCR0 + EPSMCR_STRIDE * 15, 0x76000000},
|
|
+ /* EPACR (Event Processor Action Control Registers) */
|
|
+ {EPACR0 + EPACR_STRIDE * 0, 0},
|
|
+ {EPACR0 + EPACR_STRIDE * 1, 0},
|
|
+ {EPACR0 + EPACR_STRIDE * 2, 0},
|
|
+ {EPACR0 + EPACR_STRIDE * 3, 0x00000080},
|
|
+ {EPACR0 + EPACR_STRIDE * 4, 0},
|
|
+ {EPACR0 + EPACR_STRIDE * 5, 0x00000040},
|
|
+ {EPACR0 + EPACR_STRIDE * 6, 0},
|
|
+ {EPACR0 + EPACR_STRIDE * 7, 0},
|
|
+ {EPACR0 + EPACR_STRIDE * 8, 0},
|
|
+ {EPACR0 + EPACR_STRIDE * 9, 0x0000001C},
|
|
+ {EPACR0 + EPACR_STRIDE * 10, 0x00000020},
|
|
+ {EPACR0 + EPACR_STRIDE * 11, 0},
|
|
+ {EPACR0 + EPACR_STRIDE * 12, 0x00000003},
|
|
+ {EPACR0 + EPACR_STRIDE * 13, 0x06000000},
|
|
+ {EPACR0 + EPACR_STRIDE * 14, 0x04000000},
|
|
+ {EPACR0 + EPACR_STRIDE * 15, 0x02000000},
|
|
+ /* EPIMCR (Event Processor Input Mux Control Registers) */
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 0, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 1, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 2, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 3, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 4, 0x44000000},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 5, 0x40000000},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 6, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 7, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 8, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 9, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 10, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 11, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 12, 0x44000000},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 13, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 14, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 15, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 16, 0x6A000000},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 17, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 18, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 19, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 20, 0x48000000},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 21, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 22, 0x6C000000},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 23, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 24, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 25, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 26, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 27, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 28, 0x76000000},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 29, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 30, 0},
|
|
+ {EPIMCR0 + EPIMCR_STRIDE * 31, 0x76000000},
|
|
+ /* EPXTRIGCR (Event Processor Crosstrigger Control Register) */
|
|
+ {EPXTRIGCR, 0x0000FFDF},
|
|
+ /* end */
|
|
+ {FSM_END_FLAG, 0},
|
|
+};
|
|
+
|
|
+struct fsm_reg_vals npc_default_val[] = {
|
|
+ /* NPC triggered Memory-Mapped Access Registers */
|
|
+ {NCR, 0x80000000},
|
|
+ {MCCR1, 0},
|
|
+ {MCSR1, 0},
|
|
+ {MMAR1LO, 0},
|
|
+ {MMAR1HI, 0},
|
|
+ {MMDR1, 0},
|
|
+ {MCSR2, 0},
|
|
+ {MMAR2LO, 0},
|
|
+ {MMAR2HI, 0},
|
|
+ {MMDR2, 0},
|
|
+ {MCSR3, 0x80000000},
|
|
+ {MMAR3LO, 0x000E2130},
|
|
+ {MMAR3HI, 0x00030000},
|
|
+ {MMDR3, 0x00020000},
|
|
+ /* end */
|
|
+ {FSM_END_FLAG, 0},
|
|
+};
|
|
+
|
|
+/**
|
|
+ * fsl_fsm_setup - Configure EPU's FSM registers
|
|
+ * @base: the base address of registers
|
|
+ * @val: Pointer to address-value pairs for FSM registers
|
|
+ */
|
|
+void fsl_fsm_setup(void __iomem *base, struct fsm_reg_vals *val)
|
|
+{
|
|
+ struct fsm_reg_vals *data = val;
|
|
+
|
|
+ WARN_ON(!base || !data);
|
|
+ while (data->offset != FSM_END_FLAG) {
|
|
+ iowrite32be(data->value, base + data->offset);
|
|
+ data++;
|
|
+ }
|
|
+}
|
|
+
|
|
+void fsl_epu_setup_default(void __iomem *epu_base)
|
|
+{
|
|
+ fsl_fsm_setup(epu_base, epu_default_val);
|
|
+}
|
|
+
|
|
+void fsl_npc_setup_default(void __iomem *npc_base)
|
|
+{
|
|
+ fsl_fsm_setup(npc_base, npc_default_val);
|
|
+}
|
|
+
|
|
+void fsl_epu_clean_default(void __iomem *epu_base)
|
|
+{
|
|
+ u32 offset;
|
|
+
|
|
+ /* follow the exact sequence to clear the registers */
|
|
+ /* Clear EPACRn */
|
|
+ for (offset = EPACR0; offset <= EPACR15; offset += EPACR_STRIDE)
|
|
+ iowrite32be(0, epu_base + offset);
|
|
+
|
|
+ /* Clear EPEVTCRn */
|
|
+ for (offset = EPEVTCR0; offset <= EPEVTCR9; offset += EPEVTCR_STRIDE)
|
|
+ iowrite32be(0, epu_base + offset);
|
|
+
|
|
+ /* Clear EPGCR */
|
|
+ iowrite32be(0, epu_base + EPGCR);
|
|
+
|
|
+ /* Clear EPSMCRn */
|
|
+ for (offset = EPSMCR0; offset <= EPSMCR15; offset += EPSMCR_STRIDE)
|
|
+ iowrite32be(0, epu_base + offset);
|
|
+
|
|
+ /* Clear EPCCRn */
|
|
+ for (offset = EPCCR0; offset <= EPCCR31; offset += EPCCR_STRIDE)
|
|
+ iowrite32be(0, epu_base + offset);
|
|
+
|
|
+ /* Clear EPCMPRn */
|
|
+ for (offset = EPCMPR0; offset <= EPCMPR31; offset += EPCMPR_STRIDE)
|
|
+ iowrite32be(0, epu_base + offset);
|
|
+
|
|
+ /* Clear EPCTRn */
|
|
+ for (offset = EPCTR0; offset <= EPCTR31; offset += EPCTR_STRIDE)
|
|
+ iowrite32be(0, epu_base + offset);
|
|
+
|
|
+ /* Clear EPIMCRn */
|
|
+ for (offset = EPIMCR0; offset <= EPIMCR31; offset += EPIMCR_STRIDE)
|
|
+ iowrite32be(0, epu_base + offset);
|
|
+
|
|
+ /* Clear EPXTRIGCRn */
|
|
+ iowrite32be(0, epu_base + EPXTRIGCR);
|
|
+
|
|
+ /* Clear EPECRn */
|
|
+ for (offset = EPECR0; offset <= EPECR15; offset += EPECR_STRIDE)
|
|
+ iowrite32be(0, epu_base + offset);
|
|
+}
|
|
--- /dev/null
|
|
+++ b/drivers/soc/fsl/sleep_fsm.h
|
|
@@ -0,0 +1,130 @@
|
|
+/*
|
|
+ * deep sleep FSM (finite-state machine) configuration
|
|
+ *
|
|
+ * Copyright 2018 NXP
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions are met:
|
|
+ * * Redistributions of source code must retain the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer.
|
|
+ * * Redistributions in binary form must reproduce the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer in the
|
|
+ * documentation and/or other materials provided with the distribution.
|
|
+ * * Neither the name of the above-listed copyright holders nor the
|
|
+ * names of any contributors may be used to endorse or promote products
|
|
+ * derived from this software without specific prior written permission.
|
|
+ *
|
|
+ *
|
|
+ * ALTERNATIVELY, this software may be distributed under the terms of the
|
|
+ * GNU General Public License ("GPL") as published by the Free Software
|
|
+ * Foundation, either version 2 of that License or (at your option) any
|
|
+ * later version.
|
|
+ *
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
|
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
+ * POSSIBILITY OF SUCH DAMAGE.
|
|
+ */
|
|
+
|
|
+#ifndef _FSL_SLEEP_FSM_H
|
|
+#define _FSL_SLEEP_FSM_H
|
|
+
|
|
+#define FSL_STRIDE_4B 4
|
|
+#define FSL_STRIDE_8B 8
|
|
+
|
|
+/* End flag */
|
|
+#define FSM_END_FLAG 0xFFFFFFFFUL
|
|
+
|
|
+/* Block offsets */
|
|
+#define RCPM_BLOCK_OFFSET 0x00022000
|
|
+#define EPU_BLOCK_OFFSET 0x00000000
|
|
+#define NPC_BLOCK_OFFSET 0x00001000
|
|
+
|
|
+/* EPGCR (Event Processor Global Control Register) */
|
|
+#define EPGCR 0x000
|
|
+
|
|
+/* EPEVTCR0-9 (Event Processor EVT Pin Control Registers) */
|
|
+#define EPEVTCR0 0x050
|
|
+#define EPEVTCR9 0x074
|
|
+#define EPEVTCR_STRIDE FSL_STRIDE_4B
|
|
+
|
|
+/* EPXTRIGCR (Event Processor Crosstrigger Control Register) */
|
|
+#define EPXTRIGCR 0x090
|
|
+
|
|
+/* EPIMCR0-31 (Event Processor Input Mux Control Registers) */
|
|
+#define EPIMCR0 0x100
|
|
+#define EPIMCR31 0x17C
|
|
+#define EPIMCR_STRIDE FSL_STRIDE_4B
|
|
+
|
|
+/* EPSMCR0-15 (Event Processor SCU Mux Control Registers) */
|
|
+#define EPSMCR0 0x200
|
|
+#define EPSMCR15 0x278
|
|
+#define EPSMCR_STRIDE FSL_STRIDE_8B
|
|
+
|
|
+/* EPECR0-15 (Event Processor Event Control Registers) */
|
|
+#define EPECR0 0x300
|
|
+#define EPECR15 0x33C
|
|
+#define EPECR_STRIDE FSL_STRIDE_4B
|
|
+
|
|
+/* EPACR0-15 (Event Processor Action Control Registers) */
|
|
+#define EPACR0 0x400
|
|
+#define EPACR15 0x43C
|
|
+#define EPACR_STRIDE FSL_STRIDE_4B
|
|
+
|
|
+/* EPCCRi0-15 (Event Processor Counter Control Registers) */
|
|
+#define EPCCR0 0x800
|
|
+#define EPCCR15 0x83C
|
|
+#define EPCCR31 0x87C
|
|
+#define EPCCR_STRIDE FSL_STRIDE_4B
|
|
+
|
|
+/* EPCMPR0-15 (Event Processor Counter Compare Registers) */
|
|
+#define EPCMPR0 0x900
|
|
+#define EPCMPR15 0x93C
|
|
+#define EPCMPR31 0x97C
|
|
+#define EPCMPR_STRIDE FSL_STRIDE_4B
|
|
+
|
|
+/* EPCTR0-31 (Event Processor Counter Register) */
|
|
+#define EPCTR0 0xA00
|
|
+#define EPCTR31 0xA7C
|
|
+#define EPCTR_STRIDE FSL_STRIDE_4B
|
|
+
|
|
+/* NPC triggered Memory-Mapped Access Registers */
|
|
+#define NCR 0x000
|
|
+#define MCCR1 0x0CC
|
|
+#define MCSR1 0x0D0
|
|
+#define MMAR1LO 0x0D4
|
|
+#define MMAR1HI 0x0D8
|
|
+#define MMDR1 0x0DC
|
|
+#define MCSR2 0x0E0
|
|
+#define MMAR2LO 0x0E4
|
|
+#define MMAR2HI 0x0E8
|
|
+#define MMDR2 0x0EC
|
|
+#define MCSR3 0x0F0
|
|
+#define MMAR3LO 0x0F4
|
|
+#define MMAR3HI 0x0F8
|
|
+#define MMDR3 0x0FC
|
|
+
|
|
+/* RCPM Core State Action Control Register 0 */
|
|
+#define CSTTACR0 0xB00
|
|
+
|
|
+/* RCPM Core Group 1 Configuration Register 0 */
|
|
+#define CG1CR0 0x31C
|
|
+
|
|
+struct fsm_reg_vals {
|
|
+ u32 offset;
|
|
+ u32 value;
|
|
+};
|
|
+
|
|
+void fsl_fsm_setup(void __iomem *base, struct fsm_reg_vals *val);
|
|
+void fsl_epu_setup_default(void __iomem *epu_base);
|
|
+void fsl_npc_setup_default(void __iomem *npc_base);
|
|
+void fsl_epu_clean_default(void __iomem *epu_base);
|
|
+
|
|
+#endif /* _FSL_SLEEP_FSM_H */
|