xref: /openbsd/sys/arch/loongson/dev/glx.c (revision 32ffafad)
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