Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev hdaudio: pci: PCIe config space fixes and Intel PCH ...



details:   https://anonhg.NetBSD.org/src/rev/8a01c6d96db8
branches:  trunk
changeset: 364403:8a01c6d96db8
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Mon Mar 21 09:12:09 2022 +0000

description:
hdaudio: pci: PCIe config space fixes and Intel PCH snoop support

The HD audio specification does not cover PCI config space, and this
driver was unconditionally writing to a vendor specific register. Reduce
scope of config space accesses based on PCI IDs.

With this cleaned up, add support for Intel PCH devices which require
some additional vendor specific configuration to bypass no snoop mode.

diffstat:

 sys/dev/hdaudio/hdaudioreg.h |  10 +-----
 sys/dev/pci/hdaudio_pci.c    |  76 +++++++++++++++++++++++++++++++------------
 sys/dev/pci/hdaudio_pci.h    |  20 +++++++++--
 3 files changed, 71 insertions(+), 35 deletions(-)

diffs (211 lines):

diff -r c793f03e0c61 -r 8a01c6d96db8 sys/dev/hdaudio/hdaudioreg.h
--- a/sys/dev/hdaudio/hdaudioreg.h      Mon Mar 21 00:25:04 2022 +0000
+++ b/sys/dev/hdaudio/hdaudioreg.h      Mon Mar 21 09:12:09 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudioreg.h,v 1.3 2019/01/07 01:03:05 mrg Exp $ */
+/* $NetBSD: hdaudioreg.h,v 1.4 2022/03/21 09:12:10 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2009 Precedence Technologies Ltd <support%precedence.co.uk@localhost>
@@ -36,14 +36,6 @@
 #include <sys/types.h>
 
 /*
- * High Definition Audio Audio PCI Configuration Space
- */
-#define        HDAUDIO_PCI_AZBARL      0x10
-#define        HDAUDIO_PCI_AZBARU      0x14
-#define        HDAUDIO_PCI_AZCTL       0x40
-#define        HDAUDIO_PCI_TCSEL       0x44
-
-/*
  * High Definition Audio Memory Mapped Configuration Registers
  */
 #define        HDAUDIO_MMIO_GCAP       0x000
diff -r c793f03e0c61 -r 8a01c6d96db8 sys/dev/pci/hdaudio_pci.c
--- a/sys/dev/pci/hdaudio_pci.c Mon Mar 21 00:25:04 2022 +0000
+++ b/sys/dev/pci/hdaudio_pci.c Mon Mar 21 09:12:09 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudio_pci.c,v 1.11 2021/10/28 09:15:35 msaitoh Exp $ */
+/* $NetBSD: hdaudio_pci.c,v 1.12 2022/03/21 09:12:09 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2009 Precedence Technologies Ltd <support%precedence.co.uk@localhost>
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hdaudio_pci.c,v 1.11 2021/10/28 09:15:35 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hdaudio_pci.c,v 1.12 2022/03/21 09:12:09 jmcneill Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -61,6 +61,11 @@
        pci_intr_handle_t       *sc_pihp;
 };
 
+#define        HDAUDIO_PCI_IS_INTEL(sc)        \
+       (PCI_VENDOR(sc->sc_id) == PCI_VENDOR_INTEL)
+#define        HDAUDIO_PCI_IS_NVIDIA(sc)       \
+       (PCI_VENDOR(sc->sc_id) == PCI_VENDOR_NVIDIA)
+
 static int     hdaudio_pci_match(device_t, cfdata_t, void *);
 static void    hdaudio_pci_attach(device_t, device_t, void *);
 static int     hdaudio_pci_detach(device_t, int);
@@ -68,7 +73,7 @@
 static void    hdaudio_pci_childdet(device_t, device_t);
 
 static int     hdaudio_pci_intr(void *);
-static void    hdaudio_pci_reinit(struct hdaudio_pci_softc *);
+static void    hdaudio_pci_init(struct hdaudio_pci_softc *);
 
 /* power management */
 static bool    hdaudio_pci_resume(device_t, const pmf_qual_t *);
@@ -139,7 +144,7 @@
        pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, csr);
 
        /* Map MMIO registers */
-       reg = HDAUDIO_PCI_AZBARL;
+       reg = PCI_BAR0;
        maptype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, reg);
        err = pci_mapreg_map(pa, reg, maptype, 0,
                             &sc->sc_hdaudio.sc_memt,
@@ -174,7 +179,7 @@
        }
        aprint_normal_dev(self, "interrupting at %s\n", intrstr);
 
-       hdaudio_pci_reinit(sc);
+       hdaudio_pci_init(sc);
 
        /* Attach bus-independent HD audio layer */
        if (hdaudio_attach(self, &sc->sc_hdaudio)) {
@@ -187,15 +192,18 @@
                sc->sc_hdaudio.sc_memvalid = false;
                csr = pci_conf_read(sc->sc_pc, sc->sc_tag,
                    PCI_COMMAND_STATUS_REG);
-               csr &= ~(PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_BACKTOBACK_ENABLE);
+               csr &= ~(PCI_COMMAND_MASTER_ENABLE |
+                        PCI_COMMAND_BACKTOBACK_ENABLE);
                pci_conf_write(sc->sc_pc, sc->sc_tag,
                    PCI_COMMAND_STATUS_REG, csr);
 
-               if (!pmf_device_register(self, NULL, NULL))
-                       aprint_error_dev(self, "couldn't establish power handler\n");
+               if (!pmf_device_register(self, NULL, NULL)) {
+                       aprint_error_dev(self,
+                           "couldn't establish power handler\n");
+               }
+       } else if (!pmf_device_register(self, NULL, hdaudio_pci_resume)) {
+               aprint_error_dev(self, "couldn't establish power handler\n");
        }
