1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * DECstation 5000/200 (KN02) Control and Status Register 4*4882a593Smuzhiyun * interrupts. 5*4882a593Smuzhiyun * 6*4882a593Smuzhiyun * Copyright (c) 2002, 2003, 2005 Maciej W. Rozycki 7*4882a593Smuzhiyun */ 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun #include <linux/init.h> 10*4882a593Smuzhiyun #include <linux/irq.h> 11*4882a593Smuzhiyun #include <linux/types.h> 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun #include <asm/dec/kn02.h> 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun /* 17*4882a593Smuzhiyun * Bits 7:0 of the Control Register are write-only -- the 18*4882a593Smuzhiyun * corresponding bits of the Status Register have a different 19*4882a593Smuzhiyun * meaning. Hence we use a cache. It speeds up things a bit 20*4882a593Smuzhiyun * as well. 21*4882a593Smuzhiyun * 22*4882a593Smuzhiyun * There is no default value -- it has to be initialized. 23*4882a593Smuzhiyun */ 24*4882a593Smuzhiyun u32 cached_kn02_csr; 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun static int kn02_irq_base; 27*4882a593Smuzhiyun unmask_kn02_irq(struct irq_data * d)28*4882a593Smuzhiyunstatic void unmask_kn02_irq(struct irq_data *d) 29*4882a593Smuzhiyun { 30*4882a593Smuzhiyun volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE + 31*4882a593Smuzhiyun KN02_CSR); 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun cached_kn02_csr |= (1 << (d->irq - kn02_irq_base + 16)); 34*4882a593Smuzhiyun *csr = cached_kn02_csr; 35*4882a593Smuzhiyun } 36*4882a593Smuzhiyun mask_kn02_irq(struct irq_data * d)37*4882a593Smuzhiyunstatic void mask_kn02_irq(struct irq_data *d) 38*4882a593Smuzhiyun { 39*4882a593Smuzhiyun volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE + 40*4882a593Smuzhiyun KN02_CSR); 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun cached_kn02_csr &= ~(1 << (d->irq - kn02_irq_base + 16)); 43*4882a593Smuzhiyun *csr = cached_kn02_csr; 44*4882a593Smuzhiyun } 45*4882a593Smuzhiyun ack_kn02_irq(struct irq_data * d)46*4882a593Smuzhiyunstatic void ack_kn02_irq(struct irq_data *d) 47*4882a593Smuzhiyun { 48*4882a593Smuzhiyun mask_kn02_irq(d); 49*4882a593Smuzhiyun iob(); 50*4882a593Smuzhiyun } 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun static struct irq_chip kn02_irq_type = { 53*4882a593Smuzhiyun .name = "KN02-CSR", 54*4882a593Smuzhiyun .irq_ack = ack_kn02_irq, 55*4882a593Smuzhiyun .irq_mask = mask_kn02_irq, 56*4882a593Smuzhiyun .irq_mask_ack = ack_kn02_irq, 57*4882a593Smuzhiyun .irq_unmask = unmask_kn02_irq, 58*4882a593Smuzhiyun }; 59*4882a593Smuzhiyun init_kn02_irqs(int base)60*4882a593Smuzhiyunvoid __init init_kn02_irqs(int base) 61*4882a593Smuzhiyun { 62*4882a593Smuzhiyun volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE + 63*4882a593Smuzhiyun KN02_CSR); 64*4882a593Smuzhiyun int i; 65*4882a593Smuzhiyun 66*4882a593Smuzhiyun /* Mask interrupts. */ 67*4882a593Smuzhiyun cached_kn02_csr &= ~KN02_CSR_IOINTEN; 68*4882a593Smuzhiyun *csr = cached_kn02_csr; 69*4882a593Smuzhiyun iob(); 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun for (i = base; i < base + KN02_IRQ_LINES; i++) 72*4882a593Smuzhiyun irq_set_chip_and_handler(i, &kn02_irq_type, handle_level_irq); 73*4882a593Smuzhiyun 74*4882a593Smuzhiyun kn02_irq_base = base; 75*4882a593Smuzhiyun } 76