1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/arch/sh/boards/renesas/rts7751r2d/irq.c 4 * 5 * Copyright (C) 2007 Magnus Damm 6 * Copyright (C) 2000 Kazumoto Kojima 7 * 8 * Renesas Technology Sales RTS7751R2D Support, R2D-PLUS and R2D-1. 9 * 10 * Modified for RTS7751R2D by 11 * Atom Create Engineering Co., Ltd. 2002. 12 */ 13 #include <linux/init.h> 14 #include <linux/irq.h> 15 #include <linux/interrupt.h> 16 #include <linux/io.h> 17 #include <mach/r2d.h> 18 19 #define R2D_NR_IRL 13 20 21 enum { 22 UNUSED = 0, 23 24 /* board specific interrupt sources (R2D-1 and R2D-PLUS) */ 25 EXT, /* EXT_INT0-3 */ 26 RTC_T, RTC_A, /* Real Time Clock */ 27 AX88796, /* Ethernet controller (R2D-1 board) */ 28 KEY, /* Key input (R2D-PLUS board) */ 29 SDCARD, /* SD Card */ 30 CF_CD, CF_IDE, /* CF Card Detect + CF IDE */ 31 SM501, /* SM501 aka Voyager */ 32 PCI_INTD_RTL8139, /* Ethernet controller */ 33 PCI_INTC_PCI1520, /* Cardbus/PCMCIA bridge */ 34 PCI_INTB_RTL8139, /* Ethernet controller with HUB (R2D-PLUS board) */ 35 PCI_INTB_SLOT, /* PCI Slot 3.3v (R2D-1 board) */ 36 PCI_INTA_SLOT, /* PCI Slot 3.3v */ 37 TP, /* Touch Panel */ 38 }; 39 40 #ifdef CONFIG_RTS7751R2D_1 41 42 /* Vectors for R2D-1 */ 43 static struct intc_vect vectors_r2d_1[] __initdata = { 44 INTC_IRQ(EXT, IRQ_EXT), 45 INTC_IRQ(RTC_T, IRQ_RTC_T), INTC_IRQ(RTC_A, IRQ_RTC_A), 46 INTC_IRQ(AX88796, IRQ_AX88796), INTC_IRQ(SDCARD, IRQ_SDCARD), 47 INTC_IRQ(CF_CD, IRQ_CF_CD), INTC_IRQ(CF_IDE, IRQ_CF_IDE), /* ng */ 48 INTC_IRQ(SM501, IRQ_VOYAGER), 49 INTC_IRQ(PCI_INTD_RTL8139, IRQ_PCI_INTD), 50 INTC_IRQ(PCI_INTC_PCI1520, IRQ_PCI_INTC), 51 INTC_IRQ(PCI_INTB_SLOT, IRQ_PCI_INTB), 52 INTC_IRQ(PCI_INTA_SLOT, IRQ_PCI_INTA), 53 INTC_IRQ(TP, IRQ_TP), 54 }; 55 56 /* IRLMSK mask register layout for R2D-1 */ 57 static struct intc_mask_reg mask_registers_r2d_1[] __initdata = { 58 { 0xa4000000, 0, 16, /* IRLMSK */ 59 { TP, PCI_INTA_SLOT, PCI_INTB_SLOT, 60 PCI_INTC_PCI1520, PCI_INTD_RTL8139, 61 SM501, CF_IDE, CF_CD, SDCARD, AX88796, 62 RTC_A, RTC_T, 0, 0, 0, EXT } }, 63 }; 64 65 /* IRLn to IRQ table for R2D-1 */ 66 static unsigned char irl2irq_r2d_1[R2D_NR_IRL] __initdata = { 67 IRQ_PCI_INTD, IRQ_CF_IDE, IRQ_CF_CD, IRQ_PCI_INTC, 68 IRQ_VOYAGER, IRQ_AX88796, IRQ_RTC_A, IRQ_RTC_T, 69 IRQ_SDCARD, IRQ_PCI_INTA, IRQ_PCI_INTB, IRQ_EXT, 70 IRQ_TP, 71 }; 72 73 static DECLARE_INTC_DESC(intc_desc_r2d_1, "r2d-1", vectors_r2d_1, 74 NULL, mask_registers_r2d_1, NULL, NULL); 75 76 #endif /* CONFIG_RTS7751R2D_1 */ 77 78 #ifdef CONFIG_RTS7751R2D_PLUS 79 80 /* Vectors for R2D-PLUS */ 81 static struct intc_vect vectors_r2d_plus[] __initdata = { 82 INTC_IRQ(EXT, IRQ_EXT), 83 INTC_IRQ(RTC_T, IRQ_RTC_T), INTC_IRQ(RTC_A, IRQ_RTC_A), 84 INTC_IRQ(KEY, IRQ_KEY), INTC_IRQ(SDCARD, IRQ_SDCARD), 85 INTC_IRQ(CF_CD, IRQ_CF_CD), INTC_IRQ(CF_IDE, IRQ_CF_IDE), 86 INTC_IRQ(SM501, IRQ_VOYAGER), 87 INTC_IRQ(PCI_INTD_RTL8139, IRQ_PCI_INTD), 88 INTC_IRQ(PCI_INTC_PCI1520, IRQ_PCI_INTC), 89 INTC_IRQ(PCI_INTB_RTL8139, IRQ_PCI_INTB), 90 INTC_IRQ(PCI_INTA_SLOT, IRQ_PCI_INTA), 91 INTC_IRQ(TP, IRQ_TP), 92 }; 93 94 /* IRLMSK mask register layout for R2D-PLUS */ 95 static struct intc_mask_reg mask_registers_r2d_plus[] __initdata = { 96 { 0xa4000000, 0, 16, /* IRLMSK */ 97 { TP, PCI_INTA_SLOT, PCI_INTB_RTL8139, 98 PCI_INTC_PCI1520, PCI_INTD_RTL8139, 99 SM501, CF_IDE, CF_CD, SDCARD, KEY, 100 RTC_A, RTC_T, 0, 0, 0, EXT } }, 101 }; 102 103 /* IRLn to IRQ table for R2D-PLUS */ 104 static unsigned char irl2irq_r2d_plus[R2D_NR_IRL] __initdata = { 105 IRQ_PCI_INTD, IRQ_CF_IDE, IRQ_CF_CD, IRQ_PCI_INTC, 106 IRQ_VOYAGER, IRQ_KEY, IRQ_RTC_A, IRQ_RTC_T, 107 IRQ_SDCARD, IRQ_PCI_INTA, IRQ_PCI_INTB, IRQ_EXT, 108 IRQ_TP, 109 }; 110 111 static DECLARE_INTC_DESC(intc_desc_r2d_plus, "r2d-plus", vectors_r2d_plus, 112 NULL, mask_registers_r2d_plus, NULL, NULL); 113 114 #endif /* CONFIG_RTS7751R2D_PLUS */ 115 116 static unsigned char irl2irq[R2D_NR_IRL]; 117 118 int rts7751r2d_irq_demux(int irq) 119 { 120 if (irq >= R2D_NR_IRL + 16 || irq < 16 || !irl2irq[irq - 16]) 121 return irq; 122 123 return irl2irq[irq - 16]; 124 } 125 126 /* 127 * Initialize IRQ setting 128 */ 129 void __init init_rts7751r2d_IRQ(void) 130 { 131 struct intc_desc *d; 132 133 switch (__raw_readw(PA_VERREG) & 0xf0) { 134 #ifdef CONFIG_RTS7751R2D_PLUS 135 case 0x10: 136 printk(KERN_INFO "Using R2D-PLUS interrupt controller.\n"); 137 d = &intc_desc_r2d_plus; 138 memcpy(irl2irq, irl2irq_r2d_plus, R2D_NR_IRL); 139 break; 140 #endif 141 #ifdef CONFIG_RTS7751R2D_1 142 case 0x00: /* according to manual */ 143 case 0x30: /* in reality */ 144 printk(KERN_INFO "Using R2D-1 interrupt controller.\n"); 145 d = &intc_desc_r2d_1; 146 memcpy(irl2irq, irl2irq_r2d_1, R2D_NR_IRL); 147 break; 148 #endif 149 default: 150 printk(KERN_INFO "Unknown R2D interrupt controller 0x%04x\n", 151 __raw_readw(PA_VERREG)); 152 return; 153 } 154 155 register_intc_controller(d); 156 } 157