1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <linker.h> 8#include <machine/io.h> 9#include <plat/machine/hardware.h> 10#include <plat/machine/pic.h> 11 12/* PIC (i8259) base registers */ 13#define PIC1_BASE 0x20 14#define PIC2_BASE 0xa0 15 16/* Program PIC (i8259) to remap IRQs 0-15 to interrupt vectors starting at 'interrupt' */ 17BOOT_CODE void pic_remap_irqs(interrupt_t interrupt) 18{ 19 out8(PIC1_BASE, 0x11); 20 out8(PIC2_BASE, 0x11); 21 out8(PIC1_BASE + 1, interrupt); 22 out8(PIC2_BASE + 1, interrupt + 8); 23 out8(PIC1_BASE + 1, 0x04); 24 out8(PIC2_BASE + 1, 0x02); 25 out8(PIC1_BASE + 1, 0x01); 26 out8(PIC2_BASE + 1, 0x01); 27 out8(PIC1_BASE + 1, 0x0); 28 out8(PIC2_BASE + 1, 0x0); 29} 30 31BOOT_CODE void pic_disable(void) 32{ 33 /* We assume that pic_remap_irqs has already been called and 34 * just mask all the irqs */ 35 out8(PIC1_BASE + 1, 0xff); 36 out8(PIC2_BASE + 1, 0xff); 37} 38 39void pic_mask_irq(bool_t mask, irq_t irq) 40{ 41 uint8_t bit_mask; 42 uint16_t pic_port; 43 44 assert(irq >= irq_isa_min); 45 assert(irq <= irq_isa_max); 46 47 if (irq < 8) { 48 bit_mask = BIT(irq); 49 pic_port = PIC1_BASE + 1; 50 } else { 51 bit_mask = BIT(irq - 8); 52 pic_port = PIC2_BASE + 1; 53 } 54 55 if (mask) { 56 /* Disables the interrupt */ 57 out8(pic_port, (in8(pic_port) | bit_mask)); 58 } else { 59 /* Enables the interrupt */ 60 out8(pic_port, (in8(pic_port) & ~bit_mask)); 61 } 62} 63 64bool_t pic_is_irq_pending(void) 65{ 66 /* Interrupt Request Register (IRR) - holds pending IRQs */ 67 uint8_t irr; 68 69 /* Send to PIC1's OCW3, in order to read IRR from next inb instruction */ 70 out8(PIC1_BASE, 0x0a); 71 72 /* Read IRR */ 73 irr = in8(PIC1_BASE); 74 75 /* Since slave PIC is connected to IRQ2 of master PIC, 76 * there is no need to check IRR of slave PIC. 77 */ 78 return irr != 0; 79} 80 81static uint16_t pic_get_isr(void) 82{ 83 out8(PIC1_BASE, 0x0b); 84 out8(PIC2_BASE, 0x0b); 85 return (((uint16_t)in8(PIC2_BASE)) << 8) | in8(PIC1_BASE); 86} 87 88void pic_ack_active_irq(void) 89{ 90 irq_t irq = getActiveIRQ(); 91 if (irq >= irq_isa_min + 8) { 92 /* ack slave PIC, unless we got a spurious irq 15 93 * It is spurious if the bit is not set in the ISR 94 * Even if it was spurious we will still need to 95 * acknowledge the master PIC */ 96 if (irq != irq_isa_min + 15 || (pic_get_isr() & BIT(15))) { 97 out8(PIC2_BASE, 0x20); 98 } 99 } 100 /* ack master PIC, unless we got a spurious IRQ 7 101 * It is spurious if the bit is not set in the ISR */ 102 if (irq != irq_isa_min + 7 || (pic_get_isr() & BIT(7))) { 103 out8(PIC1_BASE, 0x20); 104 } 105} 106