From: Gabor Juhos <juhosg@openwrt.org>
To: John Crispin <blogic@openwrt.org>
Cc: Ralf Baechle <ralf@linux-mips.org>, linux-mips@linux-mips.org
Subject: Re: [RFC 03/11] MIPS: ralink: adds irq code
Date: Thu, 24 Jan 2013 11:44:23 +0100 [thread overview]
Message-ID: <51011087.60709@openwrt.org> (raw)
In-Reply-To: <1358942755-25371-4-git-send-email-blogic@openwrt.org>
Hi John,
> All of the Ralink Wifi SoC currently supported by this series share the same
> interrupt controller (INTC).
>
> Signed-off-by: John Crispin <blogic@openwrt.org>
> ---
> arch/mips/ralink/irq.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 182 insertions(+)
> create mode 100644 arch/mips/ralink/irq.c
>
> diff --git a/arch/mips/ralink/irq.c b/arch/mips/ralink/irq.c
> new file mode 100644
> index 0000000..f858d5d
> --- /dev/null
> +++ b/arch/mips/ralink/irq.c
> @@ -0,0 +1,182 @@
> +/*
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License version 2 as published
> + * by the Free Software Foundation.
> + *
> + * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
> + * Copyright (C) 2013 John Crispin <blogic@openwrt.org>
> + */
> +
> +#include <linux/io.h>
> +#include <linux/bitops.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/irqdomain.h>
> +#include <linux/interrupt.h>
> +
> +#include <asm/irq_cpu.h>
> +#include <asm/mipsregs.h>
> +
> +#include "common.h"
> +
> +/* INTC register offsets */
> +#define INTC_REG_STATUS0 0x00
> +#define INTC_REG_STATUS1 0x04
> +#define INTC_REG_TYPE 0x20
> +#define INTC_REG_RAW_STATUS 0x30
> +#define INTC_REG_ENABLE 0x34
> +#define INTC_REG_DISABLE 0x38
> +
> +#define INTC_INT_GLOBAL BIT(31)
> +#define INTC_IRQ_COUNT 32
> +
> +#define RALINK_CPU_IRQ_BASE 0
> +
> +#define RALINK_CPU_IRQ_INTC (RALINK_CPU_IRQ_BASE + 2)
> +#define RALINK_CPU_IRQ_FE (RALINK_CPU_IRQ_BASE + 5)
> +#define RALINK_CPU_IRQ_WIFI (RALINK_CPU_IRQ_BASE + 6)
> +#define RALINK_CPU_IRQ_COUNTER (RALINK_CPU_IRQ_BASE + 7)
It would be better to use MIPS_CPU_IRQ_BASE instead of introducing a separate
constant. Or assign MIPS_CPU_IRQ_BASE to RALINK_CPU_IRQ_BASE at least.
> +
> +/* we have a cascade of 8 irqs */
> +#define MIPS_CPU_IRQ_CASCADE 8
The code uses this as a base number for the IRQs routed through the INTC
controller. So I would call this to RALINK_INTC_IRQ_BASE.
> +
> +/* we have 32 SoC irqs */
> +#define RALINK_INTC_IRQ_COUNT 32
> +
> +#define RALINK_INTC_IRQ_PERFC (MIPS_CPU_IRQ_CASCADE + 9)
> +
> +static void __iomem *rt_intc_membase;
> +
> +static inline void rt_intc_w32(u32 val, unsigned reg)
> +{
> + __raw_writel(val, rt_intc_membase + reg);
> +}
> +
> +static inline u32 rt_intc_r32(unsigned reg)
> +{
> + return __raw_readl(rt_intc_membase + reg);
> +}
> +
> +static void ralink_intc_irq_unmask(struct irq_data *d)
> +{
> + unsigned int irq = d->irq - MIPS_CPU_IRQ_CASCADE;
Because you are using irqdomains, you should use the hw_irq field of irq_data to
get the bit offset.
> +
> + rt_intc_w32((1 << irq), INTC_REG_ENABLE);
> +}
> +
> +static void ralink_intc_irq_mask(struct irq_data *d)
> +{
> + unsigned int irq = d->irq - MIPS_CPU_IRQ_CASCADE;
> +
> + rt_intc_w32((1 << irq), INTC_REG_DISABLE);
> +}
> +
> +static struct irq_chip ralink_intc_irq_chip = {
> + .name = "INTC",
> + .irq_unmask = ralink_intc_irq_unmask,
> + .irq_mask = ralink_intc_irq_mask,
> + .irq_mask_ack = ralink_intc_irq_mask,
> +};
> +
> +static struct irqaction ralink_intc_irqaction = {
> + .handler = no_action,
> + .name = "cascade [INTC]",
> +};
It would be simpler to use 'irq_set_chained_handler' instead of 'irq_setup' in
'intc_of_init'. In that way you would not have to use a custom irq_action.
> +
> +unsigned int __cpuinit get_c0_compare_irq(void)
> +{
> + return CP0_LEGACY_COMPARE_IRQ;
> +}
> +
> +void ralink_intc_dispatch(void)
> +{
> + u32 pending = rt_intc_r32(INTC_REG_STATUS0);
> +
> + do_IRQ((int)(__ffs(pending) + MIPS_CPU_IRQ_CASCADE));
You have to check that 'pending' is not zero before passing that to '__ffs',
because the result of '__ffs(x)' is not defined if 'x' is zero.
> +}
> +
> +asmlinkage void plat_irq_dispatch(void)
> +{
> + unsigned long pending;
> +
> + pending = read_c0_status() & read_c0_cause() & ST0_IM;
> +
> + if (pending & STATUSF_IP7)
> + do_IRQ(RALINK_CPU_IRQ_COUNTER);
> +
> + else if (pending & STATUSF_IP5)
> + do_IRQ(RALINK_CPU_IRQ_FE);
> +
> + else if (pending & STATUSF_IP6)
> + do_IRQ(RALINK_CPU_IRQ_WIFI);
> +
> + else if (pending & STATUSF_IP2)
> + ralink_intc_dispatch();
> +
> + else
> + spurious_interrupt();
> +}
> +
> +static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
> +{
> + if (hw < MIPS_CPU_IRQ_CASCADE)
> + return 0;
The INTC controller can handle 32 IRQs, so the hardware IRQ numbers within the
0..31 range are valid. With this code, the hardware IRQ numbers from the 0..7
range can't be mapped.
> +
> + irq_set_chip_and_handler(hw, &ralink_intc_irq_chip, handle_level_irq);
> +
> + return 0;
> +}
> +
> +static const struct irq_domain_ops irq_domain_ops = {
> + .xlate = irq_domain_xlate_onetwocell,
This should be either 'irq_domain_xlate_onecell' or 'irq_domain_xlate_twocell'.
Here is the note from linux/irq/irqdomain.c:
* Note: don't use this function unless your interrupt controller explicitly
* supports both one and two cell bindings. For the majority of controllers
* the _onecell() or _twocell() variants above should be used.
> + .map = intc_map,
> +};
> +
> +int __init intc_of_init(struct device_node *node, struct device_node *parent)
> +{
> + struct resource res;
> +
> + mips_cpu_irq_init();
> +
> + if (of_address_to_resource(node, 0, &res))
> + panic("Failed to get intc memory range");
> +
> + if (request_mem_region(res.start, resource_size(&res),
> + res.name) < 0)
> + pr_err("Failed to request intc memory");
> +
> + rt_intc_membase = ioremap_nocache(res.start,
> + resource_size(&res));
> + if (!rt_intc_membase)
> + panic("Failed to remap intc memory");
> +
> + /* disable all interrupts */
> + rt_intc_w32(~0, INTC_REG_DISABLE);
> +
> + /* route all INTC interrupts to MIPS HW0 interrupt */
> + rt_intc_w32(0, INTC_REG_TYPE);
> +
> + setup_irq(RALINK_CPU_IRQ_INTC, &ralink_intc_irqaction);
> +
> + irq_domain_add_linear(node,
> + MIPS_CPU_IRQ_CASCADE + RALINK_INTC_IRQ_COUNT,
> + &irq_domain_ops, 0);
> +
> + rt_intc_w32(INTC_INT_GLOBAL, INTC_REG_ENABLE);
> +
> + cp0_perfcount_irq = RALINK_INTC_IRQ_PERFC;
> +
> + return 0;
> +}
> +
> +static struct of_device_id __initdata of_irq_ids[] = {
> + { .compatible = "ralink,intc", .data = intc_of_init },
> + {},
> +};
> +
> +void __init arch_init_irq(void)
> +{
> + of_irq_init(of_irq_ids);
> +}
> +
>
next prev parent reply other threads:[~2013-01-24 10:44 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-01-23 12:05 [RFC 00/11] MIPS: ralink: adds support for ralink platform John Crispin
2013-01-23 12:05 ` [RFC 01/11] MIPS: allow platforms to override cp0_compare_irq John Crispin
[not found] ` <5101043A.6080009@openwrt.org>
2013-01-24 10:00 ` John Crispin
2013-01-23 12:05 ` [RFC 02/11] MIPS: ralink: adds include files John Crispin
2013-01-24 10:34 ` Gabor Juhos
2013-01-23 12:05 ` [RFC 03/11] MIPS: ralink: adds irq code John Crispin
2013-01-24 10:44 ` Gabor Juhos [this message]
2013-01-23 12:05 ` [RFC 04/11] MIPS: ralink: adds reset code John Crispin
2013-01-23 12:05 ` [RFC 05/11] MIPS: ralink: adds prom and cmdline code John Crispin
2013-01-24 11:52 ` Gabor Juhos
2013-01-23 12:05 ` [RFC 06/11] MIPS: ralink: adds clkdev code John Crispin
2013-01-23 12:05 ` [RFC 07/11] MIPS: ralink: adds OF code John Crispin
2013-01-24 13:20 ` Gabor Juhos
2013-01-23 12:05 ` [RFC 08/11] MIPS: ralink: adds early_printk support John Crispin
2013-01-23 19:23 ` Florian Fainelli
2013-01-23 21:54 ` Sergei Shtylyov
2013-01-23 22:15 ` Sergei Shtylyov
2013-01-24 6:57 ` John Crispin
2013-01-24 7:23 ` John Crispin
2013-01-24 7:25 ` John Crispin
2013-01-24 9:58 ` Florian Fainelli
2013-01-24 12:02 ` Sergei Shtylyov
2013-01-24 12:11 ` Gabor Juhos
2013-01-23 12:05 ` [RFC 09/11] MIPS: ralink: adds support for RT305x SoC family John Crispin
2013-01-24 12:27 ` Gabor Juhos
2013-01-23 12:05 ` [RFC 10/11] MIPS: ralink: adds rt305x devicetree John Crispin
2013-01-24 13:52 ` Gabor Juhos
2013-01-23 12:05 ` [RFC 11/11] MIPS: ralink: adds Kbuild files John Crispin
2013-01-24 13:59 ` Gabor Juhos
2013-01-24 15:06 ` John Crispin
2013-01-23 19:25 ` [RFC 00/11] MIPS: ralink: adds support for ralink platform Florian Fainelli
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51011087.60709@openwrt.org \
--to=juhosg@openwrt.org \
--cc=blogic@openwrt.org \
--cc=linux-mips@linux-mips.org \
--cc=ralf@linux-mips.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.