Date: Tue, 6 Mar 2018 23:39:43 +0000 (UTC) From: Oleksandr Tymoshenko <gonzo@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r330558 - head/sys/dev/ichiic Message-ID: <201803062339.w26NdhEl098447@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gonzo Date: Tue Mar 6 23:39:43 2018 New Revision: 330558 URL: https://svnweb.freebsd.org/changeset/base/330558 Log: [ig4] Add support for i2c controllers on Skylake and Kaby Lake This was tested by Ben on HP Chromebook 13 G1 with a Skylake CPU and Sunrise Point-LP I2C controller and by me on Minnowboard Turbot with Atom E3826 (formerly Bay Trail) Submitted by: Ben Pye <ben@curlybracket.co.uk> Reviewed by: gonzo Obtained from: DragonflyBSD (a4549657 by Imre Vadász) MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D13654 Modified: head/sys/dev/ichiic/ig4_acpi.c head/sys/dev/ichiic/ig4_iic.c head/sys/dev/ichiic/ig4_pci.c head/sys/dev/ichiic/ig4_reg.h head/sys/dev/ichiic/ig4_var.h Modified: head/sys/dev/ichiic/ig4_acpi.c ============================================================================== --- head/sys/dev/ichiic/ig4_acpi.c Tue Mar 6 23:28:12 2018 (r330557) +++ head/sys/dev/ichiic/ig4_acpi.c Tue Mar 6 23:39:43 2018 (r330558) @@ -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); Modified: head/sys/dev/ichiic/ig4_iic.c ============================================================================== --- head/sys/dev/ichiic/ig4_iic.c Tue Mar 6 23:28:12 2018 (r330557) +++ head/sys/dev/ichiic/ig4_iic.c Tue Mar 6 23:39:43 2018 (r330558) @@ -525,22 +525,38 @@ 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_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); + 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); @@ -591,8 +607,13 @@ 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); + } else if (sc->version = IG4_SKYLAKE) { + reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_ASSERT_SKL); + reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_DEASSERT_SKL); + } #endif mtx_lock(&sc->io_lock); @@ -727,14 +748,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 Modified: head/sys/dev/ichiic/ig4_pci.c ============================================================================== --- head/sys/dev/ichiic/ig4_pci.c Tue Mar 6 23:28:12 2018 (r330557) +++ head/sys/dev/ichiic/ig4_pci.c Tue Mar 6 23:39:43 2018 (r330558) @@ -74,34 +74,74 @@ static int ig4iic_pci_detach(device_t dev); #define PCI_CHIP_BRASWELL_I2C_5 0x22c58086 #define PCI_CHIP_BRASWELL_I2C_6 0x22c68086 #define PCI_CHIP_BRASWELL_I2C_7 0x22c78086 +#define PCI_CHIP_SKYLAKE_I2C_0 0x9d608086 +#define PCI_CHIP_SKYLAKE_I2C_1 0x9d618086 +#define PCI_CHIP_SKYLAKE_I2C_2 0x9d628086 +#define PCI_CHIP_SKYLAKE_I2C_3 0x9d638086 +#define PCI_CHIP_SKYLAKE_I2C_4 0x9d648086 +#define PCI_CHIP_SKYLAKE_I2C_5 0x9d658086 static int ig4iic_pci_probe(device_t dev) { + ig4iic_softc_t *sc = device_get_softc(dev); + switch(pci_get_devid(dev)) { case PCI_CHIP_LYNXPT_LP_I2C_1: device_set_desc(dev, "Intel Lynx Point-LP I2C Controller-1"); + sc->version = IG4_HASWELL; break; case PCI_CHIP_LYNXPT_LP_I2C_2: device_set_desc(dev, "Intel Lynx Point-LP I2C Controller-2"); + sc->version = IG4_HASWELL; break; case PCI_CHIP_BRASWELL_I2C_1: device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 1"); + sc->version = IG4_ATOM; break; case PCI_CHIP_BRASWELL_I2C_2: device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 2"); + sc->version = IG4_ATOM; break; case PCI_CHIP_BRASWELL_I2C_3: device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 3"); + sc->version = IG4_ATOM; break; case PCI_CHIP_BRASWELL_I2C_5: device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 5"); + sc->version = IG4_ATOM; break; case PCI_CHIP_BRASWELL_I2C_6: device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 6"); + sc->version = IG4_ATOM; break; case PCI_CHIP_BRASWELL_I2C_7: device_set_desc(dev, "Intel Braswell Serial I/O I2C Port 7"); + sc->version = IG4_ATOM; + break; + case PCI_CHIP_SKYLAKE_I2C_0: + device_set_desc(dev, "Intel Sunrise Point-LP I2C Controller-0"); + sc->version = IG4_SKYLAKE; + break; + case PCI_CHIP_SKYLAKE_I2C_1: + device_set_desc(dev, "Intel Sunrise Point-LP I2C Controller-1"); + sc->version = IG4_SKYLAKE; + break; + case PCI_CHIP_SKYLAKE_I2C_2: + device_set_desc(dev, "Intel Sunrise Point-LP I2C Controller-2"); + sc->version = IG4_SKYLAKE; + break; + case PCI_CHIP_SKYLAKE_I2C_3: + device_set_desc(dev, "Intel Sunrise Point-LP I2C Controller-3"); + sc->version = IG4_SKYLAKE; + break; + case PCI_CHIP_SKYLAKE_I2C_4: + device_set_desc(dev, "Intel Sunrise Point-LP I2C Controller-4"); + sc->version = IG4_SKYLAKE; + break; + case PCI_CHIP_SKYLAKE_I2C_5: + device_set_desc(dev, "Intel Sunrise Point-LP I2C Controller-5"); + sc->version = IG4_SKYLAKE; break; default: return (ENXIO); Modified: head/sys/dev/ichiic/ig4_reg.h ============================================================================== --- head/sys/dev/ichiic/ig4_reg.h Tue Mar 6 23:28:12 2018 (r330557) +++ head/sys/dev/ichiic/ig4_reg.h Tue Mar 6 23:39:43 2018 (r330558) @@ -109,12 +109,21 @@ #define IG4_REG_DMA_RDLR 0x0090 /* RW DMA Receive Data Level */ #define IG4_REG_SDA_SETUP 0x0094 /* RW SDA Setup */ #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 */ +/* 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 +575,12 @@ * 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 /* * GENERAL - (RW) General Reigster 22.2.38 Modified: head/sys/dev/ichiic/ig4_var.h ============================================================================== --- head/sys/dev/ichiic/ig4_var.h Tue Mar 6 23:28:12 2018 (r330557) +++ head/sys/dev/ichiic/ig4_var.h Tue Mar 6 23:39:43 2018 (r330558) @@ -47,6 +47,7 @@ #define IG4_RBUFMASK (IG4_RBUFSIZE - 1) enum ig4_op { IG4_IDLE, IG4_READ, IG4_WRITE }; +enum ig4_vers { IG4_HASWELL, IG4_ATOM, IG4_SKYLAKE }; struct ig4iic_softc { device_t dev; @@ -58,6 +59,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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803062339.w26NdhEl098447>