xref: /linux/arch/mips/sni/rm200.c (revision ebf8889bd1fe3615991ff4494635d237280652a2)
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/irq_cpu.h>
19 
20 #define PORT(_base,_irq)				\
21 	{						\
22 		.iobase		= _base,		\
23 		.irq		= _irq,			\
24 		.uartclk	= 1843200,		\
25 		.iotype		= UPIO_PORT,		\
26 		.flags		= UPF_BOOT_AUTOCONF,	\
27 	}
28 
29 static struct plat_serial8250_port rm200_data[] = {
30 	PORT(0x3f8, 4),
31 	PORT(0x2f8, 3),
32 	{ },
33 };
34 
35 static struct platform_device rm200_serial8250_device = {
36 	.name			= "serial8250",
37 	.id			= PLAT8250_DEV_PLATFORM,
38 	.dev			= {
39 		.platform_data	= rm200_data,
40 	},
41 };
42 
43 static struct resource rm200_ds1216_rsrc[] = {
44         {
45                 .start = 0x1cd41ffc,
46                 .end   = 0x1cd41fff,
47                 .flags = IORESOURCE_MEM
48         }
49 };
50 
51 static struct platform_device rm200_ds1216_device = {
52         .name           = "rtc-ds1216",
53         .num_resources  = ARRAY_SIZE(rm200_ds1216_rsrc),
54         .resource       = rm200_ds1216_rsrc
55 };
56 
57 static struct resource snirm_82596_rm200_rsrc[] = {
58 	{
59 		.start = 0x18000000,
60 		.end   = 0x180fffff,
61 		.flags = IORESOURCE_MEM
62 	},
63 	{
64 		.start = 0x1b000000,
65 		.end   = 0x1b000004,
66 		.flags = IORESOURCE_MEM
67 	},
68 	{
69 		.start = 0x1ff00000,
70 		.end   = 0x1ff00020,
71 		.flags = IORESOURCE_MEM
72 	},
73 	{
74 		.start = 27,
75 		.end   = 27,
76 		.flags = IORESOURCE_IRQ
77 	},
78 	{
79 		.flags = 0x00
80 	}
81 };
82 
83 static struct platform_device snirm_82596_rm200_pdev = {
84 	.name           = "snirm_82596",
85 	.num_resources  = ARRAY_SIZE(snirm_82596_rm200_rsrc),
86 	.resource       = snirm_82596_rm200_rsrc
87 };
88 
89 static struct resource snirm_53c710_rm200_rsrc[] = {
90 	{
91 		.start = 0x19000000,
92 		.end   = 0x190fffff,
93 		.flags = IORESOURCE_MEM
94 	},
95 	{
96 		.start = 26,
97 		.end   = 26,
98 		.flags = IORESOURCE_IRQ
99 	}
100 };
101 
102 static struct platform_device snirm_53c710_rm200_pdev = {
103 	.name           = "snirm_53c710",
104 	.num_resources  = ARRAY_SIZE(snirm_53c710_rm200_rsrc),
105 	.resource       = snirm_53c710_rm200_rsrc
106 };
107 
108 static int __init snirm_setup_devinit(void)
109 {
110 	if (sni_brd_type == SNI_BRD_RM200) {
111 		platform_device_register(&rm200_serial8250_device);
112 		platform_device_register(&rm200_ds1216_device);
113 		platform_device_register(&snirm_82596_rm200_pdev);
114 		platform_device_register(&snirm_53c710_rm200_pdev);
115 	}
116 	return 0;
117 }
118 
119 device_initcall(snirm_setup_devinit);
120 
121 
122 #define SNI_RM200_INT_STAT_REG  0xbc000000
123 #define SNI_RM200_INT_ENA_REG   0xbc080000
124 
125 #define SNI_RM200_INT_START  24
126 #define SNI_RM200_INT_END    28
127 
128 static void enable_rm200_irq(unsigned int irq)
129 {
130 	unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
131 
132 	*(volatile u8 *)SNI_RM200_INT_ENA_REG &= ~mask;
133 }
134 
135 void disable_rm200_irq(unsigned int irq)
136 {
137 	unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
138 
139 	*(volatile u8 *)SNI_RM200_INT_ENA_REG |= mask;
140 }
141 
142 void end_rm200_irq(unsigned int irq)
143 {
144 	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
145 		enable_rm200_irq(irq);
146 }
147 
148 static struct irq_chip rm200_irq_type = {
149 	.typename = "RM200",
150 	.ack = disable_rm200_irq,
151 	.mask = disable_rm200_irq,
152 	.mask_ack = disable_rm200_irq,
153 	.unmask = enable_rm200_irq,
154 	.end = end_rm200_irq,
155 };
156 
157 static void sni_rm200_hwint(void)
158 {
159 	u32 pending = read_c0_cause() & read_c0_status();
160 	u8 mask;
161 	u8 stat;
162 	int irq;
163 
164 	if (pending & C_IRQ5)
165 		do_IRQ(MIPS_CPU_IRQ_BASE + 7);
166 	else if (pending & C_IRQ0) {
167 		clear_c0_status(IE_IRQ0);
168 		mask = *(volatile u8 *)SNI_RM200_INT_ENA_REG ^ 0x1f;
169 		stat = *(volatile u8 *)SNI_RM200_INT_STAT_REG ^ 0x14;
170 		irq = ffs(stat & mask & 0x1f);
171 
172 		if (likely(irq > 0))
173 			do_IRQ(irq + SNI_RM200_INT_START - 1);
174 		set_c0_status(IE_IRQ0);
175 	}
176 }
177 
178 void __init sni_rm200_irq_init(void)
179 {
180 	int i;
181 
182 	* (volatile u8 *)SNI_RM200_INT_ENA_REG = 0x1f;
183 
184 	mips_cpu_irq_init();
185 	/* Actually we've got more interrupts to handle ...  */
186 	for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++)
187 		set_irq_chip(i, &rm200_irq_type);
188 	sni_hwint = sni_rm200_hwint;
189 	change_c0_status(ST0_IM, IE_IRQ0);
190 	setup_irq(SNI_RM200_INT_START + 0, &sni_isa_irq);
191 }
192 
193 void __init sni_rm200_init(void)
194 {
195 	set_io_port_base(SNI_PORT_BASE + 0x02000000);
196 	ioport_resource.end += 0x02000000;
197 }
198