i2c: i801: store and restore the SLVCMD register at load and unload
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>
Thu, 13 Oct 2016 12:10:35 +0000 (14:10 +0200)
committerWolfram Sang <wsa@the-dreams.de>
Thu, 24 Nov 2016 15:22:01 +0000 (16:22 +0100)
Also do not override any other configuration in this register.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
drivers/i2c/busses/i2c-i801.c

index eb3627f35d12002776447982d493835fe36dc064..750c4753e2bc4df389e98c3b5cc952e9f1b1e9bb 100644 (file)
@@ -243,6 +243,7 @@ struct i801_priv {
        struct i2c_adapter adapter;
        unsigned long smba;
        unsigned char original_hstcfg;
+       unsigned char original_slvcmd;
        struct pci_dev *pci_dev;
        unsigned int features;
 
@@ -962,13 +963,26 @@ static int i801_enable_host_notify(struct i2c_adapter *adapter)
        if (!priv->host_notify)
                return -ENOMEM;
 
-       outb_p(SMBSLVCMD_HST_NTFY_INTREN, SMBSLVCMD(priv));
+       priv->original_slvcmd = inb_p(SMBSLVCMD(priv));
+
+       if (!(SMBSLVCMD_HST_NTFY_INTREN & priv->original_slvcmd))
+               outb_p(SMBSLVCMD_HST_NTFY_INTREN | priv->original_slvcmd,
+                      SMBSLVCMD(priv));
+
        /* clear Host Notify bit to allow a new notification */
        outb_p(SMBSLVSTS_HST_NTFY_STS, SMBSLVSTS(priv));
 
        return 0;
 }
 
+static void i801_disable_host_notify(struct i801_priv *priv)
+{
+       if (!(priv->features & FEATURE_HOST_NOTIFY))
+               return;
+
+       outb_p(priv->original_slvcmd, SMBSLVCMD(priv));
+}
+
 static const struct i2c_algorithm smbus_algorithm = {
        .smbus_xfer     = i801_access,
        .functionality  = i801_func,
@@ -1663,6 +1677,7 @@ static void i801_remove(struct pci_dev *dev)
        pm_runtime_forbid(&dev->dev);
        pm_runtime_get_noresume(&dev->dev);
 
+       i801_disable_host_notify(priv);
        i801_del_mux(priv);
        i2c_del_adapter(&priv->adapter);
        i801_acpi_remove(priv);