15ad36c5fSErik Gilling /* 25ad36c5fSErik Gilling * Copyright (C) 2010 Google, Inc. 35ad36c5fSErik Gilling * 45ad36c5fSErik Gilling * Author: 55ad36c5fSErik Gilling * Colin Cross <ccross@google.com> 65ad36c5fSErik Gilling * 7460907bcSGary King * Copyright (C) 2010, NVIDIA Corporation 8460907bcSGary King * 95ad36c5fSErik Gilling * This software is licensed under the terms of the GNU General Public 105ad36c5fSErik Gilling * License version 2, as published by the Free Software Foundation, and 115ad36c5fSErik Gilling * may be copied, distributed, and modified under those terms. 125ad36c5fSErik Gilling * 135ad36c5fSErik Gilling * This program is distributed in the hope that it will be useful, 145ad36c5fSErik Gilling * but WITHOUT ANY WARRANTY; without even the implied warranty of 155ad36c5fSErik Gilling * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 165ad36c5fSErik Gilling * GNU General Public License for more details. 175ad36c5fSErik Gilling * 185ad36c5fSErik Gilling */ 195ad36c5fSErik Gilling 205ad36c5fSErik Gilling #include <linux/kernel.h> 215ad36c5fSErik Gilling #include <linux/init.h> 225ad36c5fSErik Gilling #include <linux/interrupt.h> 235ad36c5fSErik Gilling #include <linux/irq.h> 245ad36c5fSErik Gilling #include <linux/io.h> 255ad36c5fSErik Gilling 265ad36c5fSErik Gilling #include <asm/hardware/gic.h> 275ad36c5fSErik Gilling 285ad36c5fSErik Gilling #include <mach/iomap.h> 295ad36c5fSErik Gilling 305ad36c5fSErik Gilling #include "board.h" 315ad36c5fSErik Gilling 32460907bcSGary King #define INT_SYS_NR (INT_GPIO_BASE - INT_PRI_BASE) 33460907bcSGary King #define INT_SYS_SZ (INT_SEC_BASE - INT_PRI_BASE) 34460907bcSGary King #define PPI_NR ((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ) 35460907bcSGary King 36460907bcSGary King #define APBDMA_IRQ_STA_CPU 0x14 37460907bcSGary King #define APBDMA_IRQ_MASK_SET 0x20 38460907bcSGary King #define APBDMA_IRQ_MASK_CLR 0x24 39460907bcSGary King 40460907bcSGary King #define ICTLR_CPU_IER 0x20 41460907bcSGary King #define ICTLR_CPU_IER_SET 0x24 42460907bcSGary King #define ICTLR_CPU_IER_CLR 0x28 43460907bcSGary King #define ICTLR_CPU_IEP_CLASS 0x2c 44460907bcSGary King #define ICTLR_COP_IER 0x30 45460907bcSGary King #define ICTLR_COP_IER_SET 0x34 46460907bcSGary King #define ICTLR_COP_IER_CLR 0x38 47460907bcSGary King #define ICTLR_COP_IEP_CLASS 0x3c 48460907bcSGary King 49460907bcSGary King static void (*gic_mask_irq)(unsigned int irq); 50460907bcSGary King static void (*gic_unmask_irq)(unsigned int irq); 51460907bcSGary King 52460907bcSGary King #define irq_to_ictlr(irq) (((irq)-32) >> 5) 53460907bcSGary King static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE); 54460907bcSGary King #define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr)*0x100) 55460907bcSGary King 56460907bcSGary King static void tegra_mask(unsigned int irq) 57460907bcSGary King { 58460907bcSGary King void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq)); 59460907bcSGary King gic_mask_irq(irq); 60460907bcSGary King writel(1<<(irq&31), addr+ICTLR_CPU_IER_CLR); 61460907bcSGary King } 62460907bcSGary King 63460907bcSGary King static void tegra_unmask(unsigned int irq) 64460907bcSGary King { 65460907bcSGary King void __iomem *addr = ictlr_to_virt(irq_to_ictlr(irq)); 66460907bcSGary King gic_unmask_irq(irq); 67460907bcSGary King writel(1<<(irq&31), addr+ICTLR_CPU_IER_SET); 68460907bcSGary King } 69460907bcSGary King 70460907bcSGary King #ifdef CONFIG_PM 71460907bcSGary King 72460907bcSGary King static int tegra_set_wake(unsigned int irq, unsigned int on) 73460907bcSGary King { 74460907bcSGary King return 0; 75460907bcSGary King } 76460907bcSGary King #endif 77460907bcSGary King 78460907bcSGary King static struct irq_chip tegra_irq = { 79460907bcSGary King .name = "PPI", 80460907bcSGary King .mask = tegra_mask, 81460907bcSGary King .unmask = tegra_unmask, 82460907bcSGary King #ifdef CONFIG_PM 83460907bcSGary King .set_wake = tegra_set_wake, 84460907bcSGary King #endif 85460907bcSGary King }; 86460907bcSGary King 875ad36c5fSErik Gilling void __init tegra_init_irq(void) 885ad36c5fSErik Gilling { 89460907bcSGary King struct irq_chip *gic; 90460907bcSGary King unsigned int i; 91460907bcSGary King 92460907bcSGary King for (i = 0; i < PPI_NR; i++) { 93460907bcSGary King writel(~0, ictlr_to_virt(i) + ICTLR_CPU_IER_CLR); 94460907bcSGary King writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS); 95460907bcSGary King } 96460907bcSGary King 97*b580b899SRussell King gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 98*b580b899SRussell King IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); 99460907bcSGary King 100460907bcSGary King gic = get_irq_chip(29); 101460907bcSGary King gic_unmask_irq = gic->unmask; 102460907bcSGary King gic_mask_irq = gic->mask; 103460907bcSGary King tegra_irq.ack = gic->ack; 104460907bcSGary King #ifdef CONFIG_SMP 105460907bcSGary King tegra_irq.set_affinity = gic->set_affinity; 106460907bcSGary King #endif 107460907bcSGary King 108460907bcSGary King for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { 109460907bcSGary King set_irq_chip(i, &tegra_irq); 110460907bcSGary King set_irq_handler(i, handle_level_irq); 111460907bcSGary King set_irq_flags(i, IRQF_VALID); 1125ad36c5fSErik Gilling } 113460907bcSGary King } 114460907bcSGary King 115460907bcSGary King #ifdef CONFIG_PM 116460907bcSGary King static u32 cop_ier[PPI_NR]; 117460907bcSGary King static u32 cpu_ier[PPI_NR]; 118460907bcSGary King static u32 cpu_iep[PPI_NR]; 119460907bcSGary King 120460907bcSGary King void tegra_irq_suspend(void) 121460907bcSGary King { 122460907bcSGary King unsigned long flags; 123460907bcSGary King int i; 124460907bcSGary King 125460907bcSGary King for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { 126460907bcSGary King struct irq_desc *desc = irq_to_desc(i); 127460907bcSGary King if (!desc) 128460907bcSGary King continue; 129460907bcSGary King if (desc->status & IRQ_WAKEUP) { 130460907bcSGary King pr_debug("irq %d is wakeup\n", i); 131460907bcSGary King continue; 132460907bcSGary King } 133460907bcSGary King disable_irq(i); 134460907bcSGary King } 135460907bcSGary King 136460907bcSGary King local_irq_save(flags); 137460907bcSGary King for (i = 0; i < PPI_NR; i++) { 138460907bcSGary King void __iomem *ictlr = ictlr_to_virt(i); 139460907bcSGary King cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER); 140460907bcSGary King cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS); 141460907bcSGary King cop_ier[i] = readl(ictlr + ICTLR_COP_IER); 142460907bcSGary King writel(~0, ictlr + ICTLR_COP_IER_CLR); 143460907bcSGary King } 144460907bcSGary King local_irq_restore(flags); 145460907bcSGary King } 146460907bcSGary King 147460907bcSGary King void tegra_irq_resume(void) 148460907bcSGary King { 149460907bcSGary King unsigned long flags; 150460907bcSGary King int i; 151460907bcSGary King 152460907bcSGary King local_irq_save(flags); 153460907bcSGary King for (i = 0; i < PPI_NR; i++) { 154460907bcSGary King void __iomem *ictlr = ictlr_to_virt(i); 155460907bcSGary King writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS); 156460907bcSGary King writel(~0ul, ictlr + ICTLR_CPU_IER_CLR); 157460907bcSGary King writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET); 158460907bcSGary King writel(0, ictlr + ICTLR_COP_IEP_CLASS); 159460907bcSGary King writel(~0ul, ictlr + ICTLR_COP_IER_CLR); 160460907bcSGary King writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET); 161460907bcSGary King } 162460907bcSGary King local_irq_restore(flags); 163460907bcSGary King 164460907bcSGary King for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { 165460907bcSGary King struct irq_desc *desc = irq_to_desc(i); 166460907bcSGary King if (!desc || (desc->status & IRQ_WAKEUP)) 167460907bcSGary King continue; 168460907bcSGary King enable_irq(i); 169460907bcSGary King } 170460907bcSGary King } 171460907bcSGary King #endif 172