xref: /linux/arch/mips/sni/rm200.c (revision bc95f3669f5e6f63cf0b84fe4922c3c6dd4aa775)
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