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 <b...@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;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to