From: maxime.ripard@free-electrons.com (Maxime Ripard)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 5/5] pinctrl: sunxi: Implement multiple interrupt banks support
Date: Thu, 29 May 2014 20:32:44 +0200 [thread overview]
Message-ID: <20140529183244.GX4730@lukather> (raw)
In-Reply-To: <CAGb2v65-3ddhaiF-CMdem9NHHibboQYaqXC1axDX+VcpWSLPxw@mail.gmail.com>
On Wed, May 28, 2014 at 08:04:00PM +0800, Chen-Yu Tsai wrote:
> On Wed, May 28, 2014 at 7:47 PM, Chen-Yu Tsai <wens@csie.org> wrote:
> > Hi,
> >
> > On Wed, May 28, 2014 at 6:27 PM, Maxime Ripard
> > <maxime.ripard@free-electrons.com> wrote:
> >> The A23 and A31 support multiple interrupt banks. Support it by adding a linear
> >> domain covering all the banks. It's trickier than it should because there's an
> >> interrupt per bank, so we have multiple interrupts using the same domain.
> >>
> >> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> >> ---
> >> drivers/pinctrl/sunxi/pinctrl-sunxi.c | 62 +++++++++++++++++++++++++++--------
> >> drivers/pinctrl/sunxi/pinctrl-sunxi.h | 11 +++++--
> >> 2 files changed, 57 insertions(+), 16 deletions(-)
> >>
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> index 71d6cd10d56f..69b58aacc636 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
> >> @@ -635,17 +635,25 @@ static void sunxi_pinctrl_irq_handler(unsigned irq, struct irq_desc *desc)
> >> {
> >> struct irq_chip *chip = irq_get_chip(irq);
> >> struct sunxi_pinctrl *pctl = irq_get_handler_data(irq);
> >> - const unsigned long reg = readl(pctl->membase + IRQ_STATUS_REG);
> >> + unsigned long bank, reg, val;
> >> +
> >> + for (bank = 0; bank < pctl->desc->irq_banks; bank++)
> >> + if (irq == pctl->irq[bank])
> >> + break;
> >
> > bail out or BUG_ON(bank == pctl->desc->irq_banks)?
> > (dumb question: would this even happen?)
> >
> >> +
> >> + reg = sunxi_irq_status_reg_from_bank(bank);
> >> + val = readl(pctl->membase + reg);
> >>
> >> /* Clear all interrupts */
> >> - writel(reg, pctl->membase + IRQ_STATUS_REG);
> >> + writel(val, pctl->membase + reg);
> >>
> >> - if (reg) {
> >> + if (val) {
> >> int irqoffset;
> >>
> >> chained_irq_enter(chip, desc);
> >> - for_each_set_bit(irqoffset, ®, SUNXI_IRQ_NUMBER) {
> >> - int pin_irq = irq_find_mapping(pctl->domain, irqoffset);
> >> + for_each_set_bit(irqoffset, &val, SUNXI_IRQ_NUMBER) {
> >> + int pin_irq = irq_find_mapping(pctl->domain,
> >> + bank * SUNXI_IRQ_NUMBER + irqoffset);
> >> generic_handle_irq(pin_irq);
> >> }
> >> chained_irq_exit(chip, desc);
> >> @@ -713,8 +721,11 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
> >>
> >> while (func->name) {
> >> /* Create interrupt mapping while we're at it */
> >> - if (!strcmp(func->name, "irq"))
> >> - pctl->irq_array[func->irqnum] = pin->pin.number;
> >> + if (!strcmp(func->name, "irq")) {
> >> + int irqnum = func->irqnum + func->irqbank * SUNXI_IRQ_NUMBER;
> >> + pctl->irq_array[irqnum] = pin->pin.number;
> >> + }
> >> +
> >> sunxi_pinctrl_add_function(pctl, func->name);
> >> func++;
> >> }
> >> @@ -784,6 +795,13 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> >> pctl->dev = &pdev->dev;
> >> pctl->desc = desc;
> >>
> >> + pctl->irq_array = devm_kcalloc(&pdev->dev,
> >> + SUNXI_IRQ_NUMBER * pctl->desc->irq_banks,
> >> + sizeof(*pctl->irq_array),
> >> + GFP_KERNEL);
> >> + if (!pctl->irq_array)
> >> + return -ENOMEM;
> >> +
> >> ret = sunxi_pinctrl_build_state(pdev);
> >> if (ret) {
> >> dev_err(&pdev->dev, "dt probe failed: %d\n", ret);
> >> @@ -868,21 +886,34 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> >> if (ret)
> >> goto gpiochip_error;
> >>
> >> - pctl->irq = irq_of_parse_and_map(node, 0);
> >> + pctl->irq = devm_kcalloc(&pdev->dev,
> >> + pctl->desc->irq_banks,
> >> + sizeof(*pctl->irq),
> >> + GFP_KERNEL);
> >> if (!pctl->irq) {
> >> - ret = -EINVAL;
> >> + ret = -ENOMEM;
> >> goto clk_error;
> >> }
> >>
> >> - pctl->domain = irq_domain_add_linear(node, SUNXI_IRQ_NUMBER,
> >> - &irq_domain_simple_ops, NULL);
> >> + for (i = 0; i < pctl->desc->irq_banks; i++) {
> >> + pctl->irq[i] = platform_get_irq(pdev, i);
> >> + if (pctl->irq[i] < 0) {
> >> + ret = pctl->irq[i];
> >> + goto clk_error;
> >> + }
> >> + }
> >> +
> >> + pctl->domain = irq_domain_add_linear(node,
> >> + pctl->desc->irq_banks * SUNXI_IRQ_NUMBER,
> >> + &irq_domain_simple_ops,
> >> + NULL);
> >> if (!pctl->domain) {
> >> dev_err(&pdev->dev, "Couldn't register IRQ domain\n");
> >> ret = -ENOMEM;
> >> goto clk_error;
> >> }
> >>
> >> - for (i = 0; i < SUNXI_IRQ_NUMBER; i++) {
> >> + for (i = 0; i < (pctl->desc->irq_banks * SUNXI_IRQ_NUMBER); i++) {
> >> int irqno = irq_create_mapping(pctl->domain, i);
> >>
> >> irq_set_chip_and_handler(irqno, &sunxi_pinctrl_irq_chip,
> >> @@ -890,8 +921,11 @@ int sunxi_pinctrl_init(struct platform_device *pdev,
> >> irq_set_chip_data(irqno, pctl);
> >> };
> >>
> >> - irq_set_chained_handler(pctl->irq, sunxi_pinctrl_irq_handler);
> >> - irq_set_handler_data(pctl->irq, pctl);
> >> + for (i = 0; i < pctl->desc->irq_banks; i++) {
> >> + irq_set_chained_handler(pctl->irq[i],
> >> + sunxi_pinctrl_irq_handler);
> >> + irq_set_handler_data(pctl->irq[i], pctl);
> >> + }
> >>
> >> dev_info(&pdev->dev, "initialized sunXi PIO driver\n");
> >>
> >> diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> >> index 7ddcce0f3c27..e4a808e66fd2 100644
> >> --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> >> +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
> >> @@ -68,6 +68,8 @@
> >> #define IRQ_STATUS_IRQ_BITS 1
> >> #define IRQ_STATUS_IRQ_MASK ((1 << IRQ_STATUS_IRQ_BITS) - 1)
> >>
> >> +#define IRQ_MEM_SIZE 0x20
> >> +
> >> #define IRQ_EDGE_RISING 0x00
> >> #define IRQ_EDGE_FALLING 0x01
> >> #define IRQ_LEVEL_HIGH 0x02
> >> @@ -115,8 +117,8 @@ struct sunxi_pinctrl {
> >> unsigned nfunctions;
> >> struct sunxi_pinctrl_group *groups;
> >> unsigned ngroups;
> >> - int irq;
> >> - int irq_array[SUNXI_IRQ_NUMBER];
> >> + int *irq;
> >> + unsigned *irq_array;
> >> spinlock_t lock;
> >> struct pinctrl_dev *pctl_dev;
> >> };
> >> @@ -250,6 +252,11 @@ static inline u32 sunxi_irq_ctrl_offset(u16 irq)
> >> return irq_num * IRQ_CTRL_IRQ_BITS;
> >> }
> >>
> >> +static inline u32 sunxi_irq_status_reg_from_bank(u8 bank)
> >> +{
> >> + return IRQ_STATUS_REG + bank * IRQ_MEM_SIZE;
> >> +}
> >> +
> >> static inline u32 sunxi_irq_status_reg(u16 irq)
> >> {
> >> u8 reg = irq / IRQ_STATUS_IRQ_PER_REG * 0x04;
>
> Sorry, missed this. You should also change 0x04 to IRQ_MEM_SIZE
> (I believe that was the original intention?) for sunxi_irq_*_reg.
>
> This should fix the mask/unmask/set_type callbacks.
Hmm right. I completely missed this, and used a PA* pin, so it never
made any difference.
I'm sending a new version.
Thanks,
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140529/7dc0fb98/attachment.sig>
next prev parent reply other threads:[~2014-05-29 18:32 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-05-28 10:27 [PATCH 0/5] pinctrl: sunxi: Add A31 external interrupts support Maxime Ripard
2014-05-28 10:27 ` [PATCH 1/5] pinctrl: sunxi: Remove irq_mask_ack and use irq_ack instead Maxime Ripard
2014-05-28 10:27 ` [PATCH 2/5] pinctrl: sunxi: Add macro definition for pinctrl with more than one interrupt Maxime Ripard
2014-05-28 10:27 ` [PATCH 3/5] pinctrl: sunxi: Declare the number of interrupt banks in the descriptor Maxime Ripard
2014-05-28 10:27 ` [PATCH 4/5] pinctrl: sunxi: Declare the interrupt function for the A31 Maxime Ripard
2014-05-28 10:27 ` [PATCH 5/5] pinctrl: sunxi: Implement multiple interrupt banks support Maxime Ripard
2014-05-28 11:47 ` Chen-Yu Tsai
2014-05-28 12:04 ` Chen-Yu Tsai
2014-05-29 18:32 ` Maxime Ripard [this message]
2014-05-29 17:59 ` Maxime Ripard
2014-05-28 12:14 ` [PATCH 0/5] pinctrl: sunxi: Add A31 external interrupts support Chen-Yu Tsai
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=20140529183244.GX4730@lukather \
--to=maxime.ripard@free-electrons.com \
--cc=linux-arm-kernel@lists.infradead.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.