Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-iop32x/n2100.c
10817 views
1
/*
2
* arch/arm/mach-iop32x/n2100.c
3
*
4
* Board support code for the Thecus N2100 platform.
5
*
6
* Author: Rory Bolt <[email protected]>
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/f75375s.h>
20
#include <linux/leds-pca9532.h>
21
#include <linux/delay.h>
22
#include <linux/kernel.h>
23
#include <linux/pci.h>
24
#include <linux/pm.h>
25
#include <linux/string.h>
26
#include <linux/serial_core.h>
27
#include <linux/serial_8250.h>
28
#include <linux/mtd/physmap.h>
29
#include <linux/i2c.h>
30
#include <linux/platform_device.h>
31
#include <linux/reboot.h>
32
#include <linux/io.h>
33
#include <mach/hardware.h>
34
#include <asm/irq.h>
35
#include <asm/mach/arch.h>
36
#include <asm/mach/map.h>
37
#include <asm/mach/pci.h>
38
#include <asm/mach/time.h>
39
#include <asm/mach-types.h>
40
#include <asm/page.h>
41
#include <asm/pgtable.h>
42
#include <mach/time.h>
43
44
/*
45
* N2100 timer tick configuration.
46
*/
47
static void __init n2100_timer_init(void)
48
{
49
/* 33.000 MHz crystal. */
50
iop_init_time(198000000);
51
}
52
53
static struct sys_timer n2100_timer = {
54
.init = n2100_timer_init,
55
};
56
57
58
/*
59
* N2100 I/O.
60
*/
61
static struct map_desc n2100_io_desc[] __initdata = {
62
{ /* on-board devices */
63
.virtual = N2100_UART,
64
.pfn = __phys_to_pfn(N2100_UART),
65
.length = 0x00100000,
66
.type = MT_DEVICE
67
},
68
};
69
70
void __init n2100_map_io(void)
71
{
72
iop3xx_map_io();
73
iotable_init(n2100_io_desc, ARRAY_SIZE(n2100_io_desc));
74
}
75
76
77
/*
78
* N2100 PCI.
79
*/
80
static int __init
81
n2100_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
82
{
83
int irq;
84
85
if (PCI_SLOT(dev->devfn) == 1) {
86
/* RTL8110SB #1 */
87
irq = IRQ_IOP32X_XINT0;
88
} else if (PCI_SLOT(dev->devfn) == 2) {
89
/* RTL8110SB #2 */
90
irq = IRQ_IOP32X_XINT3;
91
} else if (PCI_SLOT(dev->devfn) == 3) {
92
/* Sil3512 */
93
irq = IRQ_IOP32X_XINT2;
94
} else if (PCI_SLOT(dev->devfn) == 4 && pin == 1) {
95
/* VT6212 INTA */
96
irq = IRQ_IOP32X_XINT1;
97
} else if (PCI_SLOT(dev->devfn) == 4 && pin == 2) {
98
/* VT6212 INTB */
99
irq = IRQ_IOP32X_XINT0;
100
} else if (PCI_SLOT(dev->devfn) == 4 && pin == 3) {
101
/* VT6212 INTC */
102
irq = IRQ_IOP32X_XINT2;
103
} else if (PCI_SLOT(dev->devfn) == 5) {
104
/* Mini-PCI slot */
105
irq = IRQ_IOP32X_XINT3;
106
} else {
107
printk(KERN_ERR "n2100_pci_map_irq() called for unknown "
108
"device PCI:%d:%d:%d\n", dev->bus->number,
109
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
110
irq = -1;
111
}
112
113
return irq;
114
}
115
116
static struct hw_pci n2100_pci __initdata = {
117
.swizzle = pci_std_swizzle,
118
.nr_controllers = 1,
119
.setup = iop3xx_pci_setup,
120
.preinit = iop3xx_pci_preinit,
121
.scan = iop3xx_pci_scan_bus,
122
.map_irq = n2100_pci_map_irq,
123
};
124
125
/*
126
* Both r8169 chips on the n2100 exhibit PCI parity problems. Set
127
* the ->broken_parity_status flag for both ports so that the r8169
128
* driver knows it should ignore error interrupts.
129
*/
130
static void n2100_fixup_r8169(struct pci_dev *dev)
131
{
132
if (dev->bus->number == 0 &&
133
(dev->devfn == PCI_DEVFN(1, 0) ||
134
dev->devfn == PCI_DEVFN(2, 0)))
135
dev->broken_parity_status = 1;
136
}
137
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_REALTEK, PCI_ANY_ID, n2100_fixup_r8169);
138
139
static int __init n2100_pci_init(void)
140
{
141
if (machine_is_n2100())
142
pci_common_init(&n2100_pci);
143
144
return 0;
145
}
146
147
subsys_initcall(n2100_pci_init);
148
149
150
/*
151
* N2100 machine initialisation.
152
*/
153
static struct physmap_flash_data n2100_flash_data = {
154
.width = 2,
155
};
156
157
static struct resource n2100_flash_resource = {
158
.start = 0xf0000000,
159
.end = 0xf0ffffff,
160
.flags = IORESOURCE_MEM,
161
};
162
163
static struct platform_device n2100_flash_device = {
164
.name = "physmap-flash",
165
.id = 0,
166
.dev = {
167
.platform_data = &n2100_flash_data,
168
},
169
.num_resources = 1,
170
.resource = &n2100_flash_resource,
171
};
172
173
174
static struct plat_serial8250_port n2100_serial_port[] = {
175
{
176
.mapbase = N2100_UART,
177
.membase = (char *)N2100_UART,
178
.irq = 0,
179
.flags = UPF_SKIP_TEST | UPF_AUTO_IRQ | UPF_SHARE_IRQ,
180
.iotype = UPIO_MEM,
181
.regshift = 0,
182
.uartclk = 1843200,
183
},
184
{ },
185
};
186
187
static struct resource n2100_uart_resource = {
188
.start = N2100_UART,
189
.end = N2100_UART + 7,
190
.flags = IORESOURCE_MEM,
191
};
192
193
static struct platform_device n2100_serial_device = {
194
.name = "serial8250",
195
.id = PLAT8250_DEV_PLATFORM,
196
.dev = {
197
.platform_data = n2100_serial_port,
198
},
199
.num_resources = 1,
200
.resource = &n2100_uart_resource,
201
};
202
203
static struct f75375s_platform_data n2100_f75375s = {
204
.pwm = { 255, 255 },
205
.pwm_enable = { 0, 0 },
206
};
207
208
static struct pca9532_platform_data n2100_leds = {
209
.leds = {
210
{ .name = "n2100:red:satafail0",
211
.state = PCA9532_OFF,
212
.type = PCA9532_TYPE_LED,
213
},
214
{ .name = "n2100:red:satafail1",
215
.state = PCA9532_OFF,
216
.type = PCA9532_TYPE_LED,
217
},
218
{ .name = "n2100:blue:usb",
219
.state = PCA9532_OFF,
220
.type = PCA9532_TYPE_LED,
221
},
222
{ .type = PCA9532_TYPE_NONE },
223
224
{ .type = PCA9532_TYPE_NONE },
225
{ .type = PCA9532_TYPE_NONE },
226
{ .type = PCA9532_TYPE_NONE },
227
{ .name = "n2100:red:usb",
228
.state = PCA9532_OFF,
229
.type = PCA9532_TYPE_LED,
230
},
231
232
{ .type = PCA9532_TYPE_NONE }, /* power OFF gpio */
233
{ .type = PCA9532_TYPE_NONE }, /* reset gpio */
234
{ .type = PCA9532_TYPE_NONE },
235
{ .type = PCA9532_TYPE_NONE },
236
237
{ .type = PCA9532_TYPE_NONE },
238
{ .name = "n2100:orange:system",
239
.state = PCA9532_OFF,
240
.type = PCA9532_TYPE_LED,
241
},
242
{ .name = "n2100:red:system",
243
.state = PCA9532_OFF,
244
.type = PCA9532_TYPE_LED,
245
},
246
{ .name = "N2100 beeper" ,
247
.state = PCA9532_OFF,
248
.type = PCA9532_TYPE_N2100_BEEP,
249
},
250
},
251
.psc = { 0, 0 },
252
.pwm = { 0, 0 },
253
};
254
255
static struct i2c_board_info __initdata n2100_i2c_devices[] = {
256
{
257
I2C_BOARD_INFO("rs5c372b", 0x32),
258
},
259
{
260
I2C_BOARD_INFO("f75375", 0x2e),
261
.platform_data = &n2100_f75375s,
262
},
263
{
264
I2C_BOARD_INFO("pca9532", 0x60),
265
.platform_data = &n2100_leds,
266
},
267
};
268
269
/*
270
* Pull PCA9532 GPIO #8 low to power off the machine.
271
*/
272
static void n2100_power_off(void)
273
{
274
local_irq_disable();
275
276
/* Start condition, I2C address of PCA9532, write transaction. */
277
*IOP3XX_IDBR0 = 0xc0;
278
*IOP3XX_ICR0 = 0xe9;
279
mdelay(1);
280
281
/* Write address 0x08. */
282
*IOP3XX_IDBR0 = 0x08;
283
*IOP3XX_ICR0 = 0xe8;
284
mdelay(1);
285
286
/* Write data 0x01, stop condition. */
287
*IOP3XX_IDBR0 = 0x01;
288
*IOP3XX_ICR0 = 0xea;
289
290
while (1)
291
;
292
}
293
294
295
static struct timer_list power_button_poll_timer;
296
297
static void power_button_poll(unsigned long dummy)
298
{
299
if (gpio_line_get(N2100_POWER_BUTTON) == 0) {
300
ctrl_alt_del();
301
return;
302
}
303
304
power_button_poll_timer.expires = jiffies + (HZ / 10);
305
add_timer(&power_button_poll_timer);
306
}
307
308
309
static void __init n2100_init_machine(void)
310
{
311
platform_device_register(&iop3xx_i2c0_device);
312
platform_device_register(&n2100_flash_device);
313
platform_device_register(&n2100_serial_device);
314
platform_device_register(&iop3xx_dma_0_channel);
315
platform_device_register(&iop3xx_dma_1_channel);
316
317
i2c_register_board_info(0, n2100_i2c_devices,
318
ARRAY_SIZE(n2100_i2c_devices));
319
320
pm_power_off = n2100_power_off;
321
322
init_timer(&power_button_poll_timer);
323
power_button_poll_timer.function = power_button_poll;
324
power_button_poll_timer.expires = jiffies + (HZ / 10);
325
add_timer(&power_button_poll_timer);
326
}
327
328
MACHINE_START(N2100, "Thecus N2100")
329
/* Maintainer: Lennert Buytenhek <[email protected]> */
330
.boot_params = 0xa0000100,
331
.map_io = n2100_map_io,
332
.init_irq = iop32x_init_irq,
333
.timer = &n2100_timer,
334
.init_machine = n2100_init_machine,
335
MACHINE_END
336
337