From 73c944d72999180167cb78828dbadf464b2970ff Mon Sep 17 00:00:00 2001 From: Dimitris Lampridis <dimitris.lampridis@cern.ch> Date: Tue, 3 Mar 2020 17:37:50 +0100 Subject: [PATCH] [sw][driver][i2c] make i2c-ocores work with kernels 4.7 and newer Signed-off-by: Dimitris Lampridis <dimitris.lampridis@cern.ch> --- .../drivers/i2c/busses/i2c-ocores.c | 58 ++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/software/i2c-ocores/drivers/i2c/busses/i2c-ocores.c b/software/i2c-ocores/drivers/i2c/busses/i2c-ocores.c index b7a458d6..dc6fc7de 100644 --- a/software/i2c-ocores/drivers/i2c/busses/i2c-ocores.c +++ b/software/i2c-ocores/drivers/i2c/busses/i2c-ocores.c @@ -41,8 +41,12 @@ struct ocores_i2c { unsigned long flags; wait_queue_head_t wait; struct i2c_adapter adap; +#if KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE + struct i2c_mux_core *adap_mux; +#else struct i2c_adapter **adap_mux; unsigned int n_adap_mux; +#endif struct i2c_msg *msg; int pos; int nmsgs; @@ -582,10 +586,17 @@ MODULE_DEVICE_TABLE(id_table, ocores_id_table); /** * It selects the I2C bus to use and lock it */ +#if KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE +static int ocores_i2c_mux_select(struct i2c_mux_core *adap_mux, + u32 num) +{ + struct ocores_i2c *i2c = adap_mux->priv; +#else static int ocores_i2c_mux_select(struct i2c_adapter *adap, void *priv, u32 num) { struct ocores_i2c *i2c = priv; +#endif u8 mux; mux = oc_getreg(i2c, OCI2C_OHWR_MUX); @@ -605,16 +616,25 @@ static int ocores_i2c_mux_select(struct i2c_adapter *adap, /** * It unlocks the bus so that it can be changed. */ +#if KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE +static int ocores_i2c_mux_deselect(struct i2c_mux_core *adap_mux, + u32 num) +{ + struct ocores_i2c *i2c = adap_mux->priv; + struct device *dev = adap_mux->dev; +#else static int ocores_i2c_mux_deselect(struct i2c_adapter *adap, void *priv, u32 num) { struct ocores_i2c *i2c = priv; + struct device *dev = &adap->dev; +#endif u8 mux; /* Unlock bus selection */ mux = oc_getreg(i2c, OCI2C_OHWR_MUX); if (unlikely(!(mux & OCI2C_OHWR_MUX_BUSY))) - dev_err(&adap->dev, "deselect a bus that was not selected\n"); + dev_err(dev, "deselect a bus that was not selected\n"); mux &= ~OCI2C_OHWR_MUX_BUSY; oc_setreg(i2c, OCI2C_OHWR_MUX, mux); @@ -627,12 +647,40 @@ static int ocores_i2c_mux_deselect(struct i2c_adapter *adap, */ static int ocores_i2c_probe_ohwr(struct ocores_i2c *i2c) { - int err, i; + int i, err = 0; + +#if KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE + i2c->adap_mux = i2c_mux_alloc(&i2c->adap, i2c->adap.dev.parent, + 2, sizeof(i2c), 0, + ocores_i2c_mux_select, + ocores_i2c_mux_deselect); + if (!i2c->adap_mux) { + err = -ENOMEM; + goto err_exit; + } + i2c->adap_mux->priv = i2c; + for (i = 0; i < i2c->adap_mux->max_adapters; ++i) { + err = i2c_mux_add_adapter(i2c->adap_mux, + 0, i, 0); + if (err) + goto err_add; + } + + return 0; +err_add: + i2c_mux_del_adapters(i2c->adap_mux); +err_exit: + return err; +#else /* KERNEL < 4.7 */ i2c->n_adap_mux = 2; i2c->adap_mux = devm_kzalloc(&i2c->adap.dev, sizeof(void *) * i2c->n_adap_mux, GFP_KERNEL); + if (!i2c->adap_mux) { + err = -ENOMEM; + goto err_exit; + } for (i = 0; i < i2c->n_adap_mux; ++i) { i2c->adap_mux[i] = i2c_add_mux_adapter(&i2c->adap, i2c->adap.dev.parent, @@ -652,7 +700,9 @@ static int ocores_i2c_probe_ohwr(struct ocores_i2c *i2c) err_add: while (--i >= 0) i2c_del_mux_adapter(i2c->adap_mux[i]); +err_exit: return err; +#endif } /** @@ -660,10 +710,14 @@ err_add: */ static void ocores_i2c_remove_ohwr(struct ocores_i2c *i2c) { +#if KERNEL_VERSION(4, 7, 0) <= LINUX_VERSION_CODE + i2c_mux_del_adapters(i2c->adap_mux); +#else int i; for (i = 0; i < i2c->n_adap_mux; ++i) i2c_del_mux_adapter(i2c->adap_mux[i]); +#endif } #ifdef CONFIG_OF -- GitLab