xref: /netbsd-src/sys/arch/evbmips/loongson/dev/glx.c (revision fa28c6faa16e0b00edee7acdcaf4899797043def)
1 /*	$NetBSD: glx.c,v 1.5 2015/10/02 05:22:50 msaitoh Exp $	*/
2 /*	$OpenBSD: glx.c,v 1.6 2010/10/14 21:23:04 pirofti Exp $	*/
3 
4 /*
5  * Copyright (c) 2009 Miodrag Vallat.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * AMD CS5536 PCI Mess
22  * XXX too many hardcoded numbers... need to expand glxreg.h
23  */
24 #include <sys/cdefs.h>
25 __KERNEL_RCSID(0, "$NetBSD: glx.c,v 1.5 2015/10/02 05:22:50 msaitoh Exp $");
26 
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/device.h>
30 
31 #include <evbmips/loongson/autoconf.h>
32 
33 #include <dev/pci/pcireg.h>
34 #include <dev/pci/pcivar.h>
35 #include <dev/pci/pcidevs.h>
36 
37 #include <dev/pci/pciidereg.h>
38 #include <dev/usb/usb.h>
39 #include <dev/usb/ohcireg.h>
40 #include <dev/usb/ehcireg.h>
41 
42 #include <mips/bonito/bonitoreg.h>
43 #include <mips/bonito/bonitovar.h>
44 
45 #include <evbmips/loongson/dev/glxreg.h>
46 #include <evbmips/loongson/dev/glxvar.h>
47 
48 #ifdef GLX_DEBUG
49 #define DPRINTF(x) printf x
50 #else
51 #define DPRINTF(x)
52 #endif
53 
54 /*
55  * Since the purpose of this code is to present a different view of the
56  * PCI configuration space, it can not attach as a real device.
57  * (well it could, and then we'd have to attach a fake pci to it,
58  * and fake the configuration space accesses anyways - is it worth doing?)
59  *
60  * We just keep the `would-be softc' structure as global variables.
61  */
62 
63 static pci_chipset_tag_t	glxbase_pc;
64 static pcitag_t			glxbase_tag;
65 static int			glxbase_dev;
66 
67 /* MSR access through PCI configuration space */
68 #define	PCI_MSR_CTRL		0x00f0
69 #define	PCI_MSR_ADDR		0x00f4
70 #define	PCI_MSR_LO32		0x00f8
71 #define	PCI_MSR_HI32		0x00fc
72 
73 /* access to the MSR through the PCI mailbox needs the same transformation
74  * as done by hardware when a MSR request reaches the CS5536.
75  */
76 #define GLX_MSR_ADDR_TARGET	0x00003fff
77 #define GLX_MSR_ADDR_RF		0xffffc000
78 #define GLX_MSR_ADDR_RF_SHIFT	9
79 
80 static uint glx_msra2mbxa(uint);
81 static uint
82 glx_msra2mbxa(uint msr)
83 {
84 	uint rf = (msr & GLX_MSR_ADDR_RF);
85 	return ((rf << GLX_MSR_ADDR_RF_SHIFT) | (msr & GLX_MSR_ADDR_TARGET));
86 }
87 
88 pcireg_t glx_pci_read_hook(void *, pcitag_t, int);
89 void	glx_pci_write_hook(void *, pcitag_t, int, pcireg_t);
90 
91 pcireg_t glx_get_status(void);
92 pcireg_t glx_fn0_read(int);
93 void	glx_fn0_write(int, pcireg_t);
94 pcireg_t glx_fn2_read(int);
95 void	glx_fn2_write(int, pcireg_t);
96 pcireg_t glx_fn3_read(int);
97 void	glx_fn3_write(int, pcireg_t);
98 pcireg_t glx_fn4_read(int);
99 void	glx_fn4_write(int, pcireg_t);
100 pcireg_t glx_fn5_read(int);
101 void	glx_fn5_write(int, pcireg_t);
102 pcireg_t glx_fn6_read(int);
103 void	glx_fn6_write(int, pcireg_t);
104 pcireg_t glx_fn7_read(int);
105 void	glx_fn7_write(int, pcireg_t);
106 
107 pcireg_t (*gen_pci_conf_read)(void *, pcitag_t, int);
108 void (*gen_pci_conf_write)(void *, pcitag_t, int, pcireg_t);
109 
110 void
111 glx_init(pci_chipset_tag_t pc, pcitag_t tag, int dev)
112 {
113 	uint64_t msr;
114 
115 	glxbase_pc = pc;
116 	glxbase_dev = dev;
117 	glxbase_tag = tag;
118 
119 	/*
120 	 * Register PCI configuration hooks to make the various
121 	 * embedded devices visible as PCI subfunctions.
122 	 */
123 
124 	gen_pci_conf_read = pc->pc_conf_read;
125 	pc->pc_conf_read = glx_pci_read_hook;
126 	gen_pci_conf_write = pc->pc_conf_write;
127 	pc->pc_conf_write = glx_pci_write_hook;
128 
129 	/*
130 	 * Perform some Geode intialization.
131 	 */
132 
133 	msr = rdmsr(GCSC_DIVIL_BALL_OPTS);	/* 0x71 */
134 	wrmsr(GCSC_DIVIL_BALL_OPTS, msr | 0x01);
135 
136 	/*
137 	 * Route usb and audio
138 	 */
139 	msr = 0;
140 	msr |= 11 << 8;
141 	msr |= 9 << 16;
142 	wrmsr(GCSC_PIC_YSEL_LOW, msr);
143 
144 	/*
145 	 * serial interrupts
146 	 */
147 	msr = 0;
148 	msr |= 4 << 24;
149 	msr |= 3 << 28;
150 	wrmsr(GCSC_PIC_YSEL_HIGH, msr);
151 
152 	/*
153 	 * and IDE
154 	 */
155 	msr = 0;
156 	msr |= 1 << 14;
157 	wrmsr(GCSC_PIC_IRQM_PRIM, msr);
158 
159 	/*
160 	 * keyboard and mouse interrupts
161 	 */
162 	msr = 0;
163 	msr |= 1 << 1;	/* keyboard */
164 	msr |= 1 << 12;	/* mouse */
165 	wrmsr(GCSC_PIC_IRQM_LPC, msr);
166 
167 	/* no interrupts from theses */
168 	wrmsr(GCSC_PIC_ZSEL_LOW, 0);
169 	wrmsr(GCSC_PIC_ZSEL_HIGH, 0);
170 
171 	DPRINTF(("IO space 0x%" PRIx64 "\n", rdmsr(0x80000014)));
172 }
173 
174 uint64_t
175 rdmsr(uint msr)
176 {
177 	uint64_t lo, hi;
178 	int s;
179 
180 #ifdef DIAGNOSTIC
181 	if (glxbase_tag == 0)
182 		panic("rdmsr invoked before glx initialization");
183 #endif
184 
185 	s = splhigh();
186 	pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_ADDR,
187 	    glx_msra2mbxa(msr));
188 	lo = (uint32_t)pci_conf_read(glxbase_pc, glxbase_tag, PCI_MSR_LO32);
189 	hi = (uint32_t)pci_conf_read(glxbase_pc, glxbase_tag, PCI_MSR_HI32);
190 	splx(s);
191 	return (hi << 32) | lo;
192 }
193 
194 void
195 wrmsr(uint msr, uint64_t value)
196 {
197 	int s;
198 
199 #ifdef DIAGNOSTIC
200 	if (glxbase_tag == 0)
201 		panic("wrmsr invoked before glx initialization");
202 #endif
203 
204 	s = splhigh();
205 	pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_ADDR,
206 	    glx_msra2mbxa(msr));
207 	pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_LO32, (uint32_t)value);
208 	pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_HI32, value >> 32);
209 	splx(s);
210 }
211 
212 pcireg_t
213 glx_pci_read_hook(void *v, pcitag_t tag, int offset)
214 {
215 	int bus, dev, fn;
216 	pcireg_t data;
217 
218 	if ((unsigned int)offset >= PCI_CONF_SIZE)
219 		return (pcireg_t) -1;
220 
221 	/*
222 	 * Do not get in the way of MSR programming
223 	 */
224 	if (tag == glxbase_tag && offset >= PCI_MSR_CTRL)
225 		return gen_pci_conf_read(v, tag, offset);
226 
227 	pci_decompose_tag(glxbase_pc, tag, &bus, &dev, &fn);
228 	if (bus != 0 || dev != glxbase_dev)
229 		return gen_pci_conf_read(v, tag, offset);
230 
231 	data = 0;
232 
233 	switch (fn) {
234 	case 0:	/* PCI-ISA bridge */
235 		data = glx_fn0_read(offset);
236 		break;
237 	case 1:	/* Flash memory */
238 		break;
239 	case 2:	/* IDE controller */
240 		data = glx_fn2_read(offset);
241 		break;
242 	case 3:	/* AC97 codec */
243 		data = glx_fn3_read(offset);
244 		break;
245 	case 4:	/* OHCI controller */
246 		data = glx_fn4_read(offset);
247 		break;
248 	case 5:	/* EHCI controller */
249 		data = glx_fn5_read(offset);
250 		break;
251 	case 6:	/* UDC */
252 		break;
253 	case 7:	/* OTG */
254 		break;
255 	}
256 
257 	return data;
258 }
259 
260 void
261 glx_pci_write_hook(void *v, pcitag_t tag,
262     int offset, pcireg_t data)
263 {
264 	int bus, dev, fn;
265 
266 	if ((unsigned int)offset >= PCI_CONF_SIZE)
267 		return;
268 
269 	/*
270 	 * Do not get in the way of MSR programming
271 	 */
272 	if (tag == glxbase_tag && offset >= PCI_MSR_CTRL) {
273 		gen_pci_conf_write(v, tag, offset, data);
274 		return;
275 	}
276 
277 
278 	pci_decompose_tag(glxbase_pc, tag, &bus, &dev, &fn);
279 	if (bus != 0 || dev != glxbase_dev) {
280 		gen_pci_conf_write(v, tag, offset, data);
281 		return;
282 	}
283 
284 	switch (fn) {
285 	case 0:	/* PCI-ISA bridge */
286 		glx_fn0_write(offset, data);
287 		break;
288 	case 1:	/* Flash memory */
289 		break;
290 	case 2:	/* IDE controller */
291 		glx_fn2_write(offset, data);
292 		break;
293 	case 3:	/* AC97 codec */
294 		glx_fn3_write(offset, data);
295 		break;
296 	case 4:	/* OHCI controller */
297 		glx_fn4_write(offset, data);
298 		break;
299 	case 5:	/* EHCI controller */
300 		glx_fn5_write(offset, data);
301 		break;
302 	case 6:	/* USB UDC */
303 		break;
304 	case 7:	/* USB OTG */
305 		break;
306 	}
307 }
308 
309 pcireg_t
310 glx_get_status(void)
311 {
312 	uint64_t msr;
313 	pcireg_t data;
314 
315 	data = 0;
316 	msr = rdmsr(GCSC_GLPCI_GLD_MSR_ERROR);
317 	if (msr & (1UL << 5))
318 		data |= PCI_COMMAND_PARITY_ENABLE;
319 	data |= PCI_STATUS_66MHZ_SUPPORT |
320 	    PCI_STATUS_BACKTOBACK_SUPPORT | PCI_STATUS_DEVSEL_MEDIUM;
321 	if (msr & (1UL << 21))
322 		data |= PCI_STATUS_PARITY_DETECT;
323 	if (msr & (1UL << 20))
324 		data |= PCI_STATUS_TARGET_TARGET_ABORT;
325 	if (msr & (1UL << 17))
326 		data |= PCI_STATUS_MASTER_TARGET_ABORT;
327 	if (msr & (1UL << 16))
328 		data |= PCI_STATUS_MASTER_ABORT;
329 
330 	return data;
331 }
332 
333 /*
334  * Function 0: PCI-ISA bridge
335  */
336 
337 static const pcireg_t pcib_bar_sizes[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4] = {
338 	0x008,
339 	0x100,
340 	0x040,
341 	0x020,
342 	0x080,
343 	0x020
344 };
345 
346 static pcireg_t pcib_bar_values[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4];
347 
348 static const uint64_t pcib_bar_msr[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4] = {
349 	GCSC_DIVIL_LBAR_SMB,
350 	GCSC_DIVIL_LBAR_GPIO,
351 	GCSC_DIVIL_LBAR_MFGPT,
352 	GCSC_DIVIL_LBAR_IRQ,
353 	GCSC_DIVIL_LBAR_PMS,
354 	GCSC_DIVIL_LBAR_ACPI
355 };
356 
357 pcireg_t
358 glx_fn0_read(int reg)
359 {
360 	uint64_t msr;
361 	pcireg_t data;
362 	int index;
363 
364 	switch (reg) {
365 	case PCI_ID_REG:
366 	case PCI_SUBSYS_ID_REG:
367 		data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_PCIB);
368 		break;
369 	case PCI_COMMAND_STATUS_REG:
370 		data = glx_get_status();
371 		data |= PCI_COMMAND_MASTER_ENABLE;
372 		msr = rdmsr(GCSC_DIVIL_LBAR_SMB);
373 		if (msr & (1ULL << 32))
374 			data |= PCI_COMMAND_IO_ENABLE;
375 		break;
376 	case PCI_CLASS_REG:
377 		msr = rdmsr(GCSC_GLCP_CHIP_REV_ID);
378 		data = (PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT) |
379 		    (PCI_SUBCLASS_BRIDGE_ISA << PCI_SUBCLASS_SHIFT) |
380 		    (msr & PCI_REVISION_MASK);
381 		break;
382 	case PCI_BHLC_REG:
383 		msr = rdmsr(GCSC_GLPCI_CTRL);
384 		data = (0x80 << PCI_HDRTYPE_SHIFT) |
385 		    (((msr & 0xff00000000UL) >> 32) << PCI_LATTIMER_SHIFT) |
386 		    (0x08 << PCI_CACHELINE_SHIFT);
387 		break;
388 	case PCI_MAPREG_START + 0x00:
389 	case PCI_MAPREG_START + 0x04:
390 	case PCI_MAPREG_START + 0x08:
391 	case PCI_MAPREG_START + 0x0c:
392 	case PCI_MAPREG_START + 0x10:
393 	case PCI_MAPREG_START + 0x14:
394 	case PCI_MAPREG_START + 0x18:
395 		index = (reg - PCI_MAPREG_START) / 4;
396 		if (pcib_bar_msr[index] == 0)
397 			data = 0;
398 		else {
399 			data = pcib_bar_values[index];
400 			if (data == 0xffffffff)
401 				data = PCI_MAPREG_IO_ADDR_MASK;
402 			else
403 				data = (pcireg_t)rdmsr(pcib_bar_msr[index]);
404 			data &= ~(pcib_bar_sizes[index] - 1);
405 			if (data != 0)
406 				data |= PCI_MAPREG_TYPE_IO;
407 		}
408 		break;
409 	case PCI_INTERRUPT_REG:
410 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
411 		    (PCI_INTERRUPT_PIN_NONE << PCI_INTERRUPT_PIN_SHIFT);
412 		break;
413 	default:
414 		data = 0;
415 		break;
416 	}
417 
418 	return data;
419 }
420 
421 void
422 glx_fn0_write(int reg, pcireg_t data)
423 {
424 	uint64_t msr;
425 	int index;
426 
427 	switch (reg) {
428 	case PCI_COMMAND_STATUS_REG:
429 		for (index = 0; index < __arraycount(pcib_bar_msr); index++) {
430 			if (pcib_bar_msr[index] == 0)
431 				continue;
432 			msr = rdmsr(pcib_bar_msr[index]);
433 			if (data & PCI_COMMAND_IO_ENABLE)
434 				msr |= 1ULL << 32;
435 			else
436 				msr &= ~(1ULL << 32);
437 			wrmsr(pcib_bar_msr[index], msr);
438 		}
439 
440 		msr = rdmsr(GCSC_GLPCI_GLD_MSR_ERROR);
441 		if (data & PCI_COMMAND_PARITY_ENABLE)
442 			msr |= 1ULL << 5;
443 		else
444 			msr &= ~(1ULL << 5);
445 		wrmsr(GCSC_GLPCI_GLD_MSR_ERROR, msr);
446 		break;
447 	case PCI_BHLC_REG:
448 		msr = rdmsr(GCSC_GLPCI_CTRL);
449 		msr &= 0xff00000000ULL;
450 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
451 		break;
452 	case PCI_MAPREG_START + 0x00:
453 	case PCI_MAPREG_START + 0x04:
454 	case PCI_MAPREG_START + 0x08:
455 	case PCI_MAPREG_START + 0x0c:
456 	case PCI_MAPREG_START + 0x10:
457 	case PCI_MAPREG_START + 0x14:
458 	case PCI_MAPREG_START + 0x18:
459 		index = (reg - PCI_MAPREG_START) / 4;
460 		if (data == 0xffffffff) {
461 			pcib_bar_values[index] = data;
462 		} else if (pcib_bar_msr[index] != 0) {
463 			if ((data & PCI_MAPREG_TYPE_MASK) ==
464 			    PCI_MAPREG_TYPE_IO) {
465 				data &= PCI_MAPREG_IO_ADDR_MASK;
466 				data &= ~(pcib_bar_sizes[index] - 1);
467 				wrmsr(pcib_bar_msr[index],
468 				    (0x0000f000ULL << 32) | (1ULL << 32) | data);
469 			} else {
470 				wrmsr(pcib_bar_msr[index], 0ULL);
471 			}
472 			pcib_bar_values[index] = 0;
473 		}
474 		break;
475 	}
476 }
477 
478 /*
479  * Function 2: IDE Controller
480  */
481 
482 static pcireg_t pciide_bar_size = 0x10;
483 static pcireg_t pciide_bar_value;
484 
485 pcireg_t
486 glx_fn2_read(int reg)
487 {
488 	uint64_t msr;
489 	pcireg_t data;
490 
491 	switch (reg) {
492 	case PCI_ID_REG:
493 	case PCI_SUBSYS_ID_REG:
494 		data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_IDE);
495 		break;
496 	case PCI_COMMAND_STATUS_REG:
497 		data = glx_get_status();
498 		data |= PCI_COMMAND_IO_ENABLE;
499 		msr = rdmsr(GCSC_GLIU_PAE);
500 		if ((msr & (0x3 << 4)) == (0x3 << 4))
501 			data |= PCI_COMMAND_MASTER_ENABLE;
502 		break;
503 	case PCI_CLASS_REG:
504 		msr = rdmsr(GCSC_IDE_GLD_MSR_CAP);
505 		data = (PCI_CLASS_MASS_STORAGE << PCI_CLASS_SHIFT) |
506 		    (PCI_SUBCLASS_MASS_STORAGE_IDE << PCI_SUBCLASS_SHIFT) |
507 		    (PCIIDE_INTERFACE_BUS_MASTER_DMA << PCI_INTERFACE_SHIFT) |
508 		    (msr & PCI_REVISION_MASK);
509 		break;
510 	case PCI_BHLC_REG:
511 		msr = rdmsr(GCSC_GLPCI_CTRL);
512 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
513 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
514 		    (0x08 << PCI_CACHELINE_SHIFT);
515 		break;
516 	case PCI_MAPREG_START + 0x10:
517 		data = pciide_bar_value;
518 		if (data == 0xffffffff)
519 			data = PCI_MAPREG_IO_ADDR_MASK & ~(pciide_bar_size - 1);
520 		else {
521 			msr = rdmsr(GCSC_IDE_IO_BAR);
522 			data = msr & 0xfffffff0;
523 		}
524 		if (data != 0)
525 			data |= PCI_MAPREG_TYPE_IO;
526 		break;
527 	case PCI_INTERRUPT_REG:
528 		/* compat mode */
529 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
530 		    (PCI_INTERRUPT_PIN_NONE << PCI_INTERRUPT_PIN_SHIFT);
531 		break;
532 	/*
533 	 * The following registers are used by pciide(4)
534 	 */
535 	case PCIIDE_CHANSTATUS_EN:
536 		data = rdmsr(GCSC_IDE_CFG);
537 		break;
538 	case /* AMD756_DATATIM XXX */ 0x48:
539 		data = rdmsr(GCSC_IDE_DTC);
540 		break;
541 	case /* AMD756_UDMA XXX*/ 0x50:
542 		data = rdmsr(GCSC_IDE_ETC);
543 		break;
544 	default:
545 		DPRINTF(("unimplemented pciide reg 0x%x\n", reg));
546 		data = 0;
547 		break;
548 	}
549 
550 	return data;
551 }
552 
553 void
554 glx_fn2_write(int reg, pcireg_t data)
555 {
556 	uint64_t msr;
557 
558 	switch (reg) {
559 	case PCI_COMMAND_STATUS_REG:
560 		msr = rdmsr(GCSC_GLIU_PAE);
561 		if (data & PCI_COMMAND_MASTER_ENABLE)
562 			msr |= 0x03 << 4;
563 		else
564 			msr &= ~(0x03 << 4);
565 		wrmsr(GCSC_GLIU_PAE, msr);
566 		break;
567 	case PCI_BHLC_REG:
568 		msr = rdmsr(GCSC_GLPCI_CTRL);
569 		msr &= 0xff00000000ULL;
570 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
571 		break;
572 	case PCI_MAPREG_START + 0x10:
573 		if (data == 0xffffffff) {
574 			pciide_bar_value = data;
575 		} else {
576 			if ((data & PCI_MAPREG_TYPE_MASK) ==
577 			    PCI_MAPREG_TYPE_IO) {
578 				data &= PCI_MAPREG_IO_ADDR_MASK;
579 				msr = (uint32_t)data & 0xfffffff0;
580 				wrmsr(GCSC_IDE_IO_BAR, msr);
581 			} else {
582 				wrmsr(GCSC_IDE_IO_BAR, 0);
583 			}
584 			pciide_bar_value = 0;
585 		}
586 		break;
587 	/*
588 	 * The following registers are used by pciide(4)
589 	 */
590 	case PCIIDE_CHANSTATUS_EN:
591 		wrmsr(GCSC_IDE_CFG, (uint32_t)data);
592 		break;
593 	case /* AMD756_DATATIM XXX */ 0x48:
594 		wrmsr(GCSC_IDE_DTC, (uint32_t)data);
595 		break;
596 	case /* AMD756_UDMA XXX*/ 0x50:
597 		wrmsr(GCSC_IDE_ETC, (uint32_t)data);
598 		break;
599 	default:
600 		DPRINTF(("unimplemented pciide reg 0x%x\n", reg));
601 	}
602 }
603 
604 /*
605  * Function 3: AC97 Codec
606  */
607 
608 static pcireg_t ac97_bar_size = 0x80;
609 static pcireg_t ac97_bar_value;
610 
611 pcireg_t
612 glx_fn3_read(int reg)
613 {
614 	uint64_t msr;
615 	pcireg_t data;
616 
617 	switch (reg) {
618 	case PCI_ID_REG:
619 	case PCI_SUBSYS_ID_REG:
620 		data = PCI_ID_CODE(PCI_VENDOR_AMD,
621 		    PCI_PRODUCT_AMD_CS5536_AUDIO);
622 		break;
623 	case PCI_COMMAND_STATUS_REG:
624 		data = glx_get_status();
625 		data |= PCI_COMMAND_IO_ENABLE;
626 		msr = rdmsr(GCSC_GLIU_PAE);
627 		if ((msr & (0x3 << 8)) == (0x3 << 8))
628 			data |= PCI_COMMAND_MASTER_ENABLE;
629 		break;
630 	case PCI_CLASS_REG:
631 		msr = rdmsr(GCSC_ACC_GLD_MSR_CAP);
632 		data = (PCI_CLASS_MULTIMEDIA << PCI_CLASS_SHIFT) |
633 		    (PCI_SUBCLASS_MULTIMEDIA_AUDIO << PCI_SUBCLASS_SHIFT) |
634 		    (msr & PCI_REVISION_MASK);
635 		break;
636 	case PCI_BHLC_REG:
637 		msr = rdmsr(GCSC_GLPCI_CTRL);
638 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
639 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
640 		    (0x08 << PCI_CACHELINE_SHIFT);
641 		break;
642 	case PCI_MAPREG_START:
643 		data = ac97_bar_value;
644 		if (data == 0xffffffff)
645 			data = PCI_MAPREG_IO_ADDR_MASK & ~(ac97_bar_size - 1);
646 		else {
647 			msr = rdmsr(GCSC_GLIU_IOD_BM1);
648 			data = (msr >> 20) & 0x000fffff;
649 			data &= (msr & 0x000fffff);
650 		}
651 		if (data != 0)
652 			data |= PCI_MAPREG_TYPE_IO;
653 		break;
654 	case PCI_INTERRUPT_REG:
655 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
656 		    (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
657 		break;
658 	default:
659 		data = 0;
660 		break;
661 	}
662 
663 	return data;
664 }
665 
666 void
667 glx_fn3_write(int reg, pcireg_t data)
668 {
669 	uint64_t msr;
670 
671 	switch (reg) {
672 	case PCI_COMMAND_STATUS_REG:
673 		msr = rdmsr(GCSC_GLIU_PAE);
674 		if (data & PCI_COMMAND_MASTER_ENABLE)
675 			msr |= 0x03 << 8;
676 		else
677 			msr &= ~(0x03 << 8);
678 		wrmsr(GCSC_GLIU_PAE, msr);
679 		break;
680 	case PCI_BHLC_REG:
681 		msr = rdmsr(GCSC_GLPCI_CTRL);
682 		msr &= 0xff00000000ULL;
683 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
684 		break;
685 	case PCI_MAPREG_START:
686 		if (data == 0xffffffff) {
687 			ac97_bar_value = data;
688 		} else {
689 			if ((data & PCI_MAPREG_TYPE_MASK) ==
690 			    PCI_MAPREG_TYPE_IO) {
691 				data &= PCI_MAPREG_IO_ADDR_MASK;
692 				msr = rdmsr(GCSC_GLIU_IOD_BM1);
693 				msr &= 0x0fffff0000000000ULL;
694 				msr |= 5ULL << 61;	/* AC97 */
695 				msr |= ((uint64_t)data & 0xfffff) << 20;
696 				msr |= 0x000fffff & ~(ac97_bar_size - 1);
697 				wrmsr(GCSC_GLIU_IOD_BM1, msr);
698 			} else {
699 				wrmsr(GCSC_GLIU_IOD_BM1, 0);
700 			}
701 			ac97_bar_value = 0;
702 		}
703 		break;
704 	}
705 }
706 
707 /*
708  * Function 4: OHCI Controller
709  */
710 
711 static pcireg_t ohci_bar_size = 0x1000;
712 static pcireg_t ohci_bar_value;
713 
714 pcireg_t
715 glx_fn4_read(int reg)
716 {
717 	uint64_t msr;
718 	pcireg_t data;
719 
720 	switch (reg) {
721 	case PCI_ID_REG:
722 	case PCI_SUBSYS_ID_REG:
723 		data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_OHCI);
724 		break;
725 	case PCI_COMMAND_STATUS_REG:
726 		data = glx_get_status();
727 		msr = rdmsr(GCSC_USB_MSR_OHCB);
728 		if (msr & (1ULL << 34))
729 			data |= PCI_COMMAND_MASTER_ENABLE;
730 		if (msr & (1ULL << 33))
731 			data |= PCI_COMMAND_MEM_ENABLE;
732 		break;
733 	case PCI_CLASS_REG:
734 		msr = rdmsr(GCSC_USB_GLD_MSR_CAP);
735 		data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
736 		    (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
737 		    (PCI_INTERFACE_OHCI << PCI_INTERFACE_SHIFT) |
738 		    (msr & PCI_REVISION_MASK);
739 		break;
740 	case PCI_BHLC_REG:
741 		msr = rdmsr(GCSC_GLPCI_CTRL);
742 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
743 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
744 		    (0x08 << PCI_CACHELINE_SHIFT);
745 		break;
746 	case PCI_MAPREG_START + 0x00:
747 		data = ohci_bar_value;
748 		if (data == 0xffffffff)
749 			data = PCI_MAPREG_MEM_ADDR_MASK & ~(ohci_bar_size - 1);
750 		else {
751 			msr = rdmsr(GCSC_USB_MSR_OHCB);
752 			data = msr & 0xffffff00;
753 		}
754 		if (data != 0)
755 			data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
756 		break;
757 	case PCI_CAPLISTPTR_REG:
758 		data = 0x40;
759 		break;
760 	case PCI_INTERRUPT_REG:
761 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
762 		    (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
763 		break;
764 	case 0x40:	/* USB capability pointer */
765 		data = 0;
766 		break;
767 	default:
768 		data = 0;
769 		break;
770 	}
771 
772 	return data;
773 }
774 
775 void
776 glx_fn4_write(int reg, pcireg_t data)
777 {
778 	uint64_t msr;
779 
780 	switch (reg) {
781 	case PCI_COMMAND_STATUS_REG:
782 		msr = rdmsr(GCSC_USB_MSR_OHCB);
783 		if (data & PCI_COMMAND_MASTER_ENABLE)
784 			msr |= 1ULL << 34;
785 		else
786 			msr &= ~(1ULL << 34);
787 		if (data & PCI_COMMAND_MEM_ENABLE)
788 			msr |= 1ULL << 33;
789 		else
790 			msr &= ~(1ULL << 33);
791 		wrmsr(GCSC_USB_MSR_OHCB, msr);
792 		break;
793 	case PCI_BHLC_REG:
794 		msr = rdmsr(GCSC_GLPCI_CTRL);
795 		msr &= 0xff00000000ULL;
796 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
797 		break;
798 	case PCI_MAPREG_START + 0x00:
799 		if (data == 0xffffffff) {
800 			ohci_bar_value = data;
801 		} else {
802 			if ((data & PCI_MAPREG_TYPE_MASK) ==
803 			    PCI_MAPREG_TYPE_MEM) {
804 				data &= PCI_MAPREG_MEM_ADDR_MASK;
805 				msr = rdmsr(GCSC_GLIU_P2D_BM3);
806 				msr &= 0x0fffff0000000000ULL;
807 				msr |= 2ULL << 61;	/* USB */
808 				msr |= (((uint64_t)data) >> 12) << 20;
809 				msr |= 0x000fffff;
810 				wrmsr(GCSC_GLIU_P2D_BM3, msr);
811 
812 				msr = rdmsr(GCSC_USB_MSR_OHCB);
813 				msr &= ~0xffffff00ULL;
814 				msr |= data;
815 			} else {
816 				msr = rdmsr(GCSC_USB_MSR_OHCB);
817 				msr &= ~0xffffff00ULL;
818 			}
819 			wrmsr(GCSC_USB_MSR_OHCB, msr);
820 			ohci_bar_value = 0;
821 		}
822 		break;
823 	default:
824 		break;
825 	}
826 }
827 
828 /*
829  * Function 5: EHCI Controller
830  */
831 
832 static pcireg_t ehci_bar_size = 0x1000;
833 static pcireg_t ehci_bar_value;
834 
835 pcireg_t
836 glx_fn5_read(int reg)
837 {
838 	uint64_t msr;
839 	pcireg_t data;
840 
841 	switch (reg) {
842 	case PCI_ID_REG:
843 	case PCI_SUBSYS_ID_REG:
844 		data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_EHCI);
845 		break;
846 	case PCI_COMMAND_STATUS_REG:
847 		data = glx_get_status();
848 		msr = rdmsr(GCSC_USB_MSR_EHCB);
849 		if (msr & (1ULL << 34))
850 			data |= PCI_COMMAND_MASTER_ENABLE;
851 		if (msr & (1ULL << 33))
852 			data |= PCI_COMMAND_MEM_ENABLE;
853 		break;
854 	case PCI_CLASS_REG:
855 		msr = rdmsr(GCSC_USB_GLD_MSR_CAP);
856 		data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
857 		    (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
858 		    (PCI_INTERFACE_EHCI << PCI_INTERFACE_SHIFT) |
859 		    (msr & PCI_REVISION_MASK);
860 		break;
861 	case PCI_BHLC_REG:
862 		msr = rdmsr(GCSC_GLPCI_CTRL);
863 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
864 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
865 		    (0x08 << PCI_CACHELINE_SHIFT);
866 		break;
867 	case PCI_MAPREG_START + 0x00:
868 		data = ehci_bar_value;
869 		if (data == 0xffffffff)
870 			data = PCI_MAPREG_MEM_ADDR_MASK & ~(ehci_bar_size - 1);
871 		else {
872 			msr = rdmsr(GCSC_USB_MSR_EHCB);
873 			data = msr & 0xffffff00;
874 		}
875 		if (data != 0)
876 			data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
877 		break;
878 	case PCI_CAPLISTPTR_REG:
879 		data = 0x40;
880 		break;
881 	case PCI_INTERRUPT_REG:
882 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
883 		    (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
884 		break;
885 	case 0x40:	/* USB capability pointer */
886 		data = 0;
887 		break;
888 	case PCI_USBREV:
889 		msr = rdmsr(GCSC_USB_MSR_EHCB);
890 		data = PCI_USBREV_2_0;
891 		data |= ((msr >> 40) & 0x3f) << 8;	/* PCI_EHCI_FLADJ */
892 		break;
893 	default:
894 		data = 0;
895 		break;
896 	}
897 
898 	return data;
899 }
900 
901 void
902 glx_fn5_write(int reg, pcireg_t data)
903 {
904 	uint64_t msr;
905 
906 	switch (reg) {
907 	case PCI_COMMAND_STATUS_REG:
908 		msr = rdmsr(GCSC_USB_MSR_EHCB);
909 		if (data & PCI_COMMAND_MASTER_ENABLE)
910 			msr |= 1ULL << 34;
911 		else
912 			msr &= ~(1ULL << 34);
913 		if (data & PCI_COMMAND_MEM_ENABLE)
914 			msr |= 1ULL << 33;
915 		else
916 			msr &= ~(1ULL << 33);
917 		wrmsr(GCSC_USB_MSR_EHCB, msr);
918 		break;
919 	case PCI_BHLC_REG:
920 		msr = rdmsr(GCSC_GLPCI_CTRL);
921 		msr &= 0xff00000000ULL;
922 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
923 		break;
924 	case PCI_MAPREG_START + 0x00:
925 		if (data == 0xffffffff) {
926 			ehci_bar_value = data;
927 		} else {
928 			if ((data & PCI_MAPREG_TYPE_MASK) ==
929 			    PCI_MAPREG_TYPE_MEM) {
930 				data &= PCI_MAPREG_MEM_ADDR_MASK;
931 				msr = rdmsr(GCSC_GLIU_P2D_BM4);
932 				msr &= 0x0fffff0000000000ULL;
933 				msr |= 2ULL << 61;	/* USB */
934 				msr |= (((uint64_t)data) >> 12) << 20;
935 				msr |= 0x000fffff;
936 				wrmsr(GCSC_GLIU_P2D_BM4, msr);
937 
938 				msr = rdmsr(GCSC_USB_MSR_EHCB);
939 				msr &= ~0xffffff00ULL;
940 				msr |= data;
941 			} else {
942 				msr = rdmsr(GCSC_USB_MSR_EHCB);
943 				msr &= ~0xffffff00ULL;
944 			}
945 			wrmsr(GCSC_USB_MSR_EHCB, msr);
946 			ehci_bar_value = 0;
947 		}
948 		break;
949 	default:
950 		break;
951 	}
952 }
953