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