]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: txgbe: support getting module EEPROM by page
authorJiawen Wu <jiawenwu@trustnetic.com>
Tue, 18 Nov 2025 08:02:59 +0000 (16:02 +0800)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 20 Nov 2025 11:47:26 +0000 (12:47 +0100)
Getting module EEPROM has been supported in TXGBE SP devices, since SFP
driver has already implemented it.

Now add support to read module EEPROM for AML devices. Towards this, add
a new firmware mailbox command to get the page data.

Signed-off-by: Jiawen Wu <jiawenwu@trustnetic.com>
Link: https://patch.msgid.link/20251118080259.24676-6-jiawenwu@trustnetic.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c
drivers/net/ethernet/wangxun/txgbe/txgbe_aml.h
drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c
drivers/net/ethernet/wangxun/txgbe/txgbe_type.h

index 3b6ea456fbf7045d5404b80b51d47bd63aee3e31..62d7f47d4f8d22e89394ba08a10da9065f49d7e3 100644 (file)
@@ -73,6 +73,39 @@ int txgbe_test_hostif(struct wx *wx)
                                        WX_HI_COMMAND_TIMEOUT, true);
 }
 
+int txgbe_read_eeprom_hostif(struct wx *wx,
+                            struct txgbe_hic_i2c_read *buffer,
+                            u32 length, u8 *data)
+{
+       u32 dword_len, offset, value, i;
+       int err;
+
+       buffer->hdr.cmd = FW_READ_EEPROM_CMD;
+       buffer->hdr.buf_len = sizeof(struct txgbe_hic_i2c_read) -
+                             sizeof(struct wx_hic_hdr);
+       buffer->hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED;
+
+       err = wx_host_interface_command(wx, (u32 *)buffer,
+                                       sizeof(struct txgbe_hic_i2c_read),
+                                       WX_HI_COMMAND_TIMEOUT, false);
+       if (err != 0)
+               return err;
+
+       /* buffer length offset to read return data */
+       offset = sizeof(struct txgbe_hic_i2c_read) >> 2;
+       dword_len = round_up(length, 4) >> 2;
+
+       for (i = 0; i < dword_len; i++) {
+               value = rd32a(wx, WX_FW2SW_MBOX, i + offset);
+               le32_to_cpus(&value);
+
+               memcpy(data, &value, 4);
+               data += 4;
+       }
+
+       return 0;
+}
+
 static int txgbe_identify_module_hostif(struct wx *wx,
                                        struct txgbe_hic_get_module_info *buffer)
 {
index 7c8fa48e68d37886bc68fd447a01169fad2090bc..4f6df0ee860bcc25b2e7433750506480ad53e00a 100644 (file)
@@ -7,6 +7,9 @@
 void txgbe_gpio_init_aml(struct wx *wx);
 irqreturn_t txgbe_gpio_irq_handler_aml(int irq, void *data);
 int txgbe_test_hostif(struct wx *wx);
+int txgbe_read_eeprom_hostif(struct wx *wx,
+                            struct txgbe_hic_i2c_read *buffer,
+                            u32 length, u8 *data);
 int txgbe_set_phy_link(struct wx *wx);
 int txgbe_identify_module(struct wx *wx);
 void txgbe_setup_link(struct wx *wx);
index f553ec5f8238d39fc68680822df8928e8c66d538..f3cb0010952971a5e205aba7ef95845f7c5b227f 100644 (file)
@@ -10,6 +10,7 @@
 #include "../libwx/wx_lib.h"
 #include "txgbe_type.h"
 #include "txgbe_fdir.h"
+#include "txgbe_aml.h"
 #include "txgbe_ethtool.h"
 
 int txgbe_get_link_ksettings(struct net_device *netdev,
@@ -534,6 +535,34 @@ static int txgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
        return ret;
 }
 
+static int
+txgbe_get_module_eeprom_by_page(struct net_device *netdev,
+                               const struct ethtool_module_eeprom *page_data,
+                               struct netlink_ext_ack *extack)
+{
+       struct wx *wx = netdev_priv(netdev);
+       struct txgbe_hic_i2c_read buffer;
+       int err;
+
+       if (!test_bit(WX_FLAG_SWFW_RING, wx->flags))
+               return -EOPNOTSUPP;
+
+       buffer.length = cpu_to_be32(page_data->length);
+       buffer.offset = cpu_to_be32(page_data->offset);
+       buffer.page = page_data->page;
+       buffer.bank = page_data->bank;
+       buffer.i2c_address = page_data->i2c_address;
+
+       err = txgbe_read_eeprom_hostif(wx, &buffer, page_data->length,
+                                      page_data->data);
+       if (err) {
+               wx_err(wx, "Failed to read module EEPROM\n");
+               return err;
+       }
+
+       return page_data->length;
+}
+
 static const struct ethtool_ops txgbe_ethtool_ops = {
        .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
                                     ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ |
@@ -568,6 +597,7 @@ static const struct ethtool_ops txgbe_ethtool_ops = {
        .set_msglevel           = wx_set_msglevel,
        .get_ts_info            = wx_get_ts_info,
        .get_ts_stats           = wx_get_ptp_stats,
+       .get_module_eeprom_by_page      = txgbe_get_module_eeprom_by_page,
 };
 
 void txgbe_set_ethtool_ops(struct net_device *netdev)
index e72edb9ef08477173db51eb9a49e837c9d62468b..82433e9cb0e33ebb2835d478b5dea296fd4c0d55 100644 (file)
@@ -353,6 +353,7 @@ void txgbe_do_reset(struct net_device *netdev);
 #define FW_PHY_GET_LINK_CMD             0xC0
 #define FW_PHY_SET_LINK_CMD             0xC1
 #define FW_GET_MODULE_INFO_CMD          0xC5
+#define FW_READ_EEPROM_CMD              0xC6
 
 struct txgbe_sff_id {
        u8 identifier;          /* A0H 0x00 */
@@ -394,6 +395,16 @@ struct txgbe_hic_ephy_getlink {
        u8 resv[6];
 };
 
+struct txgbe_hic_i2c_read {
+       struct wx_hic_hdr hdr;
+       __be32 offset;
+       __be32 length;
+       u8 page;
+       u8 bank;
+       u8 i2c_address;
+       u8 resv;
+};
+
 #define NODE_PROP(_NAME, _PROP)                        \
        (const struct software_node) {          \
                .name = _NAME,                  \