From: Wolfram Sang <w.sang@pengutronix.de>
To: Grant Likely <grant.likely@secretlab.ca>
Cc: linuxppc-dev@ozlabs.org
Subject: Re: [PATCH 7/8] powerpc/5200: Refactor mpc5200 interrupt controller driver
Date: Thu, 29 Jan 2009 22:33:31 +0100 [thread overview]
Message-ID: <20090129213331.GF1406@pengutronix.de> (raw)
In-Reply-To: <20090121205540.31232.77034.stgit@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 9275 bytes --]
On Wed, Jan 21, 2009 at 01:55:41PM -0700, Grant Likely wrote:
> From: Grant Likely <grant.likely@secretlab.ca>
>
> Rework the mpc5200-pic driver to simplify it and fix up the setting
> of desc->status when set_type is called for internal IRQs (so they
> are reported as level, not edge). The simplification is due to
> splitting off the handling of external IRQs into a separate block
> so they don't need to be handled as exceptions in the normal
> CRIT, MAIN and PERP paths.
>
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> CC: Wolfram Sang <w.sang@pengutronix.de>
Can't say much about this one as I have never dealt with the PIC
directly so far. Yet, my phyCORE-MPC5200B-tiny behaves normal, so
Tested-by: Wolfram Sang <w.sang@pengutronix.de>
> ---
>
> arch/powerpc/platforms/52xx/mpc52xx_pic.c | 145 ++++++++++++-----------------
> 1 files changed, 58 insertions(+), 87 deletions(-)
>
>
> diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
> index c0a9559..277c9c5 100644
> --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c
> +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c
> @@ -190,10 +190,10 @@ static void mpc52xx_extirq_ack(unsigned int virq)
>
> static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
> {
> - struct irq_desc *desc = get_irq_desc(virq);
> u32 ctrl_reg, type;
> int irq;
> int l2irq;
> + void *handler = handle_level_irq;
>
> irq = irq_map[virq].hwirq;
> l2irq = irq & MPC52xx_IRQ_L2_MASK;
> @@ -201,32 +201,21 @@ static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
> pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type);
>
> switch (flow_type) {
> - case IRQF_TRIGGER_HIGH:
> - type = 0;
> - break;
> - case IRQF_TRIGGER_RISING:
> - type = 1;
> - break;
> - case IRQF_TRIGGER_FALLING:
> - type = 2;
> - break;
> - case IRQF_TRIGGER_LOW:
> - type = 3;
> - break;
> + case IRQF_TRIGGER_HIGH: type = 0; break;
> + case IRQF_TRIGGER_RISING: type = 1; handler = handle_edge_irq; break;
> + case IRQF_TRIGGER_FALLING: type = 2; handler = handle_edge_irq; break;
> + case IRQF_TRIGGER_LOW: type = 3; break;
> default:
> type = 0;
> }
>
> - desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
> - desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
> - if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
> - desc->status |= IRQ_LEVEL;
> -
> ctrl_reg = in_be32(&intr->ctrl);
> ctrl_reg &= ~(0x3 << (22 - (l2irq * 2)));
> ctrl_reg |= (type << (22 - (l2irq * 2)));
> out_be32(&intr->ctrl, ctrl_reg);
>
> + __set_irq_handler_unlocked(virq, handler);
> +
> return 0;
> }
>
> @@ -241,6 +230,11 @@ static struct irq_chip mpc52xx_extirq_irqchip = {
> /*
> * Main interrupt irq_chip
> */
> +static int mpc52xx_null_set_type(unsigned int virq, unsigned int flow_type)
> +{
> + return 0; /* Do nothing so that the sense mask will get updated */
> +}
> +
> static void mpc52xx_main_mask(unsigned int virq)
> {
> int irq;
> @@ -268,6 +262,7 @@ static struct irq_chip mpc52xx_main_irqchip = {
> .mask = mpc52xx_main_mask,
> .mask_ack = mpc52xx_main_mask,
> .unmask = mpc52xx_main_unmask,
> + .set_type = mpc52xx_null_set_type,
> };
>
> /*
> @@ -300,6 +295,7 @@ static struct irq_chip mpc52xx_periph_irqchip = {
> .mask = mpc52xx_periph_mask,
> .mask_ack = mpc52xx_periph_mask,
> .unmask = mpc52xx_periph_unmask,
> + .set_type = mpc52xx_null_set_type,
> };
>
> /*
> @@ -343,9 +339,19 @@ static struct irq_chip mpc52xx_sdma_irqchip = {
> .mask = mpc52xx_sdma_mask,
> .unmask = mpc52xx_sdma_unmask,
> .ack = mpc52xx_sdma_ack,
> + .set_type = mpc52xx_null_set_type,
> };
>
> /**
> + * mpc52xx_is_extirq - Returns true if hwirq number is for an external IRQ
> + */
> +static int mpc52xx_is_extirq(int l1, int l2)
> +{
> + return ((l1 == 0) && (l2 == 0)) ||
> + ((l1 == 1) && (l2 >= 1) && (l2 <= 3));
> +}
> +
> +/**
> * mpc52xx_irqhost_xlate - translate virq# from device tree interrupts property
> */
> static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
> @@ -363,38 +369,23 @@ static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
>
> intrvect_l1 = (int)intspec[0];
> intrvect_l2 = (int)intspec[1];
> - intrvect_type = (int)intspec[2];
> + intrvect_type = (int)intspec[2] & 0x3;
>
> intrvect_linux = (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) &
> MPC52xx_IRQ_L1_MASK;
> intrvect_linux |= intrvect_l2 & MPC52xx_IRQ_L2_MASK;
>
> - pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
> - intrvect_l2);
> -
> *out_hwirq = intrvect_linux;
> - *out_flags = mpc52xx_map_senses[intrvect_type];
> + *out_flags = IRQ_TYPE_LEVEL_LOW;
> + if (mpc52xx_is_extirq(intrvect_l1, intrvect_l2))
> + *out_flags = mpc52xx_map_senses[intrvect_type];
>
> + pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
> + intrvect_l2);
> return 0;
> }
>
> /**
> - * mpc52xx_irqx_gettype - determine the IRQ sense type (level/edge)
> - *
> - * Only external IRQs need this.
> - */
> -static int mpc52xx_irqx_gettype(int irq)
> -{
> - int type;
> - u32 ctrl_reg;
> -
> - ctrl_reg = in_be32(&intr->ctrl);
> - type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
> -
> - return mpc52xx_map_senses[type];
> -}
> -
> -/**
> * mpc52xx_irqhost_map - Hook to map from virq to an irq_chip structure
> */
> static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
> @@ -402,68 +393,46 @@ static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
> {
> int l1irq;
> int l2irq;
> - struct irq_chip *good_irqchip;
> + struct irq_chip *irqchip;
> void *good_handle;
> int type;
> + u32 reg;
>
> l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
> l2irq = irq & MPC52xx_IRQ_L2_MASK;
>
> /*
> - * Most of ours IRQs will be level low
> - * Only external IRQs on some platform may be others
> + * External IRQs are handled differently by the hardware so they are
> + * handled by a dedicated irq_chip structure.
> */
> - type = IRQ_TYPE_LEVEL_LOW;
> + if (mpc52xx_is_extirq(l1irq, l2irq)) {
> + reg = in_be32(&intr->ctrl);
> + type = mpc52xx_map_senses[(reg >> (22 - l2irq * 2)) & 0x3];
> + if ((type == IRQ_TYPE_EDGE_FALLING) ||
> + (type == IRQ_TYPE_EDGE_RISING))
> + good_handle = handle_edge_irq;
> + else
> + good_handle = handle_level_irq;
> +
> + set_irq_chip_and_handler(virq, &mpc52xx_extirq_irqchip, good_handle);
> + pr_debug("%s: External IRQ%i virq=%x, hw=%x. type=%x\n",
> + __func__, l2irq, virq, (int)irq, type);
> + return 0;
> + }
>
> + /* It is an internal SOC irq. Choose the correct irq_chip */
> switch (l1irq) {
> - case MPC52xx_IRQ_L1_CRIT:
> - pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
> -
> - BUG_ON(l2irq != 0);
> -
> - type = mpc52xx_irqx_gettype(l2irq);
> - good_irqchip = &mpc52xx_extirq_irqchip;
> - break;
> -
> - case MPC52xx_IRQ_L1_MAIN:
> - pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
> -
> - if ((l2irq >= 1) && (l2irq <= 3)) {
> - type = mpc52xx_irqx_gettype(l2irq);
> - good_irqchip = &mpc52xx_extirq_irqchip;
> - } else {
> - good_irqchip = &mpc52xx_main_irqchip;
> - }
> - break;
> -
> - case MPC52xx_IRQ_L1_PERP:
> - pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
> - good_irqchip = &mpc52xx_periph_irqchip;
> - break;
> -
> - case MPC52xx_IRQ_L1_SDMA:
> - pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
> - good_irqchip = &mpc52xx_sdma_irqchip;
> - break;
> -
> + case MPC52xx_IRQ_L1_MAIN: irqchip = &mpc52xx_main_irqchip; break;
> + case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break;
> + case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break;
> default:
> - pr_err("%s: invalid virq requested (0x%x)\n", __func__, virq);
> + pr_err("%s: invalid irq: virq=%i, l1=%i, l2=%i\n",
> + __func__, virq, l1irq, l2irq);
> return -EINVAL;
> }
>
> - switch (type) {
> - case IRQ_TYPE_EDGE_FALLING:
> - case IRQ_TYPE_EDGE_RISING:
> - good_handle = handle_edge_irq;
> - break;
> - default:
> - good_handle = handle_level_irq;
> - }
> -
> - set_irq_chip_and_handler(virq, good_irqchip, good_handle);
> -
> - pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
> - (int)irq, type);
> + set_irq_chip_and_handler(virq, irqchip, handle_level_irq);
> + pr_debug("%s: virq=%x, l1=%i, l2=%i\n", __func__, virq, l1irq, l2irq);
>
> return 0;
> }
> @@ -502,6 +471,8 @@ void __init mpc52xx_init_irq(void)
> panic(__FILE__ ": find_and_map failed on 'mpc5200-bestcomm'. "
> "Check node !");
>
> + pr_debug("MPC5200 IRQ controller mapped to 0x%p\n", intr);
> +
> /* Disable all interrupt sources. */
> out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */
> out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */
>
--
Dipl.-Ing. Wolfram Sang | http://www.pengutronix.de
Pengutronix - Linux Solutions for Science and Industry
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
next prev parent reply other threads:[~2009-01-29 21:33 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-21 20:55 [PATCH 1/8] powerpc/5200: update device tree binding documentation Grant Likely
2009-01-21 20:55 ` [PATCH 2/8] powerpc/5200: Stop using device_type and port-number properties Grant Likely
2009-01-21 21:13 ` Juergen Beisert
2009-01-22 4:46 ` Grant Likely
2009-01-29 21:15 ` Wolfram Sang
2009-01-21 20:55 ` [PATCH 3/8] powerpc/5200: Trim cruft from device trees Grant Likely
2009-01-29 21:21 ` Wolfram Sang
2009-01-21 20:55 ` [PATCH 4/8] powerpc/5200: Add support for the Media5200 board from Freescale Grant Likely
2009-01-21 20:55 ` [PATCH 5/8] powerpc/5200: Don't specify IRQF_SHARED in PSC UART driver Grant Likely
2009-01-29 21:24 ` Wolfram Sang
2009-01-21 20:55 ` [PATCH 6/8] powerpc/5200: Remove pr_debug() from hot paths in irq driver Grant Likely
2009-01-29 21:29 ` Wolfram Sang
2009-01-21 20:55 ` [PATCH 7/8] powerpc/5200: Refactor mpc5200 interrupt controller driver Grant Likely
2009-01-25 20:06 ` Wolfgang Grandegger
2009-01-26 0:22 ` Grant Likely
2009-01-26 6:26 ` Wolfgang Denk
2009-01-26 8:31 ` Wolfgang Grandegger
2009-01-26 17:58 ` Matt Sealey
2009-01-26 9:22 ` Wolfram Sang
2009-01-27 17:52 ` Matt Sealey
2009-01-27 17:54 ` Grant Likely
2009-01-29 21:33 ` Wolfram Sang [this message]
2009-01-21 20:55 ` [PATCH 8/8] powerpc/5200: Rework GPT driver to also be an IRQ controller Grant Likely
2009-01-27 12:23 ` Wolfram Sang
2009-01-25 19:48 ` [PATCH 1/8] powerpc/5200: update device tree binding documentation Wolfram Sang
2009-01-26 1:46 ` Grant Likely
2009-01-26 9:26 ` Wolfram Sang
2009-01-27 16:25 ` Grant Likely
2009-01-27 18:00 ` Matt Sealey
2009-01-27 18:06 ` Grant Likely
2009-01-29 21:09 ` Wolfram Sang
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=20090129213331.GF1406@pengutronix.de \
--to=w.sang@pengutronix.de \
--cc=grant.likely@secretlab.ca \
--cc=linuxppc-dev@ozlabs.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.