1 /* $OpenBSD: glx.c,v 1.13 2024/05/22 14:25:47 jsg 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
24 #include <sys/param.h>
25 #include <sys/systm.h>
26 #include <sys/device.h>
27 #include <sys/kernel.h>
28
29 #include <machine/bus.h>
30
31 #include <dev/pci/pcireg.h>
32 #include <dev/pci/pcivar.h>
33 #include <dev/pci/pcidevs.h>
34
35 #include <dev/pci/pciidereg.h>
36 #include <dev/pci/pciide_amd_reg.h>
37 #include <dev/usb/ehcireg.h>
38 #include <dev/usb/ohcireg.h>
39
40 #include <dev/pci/glxreg.h>
41 #include <dev/pci/glxvar.h>
42
43 #include <loongson/dev/bonitovar.h>
44
45 /*
46 * Since the purpose of this code is to present a different view of the
47 * PCI configuration space, it can not attach as a real device.
48 * (well it could, and then we'd have to attach a fake pci to it,
49 * and fake the configuration space accesses anyways - is it worth doing?)
50 *
51 * We just keep the `would-be softc' structure as global variables.
52 */
53
54 static pci_chipset_tag_t glxbase_pc;
55 static pcitag_t glxbase_tag;
56 static int glxbase_dev;
57
58 /* MSR access through PCI configuration space */
59 #define PCI_MSR_CTRL 0x00f0
60 #define PCI_MSR_ADDR 0x00f4
61 #define PCI_MSR_LO32 0x00f8
62 #define PCI_MSR_HI32 0x00fc
63
64 int glx_pci_read_hook(void *, pci_chipset_tag_t, pcitag_t, int, pcireg_t *);
65 int glx_pci_write_hook(void *, pci_chipset_tag_t, pcitag_t, int, pcireg_t);
66
67 pcireg_t glx_get_status(void);
68 pcireg_t glx_fn0_read(int);
69 void glx_fn0_write(int, pcireg_t);
70 pcireg_t glx_fn2_read(int);
71 void glx_fn2_write(int, pcireg_t);
72 pcireg_t glx_fn3_read(int);
73 void glx_fn3_write(int, pcireg_t);
74 pcireg_t glx_fn4_read(int);
75 void glx_fn4_write(int, pcireg_t);
76 pcireg_t glx_fn5_read(int);
77 void glx_fn5_write(int, pcireg_t);
78
79 void
glx_init(pci_chipset_tag_t pc,pcitag_t tag,int dev)80 glx_init(pci_chipset_tag_t pc, pcitag_t tag, int dev)
81 {
82 uint64_t msr;
83
84 glxbase_pc = pc;
85 glxbase_dev = dev;
86 glxbase_tag = tag;
87
88 /*
89 * Register PCI configuration hooks to make the various
90 * embedded devices visible as PCI subfunctions.
91 */
92
93 bonito_pci_hook(pc, NULL, glx_pci_read_hook, glx_pci_write_hook);
94
95 /*
96 * Perform some Geode initialization.
97 */
98
99 msr = rdmsr(DIVIL_BALL_OPTS); /* 0x71 */
100 wrmsr(DIVIL_BALL_OPTS, msr | 0x01);
101
102 /*
103 * Route usb, audio and serial interrupts
104 */
105
106 msr = rdmsr(PIC_YSEL_LOW);
107 msr &= ~(0xfUL << 8);
108 msr &= ~(0xfUL << 16);
109 msr |= 11 << 8;
110 msr |= 9 << 16;
111 wrmsr(PIC_YSEL_LOW, msr);
112
113 msr = rdmsr(PIC_YSEL_HIGH);
114 msr &= ~(0xfUL << 24);
115 msr &= ~(0xfUL << 28);
116 msr |= 4 << 24;
117 msr |= 3 << 28;
118 wrmsr(PIC_YSEL_HIGH, msr);
119 }
120
121 uint64_t
rdmsr(uint msr)122 rdmsr(uint msr)
123 {
124 uint64_t lo, hi;
125 register_t sr;
126
127 #ifdef DIAGNOSTIC
128 if (glxbase_tag == 0)
129 panic("rdmsr invoked before glx initialization");
130 #endif
131
132 sr = disableintr();
133 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_ADDR, msr);
134 lo = (uint32_t)pci_conf_read(glxbase_pc, glxbase_tag, PCI_MSR_LO32);
135 hi = (uint32_t)pci_conf_read(glxbase_pc, glxbase_tag, PCI_MSR_HI32);
136 setsr(sr);
137 return (hi << 32) | lo;
138 }
139
140 void
wrmsr(uint msr,uint64_t value)141 wrmsr(uint msr, uint64_t value)
142 {
143 register_t sr;
144
145 #ifdef DIAGNOSTIC
146 if (glxbase_tag == 0)
147 panic("wrmsr invoked before glx initialization");
148 #endif
149
150 sr = disableintr();
151 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_ADDR, msr);
152 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_LO32, (uint32_t)value);
153 pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_HI32, value >> 32);
154 setsr(sr);
155 }
156
157 int
glx_pci_read_hook(void * v,pci_chipset_tag_t pc,pcitag_t tag,int offset,pcireg_t * data)158 glx_pci_read_hook(void *v, pci_chipset_tag_t pc, pcitag_t tag,
159 int offset, pcireg_t *data)
160 {
161 int bus, dev, fn;
162
163 /*
164 * Do not get in the way of MSR programming
165 */
166 if (tag == glxbase_tag && offset >= PCI_MSR_CTRL)
167 return 0;
168
169 pci_decompose_tag(pc, tag, &bus, &dev, &fn);
170 if (bus != 0 || dev != glxbase_dev)
171 return 0;
172
173 *data = 0;
174
175 switch (fn) {
176 case 0: /* PCI-ISA bridge */
177 *data = glx_fn0_read(offset);
178 break;
179 case 1: /* Flash memory */
180 break;
181 case 2: /* IDE controller */
182 *data = glx_fn2_read(offset);
183 break;
184 case 3: /* AC97 codec */
185 *data = glx_fn3_read(offset);
186 break;
187 case 4: /* OHCI controller */
188 *data = glx_fn4_read(offset);
189 break;
190 case 5: /* EHCI controller */
191 *data = glx_fn5_read(offset);
192 break;
193 case 6: /* UDC */
194 break;
195 case 7: /* OTG */
196 break;
197 }
198
199 return 1;
200 }
201
202 int
glx_pci_write_hook(void * v,pci_chipset_tag_t pc,pcitag_t tag,int offset,pcireg_t data)203 glx_pci_write_hook(void *v, pci_chipset_tag_t pc, pcitag_t tag,
204 int offset, pcireg_t data)
205 {
206 int bus, dev, fn;
207
208 /*
209 * Do not get in the way of MSR programming
210 */
211 if (tag == glxbase_tag && offset >= PCI_MSR_CTRL)
212 return 0;
213
214 pci_decompose_tag(pc, tag, &bus, &dev, &fn);
215 if (bus != 0 || dev != glxbase_dev)
216 return 0;
217
218 switch (fn) {
219 case 0: /* PCI-ISA bridge */
220 glx_fn0_write(offset, data);
221 break;
222 case 1: /* Flash memory */
223 break;
224 case 2: /* IDE controller */
225 glx_fn2_write(offset, data);
226 break;
227 case 3: /* AC97 codec */
228 glx_fn3_write(offset, data);
229 break;
230 case 4: /* OHCI controller */
231 glx_fn4_write(offset, data);
232 break;
233 case 5: /* EHCI controller */
234 glx_fn5_write(offset, data);
235 break;
236 case 6: /* USB UDC */
237 break;
238 case 7: /* USB OTG */
239 break;
240 }
241
242 return 1;
243 }
244
245 pcireg_t
glx_get_status()246 glx_get_status()
247 {
248 uint64_t msr;
249 pcireg_t data;
250
251 data = 0;
252 msr = rdmsr(GLPCI_GLD_MSR_ERROR);
253 if (msr & (1UL << 5))
254 data |= PCI_COMMAND_PARITY_ENABLE;
255 data |= PCI_STATUS_66MHZ_SUPPORT |
256 PCI_STATUS_BACKTOBACK_SUPPORT | PCI_STATUS_DEVSEL_MEDIUM;
257 if (msr & (1UL << 21))
258 data |= PCI_STATUS_PARITY_DETECT;
259 if (msr & (1UL << 20))
260 data |= PCI_STATUS_TARGET_TARGET_ABORT;
261 if (msr & (1UL << 17))
262 data |= PCI_STATUS_MASTER_TARGET_ABORT;
263 if (msr & (1UL << 16))
264 data |= PCI_STATUS_MASTER_ABORT;
265
266 return data;
267 }
268
269 /*
270 * Function 0: PCI-ISA bridge
271 */
272
273 static pcireg_t pcib_bar_sizes[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4] = {
274 0x008,
275 0x100,
276 0x040,
277 0x020,
278 0x080,
279 0x020
280 };
281
282 static pcireg_t pcib_bar_values[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4];
283
284 static uint64_t pcib_bar_msr[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4] = {
285 DIVIL_LBAR_SMB,
286 DIVIL_LBAR_GPIO,
287 DIVIL_LBAR_MFGPT,
288 DIVIL_LBAR_IRQ,
289 DIVIL_LBAR_PMS,
290 DIVIL_LBAR_ACPI
291 };
292
293 pcireg_t
glx_fn0_read(int reg)294 glx_fn0_read(int reg)
295 {
296 uint64_t msr;
297 pcireg_t data;
298 int index;
299
300 switch (reg) {
301 case PCI_ID_REG:
302 case PCI_SUBSYS_ID_REG:
303 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_PCIB);
304 break;
305 case PCI_COMMAND_STATUS_REG:
306 data = glx_get_status();
307 data |= PCI_COMMAND_MASTER_ENABLE;
308 msr = rdmsr(DIVIL_LBAR_SMB);
309 if (msr & (1UL << 32))
310 data |= PCI_COMMAND_IO_ENABLE;
311 break;
312 case PCI_CLASS_REG:
313 msr = rdmsr(GLCP_CHIP_REV_ID);
314 data = (PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT) |
315 (PCI_SUBCLASS_BRIDGE_ISA << PCI_SUBCLASS_SHIFT) |
316 (msr & PCI_REVISION_MASK);
317 break;
318 case PCI_BHLC_REG:
319 msr = rdmsr(GLPCI_CTRL);
320 data = (0x80 << PCI_HDRTYPE_SHIFT) |
321 (((msr & 0xff00000000UL) >> 32) << PCI_LATTIMER_SHIFT) |
322 (0x08 << PCI_CACHELINE_SHIFT);
323 break;
324 case PCI_MAPREG_START + 0x00:
325 case PCI_MAPREG_START + 0x04:
326 case PCI_MAPREG_START + 0x08:
327 case PCI_MAPREG_START + 0x0c:
328 case PCI_MAPREG_START + 0x10:
329 case PCI_MAPREG_START + 0x14:
330 case PCI_MAPREG_START + 0x18:
331 index = (reg - PCI_MAPREG_START) / 4;
332 if (pcib_bar_msr[index] == 0)
333 data = 0;
334 else {
335 data = pcib_bar_values[index];
336 if (data == 0xffffffff)
337 data = PCI_MAPREG_IO_ADDR_MASK;
338 else
339 data = (pcireg_t)rdmsr(pcib_bar_msr[index]);
340 data &= ~(pcib_bar_sizes[index] - 1);
341 if (data != 0)
342 data |= PCI_MAPREG_TYPE_IO;
343 }
344 break;
345 case PCI_INTERRUPT_REG:
346 data = (0x40 << PCI_MAX_LAT_SHIFT) |
347 (PCI_INTERRUPT_PIN_NONE << PCI_INTERRUPT_PIN_SHIFT);
348 break;
349 default:
350 data = 0;
351 break;
352 }
353
354 return data;
355 }
356
357 void
glx_fn0_write(int reg,pcireg_t data)358 glx_fn0_write(int reg, pcireg_t data)
359 {
360 uint64_t msr;
361 int index;
362
363 switch (reg) {
364 case PCI_COMMAND_STATUS_REG:
365 for (index = 0; index < nitems(pcib_bar_msr); index++) {
366 if (pcib_bar_msr[index] == 0)
367 continue;
368 msr = rdmsr(pcib_bar_msr[index]);
369 if (data & PCI_COMMAND_IO_ENABLE)
370 msr |= 1UL << 32;
371 else
372 msr &= ~(1UL << 32);
373 wrmsr(pcib_bar_msr[index], msr);
374 }
375
376 msr = rdmsr(GLPCI_GLD_MSR_ERROR);
377 if (data & PCI_COMMAND_PARITY_ENABLE)
378 msr |= 1UL << 5;
379 else
380 msr &= ~(1UL << 5);
381 wrmsr(GLPCI_GLD_MSR_ERROR, msr);
382 break;
383 case PCI_BHLC_REG:
384 msr = rdmsr(GLPCI_CTRL);
385 msr &= 0xff00000000UL;
386 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
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 (data == 0xffffffff) {
397 pcib_bar_values[index] = data;
398 } else if (pcib_bar_msr[index] != 0) {
399 if ((data & PCI_MAPREG_TYPE_MASK) ==
400 PCI_MAPREG_TYPE_IO) {
401 data &= PCI_MAPREG_IO_ADDR_MASK;
402 data &= ~(pcib_bar_sizes[index] - 1);
403 wrmsr(pcib_bar_msr[index],
404 (0x0000f000UL << 32) | (1UL << 32) | data);
405 } else {
406 wrmsr(pcib_bar_msr[index], 0UL);
407 }
408 pcib_bar_values[index] = 0;
409 }
410 break;
411 }
412 }
413
414 /*
415 * Function 2: IDE Controller
416 */
417
418 static pcireg_t pciide_bar_size = 0x10;
419 static pcireg_t pciide_bar_value;
420
421 pcireg_t
glx_fn2_read(int reg)422 glx_fn2_read(int reg)
423 {
424 uint64_t msr;
425 pcireg_t data;
426
427 switch (reg) {
428 case PCI_ID_REG:
429 case PCI_SUBSYS_ID_REG:
430 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_IDE);
431 break;
432 case PCI_COMMAND_STATUS_REG:
433 data = glx_get_status();
434 data |= PCI_COMMAND_IO_ENABLE;
435 msr = rdmsr(GLIU_PAE);
436 if ((msr & (0x3 << 4)) == (0x03 << 4))
437 data |= PCI_COMMAND_MASTER_ENABLE;
438 break;
439 case PCI_CLASS_REG:
440 msr = rdmsr(IDE_GLD_MSR_CAP);
441 data = (PCI_CLASS_MASS_STORAGE << PCI_CLASS_SHIFT) |
442 (PCI_SUBCLASS_MASS_STORAGE_IDE << PCI_SUBCLASS_SHIFT) |
443 (PCIIDE_INTERFACE_BUS_MASTER_DMA << PCI_INTERFACE_SHIFT) |
444 (msr & PCI_REVISION_MASK);
445 break;
446 case PCI_BHLC_REG:
447 msr = rdmsr(GLPCI_CTRL);
448 data = (0x00 << PCI_HDRTYPE_SHIFT) |
449 (((msr & 0xff00000000UL) >> 32) << PCI_LATTIMER_SHIFT) |
450 (0x08 << PCI_CACHELINE_SHIFT);
451 break;
452 case PCI_MAPREG_START + 0x10:
453 data = pciide_bar_value;
454 if (data == 0xffffffff)
455 data = PCI_MAPREG_IO_ADDR_MASK & ~(pciide_bar_size - 1);
456 else {
457 msr = rdmsr(IDE_IO_BAR);
458 data = msr & 0xfffffff0;
459 }
460 if (data != 0)
461 data |= PCI_MAPREG_TYPE_IO;
462 break;
463 case PCI_INTERRUPT_REG:
464 /* compat mode */
465 data = (0x40 << PCI_MAX_LAT_SHIFT) |
466 (PCI_INTERRUPT_PIN_NONE << PCI_INTERRUPT_PIN_SHIFT);
467 break;
468 /*
469 * The following registers are used by pciide(4)
470 */
471 case AMD756_CHANSTATUS_EN:
472 data = rdmsr(IDE_CFG);
473 break;
474 case AMD756_DATATIM:
475 data = rdmsr(IDE_DTC);
476 break;
477 case AMD756_UDMA:
478 data = rdmsr(IDE_ETC);
479 break;
480 default:
481 data = 0;
482 break;
483 }
484
485 return data;
486 }
487
488 void
glx_fn2_write(int reg,pcireg_t data)489 glx_fn2_write(int reg, pcireg_t data)
490 {
491 uint64_t msr;
492
493 switch (reg) {
494 case PCI_COMMAND_STATUS_REG:
495 msr = rdmsr(GLIU_PAE);
496 if (data & PCI_COMMAND_MASTER_ENABLE)
497 msr |= 0x03 << 4;
498 else
499 msr &= ~(0x03 << 4);
500 wrmsr(GLIU_PAE, msr);
501 break;
502 case PCI_BHLC_REG:
503 msr = rdmsr(GLPCI_CTRL);
504 msr &= 0xff00000000UL;
505 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
506 break;
507 case PCI_MAPREG_START + 0x10:
508 if (data == 0xffffffff) {
509 pciide_bar_value = data;
510 } else {
511 if ((data & PCI_MAPREG_TYPE_MASK) ==
512 PCI_MAPREG_TYPE_IO) {
513 data &= PCI_MAPREG_IO_ADDR_MASK;
514 msr = (uint32_t)data & 0xfffffff0;
515 wrmsr(IDE_IO_BAR, msr);
516 } else {
517 wrmsr(IDE_IO_BAR, 0);
518 }
519 pciide_bar_value = 0;
520 }
521 break;
522 /*
523 * The following registers are used by pciide(4)
524 */
525 case AMD756_CHANSTATUS_EN:
526 wrmsr(IDE_CFG, (uint32_t)data);
527 break;
528 case AMD756_DATATIM:
529 wrmsr(IDE_DTC, (uint32_t)data);
530 break;
531 case AMD756_UDMA:
532 wrmsr(IDE_ETC, (uint32_t)data);
533 break;
534 }
535 }
536
537 /*
538 * Function 3: AC97 Codec
539 */
540
541 static pcireg_t ac97_bar_size = 0x80;
542 static pcireg_t ac97_bar_value;
543
544 pcireg_t
glx_fn3_read(int reg)545 glx_fn3_read(int reg)
546 {
547 uint64_t msr;
548 pcireg_t data;
549
550 switch (reg) {
551 case PCI_ID_REG:
552 case PCI_SUBSYS_ID_REG:
553 data = PCI_ID_CODE(PCI_VENDOR_AMD,
554 PCI_PRODUCT_AMD_CS5536_AUDIO);
555 break;
556 case PCI_COMMAND_STATUS_REG:
557 data = glx_get_status();
558 data |= PCI_COMMAND_IO_ENABLE;
559 msr = rdmsr(GLIU_PAE);
560 if ((msr & (0x3 << 8)) == (0x03 << 8))
561 data |= PCI_COMMAND_MASTER_ENABLE;
562 break;
563 case PCI_CLASS_REG:
564 msr = rdmsr(ACC_GLD_MSR_CAP);
565 data = (PCI_CLASS_MULTIMEDIA << PCI_CLASS_SHIFT) |
566 (PCI_SUBCLASS_MULTIMEDIA_AUDIO << PCI_SUBCLASS_SHIFT) |
567 (msr & PCI_REVISION_MASK);
568 break;
569 case PCI_BHLC_REG:
570 msr = rdmsr(GLPCI_CTRL);
571 data = (0x00 << PCI_HDRTYPE_SHIFT) |
572 (((msr & 0xff00000000UL) >> 32) << PCI_LATTIMER_SHIFT) |
573 (0x08 << PCI_CACHELINE_SHIFT);
574 break;
575 case PCI_MAPREG_START:
576 data = ac97_bar_value;
577 if (data == 0xffffffff)
578 data = PCI_MAPREG_IO_ADDR_MASK & ~(ac97_bar_size - 1);
579 else {
580 msr = rdmsr(GLIU_IOD_BM1);
581 data = (msr >> 20) & 0x000fffff;
582 data &= (msr & 0x000fffff);
583 }
584 if (data != 0)
585 data |= PCI_MAPREG_TYPE_IO;
586 break;
587 case PCI_INTERRUPT_REG:
588 data = (0x40 << PCI_MAX_LAT_SHIFT) |
589 (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
590 break;
591 default:
592 data = 0;
593 break;
594 }
595
596 return data;
597 }
598
599 void
glx_fn3_write(int reg,pcireg_t data)600 glx_fn3_write(int reg, pcireg_t data)
601 {
602 uint64_t msr;
603
604 switch (reg) {
605 case PCI_COMMAND_STATUS_REG:
606 msr = rdmsr(GLIU_PAE);
607 if (data & PCI_COMMAND_MASTER_ENABLE)
608 msr |= 0x03 << 8;
609 else
610 msr &= ~(0x03 << 8);
611 wrmsr(GLIU_PAE, msr);
612 break;
613 case PCI_BHLC_REG:
614 msr = rdmsr(GLPCI_CTRL);
615 msr &= 0xff00000000UL;
616 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
617 break;
618 case PCI_MAPREG_START:
619 if (data == 0xffffffff) {
620 ac97_bar_value = data;
621 } else {
622 if ((data & PCI_MAPREG_TYPE_MASK) ==
623 PCI_MAPREG_TYPE_IO) {
624 data &= PCI_MAPREG_IO_ADDR_MASK;
625 msr = rdmsr(GLIU_IOD_BM1);
626 msr &= 0x0fffff0000000000UL;
627 msr |= 5UL << 61; /* AC97 */
628 msr |= ((uint64_t)data & 0xfffff) << 20;
629 msr |= 0x000fffff & ~(ac97_bar_size - 1);
630 wrmsr(GLIU_IOD_BM1, msr);
631 } else {
632 wrmsr(GLIU_IOD_BM1, 0);
633 }
634 ac97_bar_value = 0;
635 }
636 break;
637 }
638 }
639
640 /*
641 * Function 4: OHCI Controller
642 */
643
644 static pcireg_t ohci_bar_size = 0x1000;
645 static pcireg_t ohci_bar_value;
646
647 pcireg_t
glx_fn4_read(int reg)648 glx_fn4_read(int reg)
649 {
650 uint64_t msr;
651 pcireg_t data;
652
653 switch (reg) {
654 case PCI_ID_REG:
655 case PCI_SUBSYS_ID_REG:
656 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_OHCI);
657 break;
658 case PCI_COMMAND_STATUS_REG:
659 data = glx_get_status();
660 msr = rdmsr(USB_MSR_OHCB);
661 if (msr & (1UL << 34))
662 data |= PCI_COMMAND_MASTER_ENABLE;
663 if (msr & (1UL << 33))
664 data |= PCI_COMMAND_MEM_ENABLE;
665 break;
666 case PCI_CLASS_REG:
667 msr = rdmsr(USB_GLD_MSR_CAP);
668 data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
669 (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
670 (PCI_INTERFACE_OHCI << PCI_INTERFACE_SHIFT) |
671 (msr & PCI_REVISION_MASK);
672 break;
673 case PCI_BHLC_REG:
674 msr = rdmsr(GLPCI_CTRL);
675 data = (0x00 << PCI_HDRTYPE_SHIFT) |
676 (((msr & 0xff00000000UL) >> 32) << PCI_LATTIMER_SHIFT) |
677 (0x08 << PCI_CACHELINE_SHIFT);
678 break;
679 case PCI_MAPREG_START + 0x00:
680 data = ohci_bar_value;
681 if (data == 0xffffffff)
682 data = PCI_MAPREG_MEM_ADDR_MASK & ~(ohci_bar_size - 1);
683 else {
684 msr = rdmsr(USB_MSR_OHCB);
685 data = msr & 0xffffff00;
686 }
687 if (data != 0)
688 data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
689 break;
690 case PCI_CAPLISTPTR_REG:
691 data = 0x40;
692 break;
693 case PCI_INTERRUPT_REG:
694 data = (0x40 << PCI_MAX_LAT_SHIFT) |
695 (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
696 break;
697 case 0x40: /* USB capability pointer */
698 data = 0;
699 break;
700 default:
701 data = 0;
702 break;
703 }
704
705 return data;
706 }
707
708 void
glx_fn4_write(int reg,pcireg_t data)709 glx_fn4_write(int reg, pcireg_t data)
710 {
711 uint64_t msr;
712
713 switch (reg) {
714 case PCI_COMMAND_STATUS_REG:
715 msr = rdmsr(USB_MSR_OHCB);
716 if (data & PCI_COMMAND_MASTER_ENABLE)
717 msr |= 1UL << 34;
718 else
719 msr &= ~(1UL << 34);
720 if (data & PCI_COMMAND_MEM_ENABLE)
721 msr |= 1UL << 33;
722 else
723 msr &= ~(1UL << 33);
724 wrmsr(USB_MSR_OHCB, msr);
725 break;
726 case PCI_BHLC_REG:
727 msr = rdmsr(GLPCI_CTRL);
728 msr &= 0xff00000000UL;
729 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
730 break;
731 case PCI_MAPREG_START + 0x00:
732 if (data == 0xffffffff) {
733 ohci_bar_value = data;
734 } else {
735 if ((data & PCI_MAPREG_TYPE_MASK) ==
736 PCI_MAPREG_TYPE_MEM) {
737 data &= PCI_MAPREG_MEM_ADDR_MASK;
738 msr = rdmsr(GLIU_P2D_BM3);
739 msr &= 0x0fffff0000000000UL;
740 msr |= 2UL << 61; /* USB */
741 msr |= (((uint64_t)data) >> 12) << 20;
742 msr |= 0x000fffff;
743 wrmsr(GLIU_P2D_BM3, msr);
744
745 msr = rdmsr(USB_MSR_OHCB);
746 msr &= ~0xffffff00UL;
747 msr |= data;
748 } else {
749 msr = rdmsr(USB_MSR_OHCB);
750 msr &= ~0xffffff00UL;
751 }
752 wrmsr(USB_MSR_OHCB, msr);
753 ohci_bar_value = 0;
754 }
755 break;
756 default:
757 break;
758 }
759 }
760
761 /*
762 * Function 5: EHCI Controller
763 */
764
765 static pcireg_t ehci_bar_size = 0x1000;
766 static pcireg_t ehci_bar_value;
767
768 pcireg_t
glx_fn5_read(int reg)769 glx_fn5_read(int reg)
770 {
771 uint64_t msr;
772 pcireg_t data;
773
774 switch (reg) {
775 case PCI_ID_REG:
776 case PCI_SUBSYS_ID_REG:
777 data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_EHCI);
778 break;
779 case PCI_COMMAND_STATUS_REG:
780 data = glx_get_status();
781 msr = rdmsr(USB_MSR_EHCB);
782 if (msr & (1UL << 34))
783 data |= PCI_COMMAND_MASTER_ENABLE;
784 if (msr & (1UL << 33))
785 data |= PCI_COMMAND_MEM_ENABLE;
786 break;
787 case PCI_CLASS_REG:
788 msr = rdmsr(USB_GLD_MSR_CAP);
789 data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
790 (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
791 (PCI_INTERFACE_EHCI << PCI_INTERFACE_SHIFT) |
792 (msr & PCI_REVISION_MASK);
793 break;
794 case PCI_BHLC_REG:
795 msr = rdmsr(GLPCI_CTRL);
796 data = (0x00 << PCI_HDRTYPE_SHIFT) |
797 (((msr & 0xff00000000UL) >> 32) << PCI_LATTIMER_SHIFT) |
798 (0x08 << PCI_CACHELINE_SHIFT);
799 break;
800 case PCI_MAPREG_START + 0x00:
801 data = ehci_bar_value;
802 if (data == 0xffffffff)
803 data = PCI_MAPREG_MEM_ADDR_MASK & ~(ehci_bar_size - 1);
804 else {
805 msr = rdmsr(USB_MSR_EHCB);
806 data = msr & 0xffffff00;
807 }
808 if (data != 0)
809 data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
810 break;
811 case PCI_CAPLISTPTR_REG:
812 data = 0x40;
813 break;
814 case PCI_INTERRUPT_REG:
815 data = (0x40 << PCI_MAX_LAT_SHIFT) |
816 (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
817 break;
818 case 0x40: /* USB capability pointer */
819 data = 0;
820 break;
821 case PCI_USBREV:
822 msr = rdmsr(USB_MSR_EHCB);
823 data = PCI_USBREV_2_0;
824 data |= ((msr >> 40) & 0x3f) << 8; /* PCI_EHCI_FLADJ */
825 break;
826 default:
827 data = 0;
828 break;
829 }
830
831 return data;
832 }
833
834 void
glx_fn5_write(int reg,pcireg_t data)835 glx_fn5_write(int reg, pcireg_t data)
836 {
837 uint64_t msr;
838
839 switch (reg) {
840 case PCI_COMMAND_STATUS_REG:
841 msr = rdmsr(USB_MSR_EHCB);
842 if (data & PCI_COMMAND_MASTER_ENABLE)
843 msr |= 1UL << 34;
844 else
845 msr &= ~(1UL << 34);
846 if (data & PCI_COMMAND_MEM_ENABLE)
847 msr |= 1UL << 33;
848 else
849 msr &= ~(1UL << 33);
850 wrmsr(USB_MSR_EHCB, msr);
851 break;
852 case PCI_BHLC_REG:
853 msr = rdmsr(GLPCI_CTRL);
854 msr &= 0xff00000000UL;
855 msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
856 break;
857 case PCI_MAPREG_START + 0x00:
858 if (data == 0xffffffff) {
859 ehci_bar_value = data;
860 } else {
861 if ((data & PCI_MAPREG_TYPE_MASK) ==
862 PCI_MAPREG_TYPE_MEM) {
863 data &= PCI_MAPREG_MEM_ADDR_MASK;
864 msr = rdmsr(GLIU_P2D_BM4);
865 msr &= 0x0fffff0000000000UL;
866 msr |= 2UL << 61; /* USB */
867 msr |= (((uint64_t)data) >> 12) << 20;
868 msr |= 0x000fffff;
869 wrmsr(GLIU_P2D_BM4, msr);
870
871 msr = rdmsr(USB_MSR_EHCB);
872 msr &= ~0xffffff00UL;
873 msr |= data;
874 } else {
875 msr = rdmsr(USB_MSR_EHCB);
876 msr &= ~0xffffff00UL;
877 }
878 wrmsr(USB_MSR_EHCB, msr);
879 ehci_bar_value = 0;
880 }
881 break;
882 default:
883 break;
884 }
885 }
886