Commit | Line | Data |
---|---|---|
c066a32a TB |
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> | |
c066a32a TB |
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 | ||
06cf5583 TB |
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 | ||
c066a32a TB |
57 | static struct resource snirm_82596_rm200_rsrc[] = { |
58 | { | |
06cf5583 TB |
59 | .start = 0x18000000, |
60 | .end = 0x180fffff, | |
c066a32a TB |
61 | .flags = IORESOURCE_MEM |
62 | }, | |
63 | { | |
06cf5583 TB |
64 | .start = 0x1b000000, |
65 | .end = 0x1b000004, | |
c066a32a TB |
66 | .flags = IORESOURCE_MEM |
67 | }, | |
68 | { | |
06cf5583 TB |
69 | .start = 0x1ff00000, |
70 | .end = 0x1ff00020, | |
c066a32a TB |
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 | { | |
9815778a TB |
91 | .start = 0x19000000, |
92 | .end = 0x190fffff, | |
c066a32a TB |
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); | |
06cf5583 | 112 | platform_device_register(&rm200_ds1216_device); |
c066a32a TB |
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) | |
49a89efb | 165 | do_IRQ(MIPS_CPU_IRQ_BASE + 7); |
c066a32a | 166 | else if (pending & C_IRQ0) { |
49a89efb | 167 | clear_c0_status(IE_IRQ0); |
c066a32a TB |
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)) | |
49a89efb RB |
173 | do_IRQ(irq + SNI_RM200_INT_START - 1); |
174 | set_c0_status(IE_IRQ0); | |
c066a32a TB |
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); | |
49a89efb | 190 | setup_irq(SNI_RM200_INT_START + 0, &sni_isa_irq); |
c066a32a TB |
191 | } |
192 | ||
06cf5583 | 193 | void __init sni_rm200_init(void) |
c066a32a TB |
194 | { |
195 | set_io_port_base(SNI_PORT_BASE + 0x02000000); | |
196 | ioport_resource.end += 0x02000000; | |
c066a32a | 197 | } |