glx.c revision 1.1.6.3 1 /* $NetBSD: glx.c,v 1.1.6.3 2012/03/06 09:56:06 mrg Exp $ */
2 /* $OpenBSD: glx.c,v 1.6 2010/10/14 21:23:04 pirofti Exp $ */
3
4 /*
5 * Copyright (c) 2009 Miodrag Vallat.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*
21 * AMD CS5536 PCI Mess
22 * XXX too many hardcoded numbers... need to expand glxreg.h
23 */
24 #include <sys/cdefs.h>
25 __KERNEL_RCSID(0, "$NetBSD: glx.c,v 1.1.6.3 2012/03/06 09:56:06 mrg Exp $");
26
27
28 #include <sys/param.h>
29 #include <sys/systm.h>
30 #include <sys/device.h>
31
32 #include <evbmips/loongson/autoconf.h>
33
34 #include <dev/pci/pcireg.h>
35 #include <dev/pci/pcivar.h>
36 #include <dev/pci/pcidevs.h>
37
38 #include <dev/pci/pciidereg.h>
39 #include <dev/usb/usb.h>
40 #include <dev/usb/ohcireg.h>
41 #include <dev/usb/ehcireg.h>
42
43 #include <mips/bonito/bonitoreg.h>
44 #include <mips/bonito/bonitovar.h>
45
46 #include <evbmips/loongson/dev/glxreg.h>
47 #include <evbmips/loongson/dev/glxvar.h>
48
49 #ifdef GLX_DEBUG
50 #define DPRINTF(x) printf x
51 #else
52 #define DPRINTF(x)
53 #endif
54
55 /*
56 * Since the purpose of this code is to present a different view of the
57 * PCI configuration space, it can not attach as a real device.
58 * (well it could, and then we'd have to attach a fake pci to it,
59 * and fake the configuration space accesses anyways - is it worth doing?)
60 *
61 * We just keep the `would-be softc' structure as global variables.
62 */
63
64 static pci_chipset_tag_t glxbase_pc;
65 static pcitag_t glxbase_tag;
66 static int glxbase_dev;
67
68 /* MSR access through PCI configuration space */
69 #define PCI_MSR_CTRL 0x00f0
70 #define PCI_MSR_ADDR 0x00f4
71 #define PCI_MSR_LO32 0x00f8
72 #define PCI_MSR_HI32 0x00fc
73
74 /* access to the MSR through the PCI mailbox needs the same transformation
75 * as done by hardware when a MSR request reaches the CS5536.
76 */
77 #define GLX_MSR_ADDR_TARGET 0x00003fff
78 #define GLX_MSR_ADDR_RF 0xffffc000
79 #define GLX_MSR_ADDR_RF_SHIFT 9
80
81 static uint glx_msra2mbxa(uint);
82 static uint
83 glx_msra2mbxa(uint msr)
84 {
85 uint rf = (msr & GLX_MSR_ADDR_RF);
86 return ((rf << GLX_MSR_ADDR_RF_SHIFT) | (msr & GLX_MSR_ADDR_TARGET));
87 }
88
89 pcireg_t glx_pci_read_hook(void *, pcitag_t, int);
90 void glx_pci_write_hook(void *, pcitag_t, int, pcireg_t);
91
92 pcireg_t glx_get_status(void);
93 pcireg_t glx_fn0_read(int);
94 void glx_fn0_write(int, pcireg_t);
95 pcireg_t glx_fn2_read(int);
96 void glx_fn2_write(int, pcireg_t);
97 pcireg_t glx_fn3_read(int);
98 void glx_fn3_write(int, pcireg_t);
99 pcireg_t glx_fn4_read(int);
100 void glx_fn4_write(int, pcireg_t);
101 pcireg_t glx_fn5_read(int);
102 void glx_fn5_write(int, pcireg_t);
103 pcireg_t glx_fn6_read(int);
104 void glx_fn6_write(int, pcireg_t);
105 pcireg_t glx_fn7_read(int);
106 void glx_fn7_write(int, pcireg_t);
107
108 pcireg_t (*gen_pci_conf_read)(void *, pcitag_t, int);
109 void (*gen_pci_conf_write)(void *, pcitag_t, int, pcireg_t);
110
111 void
112 glx_init(pci_chipset_tag_t pc, pcitag_t tag, int dev)
113 {
114 uint64_t msr;
115
116 glxbase_pc = pc;
117 glxbase_dev = dev;
118 glxbase_tag = tag;
119
120 /*
121 * Register PCI configuration hooks to make the various
122 * embedded devices visible as PCI subfunctions.
123 */
124
125 gen_pci_conf_read = pc->pc_conf_read;
126 pc->pc_conf_read = glx_pci_read_hook;
127 gen_pci_conf_write = pc->pc_conf_write;
128 pc->pc_conf_write = glx_pci_write_hook;
129
130 /*
131 * Perform some Geode intialization.
132 */
133
134 msr = rdmsr(GCSC_DIVIL_BALL_OPTS); /* 0x71 */
135 wrmsr(GCSC_DIVIL_BALL_OPTS, msr | 0x01);
136
137 /*
138 * Route usb and audio
139 */
140
141 msr = 0;
142 msr |= 11 << 8;
143 msr |= 9 << 16;
144 wrmsr(GCSC_PIC_YSEL_LOW, msr);
145
146 /*
147 * serial interrupts
148 */
149 msr = 0;
150 msr |= 4 << 24;
151 msr |= 3 << 28;
152 wrmsr(GCSC_PIC_YSEL_HIGH, msr);
153
154 /*
155 * and IDE
156 */
157 msr = 0;
158 msr |= 1 << 14;
159 wrmsr(GCSC_PIC_IRQM_PRIM, msr);
160
161 /* no interrupts from theses */
162 wrmsr(GCSC_PIC_ZSEL_LOW, 0);
163 wrmsr(GCSC_PIC_ZSEL_HIGH, 0);
164 wrmsr(GCSC_PIC_IRQM_LPC, 0);
165
166 DPRINTF(("IO space 0x%" PRIx64 "\n", rdmsr(0x80000014)));
167 }
168
169 uint64_t
170 rdmsr(uint msr)
171 {
172 uint64_t lo, hi;
173 int s;
174
175 #ifdef DIAGNOSTIC
176 if (glxbase_tag == 0)
177 panic("rdmsr invoked before glx initialization");
178 #endif
179
180 s = splhigh();
181 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_ADDR,
182 glx_msra2mbxa(msr));
183 lo = (uint32_t)pci_conf_read(glxbase_pc, glxbase_tag, PCI_MSR_LO32);
184 hi = (uint32_t)pci_conf_read(glxbase_pc, glxbase_tag, PCI_MSR_HI32);
185 splx(s);
186 return (hi << 32) | lo;
187 }
188
189 void
190 wrmsr(uint msr, uint64_t value)
191 {
192 int s;
193
194 #ifdef DIAGNOSTIC
195 if (glxbase_tag == 0)
196 panic("wrmsr invoked before glx initialization");
197 #endif
198
199 s = splhigh();
200 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_ADDR,
201 glx_msra2mbxa(msr));
202 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_LO32, (uint32_t)value);
203 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_HI32, value >> 32);
204 splx(s);
205 }
206
207 pcireg_t
208 glx_pci_read_hook(void *v, pcitag_t tag, int offset)
209 {
210 int bus, dev, fn;
211 pcireg_t data;
212
213 /*
214 * Do not get in the way of MSR programming
215 */
216 if (tag == glxbase_tag && offset >= PCI_MSR_CTRL)
217 return gen_pci_conf_read(v, tag, offset);
218
219 pci_decompose_tag(glxbase_pc, tag, &bus, &dev, &fn);
220 if (bus != 0 || dev != glxbase_dev)
221 return gen_pci_conf_read(v, tag, offset);
222
223 data = 0;
224
225 switch (fn) {
226 case 0: /* PCI-ISA bridge */
227 data = glx_fn0_read(offset);
228 break;
229 case 1: /* Flash memory */
230 break;
231 case 2: /* IDE controller */
232 data = glx_fn2_read(offset);
233 break;
234 case 3: /* AC97 codec */
235 data = glx_fn3_read(offset);
236 break;
237 case 4: /* OHCI controller */
238 data = glx_fn4_read(offset);
239 break;
240 case 5: /* EHCI controller */
241 data = glx_fn5_read(offset);
242 break;
243 case 6: /* UDC */
244 break;
245 case 7: /* OTG */
246 break;
247 }
248
249 return data;
250 }
251
252 void
253 glx_pci_write_hook(void *v, pcitag_t tag,
254 int offset, pcireg_t data)
255 {
256 int bus, dev, fn;
257
258 /*
259 * Do not get in the way of MSR programming
260 */
261 if (tag == glxbase_tag && offset >= PCI_MSR_CTRL) {
262 gen_pci_conf_write(v, tag, offset, data);
263 return;
264 }
265
266
267 pci_decompose_tag(glxbase_pc, tag, &bus, &dev, &fn);
268 if (bus != 0 || dev != glxbase_dev) {
269 gen_pci_conf_write(v, tag, offset, data);
270 return;
271 }
272
273 switch (fn) {
274 case 0: /* PCI-ISA bridge */
275 glx_fn0_write(offset, data);
276 break;
277 case 1: /* Flash memory */
278 break;
279 case 2: /* IDE controller */
280 glx_fn2_write(offset, data);
281 break;
282 case 3: /* AC97 codec */
283 glx_fn3_write(offset, data);
284 break;
285 case 4: /* OHCI controller */
286 glx_fn4_write(offset, data);
287 break;
288 case 5: /* EHCI controller */
289 glx_fn5_write(offset, data);
290 break;
291 case 6: /* USB UDC */
292 break;
293 case 7: /* USB OTG */
294 break;
295 }
296 }
297
298 pcireg_t
299 glx_get_status(void)
300 {
301 uint64_t msr;
302 pcireg_t data;
303
304 data = 0;
305 msr = rdmsr(GCSC_GLPCI_GLD_MSR_ERROR);
306 if (msr & (1UL << 5))
307 data |= PCI_COMMAND_PARITY_ENABLE;
308 data |= PCI_STATUS_66MHZ_SUPPORT |
309 PCI_STATUS_BACKTOBACK_SUPPORT | PCI_STATUS_DEVSEL_MEDIUM;
310 if (msr & (1UL << 21))
311 data |= PCI_STATUS_PARITY_DETECT;
312 if (msr & (1UL << 20))
313 data |= PCI_STATUS_TARGET_TARGET_ABORT;
314 if (msr & (1UL << 17))
315 data |= PCI_STATUS_MASTER_TARGET_ABORT;
316 if (msr & (1UL << 16))
317 data |= PCI_STATUS_MASTER_ABORT;
318
319 return data;
320 }
321
322 /*
323 * Function 0: PCI-ISA bridge
324 */
325
326 static const pcireg_t pcib_bar_sizes[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4] = {
327 0x008,
328 0x100,
329 0x040,
330 0x020,
331 0x080,
332 0x020
333 };
334
335 static pcireg_t pcib_bar_values[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4];
336
337 static const uint64_t pcib_bar_msr[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4] = {
338 GCSC_DIVIL_LBAR_SMB,
339 GCSC_DIVIL_LBAR_GPIO,
340 GCSC_DIVIL_LBAR_MFGPT,
341 GCSC_DIVIL_LBAR_IRQ,
342 GCSC_DIVIL_LBAR_PMS,
343 GCSC_DIVIL_LBAR_ACPI
344 };
345
346 pcireg_t
347 glx_fn0_read(int reg)
348 {
349 uint64_t msr;
350 pcireg_t data;
351 int index;
352
353 switch (reg) {
354 case PCI_ID_REG:
355 case PCI_SUBSYS_ID_REG:
356 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_PCIB);
357 break;
358 case PCI_COMMAND_STATUS_REG:
359 data = glx_get_status();
360 data |= PCI_COMMAND_MASTER_ENABLE;
361 msr = rdmsr(GCSC_DIVIL_LBAR_SMB);
362 if (msr & (1ULL << 32))
363 data |= PCI_COMMAND_IO_ENABLE;
364 break;
365 case PCI_CLASS_REG:
366 msr = rdmsr(GCSC_GLCP_CHIP_REV_ID);
367 data = (PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT) |
368 (PCI_SUBCLASS_BRIDGE_ISA << PCI_SUBCLASS_SHIFT) |
369 (msr & PCI_REVISION_MASK);
370 break;
371 case PCI_BHLC_REG:
372 msr = rdmsr(GCSC_GLPCI_CTRL);
373 data = (0x80 << PCI_HDRTYPE_SHIFT) |
374 (((msr & 0xff00000000UL) >> 32) << PCI_LATTIMER_SHIFT) |
375 (0x08 << PCI_CACHELINE_SHIFT);
376 break;
377 case PCI_MAPREG_START + 0x00:
378 case PCI_MAPREG_START + 0x04:
379 case PCI_MAPREG_START + 0x08:
380 case PCI_MAPREG_START + 0x0c:
381 case PCI_MAPREG_START + 0x10:
382 case PCI_MAPREG_START + 0x14:
383 case PCI_MAPREG_START + 0x18:
384 index = (reg - PCI_MAPREG_START) / 4;
385 if (pcib_bar_msr[index] == 0)
386 data = 0;
387 else {
388 data = pcib_bar_values[index];
389 if (data == 0xffffffff)
390 data = PCI_MAPREG_IO_ADDR_MASK;
391 else
392 data = (pcireg_t)rdmsr(pcib_bar_msr[index]);
393 data &= ~(pcib_bar_sizes[index] - 1);
394 if (data != 0)
395 data |= PCI_MAPREG_TYPE_IO;
396 }
397 break;
398 case PCI_INTERRUPT_REG:
399 data = (0x40 << PCI_MAX_LAT_SHIFT) |
400 (PCI_INTERRUPT_PIN_NONE << PCI_INTERRUPT_PIN_SHIFT);
401 break;
402 default:
403 data = 0;
404 break;
405 }
406
407 return data;
408 }
409
410 void
411 glx_fn0_write(int reg, pcireg_t data)
412 {
413 uint64_t msr;
414 int index;
415
416 switch (reg) {
417 case PCI_COMMAND_STATUS_REG:
418 for (index = 0; index < __arraycount(pcib_bar_msr); index++) {
419 if (pcib_bar_msr[index] == 0)
420 continue;
421 msr = rdmsr(pcib_bar_msr[index]);
422 if (data & PCI_COMMAND_IO_ENABLE)
423 msr |= 1ULL << 32;
424 else
425 msr &= ~(1ULL << 32);
426 wrmsr(pcib_bar_msr[index], msr);
427 }
428
429 msr = rdmsr(GCSC_GLPCI_GLD_MSR_ERROR);
430 if (data & PCI_COMMAND_PARITY_ENABLE)
431 msr |= 1ULL << 5;
432 else
433 msr &= ~(1ULL << 5);
434 wrmsr(GCSC_GLPCI_GLD_MSR_ERROR, msr);
435 break;
436 case PCI_BHLC_REG:
437 msr = rdmsr(GCSC_GLPCI_CTRL);
438 msr &= 0xff00000000ULL;
439 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
440 break;
441 case PCI_MAPREG_START + 0x00:
442 case PCI_MAPREG_START + 0x04:
443 case PCI_MAPREG_START + 0x08:
444 case PCI_MAPREG_START + 0x0c:
445 case PCI_MAPREG_START + 0x10:
446 case PCI_MAPREG_START + 0x14:
447 case PCI_MAPREG_START + 0x18:
448 index = (reg - PCI_MAPREG_START) / 4;
449 if (data == 0xffffffff) {
450 pcib_bar_values[index] = data;
451 } else if (pcib_bar_msr[index] != 0) {
452 if ((data & PCI_MAPREG_TYPE_MASK) ==
453 PCI_MAPREG_TYPE_IO) {
454 data &= PCI_MAPREG_IO_ADDR_MASK;
455 data &= ~(pcib_bar_sizes[index] - 1);
456 wrmsr(pcib_bar_msr[index],
457 (0x0000f000ULL << 32) | (1ULL << 32) | data);
458 } else {
459 wrmsr(pcib_bar_msr[index], 0ULL);
460 }
461 pcib_bar_values[index] = 0;
462 }
463 break;
464 }
465 }
466
467 /*
468 * Function 2: IDE Controller
469 */
470
471 static pcireg_t pciide_bar_size = 0x10;
472 static pcireg_t pciide_bar_value;
473
474 pcireg_t
475 glx_fn2_read(int reg)
476 {
477 uint64_t msr;
478 pcireg_t data;
479
480 switch (reg) {
481 case PCI_ID_REG:
482 case PCI_SUBSYS_ID_REG:
483 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_IDE);
484 break;
485 case PCI_COMMAND_STATUS_REG:
486 data = glx_get_status();
487 data |= PCI_COMMAND_IO_ENABLE;
488 msr = rdmsr(GCSC_GLIU_PAE);
489 if ((msr & (0x3 << 4)) == 0x03)
490 data |= PCI_COMMAND_MASTER_ENABLE;
491 break;
492 case PCI_CLASS_REG:
493 msr = rdmsr(GCSC_IDE_GLD_MSR_CAP);
494 data = (PCI_CLASS_MASS_STORAGE << PCI_CLASS_SHIFT) |
495 (PCI_SUBCLASS_MASS_STORAGE_IDE << PCI_SUBCLASS_SHIFT) |
496 (PCIIDE_INTERFACE_BUS_MASTER_DMA << PCI_INTERFACE_SHIFT) |
497 (msr & PCI_REVISION_MASK);
498 break;
499 case PCI_BHLC_REG:
500 msr = rdmsr(GCSC_GLPCI_CTRL);
501 data = (0x00 << PCI_HDRTYPE_SHIFT) |
502 (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
503 (0x08 << PCI_CACHELINE_SHIFT);
504 break;
505 case PCI_MAPREG_START + 0x10:
506 data = pciide_bar_value;
507 if (data == 0xffffffff)
508 data = PCI_MAPREG_IO_ADDR_MASK & ~(pciide_bar_size - 1);
509 else {
510 msr = rdmsr(GCSC_IDE_IO_BAR);
511 data = msr & 0xfffffff0;
512 }
513 if (data != 0)
514 data |= PCI_MAPREG_TYPE_IO;
515 break;
516 case PCI_INTERRUPT_REG:
517 /* compat mode */
518 data = (0x40 << PCI_MAX_LAT_SHIFT) |
519 (PCI_INTERRUPT_PIN_NONE << PCI_INTERRUPT_PIN_SHIFT);
520 break;
521 /*
522 * The following registers are used by pciide(4)
523 */
524 case PCIIDE_CHANSTATUS_EN:
525 data = rdmsr(GCSC_IDE_CFG);
526 break;
527 case /* AMD756_DATATIM XXX */ 0x48:
528 data = rdmsr(GCSC_IDE_DTC);
529 break;
530 case /* AMD756_UDMA XXX*/ 0x50:
531 data = rdmsr(GCSC_IDE_ETC);
532 break;
533 default:
534 DPRINTF(("unimplemented pciide reg 0x%x\n", reg));
535 data = 0;
536 break;
537 }
538
539 return data;
540 }
541
542 void
543 glx_fn2_write(int reg, pcireg_t data)
544 {
545 uint64_t msr;
546
547 switch (reg) {
548 case PCI_COMMAND_STATUS_REG:
549 msr = rdmsr(GCSC_GLIU_PAE);
550 if (data & PCI_COMMAND_MASTER_ENABLE)
551 msr |= 0x03 << 4;
552 else
553 msr &= ~(0x03 << 4);
554 wrmsr(GCSC_GLIU_PAE, msr);
555 break;
556 case PCI_BHLC_REG:
557 msr = rdmsr(GCSC_GLPCI_CTRL);
558 msr &= 0xff00000000ULL;
559 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
560 break;
561 case PCI_MAPREG_START + 0x10:
562 if (data == 0xffffffff) {
563 pciide_bar_value = data;
564 } else {
565 if ((data & PCI_MAPREG_TYPE_MASK) ==
566 PCI_MAPREG_TYPE_IO) {
567 data &= PCI_MAPREG_IO_ADDR_MASK;
568 msr = (uint32_t)data & 0xfffffff0;
569 wrmsr(GCSC_IDE_IO_BAR, msr);
570 } else {
571 wrmsr(GCSC_IDE_IO_BAR, 0);
572 }
573 pciide_bar_value = 0;
574 }
575 break;
576 /*
577 * The following registers are used by pciide(4)
578 */
579 case PCIIDE_CHANSTATUS_EN:
580 wrmsr(GCSC_IDE_CFG, (uint32_t)data);
581 break;
582 case /* AMD756_DATATIM XXX */ 0x48:
583 wrmsr(GCSC_IDE_DTC, (uint32_t)data);
584 break;
585 case /* AMD756_UDMA XXX*/ 0x50:
586 wrmsr(GCSC_IDE_ETC, (uint32_t)data);
587 break;
588 default:
589 DPRINTF(("unimplemented pciide reg 0x%x\n", reg));
590 }
591 }
592
593 /*
594 * Function 3: AC97 Codec
595 */
596
597 static pcireg_t ac97_bar_size = 0x80;
598 static pcireg_t ac97_bar_value;
599
600 pcireg_t
601 glx_fn3_read(int reg)
602 {
603 uint64_t msr;
604 pcireg_t data;
605
606 switch (reg) {
607 case PCI_ID_REG:
608 case PCI_SUBSYS_ID_REG:
609 data = PCI_ID_CODE(PCI_VENDOR_AMD,
610 PCI_PRODUCT_AMD_CS5536_AUDIO);
611 break;
612 case PCI_COMMAND_STATUS_REG:
613 data = glx_get_status();
614 data |= PCI_COMMAND_IO_ENABLE;
615 msr = rdmsr(GCSC_GLIU_PAE);
616 if ((msr & (0x3 << 8)) == 0x03)
617 data |= PCI_COMMAND_MASTER_ENABLE;
618 break;
619 case PCI_CLASS_REG:
620 msr = rdmsr(GCSC_ACC_GLD_MSR_CAP);
621 data = (PCI_CLASS_MULTIMEDIA << PCI_CLASS_SHIFT) |
622 (PCI_SUBCLASS_MULTIMEDIA_AUDIO << PCI_SUBCLASS_SHIFT) |
623 (msr & PCI_REVISION_MASK);
624 break;
625 case PCI_BHLC_REG:
626 msr = rdmsr(GCSC_GLPCI_CTRL);
627 data = (0x00 << PCI_HDRTYPE_SHIFT) |
628 (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
629 (0x08 << PCI_CACHELINE_SHIFT);
630 break;
631 case PCI_MAPREG_START:
632 data = ac97_bar_value;
633 if (data == 0xffffffff)
634 data = PCI_MAPREG_IO_ADDR_MASK & ~(ac97_bar_size - 1);
635 else {
636 msr = rdmsr(GCSC_GLIU_IOD_BM1);
637 data = (msr >> 20) & 0x000fffff;
638 data &= (msr & 0x000fffff);
639 }
640 if (data != 0)
641 data |= PCI_MAPREG_TYPE_IO;
642 break;
643 case PCI_INTERRUPT_REG:
644 data = (0x40 << PCI_MAX_LAT_SHIFT) |
645 (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
646 break;
647 default:
648 data = 0;
649 break;
650 }
651
652 return data;
653 }
654
655 void
656 glx_fn3_write(int reg, pcireg_t data)
657 {
658 uint64_t msr;
659
660 switch (reg) {
661 case PCI_COMMAND_STATUS_REG:
662 msr = rdmsr(GCSC_GLIU_PAE);
663 if (data & PCI_COMMAND_MASTER_ENABLE)
664 msr |= 0x03 << 8;
665 else
666 msr &= ~(0x03 << 8);
667 wrmsr(GCSC_GLIU_PAE, msr);
668 break;
669 case PCI_BHLC_REG:
670 msr = rdmsr(GCSC_GLPCI_CTRL);
671 msr &= 0xff00000000ULL;
672 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
673 break;
674 case PCI_MAPREG_START:
675 if (data == 0xffffffff) {
676 ac97_bar_value = data;
677 } else {
678 if ((data & PCI_MAPREG_TYPE_MASK) ==
679 PCI_MAPREG_TYPE_IO) {
680 data &= PCI_MAPREG_IO_ADDR_MASK;
681 msr = rdmsr(GCSC_GLIU_IOD_BM1);
682 msr &= 0x0fffff0000000000ULL;
683 msr |= 5ULL << 61; /* AC97 */
684 msr |= ((uint64_t)data & 0xfffff) << 20;
685 msr |= 0x000fffff & ~(ac97_bar_size - 1);
686 wrmsr(GCSC_GLIU_IOD_BM1, msr);
687 } else {
688 wrmsr(GCSC_GLIU_IOD_BM1, 0);
689 }
690 ac97_bar_value = 0;
691 }
692 break;
693 }
694 }
695
696 /*
697 * Function 4: OHCI Controller
698 */
699
700 static pcireg_t ohci_bar_size = 0x1000;
701 static pcireg_t ohci_bar_value;
702
703 pcireg_t
704 glx_fn4_read(int reg)
705 {
706 uint64_t msr;
707 pcireg_t data;
708
709 switch (reg) {
710 case PCI_ID_REG:
711 case PCI_SUBSYS_ID_REG:
712 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_OHCI);
713 break;
714 case PCI_COMMAND_STATUS_REG:
715 data = glx_get_status();
716 msr = rdmsr(GCSC_USB_MSR_OHCB);
717 if (msr & (1ULL << 34))
718 data |= PCI_COMMAND_MASTER_ENABLE;
719 if (msr & (1ULL << 33))
720 data |= PCI_COMMAND_MEM_ENABLE;
721 break;
722 case PCI_CLASS_REG:
723 msr = rdmsr(GCSC_USB_GLD_MSR_CAP);
724 data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
725 (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
726 (PCI_INTERFACE_OHCI << PCI_INTERFACE_SHIFT) |
727 (msr & PCI_REVISION_MASK);
728 break;
729 case PCI_BHLC_REG:
730 msr = rdmsr(GCSC_GLPCI_CTRL);
731 data = (0x00 << PCI_HDRTYPE_SHIFT) |
732 (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
733 (0x08 << PCI_CACHELINE_SHIFT);
734 break;
735 case PCI_MAPREG_START + 0x00:
736 data = ohci_bar_value;
737 if (data == 0xffffffff)
738 data = PCI_MAPREG_MEM_ADDR_MASK & ~(ohci_bar_size - 1);
739 else {
740 msr = rdmsr(GCSC_USB_MSR_OHCB);
741 data = msr & 0xffffff00;
742 }
743 if (data != 0)
744 data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
745 break;
746 case PCI_CAPLISTPTR_REG:
747 data = 0x40;
748 break;
749 case PCI_INTERRUPT_REG:
750 data = (0x40 << PCI_MAX_LAT_SHIFT) |
751 (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
752 break;
753 case 0x40: /* USB capability pointer */
754 data = 0;
755 break;
756 default:
757 data = 0;
758 break;
759 }
760
761 return data;
762 }
763
764 void
765 glx_fn4_write(int reg, pcireg_t data)
766 {
767 uint64_t msr;
768
769 switch (reg) {
770 case PCI_COMMAND_STATUS_REG:
771 msr = rdmsr(GCSC_USB_MSR_OHCB);
772 if (data & PCI_COMMAND_MASTER_ENABLE)
773 msr |= 1ULL << 34;
774 else
775 msr &= ~(1ULL << 34);
776 if (data & PCI_COMMAND_MEM_ENABLE)
777 msr |= 1ULL << 33;
778 else
779 msr &= ~(1ULL << 33);
780 wrmsr(GCSC_USB_MSR_OHCB, msr);
781 break;
782 case PCI_BHLC_REG:
783 msr = rdmsr(GCSC_GLPCI_CTRL);
784 msr &= 0xff00000000ULL;
785 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
786 break;
787 case PCI_MAPREG_START + 0x00:
788 if (data == 0xffffffff) {
789 ohci_bar_value = data;
790 } else {
791 if ((data & PCI_MAPREG_TYPE_MASK) ==
792 PCI_MAPREG_TYPE_MEM) {
793 data &= PCI_MAPREG_MEM_ADDR_MASK;
794 msr = rdmsr(GCSC_GLIU_P2D_BM3);
795 msr &= 0x0fffff0000000000ULL;
796 msr |= 2ULL << 61; /* USB */
797 msr |= (((uint64_t)data) >> 12) << 20;
798 msr |= 0x000fffff;
799 wrmsr(GCSC_GLIU_P2D_BM3, msr);
800
801 msr = rdmsr(GCSC_USB_MSR_OHCB);
802 msr &= ~0xffffff00ULL;
803 msr |= data;
804 } else {
805 msr = rdmsr(GCSC_USB_MSR_OHCB);
806 msr &= ~0xffffff00ULL;
807 }
808 wrmsr(GCSC_USB_MSR_OHCB, msr);
809 ohci_bar_value = 0;
810 }
811 break;
812 default:
813 break;
814 }
815 }
816
817 /*
818 * Function 5: EHCI Controller
819 */
820
821 static pcireg_t ehci_bar_size = 0x1000;
822 static pcireg_t ehci_bar_value;
823
824 pcireg_t
825 glx_fn5_read(int reg)
826 {
827 uint64_t msr;
828 pcireg_t data;
829
830 switch (reg) {
831 case PCI_ID_REG:
832 case PCI_SUBSYS_ID_REG:
833 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_EHCI);
834 break;
835 case PCI_COMMAND_STATUS_REG:
836 data = glx_get_status();
837 msr = rdmsr(GCSC_USB_MSR_EHCB);
838 if (msr & (1ULL << 34))
839 data |= PCI_COMMAND_MASTER_ENABLE;
840 if (msr & (1ULL << 33))
841 data |= PCI_COMMAND_MEM_ENABLE;
842 break;
843 case PCI_CLASS_REG:
844 msr = rdmsr(GCSC_USB_GLD_MSR_CAP);
845 data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
846 (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
847 (PCI_INTERFACE_EHCI << PCI_INTERFACE_SHIFT) |
848 (msr & PCI_REVISION_MASK);
849 break;
850 case PCI_BHLC_REG:
851 msr = rdmsr(GCSC_GLPCI_CTRL);
852 data = (0x00 << PCI_HDRTYPE_SHIFT) |
853 (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
854 (0x08 << PCI_CACHELINE_SHIFT);
855 break;
856 case PCI_MAPREG_START + 0x00:
857 data = ehci_bar_value;
858 if (data == 0xffffffff)
859 data = PCI_MAPREG_MEM_ADDR_MASK & ~(ehci_bar_size - 1);
860 else {
861 msr = rdmsr(GCSC_USB_MSR_EHCB);
862 data = msr & 0xffffff00;
863 }
864 if (data != 0)
865 data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
866 break;
867 case PCI_CAPLISTPTR_REG:
868 data = 0x40;
869 break;
870 case PCI_INTERRUPT_REG:
871 data = (0x40 << PCI_MAX_LAT_SHIFT) |
872 (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
873 break;
874 case 0x40: /* USB capability pointer */
875 data = 0;
876 break;
877 case PCI_USBREV:
878 msr = rdmsr(GCSC_USB_MSR_EHCB);
879 data = PCI_USBREV_2_0;
880 data |= ((msr >> 40) & 0x3f) << 8; /* PCI_EHCI_FLADJ */
881 break;
882 default:
883 data = 0;
884 break;
885 }
886
887 return data;
888 }
889
890 void
891 glx_fn5_write(int reg, pcireg_t data)
892 {
893 uint64_t msr;
894
895 switch (reg) {
896 case PCI_COMMAND_STATUS_REG:
897 msr = rdmsr(GCSC_USB_MSR_EHCB);
898 if (data & PCI_COMMAND_MASTER_ENABLE)
899 msr |= 1ULL << 34;
900 else
901 msr &= ~(1ULL << 34);
902 if (data & PCI_COMMAND_MEM_ENABLE)
903 msr |= 1ULL << 33;
904 else
905 msr &= ~(1ULL << 33);
906 wrmsr(GCSC_USB_MSR_EHCB, msr);
907 break;
908 case PCI_BHLC_REG:
909 msr = rdmsr(GCSC_GLPCI_CTRL);
910 msr &= 0xff00000000ULL;
911 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
912 break;
913 case PCI_MAPREG_START + 0x00:
914 if (data == 0xffffffff) {
915 ehci_bar_value = data;
916 } else {
917 if ((data & PCI_MAPREG_TYPE_MASK) ==
918 PCI_MAPREG_TYPE_MEM) {
919 data &= PCI_MAPREG_MEM_ADDR_MASK;
920 msr = rdmsr(GCSC_GLIU_P2D_BM4);
921 msr &= 0x0fffff0000000000ULL;
922 msr |= 2ULL << 61; /* USB */
923 msr |= (((uint64_t)data) >> 12) << 20;
924 msr |= 0x000fffff;
925 wrmsr(GCSC_GLIU_P2D_BM4, msr);
926
927 msr = rdmsr(GCSC_USB_MSR_EHCB);
928 msr &= ~0xffffff00ULL;
929 msr |= data;
930 } else {
931 msr = rdmsr(GCSC_USB_MSR_EHCB);
932 msr &= ~0xffffff00ULL;
933 }
934 wrmsr(GCSC_USB_MSR_EHCB, msr);
935 ehci_bar_value = 0;
936 }
937 break;
938 default:
939 break;
940 }
941 }
942