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