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