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