Commit | Line | Data |
---|---|---|
c680b77e LB |
1 | /* |
2 | * arch/arm/mach-iop32x/iq31244.c | |
3 | * | |
4 | * Board support code for the Intel EP80219 and IQ31244 platforms. | |
5 | * | |
6 | * Author: Rory Bolt <rorybolt@pacbell.net> | |
7 | * Copyright (C) 2002 Rory Bolt | |
8 | * Copyright 2003 (c) MontaVista, Software, Inc. | |
9 | * Copyright (C) 2004 Intel Corp. | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify it | |
12 | * under the terms of the GNU General Public License as published by the | |
13 | * Free Software Foundation; either version 2 of the License, or (at your | |
14 | * option) any later version. | |
15 | */ | |
16 | ||
17 | #include <linux/mm.h> | |
18 | #include <linux/init.h> | |
19 | #include <linux/delay.h> | |
20 | #include <linux/kernel.h> | |
21 | #include <linux/pci.h> | |
22 | #include <linux/pm.h> | |
23 | #include <linux/string.h> | |
c680b77e LB |
24 | #include <linux/serial_core.h> |
25 | #include <linux/serial_8250.h> | |
26 | #include <linux/mtd/physmap.h> | |
27 | #include <linux/platform_device.h> | |
fced80c7 | 28 | #include <linux/io.h> |
a09e64fb | 29 | #include <mach/hardware.h> |
0ba8b9b2 | 30 | #include <asm/cputype.h> |
c680b77e LB |
31 | #include <asm/irq.h> |
32 | #include <asm/mach/arch.h> | |
33 | #include <asm/mach/map.h> | |
34 | #include <asm/mach/pci.h> | |
35 | #include <asm/mach/time.h> | |
36 | #include <asm/mach-types.h> | |
37 | #include <asm/page.h> | |
38 | #include <asm/pgtable.h> | |
a09e64fb | 39 | #include <mach/time.h> |
c680b77e LB |
40 | |
41 | /* | |
094f1275 DW |
42 | * Until March of 2007 iq31244 platforms and ep80219 platforms shared the |
43 | * same machine id, and the processor type was used to select board type. | |
44 | * However this assumption breaks for an iq80219 board which is an iop219 | |
45 | * processor on an iq31244 board. The force_ep80219 flag has been added | |
46 | * for old boot loaders using the iq31244 machine id for an ep80219 platform. | |
c680b77e | 47 | */ |
094f1275 DW |
48 | static int force_ep80219; |
49 | ||
c680b77e LB |
50 | static int is_80219(void) |
51 | { | |
0ba8b9b2 | 52 | return !!((read_cpuid_id() & 0xffffffe0) == 0x69052e20); |
c680b77e LB |
53 | } |
54 | ||
094f1275 DW |
55 | static int is_ep80219(void) |
56 | { | |
57 | if (machine_is_ep80219() || force_ep80219) | |
58 | return 1; | |
59 | else | |
60 | return 0; | |
61 | } | |
62 | ||
c680b77e LB |
63 | |
64 | /* | |
65 | * EP80219/IQ31244 timer tick configuration. | |
66 | */ | |
67 | static void __init iq31244_timer_init(void) | |
68 | { | |
094f1275 | 69 | if (is_ep80219()) { |
c680b77e | 70 | /* 33.333 MHz crystal. */ |
3668b45d | 71 | iop_init_time(200000000); |
c680b77e LB |
72 | } else { |
73 | /* 33.000 MHz crystal. */ | |
3668b45d | 74 | iop_init_time(198000000); |
c680b77e LB |
75 | } |
76 | } | |
77 | ||
c680b77e LB |
78 | |
79 | /* | |
80 | * IQ31244 I/O. | |
81 | */ | |
82 | static struct map_desc iq31244_io_desc[] __initdata = { | |
83 | { /* on-board devices */ | |
84 | .virtual = IQ31244_UART, | |
85 | .pfn = __phys_to_pfn(IQ31244_UART), | |
86 | .length = 0x00100000, | |
87 | .type = MT_DEVICE, | |
88 | }, | |
89 | }; | |
90 | ||
91 | void __init iq31244_map_io(void) | |
92 | { | |
93 | iop3xx_map_io(); | |
94 | iotable_init(iq31244_io_desc, ARRAY_SIZE(iq31244_io_desc)); | |
95 | } | |
96 | ||
97 | ||
98 | /* | |
99 | * EP80219/IQ31244 PCI. | |
100 | */ | |
d73d8011 | 101 | static int __init |
d5341942 | 102 | ep80219_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
c680b77e LB |
103 | { |
104 | int irq; | |
105 | ||
106 | if (slot == 0) { | |
107 | /* CFlash */ | |
c852ac80 | 108 | irq = IRQ_IOP32X_XINT1; |
c680b77e LB |
109 | } else if (slot == 1) { |
110 | /* 82551 Pro 100 */ | |
c852ac80 | 111 | irq = IRQ_IOP32X_XINT0; |
c680b77e LB |
112 | } else if (slot == 2) { |
113 | /* PCI-X Slot */ | |
c852ac80 | 114 | irq = IRQ_IOP32X_XINT3; |
c680b77e LB |
115 | } else if (slot == 3) { |
116 | /* SATA */ | |
c852ac80 | 117 | irq = IRQ_IOP32X_XINT2; |
c680b77e LB |
118 | } else { |
119 | printk(KERN_ERR "ep80219_pci_map_irq() called for unknown " | |
120 | "device PCI:%d:%d:%d\n", dev->bus->number, | |
121 | PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); | |
122 | irq = -1; | |
123 | } | |
124 | ||
125 | return irq; | |
126 | } | |
127 | ||
128 | static struct hw_pci ep80219_pci __initdata = { | |
c680b77e | 129 | .nr_controllers = 1, |
c23bfc38 | 130 | .ops = &iop3xx_ops, |
c680b77e LB |
131 | .setup = iop3xx_pci_setup, |
132 | .preinit = iop3xx_pci_preinit, | |
c680b77e LB |
133 | .map_irq = ep80219_pci_map_irq, |
134 | }; | |
135 | ||
d73d8011 | 136 | static int __init |
d5341942 | 137 | iq31244_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
c680b77e LB |
138 | { |
139 | int irq; | |
140 | ||
141 | if (slot == 0) { | |
142 | /* CFlash */ | |
c852ac80 | 143 | irq = IRQ_IOP32X_XINT1; |
c680b77e LB |
144 | } else if (slot == 1) { |
145 | /* SATA */ | |
c852ac80 | 146 | irq = IRQ_IOP32X_XINT2; |
c680b77e LB |
147 | } else if (slot == 2) { |
148 | /* PCI-X Slot */ | |
c852ac80 | 149 | irq = IRQ_IOP32X_XINT3; |
c680b77e LB |
150 | } else if (slot == 3) { |
151 | /* 82546 GigE */ | |
c852ac80 | 152 | irq = IRQ_IOP32X_XINT0; |
c680b77e | 153 | } else { |
c852ac80 | 154 | printk(KERN_ERR "iq31244_pci_map_irq called for unknown " |
c680b77e LB |
155 | "device PCI:%d:%d:%d\n", dev->bus->number, |
156 | PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); | |
157 | irq = -1; | |
158 | } | |
159 | ||
160 | return irq; | |
161 | } | |
162 | ||
163 | static struct hw_pci iq31244_pci __initdata = { | |
c680b77e | 164 | .nr_controllers = 1, |
c23bfc38 | 165 | .ops = &iop3xx_ops, |
c680b77e LB |
166 | .setup = iop3xx_pci_setup, |
167 | .preinit = iop3xx_pci_preinit, | |
c680b77e LB |
168 | .map_irq = iq31244_pci_map_irq, |
169 | }; | |
170 | ||
171 | static int __init iq31244_pci_init(void) | |
172 | { | |
c34002c1 DW |
173 | if (is_ep80219()) |
174 | pci_common_init(&ep80219_pci); | |
175 | else if (machine_is_iq31244()) { | |
c680b77e | 176 | if (is_80219()) { |
094f1275 DW |
177 | printk("note: iq31244 board type has been selected\n"); |
178 | printk("note: to select ep80219 operation:\n"); | |
179 | printk("\t1/ specify \"force_ep80219\" on the kernel" | |
180 | " command line\n"); | |
181 | printk("\t2/ update boot loader to pass" | |
182 | " the ep80219 id: %d\n", MACH_TYPE_EP80219); | |
c680b77e | 183 | } |
c34002c1 | 184 | pci_common_init(&iq31244_pci); |
c680b77e LB |
185 | } |
186 | ||
187 | return 0; | |
188 | } | |
189 | ||
190 | subsys_initcall(iq31244_pci_init); | |
191 | ||
192 | ||
193 | /* | |
194 | * IQ31244 machine initialisation. | |
195 | */ | |
196 | static struct physmap_flash_data iq31244_flash_data = { | |
197 | .width = 2, | |
198 | }; | |
199 | ||
200 | static struct resource iq31244_flash_resource = { | |
201 | .start = 0xf0000000, | |
202 | .end = 0xf07fffff, | |
203 | .flags = IORESOURCE_MEM, | |
204 | }; | |
205 | ||
206 | static struct platform_device iq31244_flash_device = { | |
207 | .name = "physmap-flash", | |
208 | .id = 0, | |
209 | .dev = { | |
210 | .platform_data = &iq31244_flash_data, | |
211 | }, | |
212 | .num_resources = 1, | |
213 | .resource = &iq31244_flash_resource, | |
214 | }; | |
215 | ||
216 | static struct plat_serial8250_port iq31244_serial_port[] = { | |
217 | { | |
218 | .mapbase = IQ31244_UART, | |
219 | .membase = (char *)IQ31244_UART, | |
c852ac80 | 220 | .irq = IRQ_IOP32X_XINT1, |
c680b77e LB |
221 | .flags = UPF_SKIP_TEST, |
222 | .iotype = UPIO_MEM, | |
223 | .regshift = 0, | |
224 | .uartclk = 1843200, | |
225 | }, | |
226 | { }, | |
227 | }; | |
228 | ||
229 | static struct resource iq31244_uart_resource = { | |
230 | .start = IQ31244_UART, | |
231 | .end = IQ31244_UART + 7, | |
232 | .flags = IORESOURCE_MEM, | |
233 | }; | |
234 | ||
235 | static struct platform_device iq31244_serial_device = { | |
236 | .name = "serial8250", | |
237 | .id = PLAT8250_DEV_PLATFORM, | |
238 | .dev = { | |
239 | .platform_data = iq31244_serial_port, | |
240 | }, | |
241 | .num_resources = 1, | |
242 | .resource = &iq31244_uart_resource, | |
243 | }; | |
244 | ||
245 | /* | |
246 | * This function will send a SHUTDOWN_COMPLETE message to the PIC | |
247 | * controller over I2C. We are not using the i2c subsystem since | |
248 | * we are going to power off and it may be removed | |
249 | */ | |
250 | void ep80219_power_off(void) | |
251 | { | |
252 | /* | |
253 | * Send the Address byte w/ the start condition | |
254 | */ | |
255 | *IOP3XX_IDBR1 = 0x60; | |
256 | *IOP3XX_ICR1 = 0xE9; | |
257 | mdelay(1); | |
258 | ||
259 | /* | |
260 | * Send the START_MSG byte w/ no start or stop condition | |
261 | */ | |
262 | *IOP3XX_IDBR1 = 0x0F; | |
263 | *IOP3XX_ICR1 = 0xE8; | |
264 | mdelay(1); | |
265 | ||
266 | /* | |
267 | * Send the SHUTDOWN_COMPLETE Message ID byte w/ no start or | |
268 | * stop condition | |
269 | */ | |
270 | *IOP3XX_IDBR1 = 0x03; | |
271 | *IOP3XX_ICR1 = 0xE8; | |
272 | mdelay(1); | |
273 | ||
274 | /* | |
275 | * Send an ignored byte w/ stop condition | |
276 | */ | |
277 | *IOP3XX_IDBR1 = 0x00; | |
278 | *IOP3XX_ICR1 = 0xEA; | |
279 | ||
280 | while (1) | |
281 | ; | |
282 | } | |
283 | ||
284 | static void __init iq31244_init_machine(void) | |
285 | { | |
286 | platform_device_register(&iop3xx_i2c0_device); | |
287 | platform_device_register(&iop3xx_i2c1_device); | |
288 | platform_device_register(&iq31244_flash_device); | |
289 | platform_device_register(&iq31244_serial_device); | |
2492c845 DW |
290 | platform_device_register(&iop3xx_dma_0_channel); |
291 | platform_device_register(&iop3xx_dma_1_channel); | |
c680b77e | 292 | |
094f1275 | 293 | if (is_ep80219()) |
c680b77e | 294 | pm_power_off = ep80219_power_off; |
2492c845 DW |
295 | |
296 | if (!is_80219()) | |
297 | platform_device_register(&iop3xx_aau_channel); | |
c680b77e LB |
298 | } |
299 | ||
094f1275 DW |
300 | static int __init force_ep80219_setup(char *str) |
301 | { | |
302 | force_ep80219 = 1; | |
303 | return 1; | |
304 | } | |
305 | ||
306 | __setup("force_ep80219", force_ep80219_setup); | |
307 | ||
c680b77e LB |
308 | MACHINE_START(IQ31244, "Intel IQ31244") |
309 | /* Maintainer: Intel Corp. */ | |
1896746d | 310 | .atag_offset = 0x100, |
c680b77e | 311 | .map_io = iq31244_map_io, |
c852ac80 | 312 | .init_irq = iop32x_init_irq, |
6bb27d73 | 313 | .init_time = iq31244_timer_init, |
c680b77e | 314 | .init_machine = iq31244_init_machine, |
bec92b1e | 315 | .restart = iop3xx_restart, |
c680b77e | 316 | MACHINE_END |
094f1275 DW |
317 | |
318 | /* There should have been an ep80219 machine identifier from the beginning. | |
319 | * Boot roms older than March 2007 do not know the ep80219 machine id. Pass | |
320 | * "force_ep80219" on the kernel command line, otherwise iq31244 operation | |
321 | * will be selected. | |
322 | */ | |
323 | MACHINE_START(EP80219, "Intel EP80219") | |
324 | /* Maintainer: Intel Corp. */ | |
1896746d | 325 | .atag_offset = 0x100, |
094f1275 DW |
326 | .map_io = iq31244_map_io, |
327 | .init_irq = iop32x_init_irq, | |
6bb27d73 | 328 | .init_time = iq31244_timer_init, |
094f1275 | 329 | .init_machine = iq31244_init_machine, |
bec92b1e | 330 | .restart = iop3xx_restart, |
094f1275 | 331 | MACHINE_END |