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/sysdev.h>
  22#include <linux/device.h>
  23#include <linux/bootmem.h>
  24#include <linux/spinlock.h>
  25#include <asm/irq.h>
  26#include <asm/io.h>
  27#include <asm/prom.h>
  28#include <asm/ipic.h>
  29
  30#include "ipic.h"
  31
  32static struct ipic * primary_ipic;
  33static DEFINE_SPINLOCK(ipic_lock);
  34
  35static struct ipic_info ipic_info[] = {
  36        [9] = {
  37                .pend   = IPIC_SIPNR_H,
  38                .mask   = IPIC_SIMSR_H,
  39                .prio   = IPIC_SIPRR_D,
  40                .force  = IPIC_SIFCR_H,
  41                .bit    = 24,
  42                .prio_mask = 0,
  43        },
  44        [10] = {
  45                .pend   = IPIC_SIPNR_H,
  46                .mask   = IPIC_SIMSR_H,
  47                .prio   = IPIC_SIPRR_D,
  48                .force  = IPIC_SIFCR_H,
  49                .bit    = 25,
  50                .prio_mask = 1,
  51        },
  52        [11] = {
  53                .pend   = IPIC_SIPNR_H,
  54                .mask   = IPIC_SIMSR_H,
  55                .prio   = IPIC_SIPRR_D,
  56                .force  = IPIC_SIFCR_H,
  57                .bit    = 26,
  58                .prio_mask = 2,
  59        },
  60        [14] = {
  61                .pend   = IPIC_SIPNR_H,
  62                .mask   = IPIC_SIMSR_H,
  63                .prio   = IPIC_SIPRR_D,
  64                .force  = IPIC_SIFCR_H,
  65                .bit    = 29,
  66                .prio_mask = 5,
  67        },
  68        [15] = {
  69                .pend   = IPIC_SIPNR_H,
  70                .mask   = IPIC_SIMSR_H,
  71                .prio   = IPIC_SIPRR_D,
  72                .force  = IPIC_SIFCR_H,
  73                .bit    = 30,
  74                .prio_mask = 6,
  75        },
  76        [16] = {
  77                .pend   = IPIC_SIPNR_H,
  78                .mask   = IPIC_SIMSR_H,
  79                .prio   = IPIC_SIPRR_D,
  80                .force  = IPIC_SIFCR_H,
  81                .bit    = 31,
  82                .prio_mask = 7,
  83        },
  84        [17] = {
  85                .pend   = IPIC_SEPNR,
  86                .mask   = IPIC_SEMSR,
  87                .prio   = IPIC_SMPRR_A,
  88                .force  = IPIC_SEFCR,
  89                .bit    = 1,
  90                .prio_mask = 5,
  91        },
  92        [18] = {
  93                .pend   = IPIC_SEPNR,
  94                .mask   = IPIC_SEMSR,
  95                .prio   = IPIC_SMPRR_A,
  96                .force  = IPIC_SEFCR,
  97                .bit    = 2,
  98                .prio_mask = 6,
  99        },
 100        [19] = {
 101                .pend   = IPIC_SEPNR,
 102                .mask   = IPIC_SEMSR,
 103                .prio   = IPIC_SMPRR_A,
 104                .force  = IPIC_SEFCR,
 105                .bit    = 3,
 106                .prio_mask = 7,
 107        },
 108        [20] = {
 109                .pend   = IPIC_SEPNR,
 110                .mask   = IPIC_SEMSR,
 111                .prio   = IPIC_SMPRR_B,
 112                .force  = IPIC_SEFCR,
 113                .bit    = 4,
 114                .prio_mask = 4,
 115        },
 116        [21] = {
 117                .pend   = IPIC_SEPNR,
 118                .mask   = IPIC_SEMSR,
 119                .prio   = IPIC_SMPRR_B,
 120                .force  = IPIC_SEFCR,
 121                .bit    = 5,
 122                .prio_mask = 5,
 123        },
 124        [22] = {
 125                .pend   = IPIC_SEPNR,
 126                .mask   = IPIC_SEMSR,
 127                .prio   = IPIC_SMPRR_B,
 128                .force  = IPIC_SEFCR,
 129                .bit    = 6,
 130                .prio_mask = 6,
 131        },
 132        [23] = {
 133                .pend   = IPIC_SEPNR,
 134                .mask   = IPIC_SEMSR,
 135                .prio   = IPIC_SMPRR_B,
 136                .force  = IPIC_SEFCR,
 137                .bit    = 7,
 138                .prio_mask = 7,
 139        },
 140        [32] = {
 141                .pend   = IPIC_SIPNR_H,
 142                .mask   = IPIC_SIMSR_H,
 143                .prio   = IPIC_SIPRR_A,
 144                .force  = IPIC_SIFCR_H,
 145                .bit    = 0,
 146                .prio_mask = 0,
 147        },
 148        [33] = {
 149                .pend   = IPIC_SIPNR_H,
 150                .mask   = IPIC_SIMSR_H,
 151                .prio   = IPIC_SIPRR_A,
 152                .force  = IPIC_SIFCR_H,
 153                .bit    = 1,
 154                .prio_mask = 1,
 155        },
 156        [34] = {
 157                .pend   = IPIC_SIPNR_H,
 158                .mask   = IPIC_SIMSR_H,
 159                .prio   = IPIC_SIPRR_A,
 160                .force  = IPIC_SIFCR_H,
 161                .bit    = 2,
 162                .prio_mask = 2,
 163        },
 164        [35] = {
 165                .pend   = IPIC_SIPNR_H,
 166                .mask   = IPIC_SIMSR_H,
 167                .prio   = IPIC_SIPRR_A,
 168                .force  = IPIC_SIFCR_H,
 169                .bit    = 3,
 170                .prio_mask = 3,
 171        },
 172        [36] = {
 173                .pend   = IPIC_SIPNR_H,
 174                .mask   = IPIC_SIMSR_H,
 175                .prio   = IPIC_SIPRR_A,
 176                .force  = IPIC_SIFCR_H,
 177                .bit    = 4,
 178                .prio_mask = 4,
 179        },
 180        [37] = {
 181                .pend   = IPIC_SIPNR_H,
 182                .mask   = IPIC_SIMSR_H,
 183                .prio   = IPIC_SIPRR_A,
 184                .force  = IPIC_SIFCR_H,
 185                .bit    = 5,
 186                .prio_mask = 5,
 187        },
 188        [38] = {
 189                .pend   = IPIC_SIPNR_H,
 190                .mask   = IPIC_SIMSR_H,
 191                .prio   = IPIC_SIPRR_A,
 192                .force  = IPIC_SIFCR_H,
 193                .bit    = 6,
 194                .prio_mask = 6,
 195        },
 196        [39] = {
 197                .pend   = IPIC_SIPNR_H,
 198                .mask   = IPIC_SIMSR_H,
 199                .prio   = IPIC_SIPRR_A,
 200                .force  = IPIC_SIFCR_H,
 201                .bit    = 7,
 202                .prio_mask = 7,
 203        },
 204        [48] = {
 205                .pend   = IPIC_SEPNR,
 206                .mask   = IPIC_SEMSR,
 207                .prio   = IPIC_SMPRR_A,
 208                .force  = IPIC_SEFCR,
 209                .bit    = 0,
 210                .prio_mask = 4,
 211        },
 212        [64] = {
 213                .pend   = IPIC_SIPNR_L,
 214                .mask   = IPIC_SIMSR_L,
 215                .prio   = IPIC_SMPRR_A,
 216                .force  = IPIC_SIFCR_L,
 217                .bit    = 0,
 218                .prio_mask = 0,
 219        },
 220        [65] = {
 221                .pend   = IPIC_SIPNR_L,
 222                .mask   = IPIC_SIMSR_L,
 223                .prio   = IPIC_SMPRR_A,
 224                .force  = IPIC_SIFCR_L,
 225                .bit    = 1,
 226                .prio_mask = 1,
 227        },
 228        [66] = {
 229                .pend   = IPIC_SIPNR_L,
 230                .mask   = IPIC_SIMSR_L,
 231                .prio   = IPIC_SMPRR_A,
 232                .force  = IPIC_SIFCR_L,
 233                .bit    = 2,
 234                .prio_mask = 2,
 235        },
 236        [67] = {
 237                .pend   = IPIC_SIPNR_L,
 238                .mask   = IPIC_SIMSR_L,
 239                .prio   = IPIC_SMPRR_A,
 240                .force  = IPIC_SIFCR_L,
 241                .bit    = 3,
 242                .prio_mask = 3,
 243        },
 244        [68] = {
 245                .pend   = IPIC_SIPNR_L,
 246                .mask   = IPIC_SIMSR_L,
 247                .prio   = IPIC_SMPRR_B,
 248                .force  = IPIC_SIFCR_L,
 249                .bit    = 4,
 250                .prio_mask = 0,
 251        },
 252        [69] = {
 253                .pend   = IPIC_SIPNR_L,
 254                .mask   = IPIC_SIMSR_L,
 255                .prio   = IPIC_SMPRR_B,
 256                .force  = IPIC_SIFCR_L,
 257                .bit    = 5,
 258                .prio_mask = 1,
 259        },
 260        [70] = {
 261                .pend   = IPIC_SIPNR_L,
 262                .mask   = IPIC_SIMSR_L,
 263                .prio   = IPIC_SMPRR_B,
 264                .force  = IPIC_SIFCR_L,
 265                .bit    = 6,
 266                .prio_mask = 2,
 267        },
 268        [71] = {
 269                .pend   = IPIC_SIPNR_L,
 270                .mask   = IPIC_SIMSR_L,
 271                .prio   = IPIC_SMPRR_B,
 272                .force  = IPIC_SIFCR_L,
 273                .bit    = 7,
 274                .prio_mask = 3,
 275        },
 276        [72] = {
 277                .pend   = IPIC_SIPNR_L,
 278                .mask   = IPIC_SIMSR_L,
 279                .prio   = 0,
 280                .force  = IPIC_SIFCR_L,
 281                .bit    = 8,
 282        },
 283        [73] = {
 284                .pend   = IPIC_SIPNR_L,
 285                .mask   = IPIC_SIMSR_L,
 286                .prio   = 0,
 287                .force  = IPIC_SIFCR_L,
 288                .bit    = 9,
 289        },
 290        [74] = {
 291                .pend   = IPIC_SIPNR_L,
 292                .mask   = IPIC_SIMSR_L,
 293                .prio   = 0,
 294                .force  = IPIC_SIFCR_L,
 295                .bit    = 10,
 296        },
 297        [75] = {
 298                .pend   = IPIC_SIPNR_L,
 299                .mask   = IPIC_SIMSR_L,
 300                .prio   = 0,
 301                .force  = IPIC_SIFCR_L,
 302                .bit    = 11,
 303        },
 304        [76] = {
 305                .pend   = IPIC_SIPNR_L,
 306                .mask   = IPIC_SIMSR_L,
 307                .prio   = 0,
 308                .force  = IPIC_SIFCR_L,
 309                .bit    = 12,
 310        },
 311        [77] = {
 312                .pend   = IPIC_SIPNR_L,
 313                .mask   = IPIC_SIMSR_L,
 314                .prio   = 0,
 315                .force  = IPIC_SIFCR_L,
 316                .bit    = 13,
 317        },
 318        [78] = {
 319                .pend   = IPIC_SIPNR_L,
 320                .mask   = IPIC_SIMSR_L,
 321                .prio   = 0,
 322                .force  = IPIC_SIFCR_L,
 323                .bit    = 14,
 324        },
 325        [79] = {
 326                .pend   = IPIC_SIPNR_L,
 327                .mask   = IPIC_SIMSR_L,
 328                .prio   = 0,
 329                .force  = IPIC_SIFCR_L,
 330                .bit    = 15,
 331        },
 332        [80] = {
 333                .pend   = IPIC_SIPNR_L,
 334                .mask   = IPIC_SIMSR_L,
 335                .prio   = 0,
 336                .force  = IPIC_SIFCR_L,
 337                .bit    = 16,
 338        },
 339        [84] = {
 340                .pend   = IPIC_SIPNR_L,
 341                .mask   = IPIC_SIMSR_L,
 342                .prio   = 0,
 343                .force  = IPIC_SIFCR_L,
 344                .bit    = 20,
 345        },
 346        [85] = {
 347                .pend   = IPIC_SIPNR_L,
 348                .mask   = IPIC_SIMSR_L,
 349                .prio   = 0,
 350                .force  = IPIC_SIFCR_L,
 351                .bit    = 21,
 352        },
 353        [90] = {
 354                .pend   = IPIC_SIPNR_L,
 355                .mask   = IPIC_SIMSR_L,
 356                .prio   = 0,
 357                .force  = IPIC_SIFCR_L,
 358                .bit    = 26,
 359        },
 360        [91] = {
 361                .pend   = IPIC_SIPNR_L,
 362                .mask   = IPIC_SIMSR_L,
 363                .prio   = 0,
 364                .force  = IPIC_SIFCR_L,
 365                .bit    = 27,
 366        },
 367};
 368
 369static inline u32 ipic_read(volatile u32 __iomem *base, unsigned int reg)
 370{
 371        return in_be32(base + (reg >> 2));
 372}
 373
 374static inline void ipic_write(volatile u32 __iomem *base, unsigned int reg, u32 value)
 375{
 376        out_be32(base + (reg >> 2), value);
 377}
 378
 379static inline struct ipic * ipic_from_irq(unsigned int virq)
 380{
 381        return primary_ipic;
 382}
 383
 384#define ipic_irq_to_hw(virq)    ((unsigned int)irq_map[virq].hwirq)
 385
 386static void ipic_unmask_irq(unsigned int virq)
 387{
 388        struct ipic *ipic = ipic_from_irq(virq);
 389        unsigned int src = ipic_irq_to_hw(virq);
 390        unsigned long flags;
 391        u32 temp;
 392
 393        spin_lock_irqsave(&ipic_lock, flags);
 394
 395        temp = ipic_read(ipic->regs, ipic_info[src].mask);
 396        temp |= (1 << (31 - ipic_info[src].bit));
 397        ipic_write(ipic->regs, ipic_info[src].mask, temp);
 398
 399        spin_unlock_irqrestore(&ipic_lock, flags);
 400}
 401
 402static void ipic_mask_irq(unsigned int virq)
 403{
 404        struct ipic *ipic = ipic_from_irq(virq);
 405        unsigned int src = ipic_irq_to_hw(virq);
 406        unsigned long flags;
 407        u32 temp;
 408
 409        spin_lock_irqsave(&ipic_lock, flags);
 410
 411        temp = ipic_read(ipic->regs, ipic_info[src].mask);
 412        temp &= ~(1 << (31 - ipic_info[src].bit));
 413        ipic_write(ipic->regs, ipic_info[src].mask, temp);
 414
 415        spin_unlock_irqrestore(&ipic_lock, flags);
 416}
 417
 418static void ipic_ack_irq(unsigned int virq)
 419{
 420        struct ipic *ipic = ipic_from_irq(virq);
 421        unsigned int src = ipic_irq_to_hw(virq);
 422        unsigned long flags;
 423        u32 temp;
 424
 425        spin_lock_irqsave(&ipic_lock, flags);
 426
 427        temp = ipic_read(ipic->regs, ipic_info[src].pend);
 428        temp |= (1 << (31 - ipic_info[src].bit));
 429        ipic_write(ipic->regs, ipic_info[src].pend, temp);
 430
 431        spin_unlock_irqrestore(&ipic_lock, flags);
 432}
 433
 434static void ipic_mask_irq_and_ack(unsigned int virq)
 435{
 436        struct ipic *ipic = ipic_from_irq(virq);
 437        unsigned int src = ipic_irq_to_hw(virq);
 438        unsigned long flags;
 439        u32 temp;
 440
 441        spin_lock_irqsave(&ipic_lock, flags);
 442
 443        temp = ipic_read(ipic->regs, ipic_info[src].mask);
 444        temp &= ~(1 << (31 - ipic_info[src].bit));
 445        ipic_write(ipic->regs, ipic_info[src].mask, temp);
 446
 447        temp = ipic_read(ipic->regs, ipic_info[src].pend);
 448        temp |= (1 << (31 - ipic_info[src].bit));
 449        ipic_write(ipic->regs, ipic_info[src].pend, temp);
 450
 451        spin_unlock_irqrestore(&ipic_lock, flags);
 452}
 453
 454static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
 455{
 456        struct ipic *ipic = ipic_from_irq(virq);
 457        unsigned int src = ipic_irq_to_hw(virq);
 458        struct irq_desc *desc = get_irq_desc(virq);
 459        unsigned int vold, vnew, edibit;
 460
 461        if (flow_type == IRQ_TYPE_NONE)
 462                flow_type = IRQ_TYPE_LEVEL_LOW;
 463
 464        /* ipic supports only low assertion and high-to-low change senses
 465         */
 466        if (!(flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))) {
 467                printk(KERN_ERR "ipic: sense type 0x%x not supported\n",
 468                        flow_type);
 469                return -EINVAL;
 470        }
 471
 472        desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
 473        desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
 474        if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
 475                desc->status |= IRQ_LEVEL;
 476                desc->handle_irq = handle_level_irq;
 477        } else {
 478                desc->handle_irq = handle_edge_irq;
 479        }
 480
 481        /* only EXT IRQ senses are programmable on ipic
 482         * internal IRQ senses are LEVEL_LOW
 483         */
 484        if (src == IPIC_IRQ_EXT0)
 485                edibit = 15;
 486        else
 487                if (src >= IPIC_IRQ_EXT1 && src <= IPIC_IRQ_EXT7)
 488                        edibit = (14 - (src - IPIC_IRQ_EXT1));
 489                else
 490                        return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
 491
 492        vold = ipic_read(ipic->regs, IPIC_SECNR);
 493        if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING) {
 494                vnew = vold | (1 << edibit);
 495        } else {
 496                vnew = vold & ~(1 << edibit);
 497        }
 498        if (vold != vnew)
 499                ipic_write(ipic->regs, IPIC_SECNR, vnew);
 500        return 0;
 501}
 502
 503static struct irq_chip ipic_irq_chip = {
 504        .typename       = " IPIC  ",
 505        .unmask         = ipic_unmask_irq,
 506        .mask           = ipic_mask_irq,
 507        .mask_ack       = ipic_mask_irq_and_ack,
 508        .ack            = ipic_ack_irq,
 509        .set_type       = ipic_set_irq_type,
 510};
 511
 512static int ipic_host_match(struct irq_host *h, struct device_node *node)
 513{
 514        /* Exact match, unless ipic node is NULL */
 515        return h->of_node == NULL || h->of_node == node;
 516}
 517
 518static int ipic_host_map(struct irq_host *h, unsigned int virq,
 519                         irq_hw_number_t hw)
 520{
 521        struct ipic *ipic = h->host_data;
 522        struct irq_chip *chip;
 523
 524        /* Default chip */
 525        chip = &ipic->hc_irq;
 526
 527        set_irq_chip_data(virq, ipic);
 528        set_irq_chip_and_handler(virq, chip, handle_level_irq);
 529
 530        /* Set default irq type */
 531        set_irq_type(virq, IRQ_TYPE_NONE);
 532
 533        return 0;
 534}
 535
 536static int ipic_host_xlate(struct irq_host *h, struct device_node *ct,
 537                           u32 *intspec, unsigned int intsize,
 538                           irq_hw_number_t *out_hwirq, unsigned int *out_flags)
 539
 540{
 541        /* interrupt sense values coming from the device tree equal either
 542         * LEVEL_LOW (low assertion) or EDGE_FALLING (high-to-low change)
 543         */
 544        *out_hwirq = intspec[0];
 545        if (intsize > 1)
 546                *out_flags = intspec[1];
 547        else
 548                *out_flags = IRQ_TYPE_NONE;
 549        return 0;
 550}
 551
 552static struct irq_host_ops ipic_host_ops = {
 553        .match  = ipic_host_match,
 554        .map    = ipic_host_map,
 555        .xlate  = ipic_host_xlate,
 556};
 557
 558struct ipic * __init ipic_init(struct device_node *node, unsigned int flags)
 559{
 560        struct ipic     *ipic;
 561        struct resource res;
 562        u32 temp = 0, ret;
 563
 564        ipic = alloc_bootmem(sizeof(struct ipic));
 565        if (ipic == NULL)
 566                return NULL;
 567
 568        memset(ipic, 0, sizeof(struct ipic));
 569
 570        ipic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
 571                                       NR_IPIC_INTS,
 572                                       &ipic_host_ops, 0);
 573        if (ipic->irqhost == NULL) {
 574                of_node_put(node);
 575                return NULL;
 576        }
 577
 578        ret = of_address_to_resource(node, 0, &res);
 579        if (ret) {
 580                of_node_put(node);
 581                return NULL;
 582        }
 583
 584        ipic->regs = ioremap(res.start, res.end - res.start + 1);
 585
 586        ipic->irqhost->host_data = ipic;
 587        ipic->hc_irq = ipic_irq_chip;
 588
 589        /* init hw */
 590        ipic_write(ipic->regs, IPIC_SICNR, 0x0);
 591
 592        /* default priority scheme is grouped. If spread mode is required
 593         * configure SICFR accordingly */
 594        if (flags & IPIC_SPREADMODE_GRP_A)
 595                temp |= SICFR_IPSA;
 596        if (flags & IPIC_SPREADMODE_GRP_D)
 597                temp |= SICFR_IPSD;
 598        if (flags & IPIC_SPREADMODE_MIX_A)
 599                temp |= SICFR_MPSA;
 600        if (flags & IPIC_SPREADMODE_MIX_B)
 601                temp |= SICFR_MPSB;
 602
 603        ipic_write(ipic->regs, IPIC_SICNR, temp);
 604
 605        /* handle MCP route */
 606        temp = 0;
 607        if (flags & IPIC_DISABLE_MCP_OUT)
 608                temp = SERCR_MCPR;
 609        ipic_write(ipic->regs, IPIC_SERCR, temp);
 610
 611        /* handle routing of IRQ0 to MCP */
 612        temp = ipic_read(ipic->regs, IPIC_SEMSR);
 613
 614        if (flags & IPIC_IRQ0_MCP)
 615                temp |= SEMSR_SIRQ0;
 616        else
 617                temp &= ~SEMSR_SIRQ0;
 618
 619        ipic_write(ipic->regs, IPIC_SEMSR, temp);
 620
 621        primary_ipic = ipic;
 622        irq_set_default_host(primary_ipic->irqhost);
 623
 624        printk ("IPIC (%d IRQ sources) at %p\n", NR_IPIC_INTS,
 625                        primary_ipic->regs);
 626
 627        return ipic;
 628}
 629
 630int ipic_set_priority(unsigned int virq, unsigned int priority)
 631{
 632        struct ipic *ipic = ipic_from_irq(virq);
 633        unsigned int src = ipic_irq_to_hw(virq);
 634        u32 temp;
 635
 636        if (priority > 7)
 637                return -EINVAL;
 638        if (src > 127)
 639                return -EINVAL;
 640        if (ipic_info[src].prio == 0)
 641                return -EINVAL;
 642
 643        temp = ipic_read(ipic->regs, ipic_info[src].prio);
 644
 645        if (priority < 4) {
 646                temp &= ~(0x7 << (20 + (3 - priority) * 3));
 647                temp |= ipic_info[src].prio_mask << (20 + (3 - priority) * 3);
 648        } else {
 649                temp &= ~(0x7 << (4 + (7 - priority) * 3));
 650                temp |= ipic_info[src].prio_mask << (4 + (7 - priority) * 3);
 651        }
 652
 653        ipic_write(ipic->regs, ipic_info[src].prio, temp);
 654
 655        return 0;
 656}
 657
 658void ipic_set_highest_priority(unsigned int virq)
 659{
 660        struct ipic *ipic = ipic_from_irq(virq);
 661        unsigned int src = ipic_irq_to_hw(virq);
 662        u32 temp;
 663
 664        temp = ipic_read(ipic->regs, IPIC_SICFR);
 665
 666        /* clear and set HPI */
 667        temp &= 0x7f000000;
 668        temp |= (src & 0x7f) << 24;
 669
 670        ipic_write(ipic->regs, IPIC_SICFR, temp);
 671}
 672
 673void ipic_set_default_priority(void)
 674{
 675        ipic_write(primary_ipic->regs, IPIC_SIPRR_A, IPIC_SIPRR_A_DEFAULT);
 676        ipic_write(primary_ipic->regs, IPIC_SIPRR_D, IPIC_SIPRR_D_DEFAULT);
 677        ipic_write(primary_ipic->regs, IPIC_SMPRR_A, IPIC_SMPRR_A_DEFAULT);
 678        ipic_write(primary_ipic->regs, IPIC_SMPRR_B, IPIC_SMPRR_B_DEFAULT);
 679}
 680
 681void ipic_enable_mcp(enum ipic_mcp_irq mcp_irq)
 682{
 683        struct ipic *ipic = primary_ipic;
 684        u32 temp;
 685
 686        temp = ipic_read(ipic->regs, IPIC_SERMR);
 687        temp |= (1 << (31 - mcp_irq));
 688        ipic_write(ipic->regs, IPIC_SERMR, temp);
 689}
 690
 691void ipic_disable_mcp(enum ipic_mcp_irq mcp_irq)
 692{
 693        struct ipic *ipic = primary_ipic;
 694        u32 temp;
 695
 696        temp = ipic_read(ipic->regs, IPIC_SERMR);
 697        temp &= (1 << (31 - mcp_irq));
 698        ipic_write(ipic->regs, IPIC_SERMR, temp);
 699}
 700
 701u32 ipic_get_mcp_status(void)
 702{
 703        return ipic_read(primary_ipic->regs, IPIC_SERMR);
 704}
 705
 706void ipic_clear_mcp_status(u32 mask)
 707{
 708        ipic_write(primary_ipic->regs, IPIC_SERMR, mask);
 709}
 710
 711/* Return an interrupt vector or NO_IRQ if no interrupt is pending. */
 712unsigned int ipic_get_irq(void)
 713{
 714        int irq;
 715
 716        BUG_ON(primary_ipic == NULL);
 717
 718#define IPIC_SIVCR_VECTOR_MASK  0x7f
 719        irq = ipic_read(primary_ipic->regs, IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK;
 720
 721        if (irq == 0)    /* 0 --> no irq is pending */
 722                return NO_IRQ;
 723
 724        return irq_linear_revmap(primary_ipic->irqhost, irq);
 725}
 726
 727static struct sysdev_class ipic_sysclass = {
 728        set_kset_name("ipic"),
 729};
 730
 731static struct sys_device device_ipic = {
 732        .id             = 0,
 733        .cls            = &ipic_sysclass,
 734};
 735
 736static int __init init_ipic_sysfs(void)
 737{
 738        int rc;
 739
 740        if (!primary_ipic->regs)
 741                return -ENODEV;
 742        printk(KERN_DEBUG "Registering ipic with sysfs...\n");
 743
 744        rc = sysdev_class_register(&ipic_sysclass);
 745        if (rc) {
 746                printk(KERN_ERR "Failed registering ipic sys class\n");
 747                return -ENODEV;
 748        }
 749        rc = sysdev_register(&device_ipic);
 750        if (rc) {
 751                printk(KERN_ERR "Failed registering ipic sys device\n");
 752                return -ENODEV;
 753        }
 754        return 0;
 755}
 756
 757subsys_initcall(init_ipic_sysfs);
 758