These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / i2c / busses / i2c-axxia.c
index 32d8834..c335cc7 100644 (file)
 #define IBML_LOW_SEXT          0x18
 #define TIMER_CLOCK_DIV                0x1c
 #define I2C_BUS_MONITOR                0x20
+#define   BM_SDAC              BIT(3)
+#define   BM_SCLC              BIT(2)
+#define   BM_SDAS              BIT(1)
+#define   BM_SCLS              BIT(0)
 #define SOFT_RESET             0x24
 #define MST_COMMAND            0x28
 #define   CMD_BUSY             (1<<3)
@@ -394,6 +398,9 @@ static int axxia_i2c_xfer_msg(struct axxia_i2c_dev *idev, struct i2c_msg *msg)
        if (time_left == 0)
                idev->msg_err = -ETIMEDOUT;
 
+       if (idev->msg_err == -ETIMEDOUT)
+               i2c_recover_bus(&idev->adapter);
+
        if (unlikely(idev->msg_err) && idev->msg_err != -ENXIO)
                axxia_i2c_init(idev);
 
@@ -437,6 +444,39 @@ axxia_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        return ret ? : i;
 }
 
+static int axxia_i2c_get_scl(struct i2c_adapter *adap)
+{
+       struct axxia_i2c_dev *idev = i2c_get_adapdata(adap);
+
+       return !!(readl(idev->base + I2C_BUS_MONITOR) & BM_SCLS);
+}
+
+static void axxia_i2c_set_scl(struct i2c_adapter *adap, int val)
+{
+       struct axxia_i2c_dev *idev = i2c_get_adapdata(adap);
+       u32 tmp;
+
+       /* Preserve SDA Control */
+       tmp = readl(idev->base + I2C_BUS_MONITOR) & BM_SDAC;
+       if (!val)
+               tmp |= BM_SCLC;
+       writel(tmp, idev->base + I2C_BUS_MONITOR);
+}
+
+static int axxia_i2c_get_sda(struct i2c_adapter *adap)
+{
+       struct axxia_i2c_dev *idev = i2c_get_adapdata(adap);
+
+       return !!(readl(idev->base + I2C_BUS_MONITOR) & BM_SDAS);
+}
+
+static struct i2c_bus_recovery_info axxia_i2c_recovery_info = {
+       .recover_bus = i2c_generic_scl_recovery,
+       .get_scl = axxia_i2c_get_scl,
+       .set_scl = axxia_i2c_set_scl,
+       .get_sda = axxia_i2c_get_sda,
+};
+
 static u32 axxia_i2c_func(struct i2c_adapter *adap)
 {
        u32 caps = (I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR |
@@ -511,6 +551,7 @@ static int axxia_i2c_probe(struct platform_device *pdev)
        strlcpy(idev->adapter.name, pdev->name, sizeof(idev->adapter.name));
        idev->adapter.owner = THIS_MODULE;
        idev->adapter.algo = &axxia_i2c_algo;
+       idev->adapter.bus_recovery_info = &axxia_i2c_recovery_info;
        idev->adapter.quirks = &axxia_i2c_quirks;
        idev->adapter.dev.parent = &pdev->dev;
        idev->adapter.dev.of_node = pdev->dev.of_node;