Module Name:    src
Committed By:   skrll
Date:           Wed May 27 07:22:52 UTC 2015

Modified Files:
        src/sys/dev/pci [nick-nhusb]: xhci_pci.c
        src/sys/dev/usb [nick-nhusb]: xhci.c

Log Message:
Add patch for intel chips quirk from ryoon@ in
    https://mail-index.netbsd.org/netbsd-bugs/2014/08/31/msg038109.html
slightly modified to set quirks before calling xhci_init.

Set special IMOD value and route ports to xhci for intel chips.

>From Takahiro HAYASHI.


To generate a diff of this commit:
cvs rdiff -u -r1.4.2.2 -r1.4.2.3 src/sys/dev/pci/xhci_pci.c
cvs rdiff -u -r1.28.2.25 -r1.28.2.26 src/sys/dev/usb/xhci.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/xhci_pci.c
diff -u src/sys/dev/pci/xhci_pci.c:1.4.2.2 src/sys/dev/pci/xhci_pci.c:1.4.2.3
--- src/sys/dev/pci/xhci_pci.c:1.4.2.2	Mon Apr  6 12:17:30 2015
+++ src/sys/dev/pci/xhci_pci.c	Wed May 27 07:22:51 2015
@@ -1,4 +1,5 @@
-/*	$NetBSD: xhci_pci.c,v 1.4.2.2 2015/04/06 12:17:30 skrll Exp $	*/
+/*	$NetBSD: xhci_pci.c,v 1.4.2.3 2015/05/27 07:22:51 skrll Exp $	*/
+/*	OpenBSD: xhci_pci.c,v 1.4 2014/07/12 17:38:51 yuo Exp	*/
 
 /*
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -31,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci_pci.c,v 1.4.2.2 2015/04/06 12:17:30 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci_pci.c,v 1.4.2.3 2015/05/27 07:22:51 skrll Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -43,6 +44,7 @@ __KERNEL_RCSID(0, "$NetBSD: xhci_pci.c,v
 #include <sys/bus.h>
 
 #include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -52,6 +54,17 @@ __KERNEL_RCSID(0, "$NetBSD: xhci_pci.c,v
 #include <dev/usb/xhcireg.h>
 #include <dev/usb/xhcivar.h>
 
+struct xhci_pci_quirk {
+	pci_vendor_id_t		vendor;
+	pci_product_id_t	product;
+	int			quirks;
+};
+
+static const struct xhci_pci_quirk xhci_pci_quirks[] = {
+	{ PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_CORE4G_M_XHCI,
+	    XHCI_QUIRK_FORCE_INTR },
+};
+
 struct xhci_pci_softc {
 	struct xhci_softc	sc_xhci;
 	pci_chipset_tag_t	sc_pc;
@@ -59,6 +72,18 @@ struct xhci_pci_softc {
 };
 
 static int
+xhci_pci_has_quirk(pci_vendor_id_t vendor, pci_product_id_t product)
+{
+	int i;
+
+	for (i = 0; i < __arraycount(xhci_pci_quirks); i++)
+		if (vendor == xhci_pci_quirks[i].vendor &&
+		    product == xhci_pci_quirks[i].product)
+			return xhci_pci_quirks[i].quirks;
+	return 0;
+}
+
+static int
 xhci_pci_match(device_t parent, cfdata_t match, void *aux)
 {
 	struct pci_attach_args *pa = (struct pci_attach_args *) aux;
@@ -71,6 +96,42 @@ xhci_pci_match(device_t parent, cfdata_t
 	return 0;
 }
 
+static int
+xhci_pci_port_route(struct xhci_pci_softc *psc)
+{
+	struct xhci_softc * const sc = &psc->sc_xhci;
+
+	pcireg_t val;
+
+	/*
+	 * Check USB3 Port Routing Mask register that indicates the ports
+	 * can be changed from OS, and turn on by USB3 Port SS Enable register.
+	 */
+	val = pci_conf_read(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_USB3PRM);
+	aprint_debug_dev(sc->sc_dev,
+	    "USB3PRM / USB3.0 configurable ports: 0x%08x\n", val);
+
+	pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_USB3_PSSEN, val);
+	val = pci_conf_read(psc->sc_pc, psc->sc_tag,PCI_XHCI_INTEL_USB3_PSSEN);
+	aprint_debug_dev(sc->sc_dev,
+	    "USB3_PSSEN / Enabled USB3.0 ports under xHCI: 0x%08x\n", val);
+
+	/*
+	 * Check USB2 Port Routing Mask register that indicates the USB2.0
+	 * ports to be controlled by xHCI HC, and switch them to xHCI HC.
+	 */
+	val = pci_conf_read(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_USB2PRM);
+	aprint_debug_dev(sc->sc_dev,
+	    "XUSB2PRM / USB2.0 ports can switch from EHCI to xHCI:"
+	    "0x%08x\n", val);
+	pci_conf_write(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_XUSB2PR, val);
+	val = pci_conf_read(psc->sc_pc, psc->sc_tag, PCI_XHCI_INTEL_XUSB2PR);
+	aprint_debug_dev(sc->sc_dev,
+	    "XUSB2PR / USB2.0 ports under xHCI: 0x%08x\n", val);
+
+	return 0;
+}
+
 static void
 xhci_pci_attach(device_t parent, device_t self, void *aux)
 {
@@ -92,6 +153,10 @@ xhci_pci_attach(device_t parent, device_
 
 	pci_aprint_devinfo(pa, "USB Controller");
 
+	/* Check for quirks */
+	sc->sc_quirks = xhci_pci_has_quirk(PCI_VENDOR(pa->pa_id),
+						PCI_PRODUCT(pa->pa_id));
+
 	/* check if memory space access is enabled */
 	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
 #ifdef DEBUG
@@ -122,9 +187,9 @@ xhci_pci_attach(device_t parent, device_
 	psc->sc_pc = pc;
 	psc->sc_tag = tag;
 
-	hccparams = bus_space_read_4(sc->sc_iot, sc->sc_ioh, 0x10);
+	hccparams = bus_space_read_4(sc->sc_iot, sc->sc_ioh, XHCI_HCCPARAMS);
 
-	if (pci_dma64_available(pa) && ((hccparams&1)==1))
+	if (pci_dma64_available(pa) && (XHCI_HCC_AC64(hccparams) != 0))
 		sc->sc_bus.ub_dmatag = pa->pa_dmat64;
 	else
 		sc->sc_bus.ub_dmatag = pa->pa_dmat;
@@ -160,12 +225,24 @@ xhci_pci_attach(device_t parent, device_
 	    sc->sc_id_vendor);
 #endif
 
+	/* Intel chipset requires SuperSpeed enable and USB2 port routing */
+	switch (PCI_VENDOR(pa->pa_id)) {
+	case PCI_VENDOR_INTEL:
+		sc->sc_quirks |= XHCI_QUIRK_INTEL;
+		break;
+	default:
+		break;
+	}
+
 	err = xhci_init(sc);
 	if (err) {
 		aprint_error_dev(self, "init failed, error=%d\n", err);
 		goto fail;
 	}
 
+	if ((sc->sc_quirks & XHCI_QUIRK_INTEL) != 0)
+		xhci_pci_port_route(psc);
+
 	if (!pmf_device_register1(self, xhci_suspend, xhci_resume,
 	                          xhci_shutdown))
 		aprint_error_dev(self, "couldn't establish power handler\n");

Index: src/sys/dev/usb/xhci.c
diff -u src/sys/dev/usb/xhci.c:1.28.2.25 src/sys/dev/usb/xhci.c:1.28.2.26
--- src/sys/dev/usb/xhci.c:1.28.2.25	Wed May 27 07:08:16 2015
+++ src/sys/dev/usb/xhci.c	Wed May 27 07:22:51 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: xhci.c,v 1.28.2.25 2015/05/27 07:08:16 skrll Exp $	*/
+/*	$NetBSD: xhci.c,v 1.28.2.26 2015/05/27 07:22:51 skrll Exp $	*/
 
 /*
  * Copyright (c) 2013 Jonathan A. Kollasch
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.25 2015/05/27 07:08:16 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: xhci.c,v 1.28.2.26 2015/05/27 07:22:51 skrll Exp $");
 
 #include "opt_usb.h"
 
@@ -910,13 +910,13 @@ xhci_init(struct xhci_softc *sc)
 #endif
 
 	xhci_rt_write_4(sc, XHCI_IMAN(0), XHCI_IMAN_INTR_ENA);
-#ifdef XHCI_QUIRK_INTEL
 	if ((sc->sc_quirks & XHCI_QUIRK_INTEL) != 0)
 		/* Intel xhci needs interrupt rate moderated. */
 		xhci_rt_write_4(sc, XHCI_IMOD(0), XHCI_IMOD_DEFAULT_LP);
 	else
-#endif /* XHCI_QUIRK_INTEL */
 		xhci_rt_write_4(sc, XHCI_IMOD(0), 0);
+	aprint_debug_dev(sc->sc_dev, "setting IMOD %u\n",
+	    xhci_rt_read_4(sc, XHCI_IMOD(0)));
 
 	xhci_op_write_4(sc, XHCI_USBCMD, XHCI_CMD_INTE|XHCI_CMD_RS); /* Go! */
 	aprint_debug_dev(sc->sc_dev, "USBCMD %08"PRIx32"\n",
@@ -977,7 +977,6 @@ xhci_intr1(struct xhci_softc * const sc)
 
 	iman = xhci_rt_read_4(sc, XHCI_IMAN(0));
 	DPRINTFN(16, "IMAN0 %08x", iman, 0, 0, 0);
-#ifdef XHCI_QUIRK_FORCE_INTR
 
 	if (!(sc->sc_quirks & XHCI_QUIRK_FORCE_INTR)) {
 		if ((iman & XHCI_IMAN_INTR_PEND) == 0) {
@@ -985,11 +984,6 @@ xhci_intr1(struct xhci_softc * const sc)
 		}
 	}
 
-#else
-	if ((iman & XHCI_IMAN_INTR_PEND) == 0) {
-		return 0;
-	}
-#endif /* XHCI_QUIRK_FORCE_INTR */
 	xhci_rt_write_4(sc, XHCI_IMAN(0), iman);
 	iman = xhci_rt_read_4(sc, XHCI_IMAN(0));
 	DPRINTFN(16, "IMAN0 %08x", iman, 0, 0, 0);

Reply via email to