/*
* Atheros AR71xx SoC specific interrupt handling
*
- * Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Atheros' 2.6.15 BSP
{
u32 pending;
- pending = ar71xx_reset_rr(RESET_REG_PCI_INT_STATUS) &
- ar71xx_reset_rr(RESET_REG_PCI_INT_ENABLE);
+ pending = ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_STATUS) &
+ ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_ENABLE);
if (pending & PCI_INT_DEV0)
do_IRQ(AR71XX_PCI_IRQ_DEV0);
else if (pending & PCI_INT_DEV2)
do_IRQ(AR71XX_PCI_IRQ_DEV2);
+ else if (pending & PCI_INT_CORE)
+ do_IRQ(AR71XX_PCI_IRQ_CORE);
+
else
spurious_interrupt();
}
static void ar71xx_pci_irq_unmask(unsigned int irq)
{
irq -= AR71XX_PCI_IRQ_BASE;
- ar71xx_reset_wr(RESET_REG_PCI_INT_ENABLE,
- ar71xx_reset_rr(RESET_REG_PCI_INT_ENABLE) | (1 << irq));
+ ar71xx_reset_wr(AR71XX_RESET_REG_PCI_INT_ENABLE,
+ ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_ENABLE) | (1 << irq));
+
+ /* flush write */
+ ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_ENABLE);
}
static void ar71xx_pci_irq_mask(unsigned int irq)
{
irq -= AR71XX_PCI_IRQ_BASE;
- ar71xx_reset_wr(RESET_REG_PCI_INT_ENABLE,
- ar71xx_reset_rr(RESET_REG_PCI_INT_ENABLE) & ~(1 << irq));
+ ar71xx_reset_wr(AR71XX_RESET_REG_PCI_INT_ENABLE,
+ ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_ENABLE) & ~(1 << irq));
+
+ /* flush write */
+ ar71xx_reset_rr(AR71XX_RESET_REG_PCI_INT_ENABLE);
}
static struct irq_chip ar71xx_pci_irq_chip = {
{
int i;
- ar71xx_reset_wr(RESET_REG_PCI_INT_ENABLE, 0);
- ar71xx_reset_wr(RESET_REG_PCI_INT_STATUS, 0);
+ ar71xx_reset_wr(AR71XX_RESET_REG_PCI_INT_ENABLE, 0);
+ ar71xx_reset_wr(AR71XX_RESET_REG_PCI_INT_STATUS, 0);
for (i = AR71XX_PCI_IRQ_BASE;
i < AR71XX_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++) {
setup_irq(AR71XX_CPU_IRQ_PCI, &ar71xx_pci_irqaction);
}
+static void ar724x_pci_irq_dispatch(void)
+{
+ u32 pending;
+
+ pending = ar724x_pci_rr(AR724X_PCI_REG_INT_STATUS) &
+ ar724x_pci_rr(AR724X_PCI_REG_INT_MASK);
+
+ if (pending & AR724X_PCI_INT_DEV0)
+ do_IRQ(AR71XX_PCI_IRQ_DEV0);
+
+ else
+ spurious_interrupt();
+}
+
+static void ar724x_pci_irq_unmask(unsigned int irq)
+{
+ switch (irq) {
+ case AR71XX_PCI_IRQ_DEV0:
+ irq -= AR71XX_PCI_IRQ_BASE;
+ ar724x_pci_wr(AR724X_PCI_REG_INT_MASK,
+ ar724x_pci_rr(AR724X_PCI_REG_INT_MASK) |
+ AR724X_PCI_INT_DEV0);
+ /* flush write */
+ ar724x_pci_rr(AR724X_PCI_REG_INT_MASK);
+ }
+}
+
+static void ar724x_pci_irq_mask(unsigned int irq)
+{
+ switch (irq) {
+ case AR71XX_PCI_IRQ_DEV0:
+ irq -= AR71XX_PCI_IRQ_BASE;
+ ar724x_pci_wr(AR724X_PCI_REG_INT_MASK,
+ ar724x_pci_rr(AR724X_PCI_REG_INT_MASK) &
+ ~AR724X_PCI_INT_DEV0);
+ /* flush write */
+ ar724x_pci_rr(AR724X_PCI_REG_INT_MASK);
+
+ ar724x_pci_wr(AR724X_PCI_REG_INT_STATUS,
+ ar724x_pci_rr(AR724X_PCI_REG_INT_STATUS) |
+ AR724X_PCI_INT_DEV0);
+ /* flush write */
+ ar724x_pci_rr(AR724X_PCI_REG_INT_STATUS);
+ }
+}
+
+static struct irq_chip ar724x_pci_irq_chip = {
+ .name = "AR724X PCI ",
+ .mask = ar724x_pci_irq_mask,
+ .unmask = ar724x_pci_irq_unmask,
+ .mask_ack = ar724x_pci_irq_mask,
+};
+
+static struct irqaction ar724x_pci_irqaction = {
+ .handler = no_action,
+ .name = "cascade [AR724X PCI]",
+};
+
+static void __init ar724x_pci_irq_init(void)
+{
+ int i;
+
+ ar724x_pci_wr(AR724X_PCI_REG_INT_MASK, 0);
+ ar724x_pci_wr(AR724X_PCI_REG_INT_STATUS, 0);
+
+ for (i = AR71XX_PCI_IRQ_BASE;
+ i < AR71XX_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++) {
+ irq_desc[i].status = IRQ_DISABLED;
+ set_irq_chip_and_handler(i, &ar724x_pci_irq_chip,
+ handle_level_irq);
+ }
+
+ setup_irq(AR71XX_CPU_IRQ_PCI, &ar724x_pci_irqaction);
+}
#endif /* CONFIG_PCI */
static void ar71xx_gpio_irq_dispatch(void)
irq -= AR71XX_GPIO_IRQ_BASE;
ar71xx_gpio_wr(GPIO_REG_INT_ENABLE,
ar71xx_gpio_rr(GPIO_REG_INT_ENABLE) | (1 << irq));
+
+ /* flush write */
+ ar71xx_gpio_rr(GPIO_REG_INT_ENABLE);
}
static void ar71xx_gpio_irq_mask(unsigned int irq)
irq -= AR71XX_GPIO_IRQ_BASE;
ar71xx_gpio_wr(GPIO_REG_INT_ENABLE,
ar71xx_gpio_rr(GPIO_REG_INT_ENABLE) & ~(1 << irq));
+
+ /* flush write */
+ ar71xx_gpio_rr(GPIO_REG_INT_ENABLE);
}
#if 0
{
u32 pending;
- pending = ar71xx_reset_rr(RESET_REG_MISC_INT_STATUS)
- & ar71xx_reset_rr(RESET_REG_MISC_INT_ENABLE);
+ pending = ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_STATUS)
+ & ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE);
if (pending & MISC_INT_UART)
do_IRQ(AR71XX_MISC_IRQ_UART);
static void ar71xx_misc_irq_unmask(unsigned int irq)
{
irq -= AR71XX_MISC_IRQ_BASE;
- ar71xx_reset_wr(RESET_REG_MISC_INT_ENABLE,
- ar71xx_reset_rr(RESET_REG_MISC_INT_ENABLE) | (1 << irq));
+ ar71xx_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE,
+ ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE) | (1 << irq));
+
+ /* flush write */
+ ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE);
+}
+
+static void ar724x_misc_irq_unmask(unsigned int irq)
+{
+ irq -= AR71XX_MISC_IRQ_BASE;
+ ar71xx_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE,
+ ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE) | (1 << irq));
+
+ /* flush write */
+ ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+ ar71xx_reset_wr(AR71XX_RESET_REG_MISC_INT_STATUS,
+ ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_STATUS) & ~(1 << irq));
+
+ /* flush write */
+ ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_STATUS);
}
static void ar71xx_misc_irq_mask(unsigned int irq)
{
irq -= AR71XX_MISC_IRQ_BASE;
- ar71xx_reset_wr(RESET_REG_MISC_INT_ENABLE,
- ar71xx_reset_rr(RESET_REG_MISC_INT_ENABLE) & ~(1 << irq));
+ ar71xx_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE,
+ ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE) & ~(1 << irq));
+
+ /* flush write */
+ ar71xx_reset_rr(AR71XX_RESET_REG_MISC_INT_ENABLE);
}
struct irq_chip ar71xx_misc_irq_chip = {
{
int i;
- ar71xx_reset_wr(RESET_REG_MISC_INT_ENABLE, 0);
- ar71xx_reset_wr(RESET_REG_MISC_INT_STATUS, 0);
+ ar71xx_reset_wr(AR71XX_RESET_REG_MISC_INT_ENABLE, 0);
+ ar71xx_reset_wr(AR71XX_RESET_REG_MISC_INT_STATUS, 0);
+
+ if (ar71xx_soc == AR71XX_SOC_AR7240)
+ ar71xx_misc_irq_chip.unmask = ar724x_misc_irq_unmask;
for (i = AR71XX_MISC_IRQ_BASE;
i < AR71XX_MISC_IRQ_BASE + AR71XX_MISC_IRQ_COUNT; i++) {
setup_irq(AR71XX_CPU_IRQ_MISC, &ar71xx_misc_irqaction);
}
+static void ar913x_wmac_irq_dispatch(void)
+{
+ do_IRQ(AR71XX_CPU_IRQ_WMAC);
+}
+
+static void (* ar71xx_ip2_irq_handler)(void) = spurious_interrupt;
+
asmlinkage void plat_irq_dispatch(void)
{
unsigned long pending;
if (pending & STATUSF_IP7)
do_IRQ(AR71XX_CPU_IRQ_TIMER);
-#ifdef CONFIG_PCI
else if (pending & STATUSF_IP2)
- ar71xx_pci_irq_dispatch();
-#endif
+ ar71xx_ip2_irq_handler();
else if (pending & STATUSF_IP4)
do_IRQ(AR71XX_CPU_IRQ_GE0);
ar71xx_misc_irq_init();
+ switch (ar71xx_soc) {
+ case AR71XX_SOC_AR7130:
+ case AR71XX_SOC_AR7141:
+ case AR71XX_SOC_AR7161:
#ifdef CONFIG_PCI
- ar71xx_pci_irq_init();
+ ar71xx_pci_irq_init();
+ ar71xx_ip2_irq_handler = ar71xx_pci_irq_dispatch;
#endif
+ break;
+ case AR71XX_SOC_AR7240:
+#ifdef CONFIG_PCI
+ ar724x_pci_irq_init();
+ ar71xx_ip2_irq_handler = ar724x_pci_irq_dispatch;
+#endif
+ break;
+ case AR71XX_SOC_AR9130:
+ case AR71XX_SOC_AR9132:
+ ar71xx_ip2_irq_handler = ar913x_wmac_irq_dispatch;
+ break;
+ default:
+ BUG();
+ }
ar71xx_gpio_irq_init();
}