Lines Matching +full:big +full:- +full:endian +full:- +full:desc
2 * Copyright (C) 2015-2017 Broadcom
71 #define GPIO_BIT(gpio) ((gpio) & (MAX_GPIO_PER_BANK - 1))
77 return bank->parent_priv; in brcmstb_gpio_gc_to_priv()
83 void __iomem *reg_base = bank->parent_priv->reg_base; in __brcmstb_gpio_get_active_irqs()
85 return bank->gc.read_reg(reg_base + GIO_STAT(bank->id)) & in __brcmstb_gpio_get_active_irqs()
86 bank->gc.read_reg(reg_base + GIO_MASK(bank->id)); in __brcmstb_gpio_get_active_irqs()
95 spin_lock_irqsave(&bank->gc.bgpio_lock, flags); in brcmstb_gpio_get_active_irqs()
97 spin_unlock_irqrestore(&bank->gc.bgpio_lock, flags); in brcmstb_gpio_get_active_irqs()
105 return hwirq - (bank->gc.base - bank->parent_priv->gpio_base); in brcmstb_gpio_hwirq_to_offset()
111 struct gpio_chip *gc = &bank->gc; in brcmstb_gpio_set_imask()
112 struct brcmstb_gpio_priv *priv = bank->parent_priv; in brcmstb_gpio_set_imask()
117 spin_lock_irqsave(&gc->bgpio_lock, flags); in brcmstb_gpio_set_imask()
118 imask = gc->read_reg(priv->reg_base + GIO_MASK(bank->id)); in brcmstb_gpio_set_imask()
123 gc->write_reg(priv->reg_base + GIO_MASK(bank->id), imask); in brcmstb_gpio_set_imask()
124 spin_unlock_irqrestore(&gc->bgpio_lock, flags); in brcmstb_gpio_set_imask()
131 int hwirq = offset + (gc->base - priv->gpio_base); in brcmstb_gpio_to_irq()
133 if (hwirq >= priv->num_gpios) in brcmstb_gpio_to_irq()
134 return -ENXIO; in brcmstb_gpio_to_irq()
135 return irq_create_mapping(priv->irq_domain, hwirq); in brcmstb_gpio_to_irq()
138 /* -------------------- IRQ chip functions -------------------- */
145 brcmstb_gpio_set_imask(bank, d->hwirq, false); in brcmstb_gpio_irq_mask()
153 brcmstb_gpio_set_imask(bank, d->hwirq, true); in brcmstb_gpio_irq_unmask()
160 struct brcmstb_gpio_priv *priv = bank->parent_priv; in brcmstb_gpio_irq_ack()
161 u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(d->hwirq, bank)); in brcmstb_gpio_irq_ack()
163 gc->write_reg(priv->reg_base + GIO_STAT(bank->id), mask); in brcmstb_gpio_irq_ack()
170 struct brcmstb_gpio_priv *priv = bank->parent_priv; in brcmstb_gpio_irq_set_type()
171 u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(d->hwirq, bank)); in brcmstb_gpio_irq_set_type()
204 return -EINVAL; in brcmstb_gpio_irq_set_type()
207 spin_lock_irqsave(&bank->gc.bgpio_lock, flags); in brcmstb_gpio_irq_set_type()
209 iedge_config = bank->gc.read_reg(priv->reg_base + in brcmstb_gpio_irq_set_type()
210 GIO_EC(bank->id)) & ~mask; in brcmstb_gpio_irq_set_type()
211 iedge_insensitive = bank->gc.read_reg(priv->reg_base + in brcmstb_gpio_irq_set_type()
212 GIO_EI(bank->id)) & ~mask; in brcmstb_gpio_irq_set_type()
213 ilevel = bank->gc.read_reg(priv->reg_base + in brcmstb_gpio_irq_set_type()
214 GIO_LEVEL(bank->id)) & ~mask; in brcmstb_gpio_irq_set_type()
216 bank->gc.write_reg(priv->reg_base + GIO_EC(bank->id), in brcmstb_gpio_irq_set_type()
218 bank->gc.write_reg(priv->reg_base + GIO_EI(bank->id), in brcmstb_gpio_irq_set_type()
220 bank->gc.write_reg(priv->reg_base + GIO_LEVEL(bank->id), in brcmstb_gpio_irq_set_type()
223 spin_unlock_irqrestore(&bank->gc.bgpio_lock, flags); in brcmstb_gpio_irq_set_type()
233 ret = enable_irq_wake(priv->parent_wake_irq); in brcmstb_gpio_priv_set_wake()
235 ret = disable_irq_wake(priv->parent_wake_irq); in brcmstb_gpio_priv_set_wake()
237 dev_err(&priv->pdev->dev, "failed to %s wake-up interrupt\n", in brcmstb_gpio_priv_set_wake()
246 struct brcmstb_gpio_priv *priv = bank->parent_priv; in brcmstb_gpio_irq_set_wake()
247 u32 mask = BIT(brcmstb_gpio_hwirq_to_offset(d->hwirq, bank)); in brcmstb_gpio_irq_set_wake()
254 bank->wake_active |= mask; in brcmstb_gpio_irq_set_wake()
256 bank->wake_active &= ~mask; in brcmstb_gpio_irq_set_wake()
265 if (!priv || irq != priv->parent_wake_irq) in brcmstb_gpio_wake_irq_handler()
274 struct brcmstb_gpio_priv *priv = bank->parent_priv; in brcmstb_gpio_irq_bank_handler()
275 struct irq_domain *domain = priv->irq_domain; in brcmstb_gpio_irq_bank_handler()
276 int hwbase = bank->gc.base - priv->gpio_base; in brcmstb_gpio_irq_bank_handler()
283 if (offset >= bank->width) in brcmstb_gpio_irq_bank_handler()
284 dev_warn(&priv->pdev->dev, in brcmstb_gpio_irq_bank_handler()
286 bank->id, offset); in brcmstb_gpio_irq_bank_handler()
293 static void brcmstb_gpio_irq_handler(struct irq_desc *desc) in brcmstb_gpio_irq_handler() argument
295 struct brcmstb_gpio_priv *priv = irq_desc_get_handler_data(desc); in brcmstb_gpio_irq_handler()
296 struct irq_chip *chip = irq_desc_get_chip(desc); in brcmstb_gpio_irq_handler()
302 chained_irq_enter(chip, desc); in brcmstb_gpio_irq_handler()
303 list_for_each_entry(bank, &priv->bank_list, node) in brcmstb_gpio_irq_handler()
305 chained_irq_exit(chip, desc); in brcmstb_gpio_irq_handler()
315 list_for_each_entry_reverse(bank, &priv->bank_list, node) { in brcmstb_gpio_hwirq_to_bank()
316 i += bank->gc.ngpio; in brcmstb_gpio_hwirq_to_bank()
334 struct brcmstb_gpio_priv *priv = d->host_data; in brcmstb_gpio_irq_map()
337 struct platform_device *pdev = priv->pdev; in brcmstb_gpio_irq_map()
341 return -EINVAL; in brcmstb_gpio_irq_map()
343 dev_dbg(&pdev->dev, "Mapping irq %d for gpio line %d (bank %d)\n", in brcmstb_gpio_irq_map()
344 irq, (int)hwirq, bank->id); in brcmstb_gpio_irq_map()
345 ret = irq_set_chip_data(irq, &bank->gc); in brcmstb_gpio_irq_map()
350 irq_set_chip_and_handler(irq, &priv->irq_chip, handle_level_irq); in brcmstb_gpio_irq_map()
373 of_property_count_u32_elems(np, "brcm,gpio-bank-widths"); in brcmstb_gpio_sanity_check_banks()
376 dev_err(dev, "Mismatch in banks: res had %d, bank-widths had %d\n", in brcmstb_gpio_sanity_check_banks()
378 return -EINVAL; in brcmstb_gpio_sanity_check_banks()
391 dev_err(&pdev->dev, "called %s without drvdata!\n", __func__); in brcmstb_gpio_remove()
392 return -EFAULT; in brcmstb_gpio_remove()
395 if (priv->parent_irq > 0) in brcmstb_gpio_remove()
396 irq_set_chained_handler_and_data(priv->parent_irq, NULL, NULL); in brcmstb_gpio_remove()
399 if (priv->irq_domain) { in brcmstb_gpio_remove()
400 for (offset = 0; offset < priv->num_gpios; offset++) { in brcmstb_gpio_remove()
401 virq = irq_find_mapping(priv->irq_domain, offset); in brcmstb_gpio_remove()
404 irq_domain_remove(priv->irq_domain); in brcmstb_gpio_remove()
411 list_for_each_entry(bank, &priv->bank_list, node) in brcmstb_gpio_remove()
412 gpiochip_remove(&bank->gc); in brcmstb_gpio_remove()
424 if (gc->of_gpio_n_cells != 2) { in brcmstb_gpio_of_xlate()
426 return -EINVAL; in brcmstb_gpio_of_xlate()
429 if (WARN_ON(gpiospec->args_count < gc->of_gpio_n_cells)) in brcmstb_gpio_of_xlate()
430 return -EINVAL; in brcmstb_gpio_of_xlate()
432 offset = gpiospec->args[0] - (gc->base - priv->gpio_base); in brcmstb_gpio_of_xlate()
433 if (offset >= gc->ngpio || offset < 0) in brcmstb_gpio_of_xlate()
434 return -EINVAL; in brcmstb_gpio_of_xlate()
436 if (unlikely(offset >= bank->width)) { in brcmstb_gpio_of_xlate()
437 dev_warn_ratelimited(&priv->pdev->dev, in brcmstb_gpio_of_xlate()
439 gpiospec->args[0]); in brcmstb_gpio_of_xlate()
443 *flags = gpiospec->args[1]; in brcmstb_gpio_of_xlate()
448 /* priv->parent_irq and priv->num_gpios must be set before calling */
452 struct device *dev = &pdev->dev; in brcmstb_gpio_irq_setup()
453 struct device_node *np = dev->of_node; in brcmstb_gpio_irq_setup()
456 priv->irq_domain = in brcmstb_gpio_irq_setup()
457 irq_domain_add_linear(np, priv->num_gpios, in brcmstb_gpio_irq_setup()
460 if (!priv->irq_domain) { in brcmstb_gpio_irq_setup()
462 return -ENXIO; in brcmstb_gpio_irq_setup()
465 if (of_property_read_bool(np, "wakeup-source")) { in brcmstb_gpio_irq_setup()
466 priv->parent_wake_irq = platform_get_irq(pdev, 1); in brcmstb_gpio_irq_setup()
467 if (priv->parent_wake_irq < 0) { in brcmstb_gpio_irq_setup()
468 priv->parent_wake_irq = 0; in brcmstb_gpio_irq_setup()
470 "Couldn't get wake IRQ - GPIOs will not be able to wake from sleep"); in brcmstb_gpio_irq_setup()
473 * Set wakeup capability so we can process boot-time in brcmstb_gpio_irq_setup()
478 err = devm_request_irq(dev, priv->parent_wake_irq, in brcmstb_gpio_irq_setup()
481 "brcmstb-gpio-wake", priv); in brcmstb_gpio_irq_setup()
490 priv->irq_chip.name = dev_name(dev); in brcmstb_gpio_irq_setup()
491 priv->irq_chip.irq_disable = brcmstb_gpio_irq_mask; in brcmstb_gpio_irq_setup()
492 priv->irq_chip.irq_mask = brcmstb_gpio_irq_mask; in brcmstb_gpio_irq_setup()
493 priv->irq_chip.irq_unmask = brcmstb_gpio_irq_unmask; in brcmstb_gpio_irq_setup()
494 priv->irq_chip.irq_ack = brcmstb_gpio_irq_ack; in brcmstb_gpio_irq_setup()
495 priv->irq_chip.irq_set_type = brcmstb_gpio_irq_set_type; in brcmstb_gpio_irq_setup()
497 if (priv->parent_wake_irq) in brcmstb_gpio_irq_setup()
498 priv->irq_chip.irq_set_wake = brcmstb_gpio_irq_set_wake; in brcmstb_gpio_irq_setup()
500 irq_set_chained_handler_and_data(priv->parent_irq, in brcmstb_gpio_irq_setup()
502 irq_set_status_flags(priv->parent_irq, IRQ_DISABLE_UNLAZY); in brcmstb_gpio_irq_setup()
507 irq_domain_remove(priv->irq_domain); in brcmstb_gpio_irq_setup()
515 struct gpio_chip *gc = &bank->gc; in brcmstb_gpio_bank_save()
519 bank->saved_regs[i] = gc->read_reg(priv->reg_base + in brcmstb_gpio_bank_save()
520 GIO_BANK_OFF(bank->id, i)); in brcmstb_gpio_bank_save()
530 /* disable non-wake interrupt */ in brcmstb_gpio_quiesce()
531 if (priv->parent_irq >= 0) in brcmstb_gpio_quiesce()
532 disable_irq(priv->parent_irq); in brcmstb_gpio_quiesce()
534 list_for_each_entry(bank, &priv->bank_list, node) { in brcmstb_gpio_quiesce()
535 gc = &bank->gc; in brcmstb_gpio_quiesce()
540 /* Unmask GPIOs which have been flagged as wake-up sources */ in brcmstb_gpio_quiesce()
541 if (priv->parent_wake_irq) in brcmstb_gpio_quiesce()
542 imask = bank->wake_active; in brcmstb_gpio_quiesce()
545 gc->write_reg(priv->reg_base + GIO_MASK(bank->id), in brcmstb_gpio_quiesce()
553 brcmstb_gpio_quiesce(&pdev->dev, false); in brcmstb_gpio_shutdown()
560 struct gpio_chip *gc = &bank->gc; in brcmstb_gpio_bank_restore()
564 gc->write_reg(priv->reg_base + GIO_BANK_OFF(bank->id, i), in brcmstb_gpio_bank_restore()
565 bank->saved_regs[i]); in brcmstb_gpio_bank_restore()
580 list_for_each_entry(bank, &priv->bank_list, node) { in brcmstb_gpio_resume()
585 if (priv->parent_wake_irq && need_wakeup_event) in brcmstb_gpio_resume()
588 /* enable non-wake interrupt */ in brcmstb_gpio_resume()
589 if (priv->parent_irq >= 0) in brcmstb_gpio_resume()
590 enable_irq(priv->parent_irq); in brcmstb_gpio_resume()
607 struct device *dev = &pdev->dev; in brcmstb_gpio_probe()
608 struct device_node *np = dev->of_node; in brcmstb_gpio_probe()
623 return -ENOMEM; in brcmstb_gpio_probe()
625 INIT_LIST_HEAD(&priv->bank_list); in brcmstb_gpio_probe()
632 priv->gpio_base = gpio_base; in brcmstb_gpio_probe()
633 priv->reg_base = reg_base; in brcmstb_gpio_probe()
634 priv->pdev = pdev; in brcmstb_gpio_probe()
636 if (of_property_read_bool(np, "interrupt-controller")) { in brcmstb_gpio_probe()
637 priv->parent_irq = platform_get_irq(pdev, 0); in brcmstb_gpio_probe()
638 if (priv->parent_irq <= 0) in brcmstb_gpio_probe()
639 return -ENOENT; in brcmstb_gpio_probe()
641 priv->parent_irq = -ENOENT; in brcmstb_gpio_probe()
645 return -EINVAL; in brcmstb_gpio_probe()
649 * bus endianness (i.e., big-endian CPU + big endian bus ==> native in brcmstb_gpio_probe()
650 * endian I/O). in brcmstb_gpio_probe()
652 * Other architectures (e.g., ARM) either do not support big endian, or in brcmstb_gpio_probe()
653 * else leave I/O in little endian mode. in brcmstb_gpio_probe()
659 of_property_for_each_u32(np, "brcm,gpio-bank-widths", prop, p, in brcmstb_gpio_probe()
678 err = -ENOMEM; in brcmstb_gpio_probe()
682 bank->parent_priv = priv; in brcmstb_gpio_probe()
683 bank->id = num_banks; in brcmstb_gpio_probe()
686 err = -EINVAL; in brcmstb_gpio_probe()
689 bank->width = bank_width; in brcmstb_gpio_probe()
696 gc = &bank->gc; in brcmstb_gpio_probe()
698 reg_base + GIO_DATA(bank->id), in brcmstb_gpio_probe()
700 reg_base + GIO_IODIR(bank->id), flags); in brcmstb_gpio_probe()
706 gc->of_node = np; in brcmstb_gpio_probe()
707 gc->owner = THIS_MODULE; in brcmstb_gpio_probe()
708 gc->label = devm_kasprintf(dev, GFP_KERNEL, "%pOF", dev->of_node); in brcmstb_gpio_probe()
709 if (!gc->label) { in brcmstb_gpio_probe()
710 err = -ENOMEM; in brcmstb_gpio_probe()
713 gc->base = gpio_base; in brcmstb_gpio_probe()
714 gc->of_gpio_n_cells = 2; in brcmstb_gpio_probe()
715 gc->of_xlate = brcmstb_gpio_of_xlate; in brcmstb_gpio_probe()
717 gc->ngpio = MAX_GPIO_PER_BANK; in brcmstb_gpio_probe()
718 gc->offset = bank->id * MAX_GPIO_PER_BANK; in brcmstb_gpio_probe()
719 if (priv->parent_irq > 0) in brcmstb_gpio_probe()
720 gc->to_irq = brcmstb_gpio_to_irq; in brcmstb_gpio_probe()
727 gc->write_reg(reg_base + GIO_MASK(bank->id), 0); in brcmstb_gpio_probe()
732 bank->id); in brcmstb_gpio_probe()
735 gpio_base += gc->ngpio; in brcmstb_gpio_probe()
737 dev_dbg(dev, "bank=%d, base=%d, ngpio=%d, width=%d\n", bank->id, in brcmstb_gpio_probe()
738 gc->base, gc->ngpio, bank->width); in brcmstb_gpio_probe()
741 list_add(&bank->node, &priv->bank_list); in brcmstb_gpio_probe()
746 priv->num_gpios = gpio_base - priv->gpio_base; in brcmstb_gpio_probe()
747 if (priv->parent_irq > 0) { in brcmstb_gpio_probe()
753 if (priv->parent_wake_irq && need_wakeup_event) in brcmstb_gpio_probe()
764 { .compatible = "brcm,brcmstb-gpio" },
772 .name = "brcmstb-gpio",