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);