[PATCH RESEND v3 1/3] irqchip: vf610-mscm: add support for MSCM interrupt router
This adds support for Vybrid's interrupt router. On VF6xx models, almost all peripherals can be accessed from either of the two CPU's, from the Cortex-A5 or from the Cortex-M4. The interrupt router routes the peripheral interrupts to the configured CPU. The driver makes use of the irqdomain hierarchy support. The parent is either the ARM GIC or the ARM NVIC interrupt controller depending on which CPU the kernel is executed on. Currently only ARM GIC is supported because the NVIC driver lacks hierarchical irqdomain support as of now. Currently, there is no resource control mechnism implemented to avoid concurrent access of the same peripheral. The user needs to make sure to use device trees which assign the peripherals orthogonally. However, this driver warns the user in case the interrupt is already configured for the other CPU. This provides a poor man's resource controller. Signed-off-by: Stefan Agner --- arch/arm/mach-imx/Kconfig| 1 + drivers/irqchip/Kconfig | 11 +++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-vf610-mscm.c | 186 +++ 4 files changed, 199 insertions(+) create mode 100644 drivers/irqchip/irq-vf610-mscm.c diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index e8627e0..3c5859e 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -631,6 +631,7 @@ config SOC_IMX6SX config SOC_VF610 bool "Vybrid Family VF610 support" + select VF610_MSCM select ARM_GIC select PINCTRL_VF610 select PL310_ERRATA_769419 if CACHE_L2X0 diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index cc79d2a..af5e72a 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -136,6 +136,17 @@ config IRQ_CROSSBAR a free irq and configures the IP. Thus the peripheral interrupts are routed to one of the free irqchip interrupt lines. +config VF610_MSCM + bool + help + Support for MSCM interrupt router available on Vybrid SoC's. The + interrupt router is between the CPU's interrupt controller and the + peripheral. The router allows to route the peripheral interrupts to + one of the two available CPU's on Vybrid VF6xx SoC's (Cortex-A5 or + Cortex-M4). The router will be configured transparently on a IRQ + request. + select IRQ_DOMAIN_HIERARCHY + config KEYSTONE_IRQ tristate "Keystone 2 IRQ controller IP" depends on ARCH_KEYSTONE diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 9516a32..85651be 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o obj-$(CONFIG_XTENSA_MX)+= irq-xtensa-mx.o obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o +obj-$(CONFIG_VF610_MSCM) += irq-vf610-mscm.o obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o diff --git a/drivers/irqchip/irq-vf610-mscm.c b/drivers/irqchip/irq-vf610-mscm.c new file mode 100644 index 000..7a284d5 --- /dev/null +++ b/drivers/irqchip/irq-vf610-mscm.c @@ -0,0 +1,186 @@ +/* + * Copyright 2014 Stefan Agner + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "irqchip.h" + +#define MSCM_CPxNUM0x4 +#define MSCM_IRSPRC(n) (0x880 + 2 * (n)) +#define MSCM_IRSPRC_CPEN_MASK 0x3 + +#define MSCM_IRSPRC_NUM112 + +struct vf610_mscm_chip_data { + void __iomem *mscm_base; + u16 cpu_mask; + u16 saved_irsprc[MSCM_IRSPRC_NUM]; +}; + +static struct vf610_mscm_chip_data *mscm_data; + +static inline void vf610_mscm_save(struct vf610_mscm_chip_data *data) +{ + int i; + + for (i = 0; i < MSCM_IRSPRC_NUM; i++) + data->saved_irsprc[i] = readw_relaxed(data->mscm_base + MSCM_IRSPRC(i)); +} + +static inline void vf610_mscm_restore(struct vf610_mscm_chip_data *data) +{ + int i; + + for (i = 0; i < MSCM_IRSPRC_NUM; i++) + writew_relaxed(data->saved_irsprc[i], data->mscm_base + MSCM_IRSPRC(i)); +} + +static int vf610_mscm_notifier(struct notifier_block *self, unsigned long cmd, + void *v) +{ + switch (cmd) { + case CPU_CLUSTER_PM_ENTER: + vf610_mscm_save(mscm_data); + break; + case CPU_CLUSTER_PM_ENTER_FAILED: + case CPU_CLUSTER_PM_EXIT: +
[PATCH RESEND v3 1/3] irqchip: vf610-mscm: add support for MSCM interrupt router
This adds support for Vybrid's interrupt router. On VF6xx models, almost all peripherals can be accessed from either of the two CPU's, from the Cortex-A5 or from the Cortex-M4. The interrupt router routes the peripheral interrupts to the configured CPU. The driver makes use of the irqdomain hierarchy support. The parent is either the ARM GIC or the ARM NVIC interrupt controller depending on which CPU the kernel is executed on. Currently only ARM GIC is supported because the NVIC driver lacks hierarchical irqdomain support as of now. Currently, there is no resource control mechnism implemented to avoid concurrent access of the same peripheral. The user needs to make sure to use device trees which assign the peripherals orthogonally. However, this driver warns the user in case the interrupt is already configured for the other CPU. This provides a poor man's resource controller. Signed-off-by: Stefan Agner ste...@agner.ch --- arch/arm/mach-imx/Kconfig| 1 + drivers/irqchip/Kconfig | 11 +++ drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-vf610-mscm.c | 186 +++ 4 files changed, 199 insertions(+) create mode 100644 drivers/irqchip/irq-vf610-mscm.c diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index e8627e0..3c5859e 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -631,6 +631,7 @@ config SOC_IMX6SX config SOC_VF610 bool Vybrid Family VF610 support + select VF610_MSCM select ARM_GIC select PINCTRL_VF610 select PL310_ERRATA_769419 if CACHE_L2X0 diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index cc79d2a..af5e72a 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -136,6 +136,17 @@ config IRQ_CROSSBAR a free irq and configures the IP. Thus the peripheral interrupts are routed to one of the free irqchip interrupt lines. +config VF610_MSCM + bool + help + Support for MSCM interrupt router available on Vybrid SoC's. The + interrupt router is between the CPU's interrupt controller and the + peripheral. The router allows to route the peripheral interrupts to + one of the two available CPU's on Vybrid VF6xx SoC's (Cortex-A5 or + Cortex-M4). The router will be configured transparently on a IRQ + request. + select IRQ_DOMAIN_HIERARCHY + config KEYSTONE_IRQ tristate Keystone 2 IRQ controller IP depends on ARCH_KEYSTONE diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 9516a32..85651be 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_TB10X_IRQC) += irq-tb10x.o obj-$(CONFIG_XTENSA) += irq-xtensa-pic.o obj-$(CONFIG_XTENSA_MX)+= irq-xtensa-mx.o obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o +obj-$(CONFIG_VF610_MSCM) += irq-vf610-mscm.o obj-$(CONFIG_BCM7120_L2_IRQ) += irq-bcm7120-l2.o obj-$(CONFIG_BRCMSTB_L2_IRQ) += irq-brcmstb-l2.o obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o diff --git a/drivers/irqchip/irq-vf610-mscm.c b/drivers/irqchip/irq-vf610-mscm.c new file mode 100644 index 000..7a284d5 --- /dev/null +++ b/drivers/irqchip/irq-vf610-mscm.c @@ -0,0 +1,186 @@ +/* + * Copyright 2014 Stefan Agner + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include linux/cpu_pm.h +#include linux/io.h +#include linux/irq.h +#include linux/irqdomain.h +#include dt-bindings/interrupt-controller/arm-gic.h +#include linux/of.h +#include linux/of_address.h +#include linux/slab.h + +#include irqchip.h + +#define MSCM_CPxNUM0x4 +#define MSCM_IRSPRC(n) (0x880 + 2 * (n)) +#define MSCM_IRSPRC_CPEN_MASK 0x3 + +#define MSCM_IRSPRC_NUM112 + +struct vf610_mscm_chip_data { + void __iomem *mscm_base; + u16 cpu_mask; + u16 saved_irsprc[MSCM_IRSPRC_NUM]; +}; + +static struct vf610_mscm_chip_data *mscm_data; + +static inline void vf610_mscm_save(struct vf610_mscm_chip_data *data) +{ + int i; + + for (i = 0; i MSCM_IRSPRC_NUM; i++) + data-saved_irsprc[i] = readw_relaxed(data-mscm_base + MSCM_IRSPRC(i)); +} + +static inline void vf610_mscm_restore(struct vf610_mscm_chip_data *data) +{ + int i; + + for (i = 0; i MSCM_IRSPRC_NUM; i++) + writew_relaxed(data-saved_irsprc[i], data-mscm_base + MSCM_IRSPRC(i)); +} + +static int vf610_mscm_notifier(struct notifier_block *self, unsigned long cmd, + void *v) +{ + switch (cmd) { + case CPU_CLUSTER_PM_ENTER: +