linux/arch/powerpc/sysdev/ipic.c
<<
>>
Prefs
   1/*
   2 * arch/powerpc/sysdev/ipic.c
   3 *
   4 * IPIC routines implementations.
   5 *
   6 * Copyright 2005 Freescale Semiconductor, Inc.
   7 *
   8 * This program is free software; you can redistribute  it and/or modify it
   9 * under  the terms of  the GNU General  Public License as published by the
  10 * Free Software Foundation;  either version 2 of the  License, or (at your
  11 * option) any later version.
  12 */
  13#include <linux/kernel.h>
  14#include <linux/init.h>
  15#include <linux/errno.h>
  16#include <linux/reboot.h>
  17#include <linux/slab.h>
  18#include <linux/stddef.h>
  19#include <linux/sched.h>
  20#include <linux/signal.h>
  21#include <linux/syscore_ops.h>
  22#include <linux/device.h>
  23#include <linux/bootmem.h>
  24#include <linux/spinlock.h>
  25#include <linux/fsl_devices.h>
  26#include <asm/irq.h>
  27#include <asm/io.h>
  28#include <asm/prom.h>
  29#include <asm/ipic.h>
  30
  31#include "ipic.h"
  32
  33static struct ipic * primary_ipic;
  34static struct irq_chip ipic_level_irq_chip, ipic_edge_irq_chip;
  35static DEFINE_RAW_SPINLOCK(ipic_lock);
  36
  37static struct ipic_info ipic_info[] = {
  38        [1] = {
  39                .mask   = IPIC_SIMSR_H,
  40                .prio   = IPIC_SIPRR_C,
  41                .force  = IPIC_SIFCR_H,
  42                .bit    = 16,
  43                .prio_mask = 0,
  44        },
  45        [2] = {
  46                .mask   = IPIC_SIMSR_H,
  47                .prio   = IPIC_SIPRR_C,
  48                .force  = IPIC_SIFCR_H,
  49                .bit    = 17,
  50                .prio_mask = 1,
  51        },
  52        [3] = {
  53                .mask   = IPIC_SIMSR_H,
  54                .prio   = IPIC_SIPRR_C,
  55                .force  = IPIC_SIFCR_H,
  56                .bit    = 18,
  57                .prio_mask = 2,
  58        },
  59        [4] = {
  60                .mask   = IPIC_SIMSR_H,
  61                .prio   = IPIC_SIPRR_C,
  62                .force  = IPIC_SIFCR_H,
  63                .bit    = 19,
  64                .prio_mask = 3,
  65        },
  66        [5] = {
  67                .mask   = IPIC_SIMSR_H,
  68                .prio   = IPIC_SIPRR_C,
  69                .force  = IPIC_SIFCR_H,
  70                .bit    = 20,
  71                .prio_mask = 4,
  72        },
  73        [6] = {
  74                .mask   = IPIC_SIMSR_H,
  75                .prio   = IPIC_SIPRR_C,
  76                .force  = IPIC_SIFCR_H,
  77                .bit    = 21,
  78                .prio_mask = 5,
  79        },
  80        [7] = {
  81                .mask   = IPIC_SIMSR_H,
  82                .prio   = IPIC_SIPRR_C,
  83                .force  = IPIC_SIFCR_H,
  84                .bit    = 22,
  85                .prio_mask = 6,
  86        },
  87        [8] = {
  88                .mask   = IPIC_SIMSR_H,
  89                .prio   = IPIC_SIPRR_C,
  90                .force  = IPIC_SIFCR_H,
  91                .bit    = 23,
  92                .prio_mask = 7,
  93        },
  94        [9] = {
  95                .mask   = IPIC_SIMSR_H,
  96                .prio   = IPIC_SIPRR_D,
  97                .force  = IPIC_SIFCR_H,
  98                .bit    = 24,
  99                .prio_mask = 0,
 100        },
 101        [10] = {
 102                .mask   = IPIC_SIMSR_H,
 103                .prio   = IPIC_SIPRR_D,
 104                .force  = IPIC_SIFCR_H,
 105                .bit    = 25,
 106                .prio_mask = 1,
 107        },
 108        [11] = {
 109                .mask   = IPIC_SIMSR_H,
 110                .prio   = IPIC_SIPRR_D,
 111                .force  = IPIC_SIFCR_H,
 112                .bit    = 26,
 113                .prio_mask = 2,
 114        },
 115        [12] = {
 116                .mask   = IPIC_SIMSR_H,
 117                .prio   = IPIC_SIPRR_D,
 118                .force  = IPIC_SIFCR_H,
 119                .bit    = 27,
 120                .prio_mask = 3,
 121        },
 122        [13] = {
 123                .mask   = IPIC_SIMSR_H,
 124                .prio   = IPIC_SIPRR_D,
 125                .force  = IPIC_SIFCR_H,
 126                .bit    = 28,
 127                .prio_mask = 4,
 128        },
 129        [14] = {
 130                .mask   = IPIC_SIMSR_H,
 131                .prio   = IPIC_SIPRR_D,
 132                .force  = IPIC_SIFCR_H,
 133                .bit    = 29,
 134                .prio_mask = 5,
 135        },
 136        [15] = {
 137                .mask   = IPIC_SIMSR_H,
 138                .prio   = IPIC_SIPRR_D,
 139                .force  = IPIC_SIFCR_H,
 140                .bit    = 30,
 141                .prio_mask = 6,
 142        },
 143        [16] = {
 144                .mask   = IPIC_SIMSR_H,
 145                .prio   = IPIC_SIPRR_D,
 146                .force  = IPIC_SIFCR_H,
 147                .bit    = 31,
 148                .prio_mask = 7,
 149        },
 150        [17] = {
 151                .ack    = IPIC_SEPNR,
 152                .mask   = IPIC_SEMSR,
 153                .prio   = IPIC_SMPRR_A,
 154                .force  = IPIC_SEFCR,
 155                .bit    = 1,
 156                .prio_mask = 5,
 157        },
 158        [18] = {
 159                .ack    = IPIC_SEPNR,
 160                .mask   = IPIC_SEMSR,
 161                .prio   = IPIC_SMPRR_A,
 162                .force  = IPIC_SEFCR,
 163                .bit    = 2,
 164                .prio_mask = 6,
 165        },
 166        [19] = {
 167                .ack    = IPIC_SEPNR,
 168                .mask   = IPIC_SEMSR,
 169                .prio   = IPIC_SMPRR_A,
 170                .force  = IPIC_SEFCR,
 171                .bit    = 3,
 172                .prio_mask = 7,
 173        },
 174        [20] = {
 175                .ack    = IPIC_SEPNR,
 176                .mask   = IPIC_SEMSR,
 177                .prio   = IPIC_SMPRR_B,
 178                .force  = IPIC_SEFCR,
 179                .bit    = 4,
 180                .prio_mask = 4,
 181        },
 182        [21] = {
 183                .ack    = IPIC_SEPNR,
 184                .mask   = IPIC_SEMSR,
 185                .prio   = IPIC_SMPRR_B,
 186                .force  = IPIC_SEFCR,
 187                .bit    = 5,
 188                .prio_mask = 5,
 189        },
 190        [22] = {
 191                .ack    = IPIC_SEPNR,
 192                .mask   = IPIC_SEMSR,
 193                .prio   = IPIC_SMPRR_B,
 194                .force  = IPIC_SEFCR,
 195                .bit    = 6,
 196                .prio_mask = 6,
 197        },
 198        [23] = {
 199                .ack    = IPIC_SEPNR,
 200                .mask   = IPIC_SEMSR,
 201                .prio   = IPIC_SMPRR_B,
 202                .force  = IPIC_SEFCR,
 203                .bit    = 7,
 204                .prio_mask = 7,
 205        },
 206        [32] = {
 207                .mask   = IPIC_SIMSR_H,
 208                .prio   = IPIC_SIPRR_A,
 209                .force  = IPIC_SIFCR_H,
 210                .bit    = 0,
 211                .prio_mask = 0,
 212        },
 213        [33] = {
 214                .mask   = IPIC_SIMSR_H,
 215                .prio   = IPIC_SIPRR_A,
 216                .force  = IPIC_SIFCR_H,
 217                .bit    = 1,
 218                .prio_mask = 1,
 219        },
 220        [34] = {
 221                .mask   = IPIC_SIMSR_H,
 222                .prio   = IPIC_SIPRR_A,
 223                .force  = IPIC_SIFCR_H,
 224                .bit    = 2,
 225                .prio_mask = 2,
 226        },
 227        [35] = {
 228                .mask   = IPIC_SIMSR_H,
 229                .prio   = IPIC_SIPRR_A,
 230                .force  = IPIC_SIFCR_H,
 231                .bit    = 3,
 232                .prio_mask = 3,
 233        },
 234        [36] = {
 235                .mask   = IPIC_SIMSR_H,
 236                .prio   = IPIC_SIPRR_A,
 237                .force  = IPIC_SIFCR_H,
 238                .bit    = 4,
 239                .prio_mask = 4,
 240        },
 241        [37] = {
 242                .mask   = IPIC_SIMSR_H,
 243                .prio   = IPIC_SIPRR_A,
 244                .force  = IPIC_SIFCR_H,
 245                .bit    = 5,
 246                .prio_mask = 5,
 247        },
 248        [38] = {
 249                .mask   = IPIC_SIMSR_H,
 250                .prio   = IPIC_SIPRR_A,
 251                .force  = IPIC_SIFCR_H,
 252                .bit    = 6,
 253                .prio_mask = 6,
 254        },
 255        [39] = {
 256                .mask   = IPIC_SIMSR_H,
 257                .prio   = IPIC_SIPRR_A,
 258                .force  = IPIC_SIFCR_H,
 259                .bit    = 7,
 260                .prio_mask = 7,
 261        },
 262        [40] = {
 263                .mask   = IPIC_SIMSR_H,
 264                .prio   = IPIC_SIPRR_B,
 265                .force  = IPIC_SIFCR_H,
 266                .bit    = 8,
 267                .prio_mask = 0,
 268        },
 269        [41] = {
 270                .mask   = IPIC_SIMSR_H,
 271                .prio   = IPIC_SIPRR_B,
 272                .force  = IPIC_SIFCR_H,
 273                .bit    = 9,
 274                .prio_mask = 1,
 275        },
 276        [42] = {
 277                .mask   = IPIC_SIMSR_H,
 278                .prio   = IPIC_SIPRR_B,
 279                .force  = IPIC_SIFCR_H,
 280                .bit    = 10,
 281                .prio_mask = 2,
 282        },
 283        [43] = {
 284                .mask   = IPIC_SIMSR_H,
 285                .prio   = IPIC_SIPRR_B,
 286                .force  = IPIC_SIFCR_H,
 287                .bit    = 11,
 288                .prio_mask = 3,
 289        },
 290        [44] = {
 291                .mask   = IPIC_SIMSR_H,
 292                .prio   = IPIC_SIPRR_B,
 293                .force  = IPIC_SIFCR_H,
 294                .bit    = 12,
 295                .prio_mask = 4,
 296        },
 297        [45] = {
 298                .mask   = IPIC_SIMSR_H,
 299                .prio   = IPIC_SIPRR_B,
 300                .force  = IPIC_SIFCR_H,
 301                .bit    = 13,
 302                .prio_mask = 5,
 303        },
 304        [46] = {
 305                .mask   = IPIC_SIMSR_H,
 306                .prio   = IPIC_SIPRR_B,
 307                .force  = IPIC_SIFCR_H,
 308                .bit    = 14,
 309                .prio_mask = 6,
 310        },
 311        [47] = {
 312                .mask   = IPIC_SIMSR_H,
 313                .prio   = IPIC_SIPRR_B,
 314                .force  = IPIC_SIFCR_H,
 315                .bit    = 15,
 316                .prio_mask = 7,
 317        },
 318        [48] = {
 319                .mask   = IPIC_SEMSR,
 320                .prio   = IPIC_SMPRR_A,
 321                .force  = IPIC_SEFCR,
 322                .bit    = 0,
 323                .prio_mask = 4,
 324        },
 325        [64] = {
 326                .mask   = IPIC_SIMSR_L,
 327                .prio   = IPIC_SMPRR_A,
 328                .force  = IPIC_SIFCR_L,
 329                .bit    = 0,
 330                .prio_mask = 0,
 331        },
 332        [65] = {
 333                .mask   = IPIC_SIMSR_L,
 334                .prio   = IPIC_SMPRR_A,
 335                .force  = IPIC_SIFCR_L,
 336                .bit    = 1,
 337                .prio_mask = 1,
 338        },
 339        [66] = {
 340                .mask   = IPIC_SIMSR_L,
 341                .prio   = IPIC_SMPRR_A,
 342                .force  = IPIC_SIFCR_L,
 343                .bit    = 2,
 344                .prio_mask = 2,
 345        },
 346        [67] = {
 347                .mask   = IPIC_SIMSR_L,
 348                .prio   = IPIC_SMPRR_A,
 349                .force  = IPIC_SIFCR_L,
 350                .bit    = 3,
 351                .prio_mask = 3,
 352        },
 353        [68] = {
 354                .mask   = IPIC_SIMSR_L,
 355                .prio   = IPIC_SMPRR_B,
 356                .force  = IPIC_SIFCR_L,
 357                .bit    = 4,
 358                .prio_mask = 0,
 359        },
 360        [69] = {
 361                .mask   = IPIC_SIMSR_L,
 362                .prio   = IPIC_SMPRR_B,
 363                .force  = IPIC_SIFCR_L,
 364                .bit    = 5,
 365                .prio_mask = 1,
 366        },
 367        [70] = {
 368                .mask   = IPIC_SIMSR_L,
 369                .prio   = IPIC_SMPRR_B,
 370                .force  = IPIC_SIFCR_L,
 371                .bit    = 6,
 372                .prio_mask = 2,
 373        },
 374        [71] = {
 375                .mask   = IPIC_SIMSR_L,
 376                .prio   = IPIC_SMPRR_B,
 377                .force  = IPIC_SIFCR_L,
 378                .bit    = 7,
 379                .prio_mask = 3,
 380        },
 381        [72] = {
 382                .mask   = IPIC_SIMSR_L,
 383                .prio   = 0,
 384                .force  = IPIC_SIFCR_L,
 385                .bit    = 8,
 386        },
 387        [73] = {
 388                .mask   = IPIC_SIMSR_L,
 389                .prio   = 0,
 390                .force  = IPIC_SIFCR_L,
 391                .bit    = 9,
 392        },
 393        [74] = {
 394                .mask   = IPIC_SIMSR_L,
 395                .prio   = 0,
 396                .force  = IPIC_SIFCR_L,
 397                .bit    = 10,
 398        },
 399        [75] = {
 400                .mask   = IPIC_SIMSR_L,
 401                .prio   = 0,
 402                .force  = IPIC_SIFCR_L,
 403                .bit    = 11,
 404        },
 405        [76] = {
 406                .mask   = IPIC_SIMSR_L,
 407                .prio   = 0,
 408                .force  = IPIC_SIFCR_L,
 409                .bit    = 12,
 410        },
 411        [77] = {
 412                .mask   = IPIC_SIMSR_L,
 413                .prio   = 0,
 414                .force  = IPIC_SIFCR_L,
 415                .bit    = 13,
 416        },
 417        [78] = {
 418                .mask   = IPIC_SIMSR_L,
 419                .prio   = 0,
 420                .force  = IPIC_SIFCR_L,
 421                .bit    = 14,
 422        },
 423        [79] = {
 424                .mask   = IPIC_SIMSR_L,
 425                .prio   = 0,
 426                .force  = IPIC_SIFCR_L,
 427                .bit    = 15,
 428        },
 429        [80] = {
 430                .mask   = IPIC_SIMSR_L,
 431                .prio   = 0,
 432                .force  = IPIC_SIFCR_L,
 433                .bit    = 16,
 434        },
 435        [81] = {
 436                .mask   = IPIC_SIMSR_L,
 437                .prio   = 0,
 438                .force  = IPIC_SIFCR_L,
 439                .bit    = 17,
 440        },
 441        [82] = {
 442                .mask   = IPIC_SIMSR_L,
 443                .prio   = 0,
 444                .force  = IPIC_SIFCR_L,
 445                .bit    = 18,
 446        },
 447        [83] = {
 448                .mask   = IPIC_SIMSR_L,
 449                .prio   = 0,
 450                .force  = IPIC_SIFCR_L,
 451                .bit    = 19,
 452        },
 453        [84] = {
 454                .mask   = IPIC_SIMSR_L,
 455                .prio   = 0,
 456                .force  = IPIC_SIFCR_L,
 457                .bit    = 20,
 458        },
 459        [85] = {
 460                .mask   = IPIC_SIMSR_L,
 461                .prio   = 0,
 462                .force  = IPIC_SIFCR_L,
 463                .bit    = 21,
 464        },
 465        [86] = {
 466                .mask   = IPIC_SIMSR_L,
 467                .prio   = 0,
 468                .force  = IPIC_SIFCR_L,
 469                .bit    = 22,
 470        },
 471        [87] = {
 472                .mask   = IPIC_SIMSR_L,
 473                .prio   = 0,
 474                .force  = IPIC_SIFCR_L,
 475                .bit    = 23,
 476        },
 477        [88] = {
 478                .mask   = IPIC_SIMSR_L,
 479                .prio   = 0,
 480                .force  = IPIC_SIFCR_L,
 481                .bit    = 24,
 482        },
 483        [89] = {
 484                .mask   = IPIC_SIMSR_L,
 485                .prio   = 0,
 486                .force  = IPIC_SIFCR_L,
 487                .bit    = 25,
 488        },
 489        [90] = {
 490                .mask   = IPIC_SIMSR_L,
 491                .prio   = 0,
 492                .force  = IPIC_SIFCR_L,
 493                .bit    = 26,
 494        },
 495        [91] = {
 496                .mask   = IPIC_SIMSR_L,
 497                .prio   = 0,
 498                .force  = IPIC_SIFCR_L,
 499                .bit    = 27,
 500        },
 501        [94] = {
 502                .mask   = IPIC_SIMSR_L,
 503                .prio   = 0,
 504                .force  = IPIC_SIFCR_L,
 505                .bit    = 30,
 506        },
 507};
 508
 509static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
 510{
 511        return in_be32(base + (reg >> 2));
 512}
 513
 514static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
 515{
 516        out_be32(base + (reg >> 2), value);
 517}
 518
 519static inline struct ipic * ipic_from_irq(unsigned int virq)
 520{
 521        return primary_ipic;
 522}
 523
 524static void ipic_unmask_irq(struct irq_data *d)
 525{
 526        struct ipic *ipic = ipic_from_irq(d->irq);
 527        unsigned int src = irqd_to_hwirq(d);
 528        unsigned long flags;
 529        u32 temp;
 530
 531        raw_spin_lock_irqsave(&ipic_lock, flags);
 532
 533        temp = ipic_read(ipic->regs, ipic_info[src].mask);
 534        temp |= (1 << (31 - ipic_info[src].bit));
 535        ipic_write(ipic->regs, ipic_info[src].mask, temp);
 536
 537        raw_spin_unlock_irqrestore(&ipic_lock, flags);
 538}
 539
 540static void ipic_mask_irq(struct irq_data *d)
 541{
 542        struct ipic *ipic = ipic_from_irq(d->irq);
 543        unsigned int src = irqd_to_hwirq(d);
 544        unsigned long flags;
 545        u32 temp;
 546
 547        raw_spin_lock_irqsave(&ipic_lock, flags);
 548
 549        temp = ipic_read(ipic->regs, ipic_info[src].mask);
 550        temp &= ~(1 << (31 - ipic_info[src].bit));
 551        ipic_write(ipic->regs, ipic_info[src].mask, temp);
 552
 553        /* mb() can't guarantee that masking is finished.  But it does finish
 554         * for nearly all cases. */
 555        mb();
 556
 557        raw_spin_unlock_irqrestore(&ipic_lock, flags);
 558}
 559
 560static void ipic_ack_irq(struct irq_data *d)
 561{
 562        struct ipic *ipic = ipic_from_irq(d->irq);
 563        unsigned int src = irqd_to_hwirq(d);
 564        unsigned long flags;
 565        u32 temp;
 566
 567        raw_spin_lock_irqsave(&ipic_lock, flags);
 568
 569        temp = 1 << (31 - ipic_info[src].bit);
 570        ipic_write(ipic->regs, ipic_info[src].ack, temp);
 571
 572        /* mb() can't guarantee that ack is finished.  But it does finish
 573         * for nearly all cases. */
 574        mb();
 575
 576        raw_spin_unlock_irqrestore(&ipic_lock, flags);
 577}
 578
 579static void ipic_mask_irq_and_ack(struct irq_data *d)
 580{
 581        struct ipic *ipic = ipic_from_irq(d->irq);
 582        unsigned int src = irqd_to_hwirq(d);
 583        unsigned long flags;
 584        u32 temp;
 585
 586        raw_spin_lock_irqsave(&ipic_lock, flags);
 587
 588        temp = ipic_read(ipic->regs, ipic_info[src].mask);
 589        temp &= ~(1 << (31 - ipic_info[src].bit));
 590        ipic_write(ipic->regs, ipic_info[src].mask, temp);
 591
 592        temp = 1 << (31 - ipic_info[src].bit);
 593        ipic_write(ipic->regs, ipic_info[src].ack, temp);
 594
 595        /* mb() can't guarantee that ack is finished.  But it does finish
 596         * for nearly all cases. */
 597        mb();
 598
 599        raw_spin_unlock_irqrestore(&ipic_lock, flags);
 600}
 601
 602static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 603{
 604        struct ipic *ipic = ipic_from_irq(d->irq);
 605        unsigned int src = irqd_to_hwirq(d);
 606        unsigned int vold, vnew, edibit;
 607
 608        if (flow_type == IRQ_TYPE_NONE)
 609                flow_type = IRQ_TYPE_LEVEL_LOW;
 610
 611        /* ipic supports only low assertion and high-to-low change senses
 612         */
 613        if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
 614                printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
 615                        flow_type);
 616                return -EINVAL;
 617        }
 618        /* ipic supports only edge mode on external interrupts */
 619        if ((flow_type & IRQ_TYPE_EDGE_FALLING) && !ipic_info[src].ack) {
 620                printk(KERN_ERR "ipic: edge sense not supported on internal "
 621                                "interrupts\n");
 622                return -EINVAL;
 623
 624        }
 625
 626        irqd_set_trigger_type(d, flow_type);
 627        if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
 628                __irq_set_handler_locked(d->irq, handle_level_irq);
 629                d->chip = &ipic_level_irq_chip;
 630        } else {
 631                __irq_set_handler_locked(d->irq, handle_edge_irq);
 632                d->chip = &ipic_edge_irq_chip;
 633        }
 634
 635        /* only EXT IRQ senses are programmable on ipic
 636         * internal IRQ senses are LEVEL_LOW
 637         */
 638        if (src == IPIC_IRQ_EXT0)
 639                edibit = 15;
 640        else
 641                if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
 642                        edibit = (14 - (src - IPIC_IRQ_EXT1));
 643                else
 644                        return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
 645
 646        vold = ipic_read(ipic->regs, IPIC_SECNR);
 647        if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
 648                vnew = vold | (1 << edibit);
 649        } else {
 650                vnew = vold & ~(1 << edibit);
 651        }
 652        if (vold != vnew)
 653                ipic_write(ipic->regs, IPIC_SECNR, vnew);
 654        return IRQ_SET_MASK_OK_NOCOPY;
 655}
 656
 657/* level interrupts and edge interrupts have different ack operations */
 658static struct irq_chip ipic_level_irq_chip = {
 659        .name           = "IPIC",
 660        .irq_unmask     = ipic_unmask_irq,
 661        .irq_mask       = ipic_mask_irq,
 662        .irq_mask_ack   = ipic_mask_irq,
 663        .irq_set_type   = ipic_set_irq_type,
 664};
 665
 666static struct irq_chip ipic_edge_irq_chip = {
 667        .name           = "IPIC",
 668        .irq_unmask     = ipic_unmask_irq,
 669        .irq_mask       = ipic_mask_irq,
 670        .irq_mask_ack   = ipic_mask_irq_and_ack,
 671        .irq_ack        = ipic_ack_irq,
 672        .irq_set_type   = ipic_set_irq_type,
 673};
 674
 675static int ipic_host_match(struct irq_domain *h, struct device_node *node)
 676{
 677        /* Exact match, unless ipic node is NULL */
 678        return h->of_node == NULL || h->of_node == node;
 679}
 680
 681static int ipic_host_map(struct irq_domain *h, unsigned int virq,
 682                         irq_hw_number_t hw)
 683{
 684        struct ipic *ipic = h->host_data;
 685
 686        irq_set_chip_data(virq, ipic);
 687        irq_set_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
 688
 689        /* Set default irq type */
 690        irq_set_irq_type(virq, IRQ_TYPE_NONE);
 691
 692        return 0;
 693}
 694
 695static struct irq_domain_ops ipic_host_ops = {
 696        .match  = ipic_host_match,
 697        .map    = ipic_host_map,
 698        .xlate  = irq_domain_xlate_onetwocell,
 699};
 700
 701struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
 702{
 703        struct ipic     *ipic;
 704        struct resource res;
 705        u32 temp = 0, ret;
 706
 707        ret = of_address_to_resource(node, 0, &res);
 708        if (ret)
 709                return NULL;
 710
 711        ipic = kzalloc(sizeof(*ipic), GFP_KERNEL);
 712        if (ipic == NULL)
 713                return NULL;
 714
 715        ipic->irqhost = irq_domain_add_linear(node, NR_IPIC_INTS,
 716                                              &ipic_host_ops, ipic);
 717        if (ipic->irqhost == NULL) {
 718                kfree(ipic);
 719                return NULL;
 720        }
 721
 722        ipic->regs = ioremap(res.start, resource_size(&res));
 723
 724        /* init hw */
 725        ipic_write(ipic->regs, IPIC_SICNR, 0x0);
 726
 727        /* default priority scheme is grouped. If spread mode is required
 728         * configure SICFR accordingly */
 729        if (flags & IPIC_SPREADMODE_GRP_A)
 730                temp |= SICFR_IPSA;
 731        if (flags & IPIC_SPREADMODE_GRP_B)
 732                temp |= SICFR_IPSB;
 733        if (flags & IPIC_SPREADMODE_GRP_C)
 734                temp |= SICFR_IPSC;
 735        if (flags & IPIC_SPREADMODE_GRP_D)
 736                temp |= SICFR_IPSD;
 737        if (flags & IPIC_SPREADMODE_MIX_A)
 738                temp |= SICFR_MPSA;
 739        if (flags & IPIC_SPREADMODE_MIX_B)
 740                temp |= SICFR_MPSB;
 741
 742        ipic_write(ipic->regs, IPIC_SICFR, temp);
 743
 744        /* handle MCP route */
 745        temp = 0;
 746        if (flags & IPIC_DISABLE_MCP_OUT)
 747                temp = SERCR_MCPR;
 748        ipic_write(ipic->regs, IPIC_SERCR, temp);
 749
 750        /* handle routing of IRQ0 to MCP */
 751        temp = ipic_read(ipic->regs, IPIC_SEMSR);
 752
 753        if (flags & IPIC_IRQ0_MCP)
 754                temp |= SEMSR_SIRQ0;
 755        else
 756                temp &= ~SEMSR_SIRQ0;
 757
 758        ipic_write(ipic->regs, IPIC_SEMSR, temp);
 759
 760        primary_ipic = ipic;
 761        irq_set_default_host(primary_ipic->irqhost);
 762
 763        ipic_write(ipic->regs, IPIC_SIMSR_H, 0);
 764        ipic_write(ipic->regs, IPIC_SIMSR_L, 0);
 765
 766        printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
 767                        primary_ipic->regs);
 768
 769        return ipic;
 770}
 771
 772int ipic_set_priority(unsigned int virq, unsigned int priority)
 773{
 774        struct ipic *ipic = ipic_from_irq(virq);
 775        unsigned int src = virq_to_hw(virq);
 776        u32 temp;
 777
 778        if (priority > 7)
 779                return -EINVAL;
 780        if (src > 127)
 781                return -EINVAL;
 782        if (ipic_info[src].prio == 0)
 783                return -EINVAL;
 784
 785        temp = ipic_read(ipic->regs, ipic_info[src].prio);
 786
 787        if (priority < 4) {
 788                temp &= ~(0x7 << (20 + (3 - priority) * 3));
 789                temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
 790        } else {
 791                temp &= ~(0x7 << (4 + (7 - priority) * 3));
 792                temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
 793        }
 794
 795        ipic_write(ipic->regs, ipic_info[src].prio, temp);
 796
 797        return 0;
 798}
 799
 800void ipic_set_highest_priority(unsigned int virq)
 801{
 802        struct ipic *ipic = ipic_from_irq(virq);
 803        unsigned int src = virq_to_hw(virq);
 804        u32 temp;
 805
 806        temp = ipic_read(ipic->regs, IPIC_SICFR);
 807
 808        /* clear and set HPI */
 809        temp &= 0x7f000000;
 810        temp |= (src & 0x7f) << 24;
 811
 812        ipic_write(ipic->regs, IPIC_SICFR, temp);
 813}
 814
 815void ipic_set_default_priority(void)
 816{
 817        ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_PRIORITY_DEFAULT);
 818        ipic_write(primary_ipic->regs, IPIC_SIPRR_B, IPIC_PRIORITY_DEFAULT);
 819        ipic_write(primary_ipic->regs, IPIC_SIPRR_C, IPIC_PRIORITY_DEFAULT);
 820        ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_PRIORITY_DEFAULT);
 821        ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_PRIORITY_DEFAULT);
 822        ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_PRIORITY_DEFAULT);
 823}
 824
 825void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
 826{
 827        struct ipic *ipic = primary_ipic;
 828        u32 temp;
 829
 830        temp = ipic_read(ipic->regs, IPIC_SERMR);
 831        temp |= (1 << (31 - mcp_irq));
 832        ipic_write(ipic->regs, IPIC_SERMR, temp);
 833}
 834
 835void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
 836{
 837        struct ipic *ipic = primary_ipic;
 838        u32 temp;
 839
 840        temp = ipic_read(ipic->regs, IPIC_SERMR);
 841        temp &= (1 << (31 - mcp_irq));
 842        ipic_write(ipic->regs, IPIC_SERMR, temp);
 843}
 844
 845u32 ipic_get_mcp_status(void)
 846{
 847        return ipic_read(primary_ipic->regs, IPIC_SERMR);
 848}
 849
 850void ipic_clear_mcp_status(u32 mask)
 851{
 852        ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
 853}
 854
 855/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
 856unsigned int ipic_get_irq(void)
 857{
 858        int irq;
 859
 860        BUG_ON(primary_ipic == NULL);
 861
 862#define IPIC_SIVCR_VECTOR_MASK  0x7f
 863        irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
 864
 865        if (irq == 0)    /* 0 --> no irq is pending */
 866                return NO_IRQ;
 867
 868        return irq_linear_revmap(primary_ipic->irqhost, irq);
 869}
 870
 871#ifdef CONFIG_SUSPEND
 872static struct {
 873        u32 sicfr;
 874        u32 siprr[2];
 875        u32 simsr[2];
 876        u32 sicnr;
 877        u32 smprr[2];
 878        u32 semsr;
 879        u32 secnr;
 880        u32 sermr;
 881        u32 sercr;
 882} ipic_saved_state;
 883
 884static int ipic_suspend(void)
 885{
 886        struct ipic *ipic = primary_ipic;
 887
 888        ipic_saved_state.sicfr = ipic_read(ipic->regs, IPIC_SICFR);
 889        ipic_saved_state.siprr[0] = ipic_read(ipic->regs, IPIC_SIPRR_A);
 890        ipic_saved_state.siprr[1] = ipic_read(ipic->regs, IPIC_SIPRR_D);
 891        ipic_saved_state.simsr[0] = ipic_read(ipic->regs, IPIC_SIMSR_H);
 892        ipic_saved_state.simsr[1] = ipic_read(ipic->regs, IPIC_SIMSR_L);
 893        ipic_saved_state.sicnr = ipic_read(ipic->regs, IPIC_SICNR);
 894        ipic_saved_state.smprr[0] = ipic_read(ipic->regs, IPIC_SMPRR_A);
 895        ipic_saved_state.smprr[1] = ipic_read(ipic->regs, IPIC_SMPRR_B);
 896        ipic_saved_state.semsr = ipic_read(ipic->regs, IPIC_SEMSR);
 897        ipic_saved_state.secnr = ipic_read(ipic->regs, IPIC_SECNR);
 898        ipic_saved_state.sermr = ipic_read(ipic->regs, IPIC_SERMR);
 899        ipic_saved_state.sercr = ipic_read(ipic->regs, IPIC_SERCR);
 900
 901        if (fsl_deep_sleep()) {
 902                /* In deep sleep, make sure there can be no
 903                 * pending interrupts, as this can cause
 904                 * problems on 831x.
 905                 */
 906                ipic_write(ipic->regs, IPIC_SIMSR_H, 0);
 907                ipic_write(ipic->regs, IPIC_SIMSR_L, 0);
 908                ipic_write(ipic->regs, IPIC_SEMSR, 0);
 909                ipic_write(ipic->regs, IPIC_SERMR, 0);
 910        }
 911
 912        return 0;
 913}
 914
 915static void ipic_resume(void)
 916{
 917        struct ipic *ipic = primary_ipic;
 918
 919        ipic_write(ipic->regs, IPIC_SICFR, ipic_saved_state.sicfr);
 920        ipic_write(ipic->regs, IPIC_SIPRR_A, ipic_saved_state.siprr[0]);
 921        ipic_write(ipic->regs, IPIC_SIPRR_D, ipic_saved_state.siprr[1]);
 922        ipic_write(ipic->regs, IPIC_SIMSR_H, ipic_saved_state.simsr[0]);
 923        ipic_write(ipic->regs, IPIC_SIMSR_L, ipic_saved_state.simsr[1]);
 924        ipic_write(ipic->regs, IPIC_SICNR, ipic_saved_state.sicnr);
 925        ipic_write(ipic->regs, IPIC_SMPRR_A, ipic_saved_state.smprr[0]);
 926        ipic_write(ipic->regs, IPIC_SMPRR_B, ipic_saved_state.smprr[1]);
 927        ipic_write(ipic->regs, IPIC_SEMSR, ipic_saved_state.semsr);
 928        ipic_write(ipic->regs, IPIC_SECNR, ipic_saved_state.secnr);
 929        ipic_write(ipic->regs, IPIC_SERMR, ipic_saved_state.sermr);
 930        ipic_write(ipic->regs, IPIC_SERCR, ipic_saved_state.sercr);
 931}
 932#else
 933#define ipic_suspend NULL
 934#define ipic_resume NULL
 935#endif
 936
 937static struct syscore_ops ipic_syscore_ops = {
 938        .suspend = ipic_suspend,
 939        .resume = ipic_resume,
 940};
 941
 942static int __init init_ipic_syscore(void)
 943{
 944        if (!primary_ipic || !primary_ipic->regs)
 945                return -ENODEV;
 946
 947        printk(KERN_DEBUG "Registering ipic system core operations\n");
 948        register_syscore_ops(&ipic_syscore_ops);
 949
 950        return 0;
 951}
 952
 953subsys_initcall(init_ipic_syscore);
 954