> Date: Fri, 15 Mar 2019 16:07:17 -0500
> From: joshua stein <[email protected]>
>
> While making dwiic at pci attach on an Intel 300 series laptop,
> dwiic was timing out while ihidev tried to fetch the HID descriptor.
> Turns out the default timing parameters pulled from the device are
> wrong, so try to fetch them from ACPI and use those instead. This
> matches what dwiic at acpi does.
>
> If you have a device where dwiic fails in this way, this may fix the
> problem for you.
>
> dwiic0 at pci0 dev 21 function 0 "Intel 300 Series I2C" rev 0x30: apic 2 int
> 16
> iic0 at dwiic0
> ihidev0 at iic0 addr 0x15dwiic0: timed out reading remaining 29
> , failed fetching initial HID descriptor
Makes sense.
ok kettenis@
> Index: sys/dev/pci/dwiic_pci.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/pci/dwiic_pci.c,v
> retrieving revision 1.3
> diff -u -p -u -p -r1.3 dwiic_pci.c
> --- sys/dev/pci/dwiic_pci.c 12 Jan 2018 08:11:48 -0000 1.3
> +++ sys/dev/pci/dwiic_pci.c 15 Mar 2019 21:04:46 -0000
> @@ -62,6 +62,12 @@ struct cfattach dwiic_pci_ca = {
> const struct pci_matchid dwiic_pci_ids[] = {
> { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_100SERIES_LP_I2C_1 },
> { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_100SERIES_LP_I2C_2 },
> + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_1 },
> + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_2 },
> + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_3 },
> + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_4 },
> + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_5 },
> + { PCI_VENDOR_INTEL, PCI_PRODUCT_INTEL_300SERIES_U_I2C_6 },
> };
>
> int
> @@ -75,6 +81,9 @@ dwiic_pci_attach(struct device *parent,
> {
> struct dwiic_softc *sc = (struct dwiic_softc *)self;
> struct pci_attach_args *pa = aux;
> +#if NACPI > 0
> + struct aml_node *node;
> +#endif
> bus_size_t iosize;
> pci_intr_handle_t ih;
> const char *intrstr = NULL;
> @@ -109,6 +118,19 @@ dwiic_pci_attach(struct device *parent,
> sc->fs_lcnt = dwiic_read(sc, DW_IC_FS_SCL_LCNT);
> sc->sda_hold_time = dwiic_read(sc, DW_IC_SDA_HOLD);
>
> +#if NACPI > 0
> + /* fetch more accurate timing parameters from ACPI, if possible */
> + node = acpi_pci_match(self, &sc->sc_paa);
> + if (node != NULL) {
> + sc->sc_devnode = node;
> +
> + dwiic_acpi_get_params(sc, "SSCN", &sc->ss_hcnt, &sc->ss_lcnt,
> + NULL);
> + dwiic_acpi_get_params(sc, "FMCN", &sc->fs_hcnt, &sc->fs_lcnt,
> + &sc->sda_hold_time);
> + }
> +#endif
> +
> if (dwiic_init(sc)) {
> printf(": failed initializing\n");
> return;
> @@ -184,12 +206,7 @@ dwiic_pci_bus_scan(struct device *iic, s
>
> sc->sc_iic = iic;
>
> -#if NACPI > 0
> - {
> - struct aml_node *node = acpi_pci_match(aux, &sc->sc_paa);
> - if (node == NULL)
> - return;
> -
> + if (sc->sc_devnode != NULL) {
> /*
> * XXX: until we can figure out why interrupts don't arrive for
> * i2c slave devices on intel 100 series and newer, force
> @@ -197,7 +214,6 @@ dwiic_pci_bus_scan(struct device *iic, s
> */
> sc->sc_poll_ihidev = 1;
>
> - aml_find_node(node, "_HID", dwiic_acpi_found_hid, sc);
> + aml_find_node(sc->sc_devnode, "_HID", dwiic_acpi_found_hid, sc);
> }
> -#endif
> }
> Index: sys/dev/ic/dwiicvar.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/dwiicvar.h,v
> retrieving revision 1.2
> diff -u -p -u -p -r1.2 dwiicvar.h
> --- sys/dev/ic/dwiicvar.h 19 Jan 2018 18:20:38 -0000 1.2
> +++ sys/dev/ic/dwiicvar.h 15 Mar 2019 21:04:46 -0000
> @@ -34,6 +34,8 @@
>
> #include <dev/ic/dwiicreg.h>
>
> +#include "acpi.h"
> +
> /* #define DWIIC_DEBUG */
>
> #ifdef DWIIC_DEBUG
> @@ -99,4 +101,8 @@ void dwiic_write(struct dwiic_softc *,
> int dwiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *,
> size_t, void *, size_t, int);
>
> -int dwiic_acpi_found_hid(struct aml_node *node, void *arg);
> +#if NACPI > 0
> +int dwiic_acpi_found_hid(struct aml_node *, void *);
> +void dwiic_acpi_get_params(struct dwiic_softc *, char *, uint16_t *,
> + uint16_t *, uint32_t *);
> +#endif
>
>