Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

net: ti: icssg-prueth: Read firmware-names from device tree

Refactor the way firmware names are handled for the ICSSG PRUETH driver.
Instead of using hardcoded firmware name arrays for different modes (EMAC,
SWITCH, HSR), the driver now reads the firmware names from the device tree
property "firmware-name". Only the EMAC firmware names are specified in the
device tree property. The firmware names for all other supported modes are
generated dynamically based on the EMAC firmware names by replacing
substrings (e.g., "eth" with "sw" or "hsr") as appropriate.

Example: Below are the firmwares used currently for PRU0 core

EMAC: ti-pruss/am65x-sr2-pru0-prueth-fw.elf
SW : ti-pruss/am65x-sr2-pru0-prusw-fw.elf
HSR : ti-pruss/am65x-sr2-pru0-pruhsr-fw.elf

All three firmware names are same except for the operating mode.

In general for PRU0 core, firmware name is,

ti-pruss/am65x-sr2-pru0-pru<mode>-fw.elf

Since the EMAC firmware names are defined in DT, driver will read those
directly and for other modes swap the mode name. i.e. eth -> sw or
eth -> hsr.

This preserves backwards compatibility as ICSSG driver is supported only
by AM65x and AM64x. Both of these have "firmware-name" property
populated in their device tree.

Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250613064547.44394-1-danishanwar@ti.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

MD Danish Anwar and committed by
Jakub Kicinski
ffe8a490 c969149b

