Merge tag 'davinci-for-v5.1/soc-part3' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci into arm/late
DaVinci SoC updates for v5.1 (part 3) ------------------------------------- This pull request gets rid of mach-davinci private interrupt controller implmentations (aintc and cp_initc) and moves them to drivers/irqchip. mach/irqs.h usage outside of mach-davinci has been rid of. The driver changes (input and irqchip) have been acked by respective maintainers. * tag 'davinci-for-v5.1/soc-part3' of git://git.kernel.org/pub/scm/linux/kernel/git/nsekhar/linux-davinci: (57 commits) ARM: davinci: remove intc related fields from davinci_soc_info irqchip: davinci-cp-intc: move the driver to drivers/irqchip ARM: davinci: cp-intc: remove redundant comments ARM: davinci: cp-intc: drop GPL license boilerplate ARM: davinci: cp-intc: use readl/writel_relaxed() ARM: davinci: cp-intc: unify error handling ARM: davinci: cp-intc: improve coding style ARM: davinci: cp-intc: request the memory region before remapping it ARM: davinci: cp-intc: use the new-style config structure ARM: davinci: cp-intc: convert all hex numbers to lowercase ARM: davinci: cp-intc: use a common prefix for all symbols ARM: davinci: cp-intc: add the new config structures for da8xx SoCs irqchip: davinci-cp-intc: add a new config structure ARM: davinci: cp-intc: add a wrapper around cp_intc_init() ARM: davinci: cp-intc: remove cp_intc.h irqchip: davinci-aintc: move the driver to drivers/irqchip ARM: davinci: aintc: remove unnecessary includes ARM: davinci: aintc: remove the timer-specific irq_set_handler() ARM: davinci: aintc: request memory region before remapping it ARM: davinci: aintc: unify error handling ... Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
@@ -129,6 +129,16 @@ config BRCMSTB_L2_IRQ
|
||||
select GENERIC_IRQ_CHIP
|
||||
select IRQ_DOMAIN
|
||||
|
||||
config DAVINCI_AINTC
|
||||
bool
|
||||
select GENERIC_IRQ_CHIP
|
||||
select IRQ_DOMAIN
|
||||
|
||||
config DAVINCI_CP_INTC
|
||||
bool
|
||||
select GENERIC_IRQ_CHIP
|
||||
select IRQ_DOMAIN
|
||||
|
||||
config DW_APB_ICTL
|
||||
bool
|
||||
select GENERIC_IRQ_CHIP
|
||||
|
@@ -6,6 +6,8 @@ obj-$(CONFIG_ATH79) += irq-ath79-cpu.o
|
||||
obj-$(CONFIG_ATH79) += irq-ath79-misc.o
|
||||
obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
|
||||
obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2836.o
|
||||
obj-$(CONFIG_DAVINCI_AINTC) += irq-davinci-aintc.o
|
||||
obj-$(CONFIG_DAVINCI_CP_INTC) += irq-davinci-cp-intc.o
|
||||
obj-$(CONFIG_ARCH_EXYNOS) += exynos-combiner.o
|
||||
obj-$(CONFIG_FARADAY_FTINTC010) += irq-ftintc010.o
|
||||
obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o
|
||||
|
163
drivers/irqchip/irq-davinci-aintc.c
Normal file
163
drivers/irqchip/irq-davinci-aintc.c
Normal file
@@ -0,0 +1,163 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
//
|
||||
// Copyright (C) 2006, 2019 Texas Instruments.
|
||||
//
|
||||
// Interrupt handler for DaVinci boards.
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqchip/irq-davinci-aintc.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irqdomain.h>
|
||||
|
||||
#include <asm/exception.h>
|
||||
|
||||
#define DAVINCI_AINTC_FIQ_REG0 0x00
|
||||
#define DAVINCI_AINTC_FIQ_REG1 0x04
|
||||
#define DAVINCI_AINTC_IRQ_REG0 0x08
|
||||
#define DAVINCI_AINTC_IRQ_REG1 0x0c
|
||||
#define DAVINCI_AINTC_IRQ_IRQENTRY 0x14
|
||||
#define DAVINCI_AINTC_IRQ_ENT_REG0 0x18
|
||||
#define DAVINCI_AINTC_IRQ_ENT_REG1 0x1c
|
||||
#define DAVINCI_AINTC_IRQ_INCTL_REG 0x20
|
||||
#define DAVINCI_AINTC_IRQ_EABASE_REG 0x24
|
||||
#define DAVINCI_AINTC_IRQ_INTPRI0_REG 0x30
|
||||
#define DAVINCI_AINTC_IRQ_INTPRI7_REG 0x4c
|
||||
|
||||
static void __iomem *davinci_aintc_base;
|
||||
static struct irq_domain *davinci_aintc_irq_domain;
|
||||
|
||||
static inline void davinci_aintc_writel(unsigned long value, int offset)
|
||||
{
|
||||
writel_relaxed(value, davinci_aintc_base + offset);
|
||||
}
|
||||
|
||||
static inline unsigned long davinci_aintc_readl(int offset)
|
||||
{
|
||||
return readl_relaxed(davinci_aintc_base + offset);
|
||||
}
|
||||
|
||||
static __init void
|
||||
davinci_aintc_setup_gc(void __iomem *base,
|
||||
unsigned int irq_start, unsigned int num)
|
||||
{
|
||||
struct irq_chip_generic *gc;
|
||||
struct irq_chip_type *ct;
|
||||
|
||||
gc = irq_get_domain_generic_chip(davinci_aintc_irq_domain, irq_start);
|
||||
gc->reg_base = base;
|
||||
gc->irq_base = irq_start;
|
||||
|
||||
ct = gc->chip_types;
|
||||
ct->chip.irq_ack = irq_gc_ack_set_bit;
|
||||
ct->chip.irq_mask = irq_gc_mask_clr_bit;
|
||||
ct->chip.irq_unmask = irq_gc_mask_set_bit;
|
||||
|
||||
ct->regs.ack = DAVINCI_AINTC_IRQ_REG0;
|
||||
ct->regs.mask = DAVINCI_AINTC_IRQ_ENT_REG0;
|
||||
irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE,
|
||||
IRQ_NOREQUEST | IRQ_NOPROBE, 0);
|
||||
}
|
||||
|
||||
static asmlinkage void __exception_irq_entry
|
||||
davinci_aintc_handle_irq(struct pt_regs *regs)
|
||||
{
|
||||
int irqnr = davinci_aintc_readl(DAVINCI_AINTC_IRQ_IRQENTRY);
|
||||
|
||||
/*
|
||||
* Use the formula for entry vector index generation from section
|
||||
* 8.3.3 of the manual.
|
||||
*/
|
||||
irqnr >>= 2;
|
||||
irqnr -= 1;
|
||||
|
||||
handle_domain_irq(davinci_aintc_irq_domain, irqnr, regs);
|
||||
}
|
||||
|
||||
/* ARM Interrupt Controller Initialization */
|
||||
void __init davinci_aintc_init(const struct davinci_aintc_config *config)
|
||||
{
|
||||
unsigned int irq_off, reg_off, prio, shift;
|
||||
void __iomem *req;
|
||||
int ret, irq_base;
|
||||
const u8 *prios;
|
||||
|
||||
req = request_mem_region(config->reg.start,
|
||||
resource_size(&config->reg),
|
||||
"davinci-cp-intc");
|
||||
if (!req) {
|
||||
pr_err("%s: register range busy\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
davinci_aintc_base = ioremap(config->reg.start,
|
||||
resource_size(&config->reg));
|
||||
if (!davinci_aintc_base) {
|
||||
pr_err("%s: unable to ioremap register range\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clear all interrupt requests */
|
||||
davinci_aintc_writel(~0x0, DAVINCI_AINTC_FIQ_REG0);
|
||||
davinci_aintc_writel(~0x0, DAVINCI_AINTC_FIQ_REG1);
|
||||
davinci_aintc_writel(~0x0, DAVINCI_AINTC_IRQ_REG0);
|
||||
davinci_aintc_writel(~0x0, DAVINCI_AINTC_IRQ_REG1);
|
||||
|
||||
/* Disable all interrupts */
|
||||
davinci_aintc_writel(0x0, DAVINCI_AINTC_IRQ_ENT_REG0);
|
||||
davinci_aintc_writel(0x0, DAVINCI_AINTC_IRQ_ENT_REG1);
|
||||
|
||||
/* Interrupts disabled immediately, IRQ entry reflects all */
|
||||
davinci_aintc_writel(0x0, DAVINCI_AINTC_IRQ_INCTL_REG);
|
||||
|
||||
/* we don't use the hardware vector table, just its entry addresses */
|
||||
davinci_aintc_writel(0, DAVINCI_AINTC_IRQ_EABASE_REG);
|
||||
|
||||
/* Clear all interrupt requests */
|
||||
davinci_aintc_writel(~0x0, DAVINCI_AINTC_FIQ_REG0);
|
||||
davinci_aintc_writel(~0x0, DAVINCI_AINTC_FIQ_REG1);
|
||||
davinci_aintc_writel(~0x0, DAVINCI_AINTC_IRQ_REG0);
|
||||
davinci_aintc_writel(~0x0, DAVINCI_AINTC_IRQ_REG1);
|
||||
|
||||
prios = config->prios;
|
||||
for (reg_off = DAVINCI_AINTC_IRQ_INTPRI0_REG;
|
||||
reg_off <= DAVINCI_AINTC_IRQ_INTPRI7_REG; reg_off += 4) {
|
||||
for (shift = 0, prio = 0; shift < 32; shift += 4, prios++)
|
||||
prio |= (*prios & 0x07) << shift;
|
||||
davinci_aintc_writel(prio, reg_off);
|
||||
}
|
||||
|
||||
irq_base = irq_alloc_descs(-1, 0, config->num_irqs, 0);
|
||||
if (irq_base < 0) {
|
||||
pr_err("%s: unable to allocate interrupt descriptors: %d\n",
|
||||
__func__, irq_base);
|
||||
return;
|
||||
}
|
||||
|
||||
davinci_aintc_irq_domain = irq_domain_add_legacy(NULL,
|
||||
config->num_irqs, irq_base, 0,
|
||||
&irq_domain_simple_ops, NULL);
|
||||
if (!davinci_aintc_irq_domain) {
|
||||
pr_err("%s: unable to create interrupt domain\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = irq_alloc_domain_generic_chips(davinci_aintc_irq_domain, 32, 1,
|
||||
"AINTC", handle_edge_irq,
|
||||
IRQ_NOREQUEST | IRQ_NOPROBE, 0, 0);
|
||||
if (ret) {
|
||||
pr_err("%s: unable to allocate generic irq chips for domain\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
for (irq_off = 0, reg_off = 0;
|
||||
irq_off < config->num_irqs;
|
||||
irq_off += 32, reg_off += 0x04)
|
||||
davinci_aintc_setup_gc(davinci_aintc_base + reg_off,
|
||||
irq_base + irq_off, 32);
|
||||
|
||||
set_handle_irq(davinci_aintc_handle_irq);
|
||||
}
|
260
drivers/irqchip/irq-davinci-cp-intc.c
Normal file
260
drivers/irqchip/irq-davinci-cp-intc.c
Normal file
@@ -0,0 +1,260 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// Author: Steve Chen <schen@mvista.com>
|
||||
// Copyright (C) 2008-2009, MontaVista Software, Inc. <source@mvista.com>
|
||||
// Author: Bartosz Golaszewski <bgolaszewski@baylibre.com>
|
||||
// Copyright (C) 2019, Texas Instruments
|
||||
//
|
||||
// TI Common Platform Interrupt Controller (cp_intc) driver
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/irqchip/irq-davinci-cp-intc.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
|
||||
#include <asm/exception.h>
|
||||
|
||||
#define DAVINCI_CP_INTC_CTRL 0x04
|
||||
#define DAVINCI_CP_INTC_HOST_CTRL 0x0c
|
||||
#define DAVINCI_CP_INTC_GLOBAL_ENABLE 0x10
|
||||
#define DAVINCI_CP_INTC_SYS_STAT_IDX_CLR 0x24
|
||||
#define DAVINCI_CP_INTC_SYS_ENABLE_IDX_SET 0x28
|
||||
#define DAVINCI_CP_INTC_SYS_ENABLE_IDX_CLR 0x2c
|
||||
#define DAVINCI_CP_INTC_HOST_ENABLE_IDX_SET 0x34
|
||||
#define DAVINCI_CP_INTC_HOST_ENABLE_IDX_CLR 0x38
|
||||
#define DAVINCI_CP_INTC_PRIO_IDX 0x80
|
||||
#define DAVINCI_CP_INTC_SYS_STAT_CLR(n) (0x0280 + (n << 2))
|
||||
#define DAVINCI_CP_INTC_SYS_ENABLE_CLR(n) (0x0380 + (n << 2))
|
||||
#define DAVINCI_CP_INTC_CHAN_MAP(n) (0x0400 + (n << 2))
|
||||
#define DAVINCI_CP_INTC_SYS_POLARITY(n) (0x0d00 + (n << 2))
|
||||
#define DAVINCI_CP_INTC_SYS_TYPE(n) (0x0d80 + (n << 2))
|
||||
#define DAVINCI_CP_INTC_HOST_ENABLE(n) (0x1500 + (n << 2))
|
||||
#define DAVINCI_CP_INTC_PRI_INDX_MASK GENMASK(9, 0)
|
||||
#define DAVINCI_CP_INTC_GPIR_NONE BIT(31)
|
||||
|
||||
static void __iomem *davinci_cp_intc_base;
|
||||
static struct irq_domain *davinci_cp_intc_irq_domain;
|
||||
|
||||
static inline unsigned int davinci_cp_intc_read(unsigned int offset)
|
||||
{
|
||||
return readl_relaxed(davinci_cp_intc_base + offset);
|
||||
}
|
||||
|
||||
static inline void davinci_cp_intc_write(unsigned long value,
|
||||
unsigned int offset)
|
||||
{
|
||||
writel_relaxed(value, davinci_cp_intc_base + offset);
|
||||
}
|
||||
|
||||
static void davinci_cp_intc_ack_irq(struct irq_data *d)
|
||||
{
|
||||
davinci_cp_intc_write(d->hwirq, DAVINCI_CP_INTC_SYS_STAT_IDX_CLR);
|
||||
}
|
||||
|
||||
static void davinci_cp_intc_mask_irq(struct irq_data *d)
|
||||
{
|
||||
/* XXX don't know why we need to disable nIRQ here... */
|
||||
davinci_cp_intc_write(1, DAVINCI_CP_INTC_HOST_ENABLE_IDX_CLR);
|
||||
davinci_cp_intc_write(d->hwirq, DAVINCI_CP_INTC_SYS_ENABLE_IDX_CLR);
|
||||
davinci_cp_intc_write(1, DAVINCI_CP_INTC_HOST_ENABLE_IDX_SET);
|
||||
}
|
||||
|
||||
static void davinci_cp_intc_unmask_irq(struct irq_data *d)
|
||||
{
|
||||
davinci_cp_intc_write(d->hwirq, DAVINCI_CP_INTC_SYS_ENABLE_IDX_SET);
|
||||
}
|
||||
|
||||
static int davinci_cp_intc_set_irq_type(struct irq_data *d,
|
||||
unsigned int flow_type)
|
||||
{
|
||||
unsigned int reg, mask, polarity, type;
|
||||
|
||||
reg = BIT_WORD(d->hwirq);
|
||||
mask = BIT_MASK(d->hwirq);
|
||||
polarity = davinci_cp_intc_read(DAVINCI_CP_INTC_SYS_POLARITY(reg));
|
||||
type = davinci_cp_intc_read(DAVINCI_CP_INTC_SYS_TYPE(reg));
|
||||
|
||||
switch (flow_type) {
|
||||
case IRQ_TYPE_EDGE_RISING:
|
||||
polarity |= mask;
|
||||
type |= mask;
|
||||
break;
|
||||
case IRQ_TYPE_EDGE_FALLING:
|
||||
polarity &= ~mask;
|
||||
type |= mask;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_HIGH:
|
||||
polarity |= mask;
|
||||
type &= ~mask;
|
||||
break;
|
||||
case IRQ_TYPE_LEVEL_LOW:
|
||||
polarity &= ~mask;
|
||||
type &= ~mask;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
davinci_cp_intc_write(polarity, DAVINCI_CP_INTC_SYS_POLARITY(reg));
|
||||
davinci_cp_intc_write(type, DAVINCI_CP_INTC_SYS_TYPE(reg));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip davinci_cp_intc_irq_chip = {
|
||||
.name = "cp_intc",
|
||||
.irq_ack = davinci_cp_intc_ack_irq,
|
||||
.irq_mask = davinci_cp_intc_mask_irq,
|
||||
.irq_unmask = davinci_cp_intc_unmask_irq,
|
||||
.irq_set_type = davinci_cp_intc_set_irq_type,
|
||||
.flags = IRQCHIP_SKIP_SET_WAKE,
|
||||
};
|
||||
|
||||
static asmlinkage void __exception_irq_entry
|
||||
davinci_cp_intc_handle_irq(struct pt_regs *regs)
|
||||
{
|
||||
int gpir, irqnr, none;
|
||||
|
||||
/*
|
||||
* The interrupt number is in first ten bits. The NONE field set to 1
|
||||
* indicates a spurious irq.
|
||||
*/
|
||||
|
||||
gpir = davinci_cp_intc_read(DAVINCI_CP_INTC_PRIO_IDX);
|
||||
irqnr = gpir & DAVINCI_CP_INTC_PRI_INDX_MASK;
|
||||
none = gpir & DAVINCI_CP_INTC_GPIR_NONE;
|
||||
|
||||
if (unlikely(none)) {
|
||||
pr_err_once("%s: spurious irq!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
handle_domain_irq(davinci_cp_intc_irq_domain, irqnr, regs);
|
||||
}
|
||||
|
||||
static int davinci_cp_intc_host_map(struct irq_domain *h, unsigned int virq,
|
||||
irq_hw_number_t hw)
|
||||
{
|
||||
pr_debug("cp_intc_host_map(%d, 0x%lx)\n", virq, hw);
|
||||
|
||||
irq_set_chip(virq, &davinci_cp_intc_irq_chip);
|
||||
irq_set_probe(virq);
|
||||
irq_set_handler(virq, handle_edge_irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct irq_domain_ops davinci_cp_intc_irq_domain_ops = {
|
||||
.map = davinci_cp_intc_host_map,
|
||||
.xlate = irq_domain_xlate_onetwocell,
|
||||
};
|
||||
|
||||
static int __init
|
||||
davinci_cp_intc_do_init(const struct davinci_cp_intc_config *config,
|
||||
struct device_node *node)
|
||||
{
|
||||
unsigned int num_regs = BITS_TO_LONGS(config->num_irqs);
|
||||
int offset, irq_base;
|
||||
void __iomem *req;
|
||||
|
||||
req = request_mem_region(config->reg.start,
|
||||
resource_size(&config->reg),
|
||||
"davinci-cp-intc");
|
||||
if (!req) {
|
||||
pr_err("%s: register range busy\n", __func__);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
davinci_cp_intc_base = ioremap(config->reg.start,
|
||||
resource_size(&config->reg));
|
||||
if (!davinci_cp_intc_base) {
|
||||
pr_err("%s: unable to ioremap register range\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
davinci_cp_intc_write(0, DAVINCI_CP_INTC_GLOBAL_ENABLE);
|
||||
|
||||
/* Disable all host interrupts */
|
||||
davinci_cp_intc_write(0, DAVINCI_CP_INTC_HOST_ENABLE(0));
|
||||
|
||||
/* Disable system interrupts */
|
||||
for (offset = 0; offset < num_regs; offset++)
|
||||
davinci_cp_intc_write(~0,
|
||||
DAVINCI_CP_INTC_SYS_ENABLE_CLR(offset));
|
||||
|
||||
/* Set to normal mode, no nesting, no priority hold */
|
||||
davinci_cp_intc_write(0, DAVINCI_CP_INTC_CTRL);
|
||||
davinci_cp_intc_write(0, DAVINCI_CP_INTC_HOST_CTRL);
|
||||
|
||||
/* Clear system interrupt status */
|
||||
for (offset = 0; offset < num_regs; offset++)
|
||||
davinci_cp_intc_write(~0,
|
||||
DAVINCI_CP_INTC_SYS_STAT_CLR(offset));
|
||||
|
||||
/* Enable nIRQ (what about nFIQ?) */
|
||||
davinci_cp_intc_write(1, DAVINCI_CP_INTC_HOST_ENABLE_IDX_SET);
|
||||
|
||||
/* Default all priorities to channel 7. */
|
||||
num_regs = (config->num_irqs + 3) >> 2; /* 4 channels per register */
|
||||
for (offset = 0; offset < num_regs; offset++)
|
||||
davinci_cp_intc_write(0x07070707,
|
||||
DAVINCI_CP_INTC_CHAN_MAP(offset));
|
||||
|
||||
irq_base = irq_alloc_descs(-1, 0, config->num_irqs, 0);
|
||||
if (irq_base < 0) {
|
||||
pr_err("%s: unable to allocate interrupt descriptors: %d\n",
|
||||
__func__, irq_base);
|
||||
return irq_base;
|
||||
}
|
||||
|
||||
davinci_cp_intc_irq_domain = irq_domain_add_legacy(
|
||||
node, config->num_irqs, irq_base, 0,
|
||||
&davinci_cp_intc_irq_domain_ops, NULL);
|
||||
|
||||
if (!davinci_cp_intc_irq_domain) {
|
||||
pr_err("%s: unable to create an interrupt domain\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
set_handle_irq(davinci_cp_intc_handle_irq);
|
||||
|
||||
/* Enable global interrupt */
|
||||
davinci_cp_intc_write(1, DAVINCI_CP_INTC_GLOBAL_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __init davinci_cp_intc_init(const struct davinci_cp_intc_config *config)
|
||||
{
|
||||
return davinci_cp_intc_do_init(config, NULL);
|
||||
}
|
||||
|
||||
static int __init davinci_cp_intc_of_init(struct device_node *node,
|
||||
struct device_node *parent)
|
||||
{
|
||||
struct davinci_cp_intc_config config = { };
|
||||
int ret;
|
||||
|
||||
ret = of_address_to_resource(node, 0, &config.reg);
|
||||
if (ret) {
|
||||
pr_err("%s: unable to get the register range from device-tree\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "ti,intc-size", &config.num_irqs);
|
||||
if (ret) {
|
||||
pr_err("%s: unable to read the 'ti,intc-size' property\n",
|
||||
__func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return davinci_cp_intc_do_init(&config, node);
|
||||
}
|
||||
IRQCHIP_DECLARE(cp_intc, "ti,cp-intc", davinci_cp_intc_of_init);
|
Reference in New Issue
Block a user