1 /* 2 * RM200 specific code 3 * 4 * This file is subject to the terms and conditions of the GNU General Public 5 * License. See the file "COPYING" in the main directory of this archive 6 * for more details. 7 * 8 * Copyright (C) 2006 Thomas Bogendoerfer (tsbogend@alpha.franken.de) 9 */ 10 11 #include <linux/init.h> 12 #include <linux/interrupt.h> 13 #include <linux/platform_device.h> 14 #include <linux/serial_8250.h> 15 16 #include <asm/sni.h> 17 #include <asm/time.h> 18 #include <asm/ds1216.h> 19 #include <asm/irq_cpu.h> 20 21 #define PORT(_base,_irq) \ 22 { \ 23 .iobase = _base, \ 24 .irq = _irq, \ 25 .uartclk = 1843200, \ 26 .iotype = UPIO_PORT, \ 27 .flags = UPF_BOOT_AUTOCONF, \ 28 } 29 30 static struct plat_serial8250_port rm200_data[] = { 31 PORT(0x3f8, 4), 32 PORT(0x2f8, 3), 33 { }, 34 }; 35 36 static struct platform_device rm200_serial8250_device = { 37 .name = "serial8250", 38 .id = PLAT8250_DEV_PLATFORM, 39 .dev = { 40 .platform_data = rm200_data, 41 }, 42 }; 43 44 static struct resource snirm_82596_rm200_rsrc[] = { 45 { 46 .start = 0xb8000000, 47 .end = 0xb80fffff, 48 .flags = IORESOURCE_MEM 49 }, 50 { 51 .start = 0xbb000000, 52 .end = 0xbb000004, 53 .flags = IORESOURCE_MEM 54 }, 55 { 56 .start = 0xbff00000, 57 .end = 0xbff00020, 58 .flags = IORESOURCE_MEM 59 }, 60 { 61 .start = 27, 62 .end = 27, 63 .flags = IORESOURCE_IRQ 64 }, 65 { 66 .flags = 0x00 67 } 68 }; 69 70 static struct platform_device snirm_82596_rm200_pdev = { 71 .name = "snirm_82596", 72 .num_resources = ARRAY_SIZE(snirm_82596_rm200_rsrc), 73 .resource = snirm_82596_rm200_rsrc 74 }; 75 76 static struct resource snirm_53c710_rm200_rsrc[] = { 77 { 78 .start = 0xb9000000, 79 .end = 0xb90fffff, 80 .flags = IORESOURCE_MEM 81 }, 82 { 83 .start = 26, 84 .end = 26, 85 .flags = IORESOURCE_IRQ 86 } 87 }; 88 89 static struct platform_device snirm_53c710_rm200_pdev = { 90 .name = "snirm_53c710", 91 .num_resources = ARRAY_SIZE(snirm_53c710_rm200_rsrc), 92 .resource = snirm_53c710_rm200_rsrc 93 }; 94 95 static int __init snirm_setup_devinit(void) 96 { 97 if (sni_brd_type == SNI_BRD_RM200) { 98 platform_device_register(&rm200_serial8250_device); 99 platform_device_register(&snirm_82596_rm200_pdev); 100 platform_device_register(&snirm_53c710_rm200_pdev); 101 } 102 return 0; 103 } 104 105 device_initcall(snirm_setup_devinit); 106 107 108 #define SNI_RM200_INT_STAT_REG 0xbc000000 109 #define SNI_RM200_INT_ENA_REG 0xbc080000 110 111 #define SNI_RM200_INT_START 24 112 #define SNI_RM200_INT_END 28 113 114 static void enable_rm200_irq(unsigned int irq) 115 { 116 unsigned int mask = 1 << (irq - SNI_RM200_INT_START); 117 118 *(volatile u8 *)SNI_RM200_INT_ENA_REG &= ~mask; 119 } 120 121 void disable_rm200_irq(unsigned int irq) 122 { 123 unsigned int mask = 1 << (irq - SNI_RM200_INT_START); 124 125 *(volatile u8 *)SNI_RM200_INT_ENA_REG |= mask; 126 } 127 128 void end_rm200_irq(unsigned int irq) 129 { 130 if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) 131 enable_rm200_irq(irq); 132 } 133 134 static struct irq_chip rm200_irq_type = { 135 .typename = "RM200", 136 .ack = disable_rm200_irq, 137 .mask = disable_rm200_irq, 138 .mask_ack = disable_rm200_irq, 139 .unmask = enable_rm200_irq, 140 .end = end_rm200_irq, 141 }; 142 143 static void sni_rm200_hwint(void) 144 { 145 u32 pending = read_c0_cause() & read_c0_status(); 146 u8 mask; 147 u8 stat; 148 int irq; 149 150 if (pending & C_IRQ5) 151 do_IRQ (MIPS_CPU_IRQ_BASE + 7); 152 else if (pending & C_IRQ0) { 153 clear_c0_status (IE_IRQ0); 154 mask = *(volatile u8 *)SNI_RM200_INT_ENA_REG ^ 0x1f; 155 stat = *(volatile u8 *)SNI_RM200_INT_STAT_REG ^ 0x14; 156 irq = ffs(stat & mask & 0x1f); 157 158 if (likely(irq > 0)) 159 do_IRQ (irq + SNI_RM200_INT_START - 1); 160 set_c0_status (IE_IRQ0); 161 } 162 } 163 164 void __init sni_rm200_irq_init(void) 165 { 166 int i; 167 168 * (volatile u8 *)SNI_RM200_INT_ENA_REG = 0x1f; 169 170 mips_cpu_irq_init(); 171 /* Actually we've got more interrupts to handle ... */ 172 for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++) 173 set_irq_chip(i, &rm200_irq_type); 174 sni_hwint = sni_rm200_hwint; 175 change_c0_status(ST0_IM, IE_IRQ0); 176 setup_irq (SNI_RM200_INT_START + 0, &sni_isa_irq); 177 } 178 179 void sni_rm200_init(void) 180 { 181 set_io_port_base(SNI_PORT_BASE + 0x02000000); 182 ioport_resource.end += 0x02000000; 183 ds1216_base = (volatile unsigned char *) SNI_DS1216_RM200_BASE; 184 rtc_mips_get_time = ds1216_get_cmos_time; 185 board_time_init = sni_cpu_time_init; 186 } 187