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