Received: by 2002:a25:ad19:0:0:0:0:0 with SMTP id y25csp2148616ybi; Sun, 28 Jul 2019 03:03:09 -0700 (PDT) X-Google-Smtp-Source: APXvYqwt0Ja5XzgQxYU5QEePHu2vrZX2FgZHIduSE0PgKRw7d4F4KA1ue4WOiE0AThaQclksGD2U X-Received: by 2002:aa7:8804:: with SMTP id c4mr30640879pfo.65.1564308189581; Sun, 28 Jul 2019 03:03:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1564308189; cv=none; d=google.com; s=arc-20160816; b=ATjXv+D+b0VU7sAppAPmIgwJFZmw4Ai21Qgg40SngIY9Yi72F11pKaB060t0kXg7Pe +7i1WbKSeAZCSNHcz8s8jZ5o8FRgJOI7KLURujGt7EjX+yG71I59NbTBXB3l2YBM/qor TmsX6fORagpBEaL35wYKkz3OeGEXfqpPB8jTQBeoQxqC6AAR35jpWfFbU7QshE8RFYNQ LhSOK0yRB+c+HvW13aOa9vEBhXWSdMUEjnubK5qLvauYJANjrxzcRnT5pbTieFv0f7V/ vPTyqyvyQkmsbRqTfq/PAu2BqENRvzxTWN/B67e/I15LFMMvBJyTszfDoQorOgLTR2Dx Hw8g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:organization:user-agent :references:in-reply-to:subject:cc:to:from:message-id:date; bh=C4C7Eg1Z8CoZ5FgFHgPK4Ka2aTGz4XoJs42NNobNR+g=; b=0evA9DF5JVhdrU4ZLFPKl0b5gw0yX9epJOgvw0Q5n426pQ2jwOT0gSuyMIt1UdWjLq yT5/8nxpcEF7VstuLk6sf/l0Mew8PgyGSHE//0tdDMsssqvGDoQ3wlLyzagSXwNvBPKZ nxwWa5L9rsjvMaagZgrdd+g/JTIvWyfNz43dHILC3BTE71JwCfqe6MDHkx9l+2A/zkBi uaBg9vfkvkGBej4H4KQqwH4gHiQeTf+cYRveYPc+6SLA4rp9ysaYxcA+7dPkgYY/Nx6z PeE9KM4x9cYrlN9zgi8as9G+BnFM5bD7Krg79Rt6zXZOC/SDp9TbATafinklW61c1t/U 629A== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o33si107439pgb.381.2019.07.28.03.02.54; Sun, 28 Jul 2019 03:03:09 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726099AbfG1KBo (ORCPT + 99 others); Sun, 28 Jul 2019 06:01:44 -0400 Received: from foss.arm.com ([217.140.110.172]:59922 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725961AbfG1KBo (ORCPT ); Sun, 28 Jul 2019 06:01:44 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 99B98337; Sun, 28 Jul 2019 03:01:42 -0700 (PDT) Received: from big-swifty.misterjones.org (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1C5193F694; Sun, 28 Jul 2019 03:01:38 -0700 (PDT) Date: Sun, 28 Jul 2019 11:01:38 +0100 Message-ID: <86y30imq9p.wl-marc.zyngier@arm.com> From: Marc Zyngier To: Martin Blumenstingl Cc: tglx@linutronix.de, jason@lakedaemon.net, ralf@linux-mips.org, paul.burton@mips.com, jhogan@kernel.org, robh+dt@kernel.org, linux-mips@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, mark.rutland@arm.com, john@phrozen.org, hauke@hauke-m.de Subject: Re: [PATCH 3/5] MIPS: lantiq: add an irq_domain and irq_chip for EBU In-Reply-To: <20190727175315.28834-4-martin.blumenstingl@googlemail.com> References: <20190727175315.28834-1-martin.blumenstingl@googlemail.com> <20190727175315.28834-4-martin.blumenstingl@googlemail.com> User-Agent: Wanderlust/2.15.9 (Almost Unreal) SEMI-EPG/1.14.7 (Harue) FLIM/1.14.9 (=?UTF-8?B?R29qxY0=?=) APEL/10.8 EasyPG/1.0.0 Emacs/26 (aarch64-unknown-linux-gnu) MULE/6.0 (HANACHIRUSATO) Organization: ARM Ltd MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Content-Type: text/plain; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi Martin, On Sat, 27 Jul 2019 18:53:13 +0100, Martin Blumenstingl wrote: > > The PCI_INTA on Lantiq SoCs is a chained interrupt: > EBU configures the interrupt type, has a registers to enable/disable > and ACK the interrupt. This is chained with the ICU interrupt where the > parent interrupt of the EBU IRQ has to be ACK'ed. > > Move all EBU interrupt logic into ebu.c and expose it using an > irq_domain and irq_chip. > Drop the hardcoded EBU interrupt configuration from pci-lantiq.c as this > can now be expressed in device tree by passing the EBU interrupt line to > PCI_INTA (using for example "... &ebu0 0 IRQ_TYPE_LEVEL_LOW"). > Also drop the EBU interrupt masking from irq.c because that's now > managed by EBU's own irq_ack callback. > > Signed-off-by: Martin Blumenstingl > --- > .../include/asm/mach-lantiq/xway/lantiq_soc.h | 3 - > arch/mips/lantiq/ebu.c | 149 ++++++++++++++++++ > arch/mips/lantiq/irq.c | 11 -- > arch/mips/pci/pci-lantiq.c | 4 - > 4 files changed, 149 insertions(+), 18 deletions(-) > > diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h > index 02a64ad6c0cc..5555deb02397 100644 > --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h > +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h > @@ -79,9 +79,6 @@ extern __iomem void *ltq_cgu_membase; > #define LTQ_EARLY_ASC KSEG1ADDR(LTQ_ASC1_BASE_ADDR) > > /* EBU - external bus unit */ > -#define LTQ_EBU_PCC_CON 0x0090 > -#define LTQ_EBU_PCC_IEN 0x00A4 > -#define LTQ_EBU_PCC_ISTAT 0x00A0 > #define LTQ_EBU_BUSCON1 0x0064 > #define LTQ_EBU_ADDRSEL1 0x0024 > > diff --git a/arch/mips/lantiq/ebu.c b/arch/mips/lantiq/ebu.c > index b2e84cf83f91..12951eb3c88f 100644 > --- a/arch/mips/lantiq/ebu.c > +++ b/arch/mips/lantiq/ebu.c > @@ -7,7 +7,11 @@ > #include > #include > #include > +#include > +#include > +#include > #include > +#include > #include > #include > > @@ -15,6 +19,19 @@ > > #define LTQ_EBU_BUSCON0 0x0060 > #define LTQ_EBU_BUSCON_WRDIS BIT(31) > +#define LTQ_EBU_PCC_CON 0x0090 > +#define LTQ_EBU_PCC_CON_PCCARD_ON BIT(0) > +#define LTQ_EBU_PCC_CON_IREQ_RISING_EDGE 0x2 > +#define LTQ_EBU_PCC_CON_IREQ_FALLING_EDGE 0x4 > +#define LTQ_EBU_PCC_CON_IREQ_BOTH_EDGE 0x6 So BOTH_EDGE is actually (RISING_EDGE | FALLING_EDGE). It'd be nice to express it this way. > +#define LTQ_EBU_PCC_CON_IREQ_DIS 0x8 What does "DIS" mean? > +#define LTQ_EBU_PCC_CON_IREQ_HIGH_LEVEL_DETECT 0xa > +#define LTQ_EBU_PCC_CON_IREQ_LOW_LEVEL_DETECT 0xc Again, these two are (DIS | RISING) and (DIS | FALLING). > +#define LTQ_EBU_PCC_CON_IREQ_MASK 0xe > +#define LTQ_EBU_PCC_ISTAT 0x00a0 > +#define LTQ_EBU_PCC_ISTAT_PCI BIT(4) > +#define LTQ_EBU_PCC_IEN 0x00a4 > +#define LTQ_EBU_PCC_IEN_PCI_EN BIT(4) > > void __iomem *ltq_ebu_membase; > > @@ -52,6 +69,131 @@ static const struct of_device_id of_ebu_ids[] __initconst = { > { /* sentinel */ }, > }; > > +static void ltq_ebu_ack_irq(struct irq_data *d) > +{ > + ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | LTQ_EBU_PCC_ISTAT_PCI, > + LTQ_EBU_PCC_ISTAT); > +} > + > +static void ltq_ebu_mask_irq(struct irq_data *d) > +{ > + ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) & ~LTQ_EBU_PCC_IEN_PCI_EN, > + LTQ_EBU_PCC_IEN); > +} > + > +static void ltq_ebu_unmask_irq(struct irq_data *d) > +{ > + ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | LTQ_EBU_PCC_IEN_PCI_EN, > + LTQ_EBU_PCC_IEN); > +} > + > +static int ltq_ebu_set_irq_type(struct irq_data *d, unsigned int flow_type) > +{ > + u32 val = ltq_ebu_r32(LTQ_EBU_PCC_CON); > + > + val &= ~LTQ_EBU_PCC_CON_IREQ_MASK; > + > + switch (flow_type & IRQ_TYPE_SENSE_MASK) { > + case IRQ_TYPE_NONE: > + val |= LTQ_EBU_PCC_CON_IREQ_DIS; > + break; I'm not sure IRQ_TYPE_NONE makes much sense here. What's the expected semantic? > + > + case IRQ_TYPE_EDGE_RISING: > + val |= LTQ_EBU_PCC_CON_IREQ_RISING_EDGE; > + break; > + > + case IRQ_TYPE_EDGE_FALLING: > + val |= LTQ_EBU_PCC_CON_IREQ_FALLING_EDGE; > + break; > + > + case IRQ_TYPE_EDGE_BOTH: > + val |= LTQ_EBU_PCC_CON_IREQ_BOTH_EDGE; > + break; > + > + case IRQ_TYPE_LEVEL_HIGH: > + val |= LTQ_EBU_PCC_CON_IREQ_HIGH_LEVEL_DETECT; > + break; > + > + case IRQ_TYPE_LEVEL_LOW: > + val |= LTQ_EBU_PCC_CON_IREQ_LOW_LEVEL_DETECT; > + break; > + > + default: > + pr_err("Invalid trigger mode %x for IRQ %d\n", flow_type, > + d->irq); irq_set_type will already complain in the kernel log, no need to add an extra message. > + return -EINVAL; > + } > + > + ltq_ebu_w32(val, LTQ_EBU_PCC_CON); > + > + return 0; > +} > + > +static void ltq_ebu_irq_handler(struct irq_desc *desc) > +{ > + struct irq_domain *domain = irq_desc_get_handler_data(desc); > + struct irq_chip *irqchip = irq_desc_get_chip(desc); > + > + chained_irq_enter(irqchip, desc); > + > + generic_handle_irq(irq_find_mapping(domain, 0)); Having an irqdomain for a single interrupt is a bit over the top... Is that for the convenience of the DT infrastructure? > + > + chained_irq_exit(irqchip, desc); > +} > + > +static struct irq_chip ltq_ebu_irq_chip = { > + .name = "EBU", > + .irq_ack = ltq_ebu_ack_irq, > + .irq_mask = ltq_ebu_mask_irq, > + .irq_unmask = ltq_ebu_unmask_irq, > + .irq_set_type = ltq_ebu_set_irq_type, > +}; > + > +static int ltq_ebu_irq_map(struct irq_domain *domain, unsigned int irq, > + irq_hw_number_t hwirq) > +{ > + irq_set_chip_and_handler(irq, <q_ebu_irq_chip, handle_edge_irq); > + irq_set_chip_data(irq, domain->host_data); > + > + return 0; > +} > + > +static const struct irq_domain_ops ltq_ebu_irqdomain_ops = { > + .map = ltq_ebu_irq_map, > + .xlate = irq_domain_xlate_twocell, > +}; > + > +static int ltq_ebu_add_irqchip(struct device_node *np) > +{ > + struct irq_domain *parent_domain, *domain; > + int irq; > + > + parent_domain = irq_find_host(of_irq_find_parent(np)); > + if (!parent_domain) { > + pr_err("%pOF: No interrupt-parent found\n", np); > + return -EINVAL; > + } > + > + domain = irq_domain_add_linear(np, 1, <q_ebu_irqdomain_ops, NULL); > + if (!domain) { > + pr_err("%pOF: Could not register EBU IRQ domain\n", np); > + return -ENOMEM; > + } > + > + irq = irq_of_parse_and_map(np, 0); > + if (!irq) { > + pr_err("%pOF: Failed to map interrupt\n", np); > + irq_domain_remove(domain); > + return -EINVAL; > + } > + > + irq_create_mapping(domain, 0); Why do you need to perform this eagerly? I'd expect this interrupt to be mapped when it is actually claimed by a driver. > + > + irq_set_chained_handler_and_data(irq, ltq_ebu_irq_handler, domain); And there is no HW initialisation whatsoever? I'd expect, at the very least, the sole interrupt to be configured as disabled/masked. > + > + return 0; > +} > + > static int __init ltq_ebu_setup(void) > { > const struct ltq_ebu_data *ebu_data; > @@ -59,6 +201,7 @@ static int __init ltq_ebu_setup(void) > struct resource res_ebu; > struct device_node *np; > u32 val; > + int ret; > > np = of_find_matching_node_and_match(NULL, of_ebu_ids, &match); > if (!np) > @@ -83,6 +226,12 @@ static int __init ltq_ebu_setup(void) > ltq_ebu_w32(val, LTQ_EBU_BUSCON0); > } > > + if (of_property_read_bool(np, "interrupt-controller")) { > + ret = ltq_ebu_add_irqchip(np); > + if (ret) > + return ret; > + } > + > return 0; > } > > diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c > index 115b417dfb8e..cb9ab51fa748 100644 > --- a/arch/mips/lantiq/irq.c > +++ b/arch/mips/lantiq/irq.c > @@ -40,12 +40,6 @@ > /* the performance counter */ > #define LTQ_PERF_IRQ (INT_NUM_IM4_IRL0 + 31) > > -/* > - * irqs generated by devices attached to the EBU need to be acked in > - * a special manner > - */ > -#define LTQ_ICU_EBU_IRQ 22 > - > #define ltq_icu_w32(vpe, m, x, y) \ > ltq_w32((x), ltq_icu_membase[vpe] + m*LTQ_ICU_IM_SIZE + (y)) > > @@ -300,11 +294,6 @@ static void ltq_hw_irq_handler(struct irq_desc *desc) > irq = __fls(irq); > hwirq = irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module); > generic_handle_irq(irq_linear_revmap(ltq_domain, hwirq)); > - > - /* if this is a EBU irq, we need to ack it or get a deadlock */ > - if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT) > - ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10, > - LTQ_EBU_PCC_ISTAT); > } > > static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) > diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c > index 1ca42f482130..a3f6ab94ee2c 100644 > --- a/arch/mips/pci/pci-lantiq.c > +++ b/arch/mips/pci/pci-lantiq.c > @@ -190,10 +190,6 @@ static int ltq_pci_startup(struct platform_device *pdev) > ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_MOD) | (1 << 24), PCI_CR_PCI_MOD); > wmb(); > > - /* setup irq line */ > - ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_CON) | 0xc, LTQ_EBU_PCC_CON); > - ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN); > - > /* toggle reset pin */ > if (gpio_is_valid(reset_gpio)) { > __gpio_set_value(reset_gpio, 0); > -- > 2.22.0 > Thanks, M. -- Jazz is not dead, it just smells funny.