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