glx.c revision 1.1.6.1 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.1.6.1 2012/02/18 07:31:56 mrg 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
140 msr = 0;
141 msr |= 11 << 8;
142 msr |= 9 << 16;
143 wrmsr(GCSC_PIC_YSEL_LOW, msr);
144
145 /*
146 * serial interrupts
147 */
148 msr = 0;
149 msr |= 4 << 24;
150 msr |= 3 << 28;
151 wrmsr(GCSC_PIC_YSEL_HIGH, msr);
152
153 /*
154 * and IDE
155 */
156 msr = 0;
157 msr |= 1 << 14;
158 wrmsr(GCSC_PIC_IRQM_PRIM, msr);
159
160 /* no interrupts from theses */
161 wrmsr(GCSC_PIC_ZSEL_LOW, 0);
162 wrmsr(GCSC_PIC_ZSEL_HIGH, 0);
163 wrmsr(GCSC_PIC_IRQM_LPC, 0);
164
165 DPRINTF(("IO space 0x%" PRIx64 "\n", rdmsr(0x80000014)));
166 }
167
168 uint64_t
169 rdmsr(uint msr)
170 {
171 uint64_t lo, hi;
172 int s;
173
174 #ifdef DIAGNOSTIC
175 if (glxbase_tag == 0)
176 panic("rdmsr invoked before glx initialization");
177 #endif
178
179 s = splhigh();
180 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_ADDR,
181 glx_msra2mbxa(msr));
182 lo = (uint32_t)pci_conf_read(glxbase_pc, glxbase_tag, PCI_MSR_LO32);
183 hi = (uint32_t)pci_conf_read(glxbase_pc, glxbase_tag, PCI_MSR_HI32);
184 splx(s);
185 return (hi << 32) | lo;
186 }
187
188 void
189 wrmsr(uint msr, uint64_t value)
190 {
191 int s;
192
193 #ifdef DIAGNOSTIC
194 if (glxbase_tag == 0)
195 panic("wrmsr invoked before glx initialization");
196 #endif
197
198 s = splhigh();
199 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_ADDR,
200 glx_msra2mbxa(msr));
201 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_LO32, (uint32_t)value);
202 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_HI32, value >> 32);
203 splx(s);
204 }
205
206 pcireg_t
207 glx_pci_read_hook(void *v, pcitag_t tag, int offset)
208 {
209 int bus, dev, fn;
210 pcireg_t data;
211
212 /*
213 * Do not get in the way of MSR programming
214 */
215 if (tag == glxbase_tag && offset >= PCI_MSR_CTRL)
216 return gen_pci_conf_read(v, tag, offset);
217
218 pci_decompose_tag(glxbase_pc, tag, &bus, &dev, &fn);
219 if (bus != 0 || dev != glxbase_dev)
220 return gen_pci_conf_read(v, tag, offset);
221
222 data = 0;
223
224 switch (fn) {
225 case 0: /* PCI-ISA bridge */
226 data = glx_fn0_read(offset);
227 break;
228 case 1: /* Flash memory */
229 break;
230 case 2: /* IDE controller */
231 data = glx_fn2_read(offset);
232 break;
233 case 3: /* AC97 codec */
234 data = glx_fn3_read(offset);
235 break;
236 case 4: /* OHCI controller */
237 data = glx_fn4_read(offset);
238 break;
239 case 5: /* EHCI controller */
240 data = glx_fn5_read(offset);
241 break;
242 case 6: /* UDC */
243 break;
244 case 7: /* OTG */
245 break;
246 }
247
248 return data;
249 }
250
251 void
252 glx_pci_write_hook(void *v, pcitag_t tag,
253 int offset, pcireg_t data)
254 {
255 int bus, dev, fn;
256
257 /*
258 * Do not get in the way of MSR programming
259 */
260 if (tag == glxbase_tag && offset >= PCI_MSR_CTRL) {
261 gen_pci_conf_write(v, tag, offset, data);
262 return;
263 }
264
265
266 pci_decompose_tag(glxbase_pc, tag, &bus, &dev, &fn);
267 if (bus != 0 || dev != glxbase_dev) {
268 gen_pci_conf_write(v, tag, offset, data);
269 return;
270 }
271
272 switch (fn) {
273 case 0: /* PCI-ISA bridge */
274 glx_fn0_write(offset, data);
275 break;
276 case 1: /* Flash memory */
277 break;
278 case 2: /* IDE controller */
279 glx_fn2_write(offset, data);
280 break;
281 case 3: /* AC97 codec */
282 glx_fn3_write(offset, data);
283 break;
284 case 4: /* OHCI controller */
285 glx_fn4_write(offset, data);
286 break;
287 case 5: /* EHCI controller */
288 glx_fn5_write(offset, data);
289 break;
290 case 6: /* USB UDC */
291 break;
292 case 7: /* USB OTG */
293 break;
294 }
295 }
296
297 pcireg_t
298 glx_get_status(void)
299 {
300 uint64_t msr;
301 pcireg_t data;
302
303 data = 0;
304 msr = rdmsr(GCSC_GLPCI_GLD_MSR_ERROR);
305 if (msr & (1UL << 5))
306 data |= PCI_COMMAND_PARITY_ENABLE;
307 data |= PCI_STATUS_66MHZ_SUPPORT |
308 PCI_STATUS_BACKTOBACK_SUPPORT | PCI_STATUS_DEVSEL_MEDIUM;
309 if (msr & (1UL << 21))
310 data |= PCI_STATUS_PARITY_DETECT;
311 if (msr & (1UL << 20))
312 data |= PCI_STATUS_TARGET_TARGET_ABORT;
313 if (msr & (1UL << 17))
314 data |= PCI_STATUS_MASTER_TARGET_ABORT;
315 if (msr & (1UL << 16))
316 data |= PCI_STATUS_MASTER_ABORT;
317
318 return data;
319 }
320
321 /*
322 * Function 0: PCI-ISA bridge
323 */
324
325 static const pcireg_t pcib_bar_sizes[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4] = {
326 0x008,
327 0x100,
328 0x040,
329 0x020,
330 0x080,
331 0x020
332 };
333
334 static pcireg_t pcib_bar_values[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4];
335
336 static const uint64_t pcib_bar_msr[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4] = {
337 GCSC_DIVIL_LBAR_SMB,
338 GCSC_DIVIL_LBAR_GPIO,
339 GCSC_DIVIL_LBAR_MFGPT,
340 GCSC_DIVIL_LBAR_IRQ,
341 GCSC_DIVIL_LBAR_PMS,
342 GCSC_DIVIL_LBAR_ACPI
343 };
344
345 pcireg_t
346 glx_fn0_read(int reg)
347 {
348 uint64_t msr;
349 pcireg_t data;
350 int index;
351
352 switch (reg) {
353 case PCI_ID_REG:
354 case PCI_SUBSYS_ID_REG:
355 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_PCIB);
356 break;
357 case PCI_COMMAND_STATUS_REG:
358 data = glx_get_status();
359 data |= PCI_COMMAND_MASTER_ENABLE;
360 msr = rdmsr(GCSC_DIVIL_LBAR_SMB);
361 if (msr & (1ULL << 32))
362 data |= PCI_COMMAND_IO_ENABLE;
363 break;
364 case PCI_CLASS_REG:
365 msr = rdmsr(GCSC_GLCP_CHIP_REV_ID);
366 data = (PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT) |
367 (PCI_SUBCLASS_BRIDGE_ISA << PCI_SUBCLASS_SHIFT) |
368 (msr & PCI_REVISION_MASK);
369 break;
370 case PCI_BHLC_REG:
371 msr = rdmsr(GCSC_GLPCI_CTRL);
372 data = (0x80 << PCI_HDRTYPE_SHIFT) |
373 (((msr & 0xff00000000UL) >> 32) << PCI_LATTIMER_SHIFT) |
374 (0x08 << PCI_CACHELINE_SHIFT);
375 break;
376 case PCI_MAPREG_START + 0x00:
377 case PCI_MAPREG_START + 0x04:
378 case PCI_MAPREG_START + 0x08:
379 case PCI_MAPREG_START + 0x0c:
380 case PCI_MAPREG_START + 0x10:
381 case PCI_MAPREG_START + 0x14:
382 case PCI_MAPREG_START + 0x18:
383 index = (reg - PCI_MAPREG_START) / 4;
384 if (pcib_bar_msr[index] == 0)
385 data = 0;
386 else {
387 data = pcib_bar_values[index];
388 if (data == 0xffffffff)
389 data = PCI_MAPREG_IO_ADDR_MASK;
390 else
391 data = (pcireg_t)rdmsr(pcib_bar_msr[index]);
392 data &= ~(pcib_bar_sizes[index] - 1);
393 if (data != 0)
394 data |= PCI_MAPREG_TYPE_IO;
395 }
396 break;
397 case PCI_INTERRUPT_REG:
398 data = (0x40 << PCI_MAX_LAT_SHIFT) |
399 (PCI_INTERRUPT_PIN_NONE << PCI_INTERRUPT_PIN_SHIFT);
400 break;
401 default:
402 data = 0;
403 break;
404 }
405
406 return data;
407 }
408
409 void
410 glx_fn0_write(int reg, pcireg_t data)
411 {
412 uint64_t msr;
413 int index;
414
415 switch (reg) {
416 case PCI_COMMAND_STATUS_REG:
417 for (index = 0; index < __arraycount(pcib_bar_msr); index++) {
418 if (pcib_bar_msr[index] == 0)
419 continue;
420 msr = rdmsr(pcib_bar_msr[index]);
421 if (data & PCI_COMMAND_IO_ENABLE)
422 msr |= 1ULL << 32;
423 else
424 msr &= ~(1ULL << 32);
425 wrmsr(pcib_bar_msr[index], msr);
426 }
427
428 msr = rdmsr(GCSC_GLPCI_GLD_MSR_ERROR);
429 if (data & PCI_COMMAND_PARITY_ENABLE)
430 msr |= 1ULL << 5;
431 else
432 msr &= ~(1ULL << 5);
433 wrmsr(GCSC_GLPCI_GLD_MSR_ERROR, msr);
434 break;
435 case PCI_BHLC_REG:
436 msr = rdmsr(GCSC_GLPCI_CTRL);
437 msr &= 0xff00000000ULL;
438 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
439 break;
440 case PCI_MAPREG_START + 0x00:
441 case PCI_MAPREG_START + 0x04:
442 case PCI_MAPREG_START + 0x08:
443 case PCI_MAPREG_START + 0x0c:
444 case PCI_MAPREG_START + 0x10:
445 case PCI_MAPREG_START + 0x14:
446 case PCI_MAPREG_START + 0x18:
447 index = (reg - PCI_MAPREG_START) / 4;
448 if (data == 0xffffffff) {
449 pcib_bar_values[index] = data;
450 } else if (pcib_bar_msr[index] != 0) {
451 if ((data & PCI_MAPREG_TYPE_MASK) ==
452 PCI_MAPREG_TYPE_IO) {
453 data &= PCI_MAPREG_IO_ADDR_MASK;
454 data &= ~(pcib_bar_sizes[index] - 1);
455 wrmsr(pcib_bar_msr[index],
456 (0x0000f000ULL << 32) | (1ULL << 32) | data);
457 } else {
458 wrmsr(pcib_bar_msr[index], 0ULL);
459 }
460 pcib_bar_values[index] = 0;
461 }
462 break;
463 }
464 }
465
466 /*
467 * Function 2: IDE Controller
468 */
469
470 static pcireg_t pciide_bar_size = 0x10;
471 static pcireg_t pciide_bar_value;
472
473 pcireg_t
474 glx_fn2_read(int reg)
475 {
476 uint64_t msr;
477 pcireg_t data;
478
479 switch (reg) {
480 case PCI_ID_REG:
481 case PCI_SUBSYS_ID_REG:
482 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_IDE);
483 break;
484 case PCI_COMMAND_STATUS_REG:
485 data = glx_get_status();
486 data |= PCI_COMMAND_IO_ENABLE;
487 msr = rdmsr(GCSC_GLIU_PAE);
488 if ((msr & (0x3 << 4)) == 0x03)
489 data |= PCI_COMMAND_MASTER_ENABLE;
490 break;
491 case PCI_CLASS_REG:
492 msr = rdmsr(GCSC_IDE_GLD_MSR_CAP);
493 data = (PCI_CLASS_MASS_STORAGE << PCI_CLASS_SHIFT) |
494 (PCI_SUBCLASS_MASS_STORAGE_IDE << PCI_SUBCLASS_SHIFT) |
495 (PCIIDE_INTERFACE_BUS_MASTER_DMA << PCI_INTERFACE_SHIFT) |
496 (msr & PCI_REVISION_MASK);
497 break;
498 case PCI_BHLC_REG:
499 msr = rdmsr(GCSC_GLPCI_CTRL);
500 data = (0x00 << PCI_HDRTYPE_SHIFT) |
501 (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
502 (0x08 << PCI_CACHELINE_SHIFT);
503 break;
504 case PCI_MAPREG_START + 0x10:
505 data = pciide_bar_value;
506 if (data == 0xffffffff)
507 data = PCI_MAPREG_IO_ADDR_MASK & ~(pciide_bar_size - 1);
508 else {
509 msr = rdmsr(GCSC_IDE_IO_BAR);
510 data = msr & 0xfffffff0;
511 }
512 if (data != 0)
513 data |= PCI_MAPREG_TYPE_IO;
514 break;
515 case PCI_INTERRUPT_REG:
516 /* compat mode */
517 data = (0x40 << PCI_MAX_LAT_SHIFT) |
518 (PCI_INTERRUPT_PIN_NONE << PCI_INTERRUPT_PIN_SHIFT);
519 break;
520 /*
521 * The following registers are used by pciide(4)
522 */
523 case PCIIDE_CHANSTATUS_EN:
524 data = rdmsr(GCSC_IDE_CFG);
525 break;
526 case /* AMD756_DATATIM XXX */ 0x48:
527 data = rdmsr(GCSC_IDE_DTC);
528 break;
529 case /* AMD756_UDMA XXX*/ 0x50:
530 data = rdmsr(GCSC_IDE_ETC);
531 break;
532 default:
533 DPRINTF(("unimplemented pciide reg 0x%x\n", reg));
534 data = 0;
535 break;
536 }
537
538 return data;
539 }
540
541 void
542 glx_fn2_write(int reg, pcireg_t data)
543 {
544 uint64_t msr;
545
546 switch (reg) {
547 case PCI_COMMAND_STATUS_REG:
548 msr = rdmsr(GCSC_GLIU_PAE);
549 if (data & PCI_COMMAND_MASTER_ENABLE)
550 msr |= 0x03 << 4;
551 else
552 msr &= ~(0x03 << 4);
553 wrmsr(GCSC_GLIU_PAE, msr);
554 break;
555 case PCI_BHLC_REG:
556 msr = rdmsr(GCSC_GLPCI_CTRL);
557 msr &= 0xff00000000ULL;
558 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
559 break;
560 case PCI_MAPREG_START + 0x10:
561 if (data == 0xffffffff) {
562 pciide_bar_value = data;
563 } else {
564 if ((data & PCI_MAPREG_TYPE_MASK) ==
565 PCI_MAPREG_TYPE_IO) {
566 data &= PCI_MAPREG_IO_ADDR_MASK;
567 msr = (uint32_t)data & 0xfffffff0;
568 wrmsr(GCSC_IDE_IO_BAR, msr);
569 } else {
570 wrmsr(GCSC_IDE_IO_BAR, 0);
571 }
572 pciide_bar_value = 0;
573 }
574 break;
575 /*
576 * The following registers are used by pciide(4)
577 */
578 case PCIIDE_CHANSTATUS_EN:
579 wrmsr(GCSC_IDE_CFG, (uint32_t)data);
580 break;
581 case /* AMD756_DATATIM XXX */ 0x48:
582 wrmsr(GCSC_IDE_DTC, (uint32_t)data);
583 break;
584 case /* AMD756_UDMA XXX*/ 0x50:
585 wrmsr(GCSC_IDE_ETC, (uint32_t)data);
586 break;
587 default:
588 DPRINTF(("unimplemented pciide reg 0x%x\n", reg));
589 }
590 }
591
592 /*
593 * Function 3: AC97 Codec
594 */
595
596 static pcireg_t ac97_bar_size = 0x80;
597 static pcireg_t ac97_bar_value;
598
599 pcireg_t
600 glx_fn3_read(int reg)
601 {
602 uint64_t msr;
603 pcireg_t data;
604
605 switch (reg) {
606 case PCI_ID_REG:
607 case PCI_SUBSYS_ID_REG:
608 data = PCI_ID_CODE(PCI_VENDOR_AMD,
609 PCI_PRODUCT_AMD_CS5536_AUDIO);
610 break;
611 case PCI_COMMAND_STATUS_REG:
612 data = glx_get_status();
613 data |= PCI_COMMAND_IO_ENABLE;
614 msr = rdmsr(GCSC_GLIU_PAE);
615 if ((msr & (0x3 << 8)) == 0x03)
616 data |= PCI_COMMAND_MASTER_ENABLE;
617 break;
618 case PCI_CLASS_REG:
619 msr = rdmsr(GCSC_ACC_GLD_MSR_CAP);
620 data = (PCI_CLASS_MULTIMEDIA << PCI_CLASS_SHIFT) |
621 (PCI_SUBCLASS_MULTIMEDIA_AUDIO << PCI_SUBCLASS_SHIFT) |
622 (msr & PCI_REVISION_MASK);
623 break;
624 case PCI_BHLC_REG:
625 msr = rdmsr(GCSC_GLPCI_CTRL);
626 data = (0x00 << PCI_HDRTYPE_SHIFT) |
627 (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
628 (0x08 << PCI_CACHELINE_SHIFT);
629 break;
630 case PCI_MAPREG_START:
631 data = ac97_bar_value;
632 if (data == 0xffffffff)
633 data = PCI_MAPREG_IO_ADDR_MASK & ~(ac97_bar_size - 1);
634 else {
635 msr = rdmsr(GCSC_GLIU_IOD_BM1);
636 data = (msr >> 20) & 0x000fffff;
637 data &= (msr & 0x000fffff);
638 }
639 if (data != 0)
640 data |= PCI_MAPREG_TYPE_IO;
641 break;
642 case PCI_INTERRUPT_REG:
643 data = (0x40 << PCI_MAX_LAT_SHIFT) |
644 (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
645 break;
646 default:
647 data = 0;
648 break;
649 }
650
651 return data;
652 }
653
654 void
655 glx_fn3_write(int reg, pcireg_t data)
656 {
657 uint64_t msr;
658
659 switch (reg) {
660 case PCI_COMMAND_STATUS_REG:
661 msr = rdmsr(GCSC_GLIU_PAE);
662 if (data & PCI_COMMAND_MASTER_ENABLE)
663 msr |= 0x03 << 8;
664 else
665 msr &= ~(0x03 << 8);
666 wrmsr(GCSC_GLIU_PAE, msr);
667 break;
668 case PCI_BHLC_REG:
669 msr = rdmsr(GCSC_GLPCI_CTRL);
670 msr &= 0xff00000000ULL;
671 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
672 break;
673 case PCI_MAPREG_START:
674 if (data == 0xffffffff) {
675 ac97_bar_value = data;
676 } else {
677 if ((data & PCI_MAPREG_TYPE_MASK) ==
678 PCI_MAPREG_TYPE_IO) {
679 data &= PCI_MAPREG_IO_ADDR_MASK;
680 msr = rdmsr(GCSC_GLIU_IOD_BM1);
681 msr &= 0x0fffff0000000000ULL;
682 msr |= 5ULL << 61; /* AC97 */
683 msr |= ((uint64_t)data & 0xfffff) << 20;
684 msr |= 0x000fffff & ~(ac97_bar_size - 1);
685 wrmsr(GCSC_GLIU_IOD_BM1, msr);
686 } else {
687 wrmsr(GCSC_GLIU_IOD_BM1, 0);
688 }
689 ac97_bar_value = 0;
690 }
691 break;
692 }
693 }
694
695 /*
696 * Function 4: OHCI Controller
697 */
698
699 static pcireg_t ohci_bar_size = 0x1000;
700 static pcireg_t ohci_bar_value;
701
702 pcireg_t
703 glx_fn4_read(int reg)
704 {
705 uint64_t msr;
706 pcireg_t data;
707
708 switch (reg) {
709 case PCI_ID_REG:
710 case PCI_SUBSYS_ID_REG:
711 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_OHCI);
712 break;
713 case PCI_COMMAND_STATUS_REG:
714 data = glx_get_status();
715 msr = rdmsr(GCSC_USB_MSR_OHCB);
716 if (msr & (1ULL << 34))
717 data |= PCI_COMMAND_MASTER_ENABLE;
718 if (msr & (1ULL << 33))
719 data |= PCI_COMMAND_MEM_ENABLE;
720 break;
721 case PCI_CLASS_REG:
722 msr = rdmsr(GCSC_USB_GLD_MSR_CAP);
723 data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
724 (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
725 (PCI_INTERFACE_OHCI << PCI_INTERFACE_SHIFT) |
726 (msr & PCI_REVISION_MASK);
727 break;
728 case PCI_BHLC_REG:
729 msr = rdmsr(GCSC_GLPCI_CTRL);
730 data = (0x00 << PCI_HDRTYPE_SHIFT) |
731 (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
732 (0x08 << PCI_CACHELINE_SHIFT);
733 break;
734 case PCI_MAPREG_START + 0x00:
735 data = ohci_bar_value;
736 if (data == 0xffffffff)
737 data = PCI_MAPREG_MEM_ADDR_MASK & ~(ohci_bar_size - 1);
738 else {
739 msr = rdmsr(GCSC_USB_MSR_OHCB);
740 data = msr & 0xffffff00;
741 }
742 if (data != 0)
743 data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
744 break;
745 case PCI_CAPLISTPTR_REG:
746 data = 0x40;
747 break;
748 case PCI_INTERRUPT_REG:
749 data = (0x40 << PCI_MAX_LAT_SHIFT) |
750 (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
751 break;
752 case 0x40: /* USB capability pointer */
753 data = 0;
754 break;
755 default:
756 data = 0;
757 break;
758 }
759
760 return data;
761 }
762
763 void
764 glx_fn4_write(int reg, pcireg_t data)
765 {
766 uint64_t msr;
767
768 switch (reg) {
769 case PCI_COMMAND_STATUS_REG:
770 msr = rdmsr(GCSC_USB_MSR_OHCB);
771 if (data & PCI_COMMAND_MASTER_ENABLE)
772 msr |= 1ULL << 34;
773 else
774 msr &= ~(1ULL << 34);
775 if (data & PCI_COMMAND_MEM_ENABLE)
776 msr |= 1ULL << 33;
777 else
778 msr &= ~(1ULL << 33);
779 wrmsr(GCSC_USB_MSR_OHCB, msr);
780 break;
781 case PCI_BHLC_REG:
782 msr = rdmsr(GCSC_GLPCI_CTRL);
783 msr &= 0xff00000000ULL;
784 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
785 break;
786 case PCI_MAPREG_START + 0x00:
787 if (data == 0xffffffff) {
788 ohci_bar_value = data;
789 } else {
790 if ((data & PCI_MAPREG_TYPE_MASK) ==
791 PCI_MAPREG_TYPE_MEM) {
792 data &= PCI_MAPREG_MEM_ADDR_MASK;
793 msr = rdmsr(GCSC_GLIU_P2D_BM3);
794 msr &= 0x0fffff0000000000ULL;
795 msr |= 2ULL << 61; /* USB */
796 msr |= (((uint64_t)data) >> 12) << 20;
797 msr |= 0x000fffff;
798 wrmsr(GCSC_GLIU_P2D_BM3, msr);
799
800 msr = rdmsr(GCSC_USB_MSR_OHCB);
801 msr &= ~0xffffff00ULL;
802 msr |= data;
803 } else {
804 msr = rdmsr(GCSC_USB_MSR_OHCB);
805 msr &= ~0xffffff00ULL;
806 }
807 wrmsr(GCSC_USB_MSR_OHCB, msr);
808 ohci_bar_value = 0;
809 }
810 break;
811 default:
812 break;
813 }
814 }
815
816 /*
817 * Function 5: EHCI Controller
818 */
819
820 static pcireg_t ehci_bar_size = 0x1000;
821 static pcireg_t ehci_bar_value;
822
823 pcireg_t
824 glx_fn5_read(int reg)
825 {
826 uint64_t msr;
827 pcireg_t data;
828
829 switch (reg) {
830 case PCI_ID_REG:
831 case PCI_SUBSYS_ID_REG:
832 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_EHCI);
833 break;
834 case PCI_COMMAND_STATUS_REG:
835 data = glx_get_status();
836 msr = rdmsr(GCSC_USB_MSR_EHCB);
837 if (msr & (1ULL << 34))
838 data |= PCI_COMMAND_MASTER_ENABLE;
839 if (msr & (1ULL << 33))
840 data |= PCI_COMMAND_MEM_ENABLE;
841 break;
842 case PCI_CLASS_REG:
843 msr = rdmsr(GCSC_USB_GLD_MSR_CAP);
844 data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
845 (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
846 (PCI_INTERFACE_EHCI << PCI_INTERFACE_SHIFT) |
847 (msr & PCI_REVISION_MASK);
848 break;
849 case PCI_BHLC_REG:
850 msr = rdmsr(GCSC_GLPCI_CTRL);
851 data = (0x00 << PCI_HDRTYPE_SHIFT) |
852 (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
853 (0x08 << PCI_CACHELINE_SHIFT);
854 break;
855 case PCI_MAPREG_START + 0x00:
856 data = ehci_bar_value;
857 if (data == 0xffffffff)
858 data = PCI_MAPREG_MEM_ADDR_MASK & ~(ehci_bar_size - 1);
859 else {
860 msr = rdmsr(GCSC_USB_MSR_EHCB);
861 data = msr & 0xffffff00;
862 }
863 if (data != 0)
864 data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
865 break;
866 case PCI_CAPLISTPTR_REG:
867 data = 0x40;
868 break;
869 case PCI_INTERRUPT_REG:
870 data = (0x40 << PCI_MAX_LAT_SHIFT) |
871 (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
872 break;
873 case 0x40: /* USB capability pointer */
874 data = 0;
875 break;
876 case PCI_USBREV:
877 msr = rdmsr(GCSC_USB_MSR_EHCB);
878 data = PCI_USBREV_2_0;
879 data |= ((msr >> 40) & 0x3f) << 8; /* PCI_EHCI_FLADJ */
880 break;
881 default:
882 data = 0;
883 break;
884 }
885
886 return data;
887 }
888
889 void
890 glx_fn5_write(int reg, pcireg_t data)
891 {
892 uint64_t msr;
893
894 switch (reg) {
895 case PCI_COMMAND_STATUS_REG:
896 msr = rdmsr(GCSC_USB_MSR_EHCB);
897 if (data & PCI_COMMAND_MASTER_ENABLE)
898 msr |= 1ULL << 34;
899 else
900 msr &= ~(1ULL << 34);
901 if (data & PCI_COMMAND_MEM_ENABLE)
902 msr |= 1ULL << 33;
903 else
904 msr &= ~(1ULL << 33);
905 wrmsr(GCSC_USB_MSR_EHCB, msr);
906 break;
907 case PCI_BHLC_REG:
908 msr = rdmsr(GCSC_GLPCI_CTRL);
909 msr &= 0xff00000000ULL;
910 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
911 break;
912 case PCI_MAPREG_START + 0x00:
913 if (data == 0xffffffff) {
914 ehci_bar_value = data;
915 } else {
916 if ((data & PCI_MAPREG_TYPE_MASK) ==
917 PCI_MAPREG_TYPE_MEM) {
918 data &= PCI_MAPREG_MEM_ADDR_MASK;
919 msr = rdmsr(GCSC_GLIU_P2D_BM4);
920 msr &= 0x0fffff0000000000ULL;
921 msr |= 2ULL << 61; /* USB */
922 msr |= (((uint64_t)data) >> 12) << 20;
923 msr |= 0x000fffff;
924 wrmsr(GCSC_GLIU_P2D_BM4, msr);
925
926 msr = rdmsr(GCSC_USB_MSR_EHCB);
927 msr &= ~0xffffff00ULL;
928 msr |= data;
929 } else {
930 msr = rdmsr(GCSC_USB_MSR_EHCB);
931 msr &= ~0xffffff00ULL;
932 }
933 wrmsr(GCSC_USB_MSR_EHCB, msr);
934 ehci_bar_value = 0;
935 }
936 break;
937 default:
938 break;
939 }
940 }
941