From owner-svn-src-all@freebsd.org Sun Nov 3 21:00:57 2019 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 8B7921A2A88; Sun, 3 Nov 2019 21:00:57 +0000 (UTC) (envelope-from wulf@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 475pHY2qDsz3GvY; Sun, 3 Nov 2019 21:00:57 +0000 (UTC) (envelope-from wulf@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 366C319980; Sun, 3 Nov 2019 21:00:57 +0000 (UTC) (envelope-from wulf@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id xA3L0vQP066514; Sun, 3 Nov 2019 21:00:57 GMT (envelope-from wulf@FreeBSD.org) Received: (from wulf@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id xA3L0uoM066509; Sun, 3 Nov 2019 21:00:56 GMT (envelope-from wulf@FreeBSD.org) Message-Id: <201911032100.xA3L0uoM066509@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: wulf set sender to wulf@FreeBSD.org using -f From: Vladimir Kondratyev Date: Sun, 3 Nov 2019 21:00:56 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r354308 - in head/sys/dev: ichiic iicbus X-SVN-Group: head X-SVN-Commit-Author: wulf X-SVN-Commit-Paths: in head/sys/dev: ichiic iicbus X-SVN-Commit-Revision: 354308 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 03 Nov 2019 21:00:57 -0000 Author: wulf Date: Sun Nov 3 21:00:55 2019 New Revision: 354308 URL: https://svnweb.freebsd.org/changeset/base/354308 Log: [ig4] Add suspend/resume support That is done with re-execution of controller initialization procedure from resume handler. PR: 238037 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_var.h head/sys/dev/iicbus/iicbus.c Modified: head/sys/dev/ichiic/ig4_acpi.c ============================================================================== --- head/sys/dev/ichiic/ig4_acpi.c Sun Nov 3 20:59:04 2019 (r354307) +++ head/sys/dev/ichiic/ig4_acpi.c Sun Nov 3 21:00:55 2019 (r354308) @@ -145,11 +145,29 @@ ig4iic_acpi_detach(device_t dev) return (0); } +static int +ig4iic_acpi_suspend(device_t dev) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + + return (ig4iic_suspend(sc)); +} + +static int +ig4iic_acpi_resume(device_t dev) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + + return (ig4iic_resume(sc)); +} + static device_method_t ig4iic_acpi_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ig4iic_acpi_probe), DEVMETHOD(device_attach, ig4iic_acpi_attach), DEVMETHOD(device_detach, ig4iic_acpi_detach), + DEVMETHOD(device_suspend, ig4iic_acpi_suspend), + DEVMETHOD(device_resume, ig4iic_acpi_resume), /* iicbus interface */ DEVMETHOD(iicbus_transfer, ig4iic_transfer), Modified: head/sys/dev/ichiic/ig4_iic.c ============================================================================== --- head/sys/dev/ichiic/ig4_iic.c Sun Nov 3 20:59:04 2019 (r354307) +++ head/sys/dev/ichiic/ig4_iic.c Sun Nov 3 21:00:55 2019 (r354308) @@ -799,20 +799,11 @@ ig4iic_get_config(ig4iic_softc_t *sc) } } -/* - * Called from ig4iic_pci_attach/detach() - */ -int -ig4iic_attach(ig4iic_softc_t *sc) +static int +ig4iic_set_config(ig4iic_softc_t *sc) { - int error; uint32_t v; - mtx_init(&sc->io_lock, "IG4 I/O lock", NULL, MTX_DEF); - sx_init(&sc->call_lock, "IG4 call lock"); - - ig4iic_get_config(sc); - 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); @@ -851,16 +842,13 @@ ig4iic_attach(ig4iic_softc_t *sc) if (sc->version == IG4_HASWELL || sc->version == IG4_ATOM) { v = reg_read(sc, IG4_REG_COMP_VER); - if (v < IG4_COMP_MIN_VER) { - error = ENXIO; - goto done; - } + if (v < IG4_COMP_MIN_VER) + return(ENXIO); } if (set_controller(sc, 0)) { device_printf(sc->dev, "controller error during attach-1\n"); - error = ENXIO; - goto done; + return (ENXIO); } reg_read(sc, IG4_REG_CLR_INTR); @@ -890,6 +878,26 @@ ig4iic_attach(ig4iic_softc_t *sc) IG4_CTL_RESTARTEN | (sc->cfg.bus_speed & IG4_CTL_SPEED_MASK)); + return (0); +} + +/* + * Called from ig4iic_pci_attach/detach() + */ +int +ig4iic_attach(ig4iic_softc_t *sc) +{ + int error; + + mtx_init(&sc->io_lock, "IG4 I/O lock", NULL, MTX_DEF); + sx_init(&sc->call_lock, "IG4 call lock"); + + ig4iic_get_config(sc); + + error = ig4iic_set_config(sc); + if (error) + goto done; + sc->iicbus = device_add_child(sc->dev, "iicbus", -1); if (sc->iicbus == NULL) { device_printf(sc->dev, "iicbus driver not found\n"); @@ -965,6 +973,49 @@ ig4iic_detach(ig4iic_softc_t *sc) sx_destroy(&sc->call_lock); return (0); +} + +int +ig4iic_suspend(ig4iic_softc_t *sc) +{ + int error; + + /* suspend all children */ + error = bus_generic_suspend(sc->dev); + + sx_xlock(&sc->call_lock); + set_controller(sc, 0); + if (sc->version == IG4_SKYLAKE) { + /* + * Place the device in the idle state, just to be safe + */ + reg_write(sc, IG4_REG_DEVIDLE_CTRL, IG4_DEVICE_IDLE); + /* + * Controller can become dysfunctional if I2C lines are pulled + * down when suspend procedure turns off power to I2C device. + * Place device in the reset state to avoid this. + */ + reg_write(sc, IG4_REG_RESETS_SKL, IG4_RESETS_ASSERT_SKL); + } + sx_xunlock(&sc->call_lock); + + return (error); +} + +int ig4iic_resume(ig4iic_softc_t *sc) +{ + int error; + + sx_xlock(&sc->call_lock); + if (ig4iic_set_config(sc)) + device_printf(sc->dev, "controller error during resume\n"); + /* Force setting of the target address on the next transfer */ + sc->slave_valid = 0; + sx_xunlock(&sc->call_lock); + + error = bus_generic_resume(sc->dev); + + return (error); } /* Modified: head/sys/dev/ichiic/ig4_pci.c ============================================================================== --- head/sys/dev/ichiic/ig4_pci.c Sun Nov 3 20:59:04 2019 (r354307) +++ head/sys/dev/ichiic/ig4_pci.c Sun Nov 3 21:00:55 2019 (r354308) @@ -206,11 +206,29 @@ ig4iic_pci_detach(device_t dev) return (0); } +static int +ig4iic_pci_suspend(device_t dev) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + + return (ig4iic_suspend(sc)); +} + +static int +ig4iic_pci_resume(device_t dev) +{ + ig4iic_softc_t *sc = device_get_softc(dev); + + return (ig4iic_resume(sc)); +} + static device_method_t ig4iic_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ig4iic_pci_probe), DEVMETHOD(device_attach, ig4iic_pci_attach), DEVMETHOD(device_detach, ig4iic_pci_detach), + DEVMETHOD(device_suspend, ig4iic_pci_suspend), + DEVMETHOD(device_resume, ig4iic_pci_resume), DEVMETHOD(iicbus_transfer, ig4iic_transfer), DEVMETHOD(iicbus_reset, ig4iic_reset), Modified: head/sys/dev/ichiic/ig4_var.h ============================================================================== --- head/sys/dev/ichiic/ig4_var.h Sun Nov 3 20:59:04 2019 (r354307) +++ head/sys/dev/ichiic/ig4_var.h Sun Nov 3 21:00:55 2019 (r354308) @@ -114,6 +114,8 @@ extern devclass_t ig4iic_devclass; /* Attach/Detach called from ig4iic_pci_*() */ int ig4iic_attach(ig4iic_softc_t *sc); int ig4iic_detach(ig4iic_softc_t *sc); +int ig4iic_suspend(ig4iic_softc_t *sc); +int ig4iic_resume(ig4iic_softc_t *sc); /* iicbus methods */ extern iicbus_transfer_t ig4iic_transfer; Modified: head/sys/dev/iicbus/iicbus.c ============================================================================== --- head/sys/dev/iicbus/iicbus.c Sun Nov 3 20:59:04 2019 (r354307) +++ head/sys/dev/iicbus/iicbus.c Sun Nov 3 21:00:55 2019 (r354308) @@ -330,6 +330,8 @@ static device_method_t iicbus_methods[] = { DEVMETHOD(device_probe, iicbus_probe), DEVMETHOD(device_attach, iicbus_attach), DEVMETHOD(device_detach, iicbus_detach), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), /* bus interface */ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),