1/* 2 * Copyright 2002 Momentum Computer 3 * Author: mdharm@momenco.com 4 * 5 * arch/mips/momentum/ocelot_c/uart-irq.c 6 * Interrupt routines for UARTs. Interrupt numbers are assigned from 7 * 80 to 81 (2 interrupt sources). 8 * 9 * This program is free software; you can redistribute it and/or modify it 10 * under the terms of the GNU General Public License as published by the 11 * Free Software Foundation; either version 2 of the License, or (at your 12 * option) any later version. 13 */ 14 15#include <linux/module.h> 16#include <linux/interrupt.h> 17#include <linux/irq.h> 18#include <linux/kernel.h> 19#include <linux/sched.h> 20#include <linux/kernel_stat.h> 21#include <asm/io.h> 22#include <asm/irq.h> 23#include "ocelot_c_fpga.h" 24 25static inline int ls1bit8(unsigned int x) 26{ 27 int b = 7, s; 28 29 s = 4; if (((unsigned char)(x << 4)) == 0) s = 0; b -= s; x <<= s; 30 s = 2; if (((unsigned char)(x << 2)) == 0) s = 0; b -= s; x <<= s; 31 s = 1; if (((unsigned char)(x << 1)) == 0) s = 0; b -= s; 32 33 return b; 34} 35 36/* mask off an interrupt -- 0 is enable, 1 is disable */ 37static inline void mask_uart_irq(unsigned int irq) 38{ 39 uint8_t value; 40 41 value = OCELOT_FPGA_READ(UART_INTMASK); 42 value |= 1 << (irq - 74); 43 OCELOT_FPGA_WRITE(value, UART_INTMASK); 44 45 /* read the value back to assure that it's really been written */ 46 value = OCELOT_FPGA_READ(UART_INTMASK); 47} 48 49/* unmask an interrupt -- 0 is enable, 1 is disable */ 50static inline void unmask_uart_irq(unsigned int irq) 51{ 52 uint8_t value; 53 54 value = OCELOT_FPGA_READ(UART_INTMASK); 55 value &= ~(1 << (irq - 74)); 56 OCELOT_FPGA_WRITE(value, UART_INTMASK); 57 58 /* read the value back to assure that it's really been written */ 59 value = OCELOT_FPGA_READ(UART_INTMASK); 60} 61 62/* 63 * Interrupt handler for interrupts coming from the FPGA chip. 64 */ 65void ll_uart_irq(void) 66{ 67 unsigned int irq_src, irq_mask; 68 69 /* read the interrupt status registers */ 70 irq_src = OCELOT_FPGA_READ(UART_INTSTAT); 71 irq_mask = OCELOT_FPGA_READ(UART_INTMASK); 72 73 /* mask for just the interrupts we want */ 74 irq_src &= ~irq_mask; 75 76 do_IRQ(ls1bit8(irq_src) + 74); 77} 78 79struct irq_chip uart_irq_type = { 80 .name = "UART/FPGA", 81 .ack = mask_uart_irq, 82 .mask = mask_uart_irq, 83 .mask_ack = mask_uart_irq, 84 .unmask = unmask_uart_irq, 85}; 86 87void uart_irq_init(void) 88{ 89 set_irq_chip_and_handler(80, &uart_irq_type, handle_level_irq); 90 set_irq_chip_and_handler(81, &uart_irq_type, handle_level_irq); 91} 92