-       else if (!pmf_device_register(self, NULL, hdaudio_pci_resume))
-               aprint_error_dev(self, "couldn't establish power handler\n");
 }
 
 static int
@@ -252,28 +260,51 @@
        return hdaudio_intr(&sc->sc_hdaudio);
 }
 
-
 static void
-hdaudio_pci_reinit(struct hdaudio_pci_softc *sc)
+hdaudio_pci_init(struct hdaudio_pci_softc *sc)
 {
        pcireg_t val;
 
-       /* stops playback static */
-       val = pci_conf_read(sc->sc_pc, sc->sc_tag, HDAUDIO_PCI_TCSEL);
-       val &= ~7;
-       val |= 0;
-       pci_conf_write(sc->sc_pc, sc->sc_tag, HDAUDIO_PCI_TCSEL, val);
+       if (HDAUDIO_PCI_IS_INTEL(sc)) {
+               /*
+                * ICH: Set traffic class for input/output/buf descriptors
+                * to TC0. For PCH without a TCSEL register, PGCTL is in
+                * the same location and clearing these bits is harmless.
+                */
+               val = pci_conf_read(sc->sc_pc, sc->sc_tag,
+                   HDAUDIO_INTEL_REG_ICH_TCSEL);
+               val &= ~HDAUDIO_INTEL_ICH_TCSEL_MASK;
+               val |= HDAUDIO_INTEL_ICH_TCSEL_TC0;
+               pci_conf_write(sc->sc_pc, sc->sc_tag,
+                   HDAUDIO_INTEL_REG_ICH_TCSEL, val);
 
-       switch (PCI_VENDOR(sc->sc_id)) {
-       case PCI_VENDOR_NVIDIA:
-               /* enable snooping */
+               /*
+                * PCH: Disable dynamic clock gating logic. Implementations
+                * without a CGCTL register do not appear to have anything
+                * else in its place.
+                */
+               val = pci_conf_read(sc->sc_pc, sc->sc_tag,
+                   HDAUDIO_INTEL_REG_PCH_CGCTL);
+               val &= ~HDAUDIO_INTEL_PCH_CGCTL_MISCBDCGE;
+               pci_conf_write(sc->sc_pc, sc->sc_tag,
+                   HDAUDIO_INTEL_REG_PCH_CGCTL, val);
+
+               /* ICH/PCH: Enable snooping. */
+               val = pci_conf_read(sc->sc_pc, sc->sc_tag,
+                   HDAUDIO_INTEL_REG_PCH_DEVC);
+               val &= ~HDAUDIO_INTEL_PCH_DEVC_NSNPEN;
+               pci_conf_write(sc->sc_pc, sc->sc_tag,
+                   HDAUDIO_INTEL_REG_PCH_DEVC, val);
+       }
+
+       if (HDAUDIO_PCI_IS_NVIDIA(sc)) {
+               /* Enable snooping. */
                val = pci_conf_read(sc->sc_pc, sc->sc_tag,
                    HDAUDIO_NV_REG_SNOOP);
                val &= ~HDAUDIO_NV_SNOOP_MASK;
                val |= HDAUDIO_NV_SNOOP_ENABLE;
                pci_conf_write(sc->sc_pc, sc->sc_tag,
                    HDAUDIO_NV_REG_SNOOP, val);
-               break;
        }
 }
 
@@ -282,7 +313,8 @@
 {
        struct hdaudio_pci_softc *sc = device_private(self);
 
-       hdaudio_pci_reinit(sc);
+       hdaudio_pci_init(sc);
+
        return hdaudio_resume(&sc->sc_hdaudio);
 }
 
diff -r c793f03e0c61 -r 8a01c6d96db8 sys/dev/pci/hdaudio_pci.h
--- a/sys/dev/pci/hdaudio_pci.h Mon Mar 21 00:25:04 2022 +0000
+++ b/sys/dev/pci/hdaudio_pci.h Mon Mar 21 09:12:09 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: hdaudio_pci.h,v 1.1 2015/03/28 14:09:59 jmcneill Exp $ */
+/* $NetBSD: hdaudio_pci.h,v 1.2 2022/03/21 09:12:09 jmcneill Exp $ */
 
 /*
  * Copyright (c) 2010 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -31,8 +31,20 @@
 #ifndef _HDAUDIO_PCI_H
 #define _HDAUDIO_PCI_H
 
-#define        HDAUDIO_NV_REG_SNOOP    0x4c
-#define          HDAUDIO_NV_SNOOP_MASK         0x00ff0000
-#define          HDAUDIO_NV_SNOOP_ENABLE       0x000f0000
+/* NVIDIA specific registers */
+#define        HDAUDIO_NV_REG_SNOOP            0x4c
+#define          HDAUDIO_NV_SNOOP_MASK                 0x00ff0000
+#define          HDAUDIO_NV_SNOOP_ENABLE               0x000f0000
+
+/* Intel ICH specific registers */
+#define        HDAUDIO_INTEL_REG_ICH_TCSEL     0x44
+#define         HDAUDIO_INTEL_ICH_TCSEL_MASK           __BITS(2,0)
+#define         HDAUDIO_INTEL_ICH_TCSEL_TC0            0
+
+/* Intel 100 Series Chipset Family Platform Controller Hub (PCH) */
+#define        HDAUDIO_INTEL_REG_PCH_CGCTL     0x48
+#define          HDAUDIO_INTEL_PCH_CGCTL_MISCBDCGE     __BIT(6)
+#define        HDAUDIO_INTEL_REG_PCH_DEVC      0x78
+#define          HDAUDIO_INTEL_PCH_DEVC_NSNPEN         __BIT(11)
 
 #endif /* !_HDAUDIO_PCI_H */



Home | Main Index | Thread Index | Old Index