summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2016-07-06 06:58:46 +0300
committerOlof Johansson <olof@lixom.net>2016-07-06 06:58:46 +0300
commit213ae9025d2861c1b8293541959e7f5f83be91a3 (patch)
tree0135ba6a01378a8c869c39b2a7af4b310b2ab3b1
parente2bd0d37bd8ec169f7e0ee9d8acd75ecdd16dfdc (diff)
parent18245c24259acaea4584464bf0215bf413dc7d23 (diff)
downloadlinux-213ae9025d2861c1b8293541959e7f5f83be91a3.tar.xz
Merge tag 'imx-soc-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into next/soc
The i.MX SoC changes for 4.8: - A patch series including both cpuidle and FEC driver changes to disable deeper idle states when FEC is active while board level workaround for ERR006687 is not available - A number patches to fix sparse warnings and spell errors - A fix for TZIC FIQ translation from VIRQ to HWIRQ - Support compatible of i.MX7 Solo SoC which has a subset of i.MX7 Dual * tag 'imx-soc-4.8' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux: ARM: imx: add support for i.MX 7Solo ARM: i.MX: Disable supervisor protect for i.MX51 ARM: imx6: fix missing <soc/imx/cpuidle.h> in cpuidle-imx6q.c ARM: i.MX: Fix FIQ interrupt handling for TZIC ARM: imx6: fix static declaration in include/soc/imx/cpuidle.h ARM: imx6q: export cpuidle functions needed by fec driver ARM: imx: fix missing include of common.h ARM: imx: fix missing includes ARM: imx6: disable deeper idle states when FEC is active w/o HW workaround ARM: mach-imx6q: fix spelling mistake in error message Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--Documentation/devicetree/bindings/net/fsl-fec.txt3
-rw-r--r--arch/arm/mach-imx/avic.c19
-rw-r--r--arch/arm/mach-imx/cpuidle-imx6q.c20
-rw-r--r--arch/arm/mach-imx/devices/devices.c3
-rw-r--r--arch/arm/mach-imx/devices/platform-gpio-mxc.c1
-rw-r--r--arch/arm/mach-imx/irq-common.c6
-rw-r--r--arch/arm/mach-imx/mach-imx51.c2
-rw-r--r--arch/arm/mach-imx/mach-imx6q.c2
-rw-r--r--arch/arm/mach-imx/mach-imx7d.c1
-rw-r--r--arch/arm/mach-imx/tzic.c6
-rw-r--r--drivers/net/ethernet/freescale/fec.h2
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c12
-rw-r--r--include/soc/imx/cpuidle.h25
13 files changed, 85 insertions, 17 deletions
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
index b037a9d78d93..a1e3693cca16 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -27,6 +27,9 @@ Optional properties:
number to 1.
- fsl,magic-packet : If present, indicates that the hardware supports waking
up via magic packet.
+- fsl,err006687-workaround-present: If present indicates that the system has
+ the hardware workaround for ERR006687 applied and does not need a software
+ workaround.
Optional subnodes:
- mdio : specifies the mdio bus in the FEC, used as a container for phy nodes
diff --git a/arch/arm/mach-imx/avic.c b/arch/arm/mach-imx/avic.c
index 7fa176e792bd..1afccae0420c 100644
--- a/arch/arm/mach-imx/avic.c
+++ b/arch/arm/mach-imx/avic.c
@@ -55,23 +55,20 @@ static void __iomem *avic_base;
static struct irq_domain *domain;
#ifdef CONFIG_FIQ
-static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
+static int avic_set_irq_fiq(unsigned int hwirq, unsigned int type)
{
- struct irq_data *d = irq_get_irq_data(irq);
unsigned int irqt;
- irq = d->hwirq;
-
- if (irq >= AVIC_NUM_IRQS)
+ if (hwirq >= AVIC_NUM_IRQS)
return -EINVAL;
- if (irq < AVIC_NUM_IRQS / 2) {
- irqt = imx_readl(avic_base + AVIC_INTTYPEL) & ~(1 << irq);
- imx_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEL);
+ if (hwirq < AVIC_NUM_IRQS / 2) {
+ irqt = imx_readl(avic_base + AVIC_INTTYPEL) & ~(1 << hwirq);
+ imx_writel(irqt | (!!type << hwirq), avic_base + AVIC_INTTYPEL);
} else {
- irq -= AVIC_NUM_IRQS / 2;
- irqt = imx_readl(avic_base + AVIC_INTTYPEH) & ~(1 << irq);
- imx_writel(irqt | (!!type << irq), avic_base + AVIC_INTTYPEH);
+ hwirq -= AVIC_NUM_IRQS / 2;
+ irqt = imx_readl(avic_base + AVIC_INTTYPEH) & ~(1 << hwirq);
+ imx_writel(irqt | (!!type << hwirq), avic_base + AVIC_INTTYPEH);
}
return 0;
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
index 353bb8774112..db0f48c4b17e 100644
--- a/arch/arm/mach-imx/cpuidle-imx6q.c
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -10,6 +10,8 @@
#include <linux/module.h>
#include <asm/cpuidle.h>
+#include <soc/imx/cpuidle.h>
+
#include "common.h"
#include "cpuidle.h"
#include "hardware.h"
@@ -62,6 +64,24 @@ static struct cpuidle_driver imx6q_cpuidle_driver = {
.safe_state_index = 0,
};
+/*
+ * i.MX6 Q/DL has an erratum (ERR006687) that prevents the FEC from waking the
+ * CPUs when they are in wait(unclocked) state. As the hardware workaround isn't
+ * applicable to all boards, disable the deeper idle state when the workaround
+ * isn't present and the FEC is in use.
+ */
+void imx6q_cpuidle_fec_irqs_used(void)
+{
+ imx6q_cpuidle_driver.states[1].disabled = true;
+}
+EXPORT_SYMBOL_GPL(imx6q_cpuidle_fec_irqs_used);
+
+void imx6q_cpuidle_fec_irqs_unused(void)
+{
+ imx6q_cpuidle_driver.states[1].disabled = false;
+}
+EXPORT_SYMBOL_GPL(imx6q_cpuidle_fec_irqs_unused);
+
int __init imx6q_cpuidle_init(void)
{
/* Set INT_MEM_CLK_LPM bit to get a reliable WAIT mode support */
diff --git a/arch/arm/mach-imx/devices/devices.c b/arch/arm/mach-imx/devices/devices.c
index 8eab5440da28..300451727362 100644
--- a/arch/arm/mach-imx/devices/devices.c
+++ b/arch/arm/mach-imx/devices/devices.c
@@ -22,6 +22,9 @@
#include <linux/err.h>
#include <linux/platform_device.h>
+#include "../common.h"
+#include "devices-common.h"
+
struct device mxc_aips_bus = {
.init_name = "mxc_aips",
};
diff --git a/arch/arm/mach-imx/devices/platform-gpio-mxc.c b/arch/arm/mach-imx/devices/platform-gpio-mxc.c
index 26483fa94b75..cd1fe69d8807 100644
--- a/arch/arm/mach-imx/devices/platform-gpio-mxc.c
+++ b/arch/arm/mach-imx/devices/platform-gpio-mxc.c
@@ -7,6 +7,7 @@
* Free Software Foundation.
*/
#include "devices-common.h"
+#include "../common.h"
struct platform_device *__init mxc_register_gpio(char *name, int id,
resource_size_t iobase, resource_size_t iosize, int irq, int irq_high)
diff --git a/arch/arm/mach-imx/irq-common.c b/arch/arm/mach-imx/irq-common.c
index 0a920d184867..210d36eba8f2 100644
--- a/arch/arm/mach-imx/irq-common.c
+++ b/arch/arm/mach-imx/irq-common.c
@@ -33,8 +33,10 @@ int mxc_set_irq_fiq(unsigned int irq, unsigned int type)
gc = irq_get_chip_data(irq);
if (gc && gc->private) {
exirq = gc->private;
- if (exirq->set_irq_fiq)
- ret = exirq->set_irq_fiq(irq, type);
+ if (exirq->set_irq_fiq) {
+ struct irq_data *d = irq_get_irq_data(irq);
+ ret = exirq->set_irq_fiq(irqd_to_hwirq(d), type);
+ }
}
return ret;
diff --git a/arch/arm/mach-imx/mach-imx51.c b/arch/arm/mach-imx/mach-imx51.c
index 10a82a4f1e58..1e91740ac7ae 100644
--- a/arch/arm/mach-imx/mach-imx51.c
+++ b/arch/arm/mach-imx/mach-imx51.c
@@ -54,6 +54,8 @@ static void __init imx51_dt_init(void)
imx_src_init();
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+
+ imx_aips_allow_unprivileged_access("fsl,imx51-aipstz");
}
static void __init imx51_init_late(void)
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index cb27d566d5ab..867121d842f7 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -220,7 +220,7 @@ static void __init imx6q_1588_init(void)
IMX6Q_GPR1_ENET_CLK_SEL_MASK,
clksel);
else
- pr_err("failed to find fsl,imx6q-iomux-gpr regmap\n");
+ pr_err("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
clk_put(enet_ref);
put_ptp_clk:
diff --git a/arch/arm/mach-imx/mach-imx7d.c b/arch/arm/mach-imx/mach-imx7d.c
index b450f525a670..36254a621e45 100644
--- a/arch/arm/mach-imx/mach-imx7d.c
+++ b/arch/arm/mach-imx/mach-imx7d.c
@@ -107,6 +107,7 @@ static void __init imx7d_init_irq(void)
static const char *const imx7d_dt_compat[] __initconst = {
"fsl,imx7d",
+ "fsl,imx7s",
NULL,
};
diff --git a/arch/arm/mach-imx/tzic.c b/arch/arm/mach-imx/tzic.c
index ae23d50f7861..4399abd0f11f 100644
--- a/arch/arm/mach-imx/tzic.c
+++ b/arch/arm/mach-imx/tzic.c
@@ -56,14 +56,14 @@ static struct irq_domain *domain;
#define TZIC_NUM_IRQS 128
#ifdef CONFIG_FIQ
-static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
+static int tzic_set_irq_fiq(unsigned int hwirq, unsigned int type)
{
unsigned int index, mask, value;
- index = irq >> 5;
+ index = hwirq >> 5;
if (unlikely(index >= 4))
return -EINVAL;
- mask = 1U << (irq & 0x1F);
+ mask = 1U << (hwirq & 0x1F);
value = imx_readl(tzic_base + TZIC_INTSEC0(index)) | mask;
if (type)
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index f58f9ea51639..dc71a88e9c55 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -442,6 +442,8 @@ struct bufdesc_ex {
#define FEC_QUIRK_SINGLE_MDIO (1 << 11)
/* Controller supports RACC register */
#define FEC_QUIRK_HAS_RACC (1 << 12)
+/* Interrupt doesn't wake CPU from deep idle */
+#define FEC_QUIRK_ERR006687 (1 << 13)
struct bufdesc_prop {
int qid;
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index fea0f330ddbd..d9ecc30ebc8b 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -60,6 +60,7 @@
#include <linux/if_vlan.h>
#include <linux/pinctrl/consumer.h>
#include <linux/prefetch.h>
+#include <soc/imx/cpuidle.h>
#include <asm/cacheflush.h>
@@ -2818,6 +2819,9 @@ fec_enet_open(struct net_device *ndev)
if (ret)
goto err_enet_mii_probe;
+ if (fep->quirks & FEC_QUIRK_ERR006687)
+ imx6q_cpuidle_fec_irqs_used();
+
napi_enable(&fep->napi);
phy_start(ndev->phydev);
netif_tx_start_all_queues(ndev);
@@ -2853,6 +2857,9 @@ fec_enet_close(struct net_device *ndev)
phy_disconnect(ndev->phydev);
+ if (fep->quirks & FEC_QUIRK_ERR006687)
+ imx6q_cpuidle_fec_irqs_unused();
+
fec_enet_clk_enable(ndev, false);
pinctrl_pm_select_sleep_state(&fep->pdev->dev);
pm_runtime_mark_last_busy(&fep->pdev->dev);
@@ -3292,6 +3299,11 @@ fec_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, ndev);
+ if ((of_machine_is_compatible("fsl,imx6q") ||
+ of_machine_is_compatible("fsl,imx6dl")) &&
+ !of_property_read_bool(np, "fsl,err006687-workaround-present"))
+ fep->quirks |= FEC_QUIRK_ERR006687;
+
if (of_get_property(np, "fsl,magic-packet", NULL))
fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET;
diff --git a/include/soc/imx/cpuidle.h b/include/soc/imx/cpuidle.h
new file mode 100644
index 000000000000..8e7743d3b34d
--- /dev/null
+++ b/include/soc/imx/cpuidle.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 Pengutronix, <kernel@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+
+#ifndef __SOC_IMX_CPUIDLE_H__
+#define __SOC_IMX_CPUIDLE_H__
+
+#if defined(CONFIG_CPU_IDLE) && defined(CONFIG_SOC_IMX6Q)
+void imx6q_cpuidle_fec_irqs_used(void);
+void imx6q_cpuidle_fec_irqs_unused(void);
+#else
+static inline void imx6q_cpuidle_fec_irqs_used(void) { }
+static inline void imx6q_cpuidle_fec_irqs_unused(void) { }
+#endif
+
+#endif /* __SOC_IMX_CPUIDLE_H__ */