Lines Matching +full:x +full:- +full:offset

1 // SPDX-License-Identifier: GPL-2.0-only
3 * arch/arm/mach-tegra/gpio.c
6 * Copyright (c) 2011-2016, NVIDIA CORPORATION. All rights reserved.
27 #define GPIO_BANK(x) ((x) >> 5) argument
28 #define GPIO_PORT(x) (((x) >> 3) & 0x3) argument
29 #define GPIO_BIT(x) ((x) & 0x7) argument
31 #define GPIO_REG(tgi, x) (GPIO_BANK(x) * tgi->soc->bank_stride + \ argument
32 GPIO_PORT(x) * 4)
34 #define GPIO_CNF(t, x) (GPIO_REG(t, x) + 0x00) argument
35 #define GPIO_OE(t, x) (GPIO_REG(t, x) + 0x10) argument
36 #define GPIO_OUT(t, x) (GPIO_REG(t, x) + 0X20) argument
37 #define GPIO_IN(t, x) (GPIO_REG(t, x) + 0x30) argument
38 #define GPIO_INT_STA(t, x) (GPIO_REG(t, x) + 0x40) argument
39 #define GPIO_INT_ENB(t, x) (GPIO_REG(t, x) + 0x50) argument
40 #define GPIO_INT_LVL(t, x) (GPIO_REG(t, x) + 0x60) argument
41 #define GPIO_INT_CLR(t, x) (GPIO_REG(t, x) + 0x70) argument
42 #define GPIO_DBC_CNT(t, x) (GPIO_REG(t, x) + 0xF0) argument
45 #define GPIO_MSK_CNF(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x00) argument
46 #define GPIO_MSK_OE(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x10) argument
47 #define GPIO_MSK_OUT(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0X20) argument
48 #define GPIO_MSK_DBC_EN(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x30) argument
49 #define GPIO_MSK_INT_STA(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x40) argument
50 #define GPIO_MSK_INT_ENB(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x50) argument
51 #define GPIO_MSK_INT_LVL(t, x) (GPIO_REG(t, x) + t->soc->upper_offset + 0x60) argument
66 * IRQ-core code uses raw locking, and thus, nested locking also
105 writel_relaxed(val, tgi->regs + reg); in tegra_gpio_writel()
110 return readl_relaxed(tgi->regs + reg); in tegra_gpio_readl()
140 static void tegra_gpio_free(struct gpio_chip *chip, unsigned int offset) in tegra_gpio_free() argument
144 pinctrl_gpio_free(chip, offset); in tegra_gpio_free()
145 tegra_gpio_disable(tgi, offset); in tegra_gpio_free()
148 static void tegra_gpio_set(struct gpio_chip *chip, unsigned int offset, in tegra_gpio_set() argument
153 tegra_gpio_mask_write(tgi, GPIO_MSK_OUT(tgi, offset), offset, value); in tegra_gpio_set()
156 static int tegra_gpio_get(struct gpio_chip *chip, unsigned int offset) in tegra_gpio_get() argument
159 unsigned int bval = BIT(GPIO_BIT(offset)); in tegra_gpio_get()
162 if (tegra_gpio_readl(tgi, GPIO_OE(tgi, offset)) & bval) in tegra_gpio_get()
163 return !!(tegra_gpio_readl(tgi, GPIO_OUT(tgi, offset)) & bval); in tegra_gpio_get()
165 return !!(tegra_gpio_readl(tgi, GPIO_IN(tgi, offset)) & bval); in tegra_gpio_get()
169 unsigned int offset) in tegra_gpio_direction_input() argument
174 tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 0); in tegra_gpio_direction_input()
175 tegra_gpio_enable(tgi, offset); in tegra_gpio_direction_input()
177 ret = pinctrl_gpio_direction_input(chip, offset); in tegra_gpio_direction_input()
179 dev_err(tgi->dev, in tegra_gpio_direction_input()
181 chip->base + offset, ret); in tegra_gpio_direction_input()
187 unsigned int offset, in tegra_gpio_direction_output() argument
193 tegra_gpio_set(chip, offset, value); in tegra_gpio_direction_output()
194 tegra_gpio_mask_write(tgi, GPIO_MSK_OE(tgi, offset), offset, 1); in tegra_gpio_direction_output()
195 tegra_gpio_enable(tgi, offset); in tegra_gpio_direction_output()
197 ret = pinctrl_gpio_direction_output(chip, offset); in tegra_gpio_direction_output()
199 dev_err(tgi->dev, in tegra_gpio_direction_output()
201 chip->base + offset, ret); in tegra_gpio_direction_output()
207 unsigned int offset) in tegra_gpio_get_direction() argument
210 u32 pin_mask = BIT(GPIO_BIT(offset)); in tegra_gpio_get_direction()
213 cnf = tegra_gpio_readl(tgi, GPIO_CNF(tgi, offset)); in tegra_gpio_get_direction()
215 return -EINVAL; in tegra_gpio_get_direction()
217 oe = tegra_gpio_readl(tgi, GPIO_OE(tgi, offset)); in tegra_gpio_get_direction()
225 static int tegra_gpio_set_debounce(struct gpio_chip *chip, unsigned int offset, in tegra_gpio_set_debounce() argument
229 struct tegra_gpio_bank *bank = &tgi->bank_info[GPIO_BANK(offset)]; in tegra_gpio_set_debounce()
235 tegra_gpio_mask_write(tgi, GPIO_MSK_DBC_EN(tgi, offset), in tegra_gpio_set_debounce()
236 offset, 0); in tegra_gpio_set_debounce()
241 port = GPIO_PORT(offset); in tegra_gpio_set_debounce()
246 spin_lock_irqsave(&bank->dbc_lock[port], flags); in tegra_gpio_set_debounce()
247 if (bank->dbc_cnt[port] < debounce_ms) { in tegra_gpio_set_debounce()
248 tegra_gpio_writel(tgi, debounce_ms, GPIO_DBC_CNT(tgi, offset)); in tegra_gpio_set_debounce()
249 bank->dbc_cnt[port] = debounce_ms; in tegra_gpio_set_debounce()
251 spin_unlock_irqrestore(&bank->dbc_lock[port], flags); in tegra_gpio_set_debounce()
253 tegra_gpio_mask_write(tgi, GPIO_MSK_DBC_EN(tgi, offset), offset, 1); in tegra_gpio_set_debounce()
258 static int tegra_gpio_set_config(struct gpio_chip *chip, unsigned int offset, in tegra_gpio_set_config() argument
264 return -ENOTSUPP; in tegra_gpio_set_config()
267 return tegra_gpio_set_debounce(chip, offset, debounce); in tegra_gpio_set_config()
274 unsigned int gpio = d->hwirq; in tegra_gpio_irq_ack()
283 unsigned int gpio = d->hwirq; in tegra_gpio_irq_mask()
293 unsigned int gpio = d->hwirq; in tegra_gpio_irq_unmask()
301 unsigned int gpio = d->hwirq, port = GPIO_PORT(gpio), lvl_type; in tegra_gpio_irq_set_type()
309 bank = &tgi->bank_info[GPIO_BANK(d->hwirq)]; in tegra_gpio_irq_set_type()
333 return -EINVAL; in tegra_gpio_irq_set_type()
336 raw_spin_lock_irqsave(&bank->lvl_lock[port], flags); in tegra_gpio_irq_set_type()
343 raw_spin_unlock_irqrestore(&bank->lvl_lock[port], flags); in tegra_gpio_irq_set_type()
348 ret = gpiochip_lock_as_irq(&tgi->gc, gpio); in tegra_gpio_irq_set_type()
350 dev_err(tgi->dev, in tegra_gpio_irq_set_type()
361 if (d->parent_data) in tegra_gpio_irq_set_type()
371 unsigned int gpio = d->hwirq; in tegra_gpio_irq_shutdown()
374 gpiochip_unlock_as_irq(&tgi->gc, gpio); in tegra_gpio_irq_shutdown()
381 struct irq_domain *domain = tgi->gc.irq.domain; in tegra_gpio_irq_handler()
389 for (i = 0; i < tgi->bank_count; i++) { in tegra_gpio_irq_handler()
390 if (tgi->irqs[i] == irq) { in tegra_gpio_irq_handler()
391 bank = &tgi->bank_info[i]; in tegra_gpio_irq_handler()
402 gpio = tegra_gpio_compose(bank->bank, port, 0); in tegra_gpio_irq_handler()
437 *parent_hwirq = chip->irq.child_offset_to_irq(chip, hwirq); in tegra_gpio_child_to_parent_hwirq()
448 struct irq_fwspec *fwspec = &gfwspec->fwspec; in tegra_gpio_populate_parent_fwspec()
450 fwspec->fwnode = chip->irq.parent_domain->fwnode; in tegra_gpio_populate_parent_fwspec()
451 fwspec->param_count = 3; in tegra_gpio_populate_parent_fwspec()
452 fwspec->param[0] = 0; in tegra_gpio_populate_parent_fwspec()
453 fwspec->param[1] = parent_hwirq; in tegra_gpio_populate_parent_fwspec()
454 fwspec->param[2] = parent_type; in tegra_gpio_populate_parent_fwspec()
465 for (b = 0; b < tgi->bank_count; b++) { in tegra_gpio_resume()
466 struct tegra_gpio_bank *bank = &tgi->bank_info[b]; in tegra_gpio_resume()
468 for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { in tegra_gpio_resume()
471 tegra_gpio_writel(tgi, bank->cnf[p], in tegra_gpio_resume()
474 if (tgi->soc->debounce_supported) { in tegra_gpio_resume()
475 tegra_gpio_writel(tgi, bank->dbc_cnt[p], in tegra_gpio_resume()
477 tegra_gpio_writel(tgi, bank->dbc_enb[p], in tegra_gpio_resume()
481 tegra_gpio_writel(tgi, bank->out[p], in tegra_gpio_resume()
483 tegra_gpio_writel(tgi, bank->oe[p], in tegra_gpio_resume()
485 tegra_gpio_writel(tgi, bank->int_lvl[p], in tegra_gpio_resume()
487 tegra_gpio_writel(tgi, bank->int_enb[p], in tegra_gpio_resume()
500 for (b = 0; b < tgi->bank_count; b++) { in tegra_gpio_suspend()
501 struct tegra_gpio_bank *bank = &tgi->bank_info[b]; in tegra_gpio_suspend()
503 for (p = 0; p < ARRAY_SIZE(bank->oe); p++) { in tegra_gpio_suspend()
506 bank->cnf[p] = tegra_gpio_readl(tgi, in tegra_gpio_suspend()
508 bank->out[p] = tegra_gpio_readl(tgi, in tegra_gpio_suspend()
510 bank->oe[p] = tegra_gpio_readl(tgi, in tegra_gpio_suspend()
512 if (tgi->soc->debounce_supported) { in tegra_gpio_suspend()
513 bank->dbc_enb[p] = tegra_gpio_readl(tgi, in tegra_gpio_suspend()
515 bank->dbc_enb[p] = (bank->dbc_enb[p] << 8) | in tegra_gpio_suspend()
516 bank->dbc_enb[p]; in tegra_gpio_suspend()
519 bank->int_enb[p] = tegra_gpio_readl(tgi, in tegra_gpio_suspend()
521 bank->int_lvl[p] = tegra_gpio_readl(tgi, in tegra_gpio_suspend()
525 tegra_gpio_writel(tgi, bank->wake_enb[p], in tegra_gpio_suspend()
538 unsigned int gpio = d->hwirq; in tegra_gpio_irq_set_wake()
542 bank = &tgi->bank_info[GPIO_BANK(d->hwirq)]; in tegra_gpio_irq_set_wake()
548 err = irq_set_irq_wake(tgi->irqs[bank->bank], enable); in tegra_gpio_irq_set_wake()
552 if (d->parent_data) { in tegra_gpio_irq_set_wake()
555 irq_set_irq_wake(tgi->irqs[bank->bank], !enable); in tegra_gpio_irq_set_wake()
561 bank->wake_enb[port] |= mask; in tegra_gpio_irq_set_wake()
563 bank->wake_enb[port] &= ~mask; in tegra_gpio_irq_set_wake()
573 if (data->parent_data) in tegra_gpio_irq_set_affinity()
576 return -EINVAL; in tegra_gpio_irq_set_affinity()
584 tegra_gpio_enable(tgi, d->hwirq); in tegra_gpio_irq_request_resources()
586 return gpiochip_reqres_irq(chip, d->hwirq); in tegra_gpio_irq_request_resources()
594 gpiochip_relres_irq(chip, d->hwirq); in tegra_gpio_irq_release_resources()
595 tegra_gpio_enable(tgi, d->hwirq); in tegra_gpio_irq_release_resources()
602 seq_printf(s, dev_name(chip->parent)); in tegra_gpio_irq_print_chip()
642 struct tegra_gpio_info *tgi = dev_get_drvdata(s->private); in tegra_dbg_gpio_show()
645 for (i = 0; i < tgi->bank_count; i++) { in tegra_dbg_gpio_show()
650 "%u:%u %02x %02x %02x %02x %02x %02x %06x\n", in tegra_dbg_gpio_show()
666 debugfs_create_devm_seqfile(tgi->dev, "tegra_gpio", NULL, in tegra_gpio_debuginit()
683 { .compatible = "nvidia,tegra210-pmc", },
696 tgi = devm_kzalloc(&pdev->dev, sizeof(*tgi), GFP_KERNEL); in tegra_gpio_probe()
698 return -ENODEV; in tegra_gpio_probe()
700 tgi->soc = of_device_get_match_data(&pdev->dev); in tegra_gpio_probe()
701 tgi->dev = &pdev->dev; in tegra_gpio_probe()
707 tgi->bank_count = ret; in tegra_gpio_probe()
709 if (!tgi->bank_count) { in tegra_gpio_probe()
710 dev_err(&pdev->dev, "Missing IRQ resource\n"); in tegra_gpio_probe()
711 return -ENODEV; in tegra_gpio_probe()
714 tgi->gc.label = "tegra-gpio"; in tegra_gpio_probe()
715 tgi->gc.request = pinctrl_gpio_request; in tegra_gpio_probe()
716 tgi->gc.free = tegra_gpio_free; in tegra_gpio_probe()
717 tgi->gc.direction_input = tegra_gpio_direction_input; in tegra_gpio_probe()
718 tgi->gc.get = tegra_gpio_get; in tegra_gpio_probe()
719 tgi->gc.direction_output = tegra_gpio_direction_output; in tegra_gpio_probe()
720 tgi->gc.set = tegra_gpio_set; in tegra_gpio_probe()
721 tgi->gc.get_direction = tegra_gpio_get_direction; in tegra_gpio_probe()
722 tgi->gc.base = 0; in tegra_gpio_probe()
723 tgi->gc.ngpio = tgi->bank_count * 32; in tegra_gpio_probe()
724 tgi->gc.parent = &pdev->dev; in tegra_gpio_probe()
728 if (tgi->soc->debounce_supported) in tegra_gpio_probe()
729 tgi->gc.set_config = tegra_gpio_set_config; in tegra_gpio_probe()
731 tgi->bank_info = devm_kcalloc(&pdev->dev, tgi->bank_count, in tegra_gpio_probe()
732 sizeof(*tgi->bank_info), GFP_KERNEL); in tegra_gpio_probe()
733 if (!tgi->bank_info) in tegra_gpio_probe()
734 return -ENOMEM; in tegra_gpio_probe()
736 tgi->irqs = devm_kcalloc(&pdev->dev, tgi->bank_count, in tegra_gpio_probe()
737 sizeof(*tgi->irqs), GFP_KERNEL); in tegra_gpio_probe()
738 if (!tgi->irqs) in tegra_gpio_probe()
739 return -ENOMEM; in tegra_gpio_probe()
741 for (i = 0; i < tgi->bank_count; i++) { in tegra_gpio_probe()
746 bank = &tgi->bank_info[i]; in tegra_gpio_probe()
747 bank->bank = i; in tegra_gpio_probe()
749 tgi->irqs[i] = ret; in tegra_gpio_probe()
752 raw_spin_lock_init(&bank->lvl_lock[j]); in tegra_gpio_probe()
753 spin_lock_init(&bank->dbc_lock[j]); in tegra_gpio_probe()
757 irq = &tgi->gc.irq; in tegra_gpio_probe()
758 irq->fwnode = of_node_to_fwnode(pdev->dev.of_node); in tegra_gpio_probe()
759 irq->child_to_parent_hwirq = tegra_gpio_child_to_parent_hwirq; in tegra_gpio_probe()
760 irq->populate_parent_alloc_arg = tegra_gpio_populate_parent_fwspec; in tegra_gpio_probe()
761 irq->handler = handle_simple_irq; in tegra_gpio_probe()
762 irq->default_type = IRQ_TYPE_NONE; in tegra_gpio_probe()
763 irq->parent_handler = tegra_gpio_irq_handler; in tegra_gpio_probe()
764 irq->parent_handler_data = tgi; in tegra_gpio_probe()
765 irq->num_parents = tgi->bank_count; in tegra_gpio_probe()
766 irq->parents = tgi->irqs; in tegra_gpio_probe()
770 irq->parent_domain = irq_find_host(np); in tegra_gpio_probe()
773 if (!irq->parent_domain) in tegra_gpio_probe()
774 return -EPROBE_DEFER; in tegra_gpio_probe()
781 tgi->regs = devm_platform_ioremap_resource(pdev, 0); in tegra_gpio_probe()
782 if (IS_ERR(tgi->regs)) in tegra_gpio_probe()
783 return PTR_ERR(tgi->regs); in tegra_gpio_probe()
785 for (i = 0; i < tgi->bank_count; i++) { in tegra_gpio_probe()
793 ret = devm_gpiochip_add_data(&pdev->dev, &tgi->gc, tgi); in tegra_gpio_probe()
819 { .compatible = "nvidia,tegra210-gpio", .data = &tegra210_gpio_config },
820 { .compatible = "nvidia,tegra30-gpio", .data = &tegra30_gpio_config },
821 { .compatible = "nvidia,tegra20-gpio", .data = &tegra20_gpio_config },
828 .name = "tegra-gpio",