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