]> www.infradead.org Git - users/hch/misc.git/commitdiff
net: ti: icssm-prueth: Adds IEP support for PRUETH on AM33x, AM43x and AM57x SOCs
authorParvathi Pudi <parvathi@couthit.com>
Fri, 12 Sep 2025 11:53:29 +0000 (17:23 +0530)
committerJakub Kicinski <kuba@kernel.org>
Sun, 14 Sep 2025 20:00:54 +0000 (13:00 -0700)
Added API hooks for IEP module (legacy 32-bit model) to support
timestamping requests from application.

Reviewed-by: Mohan Reddy Putluru <pmohan@couthit.com>
Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Andrew F. Davis <afd@ti.com>
Signed-off-by: Basharath Hussain Khaja <basharath@couthit.com>
Signed-off-by: Parvathi Pudi <parvathi@couthit.com>
Link: https://patch.msgid.link/20250912115443.529856-6-parvathi@couthit.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/ti/icssg/icss_iep.c
drivers/net/ethernet/ti/icssm/icssm_prueth.c
drivers/net/ethernet/ti/icssm/icssm_prueth.h
drivers/net/ethernet/ti/icssm/icssm_prueth_ptp.h [new file with mode: 0644]

index d8c9fe1d98c475e546db2b34f2e794584fe2d650..ec085897edf090e816b05880286a3f43c69225c8 100644 (file)
@@ -982,11 +982,112 @@ static const struct icss_iep_plat_data am654_icss_iep_plat_data = {
        .config = &am654_icss_iep_regmap_config,
 };
 
