diff options
Diffstat (limited to 'drivers/net/ethernet/ti')
-rw-r--r-- | drivers/net/ethernet/ti/am65-cpsw-nuss.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/cpts.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/icssg/icssg_config.c | 158 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/icssg/icssg_config.h | 80 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/icssg/icssg_prueth.c | 167 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/icssg/icssg_prueth.h | 19 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/ti/icssg/icssg_switch_map.h | 3 |
8 files changed, 336 insertions, 124 deletions
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index 231ca141331f..ecd6ecac87bb 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -2600,6 +2600,7 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common) return -ENOENT; for_each_child_of_node(node, port_np) { + phy_interface_t phy_if; struct am65_cpsw_port *port; u32 port_id; @@ -2665,14 +2666,36 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common) /* get phy/link info */ port->slave.port_np = of_node_get(port_np); - ret = of_get_phy_mode(port_np, &port->slave.phy_if); + ret = of_get_phy_mode(port_np, &phy_if); if (ret) { dev_err(dev, "%pOF read phy-mode err %d\n", port_np, ret); goto of_node_put; } - ret = phy_set_mode_ext(port->slave.ifphy, PHY_MODE_ETHERNET, port->slave.phy_if); + /* CPSW controllers supported by this driver have a fixed + * internal TX delay in RGMII mode. Fix up PHY mode to account + * for this and warn about Device Trees that claim to have a TX + * delay on the PCB. + */ + switch (phy_if) { + case PHY_INTERFACE_MODE_RGMII_ID: + phy_if = PHY_INTERFACE_MODE_RGMII_RXID; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + phy_if = PHY_INTERFACE_MODE_RGMII; + break; + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_RXID: + dev_warn(dev, + "RGMII mode without internal TX delay unsupported; please fix your Device Tree\n"); + break; + default: + break; + } + + port->slave.phy_if = phy_if; + ret = phy_set_mode_ext(port->slave.ifphy, PHY_MODE_ETHERNET, phy_if); if (ret) goto of_node_put; diff --git a/drivers/net/ethernet/ti/cpts.c b/drivers/net/ethernet/ti/cpts.c index dbbea9146040..2ba4c8795d60 100644 --- a/drivers/net/ethernet/ti/cpts.c +++ b/drivers/net/ethernet/ti/cpts.c @@ -181,7 +181,7 @@ void cpts_misc_interrupt(struct cpts *cpts) } EXPORT_SYMBOL_GPL(cpts_misc_interrupt); -static u64 cpts_systim_read(const struct cyclecounter *cc) +static u64 cpts_systim_read(struct cyclecounter *cc) { struct cpts *cpts = container_of(cc, struct cpts, cc); diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c index ddfd1c02a885..da53eb04b0a4 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_config.c +++ b/drivers/net/ethernet/ti/icssg/icssg_config.c @@ -288,8 +288,12 @@ static int prueth_fw_offload_buffer_setup(struct prueth_emac *emac) int i; addr = lower_32_bits(prueth->msmcram.pa); - if (slice) - addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; + if (slice) { + if (prueth->pdata.banked_ms_ram) + addr += MSMC_RAM_BANK_SIZE; + else + addr += PRUETH_SW_TOTAL_BUF_SIZE_PER_SLICE; + } if (addr % SZ_64K) { dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n"); @@ -297,43 +301,66 @@ static int prueth_fw_offload_buffer_setup(struct prueth_emac *emac) } bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; - /* workaround for f/w bug. bpool 0 needs to be initialized */ - for (i = 0; i < PRUETH_NUM_BUF_POOLS; i++) { + + /* Configure buffer pools for forwarding buffers + * - used by firmware to store packets to be forwarded to other port + * - 8 total pools per slice + */ + for (i = 0; i < PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE; i++) { writel(addr, &bpool_cfg[i].addr); - writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len); - addr += PRUETH_EMAC_BUF_POOL_SIZE; + writel(PRUETH_SW_FWD_BUF_POOL_SIZE, &bpool_cfg[i].len); + addr += PRUETH_SW_FWD_BUF_POOL_SIZE; } - if (!slice) - addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; - else - addr += PRUETH_SW_NUM_BUF_POOLS_HOST * PRUETH_SW_BUF_POOL_SIZE_HOST; - - for (i = PRUETH_NUM_BUF_POOLS; - i < 2 * PRUETH_SW_NUM_BUF_POOLS_HOST + PRUETH_NUM_BUF_POOLS; - i++) { - /* The driver only uses first 4 queues per PRU so only initialize them */ - if (i % PRUETH_SW_NUM_BUF_POOLS_HOST < PRUETH_SW_NUM_BUF_POOLS_PER_PRU) { - writel(addr, &bpool_cfg[i].addr); - writel(PRUETH_SW_BUF_POOL_SIZE_HOST, &bpool_cfg[i].len); - addr += PRUETH_SW_BUF_POOL_SIZE_HOST; + /* Configure buffer pools for Local Injection buffers + * - used by firmware to store packets received from host core + * - 16 total pools per slice + */ + for (i = 0; i < PRUETH_NUM_LI_BUF_POOLS_PER_SLICE; i++) { + int cfg_idx = i + PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE; + + /* The driver only uses first 4 queues per PRU, + * so only initialize buffer for them + */ + if ((i % PRUETH_NUM_LI_BUF_POOLS_PER_PORT_PER_SLICE) + < PRUETH_SW_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE) { + writel(addr, &bpool_cfg[cfg_idx].addr); + writel(PRUETH_SW_LI_BUF_POOL_SIZE, + &bpool_cfg[cfg_idx].len); + addr += PRUETH_SW_LI_BUF_POOL_SIZE; } else { - writel(0, &bpool_cfg[i].addr); - writel(0, &bpool_cfg[i].len); + writel(0, &bpool_cfg[cfg_idx].addr); + writel(0, &bpool_cfg[cfg_idx].len); } } - if (!slice) - addr += PRUETH_SW_NUM_BUF_POOLS_HOST * PRUETH_SW_BUF_POOL_SIZE_HOST; - else - addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; + /* Express RX buffer queue + * - used by firmware to store express packets to be transmitted + * to the host core + */ + rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET; + for (i = 0; i < 3; i++) + writel(addr, &rxq_ctx->start[i]); + + addr += PRUETH_SW_HOST_EXP_BUF_POOL_SIZE; + writel(addr, &rxq_ctx->end); + /* Pre-emptible RX buffer queue + * - used by firmware to store preemptible packets to be transmitted + * to the host core + */ rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; for (i = 0; i < 3; i++) writel(addr, &rxq_ctx->start[i]); - addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; - writel(addr - SZ_2K, &rxq_ctx->end); + addr += PRUETH_SW_HOST_PRE_BUF_POOL_SIZE; + writel(addr, &rxq_ctx->end); + + /* Set pointer for default dropped packet write + * - used by firmware to temporarily store packet to be dropped + */ + rxq_ctx = emac->dram.va + DEFAULT_MSMC_Q_OFFSET; + writel(addr, &rxq_ctx->start[0]); return 0; } @@ -347,13 +374,13 @@ static int prueth_emac_buffer_setup(struct prueth_emac *emac) u32 addr; int i; - /* Layout to have 64KB aligned buffer pool - * |BPOOL0|BPOOL1|RX_CTX0|RX_CTX1| - */ - addr = lower_32_bits(prueth->msmcram.pa); - if (slice) - addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; + if (slice) { + if (prueth->pdata.banked_ms_ram) + addr += MSMC_RAM_BANK_SIZE; + else + addr += PRUETH_EMAC_TOTAL_BUF_SIZE_PER_SLICE; + } if (addr % SZ_64K) { dev_warn(prueth->dev, "buffer pool needs to be 64KB aligned\n"); @@ -361,39 +388,66 @@ static int prueth_emac_buffer_setup(struct prueth_emac *emac) } bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; - /* workaround for f/w bug. bpool 0 needs to be initilalized */ - writel(addr, &bpool_cfg[0].addr); - writel(0, &bpool_cfg[0].len); - for (i = PRUETH_EMAC_BUF_POOL_START; - i < PRUETH_EMAC_BUF_POOL_START + PRUETH_NUM_BUF_POOLS; - i++) { - writel(addr, &bpool_cfg[i].addr); - writel(PRUETH_EMAC_BUF_POOL_SIZE, &bpool_cfg[i].len); - addr += PRUETH_EMAC_BUF_POOL_SIZE; + /* Configure buffer pools for forwarding buffers + * - in mac mode - no forwarding so initialize all pools to 0 + * - 8 total pools per slice + */ + for (i = 0; i < PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE; i++) { + writel(0, &bpool_cfg[i].addr); + writel(0, &bpool_cfg[i].len); } - if (!slice) - addr += PRUETH_NUM_BUF_POOLS * PRUETH_EMAC_BUF_POOL_SIZE; - else - addr += PRUETH_EMAC_RX_CTX_BUF_SIZE * 2; + /* Configure buffer pools for Local Injection buffers + * - used by firmware to store packets received from host core + * - 16 total pools per slice + */ + bpool_cfg = emac->dram.va + BUFFER_POOL_0_ADDR_OFFSET; + for (i = 0; i < PRUETH_NUM_LI_BUF_POOLS_PER_SLICE; i++) { + int cfg_idx = i + PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE; + + /* In EMAC mode, only first 4 buffers are used, + * as 1 slice needs to handle only 1 port + */ + if (i < PRUETH_EMAC_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE) { + writel(addr, &bpool_cfg[cfg_idx].addr); + writel(PRUETH_EMAC_LI_BUF_POOL_SIZE, + &bpool_cfg[cfg_idx].len); + addr += PRUETH_EMAC_LI_BUF_POOL_SIZE; + } else { + writel(0, &bpool_cfg[cfg_idx].addr); + writel(0, &bpool_cfg[cfg_idx].len); + } + } - /* Pre-emptible RX buffer queue */ - rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; + /* Express RX buffer queue + * - used by firmware to store express packets to be transmitted + * to host core + */ + rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET; for (i = 0; i < 3; i++) writel(addr, &rxq_ctx->start[i]); - addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; + addr += PRUETH_EMAC_HOST_EXP_BUF_POOL_SIZE; writel(addr, &rxq_ctx->end); - /* Express RX buffer queue */ - rxq_ctx = emac->dram.va + HOST_RX_Q_EXP_CONTEXT_OFFSET; + /* Pre-emptible RX buffer queue + * - used by firmware to store preemptible packets to be transmitted + * to host core + */ + rxq_ctx = emac->dram.va + HOST_RX_Q_PRE_CONTEXT_OFFSET; for (i = 0; i < 3; i++) writel(addr, &rxq_ctx->start[i]); - addr += PRUETH_EMAC_RX_CTX_BUF_SIZE; + addr += PRUETH_EMAC_HOST_PRE_BUF_POOL_SIZE; writel(addr, &rxq_ctx->end); + /* Set pointer for default dropped packet write + * - used by firmware to temporarily store packet to be dropped + */ + rxq_ctx = emac->dram.va + DEFAULT_MSMC_Q_OFFSET; + writel(addr, &rxq_ctx->start[0]); + return 0; } diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.h b/drivers/net/ethernet/ti/icssg/icssg_config.h index c884e9fa099e..60d69744ffae 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_config.h +++ b/drivers/net/ethernet/ti/icssg/icssg_config.h @@ -26,21 +26,71 @@ struct icssg_flow_cfg { #define PRUETH_MAX_RX_FLOWS 1 /* excluding default flow */ #define PRUETH_RX_FLOW_DATA 0 -#define PRUETH_EMAC_BUF_POOL_SIZE SZ_8K -#define PRUETH_EMAC_POOLS_PER_SLICE 24 -#define PRUETH_EMAC_BUF_POOL_START 8 -#define PRUETH_NUM_BUF_POOLS 8 -#define PRUETH_EMAC_RX_CTX_BUF_SIZE SZ_16K /* per slice */ -#define MSMC_RAM_SIZE \ - (2 * (PRUETH_EMAC_BUF_POOL_SIZE * PRUETH_NUM_BUF_POOLS + \ - PRUETH_EMAC_RX_CTX_BUF_SIZE * 2)) - -#define PRUETH_SW_BUF_POOL_SIZE_HOST SZ_4K -#define PRUETH_SW_NUM_BUF_POOLS_HOST 8 -#define PRUETH_SW_NUM_BUF_POOLS_PER_PRU 4 -#define MSMC_RAM_SIZE_SWITCH_MODE \ - (MSMC_RAM_SIZE + \ - (2 * PRUETH_SW_BUF_POOL_SIZE_HOST * PRUETH_SW_NUM_BUF_POOLS_HOST)) +/* Defines for forwarding path buffer pools: + * - used by firmware to store packets to be forwarded to other port + * - 8 total pools per slice + * - only used in switch mode (as no forwarding in mac mode) + */ +#define PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE 8 +#define PRUETH_SW_FWD_BUF_POOL_SIZE (SZ_8K) + +/* Defines for local injection path buffer pools: + * - used by firmware to store packets received from host core + * - 16 total pools per slice + * - 8 pools per port per slice and each slice handles both ports + * - only 4 out of 8 pools used per port (as only 4 real QoS levels in ICSSG) + * - switch mode: 8 total pools used + * - mac mode: 4 total pools used + */ +#define PRUETH_NUM_LI_BUF_POOLS_PER_SLICE 16 +#define PRUETH_NUM_LI_BUF_POOLS_PER_PORT_PER_SLICE 8 +#define PRUETH_SW_LI_BUF_POOL_SIZE SZ_4K +#define PRUETH_SW_USED_LI_BUF_POOLS_PER_SLICE 8 +#define PRUETH_SW_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE 4 +#define PRUETH_EMAC_LI_BUF_POOL_SIZE SZ_8K +#define PRUETH_EMAC_USED_LI_BUF_POOLS_PER_SLICE 4 +#define PRUETH_EMAC_USED_LI_BUF_POOLS_PER_PORT_PER_SLICE 4 + +/* Defines for host egress path - express and preemptible buffers + * - used by firmware to store express and preemptible packets + * to be transmitted to host core + * - used by both mac/switch modes + */ +#define PRUETH_SW_HOST_EXP_BUF_POOL_SIZE SZ_16K +#define PRUETH_SW_HOST_PRE_BUF_POOL_SIZE (SZ_16K - SZ_2K) +#define PRUETH_EMAC_HOST_EXP_BUF_POOL_SIZE PRUETH_SW_HOST_EXP_BUF_POOL_SIZE +#define PRUETH_EMAC_HOST_PRE_BUF_POOL_SIZE PRUETH_SW_HOST_PRE_BUF_POOL_SIZE + +/* Buffer used by firmware to temporarily store packet to be dropped */ +#define PRUETH_SW_DROP_PKT_BUF_SIZE SZ_2K +#define PRUETH_EMAC_DROP_PKT_BUF_SIZE PRUETH_SW_DROP_PKT_BUF_SIZE + +/* Total switch mode memory usage for buffers per slice */ +#define PRUETH_SW_TOTAL_BUF_SIZE_PER_SLICE \ + (PRUETH_SW_FWD_BUF_POOL_SIZE * PRUETH_NUM_FWD_BUF_POOLS_PER_SLICE + \ + PRUETH_SW_LI_BUF_POOL_SIZE * PRUETH_SW_USED_LI_BUF_POOLS_PER_SLICE + \ + PRUETH_SW_HOST_EXP_BUF_POOL_SIZE + \ + PRUETH_SW_HOST_PRE_BUF_POOL_SIZE + \ + PRUETH_SW_DROP_PKT_BUF_SIZE) + +/* Total switch mode memory usage for all buffers */ +#define PRUETH_SW_TOTAL_BUF_SIZE \ + (2 * PRUETH_SW_TOTAL_BUF_SIZE_PER_SLICE) + +/* Total mac mode memory usage for buffers per slice */ +#define PRUETH_EMAC_TOTAL_BUF_SIZE_PER_SLICE \ + (PRUETH_EMAC_LI_BUF_POOL_SIZE * \ + PRUETH_EMAC_USED_LI_BUF_POOLS_PER_SLICE + \ + PRUETH_EMAC_HOST_EXP_BUF_POOL_SIZE + \ + PRUETH_EMAC_HOST_PRE_BUF_POOL_SIZE + \ + PRUETH_EMAC_DROP_PKT_BUF_SIZE) + +/* Total mac mode memory usage for all buffers */ +#define PRUETH_EMAC_TOTAL_BUF_SIZE \ + (2 * PRUETH_EMAC_TOTAL_BUF_SIZE_PER_SLICE) + +/* Size of 1 bank of MSMC/OC_SRAM memory */ +#define MSMC_RAM_BANK_SIZE SZ_256K #define PRUETH_SWITCH_FDB_MASK ((SIZE_OF_FDB / NUMBER_OF_FDB_BUCKET_ENTRIES) - 1) diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c index 86fc1278127c..2b973d6e2341 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c @@ -125,45 +125,6 @@ static irqreturn_t prueth_tx_ts_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static struct icssg_firmwares icssg_hsr_firmwares[] = { - { - .pru = "ti-pruss/am65x-sr2-pru0-pruhsr-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu0-pruhsr-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru0-pruhsr-fw.elf", - }, - { - .pru = "ti-pruss/am65x-sr2-pru1-pruhsr-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu1-pruhsr-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru1-pruhsr-fw.elf", - } -}; - -static struct icssg_firmwares icssg_switch_firmwares[] = { - { - .pru = "ti-pruss/am65x-sr2-pru0-prusw-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu0-prusw-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru0-prusw-fw.elf", - }, - { - .pru = "ti-pruss/am65x-sr2-pru1-prusw-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu1-prusw-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru1-prusw-fw.elf", - } -}; - -static struct icssg_firmwares icssg_emac_firmwares[] = { - { - .pru = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf", - }, - { - .pru = "ti-pruss/am65x-sr2-pru1-prueth-fw.elf", - .rtu = "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf", - .txpru = "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf", - } -}; - static int prueth_start(struct rproc *rproc, const char *fw_name) { int ret; @@ -186,11 +147,13 @@ static int prueth_emac_start(struct prueth *prueth) int ret, slice; if (prueth->is_switch_mode) - firmwares = icssg_switch_firmwares; - else if (prueth->is_hsr_offload_mode) - firmwares = icssg_hsr_firmwares; + firmwares = prueth->icssg_switch_firmwares; + else if (prueth->is_hsr_offload_mode && HSR_V1 == prueth->hsr_prp_version) + firmwares = prueth->icssg_hsr_firmwares; + else if (prueth->is_hsr_offload_mode && PRP_V1 == prueth->hsr_prp_version) + firmwares = prueth->icssg_prp_firmwares; else - firmwares = icssg_emac_firmwares; + firmwares = prueth->icssg_emac_firmwares; for (slice = 0; slice < PRUETH_NUM_MACS; slice++) { ret = prueth_start(prueth->pru[slice], firmwares[slice].pru); @@ -1566,6 +1529,7 @@ static int prueth_netdevice_event(struct notifier_block *unused, struct netdev_notifier_changeupper_info *info; struct prueth_emac *emac = netdev_priv(ndev); struct prueth *prueth = emac->prueth; + enum hsr_version hsr_ndev_version; int ret = NOTIFY_DONE; if (ndev->netdev_ops != &emac_netdev_ops) @@ -1577,6 +1541,11 @@ static int prueth_netdevice_event(struct notifier_block *unused, if ((ndev->features & NETIF_PRUETH_HSR_OFFLOAD_FEATURES) && is_hsr_master(info->upper_dev)) { + hsr_get_version(info->upper_dev, &hsr_ndev_version); + if (hsr_ndev_version != HSR_V1 && hsr_ndev_version != PRP_V1) + return -EOPNOTSUPP; + prueth->hsr_prp_version = hsr_ndev_version; + if (info->linking) { if (!prueth->hsr_dev) { prueth->hsr_dev = info->upper_dev; @@ -1632,6 +1601,87 @@ static void prueth_unregister_notifiers(struct prueth *prueth) unregister_netdevice_notifier(&prueth->prueth_netdevice_nb); } +static void icssg_read_firmware_names(struct device_node *np, + struct icssg_firmwares *fw) +{ + int i; + + for (i = 0; i < PRUETH_NUM_MACS; i++) { + of_property_read_string_index(np, "firmware-name", i * 3 + 0, + &fw[i].pru); + of_property_read_string_index(np, "firmware-name", i * 3 + 1, + &fw[i].rtu); + of_property_read_string_index(np, "firmware-name", i * 3 + 2, + &fw[i].txpru); + } +} + +/* icssg_firmware_name_replace - Replace a substring in firmware name + * @dev: device pointer for memory allocation + * @src: source firmware name string + * @from: substring to replace + * @to: replacement substring + * + * Return: a newly allocated string with the replacement, or the original + * string if replacement is not possible. + */ +static const char *icssg_firmware_name_replace(struct device *dev, + const char *src, + const char *from, + const char *to) +{ + size_t prefix, from_len, to_len, total; + const char *p = strstr(src, from); + char *buf; + + if (!p) + return src; /* fallback: no replacement, use original */ + + prefix = p - src; + from_len = strlen(from); + to_len = strlen(to); + total = strlen(src) - from_len + to_len + 1; + + buf = devm_kzalloc(dev, total, GFP_KERNEL); + if (!buf) + return src; /* fallback: allocation failed, use original */ + + strscpy(buf, src, prefix + 1); + strscpy(buf + prefix, to, to_len + 1); + strscpy(buf + prefix + to_len, p + from_len, total - prefix - to_len); + + return buf; +} + +/** + * icssg_mode_firmware_names - Generate firmware names for a specific mode + * @dev: device pointer for logging and context + * @src: source array of firmware name structures + * @dst: destination array to store updated firmware name structures + * @from: substring in firmware names to be replaced + * @to: substring to replace @from in firmware names + * + * Iterates over all MACs and replaces occurrences of the @from substring + * with @to in the firmware names (pru, rtu, txpru) for each MAC. The + * updated firmware names are stored in the @dst array. + */ +static void icssg_mode_firmware_names(struct device *dev, + struct icssg_firmwares *src, + struct icssg_firmwares *dst, + const char *from, const char *to) +{ + int i; + + for (i = 0; i < PRUETH_NUM_MACS; i++) { + dst[i].pru = icssg_firmware_name_replace(dev, src[i].pru, + from, to); + dst[i].rtu = icssg_firmware_name_replace(dev, src[i].rtu, + from, to); + dst[i].txpru = icssg_firmware_name_replace(dev, src[i].txpru, + from, to); + } +} + static int prueth_probe(struct platform_device *pdev) { struct device_node *eth_node, *eth_ports_node; @@ -1764,10 +1814,15 @@ static int prueth_probe(struct platform_device *pdev) goto put_mem; } - msmc_ram_size = MSMC_RAM_SIZE; prueth->is_switchmode_supported = prueth->pdata.switch_mode; - if (prueth->is_switchmode_supported) - msmc_ram_size = MSMC_RAM_SIZE_SWITCH_MODE; + if (prueth->pdata.banked_ms_ram) { + /* Reserve 2 MSMC RAM banks for buffers to avoid arbitration */ + msmc_ram_size = (2 * MSMC_RAM_BANK_SIZE); + } else { + msmc_ram_size = PRUETH_EMAC_TOTAL_BUF_SIZE; + if (prueth->is_switchmode_supported) + msmc_ram_size = PRUETH_SW_TOTAL_BUF_SIZE; + } /* NOTE: FW bug needs buffer base to be 64KB aligned */ prueth->msmcram.va = @@ -1808,6 +1863,17 @@ static int prueth_probe(struct platform_device *pdev) icss_iep_init_fw(prueth->iep1); } + /* Read EMAC firmware names from device tree */ + icssg_read_firmware_names(np, prueth->icssg_emac_firmwares); + + /* Generate other mode firmware names based on EMAC firmware names */ + icssg_mode_firmware_names(dev, prueth->icssg_emac_firmwares, + prueth->icssg_switch_firmwares, "eth", "sw"); + icssg_mode_firmware_names(dev, prueth->icssg_emac_firmwares, + prueth->icssg_hsr_firmwares, "eth", "hsr"); + icssg_mode_firmware_names(dev, prueth->icssg_emac_firmwares, + prueth->icssg_prp_firmwares, "eth", "prp"); + spin_lock_init(&prueth->vtbl_lock); spin_lock_init(&prueth->stats_lock); /* setup netdev interfaces */ @@ -1924,7 +1990,8 @@ put_iep0: free_pool: gen_pool_free(prueth->sram_pool, - (unsigned long)prueth->msmcram.va, msmc_ram_size); + (unsigned long)prueth->msmcram.va, + prueth->msmcram.size); put_mem: pruss_release_mem_region(prueth->pruss, &prueth->shram); @@ -1976,8 +2043,8 @@ static void prueth_remove(struct platform_device *pdev) icss_iep_put(prueth->iep0); gen_pool_free(prueth->sram_pool, - (unsigned long)prueth->msmcram.va, - MSMC_RAM_SIZE); + (unsigned long)prueth->msmcram.va, + prueth->msmcram.size); pruss_release_mem_region(prueth->pruss, &prueth->shram); @@ -1994,12 +2061,14 @@ static const struct prueth_pdata am654_icssg_pdata = { .fdqring_mode = K3_RINGACC_RING_MODE_MESSAGE, .quirk_10m_link_issue = 1, .switch_mode = 1, + .banked_ms_ram = 0, }; static const struct prueth_pdata am64x_icssg_pdata = { .fdqring_mode = K3_RINGACC_RING_MODE_RING, .quirk_10m_link_issue = 1, .switch_mode = 1, + .banked_ms_ram = 1, }; static const struct of_device_id prueth_dt_match[] = { diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h index 23c465f1ce7f..ca8a22a4a5da 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h @@ -13,6 +13,7 @@ #include <linux/etherdevice.h> #include <linux/genalloc.h> #include <linux/if_vlan.h> +#include <linux/if_hsr.h> #include <linux/interrupt.h> #include <linux/kernel.h> #include <linux/mfd/syscon.h> @@ -251,17 +252,19 @@ struct prueth_emac { * @fdqring_mode: Free desc queue mode * @quirk_10m_link_issue: 10M link detect errata * @switch_mode: switch firmware support + * @banked_ms_ram: banked memory support */ struct prueth_pdata { enum k3_ring_mode fdqring_mode; u32 quirk_10m_link_issue:1; u32 switch_mode:1; + u32 banked_ms_ram:1; }; struct icssg_firmwares { - char *pru; - char *rtu; - char *txpru; + const char *pru; + const char *rtu; + const char *txpru; }; /** @@ -290,6 +293,7 @@ struct icssg_firmwares { * @vlan_tbl: VLAN-FID table pointer * @hw_bridge_dev: pointer to HW bridge net device * @hsr_dev: pointer to the HSR net device + * @hsr_prp_version: enum to store the protocol version of hsr master * @br_members: bitmask of bridge member ports * @hsr_members: bitmask of hsr member ports * @prueth_netdevice_nb: netdevice notifier block @@ -300,6 +304,10 @@ struct icssg_firmwares { * @is_switchmode_supported: indicates platform support for switch mode * @switch_id: ID for mapping switch ports to bridge * @default_vlan: Default VLAN for host + * @icssg_emac_firmwares: Firmware names for EMAC mode, indexed per MAC + * @icssg_switch_firmwares: Firmware names for SWITCH mode, indexed per MAC + * @icssg_hsr_firmwares: Firmware names for HSR mode, indexed per MAC + * @icssg_prp_firmwares: Firmware names for PRP mode, indexed per MAC */ struct prueth { struct device *dev; @@ -329,6 +337,7 @@ struct prueth { struct net_device *hw_bridge_dev; struct net_device *hsr_dev; + enum hsr_version hsr_prp_version; u8 br_members; u8 hsr_members; struct notifier_block prueth_netdevice_nb; @@ -343,6 +352,10 @@ struct prueth { spinlock_t vtbl_lock; /** @stats_lock: Lock for reading icssg stats */ spinlock_t stats_lock; + struct icssg_firmwares icssg_emac_firmwares[PRUETH_NUM_MACS]; + struct icssg_firmwares icssg_switch_firmwares[PRUETH_NUM_MACS]; + struct icssg_firmwares icssg_hsr_firmwares[PRUETH_NUM_MACS]; + struct icssg_firmwares icssg_prp_firmwares[PRUETH_NUM_MACS]; }; struct emac_tx_ts_response { diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c index ff5f41bf499e..5e225310c9de 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c +++ b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c @@ -367,7 +367,7 @@ static irqreturn_t prueth_rx_mgm_ts_thread_sr1(int irq, void *dev_id) return IRQ_NONE; prueth_tx_ts_sr1(emac, (void *)page_address(page)); - page_pool_recycle_direct(page->pp, page); + page_pool_recycle_direct(pp_page_to_nmdesc(page)->pp, page); return IRQ_HANDLED; } @@ -392,7 +392,7 @@ static irqreturn_t prueth_rx_mgm_rsp_thread(int irq, void *dev_id) complete(&emac->cmd_complete); } - page_pool_recycle_direct(page->pp, page); + page_pool_recycle_direct(pp_page_to_nmdesc(page)->pp, page); return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h index 490a9cc06fb0..7e053b8af3ec 100644 --- a/drivers/net/ethernet/ti/icssg/icssg_switch_map.h +++ b/drivers/net/ethernet/ti/icssg/icssg_switch_map.h @@ -180,6 +180,9 @@ /* Used to notify the FW of the current link speed */ #define PORT_LINK_SPEED_OFFSET 0x00A8 +/* 2k memory pointer reserved for default writes by PRU0*/ +#define DEFAULT_MSMC_Q_OFFSET 0x00AC + /* TAS gate mask for windows list0 */ #define TAS_GATE_MASK_LIST0 0x0100 |