+102 -45
+93 -42
drivers/net/ethernet/ti/icssg/icssg_prueth.c
··· 125 125 return IRQ_HANDLED; 126 126 } 127 127 128 - static struct icssg_firmwares icssg_hsr_firmwares[] = { 129 - { 130 - .pru = "ti-pruss/am65x-sr2-pru0-pruhsr-fw.elf", 131 - .rtu = "ti-pruss/am65x-sr2-rtu0-pruhsr-fw.elf", 132 - .txpru = "ti-pruss/am65x-sr2-txpru0-pruhsr-fw.elf", 133 - }, 134 - { 135 - .pru = "ti-pruss/am65x-sr2-pru1-pruhsr-fw.elf", 136 - .rtu = "ti-pruss/am65x-sr2-rtu1-pruhsr-fw.elf", 137 - .txpru = "ti-pruss/am65x-sr2-txpru1-pruhsr-fw.elf", 138 - } 139 - }; 140 - 141 - static struct icssg_firmwares icssg_switch_firmwares[] = { 142 - { 143 - .pru = "ti-pruss/am65x-sr2-pru0-prusw-fw.elf", 144 - .rtu = "ti-pruss/am65x-sr2-rtu0-prusw-fw.elf", 145 - .txpru = "ti-pruss/am65x-sr2-txpru0-prusw-fw.elf", 146 - }, 147 - { 148 - .pru = "ti-pruss/am65x-sr2-pru1-prusw-fw.elf", 149 - .rtu = "ti-pruss/am65x-sr2-rtu1-prusw-fw.elf", 150 - .txpru = "ti-pruss/am65x-sr2-txpru1-prusw-fw.elf", 151 - } 152 - }; 153 - 154 - static struct icssg_firmwares icssg_emac_firmwares[] = { 155 - { 156 - .pru = "ti-pruss/am65x-sr2-pru0-prueth-fw.elf", 157 - .rtu = "ti-pruss/am65x-sr2-rtu0-prueth-fw.elf", 158 - .txpru = "ti-pruss/am65x-sr2-txpru0-prueth-fw.elf", 159 - }, 160 - { 161 - .pru = "ti-pruss/am65x-sr2-pru1-prueth-fw.elf", 162 - .rtu = "ti-pruss/am65x-sr2-rtu1-prueth-fw.elf", 163 - .txpru = "ti-pruss/am65x-sr2-txpru1-prueth-fw.elf", 164 - } 165 - }; 166 - 167 128 static int prueth_start(struct rproc *rproc, const char *fw_name) 168 129 { 169 130 int ret; ··· 147 186 int ret, slice; 148 187 149 188 if (prueth->is_switch_mode) 150 - firmwares = icssg_switch_firmwares; 189 + firmwares = prueth->icssg_switch_firmwares; 151 190 else if (prueth->is_hsr_offload_mode) 152 - firmwares = icssg_hsr_firmwares; 191 + firmwares = prueth->icssg_hsr_firmwares; 153 192 else 154 - firmwares = icssg_emac_firmwares; 193 + firmwares = prueth->icssg_emac_firmwares; 155 194 156 195 for (slice = 0; slice < PRUETH_NUM_MACS; slice++) { 157 196 ret = prueth_start(prueth->pru[slice], firmwares[slice].pru); ··· 1593 1632 unregister_netdevice_notifier(&prueth->prueth_netdevice_nb); 1594 1633 } 1595 1634 1635 + static void icssg_read_firmware_names(struct device_node *np, 1636 + struct icssg_firmwares *fw) 1637 + { 1638 + int i; 1639 + 1640 + for (i = 0; i < PRUETH_NUM_MACS; i++) { 1641 + of_property_read_string_index(np, "firmware-name", i * 3 + 0, 1642 + &fw[i].pru); 1643 + of_property_read_string_index(np, "firmware-name", i * 3 + 1, 1644 + &fw[i].rtu); 1645 + of_property_read_string_index(np, "firmware-name", i * 3 + 2, 1646 + &fw[i].txpru); 1647 + } 1648 + } 1649 + 1650 + /* icssg_firmware_name_replace - Replace a substring in firmware name 1651 + * @dev: device pointer for memory allocation 1652 + * @src: source firmware name string 1653 + * @from: substring to replace 1654 + * @to: replacement substring 1655 + * 1656 + * Return: a newly allocated string with the replacement, or the original 1657 + * string if replacement is not possible. 1658 + */ 1659 + static const char *icssg_firmware_name_replace(struct device *dev, 1660 + const char *src, 1661 + const char *from, 1662 + const char *to) 1663 + { 1664 + size_t prefix, from_len, to_len, total; 1665 + const char *p = strstr(src, from); 1666 + char *buf; 1667 + 1668 + if (!p) 1669 + return src; /* fallback: no replacement, use original */ 1670 + 1671 + prefix = p - src; 1672 + from_len = strlen(from); 1673 + to_len = strlen(to); 1674 + total = strlen(src) - from_len + to_len + 1; 1675 + 1676 + buf = devm_kzalloc(dev, total, GFP_KERNEL); 1677 + if (!buf) 1678 + return src; /* fallback: allocation failed, use original */ 1679 + 1680 + strscpy(buf, src, prefix + 1); 1681 + strscpy(buf + prefix, to, to_len + 1); 1682 + strscpy(buf + prefix + to_len, p + from_len, total - prefix - to_len); 1683 + 1684 + return buf; 1685 + } 1686 + 1687 + /** 1688 + * icssg_mode_firmware_names - Generate firmware names for a specific mode 1689 + * @dev: device pointer for logging and context 1690 + * @src: source array of firmware name structures 1691 + * @dst: destination array to store updated firmware name structures 1692 + * @from: substring in firmware names to be replaced 1693 + * @to: substring to replace @from in firmware names 1694 + * 1695 + * Iterates over all MACs and replaces occurrences of the @from substring 1696 + * with @to in the firmware names (pru, rtu, txpru) for each MAC. The 1697 + * updated firmware names are stored in the @dst array. 1698 + */ 1699 + static void icssg_mode_firmware_names(struct device *dev, 1700 + struct icssg_firmwares *src, 1701 + struct icssg_firmwares *dst, 1702 + const char *from, const char *to) 1703 + { 1704 + int i; 1705 + 1706 + for (i = 0; i < PRUETH_NUM_MACS; i++) { 1707 + dst[i].pru = icssg_firmware_name_replace(dev, src[i].pru, 1708 + from, to); 1709 + dst[i].rtu = icssg_firmware_name_replace(dev, src[i].rtu, 1710 + from, to); 1711 + dst[i].txpru = icssg_firmware_name_replace(dev, src[i].txpru, 1712 + from, to); 1713 + } 1714 + } 1715 + 1596 1716 static int prueth_probe(struct platform_device *pdev) 1597 1717 { 1598 1718 struct device_node *eth_node, *eth_ports_node; ··· 1849 1807 */ 1850 1808 icss_iep_init_fw(prueth->iep1); 1851 1809 } 1810 + 1811 + /* Read EMAC firmware names from device tree */ 1812 + icssg_read_firmware_names(np, prueth->icssg_emac_firmwares); 1813 + 1814 + /* Generate other mode firmware names based on EMAC firmware names */ 1815 + icssg_mode_firmware_names(dev, prueth->icssg_emac_firmwares, 1816 + prueth->icssg_switch_firmwares, "eth", "sw"); 1817 + icssg_mode_firmware_names(dev, prueth->icssg_emac_firmwares, 1818 + prueth->icssg_hsr_firmwares, "eth", "hsr"); 1852 1819 1853 1820 spin_lock_init(&prueth->vtbl_lock); 1854 1821 spin_lock_init(&prueth->stats_lock);
+9 -3
drivers/net/ethernet/ti/icssg/icssg_prueth.h
··· 259 259 }; 260 260 261 261 struct icssg_firmwares { 262 - char *pru; 263 - char *rtu; 264 - char *txpru; 262 + const char *pru; 263 + const char *rtu; 264 + const char *txpru; 265 265 }; 266 266 267 267 /** ··· 300 300 * @is_switchmode_supported: indicates platform support for switch mode 301 301 * @switch_id: ID for mapping switch ports to bridge 302 302 * @default_vlan: Default VLAN for host 303 + * @icssg_emac_firmwares: Firmware names for EMAC mode, indexed per MAC 304 + * @icssg_switch_firmwares: Firmware names for SWITCH mode, indexed per MAC 305 + * @icssg_hsr_firmwares: Firmware names for HSR mode, indexed per MAC 303 306 */ 304 307 struct prueth { 305 308 struct device *dev; ··· 346 343 spinlock_t vtbl_lock; 347 344 /** @stats_lock: Lock for reading icssg stats */ 348 345 spinlock_t stats_lock; 346 + struct icssg_firmwares icssg_emac_firmwares[PRUETH_NUM_MACS]; 347 + struct icssg_firmwares icssg_switch_firmwares[PRUETH_NUM_MACS]; 348 + struct icssg_firmwares icssg_hsr_firmwares[PRUETH_NUM_MACS]; 349 349 }; 350 350 351 351 struct emac_tx_ts_response {