]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: pse-pd: tps23881: Add support for TPS23881B
authorThomas Wismer <thomas.wismer@scs.ch>
Wed, 29 Oct 2025 21:23:09 +0000 (22:23 +0100)
committerJakub Kicinski <kuba@kernel.org>
Sat, 1 Nov 2025 00:56:32 +0000 (17:56 -0700)
The TPS23881B uses different firmware than the TPS23881. Trying to load the
TPS23881 firmware on a TPS23881B device fails and must be omitted.

The TPS23881B ships with a more recent ROM firmware. Moreover, no updated
firmware has been released yet and so the firmware loading step must be
skipped. As of today, the TPS23881B is intended to use its ROM firmware.

Signed-off-by: Thomas Wismer <thomas.wismer@scs.ch>
Reviewed-by: Kory Maincent <kory.maincent@bootlin.com>
Acked-by: Oleksij Rempel <o.rempel@pengutronix.de>
Link: https://patch.msgid.link/20251029212312.108749-2-thomas@wismer.xyz
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/pse-pd/tps23881.c

index b724b222ab44c9a60c780c96a616bd8ece75dcbb..76ec1555d60df11d5c2beb503307c84aff33662d 100644 (file)
@@ -55,8 +55,6 @@
 #define TPS23881_REG_TPON      BIT(0)
 #define TPS23881_REG_FWREV     0x41
 #define TPS23881_REG_DEVID     0x43
-#define TPS23881_REG_DEVID_MASK        0xF0
-#define TPS23881_DEVICE_ID     0x02
 #define TPS23881_REG_CHAN1_CLASS       0x4c
 #define TPS23881_REG_SRAM_CTRL 0x60
 #define TPS23881_REG_SRAM_DATA 0x61
@@ -1012,8 +1010,28 @@ static const struct pse_controller_ops tps23881_ops = {
        .pi_get_pw_req = tps23881_pi_get_pw_req,
 };
 
-static const char fw_parity_name[] = "ti/tps23881/tps23881-parity-14.bin";
-static const char fw_sram_name[] = "ti/tps23881/tps23881-sram-14.bin";
+struct tps23881_info {
+       u8 dev_id;      /* device ID and silicon revision */
+       const char *fw_parity_name;     /* parity code firmware file name */
+       const char *fw_sram_name;       /* SRAM code firmware file name */
+};
+
+enum tps23881_model {
+       TPS23881,
+       TPS23881B,
+};
+
+static const struct tps23881_info tps23881_info[] = {
+       [TPS23881] = {
+               .dev_id = 0x22,
+               .fw_parity_name = "ti/tps23881/tps23881-parity-14.bin",
+               .fw_sram_name = "ti/tps23881/tps23881-sram-14.bin",
+       },
+       [TPS23881B] = {
+               .dev_id = 0x24,
+               /* skip SRAM load, ROM provides Clause 145 hardware-level support */
+       },
+};
 
 struct tps23881_fw_conf {
        u8 reg;
@@ -1085,16 +1103,17 @@ out:
        return ret;
 }
 
-static int tps23881_flash_sram_fw(struct i2c_client *client)
+static int tps23881_flash_sram_fw(struct i2c_client *client,
+                                 const struct tps23881_info *info)
 {
        int ret;
 
-       ret = tps23881_flash_sram_fw_part(client, fw_parity_name,
+       ret = tps23881_flash_sram_fw_part(client, info->fw_parity_name,
                                          tps23881_fw_parity_conf);
        if (ret)
                return ret;
 
-       ret = tps23881_flash_sram_fw_part(client, fw_sram_name,
+       ret = tps23881_flash_sram_fw_part(client, info->fw_sram_name,
                                          tps23881_fw_sram_conf);
        if (ret)
                return ret;
@@ -1412,6 +1431,7 @@ static int tps23881_setup_irq(struct tps23881_priv *priv, int irq)
 static int tps23881_i2c_probe(struct i2c_client *client)
 {
        struct device *dev = &client->dev;
+       const struct tps23881_info *info;
        struct tps23881_priv *priv;
        struct gpio_desc *reset;
        int ret;
@@ -1422,6 +1442,10 @@ static int tps23881_i2c_probe(struct i2c_client *client)
                return -ENXIO;
        }
 
+       info = i2c_get_match_data(client);
+       if (!info)
+               return -EINVAL;
+
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
@@ -1440,7 +1464,7 @@ static int tps23881_i2c_probe(struct i2c_client *client)
                 * to Load TPS2388x SRAM and Parity Code over I2C" (Rev E))
                 * indicates we should delay that programming by at least 50ms. So
                 * we'll wait the entire 50ms here to ensure we're safe to go to the
-                * SRAM loading proceedure.
+                * SRAM loading procedure.
                 */
                msleep(50);
        }
@@ -1449,20 +1473,27 @@ static int tps23881_i2c_probe(struct i2c_client *client)
        if (ret < 0)
                return ret;
 
-       if (FIELD_GET(TPS23881_REG_DEVID_MASK, ret) != TPS23881_DEVICE_ID) {
+       if (ret != info->dev_id) {
                dev_err(dev, "Wrong device ID\n");
                return -ENXIO;
        }
 
-       ret = tps23881_flash_sram_fw(client);
-       if (ret < 0)
-               return ret;
+       if (info->fw_sram_name) {
+               ret = tps23881_flash_sram_fw(client, info);
+               if (ret < 0)
+                       return ret;
+       }
 
        ret = i2c_smbus_read_byte_data(client, TPS23881_REG_FWREV);
        if (ret < 0)
                return ret;
 
-       dev_info(&client->dev, "Firmware revision 0x%x\n", ret);
+       if (ret == 0xFF) {
+               dev_err(&client->dev, "Device entered safe mode\n");
+               return -ENXIO;
+       }
+       dev_info(&client->dev, "Firmware revision 0x%x%s\n", ret,
+                ret == 0x00 ? " (ROM firmware)" : "");
 
        /* Set configuration B, 16 bit access on a single device address */
        ret = i2c_smbus_read_byte_data(client, TPS23881_REG_GEN_MASK);
@@ -1498,13 +1529,21 @@ static int tps23881_i2c_probe(struct i2c_client *client)
 }
 
 static const struct i2c_device_id tps23881_id[] = {
-       { "tps23881" },
+       { "tps23881", .driver_data = (kernel_ulong_t)&tps23881_info[TPS23881] },
+       { "tps23881b", .driver_data = (kernel_ulong_t)&tps23881_info[TPS23881B] },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, tps23881_id);
 
 static const struct of_device_id tps23881_of_match[] = {
-       { .compatible = "ti,tps23881", },
+       {
+               .compatible = "ti,tps23881",
+               .data = &tps23881_info[TPS23881]
+       },
+       {
+               .compatible = "ti,tps23881b",
+               .data = &tps23881_info[TPS23881B]
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, tps23881_of_match);