+static const struct icss_iep_plat_data am57xx_icss_iep_plat_data = {
+       .flags = ICSS_IEP_64BIT_COUNTER_SUPPORT |
+                ICSS_IEP_SLOW_COMPEN_REG_SUPPORT,
+       .reg_offs = {
+               [ICSS_IEP_GLOBAL_CFG_REG] = 0x00,
+               [ICSS_IEP_COMPEN_REG] = 0x08,
+               [ICSS_IEP_SLOW_COMPEN_REG] = 0x0c,
+               [ICSS_IEP_COUNT_REG0] = 0x10,
+               [ICSS_IEP_COUNT_REG1] = 0x14,
+               [ICSS_IEP_CAPTURE_CFG_REG] = 0x18,
+               [ICSS_IEP_CAPTURE_STAT_REG] = 0x1c,
+
+               [ICSS_IEP_CAP6_RISE_REG0] = 0x50,
+               [ICSS_IEP_CAP6_RISE_REG1] = 0x54,
+
+               [ICSS_IEP_CAP7_RISE_REG0] = 0x60,
+               [ICSS_IEP_CAP7_RISE_REG1] = 0x64,
+
+               [ICSS_IEP_CMP_CFG_REG] = 0x70,
+               [ICSS_IEP_CMP_STAT_REG] = 0x74,
+               [ICSS_IEP_CMP0_REG0] = 0x78,
+               [ICSS_IEP_CMP0_REG1] = 0x7c,
+               [ICSS_IEP_CMP1_REG0] = 0x80,
+               [ICSS_IEP_CMP1_REG1] = 0x84,
+
+               [ICSS_IEP_CMP8_REG0] = 0xc0,
+               [ICSS_IEP_CMP8_REG1] = 0xc4,
+               [ICSS_IEP_SYNC_CTRL_REG] = 0x180,
+               [ICSS_IEP_SYNC0_STAT_REG] = 0x188,
+               [ICSS_IEP_SYNC1_STAT_REG] = 0x18c,
+               [ICSS_IEP_SYNC_PWIDTH_REG] = 0x190,
+               [ICSS_IEP_SYNC0_PERIOD_REG] = 0x194,
+               [ICSS_IEP_SYNC1_DELAY_REG] = 0x198,
+               [ICSS_IEP_SYNC_START_REG] = 0x19c,
+       },
+       .config = &am654_icss_iep_regmap_config,
+};
+
+static bool am335x_icss_iep_valid_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case ICSS_IEP_GLOBAL_CFG_REG ... ICSS_IEP_CAPTURE_STAT_REG:
+       case ICSS_IEP_CAP6_RISE_REG0:
+       case ICSS_IEP_CMP_CFG_REG ... ICSS_IEP_CMP0_REG0:
+       case ICSS_IEP_CMP8_REG0 ... ICSS_IEP_SYNC_START_REG:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static const struct regmap_config am335x_icss_iep_regmap_config = {
+       .name = "icss iep",
+       .reg_stride = 1,
+       .reg_write = icss_iep_regmap_write,
+       .reg_read = icss_iep_regmap_read,
+       .writeable_reg = am335x_icss_iep_valid_reg,
+       .readable_reg = am335x_icss_iep_valid_reg,
+};
+
+static const struct icss_iep_plat_data am335x_icss_iep_plat_data = {
+       .flags = 0,
+       .reg_offs = {
+               [ICSS_IEP_GLOBAL_CFG_REG] = 0x00,
+               [ICSS_IEP_COMPEN_REG] = 0x08,
+               [ICSS_IEP_COUNT_REG0] = 0x0c,
+               [ICSS_IEP_CAPTURE_CFG_REG] = 0x10,
+               [ICSS_IEP_CAPTURE_STAT_REG] = 0x14,
+
+               [ICSS_IEP_CAP6_RISE_REG0] = 0x30,
+
+               [ICSS_IEP_CAP7_RISE_REG0] = 0x38,
+
+               [ICSS_IEP_CMP_CFG_REG] = 0x40,
+               [ICSS_IEP_CMP_STAT_REG] = 0x44,
+               [ICSS_IEP_CMP0_REG0] = 0x48,
+
+               [ICSS_IEP_CMP8_REG0] = 0x88,
+               [ICSS_IEP_SYNC_CTRL_REG] = 0x100,
+               [ICSS_IEP_SYNC0_STAT_REG] = 0x108,
+               [ICSS_IEP_SYNC1_STAT_REG] = 0x10c,
+               [ICSS_IEP_SYNC_PWIDTH_REG] = 0x110,
+               [ICSS_IEP_SYNC0_PERIOD_REG] = 0x114,
+               [ICSS_IEP_SYNC1_DELAY_REG] = 0x118,
+               [ICSS_IEP_SYNC_START_REG] = 0x11c,
+       },
+       .config = &am335x_icss_iep_regmap_config,
+};
+
 static const struct of_device_id icss_iep_of_match[] = {
        {
                .compatible = "ti,am654-icss-iep",
                .data = &am654_icss_iep_plat_data,
        },
+       {
+               .compatible = "ti,am5728-icss-iep",
+               .data = &am57xx_icss_iep_plat_data,
+       },
+       {
+               .compatible = "ti,am4376-icss-iep",
+               .data = &am335x_icss_iep_plat_data,
+       },
+       {
+               .compatible = "ti,am3356-icss-iep",
+               .data = &am335x_icss_iep_plat_data,
+       },
        {},
 };
 MODULE_DEVICE_TABLE(of, icss_iep_of_match);
index 295c8bdd7c768171a813c7f8ee348aff6949ad71..65d0b792132db6d0937f478fea3f8f5cfd18a324 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "icssm_prueth.h"
 #include "../icssg/icssg_mii_rt.h"
+#include "../icssg/icss_iep.h"
 
 #define OCMC_RAM_SIZE          (SZ_64K)
 
@@ -878,6 +879,48 @@ static int icssm_emac_request_irqs(struct prueth_emac *emac)
        return ret;
 }
 
