diff options
-rw-r--r-- | drivers/i2c/muxes/i2c-mux-pca954x.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/i2c/muxes/i2c-mux-pca954x.c b/drivers/i2c/muxes/i2c-mux-pca954x.c index 9c4ac26..3c27ab8 100644 --- a/drivers/i2c/muxes/i2c-mux-pca954x.c +++ b/drivers/i2c/muxes/i2c-mux-pca954x.c @@ -74,6 +74,7 @@ struct pca954x { u8 last_chan; /* last register value */ u8 deselect; struct i2c_client *client; + u8 disable_mux; /* do not disable mux if val not 0 */ }; /* Provide specs for the PCA954x types we know about */ @@ -196,6 +197,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); @@ -228,6 +236,28 @@ 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. + */ + match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev); + if (match) + data->chip = of_device_get_match_data(&client->dev); + else + data->chip = &chips[id->driver_data]; + + 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; @@ -240,11 +270,16 @@ 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; } +#ifndef CONFIG_ARCH_LAYERSCAPE match = of_match_device(of_match_ptr(pca954x_of_match), &client->dev); if (match) data->chip = of_device_get_match_data(&client->dev); @@ -252,6 +287,7 @@ static int pca954x_probe(struct i2c_client *client, data->chip = &chips[id->driver_data]; data->last_chan = 0; /* force the first selection */ +#endif idle_disconnect_dt = of_node && of_property_read_bool(of_node, "i2c-mux-idle-disconnect"); @@ -312,6 +348,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); } |