Messages in this thread Patch in this message | | | From | <> | Subject | [PATCH] i2c: pca954x: Add option to skip disabling PCA954x Mux device | Date | Tue, 9 May 2017 16:20:05 +0800 |
| |
From: Priyanka Jain <Priyanka.Jain@freescale.com>
On some Layerscape boards like LS2085ARDB/LS2080ARDB, input pull-up resistors on PCA954x Mux device are missing on board. So, if mux are disabled after powered-on, input lines will float leading to incorrect functionality.
Hence, PCA954x Mux device should never be turned-off after power-on.
Add option to skip disabling PCA954x Mux device if device tree contians "i2c-mux-never-disable" property for pca954x device node.
Signed-off-by: Zhang Ying-22455 <ying.zhang22455@nxp.com> --- drivers/i2c/muxes/i2c-mux-pca954x.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index f1751c2..4d18fc0 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -85,6 +85,7 @@ struct pca954x { struct irq_domain *irq; unsigned int irq_mask; raw_spinlock_t lock; + u8 disable_mux; /* do not disable mux if val not 0 */ }; /* Provide specs for the PCA954x types we know about */ @@ -221,6 +222,13 @@ static int pca954x_deselect_mux(struct i2c_mux_core *muxc, u32 chan) if (!(data->deselect & (1 << chan))) return 0; +#ifdef CONFIG_ARCH_LAYERSCAPE + if (data->disable_mux != 0) + data->last_chan = data->chip->nchans; + else + data->last_chan = 0; + return pca954x_reg_write(muxc->parent, client, data->disable_mux); +#endif /* Deselect active channel */ data->last_chan = 0; return pca954x_reg_write(muxc->parent, client, data->last_chan); @@ -361,6 +369,22 @@ static int pca954x_probe(struct i2c_client *client, return -ENOMEM; data = i2c_mux_priv(muxc); +#ifdef CONFIG_ARCH_LAYERSCAPE + /* The point here is that you must not disable a mux if there + * are no pullups on the input or you mess up the I2C. This + * needs to be put into the DTS really as the kernel cannot + * know this otherwise. + */ + data->disable_mux = of_node && + of_property_read_bool(of_node, "i2c-mux-never-disable") && + data->chip->muxtype == pca954x_ismux ? + data->chip->enable : 0; + /* force the first selection */ + if (data->disable_mux != 0) + data->last_chan = data->chip->nchans; + else + data->last_chan = 0; +#endif i2c_set_clientdata(client, muxc); data->client = client; @@ -373,7 +397,11 @@ static int pca954x_probe(struct i2c_client *client, * that the mux is in fact present. This also * initializes the mux to disconnected state. */ +#ifdef CONFIG_ARCH_LAYERSCAPE + if (i2c_smbus_write_byte(client, data->disable_mux) < 0) { +#else if (i2c_smbus_write_byte(client, 0) < 0) { +#endif dev_warn(&client->dev, "probe failed\n"); return -ENODEV; } @@ -384,7 +412,9 @@ static int pca954x_probe(struct i2c_client *client, else data->chip = &chips[id->driver_data]; +#ifndef CONFIG_ARCH_LAYERSCAPE data->last_chan = 0; /* force the first selection */ +#endif idle_disconnect_dt = of_node && of_property_read_bool(of_node, "i2c-mux-idle-disconnect"); @@ -454,6 +484,13 @@ static int pca954x_resume(struct device *dev) struct i2c_mux_core *muxc = i2c_get_clientdata(client); struct pca954x *data = i2c_mux_priv(muxc); +#ifdef CONFIG_ARCH_LAYERSCAPE + if (data->disable_mux != 0) + data->last_chan = data->chip->nchans; + else + data->last_chan = 0; + return i2c_smbus_write_byte(client, data->disable_mux); +#endif data->last_chan = 0; return i2c_smbus_write_byte(client, 0); } -- 2.1.0.27.g96db324
| |