linux/arch/mips/paravirt/paravirt-irq.c
<<
>>
Prefs
   1/*
   2 * This file is subject to the terms and conditions of the GNU General Public
   3 * License.  See the file "COPYING" in the main directory of this archive
   4 * for more details.
   5 *
   6 * Copyright (C) 2013 Cavium, Inc.
   7 */
   8
   9#include <linux/interrupt.h>
  10#include <linux/cpumask.h>
  11#include <linux/kernel.h>
  12#include <linux/mutex.h>
  13
  14#include <asm/io.h>
  15
  16#define MBOX_BITS_PER_CPU 2
  17
  18static int cpunum_for_cpu(int cpu)
  19{
  20#ifdef CONFIG_SMP
  21        return cpu_logical_map(cpu);
  22#else
  23        return get_ebase_cpunum();
  24#endif
  25}
  26
  27struct core_chip_data {
  28        struct mutex core_irq_mutex;
  29        bool current_en;
  30        bool desired_en;
  31        u8 bit;
  32};
  33
  34static struct core_chip_data irq_core_chip_data[8];
  35
  36static void irq_core_ack(struct irq_data *data)
  37{
  38        struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
  39        unsigned int bit = cd->bit;
  40
  41        /*
  42         * We don't need to disable IRQs to make these atomic since
  43         * they are already disabled earlier in the low level
  44         * interrupt code.
  45         */
  46        clear_c0_status(0x100 << bit);
  47        /* The two user interrupts must be cleared manually. */
  48        if (bit < 2)
  49                clear_c0_cause(0x100 << bit);
  50}
  51
  52static void irq_core_eoi(struct irq_data *data)
  53{
  54        struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
  55
  56        /*
  57         * We don't need to disable IRQs to make these atomic since
  58         * they are already disabled earlier in the low level
  59         * interrupt code.
  60         */
  61        set_c0_status(0x100 << cd->bit);
  62}
  63
  64static void irq_core_set_enable_local(void *arg)
  65{
  66        struct irq_data *data = arg;
  67        struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
  68        unsigned int mask = 0x100 << cd->bit;
  69
  70        /*
  71         * Interrupts are already disabled, so these are atomic.
  72         */
  73        if (cd->desired_en)
  74                set_c0_status(mask);
  75        else
  76                clear_c0_status(mask);
  77
  78}
  79
  80static void irq_core_disable(struct irq_data *data)
  81{
  82        struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
  83        cd->desired_en = false;
  84}
  85
  86static void irq_core_enable(struct irq_data *data)
  87{
  88        struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
  89        cd->desired_en = true;
  90}
  91
  92static void irq_core_bus_lock(struct irq_data *data)
  93{
  94        struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
  95
  96        mutex_lock(&cd->core_irq_mutex);
  97}
  98
  99static void irq_core_bus_sync_unlock(struct irq_data *data)
 100{
 101        struct core_chip_data *cd = irq_data_get_irq_chip_data(data);
 102
 103        if (cd->desired_en != cd->current_en) {
 104                on_each_cpu(irq_core_set_enable_local, data, 1);
 105                cd->current_en = cd->desired_en;
 106        }
 107
 108        mutex_unlock(&cd->core_irq_mutex);
 109}
 110
 111static struct irq_chip irq_chip_core = {
 112        .name = "Core",
 113        .irq_enable = irq_core_enable,
 114        .irq_disable = irq_core_disable,
 115        .irq_ack = irq_core_ack,
 116        .irq_eoi = irq_core_eoi,
 117        .irq_bus_lock = irq_core_bus_lock,
 118        .irq_bus_sync_unlock = irq_core_bus_sync_unlock,
 119
 120        .irq_cpu_online = irq_core_eoi,
 121        .irq_cpu_offline = irq_core_ack,
 122        .flags = IRQCHIP_ONOFFLINE_ENABLED,
 123};
 124
 125static void __init irq_init_core(void)
 126{
 127        int i;
 128        int irq;
 129        struct core_chip_data *cd;
 130
 131        /* Start with a clean slate */
 132        clear_c0_status(ST0_IM);
 133        clear_c0_cause(CAUSEF_IP0 | CAUSEF_IP1);
 134
 135        for (i = 0; i < ARRAY_SIZE(irq_core_chip_data); i++) {
 136                cd = irq_core_chip_data + i;
 137                cd->current_en = false;
 138                cd->desired_en = false;
 139                cd->bit = i;
 140                mutex_init(&cd->core_irq_mutex);
 141
 142                irq = MIPS_CPU_IRQ_BASE + i;
 143
 144                switch (i) {
 145                case 0: /* SW0 */
 146                case 1: /* SW1 */
 147                case 5: /* IP5 */
 148                case 6: /* IP6 */
 149                case 7: /* IP7 */
 150                        irq_set_chip_data(irq, cd);
 151                        irq_set_chip_and_handler(irq, &irq_chip_core,
 152                                                 handle_percpu_irq);
 153                        break;
 154                default:
 155                        break;
 156                }
 157        }
 158}
 159
 160static void __iomem *mips_irq_chip;
 161#define MIPS_IRQ_CHIP_NUM_BITS 0
 162#define MIPS_IRQ_CHIP_REGS 8
 163
 164static int mips_irq_cpu_stride;
 165static int mips_irq_chip_reg_raw;
 166static int mips_irq_chip_reg_src;
 167static int mips_irq_chip_reg_en;
 168static int mips_irq_chip_reg_raw_w1s;
 169static int mips_irq_chip_reg_raw_w1c;
 170static int mips_irq_chip_reg_en_w1s;
 171static int mips_irq_chip_reg_en_w1c;
 172
 173static void irq_pci_enable(struct irq_data *data)
 174{
 175        u32 mask = 1u << data->irq;
 176
 177        __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1s);
 178}
 179
 180static void irq_pci_disable(struct irq_data *data)
 181{
 182        u32 mask = 1u << data->irq;
 183
 184        __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1c);
 185}
 186
 187static void irq_pci_ack(struct irq_data *data)
 188{
 189}
 190
 191static void irq_pci_mask(struct irq_data *data)
 192{
 193        u32 mask = 1u << data->irq;
 194
 195        __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1c);
 196}
 197
 198static void irq_pci_unmask(struct irq_data *data)
 199{
 200        u32 mask = 1u << data->irq;
 201
 202        __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_en_w1s);
 203}
 204
 205static struct irq_chip irq_chip_pci = {
 206        .name = "PCI",
 207        .irq_enable = irq_pci_enable,
 208        .irq_disable = irq_pci_disable,
 209        .irq_ack = irq_pci_ack,
 210        .irq_mask = irq_pci_mask,
 211        .irq_unmask = irq_pci_unmask,
 212};
 213
 214static void irq_mbox_all(struct irq_data *data,  void __iomem *base)
 215{
 216        int cpu;
 217        unsigned int mbox = data->irq - MIPS_IRQ_MBOX0;
 218        u32 mask;
 219
 220        WARN_ON(mbox >= MBOX_BITS_PER_CPU);
 221
 222        for_each_online_cpu(cpu) {
 223                unsigned int cpuid = cpunum_for_cpu(cpu);
 224                mask = 1 << (cpuid * MBOX_BITS_PER_CPU + mbox);
 225                __raw_writel(mask, base + (cpuid * mips_irq_cpu_stride));
 226        }
 227}
 228
 229static void irq_mbox_enable(struct irq_data *data)
 230{
 231        irq_mbox_all(data, mips_irq_chip + mips_irq_chip_reg_en_w1s + sizeof(u32));
 232}
 233
 234static void irq_mbox_disable(struct irq_data *data)
 235{
 236        irq_mbox_all(data, mips_irq_chip + mips_irq_chip_reg_en_w1c + sizeof(u32));
 237}
 238
 239static void irq_mbox_ack(struct irq_data *data)
 240{
 241        u32 mask;
 242        unsigned int mbox = data->irq - MIPS_IRQ_MBOX0;
 243
 244        WARN_ON(mbox >= MBOX_BITS_PER_CPU);
 245
 246        mask = 1 << (get_ebase_cpunum() * MBOX_BITS_PER_CPU + mbox);
 247        __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_raw_w1c + sizeof(u32));
 248}
 249
 250void irq_mbox_ipi(int cpu, unsigned int actions)
 251{
 252        unsigned int cpuid = cpunum_for_cpu(cpu);
 253        u32 mask;
 254
 255        WARN_ON(actions >= (1 << MBOX_BITS_PER_CPU));
 256
 257        mask = actions << (cpuid * MBOX_BITS_PER_CPU);
 258        __raw_writel(mask, mips_irq_chip + mips_irq_chip_reg_raw_w1s + sizeof(u32));
 259}
 260
 261static void irq_mbox_cpu_onoffline(struct irq_data *data,  void __iomem *base)
 262{
 263        unsigned int mbox = data->irq - MIPS_IRQ_MBOX0;
 264        unsigned int cpuid = get_ebase_cpunum();
 265        u32 mask;
 266
 267        WARN_ON(mbox >= MBOX_BITS_PER_CPU);
 268
 269        mask = 1 << (cpuid * MBOX_BITS_PER_CPU + mbox);
 270        __raw_writel(mask, base + (cpuid * mips_irq_cpu_stride));
 271
 272}
 273
 274static void irq_mbox_cpu_online(struct irq_data *data)
 275{
 276        irq_mbox_cpu_onoffline(data, mips_irq_chip + mips_irq_chip_reg_en_w1s + sizeof(u32));
 277}
 278
 279static void irq_mbox_cpu_offline(struct irq_data *data)
 280{
 281        irq_mbox_cpu_onoffline(data, mips_irq_chip + mips_irq_chip_reg_en_w1c + sizeof(u32));
 282}
 283
 284static struct irq_chip irq_chip_mbox = {
 285        .name = "MBOX",
 286        .irq_enable = irq_mbox_enable,
 287        .irq_disable = irq_mbox_disable,
 288        .irq_ack = irq_mbox_ack,
 289        .irq_cpu_online = irq_mbox_cpu_online,
 290        .irq_cpu_offline = irq_mbox_cpu_offline,
 291        .flags = IRQCHIP_ONOFFLINE_ENABLED,
 292};
 293
 294static void __init irq_pci_init(void)
 295{
 296        int i, stride;
 297        u32 num_bits;
 298
 299        mips_irq_chip = ioremap(0x1e010000, 4096);
 300
 301        num_bits = __raw_readl(mips_irq_chip + MIPS_IRQ_CHIP_NUM_BITS);
 302        stride = 8 * (1 + ((num_bits - 1) / 64));
 303
 304
 305        pr_notice("mips_irq_chip: %u bits, reg stride: %d\n", num_bits, stride);
 306        mips_irq_chip_reg_raw           = MIPS_IRQ_CHIP_REGS + 0 * stride;
 307        mips_irq_chip_reg_raw_w1s       = MIPS_IRQ_CHIP_REGS + 1 * stride;
 308        mips_irq_chip_reg_raw_w1c       = MIPS_IRQ_CHIP_REGS + 2 * stride;
 309        mips_irq_chip_reg_src           = MIPS_IRQ_CHIP_REGS + 3 * stride;
 310        mips_irq_chip_reg_en            = MIPS_IRQ_CHIP_REGS + 4 * stride;
 311        mips_irq_chip_reg_en_w1s        = MIPS_IRQ_CHIP_REGS + 5 * stride;
 312        mips_irq_chip_reg_en_w1c        = MIPS_IRQ_CHIP_REGS + 6 * stride;
 313        mips_irq_cpu_stride             = stride * 4;
 314
 315        for (i = 0; i < 4; i++)
 316                irq_set_chip_and_handler(i + MIPS_IRQ_PCIA, &irq_chip_pci, handle_level_irq);
 317
 318        for (i = 0; i < 2; i++)
 319                irq_set_chip_and_handler(i + MIPS_IRQ_MBOX0, &irq_chip_mbox, handle_percpu_irq);
 320
 321
 322        set_c0_status(STATUSF_IP2);
 323}
 324
 325static void irq_pci_dispatch(void)
 326{
 327        unsigned int cpuid = get_ebase_cpunum();
 328        u32 en;
 329
 330        en = __raw_readl(mips_irq_chip + mips_irq_chip_reg_src +
 331                        (cpuid * mips_irq_cpu_stride));
 332
 333        if (!en) {
 334                en = __raw_readl(mips_irq_chip + mips_irq_chip_reg_src + (cpuid * mips_irq_cpu_stride) + sizeof(u32));
 335                en = (en >> (2 * cpuid)) & 3;
 336
 337                if (!en)
 338                        spurious_interrupt();
 339                else
 340                        do_IRQ(__ffs(en) + MIPS_IRQ_MBOX0);     /* MBOX type */
 341        } else {
 342                do_IRQ(__ffs(en));
 343        }
 344}
 345
 346
 347void __init arch_init_irq(void)
 348{
 349        irq_init_core();
 350        irq_pci_init();
 351}
 352
 353asmlinkage void plat_irq_dispatch(void)
 354{
 355        unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
 356        int ip;
 357
 358        if (unlikely(!pending)) {
 359                spurious_interrupt();
 360                return;
 361        }
 362
 363        ip = ffs(pending) - 1 - STATUSB_IP0;
 364        if (ip == 2)
 365                irq_pci_dispatch();
 366        else
 367                do_IRQ(MIPS_CPU_IRQ_BASE + ip);
 368}
 369