[ig4] Add suspend/resume support
That is done with re-execution of controller initialization procedure from resume handler. PR: 238037
This commit is contained in:
parent
83a66b9bda
commit
db7caa2ea7
@ -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),
|
||||
|
@ -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");
|
||||
@ -967,6 +975,49 @@ ig4iic_detach(ig4iic_softc_t *sc)
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt Operation, see ig4_var.h for locking semantics.
|
||||
*/
|
||||
|
@ -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),
|
||||
|
@ -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;
|
||||
|
@ -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),
|
||||
|
Loading…
x
Reference in New Issue
Block a user