+static void icssm_ptp_dram_init(struct prueth_emac *emac)
+{
+       void __iomem *sram = emac->prueth->mem[PRUETH_MEM_SHARED_RAM].va;
+       u64 temp64;
+
+       writew(0, sram + MII_RX_CORRECTION_OFFSET);
+       writew(0, sram + MII_TX_CORRECTION_OFFSET);
+
+       /* Initialize RCF to 1 (Linux N/A) */
+       writel(1 * 1024, sram + TIMESYNC_TC_RCF_OFFSET);
+
+       /* This flag will be set and cleared by firmware */
+       /* Write Sync0 period for sync signal generation in PTP
+        * memory in shared RAM
+        */
+       writel(200000000 / 50, sram + TIMESYNC_SYNC0_WIDTH_OFFSET);
+
+       /* Write CMP1 period for sync signal generation in PTP
+        * memory in shared RAM
+        */
+       temp64 = 1000000;
+       memcpy_toio(sram + TIMESYNC_CMP1_CMP_OFFSET, &temp64, sizeof(temp64));
+
+       /* Write Sync0 period for sync signal generation in PTP
+        * memory in shared RAM
+        */
+       writel(1000000, sram + TIMESYNC_CMP1_PERIOD_OFFSET);
+
+       /* Configures domainNumber list. Firmware supports 2 domains */
+       writeb(0, sram + TIMESYNC_DOMAIN_NUMBER_LIST);
+       writeb(0, sram + TIMESYNC_DOMAIN_NUMBER_LIST + 1);
+
+       /* Configure 1-step/2-step */
+       writeb(1, sram + DISABLE_SWITCH_SYNC_RELAY_OFFSET);
+
+       /* Configures the setting to Link local frame without HSR tag */
+       writeb(0, sram + LINK_LOCAL_FRAME_HAS_HSR_TAG);
+
+       /* Enable E2E/UDP PTP message timestamping */
+       writeb(1, sram + PTP_IPV4_UDP_E2E_ENABLE);
+}
+
 /**
  * icssm_emac_ndo_open - EMAC device open
  * @ndev: network adapter device
@@ -900,9 +943,18 @@ static int icssm_emac_ndo_open(struct net_device *ndev)
 
        icssm_prueth_emac_config(emac);
 
+       if (!prueth->emac_configured) {
+               icssm_ptp_dram_init(emac);
+               ret = icss_iep_init(prueth->iep, NULL, NULL, 0);
+               if (ret) {
+                       netdev_err(ndev, "Failed to initialize iep: %d\n", ret);
+                       goto iep_exit;
+               }
+       }
+
        ret = icssm_emac_set_boot_pru(emac, ndev);
        if (ret)
-               return ret;
+               goto iep_exit;
 
        ret = icssm_emac_request_irqs(emac);
        if (ret)
@@ -926,6 +978,10 @@ static int icssm_emac_ndo_open(struct net_device *ndev)
 rproc_shutdown:
        rproc_shutdown(emac->pru);
 
+iep_exit:
+       if (!prueth->emac_configured)
+               icss_iep_exit(prueth->iep);
+
        return ret;
 }
 
@@ -1442,12 +1498,19 @@ static int icssm_prueth_probe(struct platform_device *pdev)
                }
        }
 
+       prueth->iep = icss_iep_get(np);
+       if (IS_ERR(prueth->iep)) {
+               ret = PTR_ERR(prueth->iep);
+               dev_err(dev, "unable to get IEP\n");
+               goto netdev_exit;
+       }
+
        /* register the network devices */
        if (eth0_node) {
                ret = register_netdev(prueth->emac[PRUETH_MAC0]->ndev);
                if (ret) {
                        dev_err(dev, "can't register netdev for port MII0");
-                       goto netdev_exit;
+                       goto iep_put;
                }
 
                prueth->registered_netdevs[PRUETH_MAC0] =
@@ -1481,6 +1544,10 @@ netdev_unregister:
                unregister_netdev(prueth->registered_netdevs[i]);
        }
 
+iep_put:
+       icss_iep_put(prueth->iep);
+       prueth->iep = NULL;
+
 netdev_exit:
        for (i = 0; i < PRUETH_NUM_MACS; i++) {
                eth_node = prueth->eth_node[i];
@@ -1549,6 +1616,9 @@ static void icssm_prueth_remove(struct platform_device *pdev)
                                                 &prueth->mem[i]);
        }
 
