From: Peter Korsgaard <jacmet@sunsite.dk>
To: linuxppc-dev@lists.ozlabs.org
Subject: Re: [PATCH 3/3] mpc8xxx_gpio: add interrupt support
Date: Wed, 09 Dec 2009 08:33:00 +0100 [thread overview]
Message-ID: <87pr6omwk3.fsf@macbook.be.48ers.dk> (raw)
In-Reply-To: <1259700494-17869-3-git-send-email-jacmet@sunsite.dk> (Peter Korsgaard's message of "Tue, 1 Dec 2009 21:48:14 +0100")
>>>>> "Peter" == Peter Korsgaard <jacmet@sunsite.dk> writes:
Comments?
Peter> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
Peter> ---
Peter> arch/powerpc/sysdev/mpc8xxx_gpio.c | 147 ++++++++++++++++++++++++++++++++++++
Peter> 1 files changed, 147 insertions(+), 0 deletions(-)
Peter> diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c
Peter> index 103eace..b46f28b 100644
Peter> --- a/arch/powerpc/sysdev/mpc8xxx_gpio.c
Peter> +++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c
Peter> @@ -15,6 +15,7 @@
Peter> #include <linux/of.h>
Peter> #include <linux/of_gpio.h>
Peter> #include <linux/gpio.h>
Peter> +#include <linux/irq.h>
Peter> #define MPC8XXX_GPIO_PINS 32
Peter> @@ -34,6 +35,7 @@ struct mpc8xxx_gpio_chip {
Peter> * open drain mode safely
Peter> */
Peter> u32 data;
Peter> + struct irq_host *irq;
Peter> };
Peter> static inline u32 mpc8xxx_gpio2mask(unsigned int gpio)
Peter> @@ -111,12 +113,136 @@ static int mpc8xxx_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val
Peter> return 0;
Peter> }
Peter> +static int mpc8xxx_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
Peter> +{
Peter> + struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc);
Peter> + struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm);
Peter> +
Peter> + if (mpc8xxx_gc->irq && offset < MPC8XXX_GPIO_PINS)
Peter> + return irq_create_mapping(mpc8xxx_gc->irq, offset);
Peter> + else
Peter> + return -ENXIO;
Peter> +}
Peter> +
Peter> +static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
Peter> +{
Peter> + struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_desc_data(desc);
Peter> + struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
Peter> + unsigned int mask;
Peter> +
Peter> + mask = in_be32(mm->regs + GPIO_IER) & in_be32(mm->regs + GPIO_IMR);
Peter> + if (mask)
Peter> + generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq,
Peter> + 32 - ffs(mask)));
Peter> +}
Peter> +
Peter> +static void mpc8xxx_irq_unmask(unsigned int virq)
Peter> +{
Peter> + struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
Peter> + struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
Peter> + unsigned long flags;
Peter> +
Peter> + spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
Peter> +
Peter> + setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq)));
Peter> +
Peter> + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
Peter> +}
Peter> +
Peter> +static void mpc8xxx_irq_mask(unsigned int virq)
Peter> +{
Peter> + struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
Peter> + struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
Peter> + unsigned long flags;
Peter> +
Peter> + spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
Peter> +
Peter> + clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq)));
Peter> +
Peter> + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
Peter> +}
Peter> +
Peter> +static void mpc8xxx_irq_ack(unsigned int virq)
Peter> +{
Peter> + struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
Peter> + struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
Peter> +
Peter> + out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(virq_to_hw(virq)));
Peter> +}
Peter> +
Peter> +static int mpc8xxx_irq_set_type(unsigned int virq, unsigned int flow_type)
Peter> +{
Peter> + struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
Peter> + struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
Peter> + unsigned long flags;
Peter> +
Peter> + switch (flow_type) {
Peter> + case IRQ_TYPE_EDGE_FALLING:
Peter> + spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
Peter> + setbits32(mm->regs + GPIO_ICR,
Peter> + mpc8xxx_gpio2mask(virq_to_hw(virq)));
Peter> + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
Peter> + break;
Peter> +
Peter> + case IRQ_TYPE_EDGE_BOTH:
Peter> + spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
Peter> + clrbits32(mm->regs + GPIO_ICR,
Peter> + mpc8xxx_gpio2mask(virq_to_hw(virq)));
Peter> + spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
Peter> + break;
Peter> +
Peter> + default:
Peter> + return -EINVAL;
Peter> + }
Peter> +
Peter> + return 0;
Peter> +}
Peter> +
Peter> +static struct irq_chip mpc8xxx_irq_chip = {
Peter> + .name = "mpc8xxx-gpio",
Peter> + .unmask = mpc8xxx_irq_unmask,
Peter> + .mask = mpc8xxx_irq_mask,
Peter> + .ack = mpc8xxx_irq_ack,
Peter> + .set_type = mpc8xxx_irq_set_type,
Peter> +};
Peter> +
Peter> +static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq,
Peter> + irq_hw_number_t hw)
Peter> +{
Peter> + set_irq_chip_data(virq, h->host_data);
Peter> + set_irq_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
Peter> + set_irq_type(virq, IRQ_TYPE_NONE);
Peter> +
Peter> + return 0;
Peter> +}
Peter> +
Peter> +static int mpc8xxx_gpio_irq_xlate(struct irq_host *h, struct device_node *ct,
Peter> + u32 *intspec, unsigned int intsize,
Peter> + irq_hw_number_t *out_hwirq,
Peter> + unsigned int *out_flags)
Peter> +
Peter> +{
Peter> + /* interrupt sense values coming from the device tree equal either
Peter> + * EDGE_FALLING or EDGE_BOTH
Peter> + */
Peter> + *out_hwirq = intspec[0];
Peter> + *out_flags = intspec[1];
Peter> +
Peter> + return 0;
Peter> +}
Peter> +
Peter> +static struct irq_host_ops mpc8xxx_gpio_irq_ops = {
Peter> + .map = mpc8xxx_gpio_irq_map,
Peter> + .xlate = mpc8xxx_gpio_irq_xlate,
Peter> +};
Peter> +
Peter> static void __init mpc8xxx_add_controller(struct device_node *np)
Peter> {
Peter> struct mpc8xxx_gpio_chip *mpc8xxx_gc;
Peter> struct of_mm_gpio_chip *mm_gc;
Peter> struct of_gpio_chip *of_gc;
Peter> struct gpio_chip *gc;
Peter> + unsigned hwirq;
Peter> int ret;
Peter> mpc8xxx_gc = kzalloc(sizeof(*mpc8xxx_gc), GFP_KERNEL);
Peter> @@ -138,11 +264,32 @@ static void __init mpc8xxx_add_controller(struct device_node *np)
gc-> direction_output = mpc8xxx_gpio_dir_out;
gc-> get = mpc8xxx_gpio_get;
gc-> set = mpc8xxx_gpio_set;
Peter> + gc->to_irq = mpc8xxx_gpio_to_irq;
Peter> ret = of_mm_gpiochip_add(np, mm_gc);
Peter> if (ret)
Peter> goto err;
Peter> + hwirq = irq_of_parse_and_map(np, 0);
Peter> + if (hwirq == NO_IRQ)
Peter> + goto skip_irq;
Peter> +
Peter> + mpc8xxx_gc->irq =
Peter> + irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, MPC8XXX_GPIO_PINS,
Peter> + &mpc8xxx_gpio_irq_ops, MPC8XXX_GPIO_PINS);
Peter> + if (!mpc8xxx_gc->irq)
Peter> + goto skip_irq;
Peter> +
Peter> + mpc8xxx_gc->irq->host_data = mpc8xxx_gc;
Peter> +
Peter> + /* ack and mask all irqs */
Peter> + out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);
Peter> + out_be32(mm_gc->regs + GPIO_IMR, 0);
Peter> +
Peter> + set_irq_data(hwirq, mpc8xxx_gc);
Peter> + set_irq_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade);
Peter> +
Peter> +skip_irq:
Peter> return;
Peter> err:
Peter> --
Peter> 1.6.5
--
Bye, Peter Korsgaard
next prev parent reply other threads:[~2009-12-09 7:33 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-12-01 20:48 [PATCH 1/3] show_interrupts: use irq_chip::name if available Peter Korsgaard
2009-12-01 20:48 ` [PATCH 2/3] asm/gpio.h: support gpio_to_irq() Peter Korsgaard
2009-12-01 20:48 ` [PATCH 3/3] mpc8xxx_gpio: add interrupt support Peter Korsgaard
2009-12-09 7:33 ` Peter Korsgaard [this message]
2009-12-11 2:13 ` Kumar Gala
2009-12-11 15:31 ` Peter Korsgaard
2009-12-17 20:31 ` Peter Korsgaard
2009-12-09 7:32 ` [PATCH 2/3] asm/gpio.h: support gpio_to_irq() Peter Korsgaard
2009-12-11 2:09 ` Kumar Gala
2009-12-09 7:32 ` [PATCH 1/3] show_interrupts: use irq_chip::name if available Peter Korsgaard
2009-12-09 8:59 ` Benjamin Herrenschmidt
2009-12-09 9:09 ` Peter Korsgaard
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=87pr6omwk3.fsf@macbook.be.48ers.dk \
--to=jacmet@sunsite.dk \
--cc=linuxppc-dev@lists.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.