xref: /netbsd-src/sys/arch/evbmips/loongson/dev/glx.c (revision 85c5fcc244025f3520aae6af6beebd7258fd69cb)
1 /*	$NetBSD: glx.c,v 1.8 2021/02/17 08:19:06 skrll 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.8 2021/02/17 08:19:06 skrll 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
glx_msra2mbxa(uint msr)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
glx_init(pci_chipset_tag_t pc,pcitag_t tag,int dev)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 initialization.
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
rdmsr(uint msr)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
wrmsr(uint msr,uint64_t value)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
glx_pci_read_hook(void * v,pcitag_t tag,int offset)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
glx_pci_write_hook(void * v,pcitag_t tag,int offset,pcireg_t data)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
glx_get_status(void)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
glx_fn0_read(int reg)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
glx_fn0_write(int reg,pcireg_t data)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 (PCI_MAPREG_TYPE(data) == PCI_MAPREG_TYPE_IO) {
464 				data &= PCI_MAPREG_IO_ADDR_MASK;
465 				data &= ~(pcib_bar_sizes[index] - 1);
466 				wrmsr(pcib_bar_msr[index],
467 				    (0x0000f000ULL << 32) | (1ULL << 32) | data);
468 			} else {
469 				wrmsr(pcib_bar_msr[index], 0ULL);
470 			}
471 			pcib_bar_values[index] = 0;
472 		}
473 		break;
474 	}
475 }
476 
477 /*
478  * Function 2: IDE Controller
479  */
480 
481 static pcireg_t pciide_bar_size = 0x10;
482 static pcireg_t pciide_bar_value;
483 
484 pcireg_t
glx_fn2_read(int reg)485 glx_fn2_read(int reg)
486 {
487 	uint64_t msr;
488 	pcireg_t data;
489 
490 	switch (reg) {
491 	case PCI_ID_REG:
492 	case PCI_SUBSYS_ID_REG:
493 		data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_IDE);
494 		break;
495 	case PCI_COMMAND_STATUS_REG:
496 		data = glx_get_status();
497 		data |= PCI_COMMAND_IO_ENABLE;
498 		msr = rdmsr(GCSC_GLIU_PAE);
499 		if ((msr & (0x3 << 4)) == (0x3 << 4))
500 			data |= PCI_COMMAND_MASTER_ENABLE;
501 		break;
502 	case PCI_CLASS_REG:
503 		msr = rdmsr(GCSC_IDE_GLD_MSR_CAP);
504 		data = (PCI_CLASS_MASS_STORAGE << PCI_CLASS_SHIFT) |
505 		    (PCI_SUBCLASS_MASS_STORAGE_IDE << PCI_SUBCLASS_SHIFT) |
506 		    (PCIIDE_INTERFACE_BUS_MASTER_DMA << PCI_INTERFACE_SHIFT) |
507 		    (msr & PCI_REVISION_MASK);
508 		break;
509 	case PCI_BHLC_REG:
510 		msr = rdmsr(GCSC_GLPCI_CTRL);
511 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
512 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
513 		    (0x08 << PCI_CACHELINE_SHIFT);
514 		break;
515 	case PCI_MAPREG_START + 0x10:
516 		data = pciide_bar_value;
517 		if (data == 0xffffffff)
518 			data = PCI_MAPREG_IO_ADDR_MASK & ~(pciide_bar_size - 1);
519 		else {
520 			msr = rdmsr(GCSC_IDE_IO_BAR);
521 			data = msr & 0xfffffff0;
522 		}
523 		if (data != 0)
524 			data |= PCI_MAPREG_TYPE_IO;
525 		break;
526 	case PCI_INTERRUPT_REG:
527 		/* compat mode */
528 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
529 		    (PCI_INTERRUPT_PIN_NONE << PCI_INTERRUPT_PIN_SHIFT);
530 		break;
531 	/*
532 	 * The following registers are used by pciide(4)
533 	 */
534 	case PCIIDE_CHANSTATUS_EN:
535 		data = rdmsr(GCSC_IDE_CFG);
536 		break;
537 	case /* AMD756_DATATIM XXX */ 0x48:
538 		data = rdmsr(GCSC_IDE_DTC);
539 		break;
540 	case /* AMD756_UDMA XXX*/ 0x50:
541 		data = rdmsr(GCSC_IDE_ETC);
542 		break;
543 	default:
544 		DPRINTF(("unimplemented pciide reg 0x%x\n", reg));
545 		data = 0;
546 		break;
547 	}
548 
549 	return data;
550 }
551 
552 void
glx_fn2_write(int reg,pcireg_t data)553 glx_fn2_write(int reg, pcireg_t data)
554 {
555 	uint64_t msr;
556 
557 	switch (reg) {
558 	case PCI_COMMAND_STATUS_REG:
559 		msr = rdmsr(GCSC_GLIU_PAE);
560 		if (data & PCI_COMMAND_MASTER_ENABLE)
561 			msr |= 0x03 << 4;
562 		else
563 			msr &= ~(0x03 << 4);
564 		wrmsr(GCSC_GLIU_PAE, msr);
565 		break;
566 	case PCI_BHLC_REG:
567 		msr = rdmsr(GCSC_GLPCI_CTRL);
568 		msr &= 0xff00000000ULL;
569 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
570 		break;
571 	case PCI_MAPREG_START + 0x10:
572 		if (data == 0xffffffff) {
573 			pciide_bar_value = data;
574 		} else {
575 			if (PCI_MAPREG_TYPE(data) == PCI_MAPREG_TYPE_IO) {
576 				data &= PCI_MAPREG_IO_ADDR_MASK;
577 				msr = (uint32_t)data & 0xfffffff0;
578 				wrmsr(GCSC_IDE_IO_BAR, msr);
579 			} else {
580 				wrmsr(GCSC_IDE_IO_BAR, 0);
581 			}
582 			pciide_bar_value = 0;
583 		}
584 		break;
585 	/*
586 	 * The following registers are used by pciide(4)
587 	 */
588 	case PCIIDE_CHANSTATUS_EN:
589 		wrmsr(GCSC_IDE_CFG, (uint32_t)data);
590 		break;
591 	case /* AMD756_DATATIM XXX */ 0x48:
592 		wrmsr(GCSC_IDE_DTC, (uint32_t)data);
593 		break;
594 	case /* AMD756_UDMA XXX*/ 0x50:
595 		wrmsr(GCSC_IDE_ETC, (uint32_t)data);
596 		break;
597 	default:
598 		DPRINTF(("unimplemented pciide reg 0x%x\n", reg));
599 	}
600 }
601 
602 /*
603  * Function 3: AC97 Codec
604  */
605 
606 static pcireg_t ac97_bar_size = 0x80;
607 static pcireg_t ac97_bar_value;
608 
609 pcireg_t
glx_fn3_read(int reg)610 glx_fn3_read(int reg)
611 {
612 	uint64_t msr;
613 	pcireg_t data;
614 
615 	switch (reg) {
616 	case PCI_ID_REG:
617 	case PCI_SUBSYS_ID_REG:
618 		data = PCI_ID_CODE(PCI_VENDOR_AMD,
619 		    PCI_PRODUCT_AMD_CS5536_AUDIO);
620 		break;
621 	case PCI_COMMAND_STATUS_REG:
622 		data = glx_get_status();
623 		data |= PCI_COMMAND_IO_ENABLE;
624 		msr = rdmsr(GCSC_GLIU_PAE);
625 		if ((msr & (0x3 << 8)) == (0x3 << 8))
626 			data |= PCI_COMMAND_MASTER_ENABLE;
627 		break;
628 	case PCI_CLASS_REG:
629 		msr = rdmsr(GCSC_ACC_GLD_MSR_CAP);
630 		data = (PCI_CLASS_MULTIMEDIA << PCI_CLASS_SHIFT) |
631 		    (PCI_SUBCLASS_MULTIMEDIA_AUDIO << PCI_SUBCLASS_SHIFT) |
632 		    (msr & PCI_REVISION_MASK);
633 		break;
634 	case PCI_BHLC_REG:
635 		msr = rdmsr(GCSC_GLPCI_CTRL);
636 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
637 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
638 		    (0x08 << PCI_CACHELINE_SHIFT);
639 		break;
640 	case PCI_MAPREG_START:
641 		data = ac97_bar_value;
642 		if (data == 0xffffffff)
643 			data = PCI_MAPREG_IO_ADDR_MASK & ~(ac97_bar_size - 1);
644 		else {
645 			msr = rdmsr(GCSC_GLIU_IOD_BM1);
646 			data = (msr >> 20) & 0x000fffff;
647 			data &= (msr & 0x000fffff);
648 		}
649 		if (data != 0)
650 			data |= PCI_MAPREG_TYPE_IO;
651 		break;
652 	case PCI_INTERRUPT_REG:
653 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
654 		    (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
655 		break;
656 	default:
657 		data = 0;
658 		break;
659 	}
660 
661 	return data;
662 }
663 
664 void
glx_fn3_write(int reg,pcireg_t data)665 glx_fn3_write(int reg, pcireg_t data)
666 {
667 	uint64_t msr;
668 
669 	switch (reg) {
670 	case PCI_COMMAND_STATUS_REG:
671 		msr = rdmsr(GCSC_GLIU_PAE);
672 		if (data & PCI_COMMAND_MASTER_ENABLE)
673 			msr |= 0x03 << 8;
674 		else
675 			msr &= ~(0x03 << 8);
676 		wrmsr(GCSC_GLIU_PAE, msr);
677 		break;
678 	case PCI_BHLC_REG:
679 		msr = rdmsr(GCSC_GLPCI_CTRL);
680 		msr &= 0xff00000000ULL;
681 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
682 		break;
683 	case PCI_MAPREG_START:
684 		if (data == 0xffffffff) {
685 			ac97_bar_value = data;
686 		} else {
687 			if (PCI_MAPREG_TYPE(data) == PCI_MAPREG_TYPE_IO) {
688 				data &= PCI_MAPREG_IO_ADDR_MASK;
689 				msr = rdmsr(GCSC_GLIU_IOD_BM1);
690 				msr &= 0x0fffff0000000000ULL;
691 				msr |= 5ULL << 61;	/* AC97 */
692 				msr |= ((uint64_t)data & 0xfffff) << 20;
693 				msr |= 0x000fffff & ~(ac97_bar_size - 1);
694 				wrmsr(GCSC_GLIU_IOD_BM1, msr);
695 			} else {
696 				wrmsr(GCSC_GLIU_IOD_BM1, 0);
697 			}
698 			ac97_bar_value = 0;
699 		}
700 		break;
701 	}
702 }
703 
704 /*
705  * Function 4: OHCI Controller
706  */
707 
708 static pcireg_t ohci_bar_size = 0x1000;
709 static pcireg_t ohci_bar_value;
710 
711 pcireg_t
glx_fn4_read(int reg)712 glx_fn4_read(int reg)
713 {
714 	uint64_t msr;
715 	pcireg_t data;
716 
717 	switch (reg) {
718 	case PCI_ID_REG:
719 	case PCI_SUBSYS_ID_REG:
720 		data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_OHCI);
721 		break;
722 	case PCI_COMMAND_STATUS_REG:
723 		data = glx_get_status();
724 		msr = rdmsr(GCSC_USB_MSR_OHCB);
725 		if (msr & (1ULL << 34))
726 			data |= PCI_COMMAND_MASTER_ENABLE;
727 		if (msr & (1ULL << 33))
728 			data |= PCI_COMMAND_MEM_ENABLE;
729 		break;
730 	case PCI_CLASS_REG:
731 		msr = rdmsr(GCSC_USB_GLD_MSR_CAP);
732 		data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
733 		    (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
734 		    (PCI_INTERFACE_OHCI << PCI_INTERFACE_SHIFT) |
735 		    (msr & PCI_REVISION_MASK);
736 		break;
737 	case PCI_BHLC_REG:
738 		msr = rdmsr(GCSC_GLPCI_CTRL);
739 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
740 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
741 		    (0x08 << PCI_CACHELINE_SHIFT);
742 		break;
743 	case PCI_MAPREG_START + 0x00:
744 		data = ohci_bar_value;
745 		if (data == 0xffffffff)
746 			data = PCI_MAPREG_MEM_ADDR_MASK & ~(ohci_bar_size - 1);
747 		else {
748 			msr = rdmsr(GCSC_USB_MSR_OHCB);
749 			data = msr & 0xffffff00;
750 		}
751 		if (data != 0)
752 			data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
753 		break;
754 	case PCI_CAPLISTPTR_REG:
755 		data = 0x40;
756 		break;
757 	case PCI_INTERRUPT_REG:
758 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
759 		    (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
760 		break;
761 	case 0x40:	/* USB capability pointer */
762 		data = 0;
763 		break;
764 	default:
765 		data = 0;
766 		break;
767 	}
768 
769 	return data;
770 }
771 
772 void
glx_fn4_write(int reg,pcireg_t data)773 glx_fn4_write(int reg, pcireg_t data)
774 {
775 	uint64_t msr;
776 
777 	switch (reg) {
778 	case PCI_COMMAND_STATUS_REG:
779 		msr = rdmsr(GCSC_USB_MSR_OHCB);
780 		if (data & PCI_COMMAND_MASTER_ENABLE)
781 			msr |= 1ULL << 34;
782 		else
783 			msr &= ~(1ULL << 34);
784 		if (data & PCI_COMMAND_MEM_ENABLE)
785 			msr |= 1ULL << 33;
786 		else
787 			msr &= ~(1ULL << 33);
788 		wrmsr(GCSC_USB_MSR_OHCB, msr);
789 		break;
790 	case PCI_BHLC_REG:
791 		msr = rdmsr(GCSC_GLPCI_CTRL);
792 		msr &= 0xff00000000ULL;
793 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
794 		break;
795 	case PCI_MAPREG_START + 0x00:
796 		if (data == 0xffffffff) {
797 			ohci_bar_value = data;
798 		} else {
799 			if (PCI_MAPREG_TYPE(data) == PCI_MAPREG_TYPE_MEM) {
800 				data &= PCI_MAPREG_MEM_ADDR_MASK;
801 				msr = rdmsr(GCSC_GLIU_P2D_BM3);
802 				msr &= 0x0fffff0000000000ULL;
803 				msr |= 2ULL << 61;	/* USB */
804 				msr |= (((uint64_t)data) >> 12) << 20;
805 				msr |= 0x000fffff;
806 				wrmsr(GCSC_GLIU_P2D_BM3, msr);
807 
808 				msr = rdmsr(GCSC_USB_MSR_OHCB);
809 				msr &= ~0xffffff00ULL;
810 				msr |= data;
811 			} else {
812 				msr = rdmsr(GCSC_USB_MSR_OHCB);
813 				msr &= ~0xffffff00ULL;
814 			}
815 			wrmsr(GCSC_USB_MSR_OHCB, msr);
816 			ohci_bar_value = 0;
817 		}
818 		break;
819 	default:
820 		break;
821 	}
822 }
823 
824 /*
825  * Function 5: EHCI Controller
826  */
827 
828 static pcireg_t ehci_bar_size = 0x1000;
829 static pcireg_t ehci_bar_value;
830 
831 pcireg_t
glx_fn5_read(int reg)832 glx_fn5_read(int reg)
833 {
834 	uint64_t msr;
835 	pcireg_t data;
836 
837 	switch (reg) {
838 	case PCI_ID_REG:
839 	case PCI_SUBSYS_ID_REG:
840 		data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_EHCI);
841 		break;
842 	case PCI_COMMAND_STATUS_REG:
843 		data = glx_get_status();
844 		msr = rdmsr(GCSC_USB_MSR_EHCB);
845 		if (msr & (1ULL << 34))
846 			data |= PCI_COMMAND_MASTER_ENABLE;
847 		if (msr & (1ULL << 33))
848 			data |= PCI_COMMAND_MEM_ENABLE;
849 		break;
850 	case PCI_CLASS_REG:
851 		msr = rdmsr(GCSC_USB_GLD_MSR_CAP);
852 		data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
853 		    (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
854 		    (PCI_INTERFACE_EHCI << PCI_INTERFACE_SHIFT) |
855 		    (msr & PCI_REVISION_MASK);
856 		break;
857 	case PCI_BHLC_REG:
858 		msr = rdmsr(GCSC_GLPCI_CTRL);
859 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
860 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
861 		    (0x08 << PCI_CACHELINE_SHIFT);
862 		break;
863 	case PCI_MAPREG_START + 0x00:
864 		data = ehci_bar_value;
865 		if (data == 0xffffffff)
866 			data = PCI_MAPREG_MEM_ADDR_MASK & ~(ehci_bar_size - 1);
867 		else {
868 			msr = rdmsr(GCSC_USB_MSR_EHCB);
869 			data = msr & 0xffffff00;
870 		}
871 		if (data != 0)
872 			data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
873 		break;
874 	case PCI_CAPLISTPTR_REG:
875 		data = 0x40;
876 		break;
877 	case PCI_INTERRUPT_REG:
878 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
879 		    (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
880 		break;
881 	case 0x40:	/* USB capability pointer */
882 		data = 0;
883 		break;
884 	case PCI_USBREV:
885 		msr = rdmsr(GCSC_USB_MSR_EHCB);
886 		data = PCI_USBREV_2_0;
887 		data |= ((msr >> 40) & 0x3f) << 8;	/* PCI_EHCI_FLADJ */
888 		break;
889 	default:
890 		data = 0;
891 		break;
892 	}
893 
894 	return data;
895 }
896 
897 void
glx_fn5_write(int reg,pcireg_t data)898 glx_fn5_write(int reg, pcireg_t data)
899 {
900 	uint64_t msr;
901 
902 	switch (reg) {
903 	case PCI_COMMAND_STATUS_REG:
904 		msr = rdmsr(GCSC_USB_MSR_EHCB);
905 		if (data & PCI_COMMAND_MASTER_ENABLE)
906 			msr |= 1ULL << 34;
907 		else
908 			msr &= ~(1ULL << 34);
909 		if (data & PCI_COMMAND_MEM_ENABLE)
910 			msr |= 1ULL << 33;
911 		else
912 			msr &= ~(1ULL << 33);
913 		wrmsr(GCSC_USB_MSR_EHCB, msr);
914 		break;
915 	case PCI_BHLC_REG:
916 		msr = rdmsr(GCSC_GLPCI_CTRL);
917 		msr &= 0xff00000000ULL;
918 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
919 		break;
920 	case PCI_MAPREG_START + 0x00:
921 		if (data == 0xffffffff) {
922 			ehci_bar_value = data;
923 		} else {
924 			if (PCI_MAPREG_TYPE(data) == PCI_MAPREG_TYPE_MEM) {
925 				data = PCI_MAPREG_MEM_ADDR(data);
926 				msr = rdmsr(GCSC_GLIU_P2D_BM4);
927 				msr &= 0x0fffff0000000000ULL;
928 				msr |= 2ULL << 61;	/* USB */
929 				msr |= (((uint64_t)data) >> 12) << 20;
930 				msr |= 0x000fffff;
931 				wrmsr(GCSC_GLIU_P2D_BM4, msr);
932 
933 				msr = rdmsr(GCSC_USB_MSR_EHCB);
934 				msr &= ~0xffffff00ULL;
935 				msr |= data;
936 			} else {
937 				msr = rdmsr(GCSC_USB_MSR_EHCB);
938 				msr &= ~0xffffff00ULL;
939 			}
940 			wrmsr(GCSC_USB_MSR_EHCB, msr);
941 			ehci_bar_value = 0;
942 		}
943 		break;
944 	default:
945 		break;
946 	}
947 }
948