+       icss_iep_put(prueth->iep);
+       prueth->iep = NULL;
+
        pruss_put(prueth->pruss);
 
        if (prueth->eth_node[PRUETH_MAC0])
index f5b6b1e99bd4bdb23a8832f250a14294f8b4e8f0..8e7e0af0814491dc504db6533c95512ece01bb2b 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/remoteproc/pruss.h>
 
 #include "icssm_switch.h"
+#include "icssm_prueth_ptp.h"
 
 /* ICSSM size of redundancy tag */
 #define ICSSM_LRE_TAG_SIZE     6
@@ -238,6 +239,7 @@ struct prueth {
        struct pruss_mem_region mem[PRUETH_MEM_MAX];
        struct gen_pool *sram_pool;
        struct regmap *mii_rt;
+       struct icss_iep *iep;
 
        const struct prueth_private_data *fw_data;
        struct prueth_fw_offsets *fw_offsets;
diff --git a/drivers/net/ethernet/ti/icssm/icssm_prueth_ptp.h b/drivers/net/ethernet/ti/icssm/icssm_prueth_ptp.h
new file mode 100644 (file)
index 0000000..e0bf692
--- /dev/null
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 Texas Instruments Incorporated - https://www.ti.com
+ */
+#ifndef PRUETH_PTP_H
+#define PRUETH_PTP_H
+
+#define RX_SYNC_TIMESTAMP_OFFSET_P1            0x8    /* 8 bytes */
+#define RX_PDELAY_REQ_TIMESTAMP_OFFSET_P1      0x14   /* 12 bytes */
+
+#define DISABLE_PTP_FRAME_FORWARDING_CTRL_OFFSET 0x14  /* 1 byte */
+
+#define RX_PDELAY_RESP_TIMESTAMP_OFFSET_P1     0x20   /* 12 bytes */
+#define RX_SYNC_TIMESTAMP_OFFSET_P2            0x2c   /* 12 bytes */
+#define RX_PDELAY_REQ_TIMESTAMP_OFFSET_P2      0x38   /* 12 bytes */
+#define RX_PDELAY_RESP_TIMESTAMP_OFFSET_P2     0x44   /* 12 bytes */
+#define TIMESYNC_DOMAIN_NUMBER_LIST            0x50   /* 2 bytes */
+#define P1_SMA_LINE_DELAY_OFFSET               0x52   /* 4 bytes */
+#define P2_SMA_LINE_DELAY_OFFSET               0x56   /* 4 bytes */
+#define TIMESYNC_SECONDS_COUNT_OFFSET          0x5a   /* 6 bytes */
+#define TIMESYNC_TC_RCF_OFFSET                 0x60   /* 4 bytes */
+#define DUT_IS_MASTER_OFFSET                   0x64   /* 1 byte */
+#define MASTER_PORT_NUM_OFFSET                 0x65   /* 1 byte */
+#define SYNC_MASTER_MAC_OFFSET                 0x66   /* 6 bytes */
+#define TX_TS_NOTIFICATION_OFFSET_SYNC_P1      0x6c   /* 1 byte */
+#define TX_TS_NOTIFICATION_OFFSET_PDEL_REQ_P1  0x6d   /* 1 byte */
+#define TX_TS_NOTIFICATION_OFFSET_PDEL_RES_P1  0x6e   /* 1 byte */
+#define TX_TS_NOTIFICATION_OFFSET_SYNC_P2      0x6f   /* 1 byte */
+#define TX_TS_NOTIFICATION_OFFSET_PDEL_REQ_P2  0x70   /* 1 byte */
+#define TX_TS_NOTIFICATION_OFFSET_PDEL_RES_P2  0x71   /* 1 byte */
+#define TX_SYNC_TIMESTAMP_OFFSET_P1            0x72   /* 12 bytes */
+#define TX_PDELAY_REQ_TIMESTAMP_OFFSET_P1      0x7e   /* 12 bytes */
+#define TX_PDELAY_RESP_TIMESTAMP_OFFSET_P1     0x8a   /* 12 bytes */
+#define TX_SYNC_TIMESTAMP_OFFSET_P2            0x96   /* 12 bytes */
+#define TX_PDELAY_REQ_TIMESTAMP_OFFSET_P2      0xa2   /* 12 bytes */
+#define TX_PDELAY_RESP_TIMESTAMP_OFFSET_P2     0xae   /* 12 bytes */
+#define TIMESYNC_CTRL_VAR_OFFSET               0xba   /* 1 byte */
+#define DISABLE_SWITCH_SYNC_RELAY_OFFSET       0xbb   /* 1 byte */
+#define MII_RX_CORRECTION_OFFSET               0xbc   /* 2 bytes */
+#define MII_TX_CORRECTION_OFFSET               0xbe   /* 2 bytes */
+#define TIMESYNC_CMP1_CMP_OFFSET               0xc0   /* 8 bytes */
+#define TIMESYNC_SYNC0_CMP_OFFSET              0xc8   /* 8 bytes */
+#define TIMESYNC_CMP1_PERIOD_OFFSET            0xd0   /* 4 bytes */
+#define TIMESYNC_SYNC0_WIDTH_OFFSET            0xd4   /* 4 bytes */
+#define SINGLE_STEP_IEP_OFFSET_P1              0xd8   /* 8 bytes */
+#define SINGLE_STEP_SECONDS_OFFSET_P1          0xe0   /* 8 bytes */
+#define SINGLE_STEP_IEP_OFFSET_P2              0xe8   /* 8 bytes */
+#define SINGLE_STEP_SECONDS_OFFSET_P2          0xf0   /* 8 bytes */
+#define LINK_LOCAL_FRAME_HAS_HSR_TAG           0xf8   /* 1 bytes */
+#define PTP_PREV_TX_TIMESTAMP_P1               0xf9  /* 8 bytes */
+#define PTP_PREV_TX_TIMESTAMP_P2               0x101  /* 8 bytes */
+#define PTP_CLK_IDENTITY_OFFSET                        0x109  /* 8 bytes */
+#define PTP_SCRATCH_MEM                                0x111  /* 16 byte */
+#define PTP_IPV4_UDP_E2E_ENABLE                        0x121  /* 1 byte */
+
+enum {
+       PRUETH_PTP_SYNC,
+       PRUETH_PTP_DLY_REQ,
+       PRUETH_PTP_DLY_RESP,
+       PRUETH_PTP_TS_EVENTS,
+};
+
+#define PRUETH_PTP_TS_SIZE             12
+#define PRUETH_PTP_TS_NOTIFY_SIZE      1
+#define PRUETH_PTP_TS_NOTIFY_MASK      0xff
+
+/* Bit definitions for TIMESYNC_CTRL */
+#define TIMESYNC_CTRL_BG_ENABLE    BIT(0)
+#define TIMESYNC_CTRL_FORCED_2STEP BIT(1)
+
+static inline u32 icssm_prueth_tx_ts_offs_get(u8 port, u8 event)
+{
+       return TX_SYNC_TIMESTAMP_OFFSET_P1 + port *
+               PRUETH_PTP_TS_EVENTS * PRUETH_PTP_TS_SIZE +
+               event * PRUETH_PTP_TS_SIZE;
+}
+
+static inline u32 icssm_prueth_tx_ts_notify_offs_get(u8 port, u8 event)
+{
+       return TX_TS_NOTIFICATION_OFFSET_SYNC_P1 +
+               PRUETH_PTP_TS_EVENTS * PRUETH_PTP_TS_NOTIFY_SIZE * port +
+               event * PRUETH_PTP_TS_NOTIFY_SIZE;
+}
+
+#endif /* PRUETH_PTP_H */