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

Reply via email to