linux/arch/mips/alchemy/common/irq.c
<<
>>
Prefs
   1/*
   2 * Copyright 2001, 2007-2008 MontaVista Software Inc.
   3 * Author: MontaVista Software, Inc. <source@mvista.com>
   4 *
   5 * Copyright (C) 2007 Ralf Baechle (ralf@linux-mips.org)
   6 *
   7 *  This program is free software; you can redistribute  it and/or modify it
   8 *  under  the terms of  the GNU General  Public License as published by the
   9 *  Free Software Foundation;  either version 2 of the  License, or (at your
  10 *  option) any later version.
  11 *
  12 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
  13 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  14 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  15 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
  16 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  17 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  18 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  19 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  20 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  21 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22 *
  23 *  You should have received a copy of the  GNU General Public License along
  24 *  with this program; if not, write  to the Free Software Foundation, Inc.,
  25 *  675 Mass Ave, Cambridge, MA 02139, USA.
  26 */
  27
  28#include <linux/bitops.h>
  29#include <linux/init.h>
  30#include <linux/interrupt.h>
  31#include <linux/irq.h>
  32#include <linux/slab.h>
  33#include <linux/syscore_ops.h>
  34
  35#include <asm/irq_cpu.h>
  36#include <asm/mipsregs.h>
  37#include <asm/mach-au1x00/au1000.h>
  38#ifdef CONFIG_MIPS_PB1000
  39#include <asm/mach-pb1x00/pb1000.h>
  40#endif
  41
  42/* Interrupt Controller register offsets */
  43#define IC_CFG0RD       0x40
  44#define IC_CFG0SET      0x40
  45#define IC_CFG0CLR      0x44
  46#define IC_CFG1RD       0x48
  47#define IC_CFG1SET      0x48
  48#define IC_CFG1CLR      0x4C
  49#define IC_CFG2RD       0x50
  50#define IC_CFG2SET      0x50
  51#define IC_CFG2CLR      0x54
  52#define IC_REQ0INT      0x54
  53#define IC_SRCRD        0x58
  54#define IC_SRCSET       0x58
  55#define IC_SRCCLR       0x5C
  56#define IC_REQ1INT      0x5C
  57#define IC_ASSIGNRD     0x60
  58#define IC_ASSIGNSET    0x60
  59#define IC_ASSIGNCLR    0x64
  60#define IC_WAKERD       0x68
  61#define IC_WAKESET      0x68
  62#define IC_WAKECLR      0x6C
  63#define IC_MASKRD       0x70
  64#define IC_MASKSET      0x70
  65#define IC_MASKCLR      0x74
  66#define IC_RISINGRD     0x78
  67#define IC_RISINGCLR    0x78
  68#define IC_FALLINGRD    0x7C
  69#define IC_FALLINGCLR   0x7C
  70#define IC_TESTBIT      0x80
  71
  72static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type);
  73
  74/* NOTE on interrupt priorities: The original writers of this code said:
  75 *
  76 * Because of the tight timing of SETUP token to reply transactions,
  77 * the USB devices-side packet complete interrupt (USB_DEV_REQ_INT)
  78 * needs the highest priority.
  79 */
  80
  81/* per-processor fixed function irqs */
  82struct au1xxx_irqmap {
  83        int im_irq;
  84        int im_type;
  85        int im_request;         /* set 1 to get higher priority */
  86};
  87
  88struct au1xxx_irqmap au1000_irqmap[] __initdata = {
  89        { AU1000_UART0_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
  90        { AU1000_UART1_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
  91        { AU1000_UART2_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
  92        { AU1000_UART3_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
  93        { AU1000_SSI0_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
  94        { AU1000_SSI1_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
  95        { AU1000_DMA_INT_BASE,    IRQ_TYPE_LEVEL_HIGH,  0 },
  96        { AU1000_DMA_INT_BASE+1,  IRQ_TYPE_LEVEL_HIGH,  0 },
  97        { AU1000_DMA_INT_BASE+2,  IRQ_TYPE_LEVEL_HIGH,  0 },
  98        { AU1000_DMA_INT_BASE+3,  IRQ_TYPE_LEVEL_HIGH,  0 },
  99        { AU1000_DMA_INT_BASE+4,  IRQ_TYPE_LEVEL_HIGH,  0 },
 100        { AU1000_DMA_INT_BASE+5,  IRQ_TYPE_LEVEL_HIGH,  0 },
 101        { AU1000_DMA_INT_BASE+6,  IRQ_TYPE_LEVEL_HIGH,  0 },
 102        { AU1000_DMA_INT_BASE+7,  IRQ_TYPE_LEVEL_HIGH,  0 },
 103        { AU1000_TOY_INT,         IRQ_TYPE_EDGE_RISING, 0 },
 104        { AU1000_TOY_MATCH0_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 105        { AU1000_TOY_MATCH1_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 106        { AU1000_TOY_MATCH2_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 107        { AU1000_RTC_INT,         IRQ_TYPE_EDGE_RISING, 0 },
 108        { AU1000_RTC_MATCH0_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 109        { AU1000_RTC_MATCH1_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 110        { AU1000_RTC_MATCH2_INT,  IRQ_TYPE_EDGE_RISING, 1 },
 111        { AU1000_IRDA_TX_INT,     IRQ_TYPE_LEVEL_HIGH,  0 },
 112        { AU1000_IRDA_RX_INT,     IRQ_TYPE_LEVEL_HIGH,  0 },
 113        { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH,  1 },
 114        { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
 115        { AU1000_USB_HOST_INT,    IRQ_TYPE_LEVEL_LOW,   0 },
 116        { AU1000_ACSYNC_INT,      IRQ_TYPE_EDGE_RISING, 0 },
 117        { AU1000_MAC0_DMA_INT,    IRQ_TYPE_LEVEL_HIGH,  0 },
 118        { AU1000_MAC1_DMA_INT,    IRQ_TYPE_LEVEL_HIGH,  0 },
 119        { AU1000_AC97C_INT,       IRQ_TYPE_EDGE_RISING, 0 },
 120        { -1, },
 121};
 122
 123struct au1xxx_irqmap au1500_irqmap[] __initdata = {
 124        { AU1500_UART0_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
 125        { AU1500_PCI_INTA,        IRQ_TYPE_LEVEL_LOW,   0 },
 126        { AU1500_PCI_INTB,        IRQ_TYPE_LEVEL_LOW,   0 },
 127        { AU1500_UART3_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
 128        { AU1500_PCI_INTC,        IRQ_TYPE_LEVEL_LOW,   0 },
 129        { AU1500_PCI_INTD,        IRQ_TYPE_LEVEL_LOW,   0 },
 130        { AU1500_DMA_INT_BASE,    IRQ_TYPE_LEVEL_HIGH,  0 },
 131        { AU1500_DMA_INT_BASE+1,  IRQ_TYPE_LEVEL_HIGH,  0 },
 132        { AU1500_DMA_INT_BASE+2,  IRQ_TYPE_LEVEL_HIGH,  0 },
 133        { AU1500_DMA_INT_BASE+3,  IRQ_TYPE_LEVEL_HIGH,  0 },
 134        { AU1500_DMA_INT_BASE+4,  IRQ_TYPE_LEVEL_HIGH,  0 },
 135        { AU1500_DMA_INT_BASE+5,  IRQ_TYPE_LEVEL_HIGH,  0 },
 136        { AU1500_DMA_INT_BASE+6,  IRQ_TYPE_LEVEL_HIGH,  0 },
 137        { AU1500_DMA_INT_BASE+7,  IRQ_TYPE_LEVEL_HIGH,  0 },
 138        { AU1500_TOY_INT,         IRQ_TYPE_EDGE_RISING, 0 },
 139        { AU1500_TOY_MATCH0_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 140        { AU1500_TOY_MATCH1_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 141        { AU1500_TOY_MATCH2_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 142        { AU1500_RTC_INT,         IRQ_TYPE_EDGE_RISING, 0 },
 143        { AU1500_RTC_MATCH0_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 144        { AU1500_RTC_MATCH1_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 145        { AU1500_RTC_MATCH2_INT,  IRQ_TYPE_EDGE_RISING, 1 },
 146        { AU1500_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH,  1 },
 147        { AU1500_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
 148        { AU1500_USB_HOST_INT,    IRQ_TYPE_LEVEL_LOW,   0 },
 149        { AU1500_ACSYNC_INT,      IRQ_TYPE_EDGE_RISING, 0 },
 150        { AU1500_MAC0_DMA_INT,    IRQ_TYPE_LEVEL_HIGH,  0 },
 151        { AU1500_MAC1_DMA_INT,    IRQ_TYPE_LEVEL_HIGH,  0 },
 152        { AU1500_AC97C_INT,       IRQ_TYPE_EDGE_RISING, 0 },
 153        { -1, },
 154};
 155
 156struct au1xxx_irqmap au1100_irqmap[] __initdata = {
 157        { AU1100_UART0_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
 158        { AU1100_UART1_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
 159        { AU1100_SD_INT,          IRQ_TYPE_LEVEL_HIGH,  0 },
 160        { AU1100_UART3_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
 161        { AU1100_SSI0_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
 162        { AU1100_SSI1_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
 163        { AU1100_DMA_INT_BASE,    IRQ_TYPE_LEVEL_HIGH,  0 },
 164        { AU1100_DMA_INT_BASE+1,  IRQ_TYPE_LEVEL_HIGH,  0 },
 165        { AU1100_DMA_INT_BASE+2,  IRQ_TYPE_LEVEL_HIGH,  0 },
 166        { AU1100_DMA_INT_BASE+3,  IRQ_TYPE_LEVEL_HIGH,  0 },
 167        { AU1100_DMA_INT_BASE+4,  IRQ_TYPE_LEVEL_HIGH,  0 },
 168        { AU1100_DMA_INT_BASE+5,  IRQ_TYPE_LEVEL_HIGH,  0 },
 169        { AU1100_DMA_INT_BASE+6,  IRQ_TYPE_LEVEL_HIGH,  0 },
 170        { AU1100_DMA_INT_BASE+7,  IRQ_TYPE_LEVEL_HIGH,  0 },
 171        { AU1100_TOY_INT,         IRQ_TYPE_EDGE_RISING, 0 },
 172        { AU1100_TOY_MATCH0_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 173        { AU1100_TOY_MATCH1_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 174        { AU1100_TOY_MATCH2_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 175        { AU1100_RTC_INT,         IRQ_TYPE_EDGE_RISING, 0 },
 176        { AU1100_RTC_MATCH0_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 177        { AU1100_RTC_MATCH1_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 178        { AU1100_RTC_MATCH2_INT,  IRQ_TYPE_EDGE_RISING, 1 },
 179        { AU1100_IRDA_TX_INT,     IRQ_TYPE_LEVEL_HIGH,  0 },
 180        { AU1100_IRDA_RX_INT,     IRQ_TYPE_LEVEL_HIGH,  0 },
 181        { AU1100_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH,  1 },
 182        { AU1100_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
 183        { AU1100_USB_HOST_INT,    IRQ_TYPE_LEVEL_LOW,   0 },
 184        { AU1100_ACSYNC_INT,      IRQ_TYPE_EDGE_RISING, 0 },
 185        { AU1100_MAC0_DMA_INT,    IRQ_TYPE_LEVEL_HIGH,  0 },
 186        { AU1100_LCD_INT,         IRQ_TYPE_LEVEL_HIGH,  0 },
 187        { AU1100_AC97C_INT,       IRQ_TYPE_EDGE_RISING, 0 },
 188        { -1, },
 189};
 190
 191struct au1xxx_irqmap au1550_irqmap[] __initdata = {
 192        { AU1550_UART0_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
 193        { AU1550_PCI_INTA,        IRQ_TYPE_LEVEL_LOW,   0 },
 194        { AU1550_PCI_INTB,        IRQ_TYPE_LEVEL_LOW,   0 },
 195        { AU1550_DDMA_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
 196        { AU1550_CRYPTO_INT,      IRQ_TYPE_LEVEL_HIGH,  0 },
 197        { AU1550_PCI_INTC,        IRQ_TYPE_LEVEL_LOW,   0 },
 198        { AU1550_PCI_INTD,        IRQ_TYPE_LEVEL_LOW,   0 },
 199        { AU1550_PCI_RST_INT,     IRQ_TYPE_LEVEL_LOW,   0 },
 200        { AU1550_UART1_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
 201        { AU1550_UART3_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
 202        { AU1550_PSC0_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
 203        { AU1550_PSC1_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
 204        { AU1550_PSC2_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
 205        { AU1550_PSC3_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
 206        { AU1550_TOY_INT,         IRQ_TYPE_EDGE_RISING, 0 },
 207        { AU1550_TOY_MATCH0_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 208        { AU1550_TOY_MATCH1_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 209        { AU1550_TOY_MATCH2_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 210        { AU1550_RTC_INT,         IRQ_TYPE_EDGE_RISING, 0 },
 211        { AU1550_RTC_MATCH0_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 212        { AU1550_RTC_MATCH1_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 213        { AU1550_RTC_MATCH2_INT,  IRQ_TYPE_EDGE_RISING, 1 },
 214        { AU1550_NAND_INT,        IRQ_TYPE_EDGE_RISING, 0 },
 215        { AU1550_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH,  1 },
 216        { AU1550_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
 217        { AU1550_USB_HOST_INT,    IRQ_TYPE_LEVEL_LOW,   0 },
 218        { AU1550_MAC0_DMA_INT,    IRQ_TYPE_LEVEL_HIGH,  0 },
 219        { AU1550_MAC1_DMA_INT,    IRQ_TYPE_LEVEL_HIGH,  0 },
 220        { -1, },
 221};
 222
 223struct au1xxx_irqmap au1200_irqmap[] __initdata = {
 224        { AU1200_UART0_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
 225        { AU1200_SWT_INT,         IRQ_TYPE_EDGE_RISING, 0 },
 226        { AU1200_SD_INT,          IRQ_TYPE_LEVEL_HIGH,  0 },
 227        { AU1200_DDMA_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
 228        { AU1200_MAE_BE_INT,      IRQ_TYPE_LEVEL_HIGH,  0 },
 229        { AU1200_UART1_INT,       IRQ_TYPE_LEVEL_HIGH,  0 },
 230        { AU1200_MAE_FE_INT,      IRQ_TYPE_LEVEL_HIGH,  0 },
 231        { AU1200_PSC0_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
 232        { AU1200_PSC1_INT,        IRQ_TYPE_LEVEL_HIGH,  0 },
 233        { AU1200_AES_INT,         IRQ_TYPE_LEVEL_HIGH,  0 },
 234        { AU1200_CAMERA_INT,      IRQ_TYPE_LEVEL_HIGH,  0 },
 235        { AU1200_TOY_INT,         IRQ_TYPE_EDGE_RISING, 0 },
 236        { AU1200_TOY_MATCH0_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 237        { AU1200_TOY_MATCH1_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 238        { AU1200_TOY_MATCH2_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 239        { AU1200_RTC_INT,         IRQ_TYPE_EDGE_RISING, 0 },
 240        { AU1200_RTC_MATCH0_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 241        { AU1200_RTC_MATCH1_INT,  IRQ_TYPE_EDGE_RISING, 0 },
 242        { AU1200_RTC_MATCH2_INT,  IRQ_TYPE_EDGE_RISING, 1 },
 243        { AU1200_NAND_INT,        IRQ_TYPE_EDGE_RISING, 0 },
 244        { AU1200_USB_INT,         IRQ_TYPE_LEVEL_HIGH,  0 },
 245        { AU1200_LCD_INT,         IRQ_TYPE_LEVEL_HIGH,  0 },
 246        { AU1200_MAE_BOTH_INT,    IRQ_TYPE_LEVEL_HIGH,  0 },
 247        { -1, },
 248};
 249
 250
 251static void au1x_ic0_unmask(struct irq_data *d)
 252{
 253        unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
 254        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
 255
 256        __raw_writel(1 << bit, base + IC_MASKSET);
 257        __raw_writel(1 << bit, base + IC_WAKESET);
 258        wmb();
 259}
 260
 261static void au1x_ic1_unmask(struct irq_data *d)
 262{
 263        unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
 264        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
 265
 266        __raw_writel(1 << bit, base + IC_MASKSET);
 267        __raw_writel(1 << bit, base + IC_WAKESET);
 268
 269/* very hacky. does the pb1000 cpld auto-disable this int?
 270 * nowhere in the current kernel sources is it disabled.        --mlau
 271 */
 272#if defined(CONFIG_MIPS_PB1000)
 273        if (d->irq == AU1000_GPIO15_INT)
 274                __raw_writel(0x4000, (void __iomem *)PB1000_MDR); /* enable int */
 275#endif
 276        wmb();
 277}
 278
 279static void au1x_ic0_mask(struct irq_data *d)
 280{
 281        unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
 282        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
 283
 284        __raw_writel(1 << bit, base + IC_MASKCLR);
 285        __raw_writel(1 << bit, base + IC_WAKECLR);
 286        wmb();
 287}
 288
 289static void au1x_ic1_mask(struct irq_data *d)
 290{
 291        unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
 292        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
 293
 294        __raw_writel(1 << bit, base + IC_MASKCLR);
 295        __raw_writel(1 << bit, base + IC_WAKECLR);
 296        wmb();
 297}
 298
 299static void au1x_ic0_ack(struct irq_data *d)
 300{
 301        unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
 302        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
 303
 304        /*
 305         * This may assume that we don't get interrupts from
 306         * both edges at once, or if we do, that we don't care.
 307         */
 308        __raw_writel(1 << bit, base + IC_FALLINGCLR);
 309        __raw_writel(1 << bit, base + IC_RISINGCLR);
 310        wmb();
 311}
 312
 313static void au1x_ic1_ack(struct irq_data *d)
 314{
 315        unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
 316        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
 317
 318        /*
 319         * This may assume that we don't get interrupts from
 320         * both edges at once, or if we do, that we don't care.
 321         */
 322        __raw_writel(1 << bit, base + IC_FALLINGCLR);
 323        __raw_writel(1 << bit, base + IC_RISINGCLR);
 324        wmb();
 325}
 326
 327static void au1x_ic0_maskack(struct irq_data *d)
 328{
 329        unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
 330        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
 331
 332        __raw_writel(1 << bit, base + IC_WAKECLR);
 333        __raw_writel(1 << bit, base + IC_MASKCLR);
 334        __raw_writel(1 << bit, base + IC_RISINGCLR);
 335        __raw_writel(1 << bit, base + IC_FALLINGCLR);
 336        wmb();
 337}
 338
 339static void au1x_ic1_maskack(struct irq_data *d)
 340{
 341        unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
 342        void __iomem *base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
 343
 344        __raw_writel(1 << bit, base + IC_WAKECLR);
 345        __raw_writel(1 << bit, base + IC_MASKCLR);
 346        __raw_writel(1 << bit, base + IC_RISINGCLR);
 347        __raw_writel(1 << bit, base + IC_FALLINGCLR);
 348        wmb();
 349}
 350
 351static int au1x_ic1_setwake(struct irq_data *d, unsigned int on)
 352{
 353        int bit = d->irq - AU1000_INTC1_INT_BASE;
 354        unsigned long wakemsk, flags;
 355
 356        /* only GPIO 0-7 can act as wakeup source.  Fortunately these
 357         * are wired up identically on all supported variants.
 358         */
 359        if ((bit < 0) || (bit > 7))
 360                return -EINVAL;
 361
 362        local_irq_save(flags);
 363        wakemsk = __raw_readl((void __iomem *)SYS_WAKEMSK);
 364        if (on)
 365                wakemsk |= 1 << bit;
 366        else
 367                wakemsk &= ~(1 << bit);
 368        __raw_writel(wakemsk, (void __iomem *)SYS_WAKEMSK);
 369        wmb();
 370        local_irq_restore(flags);
 371
 372        return 0;
 373}
 374
 375/*
 376 * irq_chips for both ICs; this way the mask handlers can be
 377 * as short as possible.
 378 */
 379static struct irq_chip au1x_ic0_chip = {
 380        .name           = "Alchemy-IC0",
 381        .irq_ack        = au1x_ic0_ack,
 382        .irq_mask       = au1x_ic0_mask,
 383        .irq_mask_ack   = au1x_ic0_maskack,
 384        .irq_unmask     = au1x_ic0_unmask,
 385        .irq_set_type   = au1x_ic_settype,
 386};
 387
 388static struct irq_chip au1x_ic1_chip = {
 389        .name           = "Alchemy-IC1",
 390        .irq_ack        = au1x_ic1_ack,
 391        .irq_mask       = au1x_ic1_mask,
 392        .irq_mask_ack   = au1x_ic1_maskack,
 393        .irq_unmask     = au1x_ic1_unmask,
 394        .irq_set_type   = au1x_ic_settype,
 395        .irq_set_wake   = au1x_ic1_setwake,
 396};
 397
 398static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type)
 399{
 400        struct irq_chip *chip;
 401        unsigned int bit, irq = d->irq;
 402        irq_flow_handler_t handler = NULL;
 403        unsigned char *name = NULL;
 404        void __iomem *base;
 405        int ret;
 406
 407        if (irq >= AU1000_INTC1_INT_BASE) {
 408                bit = irq - AU1000_INTC1_INT_BASE;
 409                chip = &au1x_ic1_chip;
 410                base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
 411        } else {
 412                bit = irq - AU1000_INTC0_INT_BASE;
 413                chip = &au1x_ic0_chip;
 414                base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
 415        }
 416
 417        if (bit > 31)
 418                return -EINVAL;
 419
 420        ret = 0;
 421
 422        switch (flow_type) {    /* cfgregs 2:1:0 */
 423        case IRQ_TYPE_EDGE_RISING:      /* 0:0:1 */
 424                __raw_writel(1 << bit, base + IC_CFG2CLR);
 425                __raw_writel(1 << bit, base + IC_CFG1CLR);
 426                __raw_writel(1 << bit, base + IC_CFG0SET);
 427                handler = handle_edge_irq;
 428                name = "riseedge";
 429                break;
 430        case IRQ_TYPE_EDGE_FALLING:     /* 0:1:0 */
 431                __raw_writel(1 << bit, base + IC_CFG2CLR);
 432                __raw_writel(1 << bit, base + IC_CFG1SET);
 433                __raw_writel(1 << bit, base + IC_CFG0CLR);
 434                handler = handle_edge_irq;
 435                name = "falledge";
 436                break;
 437        case IRQ_TYPE_EDGE_BOTH:        /* 0:1:1 */
 438                __raw_writel(1 << bit, base + IC_CFG2CLR);
 439                __raw_writel(1 << bit, base + IC_CFG1SET);
 440                __raw_writel(1 << bit, base + IC_CFG0SET);
 441                handler = handle_edge_irq;
 442                name = "bothedge";
 443                break;
 444        case IRQ_TYPE_LEVEL_HIGH:       /* 1:0:1 */
 445                __raw_writel(1 << bit, base + IC_CFG2SET);
 446                __raw_writel(1 << bit, base + IC_CFG1CLR);
 447                __raw_writel(1 << bit, base + IC_CFG0SET);
 448                handler = handle_level_irq;
 449                name = "hilevel";
 450                break;
 451        case IRQ_TYPE_LEVEL_LOW:        /* 1:1:0 */
 452                __raw_writel(1 << bit, base + IC_CFG2SET);
 453                __raw_writel(1 << bit, base + IC_CFG1SET);
 454                __raw_writel(1 << bit, base + IC_CFG0CLR);
 455                handler = handle_level_irq;
 456                name = "lowlevel";
 457                break;
 458        case IRQ_TYPE_NONE:             /* 0:0:0 */
 459                __raw_writel(1 << bit, base + IC_CFG2CLR);
 460                __raw_writel(1 << bit, base + IC_CFG1CLR);
 461                __raw_writel(1 << bit, base + IC_CFG0CLR);
 462                break;
 463        default:
 464                ret = -EINVAL;
 465        }
 466        __irq_set_chip_handler_name_locked(d->irq, chip, handler, name);
 467
 468        wmb();
 469
 470        return ret;
 471}
 472
 473asmlinkage void plat_irq_dispatch(void)
 474{
 475        unsigned int pending = read_c0_status() & read_c0_cause();
 476        unsigned long s, off;
 477
 478        if (pending & CAUSEF_IP7) {
 479                off = MIPS_CPU_IRQ_BASE + 7;
 480                goto handle;
 481        } else if (pending & CAUSEF_IP2) {
 482                s = KSEG1ADDR(AU1000_IC0_PHYS_ADDR) + IC_REQ0INT;
 483                off = AU1000_INTC0_INT_BASE;
 484        } else if (pending & CAUSEF_IP3) {
 485                s = KSEG1ADDR(AU1000_IC0_PHYS_ADDR) + IC_REQ1INT;
 486                off = AU1000_INTC0_INT_BASE;
 487        } else if (pending & CAUSEF_IP4) {
 488                s = KSEG1ADDR(AU1000_IC1_PHYS_ADDR) + IC_REQ0INT;
 489                off = AU1000_INTC1_INT_BASE;
 490        } else if (pending & CAUSEF_IP5) {
 491                s = KSEG1ADDR(AU1000_IC1_PHYS_ADDR) + IC_REQ1INT;
 492                off = AU1000_INTC1_INT_BASE;
 493        } else
 494                goto spurious;
 495
 496        s = __raw_readl((void __iomem *)s);
 497        if (unlikely(!s)) {
 498spurious:
 499                spurious_interrupt();
 500                return;
 501        }
 502        off += __ffs(s);
 503handle:
 504        do_IRQ(off);
 505}
 506
 507
 508static inline void ic_init(void __iomem *base)
 509{
 510        /* initialize interrupt controller to a safe state */
 511        __raw_writel(0xffffffff, base + IC_CFG0CLR);
 512        __raw_writel(0xffffffff, base + IC_CFG1CLR);
 513        __raw_writel(0xffffffff, base + IC_CFG2CLR);
 514        __raw_writel(0xffffffff, base + IC_MASKCLR);
 515        __raw_writel(0xffffffff, base + IC_ASSIGNCLR);
 516        __raw_writel(0xffffffff, base + IC_WAKECLR);
 517        __raw_writel(0xffffffff, base + IC_SRCSET);
 518        __raw_writel(0xffffffff, base + IC_FALLINGCLR);
 519        __raw_writel(0xffffffff, base + IC_RISINGCLR);
 520        __raw_writel(0x00000000, base + IC_TESTBIT);
 521        wmb();
 522}
 523
 524static void __init au1000_init_irq(struct au1xxx_irqmap *map)
 525{
 526        unsigned int bit, irq_nr;
 527        void __iomem *base;
 528
 529        ic_init((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR));
 530        ic_init((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR));
 531        mips_cpu_irq_init();
 532
 533        /* register all 64 possible IC0+IC1 irq sources as type "none".
 534         * Use set_irq_type() to set edge/level behaviour at runtime.
 535         */
 536        for (irq_nr = AU1000_INTC0_INT_BASE;
 537             (irq_nr < AU1000_INTC0_INT_BASE + 32); irq_nr++)
 538                au1x_ic_settype(irq_get_irq_data(irq_nr), IRQ_TYPE_NONE);
 539
 540        for (irq_nr = AU1000_INTC1_INT_BASE;
 541             (irq_nr < AU1000_INTC1_INT_BASE + 32); irq_nr++)
 542                au1x_ic_settype(irq_get_irq_data(irq_nr), IRQ_TYPE_NONE);
 543
 544        /*
 545         * Initialize IC0, which is fixed per processor.
 546         */
 547        while (map->im_irq != -1) {
 548                irq_nr = map->im_irq;
 549
 550                if (irq_nr >= AU1000_INTC1_INT_BASE) {
 551                        bit = irq_nr - AU1000_INTC1_INT_BASE;
 552                        base = (void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR);
 553                } else {
 554                        bit = irq_nr - AU1000_INTC0_INT_BASE;
 555                        base = (void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR);
 556                }
 557                if (map->im_request)
 558                        __raw_writel(1 << bit, base + IC_ASSIGNSET);
 559
 560                au1x_ic_settype(irq_get_irq_data(irq_nr), map->im_type);
 561                ++map;
 562        }
 563
 564        set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3);
 565}
 566
 567void __init arch_init_irq(void)
 568{
 569        switch (alchemy_get_cputype()) {
 570        case ALCHEMY_CPU_AU1000:
 571                au1000_init_irq(au1000_irqmap);
 572                break;
 573        case ALCHEMY_CPU_AU1500:
 574                au1000_init_irq(au1500_irqmap);
 575                break;
 576        case ALCHEMY_CPU_AU1100:
 577                au1000_init_irq(au1100_irqmap);
 578                break;
 579        case ALCHEMY_CPU_AU1550:
 580                au1000_init_irq(au1550_irqmap);
 581                break;
 582        case ALCHEMY_CPU_AU1200:
 583                au1000_init_irq(au1200_irqmap);
 584                break;
 585        }
 586}
 587
 588
 589static unsigned long alchemy_ic_pmdata[7 * 2];
 590
 591static inline void alchemy_ic_suspend_one(void __iomem *base, unsigned long *d)
 592{
 593        d[0] = __raw_readl(base + IC_CFG0RD);
 594        d[1] = __raw_readl(base + IC_CFG1RD);
 595        d[2] = __raw_readl(base + IC_CFG2RD);
 596        d[3] = __raw_readl(base + IC_SRCRD);
 597        d[4] = __raw_readl(base + IC_ASSIGNRD);
 598        d[5] = __raw_readl(base + IC_WAKERD);
 599        d[6] = __raw_readl(base + IC_MASKRD);
 600        ic_init(base);          /* shut it up too while at it */
 601}
 602
 603static inline void alchemy_ic_resume_one(void __iomem *base, unsigned long *d)
 604{
 605        ic_init(base);
 606
 607        __raw_writel(d[0], base + IC_CFG0SET);
 608        __raw_writel(d[1], base + IC_CFG1SET);
 609        __raw_writel(d[2], base + IC_CFG2SET);
 610        __raw_writel(d[3], base + IC_SRCSET);
 611        __raw_writel(d[4], base + IC_ASSIGNSET);
 612        __raw_writel(d[5], base + IC_WAKESET);
 613        wmb();
 614
 615        __raw_writel(d[6], base + IC_MASKSET);
 616        wmb();
 617}
 618
 619static int alchemy_ic_suspend(void)
 620{
 621        alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR),
 622                               alchemy_ic_pmdata);
 623        alchemy_ic_suspend_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR),
 624                               &alchemy_ic_pmdata[7]);
 625        return 0;
 626}
 627
 628static void alchemy_ic_resume(void)
 629{
 630        alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC1_PHYS_ADDR),
 631                              &alchemy_ic_pmdata[7]);
 632        alchemy_ic_resume_one((void __iomem *)KSEG1ADDR(AU1000_IC0_PHYS_ADDR),
 633                              alchemy_ic_pmdata);
 634}
 635
 636static struct syscore_ops alchemy_ic_syscore_ops = {
 637        .suspend        = alchemy_ic_suspend,
 638        .resume         = alchemy_ic_resume,
 639};
 640
 641static int __init alchemy_ic_pm_init(void)
 642{
 643        register_syscore_ops(&alchemy_ic_syscore_ops);
 644        return 0;
 645}
 646device_initcall(alchemy_ic_pm_init);
 647