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