1*2874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 21da177e4SLinus Torvalds /* 31da177e4SLinus Torvalds * DECstation 5000/200 (KN02) Control and Status Register 41da177e4SLinus Torvalds * interrupts. 51da177e4SLinus Torvalds * 664dac503SMaciej W. Rozycki * Copyright (c) 2002, 2003, 2005 Maciej W. Rozycki 71da177e4SLinus Torvalds */ 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds #include <linux/init.h> 101da177e4SLinus Torvalds #include <linux/irq.h> 111da177e4SLinus Torvalds #include <linux/types.h> 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds #include <asm/dec/kn02.h> 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds 161da177e4SLinus Torvalds /* 171da177e4SLinus Torvalds * Bits 7:0 of the Control Register are write-only -- the 181da177e4SLinus Torvalds * corresponding bits of the Status Register have a different 191da177e4SLinus Torvalds * meaning. Hence we use a cache. It speeds up things a bit 201da177e4SLinus Torvalds * as well. 211da177e4SLinus Torvalds * 221da177e4SLinus Torvalds * There is no default value -- it has to be initialized. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds u32 cached_kn02_csr; 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds static int kn02_irq_base; 271da177e4SLinus Torvalds unmask_kn02_irq(struct irq_data * d)28009c200aSThomas Gleixnerstatic void unmask_kn02_irq(struct irq_data *d) 291da177e4SLinus Torvalds { 30a5fc9c0bSMaciej W. Rozycki volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE + 31a5fc9c0bSMaciej W. Rozycki KN02_CSR); 321da177e4SLinus Torvalds 33009c200aSThomas Gleixner cached_kn02_csr |= (1 << (d->irq - kn02_irq_base + 16)); 341da177e4SLinus Torvalds *csr = cached_kn02_csr; 351da177e4SLinus Torvalds } 361da177e4SLinus Torvalds mask_kn02_irq(struct irq_data * d)37009c200aSThomas Gleixnerstatic void mask_kn02_irq(struct irq_data *d) 381da177e4SLinus Torvalds { 39a5fc9c0bSMaciej W. Rozycki volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE + 40a5fc9c0bSMaciej W. Rozycki KN02_CSR); 411da177e4SLinus Torvalds 42009c200aSThomas Gleixner cached_kn02_csr &= ~(1 << (d->irq - kn02_irq_base + 16)); 431da177e4SLinus Torvalds *csr = cached_kn02_csr; 441da177e4SLinus Torvalds } 451da177e4SLinus Torvalds ack_kn02_irq(struct irq_data * d)46009c200aSThomas Gleixnerstatic void ack_kn02_irq(struct irq_data *d) 471da177e4SLinus Torvalds { 48009c200aSThomas Gleixner mask_kn02_irq(d); 491da177e4SLinus Torvalds iob(); 501da177e4SLinus Torvalds } 511da177e4SLinus Torvalds 5294dee171SRalf Baechle static struct irq_chip kn02_irq_type = { 5370d21cdeSAtsushi Nemoto .name = "KN02-CSR", 54009c200aSThomas Gleixner .irq_ack = ack_kn02_irq, 55009c200aSThomas Gleixner .irq_mask = mask_kn02_irq, 56009c200aSThomas Gleixner .irq_mask_ack = ack_kn02_irq, 57009c200aSThomas Gleixner .irq_unmask = unmask_kn02_irq, 581da177e4SLinus Torvalds }; 591da177e4SLinus Torvalds init_kn02_irqs(int base)601da177e4SLinus Torvaldsvoid __init init_kn02_irqs(int base) 611da177e4SLinus Torvalds { 62a5fc9c0bSMaciej W. Rozycki volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE + 63a5fc9c0bSMaciej W. Rozycki KN02_CSR); 641da177e4SLinus Torvalds int i; 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds /* Mask interrupts. */ 6764dac503SMaciej W. Rozycki cached_kn02_csr &= ~KN02_CSR_IOINTEN; 681da177e4SLinus Torvalds *csr = cached_kn02_csr; 691da177e4SLinus Torvalds iob(); 701da177e4SLinus Torvalds 711603b5acSAtsushi Nemoto for (i = base; i < base + KN02_IRQ_LINES; i++) 72e4ec7989SThomas Gleixner irq_set_chip_and_handler(i, &kn02_irq_type, handle_level_irq); 731da177e4SLinus Torvalds 741da177e4SLinus Torvalds kn02_irq_base = base; 751da177e4SLinus Torvalds } 76