lkml.org 
[lkml]   [2017]   [Feb]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.16 198/306] gpio/mvebu: Use irq_domain_add_linear
    3.16.40-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>

    commit 812d47889a8e418d7bea9bec383581a34c19183e upstream.

    This fixes the irq allocation in this driver to not print:
    irq: Cannot allocate irq_descs @ IRQ34, assuming pre-allocated
    irq: Cannot allocate irq_descs @ IRQ66, assuming pre-allocated

    Which happens because the driver already called irq_alloc_descs()
    and so the change to use irq_domain_add_simple resulted in calling
    irq_alloc_descs() twice.

    Modernize the irq allocation in this driver to use the
    irq_domain_add_linear flow directly and eliminate the use of
    irq_domain_add_simple/legacy

    Fixes: ce931f571b6d ("gpio/mvebu: convert to use irq_domain_add_simple()")
    Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
    Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
    [bwh: Backported to 3.16:
    - Keep using irq_set_handler_data(), irq_set_chained_handler()
    - Adjust context]
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    --- a/drivers/gpio/gpio-mvebu.c
    +++ b/drivers/gpio/gpio-mvebu.c
    @@ -294,10 +294,10 @@ static void mvebu_gpio_irq_ack(struct ir
    {
    struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
    struct mvebu_gpio_chip *mvchip = gc->private;
    - u32 mask = ~(1 << (d->irq - gc->irq_base));
    + u32 mask = d->mask;

    irq_gc_lock(gc);
    - writel_relaxed(mask, mvebu_gpioreg_edge_cause(mvchip));
    + writel_relaxed(~mask, mvebu_gpioreg_edge_cause(mvchip));
    irq_gc_unlock(gc);
    }

    @@ -306,7 +306,7 @@ static void mvebu_gpio_edge_irq_mask(str
    struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
    struct mvebu_gpio_chip *mvchip = gc->private;
    struct irq_chip_type *ct = irq_data_get_chip_type(d);
    - u32 mask = 1 << (d->irq - gc->irq_base);
    + u32 mask = d->mask;

    irq_gc_lock(gc);
    ct->mask_cache_priv &= ~mask;
    @@ -320,8 +320,7 @@ static void mvebu_gpio_edge_irq_unmask(s
    struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
    struct mvebu_gpio_chip *mvchip = gc->private;
    struct irq_chip_type *ct = irq_data_get_chip_type(d);
    -
    - u32 mask = 1 << (d->irq - gc->irq_base);
    + u32 mask = d->mask;

    irq_gc_lock(gc);
    ct->mask_cache_priv |= mask;
    @@ -334,8 +333,7 @@ static void mvebu_gpio_level_irq_mask(st
    struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
    struct mvebu_gpio_chip *mvchip = gc->private;
    struct irq_chip_type *ct = irq_data_get_chip_type(d);
    -
    - u32 mask = 1 << (d->irq - gc->irq_base);
    + u32 mask = d->mask;

    irq_gc_lock(gc);
    ct->mask_cache_priv &= ~mask;
    @@ -348,8 +346,7 @@ static void mvebu_gpio_level_irq_unmask(
    struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
    struct mvebu_gpio_chip *mvchip = gc->private;
    struct irq_chip_type *ct = irq_data_get_chip_type(d);
    -
    - u32 mask = 1 << (d->irq - gc->irq_base);
    + u32 mask = d->mask;

    irq_gc_lock(gc);
    ct->mask_cache_priv |= mask;
    @@ -464,7 +461,7 @@ static void mvebu_gpio_irq_handler(unsig
    for (i = 0; i < mvchip->chip.ngpio; i++) {
    int irq;

    - irq = mvchip->irqbase + i;
    + irq = irq_find_mapping(mvchip->domain, i);

    if (!(cause & (1 << i)))
    continue;
    @@ -572,8 +569,10 @@ static int mvebu_gpio_probe(struct platf
    struct irq_chip_type *ct;
    struct clk *clk;
    unsigned int ngpios;
    + bool have_irqs;
    int soc_variant;
    int i, cpu, id;
    + int err;

    match = of_match_device(mvebu_gpio_of_match, &pdev->dev);
    if (match)
    @@ -581,6 +580,9 @@ static int mvebu_gpio_probe(struct platf
    else
    soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION;

    + /* Some gpio controllers do not provide irq support */
    + have_irqs = of_irq_count(np) != 0;
    +
    mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL);
    if (!mvchip)
    return -ENOMEM;
    @@ -610,7 +612,8 @@ static int mvebu_gpio_probe(struct platf
    mvchip->chip.get = mvebu_gpio_get;
    mvchip->chip.direction_output = mvebu_gpio_direction_output;
    mvchip->chip.set = mvebu_gpio_set;
    - mvchip->chip.to_irq = mvebu_gpio_to_irq;
    + if (have_irqs)
    + mvchip->chip.to_irq = mvebu_gpio_to_irq;
    mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK;
    mvchip->chip.ngpio = ngpios;
    mvchip->chip.can_sleep = false;
    @@ -671,34 +674,30 @@ static int mvebu_gpio_probe(struct platf
    gpiochip_add(&mvchip->chip);

    /* Some gpio controllers do not provide irq support */
    - if (!of_irq_count(np))
    + if (!have_irqs)
    return 0;

    - /* Setup the interrupt handlers. Each chip can have up to 4
    - * interrupt handlers, with each handler dealing with 8 GPIO
    - * pins. */
    - for (i = 0; i < 4; i++) {
    - int irq;
    - irq = platform_get_irq(pdev, i);
    - if (irq < 0)
    - continue;
    - irq_set_handler_data(irq, mvchip);
    - irq_set_chained_handler(irq, mvebu_gpio_irq_handler);
    - }
    -
    - mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
    - if (mvchip->irqbase < 0) {
    - dev_err(&pdev->dev, "no irqs\n");
    - return mvchip->irqbase;
    + mvchip->domain =
    + irq_domain_add_linear(np, ngpios, &irq_generic_chip_ops, NULL);
    + if (!mvchip->domain) {
    + dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
    + mvchip->chip.label);
    + return -ENODEV;
    }

    - gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase,
    - mvchip->membase, handle_level_irq);
    - if (!gc) {
    - dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
    - return -ENOMEM;
    + err = irq_alloc_domain_generic_chips(
    + mvchip->domain, ngpios, 2, np->name, handle_level_irq,
    + IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0);
    + if (err) {
    + dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n",
    + mvchip->chip.label);
    + goto err_domain;
    }

    + /* NOTE: The common accessors cannot be used because of the percpu
    + * access to the mask registers
    + */
    + gc = irq_get_domain_generic_chip(mvchip->domain, 0);
    gc->private = mvchip;
    ct = &gc->chip_types[0];
    ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW;
    @@ -716,24 +715,25 @@ static int mvebu_gpio_probe(struct platf
    ct->handler = handle_edge_irq;
    ct->chip.name = mvchip->chip.label;

    - irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,
    - IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
    + /* Setup the interrupt handlers. Each chip can have up to 4
    + * interrupt handlers, with each handler dealing with 8 GPIO
    + * pins.
    + */
    + for (i = 0; i < 4; i++) {
    + int irq = platform_get_irq(pdev, i);

    - /* Setup irq domain on top of the generic chip. */
    - mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio,
    - mvchip->irqbase,
    - &irq_domain_simple_ops,
    - mvchip);
    - if (!mvchip->domain) {
    - dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
    - mvchip->chip.label);
    - irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
    - IRQ_LEVEL | IRQ_NOPROBE);
    - kfree(gc);
    - return -ENODEV;
    + if (irq < 0)
    + continue;
    + irq_set_handler_data(irq, mvchip);
    + irq_set_chained_handler(irq, mvebu_gpio_irq_handler);
    }

    return 0;
    +
    +err_domain:
    + irq_domain_remove(mvchip->domain);
    +
    + return err;
    }

    static struct platform_driver mvebu_gpio_driver = {
    \
     
     \ /
      Last update: 2017-02-16 01:32    [W:3.256 / U:0.048 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site