^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Atheros AR71xx/AR724x/AR913x MISC interrupt controller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2015 Alban Bedel <albeu@free.fr>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/irqchip.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/irqchip/chained_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define AR71XX_RESET_REG_MISC_INT_STATUS 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define AR71XX_RESET_REG_MISC_INT_ENABLE 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define ATH79_MISC_IRQ_COUNT 32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define ATH79_MISC_PERF_IRQ 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static int ath79_perfcount_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) int get_c0_perfcount_int(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return ath79_perfcount_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static void ath79_misc_irq_handler(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct irq_domain *domain = irq_desc_get_handler_data(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct irq_chip *chip = irq_desc_get_chip(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) void __iomem *base = domain->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) u32 pending;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) chained_irq_enter(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) pending = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) if (!pending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) spurious_interrupt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) chained_irq_exit(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) while (pending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) int bit = __ffs(pending);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) generic_handle_irq(irq_linear_revmap(domain, bit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) pending &= ~BIT(bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) chained_irq_exit(chip, desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) static void ar71xx_misc_irq_unmask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) void __iomem *base = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned int irq = d->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u32 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) __raw_writel(t | BIT(irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* flush write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static void ar71xx_misc_irq_mask(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) void __iomem *base = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned int irq = d->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) u32 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) __raw_writel(t & ~BIT(irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) /* flush write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) static void ar724x_misc_irq_ack(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) void __iomem *base = irq_data_get_irq_chip_data(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned int irq = d->hwirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) u32 t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) __raw_writel(t & ~BIT(irq), base + AR71XX_RESET_REG_MISC_INT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* flush write */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static struct irq_chip ath79_misc_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .name = "MISC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .irq_unmask = ar71xx_misc_irq_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .irq_mask = ar71xx_misc_irq_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static int misc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) irq_set_chip_and_handler(irq, &ath79_misc_irq_chip, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) irq_set_chip_data(irq, d->host_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static const struct irq_domain_ops misc_irq_domain_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) .xlate = irq_domain_xlate_onecell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) .map = misc_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static void __init ath79_misc_intc_domain_init(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct irq_domain *domain, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) void __iomem *base = domain->host_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) ath79_perfcount_irq = irq_create_mapping(domain, ATH79_MISC_PERF_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* Disable and clear all interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) irq_set_chained_handler_and_data(irq, ath79_misc_irq_handler, domain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static int __init ath79_misc_intc_of_init(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct device_node *node, struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) struct irq_domain *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) irq = irq_of_parse_and_map(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (!irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) pr_err("Failed to get MISC IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) base = of_iomap(node, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) if (!base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) pr_err("Failed to get MISC IRQ registers\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) domain = irq_domain_add_linear(node, ATH79_MISC_IRQ_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) &misc_irq_domain_ops, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (!domain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) pr_err("Failed to add MISC irqdomain\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) ath79_misc_intc_domain_init(domain, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int __init ar7100_misc_intc_of_init(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct device_node *node, struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return ath79_misc_intc_of_init(node, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) IRQCHIP_DECLARE(ar7100_misc_intc, "qca,ar7100-misc-intc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ar7100_misc_intc_of_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) static int __init ar7240_misc_intc_of_init(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct device_node *node, struct device_node *parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return ath79_misc_intc_of_init(node, parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) IRQCHIP_DECLARE(ar7240_misc_intc, "qca,ar7240-misc-intc",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ar7240_misc_intc_of_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) void __init ath79_misc_irq_init(void __iomem *regs, int irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) int irq_base, bool is_ar71xx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct irq_domain *domain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if (is_ar71xx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) domain = irq_domain_add_legacy(NULL, ATH79_MISC_IRQ_COUNT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) irq_base, 0, &misc_irq_domain_ops, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (!domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) panic("Failed to create MISC irqdomain");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) ath79_misc_intc_domain_init(domain, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }