Commit 2d74187d authored by Peter Rosin's avatar Peter Rosin

i2c: mux: pca954x: verify the device id of the pca984x chips

Make sure to not disallow the chips on adapters that are not capable
of reading the device id, but also make sure to check the device id
before writing to the chip.
Tested-by: default avatarAdrian Fiergolski <adrian.fiergolski@cern.ch>
Signed-off-by: default avatarPeter Rosin <peda@axentia.se>
parent dde67eb1
...@@ -77,6 +77,7 @@ struct chip_desc { ...@@ -77,6 +77,7 @@ struct chip_desc {
pca954x_ismux = 0, pca954x_ismux = 0,
pca954x_isswi pca954x_isswi
} muxtype; } muxtype;
struct i2c_device_identity id;
}; };
struct pca954x { struct pca954x {
...@@ -97,59 +98,83 @@ static const struct chip_desc chips[] = { ...@@ -97,59 +98,83 @@ static const struct chip_desc chips[] = {
.nchans = 2, .nchans = 2,
.enable = 0x4, .enable = 0x4,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9542] = { [pca_9542] = {
.nchans = 2, .nchans = 2,
.enable = 0x4, .enable = 0x4,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9543] = { [pca_9543] = {
.nchans = 2, .nchans = 2,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9544] = { [pca_9544] = {
.nchans = 4, .nchans = 4,
.enable = 0x4, .enable = 0x4,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9545] = { [pca_9545] = {
.nchans = 4, .nchans = 4,
.has_irq = 1, .has_irq = 1,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9546] = { [pca_9546] = {
.nchans = 4, .nchans = 4,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9547] = { [pca_9547] = {
.nchans = 8, .nchans = 8,
.enable = 0x8, .enable = 0x8,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9548] = { [pca_9548] = {
.nchans = 8, .nchans = 8,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = { .manufacturer_id = I2C_DEVICE_ID_NONE },
}, },
[pca_9846] = { [pca_9846] = {
.nchans = 4, .nchans = 4,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x10b,
},
}, },
[pca_9847] = { [pca_9847] = {
.nchans = 8, .nchans = 8,
.enable = 0x8, .enable = 0x8,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x108,
},
}, },
[pca_9848] = { [pca_9848] = {
.nchans = 8, .nchans = 8,
.muxtype = pca954x_isswi, .muxtype = pca954x_isswi,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x10a,
},
}, },
[pca_9849] = { [pca_9849] = {
.nchans = 4, .nchans = 4,
.enable = 0x4, .enable = 0x4,
.muxtype = pca954x_ismux, .muxtype = pca954x_ismux,
.id = {
.manufacturer_id = I2C_DEVICE_ID_NXP_SEMICONDUCTORS,
.part_id = 0x109,
},
}, },
}; };
...@@ -369,6 +394,30 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -369,6 +394,30 @@ static int pca954x_probe(struct i2c_client *client,
if (IS_ERR(gpio)) if (IS_ERR(gpio))
return PTR_ERR(gpio); return PTR_ERR(gpio);
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];
if (data->chip->id.manufacturer_id != I2C_DEVICE_ID_NONE) {
struct i2c_device_identity id;
ret = i2c_get_device_id(client, &id);
if (ret && ret != -EOPNOTSUPP)
return ret;
if (!ret &&
(id.manufacturer_id != data->chip->id.manufacturer_id ||
id.part_id != data->chip->id.part_id)) {
dev_warn(&client->dev,
"unexpected device id %03x-%03x-%x\n",
id.manufacturer_id, id.part_id,
id.die_revision);
return -ENODEV;
}
}
/* Write the mux register at addr to verify /* Write the mux register at addr to verify
* that the mux is in fact present. This also * that the mux is in fact present. This also
* initializes the mux to disconnected state. * initializes the mux to disconnected state.
...@@ -378,12 +427,6 @@ static int pca954x_probe(struct i2c_client *client, ...@@ -378,12 +427,6 @@ static int pca954x_probe(struct i2c_client *client,
return -ENODEV; return -ENODEV;
} }
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->last_chan = 0; /* force the first selection */ data->last_chan = 0; /* force the first selection */
idle_disconnect_dt = of_node && idle_disconnect_dt = of_node &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment