struct bcm_kona_gpio_bank { int id; int irq; /* * Used to keep track of lock/unlock operations for each GPIO in the * bank. * * All GPIOs are locked by default (see bcm_kona_gpio_reset), and the * unlock count for all GPIOs is 0 by default. Each unlock increments * the counter, and each lock decrements the counter. * * The lock function only locks the GPIO once its unlock counter is * down to 0. This is necessary because the GPIO is unlocked in two * places in this driver: once for requested GPIOs, and once for * requested IRQs. Since it is possible for a GPIO to be requested * as both a GPIO and an IRQ, we need to ensure that we don't lock it * too early.
*/
u8 gpio_unlock_count[GPIO_PER_BANK]; /* Used in the interrupt handler */ struct bcm_kona_gpio *kona_gpio;
};
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_IOTR_MASK;
val |= GPIO_GPCTR0_IOTR_CMD_INPUT;
writel(val, reg_base + GPIO_CONTROL(gpio));
return 0;
}
staticint bcm_kona_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
{ struct bcm_kona_gpio *kona_gpio; void __iomem *reg_base; int bank_id = GPIO_BANK(gpio); int bit = GPIO_BIT(gpio);
u32 val, reg_offset;
kona_gpio = gpiochip_get_data(chip);
reg_base = kona_gpio->reg_base; /* debounce must be 1-128ms (or 0) */ if ((debounce > 0 && debounce < 1000) || debounce > 128000) {
dev_err(chip->parent, "Debounce value %u not in range\n",
debounce); return -EINVAL;
}
/* calculate debounce bit value */ if (debounce != 0) { /* Convert to ms */
debounce /= 1000; /* find the MSB */
res = fls(debounce) - 1; /* Check if MSB-1 is set (round up or down) */ if (res > 0 && (debounce & BIT(res - 1)))
res++;
}
/* spin lock for read-modify-write of the GPIO register */
guard(raw_spinlock_irqsave)(&kona_gpio->lock);
val = readl(reg_base + GPIO_CONTROL(gpio));
val &= ~GPIO_GPCTR0_DBR_MASK;
if (debounce == 0) { /* disable debounce */
val &= ~GPIO_GPCTR0_DB_ENABLE_MASK;
} else {
val |= GPIO_GPCTR0_DB_ENABLE_MASK |
(res << GPIO_GPCTR0_DBR_SHIFT);
}
/* * For bank interrupts, we can't use chip_data to store the kona_gpio * pointer, since GIC needs it for its own purposes. Therefore, we get * our pointer from the bank structure.
*/
reg_base = bank->kona_gpio->reg_base;
bank_id = bank->id;
while ((sta = readl(reg_base + GPIO_INT_STATUS(bank_id)) &
(~(readl(reg_base + GPIO_INT_MASK(bank_id)))))) {
for_each_set_bit(bit, &sta, 32) { int hwirq = GPIO_PER_BANK * bank_id + bit; /* * Clear interrupt before handler is called so we don't * miss any interrupt occurred during executing them.
*/
writel(readl(reg_base + GPIO_INT_STATUS(bank_id)) |
BIT(bit), reg_base + GPIO_INT_STATUS(bank_id)); /* Invoke interrupt handler */
generic_handle_domain_irq(bank->kona_gpio->irq_domain,
hwirq);
}
}
/* * We need to unlock the GPIO before any other operations are performed * on the relevant GPIO configuration registers
*/
bcm_kona_gpio_unlock_gpio(kona_gpio, gpio);
/* * This lock class tells lockdep that GPIO irqs are in a different * category than their parents, so it won't report false recursion.
*/ staticstruct lock_class_key gpio_lock_class; staticstruct lock_class_key gpio_request_class;
staticvoid bcm_kona_gpio_reset(struct bcm_kona_gpio *kona_gpio)
{ void __iomem *reg_base; int i;
reg_base = kona_gpio->reg_base; /* disable interrupts and clear status */ for (i = 0; i < kona_gpio->num_bank; i++) { /* Unlock the entire bank first */
bcm_kona_gpio_write_lock_regs(reg_base, i, UNLOCK_CODE);
writel(0xffffffff, reg_base + GPIO_INT_MASK(i));
writel(0xffffffff, reg_base + GPIO_INT_STATUS(i)); /* Now re-lock the bank */
bcm_kona_gpio_write_lock_regs(reg_base, i, LOCK_CODE);
}
}
kona_gpio->reg_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(kona_gpio->reg_base)) {
ret = PTR_ERR(kona_gpio->reg_base); goto err_irq_domain;
}
for (i = 0; i < kona_gpio->num_bank; i++) {
bank = &kona_gpio->banks[i];
bank->id = i;
bank->irq = platform_get_irq(pdev, i);
bank->kona_gpio = kona_gpio; if (bank->irq < 0) {
dev_err(dev, "Couldn't get IRQ for bank %d\n", i);
ret = -ENOENT; goto err_irq_domain;
}
}
dev_info(&pdev->dev, "Setting up Kona GPIO\n");
bcm_kona_gpio_reset(kona_gpio);
ret = devm_gpiochip_add_data(dev, chip, kona_gpio); if (ret < 0) {
dev_err(dev, "Couldn't add GPIO chip -- %d\n", ret); goto err_irq_domain;
} for (i = 0; i < kona_gpio->num_bank; i++) {
bank = &kona_gpio->banks[i];
irq_set_chained_handler_and_data(bank->irq,
bcm_kona_gpio_irq_handler,
bank);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.