FreeBSD Bugzilla – Attachment 185729 Details for
Bug 221777
merge the latest changes to the ig4 module from DragonFly BSD and add Kaby Lake / Intel 100 series platform support
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for ig4
ig4.patch (text/plain), 13.00 KB, created by
marc.priggemeyer
on 2017-08-24 20:46:14 UTC
(
hide
)
Description:
Patch for ig4
Filename:
MIME Type:
Creator:
marc.priggemeyer
Created:
2017-08-24 20:46:14 UTC
Size:
13.00 KB
patch
obsolete
>diff --git a/sys/dev/ichiic/ig4_acpi.c b/sys/dev/ichiic/ig4_acpi.c >index 90d6214bf72..882685abf1f 100644 >--- a/sys/dev/ichiic/ig4_acpi.c >+++ b/sys/dev/ichiic/ig4_acpi.c >@@ -85,6 +85,8 @@ ig4iic_acpi_attach(device_t dev) > sc = device_get_softc(dev); > > sc->dev = dev; >+ /* All the HIDs matched are Atom SOCs. */ >+ sc->version = IG4_ATOM; > sc->regs_rid = 0; > sc->regs_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, > &sc->regs_rid, RF_ACTIVE); >diff --git a/sys/dev/ichiic/ig4_iic.c b/sys/dev/ichiic/ig4_iic.c >index b99ce3a1fe7..0948f4f9321 100644 >--- a/sys/dev/ichiic/ig4_iic.c >+++ b/sys/dev/ichiic/ig4_iic.c >@@ -117,8 +117,9 @@ set_controller(ig4iic_softc_t *sc, uint32_t ctl) > reg_write(sc, IG4_REG_INTR_MASK, IG4_INTR_STOP_DET | > IG4_INTR_RX_FULL); > reg_read(sc, IG4_REG_CLR_INTR); >- } else >+ } else { > reg_write(sc, IG4_REG_INTR_MASK, 0); >+ } > > reg_write(sc, IG4_REG_I2C_EN, ctl); > error = IIC_ETIMEOUT; >@@ -134,6 +135,8 @@ set_controller(ig4iic_softc_t *sc, uint32_t ctl) > else > mtx_sleep(sc, &sc->io_lock, 0, "i2cslv", 1); > } >+ >+ > return (error); > } > >@@ -525,23 +528,53 @@ ig4iic_attach(ig4iic_softc_t *sc) > mtx_init(&sc->io_lock, "IG4 I/O lock", NULL, MTX_DEF); > sx_init(&sc->call_lock, "IG4 call lock"); > >+ v = reg_read(sc, IG4_REG_DEVIDLE_CTRL); >+ if (sc->version == IG4_SKYLAKE && (v & IG4_RESTORE_REQUIRED) ) { >+ reg_write(sc, IG4_REG_DEVIDLE_CTRL, IG4_DEVICE_IDLE | IG4_RESTORE_REQUIRED); >+ reg_write(sc, IG4_REG_DEVIDLE_CTRL, 0); >+ >+ reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_ASSERT_SKL); >+ reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_DEASSERT_SKL); >+ DELAY(1000); >+ } >+ > v = reg_read(sc, IG4_REG_COMP_TYPE); > v = reg_read(sc, IG4_REG_COMP_PARAM1); > v = reg_read(sc, IG4_REG_GENERAL); >- if ((v & IG4_GENERAL_SWMODE) == 0) { >- v |= IG4_GENERAL_SWMODE; >- reg_write(sc, IG4_REG_GENERAL, v); >- v = reg_read(sc, IG4_REG_GENERAL); >+ if (sc->version == IG4_ATOM) { >+ v = reg_read(sc, IG4_REG_COMP_TYPE); >+ } >+ if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { >+ v = reg_read(sc, IG4_REG_COMP_PARAM1); >+ v = reg_read(sc, IG4_REG_GENERAL); >+ /* >+ * The content of IG4_REG_GENERAL is different for each >+ * controller version. >+ */ >+ if (sc->version == IG4_HASWELL && >+ (v & IG4_GENERAL_SWMODE) == 0) { >+ v |= IG4_GENERAL_SWMODE; >+ reg_write(sc, IG4_REG_GENERAL, v); >+ v = reg_read(sc, IG4_REG_GENERAL); >+ } > } > >- v = reg_read(sc, IG4_REG_SW_LTR_VALUE); >- v = reg_read(sc, IG4_REG_AUTO_LTR_VALUE); >+ if (sc->version == IG4_HASWELL) { >+ v = reg_read(sc, IG4_REG_SW_LTR_VALUE); >+ v = reg_read(sc, IG4_REG_AUTO_LTR_VALUE); >+ } else if (sc->version == IG4_SKYLAKE) { >+ v = reg_read(sc, IG4_REG_ACTIVE_LTR_VALUE); >+ v = reg_read(sc, IG4_REG_IDLE_LTR_VALUE); >+ } > >- v = reg_read(sc, IG4_REG_COMP_VER); >- if (v != IG4_COMP_VER) { >- error = ENXIO; >- goto done; >+ if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { >+ v = reg_read(sc, IG4_REG_COMP_VER); >+ if (v != IG4_COMP_VER) { >+ error = ENXIO; >+ goto done; >+ } > } >+ > v = reg_read(sc, IG4_REG_SS_SCL_HCNT); > v = reg_read(sc, IG4_REG_SS_SCL_LCNT); > v = reg_read(sc, IG4_REG_FS_SCL_HCNT); >@@ -591,8 +624,10 @@ ig4iic_attach(ig4iic_softc_t *sc) > /* > * Don't do this, it blows up the PCI config > */ >- reg_write(sc, IG4_REG_RESETS, IG4_RESETS_ASSERT); >- reg_write(sc, IG4_REG_RESETS, IG4_RESETS_DEASSERT); >+ if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { >+ reg_write(sc, IG4_REG_RESETS_HSW, IG4_RESETS_ASSERT_HSW); >+ reg_write(sc, IG4_REG_RESETS_HSW, IG4_RESETS_DEASSERT_HSW); >+ } > #endif > > mtx_lock(&sc->io_lock); >@@ -727,14 +762,27 @@ ig4iic_dump(ig4iic_softc_t *sc) > REGDUMP(sc, IG4_REG_DMA_RDLR); > REGDUMP(sc, IG4_REG_SDA_SETUP); > REGDUMP(sc, IG4_REG_ENABLE_STATUS); >- REGDUMP(sc, IG4_REG_COMP_PARAM1); >- REGDUMP(sc, IG4_REG_COMP_VER); >- REGDUMP(sc, IG4_REG_COMP_TYPE); >- REGDUMP(sc, IG4_REG_CLK_PARMS); >- REGDUMP(sc, IG4_REG_RESETS); >- REGDUMP(sc, IG4_REG_GENERAL); >- REGDUMP(sc, IG4_REG_SW_LTR_VALUE); >- REGDUMP(sc, IG4_REG_AUTO_LTR_VALUE); >+ if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { >+ REGDUMP(sc, IG4_REG_COMP_PARAM1); >+ REGDUMP(sc, IG4_REG_COMP_VER); >+ } >+ if (sc->version == IG4_ATOM) { >+ REGDUMP(sc, IG4_REG_COMP_TYPE); >+ REGDUMP(sc, IG4_REG_CLK_PARMS); >+ } >+ if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { >+ REGDUMP(sc, IG4_REG_RESETS_HSW); >+ REGDUMP(sc, IG4_REG_GENERAL); >+ } else if (sc->version == IG4_SKYLAKE) { >+ REGDUMP(sc, IG4_REG_RESETS_SKL); >+ } >+ if (sc->version == IG4_HASWELL) { >+ REGDUMP(sc, IG4_REG_SW_LTR_VALUE); >+ REGDUMP(sc, IG4_REG_AUTO_LTR_VALUE); >+ } else if (sc->version == IG4_SKYLAKE) { >+ REGDUMP(sc, IG4_REG_ACTIVE_LTR_VALUE); >+ REGDUMP(sc, IG4_REG_IDLE_LTR_VALUE); >+ } > } > #undef REGDUMP > >diff --git a/sys/dev/ichiic/ig4_pci.c b/sys/dev/ichiic/ig4_pci.c >index 04e31d654f6..d112fbffa18 100644 >--- a/sys/dev/ichiic/ig4_pci.c >+++ b/sys/dev/ichiic/ig4_pci.c >@@ -66,46 +66,62 @@ __FBSDID("$FreeBSD$"); > > static int ig4iic_pci_detach(device_t dev); > >-#define PCI_CHIP_LYNXPT_LP_I2C_1 0x9c618086 >-#define PCI_CHIP_LYNXPT_LP_I2C_2 0x9c628086 >-#define PCI_CHIP_BRASWELL_I2C_1 0x22c18086 >-#define PCI_CHIP_BRASWELL_I2C_2 0x22c28086 >-#define PCI_CHIP_BRASWELL_I2C_3 0x22c38086 >-#define PCI_CHIP_BRASWELL_I2C_5 0x22c58086 >-#define PCI_CHIP_BRASWELL_I2C_6 0x22c68086 >-#define PCI_CHIP_BRASWELL_I2C_7 0x22c78086 >+#ifndef NELEM >+#define NELEM(ary) (sizeof(ary) / sizeof((ary)[0])) >+#endif >+ >+static struct { >+ uint32_t id; >+ char *name; >+ enum ig4_vers version; >+} intel_i2c_ids[] = { >+ /* Haswell */ >+ { 0x9c618086, "Intel Lynx Point-LP I2C Controller-1", IG4_HASWELL }, >+ { 0x9c628086, "Intel Lynx Point-LP I2C Controller-2", IG4_HASWELL }, >+ >+ /* Braswell */ >+ { 0x22c18086, "Intel Braswell Serial I/O I2C Port 1", IG4_HASWELL }, >+ { 0x22c28086, "Intel Braswell Serial I/O I2C Port 2", IG4_HASWELL }, >+ { 0x22c38086, "Intel Braswell Serial I/O I2C Port 3", IG4_HASWELL }, >+ { 0x22c58086, "Intel Braswell Serial I/O I2C Port 4", IG4_HASWELL }, >+ { 0x22c68086, "Intel Braswell Serial I/O I2C Port 6", IG4_HASWELL }, >+ { 0x22c78086, "Intel Braswell Serial I/O I2C Port 7", IG4_HASWELL }, >+ >+ /* Skylake-U/Y and Kaby Lake-U/Y CPUs */ >+ { 0x9d608086, "Intel Sunrise Point-LP I2C Controller-0", IG4_SKYLAKE }, >+ { 0x9d618086, "Intel Sunrise Point-LP I2C Controller-1", IG4_SKYLAKE }, >+ { 0x9d628086, "Intel Sunrise Point-LP I2C Controller-2", IG4_SKYLAKE }, >+ { 0x9d638086, "Intel Sunrise Point-LP I2C Controller-3", IG4_SKYLAKE }, >+ { 0x9d648086, "Intel Sunrise Point-LP I2C Controller-4", IG4_SKYLAKE }, >+ { 0x9d658086, "Intel Sunrise Point-LP I2C Controller-5", IG4_SKYLAKE }, >+ >+ /* Kabylake-H CPUs*/ >+ { 0xa1608086, "Intel Sunrise Point-H I2C Controller-0", IG4_SKYLAKE }, >+ { 0xa1618086, "Intel Sunrise Point-H I2C Controller-1", IG4_SKYLAKE }, >+}; > > static int > ig4iic_pci_probe(device_t dev) > { >- switch(pci_get_devid(dev)) { >- case PCI_CHIP_LYNXPT_LP_I2C_1: >- device_set_desc(dev, "Intel Lynx Point-LP I2C Controller-1"); >- break; >- case PCI_CHIP_LYNXPT_LP_I2C_2: >- device_set_desc(dev, "Intel Lynx Point-LP I2C Controller-2"); >- break; >- case PCI_CHIP_BRASWELL_I2C_1: >- device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 1"); >- break; >- case PCI_CHIP_BRASWELL_I2C_2: >- device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 2"); >- break; >- case PCI_CHIP_BRASWELL_I2C_3: >- device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 3"); >- break; >- case PCI_CHIP_BRASWELL_I2C_5: >- device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 5"); >- break; >- case PCI_CHIP_BRASWELL_I2C_6: >- device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 6"); >- break; >- case PCI_CHIP_BRASWELL_I2C_7: >- device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 7"); >- break; >- default: >+ int i; >+ uint32_t device_id; >+ const char *name = NULL; >+ >+ device_id = pci_get_devid(dev); >+ for (i = 0; i < NELEM(intel_i2c_ids); i++) { >+ if (intel_i2c_ids[i].id == device_id) { >+ name = intel_i2c_ids[i].name; >+ device_printf(dev, "found %s\n", name); >+ break; >+ } >+ } >+ >+ if (name != NULL) { >+ device_set_desc(dev, name); >+ } else { > return (ENXIO); > } >+ > return (BUS_PROBE_DEFAULT); > } > >@@ -113,7 +129,16 @@ static int > ig4iic_pci_attach(device_t dev) > { > ig4iic_softc_t *sc = device_get_softc(dev); >- int error; >+ int error, i; >+ uint32_t device_id; >+ >+ device_id = pci_get_devid(dev); >+ for (i = 0; i < NELEM(intel_i2c_ids); i++) { >+ if (intel_i2c_ids[i].id == device_id) { >+ sc->version = intel_i2c_ids[i].version; >+ break; >+ } >+ } > > sc->dev = dev; > sc->regs_rid = PCIR_BAR(0); >@@ -194,8 +219,7 @@ static driver_t ig4iic_pci_driver = { > > static devclass_t ig4iic_pci_devclass; > >-DRIVER_MODULE_ORDERED(ig4iic_pci, pci, ig4iic_pci_driver, ig4iic_pci_devclass, 0, 0, >- SI_ORDER_ANY); >+DRIVER_MODULE(ig4iic_pci, pci, ig4iic_pci_driver, ig4iic_pci_devclass, 0, 0); > MODULE_DEPEND(ig4iic_pci, pci, 1, 1, 1); > MODULE_DEPEND(ig4iic_pci, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); > MODULE_VERSION(ig4iic_pci, 1); >diff --git a/sys/dev/ichiic/ig4_reg.h b/sys/dev/ichiic/ig4_reg.h >index f1288dee9e4..da1d30d241c 100644 >--- a/sys/dev/ichiic/ig4_reg.h >+++ b/sys/dev/ichiic/ig4_reg.h >@@ -78,6 +78,7 @@ > > #define IG4_REG_CTL 0x0000 /* RW Control Register */ > #define IG4_REG_TAR_ADD 0x0004 /* RW Target Address */ >+#define IG4_REG_HS_MADDR 0x000C /* RW High Speed Master Mode Code Address*/ > #define IG4_REG_DATA_CMD 0x0010 /* RW Data Buffer and Command */ > #define IG4_REG_SS_SCL_HCNT 0x0014 /* RW Std Speed clock High Count */ > #define IG4_REG_SS_SCL_LCNT 0x0018 /* RW Std Speed clock Low Count */ >@@ -91,8 +92,10 @@ > #define IG4_REG_CLR_INTR 0x0040 /* RO Clear Interrupt */ > #define IG4_REG_CLR_RX_UNDER 0x0044 /* RO Clear RX_Under Interrupt */ > #define IG4_REG_CLR_RX_OVER 0x0048 /* RO Clear RX_Over Interrupt */ >-#define IG4_REG_CLR_TX_OVER 0x004C /* RO Clear TX_Over Interrupt */ >+#define IG4_REG_CLR_TX_OVER 0x004C /* RO Clear TX_Over Interrupt */i >+#define IG4_REG_CLR_RD_REQ 0x0050 /* RO Clear RD_Req Interrupt */ > #define IG4_REG_CLR_TX_ABORT 0x0054 /* RO Clear TX_Abort Interrupt */ >+#define IG4_REG_CLR_RX_DONE 0x0058 /* RO Clear RX_Done Interrupt */ > #define IG4_REG_CLR_ACTIVITY 0x005C /* RO Clear Activity Interrupt */ > #define IG4_REG_CLR_STOP_DET 0x0060 /* RO Clear STOP Detection Int */ > #define IG4_REG_CLR_START_DET 0x0064 /* RO Clear START Detection Int */ >@@ -108,13 +111,26 @@ > #define IG4_REG_DMA_TDLR 0x008C /* RW DMA Transmit Data Level */ > #define IG4_REG_DMA_RDLR 0x0090 /* RW DMA Receive Data Level */ > #define IG4_REG_SDA_SETUP 0x0094 /* RW SDA Setup */ >+#define IG4_REG_ACK_GENERAL_CALL 0x0098 /* RW I2C ACK General Call */ > #define IG4_REG_ENABLE_STATUS 0x009C /* RO Enable Status */ >+/* Available at least on Atom SoCs and Haswell mobile. */ > #define IG4_REG_COMP_PARAM1 0x00F4 /* RO Component Parameter */ > #define IG4_REG_COMP_VER 0x00F8 /* RO Component Version */ >+/* Available at least on Atom SoCs */ > #define IG4_REG_COMP_TYPE 0x00FC /* RO Probe width/endian? (linux) */ >+/* Available on Skylake-U/Y and Kaby Lake-U/Y */ >+#define IG4_REG_RESETS_SKL 0x0204 /* RW Reset Register */ >+#define IG4_REG_ACTIVE_LTR_VALUE 0x0210 /* RW Active LTR Value */ >+#define IG4_REG_IDLE_LTR_VALUE 0x0214 /* RW Idle LTR Value */ >+#define IG4_REG_TX_ACK_COUNT 0x0218 /* RO TX ACK Count */ >+#define IG4_REG_RX_BYTE_COUNT 0x021C /* RO RX ACK Count */ >+#define IG4_REG_DEVIDLE_CTRL 0x024C /* RW Device Control */ >+/* Available at least on Atom SoCs */ > #define IG4_REG_CLK_PARMS 0x0800 /* RW Clock Parameters */ >-#define IG4_REG_RESETS 0x0804 /* RW Reset Register */ >+/* Available at least on Atom SoCs and Haswell mobile */ >+#define IG4_REG_RESETS_HSW 0x0804 /* RW Reset Register */ > #define IG4_REG_GENERAL 0x0808 /* RW General Register */ >+/* These LTR config registers are at least available on Haswell mobile. */ > #define IG4_REG_SW_LTR_VALUE 0x0810 /* RW SW LTR Value */ > #define IG4_REG_AUTO_LTR_VALUE 0x0814 /* RW Auto LTR Value */ > >@@ -566,8 +582,23 @@ > * 10 (reserved) > * 11 I2C host controller is in reset. > */ >-#define IG4_RESETS_ASSERT 0x0003 >-#define IG4_RESETS_DEASSERT 0x0000 >+#define IG4_RESETS_ASSERT_HSW 0x0003 >+#define IG4_RESETS_DEASSERT_HSW 0x0000 >+ >+/* Skylake-U/Y and Kaby Lake-U/Y have the reset bits inverted */ >+#define IG4_RESETS_DEASSERT_SKL 0x0003 >+#define IG4_RESETS_ASSERT_SKL 0x0000 >+ >+/* Newer versions of the I2C controller allow to check whether >+ * the above ASSERT/DEASSERT is necessary by querying the DEVIDLE_CONTROL >+ * register. >+ * >+ * the RESTORE_REQUIRED bit can be cleared by writing 1 >+ * the DEVICE_IDLE status can be set to put the controller in an idle state >+ * */ >+ >+#define IG4_RESTORE_REQUIRED 0x0008 >+#define IG4_DEVICE_IDLE 0x0004 > > /* > * GENERAL - (RW) General Reigster 22.2.38 >diff --git a/sys/dev/ichiic/ig4_var.h b/sys/dev/ichiic/ig4_var.h >index efa24828e2b..14f4b30965b 100644 >--- a/sys/dev/ichiic/ig4_var.h >+++ b/sys/dev/ichiic/ig4_var.h >@@ -48,6 +48,12 @@ > > enum ig4_op { IG4_IDLE, IG4_READ, IG4_WRITE }; > >+enum ig4_vers { >+ IG4_HASWELL = 0, >+ IG4_ATOM, >+ IG4_SKYLAKE, >+}; >+ > struct ig4iic_softc { > device_t dev; > struct intr_config_hook enum_hook; >@@ -58,6 +64,7 @@ struct ig4iic_softc { > int intr_rid; > void *intr_handle; > int intr_type; >+ enum ig4_vers version; > enum ig4_op op; > int cmd; > int rnext;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 221777
:
185729
|
196137
|
196970