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