uboot/arch/x86/lib/pcat_interrupts.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2009
   3 * Graeme Russ, <graeme.russ@gmail.com>
   4 *
   5 * (C) Copyright 2002
   6 * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 */
  26
  27/*
  28 * This file provides the interrupt handling functionality for systems
  29 * based on the standard PC/AT architecture using two cascaded i8259
  30 * Programmable Interrupt Controllers.
  31 */
  32
  33#include <common.h>
  34#include <asm/io.h>
  35#include <asm/i8259.h>
  36#include <asm/ibmpc.h>
  37#include <asm/interrupt.h>
  38
  39#if CONFIG_SYS_NUM_IRQS != 16
  40#error "CONFIG_SYS_NUM_IRQS must equal 16 if CONFIG_SYS_NUM_IRQS is defined"
  41#endif
  42
  43int interrupt_init(void)
  44{
  45        u8 i;
  46
  47        disable_interrupts();
  48
  49        /* Mask all interrupts */
  50        outb(0xff, MASTER_PIC + IMR);
  51        outb(0xff, SLAVE_PIC + IMR);
  52
  53        /* Master PIC */
  54        /* Place master PIC interrupts at INT20 */
  55        /* ICW3, One slave PIC is present */
  56        outb(ICW1_SEL|ICW1_EICW4, MASTER_PIC + ICW1);
  57        outb(0x20, MASTER_PIC + ICW2);
  58        outb(IR2, MASTER_PIC + ICW3);
  59        outb(ICW4_PM, MASTER_PIC + ICW4);
  60
  61        for (i = 0; i < 8; i++)
  62                outb(OCW2_SEOI | i, MASTER_PIC + OCW2);
  63
  64        /* Slave PIC */
  65        /* Place slave PIC interrupts at INT28 */
  66        /* Slave ID */
  67        outb(ICW1_SEL|ICW1_EICW4, SLAVE_PIC + ICW1);
  68        outb(0x28, SLAVE_PIC + ICW2);
  69        outb(0x02, SLAVE_PIC + ICW3);
  70        outb(ICW4_PM, SLAVE_PIC + ICW4);
  71
  72        for (i = 0; i < 8; i++)
  73                outb(OCW2_SEOI | i, SLAVE_PIC + OCW2);
  74
  75        /*
  76         * Enable cascaded interrupts by unmasking the cascade IRQ pin of
  77         * the master PIC
  78         */
  79        unmask_irq(2);
  80
  81        enable_interrupts();
  82
  83        return 0;
  84}
  85
  86void mask_irq(int irq)
  87{
  88        int imr_port;
  89
  90        if (irq >= CONFIG_SYS_NUM_IRQS)
  91                return;
  92
  93        if (irq > 7)
  94                imr_port = SLAVE_PIC + IMR;
  95        else
  96                imr_port = MASTER_PIC + IMR;
  97
  98        outb(inb(imr_port) | (1 << (irq & 7)), imr_port);
  99}
 100
 101void unmask_irq(int irq)
 102{
 103        int imr_port;
 104
 105        if (irq >= CONFIG_SYS_NUM_IRQS)
 106                return;
 107
 108        if (irq > 7)
 109                imr_port = SLAVE_PIC + IMR;
 110        else
 111                imr_port = MASTER_PIC + IMR;
 112
 113        outb(inb(imr_port) & ~(1 << (irq & 7)), imr_port);
 114}
 115
 116void specific_eoi(int irq)
 117{
 118        if (irq >= CONFIG_SYS_NUM_IRQS)
 119                return;
 120
 121        if (irq > 7) {
 122                /*
 123                 *  IRQ is on the slave - Issue a corresponding EOI to the
 124                 *  slave PIC and an EOI for IRQ2 (the cascade interrupt)
 125                 *  on the master PIC
 126                 */
 127                outb(OCW2_SEOI | (irq & 7), SLAVE_PIC + OCW2);
 128                irq = SEOI_IR2;
 129        }
 130
 131        outb(OCW2_SEOI | irq, MASTER_PIC + OCW2);
 132}
 133