generic2e_machdep.c revision 1.5 1 1.1 bouyer /* $OpenBSD: generic2e_machdep.c,v 1.2 2011/04/15 20:40:06 deraadt Exp $ */
2 1.1 bouyer
3 1.1 bouyer /*
4 1.1 bouyer * Copyright (c) 2010 Miodrag Vallat.
5 1.1 bouyer *
6 1.1 bouyer * Permission to use, copy, modify, and distribute this software for any
7 1.1 bouyer * purpose with or without fee is hereby granted, provided that the above
8 1.1 bouyer * copyright notice and this permission notice appear in all copies.
9 1.1 bouyer *
10 1.1 bouyer * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 1.1 bouyer * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 1.1 bouyer * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 1.1 bouyer * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 1.1 bouyer * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 1.1 bouyer * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 1.1 bouyer * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 1.1 bouyer */
18 1.1 bouyer /*-
19 1.1 bouyer * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
20 1.1 bouyer * All rights reserved.
21 1.1 bouyer *
22 1.1 bouyer * This code is derived from software contributed to The NetBSD Foundation
23 1.1 bouyer * by Jason R. Thorpe.
24 1.1 bouyer *
25 1.1 bouyer * Redistribution and use in source and binary forms, with or without
26 1.1 bouyer * modification, are permitted provided that the following conditions
27 1.1 bouyer * are met:
28 1.1 bouyer * 1. Redistributions of source code must retain the above copyright
29 1.1 bouyer * notice, this list of conditions and the following disclaimer.
30 1.1 bouyer * 2. Redistributions in binary form must reproduce the above copyright
31 1.1 bouyer * notice, this list of conditions and the following disclaimer in the
32 1.1 bouyer * documentation and/or other materials provided with the distribution.
33 1.1 bouyer *
34 1.1 bouyer * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
35 1.1 bouyer * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
36 1.1 bouyer * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
37 1.1 bouyer * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
38 1.1 bouyer * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39 1.1 bouyer * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40 1.1 bouyer * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41 1.1 bouyer * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
42 1.1 bouyer * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
43 1.1 bouyer * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44 1.1 bouyer * POSSIBILITY OF SUCH DAMAGE.
45 1.1 bouyer */
46 1.1 bouyer
47 1.1 bouyer /*
48 1.1 bouyer * Generic Loongson 2E code and configuration data.
49 1.1 bouyer */
50 1.1 bouyer #include <sys/cdefs.h>
51 1.5 macallan __KERNEL_RCSID(0, "$NetBSD: generic2e_machdep.c,v 1.5 2015/06/09 16:10:48 macallan Exp $");
52 1.1 bouyer
53 1.1 bouyer #include <sys/param.h>
54 1.1 bouyer #include <sys/systm.h>
55 1.1 bouyer #include <sys/device.h>
56 1.1 bouyer #include <sys/types.h>
57 1.1 bouyer
58 1.1 bouyer
59 1.1 bouyer #include <dev/ic/i8259reg.h>
60 1.1 bouyer
61 1.1 bouyer #include <dev/isa/isareg.h>
62 1.1 bouyer #include <dev/isa/isavar.h>
63 1.1 bouyer
64 1.1 bouyer #include <dev/pci/pcireg.h>
65 1.1 bouyer #include <dev/pci/pcivar.h>
66 1.1 bouyer #include <dev/pci/pcidevs.h>
67 1.1 bouyer
68 1.5 macallan #include <mips/cpuregs.h>
69 1.1 bouyer #include <mips/bonito/bonitoreg.h>
70 1.1 bouyer #include <mips/bonito/bonitovar.h>
71 1.1 bouyer
72 1.1 bouyer #include <evbmips/loongson/autoconf.h>
73 1.1 bouyer #include <mips/pmon/pmon.h>
74 1.1 bouyer #include <evbmips/loongson/loongson_intr.h>
75 1.1 bouyer #include <evbmips/loongson/loongson_isa.h>
76 1.1 bouyer #include <evbmips/loongson/loongson_bus_defs.h>
77 1.1 bouyer
78 1.1 bouyer #include "com.h"
79 1.1 bouyer #include "isa.h"
80 1.1 bouyer
81 1.1 bouyer #if NCOM > 0
82 1.1 bouyer #include <sys/termios.h>
83 1.1 bouyer #include <dev/ic/comvar.h>
84 1.1 bouyer #endif
85 1.1 bouyer
86 1.3 chs void generic2e_device_register(device_t, void *);
87 1.1 bouyer void generic2e_reset(void);
88 1.1 bouyer
89 1.1 bouyer void generic2e_setup(void);
90 1.1 bouyer
91 1.1 bouyer void generic2e_pci_attach_hook(device_t, device_t,
92 1.1 bouyer struct pcibus_attach_args *);
93 1.1 bouyer int generic2e_intr_map(int, int, int, pci_intr_handle_t *);
94 1.1 bouyer
95 1.3 chs void generic2e_isa_attach_hook(device_t, device_t,
96 1.1 bouyer struct isabus_attach_args *);
97 1.1 bouyer void *generic2e_isa_intr_establish(void *, int, int, int,
98 1.1 bouyer int (*)(void *), void *);
99 1.1 bouyer void generic2e_isa_intr_disestablish(void *, void *);
100 1.1 bouyer const struct evcnt * generic2e_isa_intr_evcnt(void *, int);
101 1.4 christos const char * generic2e_isa_intr_string(void *, int, char *, size_t);
102 1.1 bouyer
103 1.1 bouyer void generic2e_isa_intr(int, vaddr_t, uint32_t);
104 1.1 bouyer
105 1.1 bouyer void via686sb_setup(pci_chipset_tag_t, int);
106 1.1 bouyer
107 1.1 bouyer /* PnP IRQ assignment for VIA686 SuperIO components */
108 1.1 bouyer #define VIA686_IRQ_PCIA 9
109 1.1 bouyer #define VIA686_IRQ_PCIB 10
110 1.1 bouyer #define VIA686_IRQ_PCIC 11
111 1.1 bouyer #define VIA686_IRQ_PCID 13
112 1.1 bouyer
113 1.1 bouyer static int generic2e_via686sb_dev = -1;
114 1.1 bouyer
115 1.1 bouyer const struct bonito_config generic2e_bonito = {
116 1.1 bouyer .bc_adbase = 11,
117 1.1 bouyer
118 1.1 bouyer .bc_gpioIE = 0xffffffff,
119 1.1 bouyer .bc_intEdge = BONITO_INTRMASK_SYSTEMERR | BONITO_INTRMASK_MASTERERR |
120 1.1 bouyer BONITO_INTRMASK_RETRYERR | BONITO_INTRMASK_MBOX,
121 1.1 bouyer .bc_intSteer = 0,
122 1.1 bouyer .bc_intPol = 0,
123 1.1 bouyer
124 1.1 bouyer .bc_attach_hook = generic2e_pci_attach_hook,
125 1.1 bouyer };
126 1.1 bouyer
127 1.1 bouyer const struct legacy_io_range generic2e_legacy_ranges[] = {
128 1.1 bouyer /* no isa space access restrictions */
129 1.1 bouyer { 0, BONITO_PCIIO_LEGACY },
130 1.1 bouyer
131 1.1 bouyer { 0 }
132 1.1 bouyer };
133 1.1 bouyer
134 1.1 bouyer struct mips_isa_chipset generic2e_isa_chipset = {
135 1.1 bouyer .ic_v = NULL,
136 1.1 bouyer
137 1.1 bouyer .ic_attach_hook = generic2e_isa_attach_hook,
138 1.1 bouyer .ic_intr_establish = generic2e_isa_intr_establish,
139 1.1 bouyer .ic_intr_disestablish = generic2e_isa_intr_disestablish,
140 1.1 bouyer .ic_intr_evcnt = generic2e_isa_intr_evcnt,
141 1.1 bouyer .ic_intr_string = generic2e_isa_intr_string,
142 1.1 bouyer };
143 1.1 bouyer
144 1.1 bouyer const struct platform generic2e_platform = {
145 1.1 bouyer .system_type = LOONGSON_2E,
146 1.1 bouyer .vendor = "Generic",
147 1.1 bouyer .product = "Loongson2E",
148 1.1 bouyer
149 1.1 bouyer .bonito_config = &generic2e_bonito,
150 1.1 bouyer .isa_chipset = &generic2e_isa_chipset,
151 1.1 bouyer .legacy_io_ranges = generic2e_legacy_ranges,
152 1.1 bouyer .bonito_mips_intr = MIPS_INT_MASK_0,
153 1.1 bouyer .isa_mips_intr = MIPS_INT_MASK_3,
154 1.1 bouyer .isa_intr = generic2e_isa_intr,
155 1.1 bouyer .p_pci_intr_map = generic2e_intr_map,
156 1.1 bouyer .irq_map = loongson2e_irqmap,
157 1.1 bouyer
158 1.1 bouyer .setup = generic2e_setup,
159 1.1 bouyer .device_register = generic2e_device_register,
160 1.1 bouyer
161 1.1 bouyer .powerdown = NULL,
162 1.1 bouyer .reset = generic2e_reset
163 1.1 bouyer };
164 1.1 bouyer
165 1.1 bouyer /*
166 1.1 bouyer * PCI model specific routines
167 1.1 bouyer */
168 1.1 bouyer
169 1.1 bouyer void
170 1.1 bouyer generic2e_pci_attach_hook(device_t parent, device_t self,
171 1.1 bouyer struct pcibus_attach_args *pba)
172 1.1 bouyer {
173 1.1 bouyer pci_chipset_tag_t pc = pba->pba_pc;
174 1.1 bouyer pcireg_t id;
175 1.1 bouyer pcitag_t tag;
176 1.1 bouyer int dev;
177 1.1 bouyer
178 1.1 bouyer if (pba->pba_bus != 0)
179 1.1 bouyer return;
180 1.1 bouyer
181 1.1 bouyer /*
182 1.1 bouyer * Check for a VIA 686 southbridge; if one is found, remember
183 1.1 bouyer * its location, needed by generic2e_intr_map().
184 1.1 bouyer */
185 1.1 bouyer
186 1.1 bouyer for (dev = pci_bus_maxdevs(pc, 0); dev >= 0; dev--) {
187 1.1 bouyer tag = pci_make_tag(pc, 0, dev, 0);
188 1.1 bouyer id = pci_conf_read(pc, tag, PCI_ID_REG);
189 1.1 bouyer if (id == PCI_ID_CODE(PCI_VENDOR_VIATECH,
190 1.1 bouyer PCI_PRODUCT_VIATECH_VT82C686A_ISA)) {
191 1.1 bouyer generic2e_via686sb_dev = dev;
192 1.1 bouyer break;
193 1.1 bouyer }
194 1.1 bouyer }
195 1.1 bouyer
196 1.1 bouyer if (generic2e_via686sb_dev != 0)
197 1.1 bouyer via686sb_setup(pc, generic2e_via686sb_dev);
198 1.1 bouyer }
199 1.1 bouyer
200 1.1 bouyer int
201 1.1 bouyer generic2e_intr_map(int dev, int fn, int pin, pci_intr_handle_t *ihp)
202 1.1 bouyer {
203 1.1 bouyer if (dev == generic2e_via686sb_dev) {
204 1.1 bouyer switch (fn) {
205 1.1 bouyer case 1: /* PCIIDE */
206 1.1 bouyer /* will use compat interrupt */
207 1.1 bouyer break;
208 1.1 bouyer case 2: /* USB */
209 1.1 bouyer *ihp = BONITO_ISA_IRQ(VIA686_IRQ_PCIB);
210 1.1 bouyer return 0;
211 1.1 bouyer case 3: /* USB */
212 1.1 bouyer *ihp = BONITO_ISA_IRQ(VIA686_IRQ_PCIC);
213 1.1 bouyer return 0;
214 1.1 bouyer case 4: /* power management, SMBus */
215 1.1 bouyer break;
216 1.1 bouyer case 5: /* Audio */
217 1.1 bouyer *ihp = BONITO_ISA_IRQ(VIA686_IRQ_PCIA);
218 1.1 bouyer return 0;
219 1.1 bouyer case 6: /* Modem */
220 1.1 bouyer break;
221 1.1 bouyer default:
222 1.1 bouyer break;
223 1.1 bouyer }
224 1.1 bouyer } else {
225 1.1 bouyer *ihp = BONITO_DIRECT_IRQ(BONITO_INTR_GPIN +
226 1.1 bouyer pin - PCI_INTERRUPT_PIN_A);
227 1.1 bouyer return 0;
228 1.1 bouyer }
229 1.1 bouyer
230 1.1 bouyer return 1;
231 1.1 bouyer }
232 1.1 bouyer
233 1.1 bouyer /*
234 1.1 bouyer * ISA model specific routines
235 1.1 bouyer */
236 1.1 bouyer
237 1.1 bouyer void
238 1.3 chs generic2e_isa_attach_hook(device_t parent, device_t self,
239 1.1 bouyer struct isabus_attach_args *iba)
240 1.1 bouyer {
241 1.1 bouyer loongson_set_isa_imr(loongson_isaimr);
242 1.1 bouyer }
243 1.1 bouyer
244 1.1 bouyer void *
245 1.1 bouyer generic2e_isa_intr_establish(void *v, int irq, int type, int level,
246 1.1 bouyer int (*handler)(void *), void *arg)
247 1.1 bouyer {
248 1.1 bouyer void *ih;
249 1.1 bouyer uint imr;
250 1.1 bouyer
251 1.1 bouyer ih = evbmips_intr_establish(BONITO_ISA_IRQ(irq), handler, arg);
252 1.1 bouyer if (ih == NULL)
253 1.1 bouyer return NULL;
254 1.1 bouyer /* enable interrupt */
255 1.1 bouyer imr = loongson_isaimr;
256 1.1 bouyer imr |= (1 << irq);
257 1.1 bouyer loongson_set_isa_imr(imr);
258 1.1 bouyer return ih;
259 1.1 bouyer }
260 1.1 bouyer
261 1.1 bouyer void
262 1.1 bouyer generic2e_isa_intr_disestablish(void *v, void *ih)
263 1.1 bouyer {
264 1.1 bouyer evbmips_intr_disestablish(ih);
265 1.1 bouyer }
266 1.1 bouyer
267 1.1 bouyer const struct evcnt *
268 1.1 bouyer generic2e_isa_intr_evcnt(void *v, int irq)
269 1.1 bouyer {
270 1.1 bouyer
271 1.1 bouyer if (irq == 0 || irq >= BONITO_NISA || irq == 2)
272 1.1 bouyer panic("generic2e_isa_intr_evcnt: bogus isa irq 0x%x", irq);
273 1.1 bouyer
274 1.1 bouyer return (&bonito_intrhead[BONITO_ISA_IRQ(irq)].intr_count);
275 1.1 bouyer }
276 1.1 bouyer
277 1.1 bouyer const char *
278 1.4 christos generic2e_isa_intr_string(void *v, int irq, char *buf, size_t len)
279 1.1 bouyer {
280 1.1 bouyer if (irq == 0 || irq >= BONITO_NISA || irq == 2)
281 1.1 bouyer panic("generic2e_isa_intr_string: bogus isa irq 0x%x", irq);
282 1.1 bouyer
283 1.4 christos return loongson_intr_string(&generic2e_bonito, irq, buf, len);
284 1.1 bouyer }
285 1.1 bouyer
286 1.1 bouyer void
287 1.1 bouyer generic2e_isa_intr(int ipl, vaddr_t pc, uint32_t ipending)
288 1.1 bouyer {
289 1.1 bouyer #if NISA > 0
290 1.1 bouyer struct evbmips_intrhand *ih;
291 1.1 bouyer uint64_t isr, mask = 0;
292 1.1 bouyer int rc, irq, ret;
293 1.1 bouyer uint8_t ocw1, ocw2;
294 1.1 bouyer
295 1.1 bouyer for (;;) {
296 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) =
297 1.1 bouyer OCW3_SELECT | OCW3_POLL;
298 1.1 bouyer ocw1 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3);
299 1.1 bouyer if ((ocw1 & OCW3_POLL_PENDING) == 0)
300 1.1 bouyer break;
301 1.1 bouyer
302 1.1 bouyer irq = OCW3_POLL_IRQ(ocw1);
303 1.1 bouyer
304 1.1 bouyer if (irq == 2) /* cascade */ {
305 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) =
306 1.1 bouyer OCW3_SELECT | OCW3_POLL;
307 1.1 bouyer ocw2 = REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3);
308 1.1 bouyer if (ocw2 & OCW3_POLL_PENDING)
309 1.1 bouyer irq = OCW3_POLL_IRQ(ocw2);
310 1.1 bouyer else
311 1.1 bouyer irq = 2;
312 1.1 bouyer } else
313 1.1 bouyer ocw2 = 0;
314 1.1 bouyer
315 1.1 bouyer /*
316 1.1 bouyer * Mask the interrupt before servicing it.
317 1.1 bouyer */
318 1.1 bouyer isr = 1UL << irq;
319 1.1 bouyer loongson_set_isa_imr(loongson_isaimr & ~isr);
320 1.1 bouyer
321 1.1 bouyer mask |= isr;
322 1.1 bouyer
323 1.1 bouyer rc = 0;
324 1.1 bouyer LIST_FOREACH(ih,
325 1.1 bouyer &bonito_intrhead[BONITO_ISA_IRQ(irq)].intrhand_head,
326 1.1 bouyer ih_q) {
327 1.1 bouyer ret = (*ih->ih_func)(ih->ih_arg);
328 1.1 bouyer if (ret) {
329 1.1 bouyer rc = 1;
330 1.1 bouyer bonito_intrhead[BONITO_ISA_IRQ(irq)].intr_count.ev_count++;
331 1.1 bouyer }
332 1.1 bouyer
333 1.1 bouyer if (ret == 1)
334 1.1 bouyer break;
335 1.1 bouyer }
336 1.1 bouyer
337 1.1 bouyer /* Send a specific EOI to the 8259. */
338 1.1 bouyer loongson_isa_specific_eoi(irq);
339 1.1 bouyer
340 1.1 bouyer if (rc == 0) {
341 1.1 bouyer printf("spurious isa interrupt %d\n", irq);
342 1.1 bouyer }
343 1.1 bouyer }
344 1.1 bouyer
345 1.1 bouyer /*
346 1.1 bouyer * Reenable interrupts which have been serviced.
347 1.1 bouyer */
348 1.1 bouyer if (mask != 0)
349 1.1 bouyer loongson_set_isa_imr(loongson_isaimr | mask);
350 1.1 bouyer
351 1.1 bouyer #endif
352 1.1 bouyer }
353 1.1 bouyer
354 1.1 bouyer /*
355 1.1 bouyer * Other model specific routines
356 1.1 bouyer */
357 1.1 bouyer
358 1.1 bouyer void
359 1.2 christos generic2e_reset(void)
360 1.1 bouyer {
361 1.1 bouyer REGVAL(BONITO_BONGENCFG) &= ~BONITO_BONGENCFG_CPUSELFRESET;
362 1.1 bouyer REGVAL(BONITO_BONGENCFG) |= BONITO_BONGENCFG_CPUSELFRESET;
363 1.1 bouyer delay(1000000);
364 1.1 bouyer }
365 1.1 bouyer
366 1.1 bouyer void
367 1.1 bouyer generic2e_setup(void)
368 1.1 bouyer {
369 1.1 bouyer #if NCOM > 0
370 1.1 bouyer const char *envvar;
371 1.1 bouyer int serial;
372 1.1 bouyer
373 1.1 bouyer envvar = pmon_getenv("nokbd");
374 1.1 bouyer serial = envvar != NULL;
375 1.1 bouyer envvar = pmon_getenv("novga");
376 1.1 bouyer serial = serial && envvar != NULL;
377 1.1 bouyer
378 1.1 bouyer if (serial) {
379 1.1 bouyer comconsiot = &bonito_iot;
380 1.1 bouyer comconsaddr = 0x3f8;
381 1.1 bouyer comconsrate = 115200; /* default PMON console speed */
382 1.1 bouyer }
383 1.1 bouyer #endif
384 1.1 bouyer }
385 1.1 bouyer
386 1.1 bouyer void
387 1.3 chs generic2e_device_register(device_t dev, void *aux)
388 1.1 bouyer {
389 1.1 bouyer const char *name = device_xname(dev);
390 1.1 bouyer
391 1.3 chs if (device_class(dev) != bootdev_class)
392 1.3 chs return;
393 1.1 bouyer
394 1.1 bouyer /*
395 1.1 bouyer * The device numbering must match. There's no way
396 1.1 bouyer * pmon tells us more info. Depending on the usb slot
397 1.1 bouyer * and hubs used you may be lucky. Also, assume umass/sd for usb
398 1.1 bouyer * attached devices.
399 1.1 bouyer */
400 1.1 bouyer switch (bootdev_class) {
401 1.1 bouyer case DV_DISK:
402 1.1 bouyer if (device_is_a(dev, "wd") && strcmp(name, bootdev) == 0) {
403 1.1 bouyer if (booted_device == NULL)
404 1.1 bouyer booted_device = dev;
405 1.1 bouyer } else {
406 1.1 bouyer /* XXX this really only works safely for usb0... */
407 1.1 bouyer if ((device_is_a(dev, "sd") ||
408 1.1 bouyer device_is_a(dev, "cd")) &&
409 1.1 bouyer strncmp(bootdev, "usb", 3) == 0 &&
410 1.1 bouyer strcmp(name + 2, bootdev + 3) == 0) {
411 1.1 bouyer if (booted_device == NULL)
412 1.1 bouyer booted_device = dev;
413 1.1 bouyer }
414 1.1 bouyer }
415 1.1 bouyer break;
416 1.1 bouyer case DV_IFNET:
417 1.1 bouyer /*
418 1.1 bouyer * This relies on the onboard Ethernet interface being
419 1.1 bouyer * attached before any other (usb) interface.
420 1.1 bouyer */
421 1.1 bouyer if (booted_device == NULL)
422 1.1 bouyer booted_device = dev;
423 1.1 bouyer break;
424 1.1 bouyer default:
425 1.1 bouyer break;
426 1.1 bouyer }
427 1.1 bouyer }
428 1.1 bouyer
429 1.1 bouyer /*
430 1.1 bouyer * Initialize a VIA686 south bridge.
431 1.1 bouyer *
432 1.1 bouyer * PMON apparently does not perform enough initialization; one may argue this
433 1.1 bouyer * could be done with a specific pcib(4) driver, but then no other system
434 1.1 bouyer * will hopefully need this, so keep it local to the 2E setup code.
435 1.1 bouyer */
436 1.1 bouyer
437 1.1 bouyer #define VIA686_ISA_ROM_CONTROL 0x40
438 1.1 bouyer #define VIA686_ROM_WRITE_ENABLE 0x00000001
439 1.1 bouyer #define VIA686_NO_ROM_WAIT_STATE 0x00000002
440 1.1 bouyer #define VIA686_EXTEND_ALE 0x00000004
441 1.1 bouyer #define VIA686_IO_RECOVERY_TIME 0x00000008
442 1.1 bouyer #define VIA686_CHIPSET_EXTRA_WAIT_STATES 0x00000010
443 1.1 bouyer #define VIA686_ISA_EXTRA_WAIT_STATES 0x00000020
444 1.1 bouyer #define VIA686_ISA_EXTENDED_BUS_READY 0x00000040
445 1.1 bouyer #define VIA686_ISA_EXTRA_COMMAND_DELAY 0x00000080
446 1.1 bouyer #define VIA686_ISA_REFRESH 0x00000100
447 1.1 bouyer #define VIA686_DOUBLE_DMA_CLOCK 0x00000800
448 1.1 bouyer #define VIA686_PORT_92_FAST_RESET 0x00002000
449 1.1 bouyer #define VIA686_IO_MEDIUM_RECOVERY_TIME 0x00004000
450 1.1 bouyer #define VIA686_KBC_DMA_MISC12 0x44
451 1.1 bouyer #define VIA686_ISA_MASTER_TO_LINE_BUFFER 0x00008000
452 1.1 bouyer #define VIA686_POSTED_MEMORY_WRITE_ENABLE 0x00010000
453 1.1 bouyer #define VIA686_PCI_BURST_INTERRUPTABLE 0x00020000
454 1.1 bouyer #define VIA686_FLUSH_LINE_BUFFER_ON_INTR 0x00200000
455 1.1 bouyer #define VIA686_GATE_INTR 0x00400000
456 1.1 bouyer #define VIA686_PCI_MASTER_WRITE_WAIT_STATE 0x00800000
457 1.1 bouyer #define VIA686_PCI_RESET 0x01000000
458 1.1 bouyer #define VIA686_PCI_READ_DELAY_TRANSACTION_TMO 0x02000000
459 1.1 bouyer #define VIA686_PCI_WRITE_DELAY_TRANSACTION_TMO 0x04000000
460 1.1 bouyer #define VIA686_ICR_SHADOW_ENABLE 0x10000000
461 1.1 bouyer #define VIA686_EISA_PORT_4D0_4D1_ENABLE 0x20000000
462 1.1 bouyer #define VIA686_PCI_DELAY_TRANSACTION_ENABLE 0x40000000
463 1.1 bouyer #define VIA686_CPU_RESET_SOURCE_INIT 0x80000000
464 1.1 bouyer #define VIA686_MISC3_IDE_INTR 0x48
465 1.1 bouyer #define VIA686_IDE_PRIMARY_CHAN_MASK 0x00030000
466 1.1 bouyer #define VIA686_IDE_PRIMARY_CHAN_SHIFT 16
467 1.1 bouyer #define VIA686_IDE_SECONDARY_CHAN_MASK 0x000c0000
468 1.1 bouyer #define VIA686_IDE_SECONDARY_CHAN_SHIFT 18
469 1.1 bouyer #define VIA686_IDE_IRQ14 00
470 1.1 bouyer #define VIA686_IDE_IRQ15 01
471 1.1 bouyer #define VIA686_IDE_IRQ10 02
472 1.1 bouyer #define VIA686_IDE_IRQ11 03
473 1.1 bouyer #define VIA686_IDE_PGNT 0x00800000
474 1.1 bouyer #define VIA686_PNP_DMA_IRQ 0x50
475 1.1 bouyer #define VIA686_DMA_FDC_MASK 0x00000003
476 1.1 bouyer #define VIA686_DMA_FDC_SHIFT 0
477 1.1 bouyer #define VIA686_DMA_LPT_MASK 0x0000000c
478 1.1 bouyer #define VIA686_DMA_LPT_SHIFT 2
479 1.1 bouyer #define VIA686_IRQ_FDC_MASK 0x00000f00
480 1.1 bouyer #define VIA686_IRQ_FDC_SHIFT 8
481 1.1 bouyer #define VIA686_IRQ_LPT_MASK 0x0000f000
482 1.1 bouyer #define VIA686_IRQ_LPT_SHIFT 12
483 1.1 bouyer #define VIA686_IRQ_COM0_MASK 0x000f0000
484 1.1 bouyer #define VIA686_IRQ_COM0_SHIFT 16
485 1.1 bouyer #define VIA686_IRQ_COM1_MASK 0x00f00000
486 1.1 bouyer #define VIA686_IRQ_COM1_SHIFT 20
487 1.1 bouyer #define VIA686_PCI_LEVEL_PNP_IRQ2 0x54
488 1.1 bouyer #define VIA686_PCI_IRQD_EDGE 0x00000001
489 1.1 bouyer #define VIA686_PCI_IRQC_EDGE 0x00000002
490 1.1 bouyer #define VIA686_PCI_IRQB_EDGE 0x00000004
491 1.1 bouyer #define VIA686_PCI_IRQA_EDGE 0x00000008
492 1.1 bouyer #define VIA686_IRQ_PCIA_MASK 0x0000f000
493 1.1 bouyer #define VIA686_IRQ_PCIA_SHIFT 12
494 1.1 bouyer #define VIA686_IRQ_PCIB_MASK 0x000f0000
495 1.1 bouyer #define VIA686_IRQ_PCIB_SHIFT 16
496 1.1 bouyer #define VIA686_IRQ_PCIC_MASK 0x00f00000
497 1.1 bouyer #define VIA686_IRQ_PCIC_SHIFT 20
498 1.1 bouyer #define VIA686_IRQ_PCID_MASK 0xf0000000
499 1.1 bouyer #define VIA686_IRQ_PCID_SHIFT 28
500 1.1 bouyer
501 1.1 bouyer void
502 1.1 bouyer via686sb_setup(pci_chipset_tag_t pc, int dev)
503 1.1 bouyer {
504 1.1 bouyer pcitag_t tag;
505 1.1 bouyer pcireg_t reg;
506 1.1 bouyer uint elcr;
507 1.1 bouyer
508 1.1 bouyer tag = pci_make_tag(pc, 0, dev, 0);
509 1.1 bouyer
510 1.1 bouyer /*
511 1.1 bouyer * Generic ISA bus initialization.
512 1.1 bouyer */
513 1.1 bouyer
514 1.1 bouyer reg = pci_conf_read(pc, tag, VIA686_ISA_ROM_CONTROL);
515 1.1 bouyer reg |= VIA686_IO_RECOVERY_TIME | VIA686_ISA_REFRESH;
516 1.1 bouyer pci_conf_write(pc, tag, VIA686_ISA_ROM_CONTROL, reg);
517 1.1 bouyer
518 1.1 bouyer reg = pci_conf_read(pc, tag, VIA686_KBC_DMA_MISC12);
519 1.1 bouyer reg |= VIA686_CPU_RESET_SOURCE_INIT |
520 1.1 bouyer VIA686_PCI_DELAY_TRANSACTION_ENABLE |
521 1.1 bouyer VIA686_EISA_PORT_4D0_4D1_ENABLE |
522 1.1 bouyer VIA686_PCI_WRITE_DELAY_TRANSACTION_TMO |
523 1.1 bouyer VIA686_PCI_READ_DELAY_TRANSACTION_TMO |
524 1.1 bouyer VIA686_PCI_MASTER_WRITE_WAIT_STATE | VIA686_GATE_INTR |
525 1.1 bouyer VIA686_FLUSH_LINE_BUFFER_ON_INTR;
526 1.1 bouyer reg &= ~VIA686_ISA_MASTER_TO_LINE_BUFFER;
527 1.1 bouyer pci_conf_write(pc, tag, VIA686_KBC_DMA_MISC12, reg);
528 1.1 bouyer
529 1.1 bouyer /*
530 1.1 bouyer * SuperIO devices interrupt and DMA setup.
531 1.1 bouyer */
532 1.1 bouyer
533 1.1 bouyer reg = pci_conf_read(pc, tag, VIA686_MISC3_IDE_INTR);
534 1.1 bouyer reg &= ~(VIA686_IDE_PRIMARY_CHAN_MASK | VIA686_IDE_SECONDARY_CHAN_MASK);
535 1.1 bouyer reg |= (VIA686_IDE_IRQ14 << VIA686_IDE_PRIMARY_CHAN_SHIFT);
536 1.1 bouyer reg |= (VIA686_IDE_IRQ15 << VIA686_IDE_SECONDARY_CHAN_SHIFT);
537 1.1 bouyer reg |= VIA686_IDE_PGNT;
538 1.1 bouyer pci_conf_write(pc, tag, VIA686_MISC3_IDE_INTR, reg);
539 1.1 bouyer
540 1.1 bouyer reg = pci_conf_read(pc, tag, VIA686_PNP_DMA_IRQ);
541 1.1 bouyer reg &= ~(VIA686_DMA_FDC_MASK | VIA686_DMA_LPT_MASK);
542 1.1 bouyer reg |= (2 << VIA686_DMA_FDC_SHIFT) | (3 << VIA686_DMA_LPT_SHIFT);
543 1.1 bouyer reg &= ~(VIA686_IRQ_FDC_MASK | VIA686_IRQ_LPT_MASK);
544 1.1 bouyer reg |= (6 << VIA686_IRQ_FDC_SHIFT) | (7 << VIA686_IRQ_LPT_SHIFT);
545 1.1 bouyer reg &= ~(VIA686_IRQ_COM0_MASK | VIA686_IRQ_COM1_MASK);
546 1.1 bouyer reg |= (4 << VIA686_IRQ_COM0_SHIFT) | (3 << VIA686_IRQ_COM1_SHIFT);
547 1.1 bouyer
548 1.1 bouyer reg = pci_conf_read(pc, tag, VIA686_PCI_LEVEL_PNP_IRQ2);
549 1.1 bouyer reg &= ~(VIA686_PCI_IRQA_EDGE | VIA686_PCI_IRQB_EDGE |
550 1.1 bouyer VIA686_PCI_IRQB_EDGE | VIA686_PCI_IRQD_EDGE);
551 1.1 bouyer reg &= ~(VIA686_IRQ_PCIA_MASK | VIA686_IRQ_PCIB_MASK |
552 1.1 bouyer VIA686_IRQ_PCIC_MASK | VIA686_IRQ_PCID_MASK);
553 1.1 bouyer reg |= (VIA686_IRQ_PCIA << VIA686_IRQ_PCIA_SHIFT) |
554 1.1 bouyer (VIA686_IRQ_PCIB << VIA686_IRQ_PCIB_SHIFT) |
555 1.1 bouyer (VIA686_IRQ_PCIC << VIA686_IRQ_PCIC_SHIFT) |
556 1.1 bouyer (VIA686_IRQ_PCID << VIA686_IRQ_PCID_SHIFT);
557 1.1 bouyer
558 1.1 bouyer /*
559 1.1 bouyer * Interrupt controller setup.
560 1.1 bouyer */
561 1.1 bouyer
562 1.1 bouyer /* reset; program device, four bytes */
563 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW1) =
564 1.1 bouyer ICW1_SELECT | ICW1_IC4;
565 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW2) = ICW2_VECTOR(0);
566 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW3) = ICW3_CASCADE(2);
567 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_ICW4) = ICW4_8086;
568 1.1 bouyer /* leave interrupts masked */
569 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW1) = 0xff;
570 1.1 bouyer /* special mask mode (if available) */
571 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) =
572 1.1 bouyer OCW3_SELECT | OCW3_SSMM | OCW3_SMM;
573 1.1 bouyer /* read IRR by default. */
574 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU1 + PIC_OCW3) = OCW3_SELECT | OCW3_RR;
575 1.1 bouyer
576 1.1 bouyer /* reset; program device, four bytes */
577 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW1) =
578 1.1 bouyer ICW1_SELECT | ICW1_IC4;
579 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW2) = ICW2_VECTOR(8);
580 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW3) = ICW3_SIC(2);
581 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_ICW4) = ICW4_8086;
582 1.1 bouyer /* leave interrupts masked */
583 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW1) = 0xff;
584 1.1 bouyer /* special mask mode (if available) */
585 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) =
586 1.1 bouyer OCW3_SELECT | OCW3_SSMM | OCW3_SMM;
587 1.1 bouyer /* read IRR by default. */
588 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + IO_ICU2 + PIC_OCW3) = OCW3_SELECT | OCW3_RR;
589 1.1 bouyer
590 1.1 bouyer /* setup ELCR: PCI interrupts are level-triggered. */
591 1.1 bouyer elcr = (1 << VIA686_IRQ_PCIA) | (1 << VIA686_IRQ_PCIB) |
592 1.1 bouyer (1 << VIA686_IRQ_PCIC) | (1 << VIA686_IRQ_PCID);
593 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + 0x4d0) = (elcr >> 0) & 0xff;
594 1.1 bouyer REGVAL8(BONITO_PCIIO_BASE + 0x4d1) = (elcr >> 8) & 0xff;
595 1.1 bouyer
596 1.1 bouyer __asm__ __volatile__ ("sync" ::: "memory");
597 1.1 bouyer
598 1.1 bouyer /*
599 1.1 bouyer * Update interrupt information for secondary functions.
600 1.1 bouyer * Although this information is not used by pci_intr_establish()
601 1.1 bouyer * because of generic2e_intr_map() behaviour, it seems to be
602 1.1 bouyer * required to complete proper interrupt routing.
603 1.1 bouyer */
604 1.1 bouyer
605 1.1 bouyer tag = pci_make_tag(pc, 0, dev, 2);
606 1.1 bouyer reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
607 1.1 bouyer reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
608 1.1 bouyer reg |= VIA686_IRQ_PCIB << PCI_INTERRUPT_LINE_SHIFT;
609 1.1 bouyer pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg);
610 1.1 bouyer
611 1.1 bouyer tag = pci_make_tag(pc, 0, dev, 3);
612 1.1 bouyer reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
613 1.1 bouyer reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
614 1.1 bouyer reg |= VIA686_IRQ_PCIC << PCI_INTERRUPT_LINE_SHIFT;
615 1.1 bouyer pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg);
616 1.1 bouyer
617 1.1 bouyer tag = pci_make_tag(pc, 0, dev, 5);
618 1.1 bouyer reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
619 1.1 bouyer reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
620 1.1 bouyer reg |= VIA686_IRQ_PCIA << PCI_INTERRUPT_LINE_SHIFT;
621 1.1 bouyer pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg);
622 1.1 bouyer }
623