Home | History | Annotate | Line # | Download | only in dev
glx.c revision 1.1.6.1
      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 #include <sys/cdefs.h>
     24 __KERNEL_RCSID(0, "$NetBSD: glx.c,v 1.1.6.1 2012/02/18 07:31:56 mrg Exp $");
     25 
     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 
    140 	msr = 0;
    141 	msr |= 11 << 8;
    142 	msr |= 9 << 16;
    143 	wrmsr(GCSC_PIC_YSEL_LOW, msr);
    144 
    145 	/*
    146 	 * serial interrupts
    147 	 */
    148 	msr = 0;
    149 	msr |= 4 << 24;
    150 	msr |= 3 << 28;
    151 	wrmsr(GCSC_PIC_YSEL_HIGH, msr);
    152 
    153 	/*
    154 	 * and IDE
    155 	 */
    156 	msr = 0;
    157 	msr |= 1 << 14;
    158 	wrmsr(GCSC_PIC_IRQM_PRIM, msr);
    159 
    160 	/* no interrupts from theses */
    161 	wrmsr(GCSC_PIC_ZSEL_LOW, 0);
    162 	wrmsr(GCSC_PIC_ZSEL_HIGH, 0);
    163 	wrmsr(GCSC_PIC_IRQM_LPC, 0);
    164 
    165 	DPRINTF(("IO space 0x%" PRIx64 "\n", rdmsr(0x80000014)));
    166 }
    167 
    168 uint64_t
    169 rdmsr(uint msr)
    170 {
    171 	uint64_t lo, hi;
    172 	int s;
    173 
    174 #ifdef DIAGNOSTIC
    175 	if (glxbase_tag == 0)
    176 		panic("rdmsr invoked before glx initialization");
    177 #endif
    178 
    179 	s = splhigh();
    180 	pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_ADDR,
    181 	    glx_msra2mbxa(msr));
    182 	lo = (uint32_t)pci_conf_read(glxbase_pc, glxbase_tag, PCI_MSR_LO32);
    183 	hi = (uint32_t)pci_conf_read(glxbase_pc, glxbase_tag, PCI_MSR_HI32);
    184 	splx(s);
    185 	return (hi << 32) | lo;
    186 }
    187 
    188 void
    189 wrmsr(uint msr, uint64_t value)
    190 {
    191 	int s;
    192 
    193 #ifdef DIAGNOSTIC
    194 	if (glxbase_tag == 0)
    195 		panic("wrmsr invoked before glx initialization");
    196 #endif
    197 
    198 	s = splhigh();
    199 	pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_ADDR,
    200 	    glx_msra2mbxa(msr));
    201 	pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_LO32, (uint32_t)value);
    202 	pci_conf_write(glxbase_pc, glxbase_tag, PCI_MSR_HI32, value >> 32);
    203 	splx(s);
    204 }
    205 
    206 pcireg_t
    207 glx_pci_read_hook(void *v, pcitag_t tag, int offset)
    208 {
    209 	int bus, dev, fn;
    210 	pcireg_t data;
    211 
    212 	/*
    213 	 * Do not get in the way of MSR programming
    214 	 */
    215 	if (tag == glxbase_tag && offset >= PCI_MSR_CTRL)
    216 		return gen_pci_conf_read(v, tag, offset);
    217 
    218 	pci_decompose_tag(glxbase_pc, tag, &bus, &dev, &fn);
    219 	if (bus != 0 || dev != glxbase_dev)
    220 		return gen_pci_conf_read(v, tag, offset);
    221 
    222 	data = 0;
    223 
    224 	switch (fn) {
    225 	case 0:	/* PCI-ISA bridge */
    226 		data = glx_fn0_read(offset);
    227 		break;
    228 	case 1:	/* Flash memory */
    229 		break;
    230 	case 2:	/* IDE controller */
    231 		data = glx_fn2_read(offset);
    232 		break;
    233 	case 3:	/* AC97 codec */
    234 		data = glx_fn3_read(offset);
    235 		break;
    236 	case 4:	/* OHCI controller */
    237 		data = glx_fn4_read(offset);
    238 		break;
    239 	case 5:	/* EHCI controller */
    240 		data = glx_fn5_read(offset);
    241 		break;
    242 	case 6:	/* UDC */
    243 		break;
    244 	case 7:	/* OTG */
    245 		break;
    246 	}
    247 
    248 	return data;
    249 }
    250 
    251 void
    252 glx_pci_write_hook(void *v, pcitag_t tag,
    253     int offset, pcireg_t data)
    254 {
    255 	int bus, dev, fn;
    256 
    257 	/*
    258 	 * Do not get in the way of MSR programming
    259 	 */
    260 	if (tag == glxbase_tag && offset >= PCI_MSR_CTRL) {
    261 		gen_pci_conf_write(v, tag, offset, data);
    262 		return;
    263 	}
    264 
    265 
    266 	pci_decompose_tag(glxbase_pc, tag, &bus, &dev, &fn);
    267 	if (bus != 0 || dev != glxbase_dev) {
    268 		gen_pci_conf_write(v, tag, offset, data);
    269 		return;
    270 	}
    271 
    272 	switch (fn) {
    273 	case 0:	/* PCI-ISA bridge */
    274 		glx_fn0_write(offset, data);
    275 		break;
    276 	case 1:	/* Flash memory */
    277 		break;
    278 	case 2:	/* IDE controller */
    279 		glx_fn2_write(offset, data);
    280 		break;
    281 	case 3:	/* AC97 codec */
    282 		glx_fn3_write(offset, data);
    283 		break;
    284 	case 4:	/* OHCI controller */
    285 		glx_fn4_write(offset, data);
    286 		break;
    287 	case 5:	/* EHCI controller */
    288 		glx_fn5_write(offset, data);
    289 		break;
    290 	case 6:	/* USB UDC */
    291 		break;
    292 	case 7:	/* USB OTG */
    293 		break;
    294 	}
    295 }
    296 
    297 pcireg_t
    298 glx_get_status(void)
    299 {
    300 	uint64_t msr;
    301 	pcireg_t data;
    302 
    303 	data = 0;
    304 	msr = rdmsr(GCSC_GLPCI_GLD_MSR_ERROR);
    305 	if (msr & (1UL << 5))
    306 		data |= PCI_COMMAND_PARITY_ENABLE;
    307 	data |= PCI_STATUS_66MHZ_SUPPORT |
    308 	    PCI_STATUS_BACKTOBACK_SUPPORT | PCI_STATUS_DEVSEL_MEDIUM;
    309 	if (msr & (1UL << 21))
    310 		data |= PCI_STATUS_PARITY_DETECT;
    311 	if (msr & (1UL << 20))
    312 		data |= PCI_STATUS_TARGET_TARGET_ABORT;
    313 	if (msr & (1UL << 17))
    314 		data |= PCI_STATUS_MASTER_TARGET_ABORT;
    315 	if (msr & (1UL << 16))
    316 		data |= PCI_STATUS_MASTER_ABORT;
    317 
    318 	return data;
    319 }
    320 
    321 /*
    322  * Function 0: PCI-ISA bridge
    323  */
    324 
    325 static const pcireg_t pcib_bar_sizes[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4] = {
    326 	0x008,
    327 	0x100,
    328 	0x040,
    329 	0x020,
    330 	0x080,
    331 	0x020
    332 };
    333 
    334 static pcireg_t pcib_bar_values[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4];
    335 
    336 static const uint64_t pcib_bar_msr[(4 + PCI_MAPREG_END - PCI_MAPREG_START) / 4] = {
    337 	GCSC_DIVIL_LBAR_SMB,
    338 	GCSC_DIVIL_LBAR_GPIO,
    339 	GCSC_DIVIL_LBAR_MFGPT,
    340 	GCSC_DIVIL_LBAR_IRQ,
    341 	GCSC_DIVIL_LBAR_PMS,
    342 	GCSC_DIVIL_LBAR_ACPI
    343 };
    344 
    345 pcireg_t
    346 glx_fn0_read(int reg)
    347 {
    348 	uint64_t msr;
    349 	pcireg_t data;
    350 	int index;
    351 
    352 	switch (reg) {
    353 	case PCI_ID_REG:
    354 	case PCI_SUBSYS_ID_REG:
    355 		data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_PCIB);
    356 		break;
    357 	case PCI_COMMAND_STATUS_REG:
    358 		data = glx_get_status();
    359 		data |= PCI_COMMAND_MASTER_ENABLE;
    360 		msr = rdmsr(GCSC_DIVIL_LBAR_SMB);
    361 		if (msr & (1ULL << 32))
    362 			data |= PCI_COMMAND_IO_ENABLE;
    363 		break;
    364 	case PCI_CLASS_REG:
    365 		msr = rdmsr(GCSC_GLCP_CHIP_REV_ID);
    366 		data = (PCI_CLASS_BRIDGE << PCI_CLASS_SHIFT) |
    367 		    (PCI_SUBCLASS_BRIDGE_ISA << PCI_SUBCLASS_SHIFT) |
    368 		    (msr & PCI_REVISION_MASK);
    369 		break;
    370 	case PCI_BHLC_REG:
    371 		msr = rdmsr(GCSC_GLPCI_CTRL);
    372 		data = (0x80 << PCI_HDRTYPE_SHIFT) |
    373 		    (((msr & 0xff00000000UL) >> 32) << PCI_LATTIMER_SHIFT) |
    374 		    (0x08 << PCI_CACHELINE_SHIFT);
    375 		break;
    376 	case PCI_MAPREG_START + 0x00:
    377 	case PCI_MAPREG_START + 0x04:
    378 	case PCI_MAPREG_START + 0x08:
    379 	case PCI_MAPREG_START + 0x0c:
    380 	case PCI_MAPREG_START + 0x10:
    381 	case PCI_MAPREG_START + 0x14:
    382 	case PCI_MAPREG_START + 0x18:
    383 		index = (reg - PCI_MAPREG_START) / 4;
    384 		if (pcib_bar_msr[index] == 0)
    385 			data = 0;
    386 		else {
    387 			data = pcib_bar_values[index];
    388 			if (data == 0xffffffff)
    389 				data = PCI_MAPREG_IO_ADDR_MASK;
    390 			else
    391 				data = (pcireg_t)rdmsr(pcib_bar_msr[index]);
    392 			data &= ~(pcib_bar_sizes[index] - 1);
    393 			if (data != 0)
    394 				data |= PCI_MAPREG_TYPE_IO;
    395 		}
    396 		break;
    397 	case PCI_INTERRUPT_REG:
    398 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
    399 		    (PCI_INTERRUPT_PIN_NONE << PCI_INTERRUPT_PIN_SHIFT);
    400 		break;
    401 	default:
    402 		data = 0;
    403 		break;
    404 	}
    405 
    406 	return data;
    407 }
    408 
    409 void
    410 glx_fn0_write(int reg, pcireg_t data)
    411 {
    412 	uint64_t msr;
    413 	int index;
    414 
    415 	switch (reg) {
    416 	case PCI_COMMAND_STATUS_REG:
    417 		for (index = 0; index < __arraycount(pcib_bar_msr); index++) {
    418 			if (pcib_bar_msr[index] == 0)
    419 				continue;
    420 			msr = rdmsr(pcib_bar_msr[index]);
    421 			if (data & PCI_COMMAND_IO_ENABLE)
    422 				msr |= 1ULL << 32;
    423 			else
    424 				msr &= ~(1ULL << 32);
    425 			wrmsr(pcib_bar_msr[index], msr);
    426 		}
    427 
    428 		msr = rdmsr(GCSC_GLPCI_GLD_MSR_ERROR);
    429 		if (data & PCI_COMMAND_PARITY_ENABLE)
    430 			msr |= 1ULL << 5;
    431 		else
    432 			msr &= ~(1ULL << 5);
    433 		wrmsr(GCSC_GLPCI_GLD_MSR_ERROR, msr);
    434 		break;
    435 	case PCI_BHLC_REG:
    436 		msr = rdmsr(GCSC_GLPCI_CTRL);
    437 		msr &= 0xff00000000ULL;
    438 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
    439 		break;
    440 	case PCI_MAPREG_START + 0x00:
    441 	case PCI_MAPREG_START + 0x04:
    442 	case PCI_MAPREG_START + 0x08:
    443 	case PCI_MAPREG_START + 0x0c:
    444 	case PCI_MAPREG_START + 0x10:
    445 	case PCI_MAPREG_START + 0x14:
    446 	case PCI_MAPREG_START + 0x18:
    447 		index = (reg - PCI_MAPREG_START) / 4;
    448 		if (data == 0xffffffff) {
    449 			pcib_bar_values[index] = data;
    450 		} else if (pcib_bar_msr[index] != 0) {
    451 			if ((data & PCI_MAPREG_TYPE_MASK) ==
    452 			    PCI_MAPREG_TYPE_IO) {
    453 				data &= PCI_MAPREG_IO_ADDR_MASK;
    454 				data &= ~(pcib_bar_sizes[index] - 1);
    455 				wrmsr(pcib_bar_msr[index],
    456 				    (0x0000f000ULL << 32) | (1ULL << 32) | data);
    457 			} else {
    458 				wrmsr(pcib_bar_msr[index], 0ULL);
    459 			}
    460 			pcib_bar_values[index] = 0;
    461 		}
    462 		break;
    463 	}
    464 }
    465 
    466 /*
    467  * Function 2: IDE Controller
    468  */
    469 
    470 static pcireg_t pciide_bar_size = 0x10;
    471 static pcireg_t pciide_bar_value;
    472 
    473 pcireg_t
    474 glx_fn2_read(int reg)
    475 {
    476 	uint64_t msr;
    477 	pcireg_t data;
    478 
    479 	switch (reg) {
    480 	case PCI_ID_REG:
    481 	case PCI_SUBSYS_ID_REG:
    482 		data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_IDE);
    483 		break;
    484 	case PCI_COMMAND_STATUS_REG:
    485 		data = glx_get_status();
    486 		data |= PCI_COMMAND_IO_ENABLE;
    487 		msr = rdmsr(GCSC_GLIU_PAE);
    488 		if ((msr & (0x3 << 4)) == 0x03)
    489 			data |= PCI_COMMAND_MASTER_ENABLE;
    490 		break;
    491 	case PCI_CLASS_REG:
    492 		msr = rdmsr(GCSC_IDE_GLD_MSR_CAP);
    493 		data = (PCI_CLASS_MASS_STORAGE << PCI_CLASS_SHIFT) |
    494 		    (PCI_SUBCLASS_MASS_STORAGE_IDE << PCI_SUBCLASS_SHIFT) |
    495 		    (PCIIDE_INTERFACE_BUS_MASTER_DMA << PCI_INTERFACE_SHIFT) |
    496 		    (msr & PCI_REVISION_MASK);
    497 		break;
    498 	case PCI_BHLC_REG:
    499 		msr = rdmsr(GCSC_GLPCI_CTRL);
    500 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
    501 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
    502 		    (0x08 << PCI_CACHELINE_SHIFT);
    503 		break;
    504 	case PCI_MAPREG_START + 0x10:
    505 		data = pciide_bar_value;
    506 		if (data == 0xffffffff)
    507 			data = PCI_MAPREG_IO_ADDR_MASK & ~(pciide_bar_size - 1);
    508 		else {
    509 			msr = rdmsr(GCSC_IDE_IO_BAR);
    510 			data = msr & 0xfffffff0;
    511 		}
    512 		if (data != 0)
    513 			data |= PCI_MAPREG_TYPE_IO;
    514 		break;
    515 	case PCI_INTERRUPT_REG:
    516 		/* compat mode */
    517 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
    518 		    (PCI_INTERRUPT_PIN_NONE << PCI_INTERRUPT_PIN_SHIFT);
    519 		break;
    520 	/*
    521 	 * The following registers are used by pciide(4)
    522 	 */
    523 	case PCIIDE_CHANSTATUS_EN:
    524 		data = rdmsr(GCSC_IDE_CFG);
    525 		break;
    526 	case /* AMD756_DATATIM XXX */ 0x48:
    527 		data = rdmsr(GCSC_IDE_DTC);
    528 		break;
    529 	case /* AMD756_UDMA XXX*/ 0x50:
    530 		data = rdmsr(GCSC_IDE_ETC);
    531 		break;
    532 	default:
    533 		DPRINTF(("unimplemented pciide reg 0x%x\n", reg));
    534 		data = 0;
    535 		break;
    536 	}
    537 
    538 	return data;
    539 }
    540 
    541 void
    542 glx_fn2_write(int reg, pcireg_t data)
    543 {
    544 	uint64_t msr;
    545 
    546 	switch (reg) {
    547 	case PCI_COMMAND_STATUS_REG:
    548 		msr = rdmsr(GCSC_GLIU_PAE);
    549 		if (data & PCI_COMMAND_MASTER_ENABLE)
    550 			msr |= 0x03 << 4;
    551 		else
    552 			msr &= ~(0x03 << 4);
    553 		wrmsr(GCSC_GLIU_PAE, msr);
    554 		break;
    555 	case PCI_BHLC_REG:
    556 		msr = rdmsr(GCSC_GLPCI_CTRL);
    557 		msr &= 0xff00000000ULL;
    558 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
    559 		break;
    560 	case PCI_MAPREG_START + 0x10:
    561 		if (data == 0xffffffff) {
    562 			pciide_bar_value = data;
    563 		} else {
    564 			if ((data & PCI_MAPREG_TYPE_MASK) ==
    565 			    PCI_MAPREG_TYPE_IO) {
    566 				data &= PCI_MAPREG_IO_ADDR_MASK;
    567 				msr = (uint32_t)data & 0xfffffff0;
    568 				wrmsr(GCSC_IDE_IO_BAR, msr);
    569 			} else {
    570 				wrmsr(GCSC_IDE_IO_BAR, 0);
    571 			}
    572 			pciide_bar_value = 0;
    573 		}
    574 		break;
    575 	/*
    576 	 * The following registers are used by pciide(4)
    577 	 */
    578 	case PCIIDE_CHANSTATUS_EN:
    579 		wrmsr(GCSC_IDE_CFG, (uint32_t)data);
    580 		break;
    581 	case /* AMD756_DATATIM XXX */ 0x48:
    582 		wrmsr(GCSC_IDE_DTC, (uint32_t)data);
    583 		break;
    584 	case /* AMD756_UDMA XXX*/ 0x50:
    585 		wrmsr(GCSC_IDE_ETC, (uint32_t)data);
    586 		break;
    587 	default:
    588 		DPRINTF(("unimplemented pciide reg 0x%x\n", reg));
    589 	}
    590 }
    591 
    592 /*
    593  * Function 3: AC97 Codec
    594  */
    595 
    596 static pcireg_t ac97_bar_size = 0x80;
    597 static pcireg_t ac97_bar_value;
    598 
    599 pcireg_t
    600 glx_fn3_read(int reg)
    601 {
    602 	uint64_t msr;
    603 	pcireg_t data;
    604 
    605 	switch (reg) {
    606 	case PCI_ID_REG:
    607 	case PCI_SUBSYS_ID_REG:
    608 		data = PCI_ID_CODE(PCI_VENDOR_AMD,
    609 		    PCI_PRODUCT_AMD_CS5536_AUDIO);
    610 		break;
    611 	case PCI_COMMAND_STATUS_REG:
    612 		data = glx_get_status();
    613 		data |= PCI_COMMAND_IO_ENABLE;
    614 		msr = rdmsr(GCSC_GLIU_PAE);
    615 		if ((msr & (0x3 << 8)) == 0x03)
    616 			data |= PCI_COMMAND_MASTER_ENABLE;
    617 		break;
    618 	case PCI_CLASS_REG:
    619 		msr = rdmsr(GCSC_ACC_GLD_MSR_CAP);
    620 		data = (PCI_CLASS_MULTIMEDIA << PCI_CLASS_SHIFT) |
    621 		    (PCI_SUBCLASS_MULTIMEDIA_AUDIO << PCI_SUBCLASS_SHIFT) |
    622 		    (msr & PCI_REVISION_MASK);
    623 		break;
    624 	case PCI_BHLC_REG:
    625 		msr = rdmsr(GCSC_GLPCI_CTRL);
    626 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
    627 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
    628 		    (0x08 << PCI_CACHELINE_SHIFT);
    629 		break;
    630 	case PCI_MAPREG_START:
    631 		data = ac97_bar_value;
    632 		if (data == 0xffffffff)
    633 			data = PCI_MAPREG_IO_ADDR_MASK & ~(ac97_bar_size - 1);
    634 		else {
    635 			msr = rdmsr(GCSC_GLIU_IOD_BM1);
    636 			data = (msr >> 20) & 0x000fffff;
    637 			data &= (msr & 0x000fffff);
    638 		}
    639 		if (data != 0)
    640 			data |= PCI_MAPREG_TYPE_IO;
    641 		break;
    642 	case PCI_INTERRUPT_REG:
    643 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
    644 		    (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
    645 		break;
    646 	default:
    647 		data = 0;
    648 		break;
    649 	}
    650 
    651 	return data;
    652 }
    653 
    654 void
    655 glx_fn3_write(int reg, pcireg_t data)
    656 {
    657 	uint64_t msr;
    658 
    659 	switch (reg) {
    660 	case PCI_COMMAND_STATUS_REG:
    661 		msr = rdmsr(GCSC_GLIU_PAE);
    662 		if (data & PCI_COMMAND_MASTER_ENABLE)
    663 			msr |= 0x03 << 8;
    664 		else
    665 			msr &= ~(0x03 << 8);
    666 		wrmsr(GCSC_GLIU_PAE, msr);
    667 		break;
    668 	case PCI_BHLC_REG:
    669 		msr = rdmsr(GCSC_GLPCI_CTRL);
    670 		msr &= 0xff00000000ULL;
    671 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
    672 		break;
    673 	case PCI_MAPREG_START:
    674 		if (data == 0xffffffff) {
    675 			ac97_bar_value = data;
    676 		} else {
    677 			if ((data & PCI_MAPREG_TYPE_MASK) ==
    678 			    PCI_MAPREG_TYPE_IO) {
    679 				data &= PCI_MAPREG_IO_ADDR_MASK;
    680 				msr = rdmsr(GCSC_GLIU_IOD_BM1);
    681 				msr &= 0x0fffff0000000000ULL;
    682 				msr |= 5ULL << 61;	/* AC97 */
    683 				msr |= ((uint64_t)data & 0xfffff) << 20;
    684 				msr |= 0x000fffff & ~(ac97_bar_size - 1);
    685 				wrmsr(GCSC_GLIU_IOD_BM1, msr);
    686 			} else {
    687 				wrmsr(GCSC_GLIU_IOD_BM1, 0);
    688 			}
    689 			ac97_bar_value = 0;
    690 		}
    691 		break;
    692 	}
    693 }
    694 
    695 /*
    696  * Function 4: OHCI Controller
    697  */
    698 
    699 static pcireg_t ohci_bar_size = 0x1000;
    700 static pcireg_t ohci_bar_value;
    701 
    702 pcireg_t
    703 glx_fn4_read(int reg)
    704 {
    705 	uint64_t msr;
    706 	pcireg_t data;
    707 
    708 	switch (reg) {
    709 	case PCI_ID_REG:
    710 	case PCI_SUBSYS_ID_REG:
    711 		data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_OHCI);
    712 		break;
    713 	case PCI_COMMAND_STATUS_REG:
    714 		data = glx_get_status();
    715 		msr = rdmsr(GCSC_USB_MSR_OHCB);
    716 		if (msr & (1ULL << 34))
    717 			data |= PCI_COMMAND_MASTER_ENABLE;
    718 		if (msr & (1ULL << 33))
    719 			data |= PCI_COMMAND_MEM_ENABLE;
    720 		break;
    721 	case PCI_CLASS_REG:
    722 		msr = rdmsr(GCSC_USB_GLD_MSR_CAP);
    723 		data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
    724 		    (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
    725 		    (PCI_INTERFACE_OHCI << PCI_INTERFACE_SHIFT) |
    726 		    (msr & PCI_REVISION_MASK);
    727 		break;
    728 	case PCI_BHLC_REG:
    729 		msr = rdmsr(GCSC_GLPCI_CTRL);
    730 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
    731 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
    732 		    (0x08 << PCI_CACHELINE_SHIFT);
    733 		break;
    734 	case PCI_MAPREG_START + 0x00:
    735 		data = ohci_bar_value;
    736 		if (data == 0xffffffff)
    737 			data = PCI_MAPREG_MEM_ADDR_MASK & ~(ohci_bar_size - 1);
    738 		else {
    739 			msr = rdmsr(GCSC_USB_MSR_OHCB);
    740 			data = msr & 0xffffff00;
    741 		}
    742 		if (data != 0)
    743 			data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
    744 		break;
    745 	case PCI_CAPLISTPTR_REG:
    746 		data = 0x40;
    747 		break;
    748 	case PCI_INTERRUPT_REG:
    749 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
    750 		    (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
    751 		break;
    752 	case 0x40:	/* USB capability pointer */
    753 		data = 0;
    754 		break;
    755 	default:
    756 		data = 0;
    757 		break;
    758 	}
    759 
    760 	return data;
    761 }
    762 
    763 void
    764 glx_fn4_write(int reg, pcireg_t data)
    765 {
    766 	uint64_t msr;
    767 
    768 	switch (reg) {
    769 	case PCI_COMMAND_STATUS_REG:
    770 		msr = rdmsr(GCSC_USB_MSR_OHCB);
    771 		if (data & PCI_COMMAND_MASTER_ENABLE)
    772 			msr |= 1ULL << 34;
    773 		else
    774 			msr &= ~(1ULL << 34);
    775 		if (data & PCI_COMMAND_MEM_ENABLE)
    776 			msr |= 1ULL << 33;
    777 		else
    778 			msr &= ~(1ULL << 33);
    779 		wrmsr(GCSC_USB_MSR_OHCB, msr);
    780 		break;
    781 	case PCI_BHLC_REG:
    782 		msr = rdmsr(GCSC_GLPCI_CTRL);
    783 		msr &= 0xff00000000ULL;
    784 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
    785 		break;
    786 	case PCI_MAPREG_START + 0x00:
    787 		if (data == 0xffffffff) {
    788 			ohci_bar_value = data;
    789 		} else {
    790 			if ((data & PCI_MAPREG_TYPE_MASK) ==
    791 			    PCI_MAPREG_TYPE_MEM) {
    792 				data &= PCI_MAPREG_MEM_ADDR_MASK;
    793 				msr = rdmsr(GCSC_GLIU_P2D_BM3);
    794 				msr &= 0x0fffff0000000000ULL;
    795 				msr |= 2ULL << 61;	/* USB */
    796 				msr |= (((uint64_t)data) >> 12) << 20;
    797 				msr |= 0x000fffff;
    798 				wrmsr(GCSC_GLIU_P2D_BM3, msr);
    799 
    800 				msr = rdmsr(GCSC_USB_MSR_OHCB);
    801 				msr &= ~0xffffff00ULL;
    802 				msr |= data;
    803 			} else {
    804 				msr = rdmsr(GCSC_USB_MSR_OHCB);
    805 				msr &= ~0xffffff00ULL;
    806 			}
    807 			wrmsr(GCSC_USB_MSR_OHCB, msr);
    808 			ohci_bar_value = 0;
    809 		}
    810 		break;
    811 	default:
    812 		break;
    813 	}
    814 }
    815 
    816 /*
    817  * Function 5: EHCI Controller
    818  */
    819 
    820 static pcireg_t ehci_bar_size = 0x1000;
    821 static pcireg_t ehci_bar_value;
    822 
    823 pcireg_t
    824 glx_fn5_read(int reg)
    825 {
    826 	uint64_t msr;
    827 	pcireg_t data;
    828 
    829 	switch (reg) {
    830 	case PCI_ID_REG:
    831 	case PCI_SUBSYS_ID_REG:
    832 		data = PCI_ID_CODE(PCI_VENDOR_AMD, PCI_PRODUCT_AMD_CS5536_EHCI);
    833 		break;
    834 	case PCI_COMMAND_STATUS_REG:
    835 		data = glx_get_status();
    836 		msr = rdmsr(GCSC_USB_MSR_EHCB);
    837 		if (msr & (1ULL << 34))
    838 			data |= PCI_COMMAND_MASTER_ENABLE;
    839 		if (msr & (1ULL << 33))
    840 			data |= PCI_COMMAND_MEM_ENABLE;
    841 		break;
    842 	case PCI_CLASS_REG:
    843 		msr = rdmsr(GCSC_USB_GLD_MSR_CAP);
    844 		data = (PCI_CLASS_SERIALBUS << PCI_CLASS_SHIFT) |
    845 		    (PCI_SUBCLASS_SERIALBUS_USB << PCI_SUBCLASS_SHIFT) |
    846 		    (PCI_INTERFACE_EHCI << PCI_INTERFACE_SHIFT) |
    847 		    (msr & PCI_REVISION_MASK);
    848 		break;
    849 	case PCI_BHLC_REG:
    850 		msr = rdmsr(GCSC_GLPCI_CTRL);
    851 		data = (0x00 << PCI_HDRTYPE_SHIFT) |
    852 		    (((msr & 0xff00000000ULL) >> 32) << PCI_LATTIMER_SHIFT) |
    853 		    (0x08 << PCI_CACHELINE_SHIFT);
    854 		break;
    855 	case PCI_MAPREG_START + 0x00:
    856 		data = ehci_bar_value;
    857 		if (data == 0xffffffff)
    858 			data = PCI_MAPREG_MEM_ADDR_MASK & ~(ehci_bar_size - 1);
    859 		else {
    860 			msr = rdmsr(GCSC_USB_MSR_EHCB);
    861 			data = msr & 0xffffff00;
    862 		}
    863 		if (data != 0)
    864 			data |= PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT;
    865 		break;
    866 	case PCI_CAPLISTPTR_REG:
    867 		data = 0x40;
    868 		break;
    869 	case PCI_INTERRUPT_REG:
    870 		data = (0x40 << PCI_MAX_LAT_SHIFT) |
    871 		    (PCI_INTERRUPT_PIN_A << PCI_INTERRUPT_PIN_SHIFT);
    872 		break;
    873 	case 0x40:	/* USB capability pointer */
    874 		data = 0;
    875 		break;
    876 	case PCI_USBREV:
    877 		msr = rdmsr(GCSC_USB_MSR_EHCB);
    878 		data = PCI_USBREV_2_0;
    879 		data |= ((msr >> 40) & 0x3f) << 8;	/* PCI_EHCI_FLADJ */
    880 		break;
    881 	default:
    882 		data = 0;
    883 		break;
    884 	}
    885 
    886 	return data;
    887 }
    888 
    889 void
    890 glx_fn5_write(int reg, pcireg_t data)
    891 {
    892 	uint64_t msr;
    893 
    894 	switch (reg) {
    895 	case PCI_COMMAND_STATUS_REG:
    896 		msr = rdmsr(GCSC_USB_MSR_EHCB);
    897 		if (data & PCI_COMMAND_MASTER_ENABLE)
    898 			msr |= 1ULL << 34;
    899 		else
    900 			msr &= ~(1ULL << 34);
    901 		if (data & PCI_COMMAND_MEM_ENABLE)
    902 			msr |= 1ULL << 33;
    903 		else
    904 			msr &= ~(1ULL << 33);
    905 		wrmsr(GCSC_USB_MSR_EHCB, msr);
    906 		break;
    907 	case PCI_BHLC_REG:
    908 		msr = rdmsr(GCSC_GLPCI_CTRL);
    909 		msr &= 0xff00000000ULL;
    910 		msr |= ((uint64_t)PCI_LATTIMER(data)) << 32;
    911 		break;
    912 	case PCI_MAPREG_START + 0x00:
    913 		if (data == 0xffffffff) {
    914 			ehci_bar_value = data;
    915 		} else {
    916 			if ((data & PCI_MAPREG_TYPE_MASK) ==
    917 			    PCI_MAPREG_TYPE_MEM) {
    918 				data &= PCI_MAPREG_MEM_ADDR_MASK;
    919 				msr = rdmsr(GCSC_GLIU_P2D_BM4);
    920 				msr &= 0x0fffff0000000000ULL;
    921 				msr |= 2ULL << 61;	/* USB */
    922 				msr |= (((uint64_t)data) >> 12) << 20;
    923 				msr |= 0x000fffff;
    924 				wrmsr(GCSC_GLIU_P2D_BM4, msr);
    925 
    926 				msr = rdmsr(GCSC_USB_MSR_EHCB);
    927 				msr &= ~0xffffff00ULL;
    928 				msr |= data;
    929 			} else {
    930 				msr = rdmsr(GCSC_USB_MSR_EHCB);
    931 				msr &= ~0xffffff00ULL;
    932 			}
    933 			wrmsr(GCSC_USB_MSR_EHCB, msr);
    934 			ehci_bar_value = 0;
    935 		}
    936 		break;
    937 	default:
    938 		break;
    939 	}
    940 }
    941