linux/arch/arm/mach-msm/irq-vic.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2007 Google, Inc.
   3 * Copyright (c) 2009, Code Aurora Forum. All rights reserved.
   4 *
   5 * This software is licensed under the terms of the GNU General Public
   6 * License version 2, as published by the Free Software Foundation, and
   7 * may be copied, distributed, and modified under those terms.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 *
  14 */
  15
  16#include <linux/init.h>
  17#include <linux/module.h>
  18#include <linux/sched.h>
  19#include <linux/interrupt.h>
  20#include <linux/ptrace.h>
  21#include <linux/timer.h>
  22#include <linux/irq.h>
  23#include <linux/io.h>
  24
  25#include <asm/cacheflush.h>
  26
  27#include <mach/hardware.h>
  28
  29#include <mach/msm_iomap.h>
  30
  31#include "smd_private.h"
  32
  33enum {
  34        IRQ_DEBUG_SLEEP_INT_TRIGGER = 1U << 0,
  35        IRQ_DEBUG_SLEEP_INT = 1U << 1,
  36        IRQ_DEBUG_SLEEP_ABORT = 1U << 2,
  37        IRQ_DEBUG_SLEEP = 1U << 3,
  38        IRQ_DEBUG_SLEEP_REQUEST = 1U << 4,
  39};
  40static int msm_irq_debug_mask;
  41module_param_named(debug_mask, msm_irq_debug_mask, int,
  42                   S_IRUGO | S_IWUSR | S_IWGRP);
  43
  44#define VIC_REG(off) (MSM_VIC_BASE + (off))
  45#define VIC_INT_TO_REG_ADDR(base, irq) (base + (irq / 32) * 4)
  46#define VIC_INT_TO_REG_INDEX(irq) ((irq >> 5) & 3)
  47
  48#define VIC_INT_SELECT0     VIC_REG(0x0000)  /* 1: FIQ, 0: IRQ */
  49#define VIC_INT_SELECT1     VIC_REG(0x0004)  /* 1: FIQ, 0: IRQ */
  50#define VIC_INT_SELECT2     VIC_REG(0x0008)  /* 1: FIQ, 0: IRQ */
  51#define VIC_INT_SELECT3     VIC_REG(0x000C)  /* 1: FIQ, 0: IRQ */
  52#define VIC_INT_EN0         VIC_REG(0x0010)
  53#define VIC_INT_EN1         VIC_REG(0x0014)
  54#define VIC_INT_EN2         VIC_REG(0x0018)
  55#define VIC_INT_EN3         VIC_REG(0x001C)
  56#define VIC_INT_ENCLEAR0    VIC_REG(0x0020)
  57#define VIC_INT_ENCLEAR1    VIC_REG(0x0024)
  58#define VIC_INT_ENCLEAR2    VIC_REG(0x0028)
  59#define VIC_INT_ENCLEAR3    VIC_REG(0x002C)
  60#define VIC_INT_ENSET0      VIC_REG(0x0030)
  61#define VIC_INT_ENSET1      VIC_REG(0x0034)
  62#define VIC_INT_ENSET2      VIC_REG(0x0038)
  63#define VIC_INT_ENSET3      VIC_REG(0x003C)
  64#define VIC_INT_TYPE0       VIC_REG(0x0040)  /* 1: EDGE, 0: LEVEL  */
  65#define VIC_INT_TYPE1       VIC_REG(0x0044)  /* 1: EDGE, 0: LEVEL  */
  66#define VIC_INT_TYPE2       VIC_REG(0x0048)  /* 1: EDGE, 0: LEVEL  */
  67#define VIC_INT_TYPE3       VIC_REG(0x004C)  /* 1: EDGE, 0: LEVEL  */
  68#define VIC_INT_POLARITY0   VIC_REG(0x0050)  /* 1: NEG, 0: POS */
  69#define VIC_INT_POLARITY1   VIC_REG(0x0054)  /* 1: NEG, 0: POS */
  70#define VIC_INT_POLARITY2   VIC_REG(0x0058)  /* 1: NEG, 0: POS */
  71#define VIC_INT_POLARITY3   VIC_REG(0x005C)  /* 1: NEG, 0: POS */
  72#define VIC_NO_PEND_VAL     VIC_REG(0x0060)
  73
  74#if defined(CONFIG_ARCH_MSM_SCORPION)
  75#define VIC_NO_PEND_VAL_FIQ VIC_REG(0x0064)
  76#define VIC_INT_MASTEREN    VIC_REG(0x0068)  /* 1: IRQ, 2: FIQ     */
  77#define VIC_CONFIG          VIC_REG(0x006C)  /* 1: USE SC VIC */
  78#else
  79#define VIC_INT_MASTEREN    VIC_REG(0x0064)  /* 1: IRQ, 2: FIQ     */
  80#define VIC_PROTECTION      VIC_REG(0x006C)  /* 1: ENABLE          */
  81#define VIC_CONFIG          VIC_REG(0x0068)  /* 1: USE ARM1136 VIC */
  82#endif
  83
  84#define VIC_IRQ_STATUS0     VIC_REG(0x0080)
  85#define VIC_IRQ_STATUS1     VIC_REG(0x0084)
  86#define VIC_IRQ_STATUS2     VIC_REG(0x0088)
  87#define VIC_IRQ_STATUS3     VIC_REG(0x008C)
  88#define VIC_FIQ_STATUS0     VIC_REG(0x0090)
  89#define VIC_FIQ_STATUS1     VIC_REG(0x0094)
  90#define VIC_FIQ_STATUS2     VIC_REG(0x0098)
  91#define VIC_FIQ_STATUS3     VIC_REG(0x009C)
  92#define VIC_RAW_STATUS0     VIC_REG(0x00A0)
  93#define VIC_RAW_STATUS1     VIC_REG(0x00A4)
  94#define VIC_RAW_STATUS2     VIC_REG(0x00A8)
  95#define VIC_RAW_STATUS3     VIC_REG(0x00AC)
  96#define VIC_INT_CLEAR0      VIC_REG(0x00B0)
  97#define VIC_INT_CLEAR1      VIC_REG(0x00B4)
  98#define VIC_INT_CLEAR2      VIC_REG(0x00B8)
  99#define VIC_INT_CLEAR3      VIC_REG(0x00BC)
 100#define VIC_SOFTINT0        VIC_REG(0x00C0)
 101#define VIC_SOFTINT1        VIC_REG(0x00C4)
 102#define VIC_SOFTINT2        VIC_REG(0x00C8)
 103#define VIC_SOFTINT3        VIC_REG(0x00CC)
 104#define VIC_IRQ_VEC_RD      VIC_REG(0x00D0)  /* pending int # */
 105#define VIC_IRQ_VEC_PEND_RD VIC_REG(0x00D4)  /* pending vector addr */
 106#define VIC_IRQ_VEC_WR      VIC_REG(0x00D8)
 107
 108#if defined(CONFIG_ARCH_MSM_SCORPION)
 109#define VIC_FIQ_VEC_RD      VIC_REG(0x00DC)
 110#define VIC_FIQ_VEC_PEND_RD VIC_REG(0x00E0)
 111#define VIC_FIQ_VEC_WR      VIC_REG(0x00E4)
 112#define VIC_IRQ_IN_SERVICE  VIC_REG(0x00E8)
 113#define VIC_IRQ_IN_STACK    VIC_REG(0x00EC)
 114#define VIC_FIQ_IN_SERVICE  VIC_REG(0x00F0)
 115#define VIC_FIQ_IN_STACK    VIC_REG(0x00F4)
 116#define VIC_TEST_BUS_SEL    VIC_REG(0x00F8)
 117#define VIC_IRQ_CTRL_CONFIG VIC_REG(0x00FC)
 118#else
 119#define VIC_IRQ_IN_SERVICE  VIC_REG(0x00E0)
 120#define VIC_IRQ_IN_STACK    VIC_REG(0x00E4)
 121#define VIC_TEST_BUS_SEL    VIC_REG(0x00E8)
 122#endif
 123
 124#define VIC_VECTPRIORITY(n) VIC_REG(0x0200+((n) * 4))
 125#define VIC_VECTADDR(n)     VIC_REG(0x0400+((n) * 4))
 126
 127#if defined(CONFIG_ARCH_MSM7X30)
 128#define VIC_NUM_REGS        4
 129#else
 130#define VIC_NUM_REGS        2
 131#endif
 132
 133#if VIC_NUM_REGS == 2
 134#define DPRINT_REGS(base_reg, format, ...)                              \
 135        printk(KERN_INFO format " %x %x\n", ##__VA_ARGS__,              \
 136                        readl(base_reg ## 0), readl(base_reg ## 1))
 137#define DPRINT_ARRAY(array, format, ...)                                \
 138        printk(KERN_INFO format " %x %x\n", ##__VA_ARGS__,              \
 139                        array[0], array[1])
 140#elif VIC_NUM_REGS == 4
 141#define DPRINT_REGS(base_reg, format, ...) \
 142        printk(KERN_INFO format " %x %x %x %x\n", ##__VA_ARGS__,        \
 143                        readl(base_reg ## 0), readl(base_reg ## 1),     \
 144                        readl(base_reg ## 2), readl(base_reg ## 3))
 145#define DPRINT_ARRAY(array, format, ...)                                \
 146        printk(KERN_INFO format " %x %x %x %x\n", ##__VA_ARGS__,        \
 147                        array[0], array[1],                             \
 148                        array[2], array[3])
 149#else
 150#error "VIC_NUM_REGS set to illegal value"
 151#endif
 152
 153static uint32_t msm_irq_smsm_wake_enable[2];
 154static struct {
 155        uint32_t int_en[2];
 156        uint32_t int_type;
 157        uint32_t int_polarity;
 158        uint32_t int_select;
 159} msm_irq_shadow_reg[VIC_NUM_REGS];
 160static uint32_t msm_irq_idle_disable[VIC_NUM_REGS];
 161
 162#define SMSM_FAKE_IRQ (0xff)
 163static uint8_t msm_irq_to_smsm[NR_IRQS] = {
 164        [INT_MDDI_EXT] = 1,
 165        [INT_MDDI_PRI] = 2,
 166        [INT_MDDI_CLIENT] = 3,
 167        [INT_USB_OTG] = 4,
 168
 169        [INT_PWB_I2C] = 5,
 170        [INT_SDC1_0] = 6,
 171        [INT_SDC1_1] = 7,
 172        [INT_SDC2_0] = 8,
 173
 174        [INT_SDC2_1] = 9,
 175        [INT_ADSP_A9_A11] = 10,
 176        [INT_UART1] = 11,
 177        [INT_UART2] = 12,
 178
 179        [INT_UART3] = 13,
 180        [INT_UART1_RX] = 14,
 181        [INT_UART2_RX] = 15,
 182        [INT_UART3_RX] = 16,
 183
 184        [INT_UART1DM_IRQ] = 17,
 185        [INT_UART1DM_RX] = 18,
 186        [INT_KEYSENSE] = 19,
 187#if !defined(CONFIG_ARCH_MSM7X30)
 188        [INT_AD_HSSD] = 20,
 189#endif
 190
 191        [INT_NAND_WR_ER_DONE] = 21,
 192        [INT_NAND_OP_DONE] = 22,
 193        [INT_TCHSCRN1] = 23,
 194        [INT_TCHSCRN2] = 24,
 195
 196        [INT_TCHSCRN_SSBI] = 25,
 197        [INT_USB_HS] = 26,
 198        [INT_UART2DM_RX] = 27,
 199        [INT_UART2DM_IRQ] = 28,
 200
 201        [INT_SDC4_1] = 29,
 202        [INT_SDC4_0] = 30,
 203        [INT_SDC3_1] = 31,
 204        [INT_SDC3_0] = 32,
 205
 206        /* fake wakeup interrupts */
 207        [INT_GPIO_GROUP1] = SMSM_FAKE_IRQ,
 208        [INT_GPIO_GROUP2] = SMSM_FAKE_IRQ,
 209        [INT_A9_M2A_0] = SMSM_FAKE_IRQ,
 210        [INT_A9_M2A_1] = SMSM_FAKE_IRQ,
 211        [INT_A9_M2A_5] = SMSM_FAKE_IRQ,
 212        [INT_GP_TIMER_EXP] = SMSM_FAKE_IRQ,
 213        [INT_DEBUG_TIMER_EXP] = SMSM_FAKE_IRQ,
 214        [INT_ADSP_A11] = SMSM_FAKE_IRQ,
 215#ifdef CONFIG_ARCH_QSD8X50
 216        [INT_SIRC_0] = SMSM_FAKE_IRQ,
 217        [INT_SIRC_1] = SMSM_FAKE_IRQ,
 218#endif
 219};
 220
 221static inline void msm_irq_write_all_regs(void __iomem *base, unsigned int val)
 222{
 223        int i;
 224
 225        for (i = 0; i < VIC_NUM_REGS; i++)
 226                writel(val, base + (i * 4));
 227}
 228
 229static void msm_irq_ack(struct irq_data *d)
 230{
 231        void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_CLEAR0, d->irq);
 232        writel(1 << (d->irq & 31), reg);
 233}
 234
 235static void msm_irq_mask(struct irq_data *d)
 236{
 237        void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENCLEAR0, d->irq);
 238        unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
 239        uint32_t mask = 1UL << (d->irq & 31);
 240        int smsm_irq = msm_irq_to_smsm[d->irq];
 241
 242        msm_irq_shadow_reg[index].int_en[0] &= ~mask;
 243        writel(mask, reg);
 244        if (smsm_irq == 0)
 245                msm_irq_idle_disable[index] &= ~mask;
 246        else {
 247                mask = 1UL << (smsm_irq - 1);
 248                msm_irq_smsm_wake_enable[0] &= ~mask;
 249        }
 250}
 251
 252static void msm_irq_unmask(struct irq_data *d)
 253{
 254        void __iomem *reg = VIC_INT_TO_REG_ADDR(VIC_INT_ENSET0, d->irq);
 255        unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
 256        uint32_t mask = 1UL << (d->irq & 31);
 257        int smsm_irq = msm_irq_to_smsm[d->irq];
 258
 259        msm_irq_shadow_reg[index].int_en[0] |= mask;
 260        writel(mask, reg);
 261
 262        if (smsm_irq == 0)
 263                msm_irq_idle_disable[index] |= mask;
 264        else {
 265                mask = 1UL << (smsm_irq - 1);
 266                msm_irq_smsm_wake_enable[0] |= mask;
 267        }
 268}
 269
 270static int msm_irq_set_wake(struct irq_data *d, unsigned int on)
 271{
 272        unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
 273        uint32_t mask = 1UL << (d->irq & 31);
 274        int smsm_irq = msm_irq_to_smsm[d->irq];
 275
 276        if (smsm_irq == 0) {
 277                printk(KERN_ERR "msm_irq_set_wake: bad wakeup irq %d\n", d->irq);
 278                return -EINVAL;
 279        }
 280        if (on)
 281                msm_irq_shadow_reg[index].int_en[1] |= mask;
 282        else
 283                msm_irq_shadow_reg[index].int_en[1] &= ~mask;
 284
 285        if (smsm_irq == SMSM_FAKE_IRQ)
 286                return 0;
 287
 288        mask = 1UL << (smsm_irq - 1);
 289        if (on)
 290                msm_irq_smsm_wake_enable[1] |= mask;
 291        else
 292                msm_irq_smsm_wake_enable[1] &= ~mask;
 293        return 0;
 294}
 295
 296static int msm_irq_set_type(struct irq_data *d, unsigned int flow_type)
 297{
 298        void __iomem *treg = VIC_INT_TO_REG_ADDR(VIC_INT_TYPE0, d->irq);
 299        void __iomem *preg = VIC_INT_TO_REG_ADDR(VIC_INT_POLARITY0, d->irq);
 300        unsigned index = VIC_INT_TO_REG_INDEX(d->irq);
 301        int b = 1 << (d->irq & 31);
 302        uint32_t polarity;
 303        uint32_t type;
 304
 305        polarity = msm_irq_shadow_reg[index].int_polarity;
 306        if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW))
 307                polarity |= b;
 308        if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH))
 309                polarity &= ~b;
 310        writel(polarity, preg);
 311        msm_irq_shadow_reg[index].int_polarity = polarity;
 312
 313        type = msm_irq_shadow_reg[index].int_type;
 314        if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
 315                type |= b;
 316                __irq_set_handler_locked(d->irq, handle_edge_irq);
 317        }
 318        if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
 319                type &= ~b;
 320                __irq_set_handler_locked(d->irq, handle_level_irq);
 321        }
 322        writel(type, treg);
 323        msm_irq_shadow_reg[index].int_type = type;
 324        return 0;
 325}
 326
 327static struct irq_chip msm_irq_chip = {
 328        .name          = "msm",
 329        .irq_disable   = msm_irq_mask,
 330        .irq_ack       = msm_irq_ack,
 331        .irq_mask      = msm_irq_mask,
 332        .irq_unmask    = msm_irq_unmask,
 333        .irq_set_wake  = msm_irq_set_wake,
 334        .irq_set_type  = msm_irq_set_type,
 335};
 336
 337void __init msm_init_irq(void)
 338{
 339        unsigned n;
 340
 341        /* select level interrupts */
 342        msm_irq_write_all_regs(VIC_INT_TYPE0, 0);
 343
 344        /* select highlevel interrupts */
 345        msm_irq_write_all_regs(VIC_INT_POLARITY0, 0);
 346
 347        /* select IRQ for all INTs */
 348        msm_irq_write_all_regs(VIC_INT_SELECT0, 0);
 349
 350        /* disable all INTs */
 351        msm_irq_write_all_regs(VIC_INT_EN0, 0);
 352
 353        /* don't use vic */
 354        writel(0, VIC_CONFIG);
 355
 356        /* enable interrupt controller */
 357        writel(3, VIC_INT_MASTEREN);
 358
 359        for (n = 0; n < NR_MSM_IRQS; n++) {
 360                irq_set_chip_and_handler(n, &msm_irq_chip, handle_level_irq);
 361                set_irq_flags(n, IRQF_VALID);
 362        }
 363}
 364